diff --git a/app/build.gradle b/app/build.gradle index edf8af1..a7716cd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -79,10 +79,13 @@ dependencies { // retrofit implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.3' // gson converter implementation 'com.squareup.retrofit2:converter-gson:2.9.0' + implementation 'com.github.dhaval2404:imagepicker:2.1' + implementation 'androidx.appcompat:appcompat:1.6.0' implementation 'com.google.android.material:material:1.8.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a22ad85..6b9d4b7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -5,9 +5,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/ssb/simplitend/apputils/AppUtil.java b/app/src/main/java/com/ssb/simplitend/apputils/AppUtil.java index 22a1602..37c0dda 100644 --- a/app/src/main/java/com/ssb/simplitend/apputils/AppUtil.java +++ b/app/src/main/java/com/ssb/simplitend/apputils/AppUtil.java @@ -30,6 +30,7 @@ public abstract class AppUtil { public static final String USER_DETAILS = "user_details"; public static final String USER_TOKEN = "user_token"; + public static final String PATIENT_UID = "patient_uid"; // util functions @@ -124,16 +125,20 @@ public abstract class AppUtil { alertBuilder.create().show(); // Showing alert dialog } - public static void saveToken(String token, Context context){ + public static void saveUserCache(String token, int patient_uid, Context context){ SharedPreferences sp = context.getSharedPreferences(USER_DETAILS, Context.MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); editor.putString(USER_TOKEN, token); + editor.putInt(PATIENT_UID, patient_uid); editor.apply(); Log.d(TAG, "saveToken: user token saved successful"); + // TODO: 17-07-2023 remove below line afterwards + Log.d(TAG, "saveUserCache: " + token); + } public static String getUserToken(Context context){ @@ -141,4 +146,9 @@ public abstract class AppUtil { return sp.getString(USER_TOKEN, ""); } + public static int getPatientUid(Context context){ + SharedPreferences sp = context.getSharedPreferences(USER_DETAILS, Context.MODE_PRIVATE); + return sp.getInt(PATIENT_UID, -1); + } + } diff --git a/app/src/main/java/com/ssb/simplitend/apputils/RetrofitHelper.java b/app/src/main/java/com/ssb/simplitend/apputils/RetrofitHelper.java index 5aaf86a..c0a62dc 100644 --- a/app/src/main/java/com/ssb/simplitend/apputils/RetrofitHelper.java +++ b/app/src/main/java/com/ssb/simplitend/apputils/RetrofitHelper.java @@ -1,11 +1,14 @@ package com.ssb.simplitend.apputils; +import com.ssb.simplitend.BuildConfig; + import java.io.IOException; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; @@ -18,25 +21,38 @@ public abstract class RetrofitHelper { public static final String GET_CONTACT_LIST = "api/patients-contact-list"; + public static final String CREATE_CONTACT = "api/contact-create"; + + public static final String UPDATE_CONTACT = "api/patient-contact-update/"; + // util functions private static Retrofit retrofit; public static synchronized Retrofit getRetrofit(){ if (retrofit == null){ + + OkHttpClient.Builder builder = new OkHttpClient.Builder() + .addInterceptor(chain -> { + Request request = chain.request().newBuilder() + .addHeader("Accept", "*/*") + .addHeader("Accept-Encoding", "gzip, deflate, br") + .addHeader("Connection", "keep-alive") + .addHeader("Content-Type", "multipart/form-data") + .build(); + return chain.proceed(request); + }); + + if (BuildConfig.DEBUG){ + HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); + builder.addInterceptor(interceptor); + + } retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) - .client(new OkHttpClient.Builder() - .addInterceptor(chain -> { - Request request = chain.request().newBuilder() - .addHeader("Accept", "*/*") - .addHeader("Accept-Encoding", "gzip, deflate, br") - .addHeader("Connection", "keep-alive") - .addHeader("Content-Type", "multipart/form-data") - .build(); - return chain.proceed(request); - }).build()) + .client(builder.build()) .build(); } diff --git a/app/src/main/java/com/ssb/simplitend/welcome/fragments/SignInFragment.java b/app/src/main/java/com/ssb/simplitend/welcome/fragments/SignInFragment.java index 6d3f7c7..bdb8d58 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/fragments/SignInFragment.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/fragments/SignInFragment.java @@ -2,6 +2,7 @@ package com.ssb.simplitend.welcome.fragments; import android.os.Bundle; import android.text.InputType; +import android.util.Patterns; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -9,16 +10,21 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; import androidx.navigation.Navigation; import com.ssb.simplitend.R; import com.ssb.simplitend.databinding.SignInFragmentBinding; +import com.ssb.simplitend.welcome.mvvm.WelcomeViewModel; public class SignInFragment extends Fragment { // view binding protected SignInFragmentBinding binding; + // view model + private WelcomeViewModel welcomeViewModel; + public SignInFragment(){ // required empty constructor } @@ -28,6 +34,8 @@ public class SignInFragment extends Fragment { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { binding = SignInFragmentBinding.inflate(inflater, container, false); + welcomeViewModel = new ViewModelProvider(requireActivity()).get(WelcomeViewModel.class); + initViews(); clickEvents(); @@ -43,5 +51,33 @@ public class SignInFragment extends Fragment { binding.forgotPin.setOnClickListener(v -> Navigation.findNavController(v).navigate(R.id.action_signInFragment_to_forgotPinFragment)); + binding.signInBtn.setOnClickListener(v -> { + if (allOkay()){ + + } + }); + + } + + private boolean allOkay() { + boolean allOkay = true; + + if (binding.email.getText().toString().trim().isEmpty()){ + allOkay = false; + binding.email.setError("Required"); + }else if (!Patterns.EMAIL_ADDRESS.matcher(binding.email.getText().toString().trim()).matches()){ + allOkay = false; + binding.email.setError("Invalid email"); + } + + if (binding.pin.getText().toString().trim().isEmpty()){ + allOkay = false; + binding.pin.setError("Required"); + }else if (binding.pin.getText().toString().trim().length() != 4){ + allOkay = false; + binding.pin.setError("Pin should be 4 digit."); + } + + return allOkay; } } diff --git a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/AddContactFragment.java b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/AddContactFragment.java index d57c495..845d1f1 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/AddContactFragment.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/AddContactFragment.java @@ -1,32 +1,47 @@ package com.ssb.simplitend.welcome.fragments.contacts; +import static com.ssb.simplitend.welcome.fragments.contacts.ContactInfoFragment.CONTACT_DATA_KEY; + +import android.app.ProgressDialog; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; import androidx.navigation.Navigation; import androidx.recyclerview.widget.GridLayoutManager; import com.google.android.material.bottomsheet.BottomSheetDialog; import com.ssb.simplitend.R; +import com.ssb.simplitend.apputils.AppUtil; +import com.ssb.simplitend.apputils.RetrofitHelper; import com.ssb.simplitend.databinding.AddContactFragmentBinding; import com.ssb.simplitend.databinding.DoneBottomsheetBinding; import com.ssb.simplitend.welcome.fragments.contacts.mvvm.AddContactAdapter; -import com.ssb.simplitend.welcome.fragments.contacts.mvvm.Contact; +import com.ssb.simplitend.welcome.fragments.contacts.mvvm.ContactViewModel; +import com.ssb.simplitend.welcome.fragments.contacts.mvvm.models.ContactData; +import com.ssb.simplitend.welcome.fragments.contacts.mvvm.models.ContactListResponse; +import com.ssb.simplitend.welcome.mvvm.WelcomeContracts; import java.util.ArrayList; +import java.util.List; -public class AddContactFragment extends Fragment { +public class AddContactFragment extends Fragment implements WelcomeContracts.ContactListContracts, AddContactAdapter.ContactClickListener{ // view binding protected AddContactFragmentBinding binding; protected AddContactAdapter contactAdapter; + private ProgressDialog progressDialog; + + private ContactViewModel contactViewModel; + public AddContactFragment(){ // required empty const. } @@ -36,6 +51,8 @@ public class AddContactFragment extends Fragment { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { binding = AddContactFragmentBinding.inflate(inflater, container, false); + contactViewModel = new ViewModelProvider(requireActivity()).get(ContactViewModel.class); + initViews(); clickEvents(); @@ -45,6 +62,8 @@ public class AddContactFragment extends Fragment { private void initViews() { + progressDialog = new ProgressDialog(requireContext()); + binding.contactRv.setLayoutManager(new GridLayoutManager(requireContext(), 2)); contactAdapter = new AddContactAdapter(); binding.contactRv.setAdapter(contactAdapter); @@ -54,22 +73,13 @@ public class AddContactFragment extends Fragment { } private void loadContacts() { - // static data - ArrayList contacts = new ArrayList<>(); - // adding 10 contacts - contacts.add(new Contact("Akansha Surve", "phone number")); - contacts.add(new Contact("Akansha Surve", "phone number")); - contacts.add(new Contact("Akansha Surve", "phone number")); - contacts.add(new Contact("Akansha Surve", "phone number")); - contacts.add(new Contact("Akansha Surve", "phone number")); - contacts.add(new Contact("Akansha Surve", "phone number")); - contacts.add(new Contact("Akansha Surve", "phone number")); - contacts.add(new Contact("Akansha Surve", "phone number")); - contacts.add(new Contact("Akansha Surve", "phone number")); - contacts.add(new Contact("Akansha Surve", "phone number")); - contactAdapter.submitList(contacts); + binding.progressBar.setVisibility(View.VISIBLE); + contactViewModel.getRemoteContactList(RetrofitHelper.GET_CONTACT_LIST, this, + "Bearer " + AppUtil.getUserToken(requireContext())); + contactAdapter.setContactClickListener(this); + } private void clickEvents() { @@ -81,6 +91,48 @@ public class AddContactFragment extends Fragment { } + @Override + public void onResponse(List responseList) { + ArrayList contactList = new ArrayList<>(); + + for (ContactListResponse response : responseList){ + response.contact_data.contact_id = response.id; + contactList.add(response.contact_data); + } + + for (int i = contactList.size(); i<10; i++){ + contactList.add(new ContactData(-1)); + } + + binding.progressBar.setVisibility(View.GONE); + + contactAdapter.submitList(contactList); + + binding.nextBtn.setVisibility(View.VISIBLE); + } + + @Override + public void onFailure(Throwable t, String message, int error_code) { + Toast.makeText(requireContext(), "Something went wrong", Toast.LENGTH_SHORT).show(); + binding.progressBar.setVisibility(View.GONE); + } + + @Override + public void onContactClick(ContactData contactData, int position) { + if (contactData.id == -1){ + // a new contact should be added + Navigation.findNavController(binding.getRoot()) + .navigate(R.id.action_addContactFragment_to_contactListFragment); + }else{ + // show contact details + Bundle bundle = new Bundle(); + bundle.putSerializable(CONTACT_DATA_KEY, contactData); + + Navigation.findNavController(binding.getRoot()) + .navigate(R.id.action_addContactFragment_to_contactInfoFragment, bundle); + } + } + private void showEmailSentAnim() { DoneBottomsheetBinding binding = DoneBottomsheetBinding.inflate(getLayoutInflater()); diff --git a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/ContactInfoFragment.java b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/ContactInfoFragment.java index 64267ad..af7aad8 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/ContactInfoFragment.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/ContactInfoFragment.java @@ -1,23 +1,45 @@ package com.ssb.simplitend.welcome.fragments.contacts; +import static com.ssb.simplitend.welcome.fragments.contacts.CreateContactFragment.CONTACT_KEY; +import static com.ssb.simplitend.welcome.fragments.contacts.CreateContactFragment.TO_EDIT_KEY; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; import androidx.navigation.Navigation; +import com.bumptech.glide.Glide; +import com.ssb.simplitend.R; +import com.ssb.simplitend.apputils.AppUtil; import com.ssb.simplitend.databinding.ContactInfoFragmentBinding; +import com.ssb.simplitend.welcome.fragments.contacts.mvvm.ContactViewModel; +import com.ssb.simplitend.welcome.fragments.contacts.mvvm.models.ContactData; +import com.ssb.simplitend.welcome.mvvm.WelcomeContracts; -public class ContactInfoFragment extends Fragment { +public class ContactInfoFragment extends Fragment implements WelcomeContracts.DeleteContactInterface { // view binding protected ContactInfoFragmentBinding binding; - public ContactInfoFragment(){ + public static final String CONTACT_DATA_KEY = "contact_key"; + + private ContactData contactData; + + private ContactViewModel contactViewModel; + + private ProgressDialog progressDialog; + + public ContactInfoFragment() { // required empty const. } @@ -26,14 +48,109 @@ public class ContactInfoFragment extends Fragment { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { binding = ContactInfoFragmentBinding.inflate(inflater, container, false); + contactViewModel = new ViewModelProvider(requireActivity()).get(ContactViewModel.class); + + initViews(); + clickEvents(); return binding.getRoot(); } + private void initViews() { + + if (getArguments() != null && getArguments().getSerializable(CONTACT_DATA_KEY) != null) { + contactData = (ContactData) getArguments().getSerializable(CONTACT_DATA_KEY); + } else { + // no arguments received + Navigation.findNavController(binding.getRoot()).popBackStack(); + return; + } + + progressDialog = new ProgressDialog(requireContext()); + + loadUserData(); + + } + + private void loadUserData() { + Glide.with(requireContext()) + .load("https://simplitend.betadelivery.com/storage/upload/" + contactData.contact_photo) + .placeholder(android.R.color.darker_gray) + .error(R.drawable.ic_contact) + .fitCenter().into(binding.image); + + binding.name.setText(contactData.first_name); + binding.phoneNumber.setText(contactData.phone_number); + binding.email.setText(contactData.email_address); + binding.relationship.setText(contactData.relationship); + } + private void clickEvents() { binding.backBtn.setOnClickListener(v -> Navigation.findNavController(v).popBackStack()); + binding.delete.setOnClickListener(v -> { + + if (contactData.care_giver_data.id != null){ + // This is a caregiver contact + // thus, cannot be deleted + Toast.makeText(requireContext(), "You cannot delete caregiver contact.", Toast.LENGTH_SHORT).show(); + return; + } + + AppUtil.showSOSDecision(requireContext(), + getString(R.string.sure_delete), + getString(R.string.yes), + getString(R.string.no), + yes -> { + progressDialog.setTitle("Please wait"); + progressDialog.setMessage("while we delete the contact details."); + progressDialog.setCancelable(false); + progressDialog.show(); + + contactViewModel.deleteContact(AppUtil.getUserToken(requireContext()), + contactData.contact_id, this); + }, no -> { + // nothing to do + }); + }); + + binding.edit.setOnClickListener(v -> { + Bundle bundle = new Bundle(); + bundle.putBoolean(TO_EDIT_KEY, true); + bundle.putSerializable(CONTACT_KEY, contactData); + + Navigation.findNavController(v) + .navigate(R.id.action_contactInfoFragment_to_createContactFragment, bundle); + }); + + binding.callBtn.setOnClickListener(v -> { + Intent intent = new Intent(Intent.ACTION_DIAL, Uri.fromParts("tel", + contactData.phone_number.replace(" ", ""), + null)); + startActivity(intent); + }); + + binding.messageBtn.setOnClickListener(v -> { + Uri uri = Uri.parse("smsto:"+contactData.phone_number.replace(" ", "")); + Intent intent = new Intent(Intent.ACTION_SENDTO, uri); +// intent.putExtra("sms_body", "The SMS text"); + startActivity(intent); + }); + + } + + @Override + public void onContactDelete() { + progressDialog.dismiss(); + Toast.makeText(requireActivity(), "Contact deleted successfully.", Toast.LENGTH_SHORT).show(); + Navigation.findNavController(binding.getRoot()).popBackStack(); + } + + @Override + public void onContactDeleteFailed() { + progressDialog.dismiss(); + Toast.makeText(requireActivity(), "Contact deleted successfully.", Toast.LENGTH_SHORT).show(); } } diff --git a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/ContactListAdapter.java b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/ContactListAdapter.java index 3206778..0d8e6bc 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/ContactListAdapter.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/ContactListAdapter.java @@ -1,5 +1,6 @@ package com.ssb.simplitend.welcome.fragments.contacts; +import android.util.Log; import android.view.LayoutInflater; import android.view.ViewGroup; @@ -18,7 +19,7 @@ public class ContactListAdapter extends ListAdapter DIFF_UTIL = new DiffUtil.ItemCallback() { @Override public boolean areItemsTheSame(@NonNull Contact oldItem, @NonNull Contact newItem) { - return oldItem.name.equals(newItem.name); + return oldItem.first_name.equals(newItem.first_name); } @Override @@ -43,6 +44,7 @@ public class ContactListAdapter extends ListAdapter { + Log.d("aditya", "onBindViewHolder: " + getItemCount() + " " + position); if (contactClickListener != null){ contactClickListener.onClick(getItem(position)); } @@ -63,11 +65,10 @@ public class ContactListAdapter extends ListAdapter { Bundle bundle = new Bundle(); - bundle.putBoolean(TO_EDIT_KEY, true); - bundle.putSerializable(CONTACT_KEY, contact); + bundle.putBoolean(TO_EDIT_KEY, false); + bundle.putSerializable(CONTACT_KEY, new ContactData(contact)); Navigation.findNavController(binding.getRoot()).navigate(R.id.action_contactListFragment_to_createContactFragment, bundle); } ); @@ -121,11 +122,11 @@ public class ContactListFragment extends Fragment{ ArrayList filteredList = new ArrayList<>(); for (Contact contact: contactList){ - if (contact.name != null && contact.name.trim().toLowerCase().contains(searchInput)){ + if (contact.first_name != null && contact.first_name.trim().toLowerCase().contains(searchInput)){ filteredList.add(contact); - }else if (contact.phoneNumber != null && contact.phoneNumber.trim().contains(searchInput)){ + }else if (contact.phone_number != null && contact.phone_number.trim().contains(searchInput)){ filteredList.add(contact); - }else if (contact.email != null && contact.email.trim().toLowerCase().contains(searchInput)){ + }else if (contact.email_address != null && contact.email_address.trim().toLowerCase().contains(searchInput)){ filteredList.add(contact); }else if (contact.relationship != null && contact.relationship.trim().toLowerCase().contains(searchInput)){ filteredList.add(contact); diff --git a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/CreateContactFragment.java b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/CreateContactFragment.java index 243d8de..347c028 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/CreateContactFragment.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/CreateContactFragment.java @@ -1,11 +1,17 @@ package com.ssb.simplitend.welcome.fragments.contacts; +import static com.ssb.simplitend.apputils.RetrofitHelper.CREATE_CONTACT; import static com.ssb.simplitend.apputils.RetrofitHelper.GET_CONTACT_LIST; +import static com.ssb.simplitend.apputils.RetrofitHelper.UPDATE_CONTACT; +import android.app.Activity; import android.app.ProgressDialog; +import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.util.Log; +import android.util.Patterns; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -19,22 +25,32 @@ import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.navigation.Navigation; +import com.bumptech.glide.Glide; +import com.github.dhaval2404.imagepicker.ImagePicker; import com.google.android.material.bottomsheet.BottomSheetDialog; import com.ssb.simplitend.R; import com.ssb.simplitend.apputils.AppUtil; import com.ssb.simplitend.databinding.CreateEditContactFragmentBinding; import com.ssb.simplitend.welcome.fragments.contacts.mvvm.Contact; import com.ssb.simplitend.welcome.fragments.contacts.mvvm.ContactViewModel; +import com.ssb.simplitend.welcome.fragments.contacts.mvvm.models.ContactData; import com.ssb.simplitend.welcome.fragments.contacts.mvvm.models.ContactListResponse; import com.ssb.simplitend.welcome.mvvm.WelcomeContracts; +import java.io.File; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; + +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; public class CreateContactFragment extends Fragment implements WelcomeContracts.ContactListContracts, ContactViewModel.GotoAddContactInterface, ContactViewModel.SOSCheckInterface, - WelcomeContracts.CreateContactInterface { - + WelcomeContracts.CreateContactInterface, WelcomeContracts.UpdateContactContracts { + // log tag private static final String TAG = "CreateContactFragment"; @@ -51,12 +67,20 @@ public class CreateContactFragment extends Fragment implements WelcomeContracts. boolean to_edit; // image selector launcher - private ActivityResultLauncher imageSelector; + private ActivityResultLauncher imageSelector; private ContactViewModel contactViewModel; private ArrayList countryCodeList; + // flag indicating that current contact must be a caregiver or not + private boolean mustBeeCaregiver; + + // image selected uri + private Uri selectedImageUri; + + private ContactData contactData; + public CreateContactFragment() { // required empty const. } @@ -80,39 +104,6 @@ public class CreateContactFragment extends Fragment implements WelcomeContracts. } private void initializeViews() { - Bundle bundle = getArguments(); - - if (bundle != null){ - to_edit = bundle.getBoolean(TO_EDIT_KEY, false); - - if (to_edit){ - - setLayoutDetails(getString(R.string.edit_contact), getString(R.string.change_photo), getString(R.string.save)); - - Contact contact = (Contact) bundle.getSerializable(CONTACT_KEY); - setDetails(contact); - - }else{ - setLayoutDetails(getString(R.string.create_contact), getString(R.string.add_photo), getString(R.string.create_contact)); - } - } - - progressDialog = new ProgressDialog(requireContext()); - - binding.sosCheck.setOnCheckedChangeListener((buttonView, isChecked) -> { - if (isChecked){ - contactViewModel.showSOSDecision(requireContext()); - } - }); - - // image selector launcher - imageSelector = registerForActivityResult(new ActivityResultContracts.GetContent(), - uri -> { - if (uri != null){ - binding.image.setImageURI(null); - binding.image.setImageURI(uri); - } - }); // country code loading countryCodeList = contactViewModel.loadCountryCodeDropDown(requireContext()); @@ -127,8 +118,59 @@ public class CreateContactFragment extends Fragment implements WelcomeContracts. binding.countryCodes.setIsFocusable(true); - loadRemoteContactList(); + progressDialog = new ProgressDialog(requireContext()); + Bundle bundle = getArguments(); + + if (bundle != null) { + to_edit = bundle.getBoolean(TO_EDIT_KEY, false); + + if (to_edit) { + + setLayoutDetails(getString(R.string.edit_contact), getString(R.string.change_photo), getString(R.string.save)); + + } else { + setLayoutDetails(getString(R.string.create_contact), getString(R.string.add_photo), getString(R.string.create_contact)); + loadRemoteContactList(); + } + + if (bundle.getSerializable(CONTACT_KEY) != null) { + contactData = (ContactData) bundle.getSerializable(CONTACT_KEY); + setDetails(); + } + } else { + loadRemoteContactList(); + } + + binding.sosCheck.setOnCheckedChangeListener((buttonView, isChecked) -> { + if (isChecked) { + contactViewModel.showSOSDecision(requireContext()); + } + }); + + binding.caregiverCheck.setOnCheckedChangeListener(((buttonView, isChecked) -> { + if (!isChecked && mustBeeCaregiver) { + binding.caregiverCheck.setChecked(true); + Toast.makeText(requireContext(), "This contact should be a caregiver.", Toast.LENGTH_SHORT).show(); + } + })); + + imageSelector = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> { + if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { + //Image Uri will not be null for RESULT_OK + selectedImageUri = result.getData().getData(); + + binding.image.setImageURI(null); + binding.image.setImageURI(selectedImageUri); + + Log.d(TAG, "initializeViews: " + selectedImageUri.getPath()); + } else if (result.getResultCode() == ImagePicker.RESULT_ERROR) { + Toast.makeText(requireContext(), ImagePicker.getError(result.getData()), Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(requireContext(), "Task Cancelled", Toast.LENGTH_SHORT).show(); + } + }); } private void clickEvents() { @@ -137,26 +179,139 @@ public class CreateContactFragment extends Fragment implements WelcomeContracts. binding.nextBtn.setOnClickListener(v -> { - if (to_edit){ + if (to_edit) { // editing existing contact - contactViewModel.showSaveEditDecision(requireContext()); - }else { - // saving new contact - Navigation.findNavController(v).popBackStack(); + + AppUtil.showSOSDecision(requireContext(), + getString(R.string.make_changes), + getString(R.string.yes), + getString(R.string.no), + yes -> { + if (allOkay()){ + createEditContact("While we update your contact details.", true, UPDATE_CONTACT + contactData.contact_id); + } + }, no -> { + + }); + + } else { + if (allOkay()) { + createEditContact("While we save the contact details.", false, CREATE_CONTACT); + } } }); - binding.image.setOnClickListener(v -> imageSelector.launch("image/*")); + binding.image.setOnClickListener(v -> { + ImagePicker.with(requireActivity()) + .cropSquare() + .maxResultSize(500, 500) + .galleryOnly() + .createIntent(intent -> { + imageSelector.launch(intent); + return null; + }); + + }); + + } + + private void createEditContact(String progressMsg, boolean edit_contact, + String URL) { + + progressDialog.setTitle("Please wait"); + progressDialog.setMessage(progressMsg); + progressDialog.setCancelable(false); + progressDialog.show(); + + Map body = new HashMap<>(); + RequestBody user_first_name = RequestBody.create(binding.name.getText().toString().trim(), MediaType.parse("text/plain;charset=utf-8") ); + body.put("full_name", user_first_name ); + + String contact_number = countryCodeList.get(binding.countryCodes.getSelectedIndex()) + " " + + binding.phoneNumber.getText().toString(); + + RequestBody contact_number_part = RequestBody.create(contact_number, MediaType.parse("text/plain;charset=utf-8") ); + + body.put("contact_number", contact_number_part); + + RequestBody email_ = RequestBody.create(binding.email.getText().toString().trim(), MediaType.parse("text/plain;charset=utf-8") ); + body.put("email_address", email_); + + RequestBody relationship_ = RequestBody.create(binding.relationship.getText().toString().trim(), MediaType.parse("text/plain;charset=utf-8") ); + body.put("relationship", relationship_); + + Map intBody = new HashMap<>(); + + intBody.put("is_sos", binding.sosCheck.isChecked() ? 1 : 0); + intBody.put("is_caregiver_contact", binding.caregiverCheck.isChecked() ? 1 : 0); + intBody.put("patient_xid", AppUtil.getPatientUid(requireContext())); + + MultipartBody.Part filePart = null; + + if (selectedImageUri != null) { + RequestBody requestFile = RequestBody.create(MediaType.parse("image/jpeg"), new File(selectedImageUri.getPath())); + filePart = MultipartBody.Part.createFormData("contact_photo", + "img_" + System.currentTimeMillis() + , requestFile); + } + + contactViewModel.createEditContact( + URL, + body, + intBody, + filePart, + edit_contact ? null : this, // create contact call back + edit_contact ? this : null, // update contact call back + "Bearer " + AppUtil.getUserToken(requireContext())); + + } + + private boolean allOkay() { + boolean allOkay = true; + + if (binding.name.getText().toString().trim().isEmpty()) { + allOkay = false; + binding.name.setError("Required"); + } + + if (binding.relationship.getText().toString().trim().isEmpty()) { + allOkay = false; + binding.relationship.setError("Required"); + } + + if (binding.phoneNumber.getText().toString().trim().isEmpty()) { + allOkay = false; + binding.phoneNumber.setError("Required"); + } else if (!Patterns.PHONE.matcher(binding.phoneNumber.getText().toString()).matches()) { + allOkay = false; + binding.phoneNumber.setError("Invalid number"); + } + + if (binding.email.getText().toString().trim().isEmpty()) { + allOkay = false; + binding.email.setError("Required"); + } else if (!Patterns.EMAIL_ADDRESS.matcher(binding.email.getText().toString()).matches()) { + allOkay = false; + binding.email.setError("Invalid email"); + } + + if (binding.countryCodes.getSelectedIndex() == -1 && allOkay) { + allOkay = false; + Toast.makeText(requireContext(), "please select a country code", Toast.LENGTH_SHORT).show(); + } + + return allOkay; } @Override public void gotoAddFragment(BottomSheetDialog bsd) { new Handler().postDelayed(() -> { if (bsd != null) bsd.dismiss(); - Navigation.findNavController(binding.getRoot()) - .navigate(R.id.action_createContactFragment_to_addContactFragment); + + Toast.makeText(requireActivity(), "Contact updated successFully.", Toast.LENGTH_SHORT).show(); + Navigation.findNavController(binding.getRoot()).popBackStack(R.id.addContactFragment, false); }, 3000); } @@ -170,14 +325,15 @@ public class CreateContactFragment extends Fragment implements WelcomeContracts. @Override public void onResponse(List contactList) { Log.d(TAG, "onResponse: " + contactList); - if (contactList.size() == 0){ + if (contactList.size() == 0) { // there are no contacts in remote database // thus, this contact has to be a caregiver binding.relationship.setText(getString(R.string.caregiver)); binding.relationship.setEnabled(false); + binding.caregiverCheckView.setVisibility(View.VISIBLE); + this.mustBeeCaregiver = true; binding.caregiverCheck.setChecked(true); - binding.caregiverCheck.setEnabled(false); } progressDialog.dismiss(); @@ -193,15 +349,37 @@ public class CreateContactFragment extends Fragment implements WelcomeContracts. } // create contact callback - @Override public void onContactCreated(Contact contact) { + Log.d(TAG, "onContactCreated: " + contact); + progressDialog.dismiss(); + Navigation.findNavController(binding.getRoot()).navigate(R.id.action_createContactFragment_to_addContactFragment); } @Override public void onContactCreateFailed(Throwable t, String message, int error_code) { + Log.d(TAG, "onContactCreateFailed: " + t.getMessage()); + progressDialog.dismiss(); + AppUtil.showAlert(requireContext(), "Something went wrong", + message, getString(R.string.OK), + (dialog, which) -> { + dialog.dismiss(); + }, null, null); + + } + + @Override + public void onContactUpdated() { + progressDialog.dismiss(); + contactViewModel.showDoneBottomSheet(requireContext()); + } + + @Override + public void onUpdateFailed() { + progressDialog.dismiss(); + Toast.makeText(requireActivity(), "Contact update failed.", Toast.LENGTH_SHORT).show(); } // loading remote contact list to know whether this is user's first contact @@ -216,14 +394,69 @@ public class CreateContactFragment extends Fragment implements WelcomeContracts. contactViewModel.getRemoteContactList(GET_CONTACT_LIST, this, token); } - private void setDetails(Contact contact) { - binding.name.setText(contact.first_name); - binding.phoneNumber.setText(contact.phone_number); - binding.email.setText(contact.email_address); - binding.relationship.setText(contact.relationship); + private void setDetails() { + if (contactData.contact_photo != null) + { + Glide.with(requireContext()) + .load("https://simplitend.betadelivery.com/storage/upload/" + contactData.contact_photo) + .placeholder(android.R.color.darker_gray) + .error(R.drawable.ic_contact) + .fitCenter().into(binding.image); + } + + if (contactData.first_name != null) + binding.name.setText(contactData.first_name); + + String[] code_phone = contactData.phone_number.split(" "); + + if (code_phone.length > 1) { + // there is a country code + int index = countryCodeList.indexOf(code_phone[0]); + + if (index >= 0) binding.countryCodes.selectItemByIndex(index); + else binding.countryCodes.clearSelectedItem(); + + contactData.phone_number = ""; + for (int i = 1; i < code_phone.length; i++) { + contactData.phone_number = contactData.phone_number.concat(code_phone[i]); + } + } else { + binding.countryCodes.clearSelectedItem(); + } + + binding.phoneNumber.setText(contactData.phone_number); + + if (contactData.email_address != null) + binding.email.setText(contactData.email_address); + + if (contactData.relationship != null) + binding.relationship.setText(contactData.relationship); + + if (contactData.is_sos != null && contactData.is_sos.equals("1")){ + binding.sosCheck.setChecked(true); + } + + // if caregiver cannot change email and phone number + if (contactData.care_giver_data != null && contactData.care_giver_data.id != null) { + binding.email.setClickable(false); + binding.email.setFocusable(false); + + binding.phoneNumber.setClickable(false); + binding.phoneNumber.setFocusable(false); + + binding.countryCodes.setClickable(false); + binding.countryCodes.setFocusable(false); + + binding.caregiverCheck.setChecked(true); + binding.caregiverCheck.setEnabled(false); + binding.relationship.setEnabled(false); + }else{ + binding.caregiverCheckView.setVisibility(View.GONE); + } + } - public void setLayoutDetails(String title, String photo_title, String btn_txt){ + public void setLayoutDetails(String title, String photo_title, String btn_txt) { binding.title.setText(title); binding.photoTv.setText(photo_title); binding.nextBtn.setText(btn_txt); diff --git a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/AddContactAdapter.java b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/AddContactAdapter.java index d77a63e..f41077e 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/AddContactAdapter.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/AddContactAdapter.java @@ -3,7 +3,6 @@ package com.ssb.simplitend.welcome.fragments.contacts.mvvm; import static com.ssb.simplitend.welcome.fragments.contacts.CreateContactFragment.TO_EDIT_KEY; import android.app.AlertDialog; -import android.graphics.Color; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -15,23 +14,27 @@ import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.ListAdapter; import androidx.recyclerview.widget.RecyclerView; +import com.bumptech.glide.Glide; import com.ssb.simplitend.R; import com.ssb.simplitend.databinding.AddContactViewholderBinding; +import com.ssb.simplitend.welcome.fragments.contacts.mvvm.models.ContactData; -public class AddContactAdapter extends ListAdapter { +public class AddContactAdapter extends ListAdapter { - private static final DiffUtil.ItemCallback DIFF_UTIL = new DiffUtil.ItemCallback() { + private static final DiffUtil.ItemCallback DIFF_UTIL = new DiffUtil.ItemCallback() { @Override - public boolean areItemsTheSame(@NonNull Contact oldItem, @NonNull Contact newItem) { - return oldItem.name.equals(newItem.name); + public boolean areItemsTheSame(@NonNull ContactData oldItem, @NonNull ContactData newItem) { + return oldItem.first_name.equals(newItem.first_name); } @Override - public boolean areContentsTheSame(@NonNull Contact oldItem, @NonNull Contact newItem) { + public boolean areContentsTheSame(@NonNull ContactData oldItem, @NonNull ContactData newItem) { return oldItem.equals(newItem); } }; + private ContactClickListener contactClickListener; + public AddContactAdapter() { super(DIFF_UTIL); } @@ -46,6 +49,16 @@ public class AddContactAdapter extends ListAdapter { + if (contactClickListener != null){ + contactClickListener.onContactClick(getItem(position), position); + } + }); + } + + public void setContactClickListener(ContactClickListener contactClickListener) { + this.contactClickListener = contactClickListener; } public static class ContactViewHolder extends RecyclerView.ViewHolder { @@ -73,30 +86,48 @@ public class AddContactAdapter extends ListAdapter { - Navigation.findNavController(v).navigate(R.id.action_addContactFragment_to_contactInfoFragment); - }); + binding.card.setCardBackgroundColor(itemView.getContext().getColor(R.color.color_accent)); - } else { - binding.name.setText("Add contact"); + }else{ + // TODO: 17-07-2023 work on \" part of the string + binding.name.setText(contact.first_name); - binding.card.setOnClickListener(v -> { + if (contact.contact_photo == null || contact.contact_photo.isEmpty()){ + binding.addImeg.setVisibility(View.VISIBLE); + binding.imag.setVisibility(View.GONE); + }else{ + binding.addImeg.setVisibility(View.GONE); + binding.imag.setVisibility(View.VISIBLE); - contactDialog.show(); + Glide.with(itemView.getContext()) + .load("https://simplitend.betadelivery.com/storage/upload/" + contact.contact_photo) + .placeholder(android.R.color.darker_gray) + .error(R.drawable.ic_contact) + .fitCenter().into(binding.imag); + } - }); + binding.card.setCardBackgroundColor(itemView.getContext().getColor(R.color.white_bg)); + if (contact.care_giver_data.id != null){ + // this contact is caregiver + binding.sos.setVisibility(View.VISIBLE); + } } } } + @FunctionalInterface + public interface ContactClickListener{ + void onContactClick(ContactData contactData, int position); + } + } diff --git a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/Contact.java b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/Contact.java index be8e3da..e78a031 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/Contact.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/Contact.java @@ -22,6 +22,16 @@ public class Contact implements Serializable { this.phone_number = phoneNumber; } + public Contact(String first_name, String phone_number, String relationship, String email_address, String is_sos, String updated_at, String created_at) { + this.first_name = first_name; + this.phone_number = phone_number; + this.relationship = relationship; + this.email_address = email_address; + this.is_sos = is_sos; + this.updated_at = updated_at; + this.created_at = created_at; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/ContactViewModel.java b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/ContactViewModel.java index 0dd90d5..936d84b 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/ContactViewModel.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/ContactViewModel.java @@ -25,6 +25,10 @@ import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Map; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; +import okhttp3.ResponseBody; + public class ContactViewModel extends AndroidViewModel { private static final String TAG = "ContactViewModel"; @@ -60,37 +64,22 @@ public class ContactViewModel extends AndroidViewModel { contactRepository.getRemoteContactList(URL, contactListContracts, token); } - public void createContact(@NonNull String URL, - @NonNull Map body, - @NonNull WelcomeContracts.CreateContactInterface createContactInterface, - @NonNull String token){ - contactRepository.createContact(URL, body, createContactInterface, token); + public void createEditContact(@NonNull String URL, + Map body, + Map intBody, + MultipartBody.Part userImage, + WelcomeContracts.CreateContactInterface createContactInterface, + WelcomeContracts.UpdateContactContracts updateContactContracts, + @NonNull String token){ + contactRepository.createEditContact(URL, body, intBody, userImage, createContactInterface, updateContactContracts, token); } - public void showSaveEditDecision(Context context) { - - DecisionBottomsheetBinding binding = DecisionBottomsheetBinding.inflate(LayoutInflater.from(context)); - - BottomSheetDialog bsd = new BottomSheetDialog(context, R.style.BottomSheetDialog); - bsd.setContentView(binding.getRoot()); - - binding.text.setText(context.getString(R.string.make_changes)); - - binding.positiveBtn.setText(context.getString(R.string.yes)); - binding.negativeBtn.setText(context.getString(R.string.no)); - - binding.negativeBtn.setOnClickListener(v -> bsd.dismiss()); - - binding.positiveBtn.setOnClickListener(v -> { - bsd.dismiss(); - showDoneBottomSheet(context); - }); - - bsd.show(); - + public void deleteContact(String token, int contact_id, WelcomeContracts.DeleteContactInterface deleteContactInterface){ + contactRepository.deleteContact(contact_id, "Bearer " + token, + deleteContactInterface); } - private void showDoneBottomSheet(Context context) { + public void showDoneBottomSheet(Context context) { DoneBottomsheetBinding binding = DoneBottomsheetBinding.inflate(LayoutInflater.from(context)); BottomSheetDialog bsd = new BottomSheetDialog(context, R.style.BottomSheetDialog); diff --git a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/UserContactRepository.java b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/UserContactRepository.java index bf4275a..280d6f8 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/UserContactRepository.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/UserContactRepository.java @@ -4,10 +4,12 @@ import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; import android.provider.ContactsContract; +import android.telephony.PhoneNumberUtils; import android.util.Log; import androidx.annotation.NonNull; +import com.google.gson.JsonObject; import com.ssb.simplitend.apputils.RetrofitHelper; import com.ssb.simplitend.welcome.fragments.contacts.mvvm.models.ContactListResponse; import com.ssb.simplitend.welcome.mvvm.APIService; @@ -17,8 +19,13 @@ import com.ssb.simplitend.welcome.mvvm.models.CallResponse; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; +import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; @@ -74,30 +81,91 @@ public class UserContactRepository { } - public void createContact(@NonNull String URL, - @NonNull Map body, - @NonNull WelcomeContracts.CreateContactInterface createContactInterface, - @NonNull String token){ - apiService.createContact(URL, body, token).enqueue(new Callback>() { + public void createEditContact(@NonNull String URL, + Map body, + Map intBody, + MultipartBody.Part userImage, + WelcomeContracts.CreateContactInterface createContactInterface, + WelcomeContracts.UpdateContactContracts updateContactContracts, + @NonNull String token){ + + apiService.createEditContact(URL, body, intBody, userImage, token).enqueue(new Callback>() { @Override public void onResponse(Call> call, Response> response) { if (response.isSuccessful() && response.body() != null && response.body().result != null){ - createContactInterface.onContactCreated(response.body().result); - }else if (response.body() != null && response.body().result != null){ - Log.e(TAG, "onResponse: contact create " + response); - createContactInterface.onContactCreateFailed(new Exception(response.toString()), response.body().message, response.code()); + if (createContactInterface != null) + { + createContactInterface.onContactCreated(response.body().result); + } + + if (updateContactContracts != null){ + updateContactContracts.onContactUpdated(); + } + + }else if (response.body() != null){ + Log.e(TAG, "onResponse: contact create or edit contact " + response); + + if (createContactInterface != null) + { + createContactInterface.onContactCreateFailed(new Exception(response.toString()), response.body().message, response.code()); + } + + if (updateContactContracts != null){ + updateContactContracts.onUpdateFailed(); + } + }else{ Log.e(TAG, "onResponse: no success response and also response body is null"); - createContactInterface.onContactCreateFailed(new Exception("no success response and also response body is null"), "It's not you, it's us.\nPlease try again later", 1); + + if (createContactInterface != null){ + createContactInterface.onContactCreateFailed(new Exception("no success response and also response body is null"), "It's not you, it's us.\nPlease try again later", 1); + } + + if (updateContactContracts != null){ + updateContactContracts.onUpdateFailed(); + } + } } @Override public void onFailure(Call> call, Throwable t) { - Log.e(TAG, "onFailure: ", t); - createContactInterface.onContactCreateFailed(t, t.getMessage(), 1); + Log.e(TAG, "onFailure: create or update contact ", t); + + if (createContactInterface != null) + { + createContactInterface.onContactCreateFailed(t, "It's not you, it's us.\nPlease try again later.", 1); + } + + if (updateContactContracts != null){ + updateContactContracts.onUpdateFailed(); + } } }); + + } + + public void deleteContact(int contact_id, String token, + @NonNull WelcomeContracts.DeleteContactInterface deleteContactInterface){ + apiService.deleteContact(token, contact_id) + .enqueue(new Callback>() { + @Override + public void onResponse(Call> call, Response> response) { + if (response.isSuccessful()){ + deleteContactInterface.onContactDelete(); + }else{ + deleteContactInterface.onContactDeleteFailed(); + Log.e(TAG, "onResponse: delete contact message " + response.message() + " " + + "code " + response.code()); + } + } + + @Override + public void onFailure(Call> call, Throwable t) { + Log.e(TAG, "onFailure: delete contact", t); + deleteContactInterface.onContactDeleteFailed(); + } + }); } public ArrayList getContactList(Context context) { @@ -123,10 +191,13 @@ public class UserContactRepository { name = cursor.getString(nameIndex); number = cursor.getString(numberIndex); - - // avoiding duplicate phone number - number = number.replace(" ", ""); if (!mobileNoSet.contains(number)) { + number = PhoneNumberUtils.formatNumber(number, Locale.getDefault().getCountry()); + + number = number.replace("-", ""); + number = number.replace("(", ""); + number = number.replace(")", ""); + contactList.add(new Contact(name, number)); mobileNoSet.add(number); } diff --git a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/models/CareGiverData.java b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/models/CareGiverData.java new file mode 100644 index 0000000..2cb0589 --- /dev/null +++ b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/models/CareGiverData.java @@ -0,0 +1,24 @@ +package com.ssb.simplitend.welcome.fragments.contacts.mvvm.models; + +import androidx.annotation.NonNull; + +import java.io.Serializable; + +public class CareGiverData implements Serializable { + public int contact_xid; + public String id; + public String principalXid; + + public CareGiverData() { + } + + @NonNull + @Override + public String toString() { + return "CareGiverData{" + + "contact_xid=" + contact_xid + + ", id='" + id + '\'' + + ", principalXid='" + principalXid + '\'' + + '}'; + } +} diff --git a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/models/ContactData.java b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/models/ContactData.java new file mode 100644 index 0000000..000eb1c --- /dev/null +++ b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/models/ContactData.java @@ -0,0 +1,61 @@ +package com.ssb.simplitend.welcome.fragments.contacts.mvvm.models; + +import androidx.annotation.NonNull; + +import com.ssb.simplitend.welcome.fragments.contacts.mvvm.Contact; + +import java.io.Serializable; +import java.util.Objects; + +public class ContactData implements Serializable { + public int id; + public String first_name; + public String phone_number; + public String email_address; + public String relationship; + public String is_sos; + public String contact_photo; + public CareGiverData care_giver_data; + + public int contact_id; + + public ContactData() { + } + + public ContactData(Contact contact){ + this.first_name = contact.first_name; + this.phone_number = contact.phone_number; + } + + public ContactData(int id) { + this.id = id; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ContactData that = (ContactData) o; + return id == that.id && Objects.equals(first_name, that.first_name) && Objects.equals(phone_number, that.phone_number) && Objects.equals(email_address, that.email_address) && Objects.equals(relationship, that.relationship) && Objects.equals(is_sos, that.is_sos) && Objects.equals(contact_photo, that.contact_photo) && Objects.equals(care_giver_data, that.care_giver_data); + } + + @Override + public int hashCode() { + return Objects.hash(id, first_name, phone_number, email_address, relationship, is_sos, contact_photo, care_giver_data); + } + + @NonNull + @Override + public String toString() { + return "ContactData{" + + "id=" + id + + ", first_name='" + first_name + '\'' + + ", phone_number='" + phone_number + '\'' + + ", email_address='" + email_address + '\'' + + ", relationship='" + relationship + '\'' + + ", is_sos='" + is_sos + '\'' + + ", contact_photo='" + contact_photo + '\'' + + ", care_giver_data=" + care_giver_data + + '}'; + } +} diff --git a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/models/ContactListResponse.java b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/models/ContactListResponse.java index 2f1637e..7765b3e 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/models/ContactListResponse.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/fragments/contacts/mvvm/models/ContactListResponse.java @@ -25,52 +25,4 @@ public class ContactListResponse{ } } -class CareGiverData{ - public int contact_xid; - public String id; - public String principalXid; - - public CareGiverData() { - } - - @NonNull - @Override - public String toString() { - return "CareGiverData{" + - "contact_xid=" + contact_xid + - ", id='" + id + '\'' + - ", principalXid='" + principalXid + '\'' + - '}'; - } -} - -class ContactData{ - public int id; - public String first_name; - public String phone_number; - public String email_address; - public String relationship; - public String is_sos; - public String contact_photo; - public CareGiverData care_giver_data; - - public ContactData() { - } - - @NonNull - @Override - public String toString() { - return "ContactData{" + - "id=" + id + - ", first_name='" + first_name + '\'' + - ", phone_number='" + phone_number + '\'' + - ", email_address='" + email_address + '\'' + - ", relationship='" + relationship + '\'' + - ", is_sos='" + is_sos + '\'' + - ", contact_photo='" + contact_photo + '\'' + - ", care_giver_data=" + care_giver_data + - '}'; - } -} - diff --git a/app/src/main/java/com/ssb/simplitend/welcome/fragments/register/CreatePinFragment.java b/app/src/main/java/com/ssb/simplitend/welcome/fragments/register/CreatePinFragment.java index e045ada..1bf2a93 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/fragments/register/CreatePinFragment.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/fragments/register/CreatePinFragment.java @@ -116,7 +116,7 @@ public class CreatePinFragment extends Fragment implements WelcomeContracts.Regi progressDialog.setMessage("Almost there..."); - AppUtil.saveToken(token, requireContext()); + AppUtil.saveUserCache(token, patientResult.patientId, requireContext()); progressDialog.dismiss(); diff --git a/app/src/main/java/com/ssb/simplitend/welcome/fragments/register/RegisterFragment.java b/app/src/main/java/com/ssb/simplitend/welcome/fragments/register/RegisterFragment.java index bf39aeb..dd35290 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/fragments/register/RegisterFragment.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/fragments/register/RegisterFragment.java @@ -33,9 +33,12 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; import java.util.Locale; public class RegisterFragment extends Fragment { @@ -100,6 +103,8 @@ public class RegisterFragment extends Fragment { binding.nextBtn.setOnClickListener(v -> { if (allOkay()){ + AppUtil.closeKeyboard(requireActivity()); + PatientData patientData = viewModel.getPatientData(); patientData.first_name = patientData.user_name = binding.name.getText().toString(); @@ -147,6 +152,24 @@ public class RegisterFragment extends Fragment { if (binding.dob.getText().toString().trim().isEmpty()){ binding.dob.setError("Required"); allOkay = false; + }else { + SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy", Locale.getDefault()); + try { + Date selected_date = sdf.parse(binding.dob.getText().toString().trim()); + Calendar selected_calender = Calendar.getInstance(); + selected_calender.setTime(selected_date); + + Calendar minAdultAge = Calendar.getInstance(); + minAdultAge.add(Calendar.YEAR, -18); + + if (minAdultAge.before(selected_calender)){ + Toast.makeText(requireContext(), "Age must be above 18+ years", Toast.LENGTH_SHORT).show(); + } + + } catch (Exception e) { + Log.e(TAG, "allOkay: ", e); + // TODO: 17-07-2023 check out this thing + } } if (binding.contactNumber.getText().toString().trim().isEmpty()){ @@ -243,6 +266,10 @@ public class RegisterFragment extends Fragment { DatePickerDialog datePickerDialog = new DatePickerDialog(requireContext()); + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) - 18); + datePickerDialog.getDatePicker().setMaxDate(calendar.getTimeInMillis()); + datePickerDialog.setOnDateSetListener((view, year, month, dayOfMonth) -> { setDOB(year, month, dayOfMonth); }); diff --git a/app/src/main/java/com/ssb/simplitend/welcome/mvvm/APIService.java b/app/src/main/java/com/ssb/simplitend/welcome/mvvm/APIService.java index b0d356d..ac90127 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/mvvm/APIService.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/mvvm/APIService.java @@ -8,22 +8,40 @@ import com.ssb.simplitend.welcome.mvvm.models.PatientResult; import java.util.List; import java.util.Map; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; import retrofit2.Call; -import retrofit2.http.Body; import retrofit2.http.GET; import retrofit2.http.Header; +import retrofit2.http.Multipart; import retrofit2.http.POST; +import retrofit2.http.Part; +import retrofit2.http.PartMap; +import retrofit2.http.Path; import retrofit2.http.Url; public interface APIService { + @Multipart @POST - Call> registerPatient(@Url String URL, @Body Map body); + Call> registerPatient(@Url String URL, + @PartMap Map body); + @Multipart + @POST("api/auth/patient-login") + Call> loginPatient(@PartMap Map credentials); + + @Multipart @POST - Call> createContact(@Url String URL, @Body Map body, - @Header("Authorization") String token); + Call> createEditContact(@Url String URL, + @PartMap Map body, + @PartMap Map intBody, + @Part MultipartBody.Part userImage, + @Header("Authorization") String token); @GET Call>> getContactList(@Url String URL, @Header("Authorization") String token); + + @POST("api/patient-contact-delete/{id}") + Call> deleteContact(@Header("Authorization") String token, @Path("id") int contact_id); } diff --git a/app/src/main/java/com/ssb/simplitend/welcome/mvvm/WelcomeContracts.java b/app/src/main/java/com/ssb/simplitend/welcome/mvvm/WelcomeContracts.java index 3d2b264..47de6ee 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/mvvm/WelcomeContracts.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/mvvm/WelcomeContracts.java @@ -31,4 +31,20 @@ public interface WelcomeContracts { } + interface DeleteContactInterface { + + void onContactDelete(); + + void onContactDeleteFailed(); + + } + + interface UpdateContactContracts { + + void onContactUpdated(); + + void onUpdateFailed(); + + } + } diff --git a/app/src/main/java/com/ssb/simplitend/welcome/mvvm/WelcomeRepository.java b/app/src/main/java/com/ssb/simplitend/welcome/mvvm/WelcomeRepository.java index 327560c..37af8da 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/mvvm/WelcomeRepository.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/mvvm/WelcomeRepository.java @@ -11,6 +11,7 @@ import androidx.annotation.NonNull; import com.ssb.simplitend.welcome.mvvm.models.CallResponse; import com.ssb.simplitend.welcome.mvvm.models.PatientResult; +import okhttp3.RequestBody; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; @@ -31,8 +32,37 @@ public class WelcomeRepository { return welcomeRepository; } + public void loginPatient(@NonNull Map credentials, + @NonNull WelcomeContracts.RegisterPatientContract loginCallback){ + + APIService welcomeService = getRetrofit().create(APIService.class); + + welcomeService.loginPatient(credentials).enqueue(new Callback>() { + @Override + public void onResponse(Call> call, Response> response) { + if (response.isSuccessful() && response.body() != null && response.body().result != null) + { + loginCallback.onResponse(response.body().result, response.body().token); + }else if (response.body() != null){ + Log.e(TAG, "onResponse: login patient " + response); + loginCallback.onFailure(new Exception(response.toString()), response.body().message, response.code()); + }else{ + Log.e(TAG, "onResponse: login patient :no success response and also response body is null"); + loginCallback.onFailure(new Exception("no success response and also response body is null"), "It's not you, it's us.\nPlease try again later", 1); + } + } + + @Override + public void onFailure(Call> call, Throwable t) { + Log.e(TAG, "onFailure: login patient", t); + loginCallback.onFailure(t, t.getMessage(), 1); + } + }); + + } + public void registerPatient(@NonNull String URL, - @NonNull Map body, + @NonNull Map body, @NonNull WelcomeContracts.RegisterPatientContract registerPatient){ APIService welcomeService = getRetrofit().create(APIService.class); diff --git a/app/src/main/java/com/ssb/simplitend/welcome/mvvm/WelcomeViewModel.java b/app/src/main/java/com/ssb/simplitend/welcome/mvvm/WelcomeViewModel.java index e822ae4..6861efa 100644 --- a/app/src/main/java/com/ssb/simplitend/welcome/mvvm/WelcomeViewModel.java +++ b/app/src/main/java/com/ssb/simplitend/welcome/mvvm/WelcomeViewModel.java @@ -8,6 +8,9 @@ import com.ssb.simplitend.welcome.mvvm.models.PatientData; import java.util.HashMap; import java.util.Map; +import okhttp3.MediaType; +import okhttp3.RequestBody; + public class WelcomeViewModel extends ViewModel { private final WelcomeRepository welcomeRepository; @@ -20,28 +23,60 @@ public class WelcomeViewModel extends ViewModel { } public void registerPatient(@NonNull String URL, @NonNull WelcomeContracts.RegisterPatientContract registerPatientContract){ - Map body = new HashMap<>(); + Map body = new HashMap<>(); PatientData patientData = getPatientData(); - body.put("full_name", patientData.first_name); - body.put("date_of_birth", patientData.date_of_birth); - body.put("contact_number", patientData.phone_number); - body.put("email", patientData.email); - body.put("street", patientData.address_line1); - body.put("town", patientData.city); - body.put("state", patientData.state); - body.put("country", patientData.country); - body.put("zip_code", patientData.post_code); - body.put("pin_code", patientData.pin_code); - body.put("cpin_code", patientData.c_pin_code); - body.put("lat", patientData.lat); - body.put("lng", patientData.lng); + RequestBody first_name_body = RequestBody.create(patientData.first_name, MediaType.parse("text/plain;charset=utf-8") ); + body.put("full_name", first_name_body); + + RequestBody dob_body = RequestBody.create(patientData.date_of_birth, MediaType.parse("text/plain;charset=utf-8") ); + body.put("date_of_birth", dob_body); + + RequestBody phone_number_body = RequestBody.create(patientData.phone_number, MediaType.parse("text/plain;charset=utf-8") ); + body.put("contact_number", phone_number_body); + + RequestBody email_body = RequestBody.create(patientData.email, MediaType.parse("text/plain;charset=utf-8") ); + body.put("email", email_body); + + RequestBody street_body = RequestBody.create(patientData.address_line1, MediaType.parse("text/plain;charset=utf-8") ); + body.put("street", street_body); + + RequestBody town_body = RequestBody.create(patientData.city, MediaType.parse("text/plain;charset=utf-8") ); + body.put("town", town_body); + + RequestBody state_body = RequestBody.create(patientData.state, MediaType.parse("text/plain;charset=utf-8") ); + body.put("state", state_body); + + RequestBody country_body = RequestBody.create(patientData.country, MediaType.parse("text/plain;charset=utf-8") ); + body.put("country", country_body); + + RequestBody zip_code_body = RequestBody.create(patientData.post_code, MediaType.parse("text/plain;charset=utf-8") ); + body.put("zip_code", zip_code_body); + + RequestBody pin_body = RequestBody.create(patientData.pin_code, MediaType.parse("text/plain;charset=utf-8") ); + body.put("pin_code", pin_body); + + RequestBody cpin_body = RequestBody.create(patientData.c_pin_code, MediaType.parse("text/plain;charset=utf-8") ); + body.put("cpin_code", cpin_body); + + RequestBody lat_body = RequestBody.create(patientData.lat, MediaType.parse("text/plain;charset=utf-8") ); + body.put("lat", lat_body); + + RequestBody lng_body = RequestBody.create(patientData.lng, MediaType.parse("text/plain;charset=utf-8") ); + body.put("lng", lng_body); welcomeRepository.registerPatient(URL, body, registerPatientContract); } + public void loginPatient(@NonNull Map credentials, + @NonNull WelcomeContracts.RegisterPatientContract loginCallback){ + + welcomeRepository.loginPatient(credentials, loginCallback); + + } + public synchronized PatientData getPatientData(){ if (patientData == null){ diff --git a/app/src/main/res/layout/add_contact_fragment.xml b/app/src/main/res/layout/add_contact_fragment.xml index 83b956d..e5835f9 100644 --- a/app/src/main/res/layout/add_contact_fragment.xml +++ b/app/src/main/res/layout/add_contact_fragment.xml @@ -1,5 +1,5 @@ - + + android:paddingHorizontal="10dp" + android:paddingVertical="15dp" + + android:textColor="@color/black" + android:textColorHint="@android:color/darker_gray" /> + android:text="@string/atleast_add_one_contact" + android:textColor="@color/black" /> + + - - + android:overScrollMode="never" /> - \ No newline at end of file + + + \ No newline at end of file diff --git a/app/src/main/res/layout/add_contact_viewholder.xml b/app/src/main/res/layout/add_contact_viewholder.xml index f837991..955739e 100644 --- a/app/src/main/res/layout/add_contact_viewholder.xml +++ b/app/src/main/res/layout/add_contact_viewholder.xml @@ -11,7 +11,7 @@ - + + @@ -43,7 +45,10 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" - android:layout_margin="15dp" + android:layout_marginStart="15dp" + android:layout_marginTop="15dp" + android:layout_marginEnd="15dp" + android:layout_marginBottom="15dp" android:layout_toStartOf="@id/edit" android:contentDescription="@string/edit_contact" android:padding="5dp" @@ -61,23 +66,35 @@ android:textAppearance="@style/TextAppearance.Material3.TitleLarge" android:textColor="@color/black" /> - + app:cardCornerRadius="@dimen/_50sdp" + app:strokeColor="@color/color_accent" + app:strokeWidth="1dp" + > + + + + @@ -98,9 +115,10 @@ android:fontFamily="@font/nunito_medium" android:textAppearance="@style/TextAppearance.Material3.TitleLarge" android:textColor="@color/black" - android:text="@string/_918208401763" /> + tools:text="@string/_918208401763" /> @@ -158,39 +177,6 @@ android:alpha="0.5" android:background="@android:color/darker_gray" /> - - - - - diff --git a/app/src/main/res/layout/sign_in_fragment.xml b/app/src/main/res/layout/sign_in_fragment.xml index 99dd114..eeff3d0 100644 --- a/app/src/main/res/layout/sign_in_fragment.xml +++ b/app/src/main/res/layout/sign_in_fragment.xml @@ -142,6 +142,7 @@ /> + app:startDestination="@id/addContactFragment"> @@ -117,7 +116,7 @@ + android:label="AddContactFragment"> @@ -136,7 +135,12 @@ + android:label="ContactInfoFragment" + > + + Welcome to SimpliTend Sign in to continue. Email address* + Email address Enter your email. Enter pin Enter your pin @@ -49,6 +50,7 @@ Name* Enter your full name Date of birth* + Date of birth Select your date of birth Contact number* Phone number @@ -80,6 +82,7 @@ Change photo Add photo Relationship* + Relationship Make current contact as a caregiver Make current contact as In Case Of Emergency Contact (SOS) *SOS is set to E911 default @@ -225,5 +228,8 @@ Search places I accept terms and conditions + Ok + Add contact + Are you sure you want to delete this contact? \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 867d833..787b000 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -2,13 +2,13 @@