This commit is contained in:
ADITYA
2023-07-13 21:12:17 +05:30
parent 6828216756
commit abc3070b18
44 changed files with 1994 additions and 266 deletions

View File

@@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application
@@ -14,6 +16,15 @@
android:supportsRtl="true"
android:theme="@style/Theme.SimpliTend"
tools:targetApi="31">
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="${MAPS_API_KEY}" />
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity
android:name=".careperson_dashboard.DashBoardActivityCP"
android:exported="true"

View File

@@ -1,8 +1,13 @@
package com.ssb.simplitend.apputils;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
@@ -18,6 +23,16 @@ import com.ssb.simplitend.databinding.DoneBottomsheetBinding;
public abstract class AppUtil {
private static final String TAG = "AppUtil";
// fields
public static final String USER_DETAILS = "user_details";
public static final String USER_TOKEN = "user_token";
// util functions
// closes keyboard
public static void closeKeyboard(Activity activity){
if (activity != null){
@@ -88,4 +103,42 @@ public abstract class AppUtil {
}, doneInterval);
}
// Show alert dialog
public static synchronized void showAlert(@NonNull Context context,
@NonNull String title, @NonNull String message,
@NonNull String positiveText, @NonNull DialogInterface.OnClickListener positiveClickListener,
String negativeText, DialogInterface.OnClickListener negativeClickListener) {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
alertBuilder.setTitle(title);
alertBuilder.setMessage(message);
alertBuilder.setPositiveButton(positiveText, positiveClickListener /* Call back*/);
if (negativeText != null && negativeClickListener != null) {
// Negative button
alertBuilder.setNegativeButton(negativeText, negativeClickListener);
}
alertBuilder.create().show(); // Showing alert dialog
}
public static void saveToken(String token, Context context){
SharedPreferences sp = context.getSharedPreferences(USER_DETAILS, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putString(USER_TOKEN, token);
editor.apply();
Log.d(TAG, "saveToken: user token saved successful");
}
public static String getUserToken(Context context){
SharedPreferences sp = context.getSharedPreferences(USER_DETAILS, Context.MODE_PRIVATE);
return sp.getString(USER_TOKEN, "");
}
}

View File

@@ -0,0 +1,46 @@
package com.ssb.simplitend.apputils;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public abstract class RetrofitHelper {
// urls
public static final String BASE_URL = "https://simplitend.betadelivery.com/";
public static final String REGISTER_PATIENT = "api/auth/patient-register";
public static final String GET_CONTACT_LIST = "api/patients-contact-list";
// util functions
private static Retrofit retrofit;
public static synchronized Retrofit getRetrofit(){
if (retrofit == null){
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())
.build();
}
return retrofit;
}
}

View File

@@ -0,0 +1,99 @@
package com.ssb.simplitend.careperson_dashboard.chats;
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.navigation.Navigation;
import com.ssb.simplitend.R;
import com.ssb.simplitend.careperson_dashboard.chats.mvvm.Author;
import com.ssb.simplitend.careperson_dashboard.chats.mvvm.ChatItem;
import com.ssb.simplitend.careperson_dashboard.chats.mvvm.Message;
import com.ssb.simplitend.careperson_dashboard.chats.mvvm.Receiver;
import com.ssb.simplitend.databinding.ChatFragmentBinding;
import com.stfalcon.chatkit.messages.MessagesListAdapter;
public class ChatFragment extends Fragment {
// view binding
protected ChatFragmentBinding binding;
// chat item
private ChatItem chatItem;
public static final String CHAT_ITEM_KEY = "chat_item_key";
private MessagesListAdapter<Message> messageAdapter;
public ChatFragment() {
// required
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = ChatFragmentBinding.inflate(inflater, container, false);
initViews();
clickEvents();
return binding.getRoot();
}
private void clickEvents() {
binding.backBtn.setOnClickListener(v -> Navigation.findNavController(v).popBackStack());
binding.sendBtn.setOnClickListener(v -> {
if (!binding.messageEt.getText().toString().trim().isEmpty()){
messageAdapter.addToStart(new Message(new Author(), binding.messageEt.getText().toString().trim()), true);
binding.messageEt.setText(null);
}
});
}
private void initViews() {
Bundle bundle = getArguments();
if (bundle == null) {
Toast.makeText(requireActivity(), "Something went wrong", Toast.LENGTH_SHORT).show();
return;
}
chatItem = (ChatItem) bundle.getSerializable(CHAT_ITEM_KEY);
if (chatItem == null) {
Toast.makeText(requireActivity(), "Something went wrong", Toast.LENGTH_SHORT).show();
return;
}
binding.chatTitle.setText(chatItem.name);
MessagesListAdapter.HoldersConfig holdersConfig = new MessagesListAdapter.HoldersConfig();
holdersConfig.setOutcomingLayout(R.layout.sender_msg_viewholder);
messageAdapter = new MessagesListAdapter<>("sender", holdersConfig, (imageView, url, payload) -> {
if (url != null) imageView.setImageResource(Integer.parseInt(url));
});
binding.messageList.setAdapter(messageAdapter);
// static
messageAdapter.addToStart(new Message(new Author(), "Good morning"), true);
messageAdapter.addToStart(new Message(new Receiver(), "Good morning mate! I am fine here how are you there"), true);
messageAdapter.addToStart(new Message(new Author(), "Good morning"), true);
messageAdapter.addToStart(new Message(new Receiver(), "Good morning mate!"), true);
messageAdapter.addToStart(new Message(new Author(), "Good morning"), true);
messageAdapter.addToStart(new Message(new Receiver(), "Good morning mate!"), true);
messageAdapter.addToStart(new Message(new Author(), "Good morning"), true);
messageAdapter.addToStart(new Message(new Receiver(), "Good morning mate!"), true);
messageAdapter.addToStart(new Message(new Receiver(), chatItem.last_message), true);
}
}

View File

@@ -13,6 +13,8 @@ import com.ssb.simplitend.databinding.ChatCardViewholderBinding;
public class ChatListAdapter extends ListAdapter<ChatItem, ChatListAdapter.ChatCardViewHolder> {
private OnChatItemClickListener chatItemClickListener;
private static final DiffUtil.ItemCallback<ChatItem> DIFF_UTIL = new DiffUtil.ItemCallback<ChatItem>() {
@Override
public boolean areItemsTheSame(@NonNull ChatItem oldItem, @NonNull ChatItem newItem) {
@@ -41,6 +43,12 @@ public class ChatListAdapter extends ListAdapter<ChatItem, ChatListAdapter.ChatC
@Override
public void onBindViewHolder(@NonNull ChatCardViewHolder holder, int position) {
holder.setData(getItem(position), position);
holder.binding.card.setOnClickListener(v -> {
if (chatItemClickListener != null){
chatItemClickListener.onChatItemClick(getItem(position), position);
}
});
}
public static class ChatCardViewHolder extends RecyclerView.ViewHolder{
@@ -61,4 +69,18 @@ public class ChatListAdapter extends ListAdapter<ChatItem, ChatListAdapter.ChatC
}
// setters
public void setChatItemClickListener(OnChatItemClickListener chatItemClickListener) {
this.chatItemClickListener = chatItemClickListener;
}
// interfaces
@FunctionalInterface
public interface OnChatItemClickListener{
void onChatItemClick(ChatItem chatItem, int position);
}
}

View File

@@ -1,5 +1,7 @@
package com.ssb.simplitend.careperson_dashboard.chats;
import static com.ssb.simplitend.careperson_dashboard.chats.ChatFragment.CHAT_ITEM_KEY;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -14,10 +16,11 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import com.ssb.simplitend.R;
import com.ssb.simplitend.apputils.AppUtil;
import com.ssb.simplitend.careperson_dashboard.chats.mvvm.ChatItem;
import com.ssb.simplitend.careperson_dashboard.chats.mvvm.ChatListViewModel;
import com.ssb.simplitend.databinding.ChatListFragmentBinding;
public class ChatListFragment extends Fragment {
public class ChatListFragment extends Fragment implements ChatListAdapter.OnChatItemClickListener {
// view binding
protected ChatListFragmentBinding binding;
@@ -49,6 +52,8 @@ public class ChatListFragment extends Fragment {
binding.chatsRv.setAdapter(viewModel.getChatListAdapter());
viewModel.getChatListAdapter().submitList(viewModel.getChatItemList());
viewModel.getChatListAdapter().setChatItemClickListener(this);
}
private void clickEvents() {
@@ -59,4 +64,12 @@ public class ChatListFragment extends Fragment {
});
}
@Override
public void onChatItemClick(ChatItem chatItem, int position) {
Bundle bundle = new Bundle();
bundle.putSerializable(CHAT_ITEM_KEY, chatItem);
Navigation.findNavController(binding.getRoot()).navigate(R.id.action_chatListFragment_to_chatFragment, bundle);
}
}

View File

@@ -0,0 +1,21 @@
package com.ssb.simplitend.careperson_dashboard.chats.mvvm;
import com.ssb.simplitend.R;
import com.stfalcon.chatkit.commons.models.IUser;
public class Author implements IUser {
@Override
public String getId() {
return "sender";
}
@Override
public String getName() {
return null;
}
@Override
public String getAvatar() {
return String.valueOf(R.drawable.static_3);
}
}

View File

@@ -1,6 +1,8 @@
package com.ssb.simplitend.careperson_dashboard.chats.mvvm;
public class ChatItem {
import java.io.Serializable;
public class ChatItem implements Serializable {
public String type, name, time, last_message;

View File

@@ -0,0 +1,37 @@
package com.ssb.simplitend.careperson_dashboard.chats.mvvm;
import com.stfalcon.chatkit.commons.models.IMessage;
import com.stfalcon.chatkit.commons.models.IUser;
import java.util.Date;
public class Message implements IMessage {
private final IUser author;
private final String text;
public Message(IUser user, String text){
this.author = user;
this.text = text;
}
@Override
public String getId() {
return "message_id";
}
@Override
public String getText() {
return text;
}
@Override
public IUser getUser() {
return author;
}
@Override
public Date getCreatedAt() {
return new Date(System.currentTimeMillis());
}
}

View File

@@ -0,0 +1,22 @@
package com.ssb.simplitend.careperson_dashboard.chats.mvvm;
import com.ssb.simplitend.R;
import com.stfalcon.chatkit.commons.models.IUser;
public class Receiver implements IUser {
@Override
public String getId() {
return "receiver";
}
@Override
public String getName() {
return null;
}
@Override
public String getAvatar() {
return String.valueOf(R.drawable.static_3);
}
}

View File

@@ -1,7 +1,6 @@
package com.ssb.simplitend.welcome.activities;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import android.os.Bundle;
@@ -12,6 +11,8 @@ public class WelcomeActivity extends AppCompatActivity {
// View binding
protected ActivityWelcomeBinding binding;
private static final String TAG = "aditya";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

View File

@@ -1,6 +1,7 @@
package com.ssb.simplitend.welcome.fragments;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -9,10 +10,12 @@ 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.ssb.simplitend.R;
import com.ssb.simplitend.databinding.WelcomeFragmentBinding;
import com.ssb.simplitend.welcome.mvvm.WelcomeViewModel;
public class WelcomeFragment extends Fragment {
@@ -37,6 +40,7 @@ public class WelcomeFragment extends Fragment {
// Initialize views
private void initViews(Bundle savedInstanceState) {
WelcomeViewModel wv = new ViewModelProvider(requireActivity()).get(WelcomeViewModel.class);
}
// Register click events

View File

@@ -32,7 +32,7 @@ import com.ssb.simplitend.welcome.fragments.contacts.mvvm.ContactViewModel;
import java.util.ArrayList;
public class ContactListFragment extends Fragment {
public class ContactListFragment extends Fragment{
private static final String TAG = "aditya";
@@ -171,7 +171,7 @@ public class ContactListFragment extends Fragment {
return;
}
contactViewModel = new ViewModelProvider(this).get(ContactViewModel.class);
contactViewModel = new ViewModelProvider(requireActivity()).get(ContactViewModel.class);
Log.d(TAG, "initializeViews: viewmodel " + contactViewModel);
contactList = null;

View File

@@ -1,38 +1,39 @@
package com.ssb.simplitend.welcome.fragments.contacts;
import android.content.Context;
import static com.ssb.simplitend.apputils.RetrofitHelper.GET_CONTACT_LIST;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
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.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.databinding.DecisionBottomsheetBinding;
import com.ssb.simplitend.databinding.DoneBottomsheetBinding;
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.ContactListResponse;
import com.ssb.simplitend.welcome.mvvm.WelcomeContracts;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class CreateContactFragment extends Fragment {
public class CreateContactFragment extends Fragment implements WelcomeContracts.ContactListContracts,
ContactViewModel.GotoAddContactInterface, ContactViewModel.SOSCheckInterface,
WelcomeContracts.CreateContactInterface {
// log tag
private static final String TAG = "CreateContactFragment";
@@ -40,6 +41,8 @@ public class CreateContactFragment extends Fragment {
// view binding
protected CreateEditContactFragmentBinding binding;
private ProgressDialog progressDialog;
// arguments keys
public static final String TO_EDIT_KEY = "to_edit";
public static final String CONTACT_KEY = "contact_key";
@@ -50,6 +53,10 @@ public class CreateContactFragment extends Fragment {
// image selector launcher
private ActivityResultLauncher<String> imageSelector;
private ContactViewModel contactViewModel;
private ArrayList<String> countryCodeList;
public CreateContactFragment() {
// required empty const.
}
@@ -59,6 +66,12 @@ public class CreateContactFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = CreateEditContactFragmentBinding.inflate(inflater, container, false);
contactViewModel = new ViewModelProvider(requireActivity()).get(ContactViewModel.class);
// interfaces
contactViewModel.setSosCheckInterface(this);
contactViewModel.setGotoAddContactInterface(this);
initializeViews();
clickEvents();
@@ -66,106 +79,6 @@ public class CreateContactFragment extends Fragment {
return binding.getRoot();
}
private void clickEvents() {
binding.backBtn.setOnClickListener(v -> Navigation.findNavController(v).popBackStack());
binding.nextBtn.setOnClickListener(v -> {
if (to_edit){
// editing existing contact
showSaveEditDecision();
}else {
// saving new contact
Navigation.findNavController(v).popBackStack();
}
});
binding.image.setOnClickListener(v -> imageSelector.launch("image/*"));
}
private void showSaveEditDecision() {
DecisionBottomsheetBinding binding = DecisionBottomsheetBinding.inflate(getLayoutInflater());
BottomSheetDialog bsd = new BottomSheetDialog(requireContext(), R.style.BottomSheetDialog);
bsd.setContentView(binding.getRoot());
binding.text.setText(getString(R.string.make_changes));
binding.positiveBtn.setText(getString(R.string.yes));
binding.negativeBtn.setText(getString(R.string.no));
binding.negativeBtn.setOnClickListener(v -> bsd.dismiss());
binding.positiveBtn.setOnClickListener(v -> {
bsd.dismiss();
showDoneBottomSheet();
});
bsd.show();
}
private void showDoneBottomSheet() {
DoneBottomsheetBinding binding = DoneBottomsheetBinding.inflate(getLayoutInflater());
BottomSheetDialog bsd = new BottomSheetDialog(requireContext(), R.style.BottomSheetDialog);
bsd.setContentView(binding.getRoot());
bsd.setCancelable(false);
binding.text.setText(getString(R.string.changes_successful));
Glide.with(requireContext())
.asGif()
.load(R.raw.done_anim_primary)
.into(binding.doneAnim);
bsd.show();
gotoAddContactFragment(3000, bsd);
}
private void gotoAddContactFragment(long inMsm, BottomSheetDialog bsd){
new Handler().postDelayed(() -> {
if (bsd != null) bsd.dismiss();
Navigation.findNavController(binding.getRoot())
.navigate(R.id.action_createContactFragment_to_addContactFragment);
}, inMsm);
}
private void showSOSDecision() {
DecisionBottomsheetBinding binding = DecisionBottomsheetBinding.inflate(getLayoutInflater());
BottomSheetDialog bsd = new BottomSheetDialog(requireContext(), R.style.BottomSheetDialog);
bsd.setContentView(binding.getRoot());
bsd.setCancelable(false);
binding.text.setText(getString(R.string.make_sos));
binding.positiveBtn.setText(getString(R.string.yes));
binding.negativeBtn.setText(getString(R.string.no));
binding.negativeBtn.setOnClickListener(v -> {
bsd.dismiss();
this.binding.sosCheck.setChecked(false);
});
binding.positiveBtn.setOnClickListener(v -> {
bsd.dismiss();
this.binding.sosCheck.setChecked(true);
});
bsd.show();
}
private void initializeViews() {
Bundle bundle = getArguments();
@@ -184,14 +97,14 @@ public class CreateContactFragment extends Fragment {
}
}
progressDialog = new ProgressDialog(requireContext());
binding.sosCheck.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked){
showSOSDecision();
contactViewModel.showSOSDecision(requireContext());
}
});
loadCountryCodeDropDown();
// image selector launcher
imageSelector = registerForActivityResult(new ActivityResultContracts.GetContent(),
uri -> {
@@ -201,32 +114,8 @@ public class CreateContactFragment extends Fragment {
}
});
}
private void loadCountryCodeDropDown() {
ArrayList<String> countryCodeList = new ArrayList<>();
try {
String countryCodeStr = readCountryCodes(requireContext());
JSONArray jsonArray = new JSONArray(countryCodeStr);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject code = jsonArray.getJSONObject(i);
countryCodeList.add(code.getString("dial_code"));
}
} catch (Exception e) {
// if cannot load all country codes showing only india's dial code
countryCodeList.add("+91");
Log.e(TAG, "loadCountryCodeDropDown: ", e);
}
// country code loading
countryCodeList = contactViewModel.loadCountryCodeDropDown(requireContext());
binding.countryCodes.setLifecycleOwner(this);
@@ -238,39 +127,99 @@ public class CreateContactFragment extends Fragment {
binding.countryCodes.setIsFocusable(true);
loadRemoteContactList();
}
public String readCountryCodes(Context context) throws IOException {
StringBuilder returnString = new StringBuilder();
private void clickEvents() {
InputStream fIn = context.getResources().openRawResource(R.raw.country_code);
InputStreamReader isr = new InputStreamReader(fIn);
BufferedReader input = new BufferedReader(isr);
binding.backBtn.setOnClickListener(v -> Navigation.findNavController(v).popBackStack());
String line = "";
binding.nextBtn.setOnClickListener(v -> {
while ((line = input.readLine()) != null) {
returnString.append(line);
if (to_edit){
// editing existing contact
contactViewModel.showSaveEditDecision(requireContext());
}else {
// saving new contact
Navigation.findNavController(v).popBackStack();
}
});
binding.image.setOnClickListener(v -> imageSelector.launch("image/*"));
}
@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);
}, 3000);
}
@Override
public void onCheckChange(boolean state) {
binding.sosCheck.setChecked(state);
}
// remote call back fetching callBack
@Override
public void onResponse(List<ContactListResponse> contactList) {
Log.d(TAG, "onResponse: " + contactList);
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.caregiverCheck.setChecked(true);
binding.caregiverCheck.setEnabled(false);
}
try {
isr.close();
progressDialog.dismiss();
}
if (fIn != null) fIn.close();
@Override
public void onFailure(Throwable t, String message, int error_code) {
Log.e(TAG, "onFailure: message : " + message + "\n", t);
input.close();
progressDialog.dismiss();
Navigation.findNavController(binding.getRoot()).popBackStack();
Toast.makeText(requireContext(), "Couldn't load contact", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Log.e(TAG, "readCountryCodes: ", e);
}
// create contact callback
return returnString.toString();
@Override
public void onContactCreated(Contact contact) {
}
@Override
public void onContactCreateFailed(Throwable t, String message, int error_code) {
}
// loading remote contact list to know whether this is user's first contact
private void loadRemoteContactList() {
progressDialog.setTitle("Please wait");
progressDialog.setMessage("Loading contact details");
progressDialog.setCancelable(false);
progressDialog.show();
String token = "Bearer " + AppUtil.getUserToken(requireContext());
contactViewModel.getRemoteContactList(GET_CONTACT_LIST, this, token);
}
private void setDetails(Contact contact) {
binding.name.setText(contact.name);
binding.phoneNumber.setText(contact.phoneNumber);
binding.email.setText(contact.email);
binding.name.setText(contact.first_name);
binding.phoneNumber.setText(contact.phone_number);
binding.email.setText(contact.email_address);
binding.relationship.setText(contact.relationship);
}

View File

@@ -1,6 +1,5 @@
package com.ssb.simplitend.welcome.fragments.contacts.mvvm;
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.AlertDialog;

View File

@@ -5,17 +5,21 @@ import java.util.Objects;
public class Contact implements Serializable {
public String name, imageUri, phoneNumber, relationship, email;
public String first_name, imageUri, phone_number, relationship, email_address;
public String is_sos, updated_at, created_at;
public long id;
public Contact(){}
public Contact(String name){
this.name = name;
this.first_name = first_name;
}
public Contact(String name, String phoneNumber){
this.name = name;
this.phoneNumber = phoneNumber;
public Contact(String first_name, String phoneNumber){
this.first_name= first_name;
this.phone_number = phoneNumber;
}
@Override
@@ -23,22 +27,22 @@ public class Contact implements Serializable {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Contact contact = (Contact) o;
return name.equals(contact.name) && Objects.equals(imageUri, contact.imageUri) && phoneNumber.equals(contact.phoneNumber) && Objects.equals(relationship, contact.relationship) && Objects.equals(email, contact.email);
return first_name.equals(contact.first_name) && Objects.equals(imageUri, contact.imageUri) && phone_number.equals(contact.phone_number) && Objects.equals(relationship, contact.relationship) && Objects.equals(email_address, contact.email_address);
}
@Override
public int hashCode() {
return Objects.hash(name, imageUri, phoneNumber, relationship, email);
return Objects.hash(first_name, imageUri, phone_number, relationship, email_address);
}
@Override
public String toString() {
return "Contact{" +
"name='" + name + '\'' +
"first_name='" + first_name + '\'' +
", imageUri='" + imageUri + '\'' +
", phoneNumber='" + phoneNumber + '\'' +
", phone_number='" + phone_number + '\'' +
", relationship='" + relationship + '\'' +
", email='" + email + '\'' +
", email_address='" + email_address + '\'' +
'}';
}
}

View File

@@ -2,18 +2,42 @@ package com.ssb.simplitend.welcome.fragments.contacts.mvvm;
import android.app.Application;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import com.bumptech.glide.Glide;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.ssb.simplitend.R;
import com.ssb.simplitend.databinding.DecisionBottomsheetBinding;
import com.ssb.simplitend.databinding.DoneBottomsheetBinding;
import com.ssb.simplitend.welcome.mvvm.WelcomeContracts;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Map;
public class ContactViewModel extends AndroidViewModel {
private static final String TAG = "ContactViewModel";
private final UserContactRepository contactRepository;
private GotoAddContactInterface gotoAddContactInterface;
private SOSCheckInterface sosCheckInterface;
public ContactViewModel(Application application){
super(application);
this.contactRepository = new UserContactRepository();
this.contactRepository = UserContactRepository.getContactRepository();
}
public ArrayList<Contact> getContactList(Context context) {
@@ -23,4 +47,162 @@ public class ContactViewModel extends AndroidViewModel {
public UserContactRepository getContactRepository() {
return contactRepository;
}
public void setGotoAddContactInterface(GotoAddContactInterface gotoAddContactInterface) {
this.gotoAddContactInterface = gotoAddContactInterface;
}
public void setSosCheckInterface(SOSCheckInterface sosCheckInterface) {
this.sosCheckInterface = sosCheckInterface;
}
public void getRemoteContactList(String URL, WelcomeContracts.ContactListContracts contactListContracts, String token){
contactRepository.getRemoteContactList(URL, contactListContracts, token);
}
public void createContact(@NonNull String URL,
@NonNull Map<String, String> body,
@NonNull WelcomeContracts.CreateContactInterface createContactInterface,
@NonNull String token){
contactRepository.createContact(URL, body, createContactInterface, 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();
}
private void showDoneBottomSheet(Context context) {
DoneBottomsheetBinding binding = DoneBottomsheetBinding.inflate(LayoutInflater.from(context));
BottomSheetDialog bsd = new BottomSheetDialog(context, R.style.BottomSheetDialog);
bsd.setContentView(binding.getRoot());
bsd.setCancelable(false);
binding.text.setText(context.getString(R.string.changes_successful));
Glide.with(context)
.asGif()
.load(R.raw.done_anim_primary)
.into(binding.doneAnim);
bsd.show();
gotoAddContactFragment(3000, bsd);
}
private void gotoAddContactFragment(long inMsm, BottomSheetDialog bsd){
if (gotoAddContactInterface != null) gotoAddContactInterface.gotoAddFragment(bsd);
}
public void showSOSDecision(Context context) {
DecisionBottomsheetBinding binding = DecisionBottomsheetBinding.inflate(LayoutInflater.from(context));
BottomSheetDialog bsd = new BottomSheetDialog(context, R.style.BottomSheetDialog);
bsd.setContentView(binding.getRoot());
bsd.setCancelable(false);
binding.text.setText(context.getString(R.string.make_sos));
binding.positiveBtn.setText(context.getString(R.string.yes));
binding.negativeBtn.setText(context.getString(R.string.no));
binding.negativeBtn.setOnClickListener(v -> {
bsd.dismiss();
if (sosCheckInterface != null) sosCheckInterface.onCheckChange(false);
});
binding.positiveBtn.setOnClickListener(v -> {
bsd.dismiss();
if (sosCheckInterface != null) sosCheckInterface.onCheckChange(true);
});
bsd.show();
}
public ArrayList<String> loadCountryCodeDropDown(Context context) {
ArrayList<String> countryCodeList = new ArrayList<>();
try {
String countryCodeStr = readCountryCodes(context);
JSONArray jsonArray = new JSONArray(countryCodeStr);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject code = jsonArray.getJSONObject(i);
countryCodeList.add(code.getString("dial_code"));
}
} catch (Exception e) {
// if cannot load all country codes showing only india's dial code
countryCodeList.add("+91");
Log.e(TAG, "loadCountryCodeDropDown: ", e);
}
return countryCodeList;
}
public String readCountryCodes(Context context) throws IOException {
StringBuilder returnString = new StringBuilder();
InputStream fIn = context.getResources().openRawResource(R.raw.country_code);
InputStreamReader isr = new InputStreamReader(fIn);
BufferedReader input = new BufferedReader(isr);
String line = "";
while ((line = input.readLine()) != null) {
returnString.append(line);
}
try {
isr.close();
if (fIn != null) fIn.close();
input.close();
} catch (Exception e) {
Log.e(TAG, "readCountryCodes: ", e);
}
return returnString.toString();
}
// interfaces
public interface GotoAddContactInterface{
void gotoAddFragment(BottomSheetDialog bsd);
}
public interface SOSCheckInterface{
void onCheckChange(boolean state);
}
}

View File

@@ -2,23 +2,31 @@ package com.ssb.simplitend.welcome.fragments.contacts.mvvm;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.ssb.simplitend.welcome.fragments.contacts.mvvm.Contact;
import com.ssb.simplitend.apputils.RetrofitHelper;
import com.ssb.simplitend.welcome.fragments.contacts.mvvm.models.ContactListResponse;
import com.ssb.simplitend.welcome.mvvm.APIService;
import com.ssb.simplitend.welcome.mvvm.WelcomeContracts;
import com.ssb.simplitend.welcome.mvvm.models.CallResponse;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class UserContactRepository {
private static final String TAG = "UserContactRepository";
private static final String[] PROJECTION = new String[]{
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
@@ -26,7 +34,71 @@ public class UserContactRepository {
ContactsContract.CommonDataKinds.Phone.PHOTO_URI
};
public UserContactRepository(){}
private static UserContactRepository contactRepository;
private final APIService apiService;
private UserContactRepository(){
apiService = RetrofitHelper.getRetrofit().create(APIService.class);
}
public static synchronized UserContactRepository getContactRepository(){
if (contactRepository == null){
contactRepository = new UserContactRepository();
}
return contactRepository;
}
public void getRemoteContactList(String URL, WelcomeContracts.ContactListContracts contactListContracts, String token){
apiService.getContactList(URL, token).enqueue(new Callback<CallResponse<List<ContactListResponse>>>() {
@Override
public void onResponse(Call<CallResponse<List<ContactListResponse>>> call, Response<CallResponse<List<ContactListResponse>>> response) {
if (response.isSuccessful() && response.body() != null && response.body().result != null){
contactListContracts.onResponse(response.body().result);
}else if (response.body() != null && response.body().result != null){
Log.e(TAG, "onResponse: get contact list" + response);
contactListContracts.onFailure(new Exception(response.toString()), response.body().message, response.code());
}else{
Log.e(TAG, "onResponse: no success response and also response body is null");
contactListContracts.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<CallResponse<List<ContactListResponse>>> call, Throwable t) {
Log.e(TAG, "onFailure: ", t);
contactListContracts.onFailure(t, t.getMessage(), 1);
}
});
}
public void createContact(@NonNull String URL,
@NonNull Map<String, String> body,
@NonNull WelcomeContracts.CreateContactInterface createContactInterface,
@NonNull String token){
apiService.createContact(URL, body, token).enqueue(new Callback<CallResponse<Contact>>() {
@Override
public void onResponse(Call<CallResponse<Contact>> call, Response<CallResponse<Contact>> 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());
}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);
}
}
@Override
public void onFailure(Call<CallResponse<Contact>> call, Throwable t) {
Log.e(TAG, "onFailure: ", t);
createContactInterface.onContactCreateFailed(t, t.getMessage(), 1);
}
});
}
public ArrayList<Contact> getContactList(Context context) {
final ArrayList<Contact> contactList = new ArrayList<>();

View File

@@ -0,0 +1,76 @@
package com.ssb.simplitend.welcome.fragments.contacts.mvvm.models;
import androidx.annotation.NonNull;
public class ContactListResponse{
public int id;
public String patient_xid;
public String contact_xid;
public String is_sos_contact;
public ContactData contact_data;
public ContactListResponse() {
}
@NonNull
@Override
public String toString() {
return "ContactListResponse{" +
"id=" + id +
", patient_xid='" + patient_xid + '\'' +
", contact_xid='" + contact_xid + '\'' +
", is_sos_contact='" + is_sos_contact + '\'' +
", contact_data=" + contact_data +
'}';
}
}
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 +
'}';
}
}

View File

@@ -1,6 +1,8 @@
package com.ssb.simplitend.welcome.fragments.register;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -8,17 +10,31 @@ 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.apputils.AppUtil;
import com.ssb.simplitend.apputils.RetrofitHelper;
import com.ssb.simplitend.databinding.CreatePinFragmentBinding;
import com.ssb.simplitend.welcome.mvvm.WelcomeContracts;
import com.ssb.simplitend.welcome.mvvm.WelcomeViewModel;
import com.ssb.simplitend.welcome.mvvm.models.PatientData;
import com.ssb.simplitend.welcome.mvvm.models.PatientResult;
public class CreatePinFragment extends Fragment {
public class CreatePinFragment extends Fragment implements WelcomeContracts.RegisterPatientContract {
private static final String TAG = "CreatePinFragment";
// view binding
protected CreatePinFragmentBinding binding;
public CreatePinFragment(){
// view model (common for this activity)
private WelcomeViewModel welcomeViewModel;
private ProgressDialog progressDialog;
public CreatePinFragment() {
// required empty const.
}
@@ -27,18 +43,96 @@ public class CreatePinFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = CreatePinFragmentBinding.inflate(inflater, container, false);
welcomeViewModel = new ViewModelProvider(requireActivity()).get(WelcomeViewModel.class);
initViews();
clickEvents();
return binding.getRoot();
}
private void initViews() {
loadPinsSavedState();
progressDialog = new ProgressDialog(requireContext());
}
private void loadPinsSavedState() {
PatientData patientData = welcomeViewModel.getPatientData();
binding.pin.setText(patientData.pin_code);
binding.confirmPin.setText(patientData.c_pin_code);
}
private void clickEvents() {
binding.backBtn.setOnClickListener(v -> Navigation.findNavController(v).popBackStack());
binding.setPin.setOnClickListener(v ->
Navigation.findNavController(v).navigate(R.id.action_createPinFragment_to_thankYouFragment)
{
if (allOkay() && binding.pin.getText() != null && binding.confirmPin.getText() != null) {
AppUtil.closeKeyboard(requireActivity());
PatientData patientData = welcomeViewModel.getPatientData();
patientData.pin_code = binding.pin.getText().toString();
patientData.c_pin_code = binding.confirmPin.getText().toString();
progressDialog.setTitle("Please wait");
progressDialog.setMessage("while we sign you up");
progressDialog.setCancelable(false);
progressDialog.show();
welcomeViewModel.registerPatient(RetrofitHelper.REGISTER_PATIENT, this);
}
}
);
}
private boolean allOkay() {
boolean allOkay = true;
if (binding.pin.getText() == null || binding.pin.getText().toString().length() != 4) {
allOkay = false;
binding.pin.setError("Invalid pin");
} else if (binding.confirmPin.getText() == null ||
!binding.confirmPin.getText().toString().equals(binding.pin.getText().toString())) {
allOkay = false;
binding.confirmPin.setError("Pin doesn't match");
}
return allOkay;
}
@Override
public void onResponse(PatientResult patientResult, String token) {
Log.d(TAG, "onResponse: " + patientResult);
Log.d(TAG, "onResponse: Token " + token);
progressDialog.setMessage("Almost there...");
AppUtil.saveToken(token, requireContext());
progressDialog.dismiss();
Navigation.findNavController(binding.getRoot()).navigate(R.id.action_createPinFragment_to_thankYouFragment);
}
@Override
public void onFailure(Throwable t, @NonNull String message, int error_code) {
Log.d(TAG, "onFailure: " + t);
progressDialog.dismiss();
AppUtil.showAlert(requireContext(),
"Something went wrong",
message, "OK", (dialog, which) -> {
dialog.dismiss();
}, null, null);
}
}

View File

@@ -1,20 +1,53 @@
package com.ssb.simplitend.welcome.fragments.register;
import static android.content.Context.LOCATION_SERVICE;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.Navigation;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMapOptions;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.libraries.places.api.Places;
import com.google.android.libraries.places.api.model.Place;
import com.google.android.libraries.places.widget.Autocomplete;
import com.google.android.libraries.places.widget.model.AutocompleteActivityMode;
import com.skydoves.powerspinner.OnSpinnerItemSelectedListener;
import com.ssb.simplitend.R;
import com.ssb.simplitend.apputils.AppUtil;
import com.ssb.simplitend.databinding.LocationFragmentBinding;
import com.ssb.simplitend.welcome.mvvm.WelcomeViewModel;
import com.ssb.simplitend.welcome.mvvm.models.PatientData;
import org.json.JSONArray;
import org.json.JSONObject;
@@ -24,10 +57,12 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
public class LocationFragment extends Fragment {
public class LocationFragment extends Fragment implements OnMapReadyCallback,
GoogleMap.OnMapClickListener, LocationListener {
private static final String TAG = "LocationFragment";
@@ -35,10 +70,28 @@ public class LocationFragment extends Fragment {
protected LocationFragmentBinding binding;
// country list
ArrayList<String> countryList;
private ArrayList<String> countryList;
// Map for country and their states
HashMap<String, ArrayList<String>> country_N_states_map;
private HashMap<String, ArrayList<String>> country_N_states_map;
// user location selection marker
private Marker marker = null;
// Google map object
private GoogleMap googleMap;
// user selected current location
private LatLng currentLocation;
// Fused location object
private FusedLocationProviderClient fusedLocationProviderClient;
private LocationRequest locationRequest;
private ActivityResultLauncher<Intent> startAutocompleteMapSearch;
// viewmodel
private WelcomeViewModel viewModel;
public LocationFragment(){
// required empty const.
@@ -49,6 +102,10 @@ public class LocationFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = LocationFragmentBinding.inflate(inflater, container, false);
viewModel = new ViewModelProvider(requireActivity()).get(WelcomeViewModel.class);
Log.d(TAG, "onCreateView: " + viewModel.getPatientData());
initViews();
clickEvents();
@@ -56,10 +113,309 @@ public class LocationFragment extends Fragment {
return binding.getRoot();
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.d(TAG, "location updates removed");
fusedLocationProviderClient.removeLocationUpdates(this);
}
@SuppressLint("ClickableViewAccessibility")
private void initViews() {
loadCountriesAndStates();
try {
loadPatientAddressSavedState();
} catch (Exception e) {
Log.e(TAG, "initViews: ", e);
}
// requesting scroll view to stop listening to gestures for mapview
binding.transImg.setOnTouchListener((v, event) -> {
binding.scrollView.requestDisallowInterceptTouchEvent(true);
return false;
});
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(requireContext());
locationRequest = new LocationRequest.Builder(LocationRequest.PRIORITY_HIGH_ACCURACY, 5000)
.build();
registerMapSearchResultLauncher();
getLocationPermission();
// default current location // Mumbai marine drive
currentLocation = new LatLng(19.026452, 72.838845);
// initializing maps
GoogleMapOptions gmo = new GoogleMapOptions();
gmo.mapType(GoogleMap.MAP_TYPE_NORMAL)
.compassEnabled(true)
.useViewLifecycleInFragment(true);
SupportMapFragment mapFragment = SupportMapFragment.newInstance(gmo);
getParentFragmentManager().beginTransaction()
.add(R.id.map_frag_cont, mapFragment)
.commit();
mapFragment.getMapAsync(this);
}
// load data from watcher
private void loadPatientAddressSavedState() throws Exception {
PatientData patientData = viewModel.getPatientData();
if (patientData.country != null){
binding.countrySpinner.selectItemByIndex(countryList.indexOf(patientData.country));
if (patientData.state != null){
binding.stateSpinner.selectItemByIndex(country_N_states_map.get(patientData.country).indexOf(patientData.state));
}
}
if (patientData.lat != null && patientData.lng != null){
double lat = Double.parseDouble(patientData.lat);
double lng = Double.parseDouble(patientData.lng);
currentLocation = new LatLng(lat, lng);
}
if (patientData.address_line1 != null){
binding.street.setText(patientData.address_line1);
}
if (patientData.city != null){
binding.town.setText(patientData.city);
}
if (patientData.post_code != null){
binding.zipCode.setText(patientData.post_code);
}
}
private void registerMapSearchResultLauncher() {
// initializing places
// Initialize the SDK
Places.initialize(requireContext(), getString(R.string.GOOGLE_MAPS_API_KEY));
startAutocompleteMapSearch = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent intent = result.getData();
if (intent != null) {
Place place = Autocomplete.getPlaceFromIntent(intent);
Log.d(TAG, "Place: selected" + place.getLatLng());
if (place.getLatLng() == null) return;
// animating camera to selected location
CameraPosition camPos = new CameraPosition.Builder()
.target(place.getLatLng())
.zoom(15)
.build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(camPos));
// updating current location and adding a land mark
addMarker(place.getLatLng(), place.getName());
}
} else if (result.getResultCode() == Activity.RESULT_CANCELED) {
// The user canceled the operation.
Log.d(TAG, "User canceled autocomplete");
}
});
}
private void clickEvents() {
binding.backBtn.setOnClickListener(v -> Navigation.findNavController(v).popBackStack());
binding.submit.setOnClickListener(v ->
{
if (allOkay()){
PatientData patientData = viewModel.getPatientData();
patientData.address_line1 = binding.street.getText().toString();
patientData.city = binding.town.getText().toString();
patientData.post_code = binding.zipCode.getText().toString();
patientData.country = countryList.get(binding.countrySpinner.getSelectedIndex());
patientData.state = country_N_states_map.get(patientData.country).get(binding.countrySpinner.getSelectedIndex());
patientData.lat = String.valueOf(currentLocation.latitude);
patientData.lng = String.valueOf(currentLocation.longitude);
Navigation.findNavController(v).navigate(R.id.action_locationFragment_to_createPinFragment);
}
}
);
binding.search.setOnClickListener(v -> {
List<Place.Field> fields = Arrays.asList(Place.Field.ID, Place.Field.NAME, Place.Field.LAT_LNG);
Intent intent = new Autocomplete.IntentBuilder(AutocompleteActivityMode.OVERLAY, fields)
.build(requireContext());
startAutocompleteMapSearch.launch(intent);
});
}
private boolean allOkay() {
boolean allOkay = true;
if (binding.street.getText().toString().trim().isEmpty()){
allOkay = false;
binding.street.setError("Required");
}
if (binding.town.getText().toString().trim().isEmpty()){
allOkay = false;
binding.town.setError("Required");
}
if (binding.zipCode.getText().toString().trim().isEmpty()){
allOkay = false;
binding.zipCode.setError("Required");
}
if (binding.countrySpinner.getSelectedIndex() == -1){
allOkay = false;
binding.countrySpinner.setError("Required");
}
if (binding.stateSpinner.getSelectedIndex() == -1){
allOkay = false;
binding.stateSpinner.setError("Required");
}
if (currentLocation == null && allOkay){
allOkay = false;
Toast.makeText(requireContext(), "Please click on map to select a location.", Toast.LENGTH_SHORT).show();
}
return allOkay;
}
private void getLocationPermission() {
// launching request to location permissions
registerForActivityResult(new ActivityResultContracts
.RequestMultiplePermissions(), result -> {
Boolean fineLocationGranted;
if (result.containsKey(Manifest.permission.ACCESS_FINE_LOCATION)){
fineLocationGranted = result.get(Manifest.permission.ACCESS_FINE_LOCATION);
}else{
fineLocationGranted = false;
}
Boolean coarseLocationGranted;
if (result.containsKey(Manifest.permission.ACCESS_COARSE_LOCATION)){
coarseLocationGranted = result.get(Manifest.permission.ACCESS_COARSE_LOCATION);
}else{
coarseLocationGranted = false;
}
if ((fineLocationGranted != null && fineLocationGranted) || (coarseLocationGranted != null && coarseLocationGranted)) {
// one of the location access granted.
Toast.makeText(requireContext(), "Fetching your current location", Toast.LENGTH_SHORT).show();
requestLocations();
}
}
).launch(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION});
}
@Override
public void onLocationChanged(@NonNull Location location) {
Log.d(TAG, "onLocationChanged: " + location);
this.currentLocation = new LatLng(location.getLatitude(), location.getLongitude());
fusedLocationProviderClient.removeLocationUpdates(this);
Log.d(TAG, "onLocationChanged: location updates removed");
CameraPosition default_map_pos = new CameraPosition.Builder()
.target(currentLocation)
.zoom(15)
.build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(default_map_pos));
addMarker(currentLocation, "Current location");
}
@Override
public void onMapReady(@NonNull GoogleMap googleMap) {
this.googleMap = googleMap;
CameraPosition default_map_pos = new CameraPosition.Builder()
.target(currentLocation)
.zoom(15)
.build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(default_map_pos));
googleMap.setOnMapClickListener(this);
if (currentLocation != null){
addMarker(currentLocation, "Selected location");
}
}
@Override
public void onMapClick(@NonNull LatLng latLng) {
addMarker(latLng, "Selected location");
}
private void addMarker(LatLng latLng, String title){
// updating current location
this.currentLocation = latLng;
if (marker != null && marker.isVisible()) marker.remove();
marker = null;
marker = googleMap.addMarker(new MarkerOptions()
.position(latLng).draggable(false)
.title(title));
}
private void requestLocations(){
if (!isLocationProviderEnabled(requireContext())){
AppUtil.showAlert(requireContext(),
getString(R.string.GPS_ENABLE_REQUIRED),
getString(R.string.GPS_ENABLE_MESSAGE),
getString(R.string.SETTINGS),
(dialog, which) -> {
// Settings button click callback
// Sending user to turn location on
Intent intent = new Intent();
intent.setAction(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
},
getString(R.string.NOT_NOW),
(dialog, which) -> dialog.dismiss()
);
}
fusedLocationProviderClient.requestLocationUpdates(locationRequest, this, null);
}
public boolean isLocationProviderEnabled(Context context) {
LocationManager locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
// loads all countries and their states into the spinners
@@ -112,6 +468,8 @@ public class LocationFragment extends Fragment {
binding.countrySpinner.setIsFocusable(true);
binding.countrySpinner.setOnSpinnerItemSelectedListener((OnSpinnerItemSelectedListener<String>) (i, s, i1, t1) -> {
binding.countrySpinner.setError(null);
ArrayList<String> stateList;
@@ -126,6 +484,10 @@ public class LocationFragment extends Fragment {
binding.stateSpinner.clearSelectedItem();
}
});
binding.stateSpinner.setOnSpinnerItemSelectedListener((OnSpinnerItemSelectedListener<String>) (i, s, i1, t1) -> {
binding.stateSpinner.setError(null);
});
}
@@ -155,14 +517,4 @@ public class LocationFragment extends Fragment {
return returnString.toString();
}
private void clickEvents() {
binding.backBtn.setOnClickListener(v -> Navigation.findNavController(v).popBackStack());
binding.submit.setOnClickListener(v ->
Navigation.findNavController(v).navigate(R.id.action_locationFragment_to_createPinFragment)
);
}
}

View File

@@ -2,23 +2,29 @@ package com.ssb.simplitend.welcome.fragments.register;
import android.app.DatePickerDialog;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.util.Patterns;
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.annotation.RequiresApi;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.Navigation;
import com.skydoves.powerspinner.OnSpinnerDismissListener;
import com.ssb.simplitend.R;
import com.ssb.simplitend.apputils.AppUtil;
import com.ssb.simplitend.databinding.RegisterFragmentBinding;
import com.ssb.simplitend.welcome.mvvm.WelcomeViewModel;
import com.ssb.simplitend.welcome.mvvm.models.PatientData;
import org.json.JSONArray;
import org.json.JSONObject;
@@ -36,8 +42,14 @@ public class RegisterFragment extends Fragment {
private static final String TAG = "RegisterFragment";
// view binding
protected RegisterFragmentBinding binding;
// view model
private WelcomeViewModel viewModel;
private ArrayList<String> countryCodeList;
public RegisterFragment() {
// required empty const.
}
@@ -47,6 +59,8 @@ public class RegisterFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = RegisterFragmentBinding.inflate(inflater, container, false);
viewModel = new ViewModelProvider(requireActivity()).get(WelcomeViewModel.class);
initViews();
clickEvents();
@@ -58,27 +72,110 @@ public class RegisterFragment extends Fragment {
loadCountryCodeDropDown();
loadPatientDataSavedState();
}
private void loadPatientDataSavedState() {
// loading data from view model
PatientData patientData = viewModel.getPatientData();
binding.name.setText(patientData.first_name);
binding.dob.setText(patientData.date_of_birth);
if (patientData.phone_number != null){
String[] contact = patientData.phone_number.split(" ");
if (contact.length == 2){
binding.contactNumber.setText(contact[1]);
binding.countryCodes.selectItemByIndex(countryCodeList.indexOf(contact[0]));
}
}
binding.email.setText(patientData.email);
}
private void clickEvents() {
binding.backBtn.setOnClickListener(v -> Navigation.findNavController(v).popBackStack());
binding.nextBtn.setOnClickListener(v ->
Navigation.findNavController(v).navigate(R.id.action_registerFragment_to_locationFragment));
binding.nextBtn.setOnClickListener(v -> {
if (allOkay()){
PatientData patientData = viewModel.getPatientData();
patientData.first_name = patientData.user_name = binding.name.getText().toString();
patientData.phone_number = countryCodeList.get(binding.countryCodes.getSelectedIndex())
+ " " + binding.contactNumber.getText().toString();
patientData.date_of_birth = binding.dob.getText().toString();
patientData.email = binding.email.getText().toString();
Navigation.findNavController(v).navigate(R.id.action_registerFragment_to_locationFragment);
}
});
binding.dob.setOnClickListener(v -> {
binding.dob.setError(null);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
AppUtil.closeKeyboard(requireActivity());
pickDate();
}
});
binding.tncBtn.setOnClickListener(v -> {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://www.google.com"));
startActivity(intent);
});
// static thing for lower android versions
// todo should be removed afterwards
binding.dob.setOnLongClickListener(v -> {
binding.dob.setText("12-12-2001");
return false;
});
}
private boolean allOkay() {
boolean allOkay = true;
if (binding.name.getText().toString().trim().isEmpty()){
binding.name.setError("Required");
allOkay = false;
}
if (binding.dob.getText().toString().trim().isEmpty()){
binding.dob.setError("Required");
allOkay = false;
}
if (binding.contactNumber.getText().toString().trim().isEmpty()){
binding.contactNumber.setError("Required");
allOkay = false;
}else if (!Patterns.PHONE.matcher(binding.contactNumber.getText().toString()).matches()){
binding.contactNumber.setError("Invalid contact");
allOkay = false;
}
if (binding.email.getText().toString().trim().isEmpty()){
binding.email.setError("Required");
allOkay = false;
}else if (!Patterns.EMAIL_ADDRESS.matcher(binding.email.getText().toString()).matches()){
binding.email.setError("Invalid email");
allOkay = false;
}
if (!binding.tncCheck.isChecked() && allOkay){
Toast.makeText(requireContext(), "Please check terms and conditions to continue.", Toast.LENGTH_SHORT).show();
allOkay = false;
}
return allOkay;
}
private void loadCountryCodeDropDown() {
ArrayList<String> countryCodeList = new ArrayList<>();
countryCodeList = new ArrayList<>();
try {

View File

@@ -44,13 +44,9 @@ public class ThankYouFragment extends Fragment {
}
private void clickEvents() {
binding.backBtn.setOnClickListener(v -> Navigation.findNavController(v).popBackStack());
binding.proceed.setOnClickListener(v ->
Navigation.findNavController(v).navigate(R.id.action_thankYouFragment_to_contactListFragment)
);
}
}

View File

@@ -0,0 +1,29 @@
package com.ssb.simplitend.welcome.mvvm;
import com.ssb.simplitend.welcome.fragments.contacts.mvvm.Contact;
import com.ssb.simplitend.welcome.fragments.contacts.mvvm.models.ContactListResponse;
import com.ssb.simplitend.welcome.mvvm.models.CallResponse;
import com.ssb.simplitend.welcome.mvvm.models.PatientResult;
import java.util.List;
import java.util.Map;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.POST;
import retrofit2.http.Url;
public interface APIService {
@POST
Call<CallResponse<PatientResult>> registerPatient(@Url String URL, @Body Map<String, String> body);
@POST
Call<CallResponse<Contact>> createContact(@Url String URL, @Body Map<String, String> body,
@Header("Authorization") String token);
@GET
Call<CallResponse<List<ContactListResponse>>> getContactList(@Url String URL, @Header("Authorization") String token);
}

View File

@@ -0,0 +1,34 @@
package com.ssb.simplitend.welcome.mvvm;
import com.ssb.simplitend.welcome.fragments.contacts.mvvm.Contact;
import com.ssb.simplitend.welcome.fragments.contacts.mvvm.models.ContactListResponse;
import com.ssb.simplitend.welcome.mvvm.models.PatientResult;
import java.util.List;
public interface WelcomeContracts {
interface RegisterPatientContract{
void onResponse(PatientResult patientResult, String token);
void onFailure(Throwable t, String message, int error_code);
}
interface ContactListContracts{
void onResponse(List<ContactListResponse> contactList);
void onFailure(Throwable t, String message, int error_code);
}
interface CreateContactInterface{
void onContactCreated(Contact contact);
void onContactCreateFailed(Throwable t, String message, int error_code);
}
}

View File

@@ -0,0 +1,64 @@
package com.ssb.simplitend.welcome.mvvm;
import java.util.Map;
import static com.ssb.simplitend.apputils.RetrofitHelper.*;
import android.util.Log;
import androidx.annotation.NonNull;
import com.ssb.simplitend.welcome.mvvm.models.CallResponse;
import com.ssb.simplitend.welcome.mvvm.models.PatientResult;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class WelcomeRepository {
private static final String TAG = "WelcomeRepository";
private static WelcomeRepository welcomeRepository;
private WelcomeRepository() {}
public static synchronized WelcomeRepository getWelcomeRepository(){
if (welcomeRepository == null){
welcomeRepository = new WelcomeRepository();
}
return welcomeRepository;
}
public void registerPatient(@NonNull String URL,
@NonNull Map<String, String> body,
@NonNull WelcomeContracts.RegisterPatientContract registerPatient){
APIService welcomeService = getRetrofit().create(APIService.class);
welcomeService.registerPatient(URL, body).enqueue(new Callback<CallResponse<PatientResult>>() {
@Override
public void onResponse(Call<CallResponse<PatientResult>> call, Response<CallResponse<PatientResult>> response) {
if (response.isSuccessful() && response.body() != null && response.body().result != null)
{
registerPatient.onResponse(response.body().result, response.body().token);
}else if (response.body() != null){
Log.e(TAG, "onResponse: " + response);
registerPatient.onFailure(new Exception(response.toString()), response.body().message, response.code());
}else{
Log.e(TAG, "onResponse: no success response and also response body is null");
registerPatient.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<CallResponse<PatientResult>> call, Throwable t) {
Log.e(TAG, "onFailure: ", t);
registerPatient.onFailure(t, t.getMessage(), 1);
}
});
}
}

View File

@@ -0,0 +1,54 @@
package com.ssb.simplitend.welcome.mvvm;
import androidx.annotation.NonNull;
import androidx.lifecycle.ViewModel;
import com.ssb.simplitend.welcome.mvvm.models.PatientData;
import java.util.HashMap;
import java.util.Map;
public class WelcomeViewModel extends ViewModel {
private final WelcomeRepository welcomeRepository;
// Patient data watcher
private PatientData patientData;
public WelcomeViewModel(){
this.welcomeRepository = WelcomeRepository.getWelcomeRepository();
}
public void registerPatient(@NonNull String URL, @NonNull WelcomeContracts.RegisterPatientContract registerPatientContract){
Map<String, String> 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);
welcomeRepository.registerPatient(URL, body, registerPatientContract);
}
public synchronized PatientData getPatientData(){
if (patientData == null){
patientData = new PatientData();
}
return patientData;
}
}

View File

@@ -0,0 +1,13 @@
package com.ssb.simplitend.welcome.mvvm.models;
// base class for response
public class CallResponse<T> {
public String message;
public int error_code, status;
public T result;
public String token;
public CallResponse() {}
}

View File

@@ -0,0 +1,58 @@
package com.ssb.simplitend.welcome.mvvm.models;
public class PatientData {
// fields
public String user_name;
public String first_name;
public String date_of_birth;
public String phone_number;
public String email;
public String password;
public String address_line1;
public String city;
public String state;
public String country;
public String post_code;
public String lat;
public String lng;
public int is_patient;
public String updated_at;
public String created_at;
public int id;
// for payload purpose
public String pin_code, c_pin_code;
public PatientData() {
}
public PatientData(String user_name, String first_name, String date_of_birth, String phone_number) {
this.user_name = user_name;
this.first_name = first_name;
this.date_of_birth = date_of_birth;
this.phone_number = phone_number;
}
@Override
public String toString() {
return "PatientData{" +
"user_name='" + user_name + '\'' +
", first_name='" + first_name + '\'' +
", date_of_birth='" + date_of_birth + '\'' +
", phone_number='" + phone_number + '\'' +
", email='" + email + '\'' +
", password='" + password + '\'' +
", address_line1='" + address_line1 + '\'' +
", city='" + city + '\'' +
", state='" + state + '\'' +
", country='" + country + '\'' +
", post_code='" + post_code + '\'' +
", lat='" + lat + '\'' +
", lng='" + lng + '\'' +
", is_patient=" + is_patient +
", updated_at='" + updated_at + '\'' +
", created_at='" + created_at + '\'' +
", id=" + id +
'}';
}
}

View File

@@ -0,0 +1,19 @@
package com.ssb.simplitend.welcome.mvvm.models;
import com.google.gson.annotations.SerializedName;
public class PatientResult {
@SerializedName("PatientData")
public PatientData patientData;
public int patientId;
public PatientResult(){}
@Override
public String toString() {
return "PatientResult{" +
"patientData=" + patientData +
", patientId=" + patientId +
'}';
}
}

View File

@@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="22.746dp"
android:height="22.746dp"
android:viewportWidth="22.746"
android:viewportHeight="22.746">
<path
android:pathData="M11.373,21.996A10.623,10.623 0,1 1,21.996 11.373,10.623 10.623,0 0,1 11.373,21.996Z"
android:strokeLineJoin="round"
android:strokeWidth="1.5"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:pathData="M16.154,14.029a6.159,6.159 0,0 1,-4.78 2.125A6.159,6.159 0,0 1,6.593 14.029"
android:strokeLineJoin="round"
android:strokeWidth="1.5"
android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:fillColor="#FF000000"
android:pathData="M15.091,8.186a0.531,0.531 0,1 1,0.531 -0.531A0.531,0.531 0,0 1,15.091 8.186Z"
android:strokeLineJoin="round"
android:strokeWidth="1.5"
android:strokeColor="#000"
android:strokeLineCap="round"/>
<path
android:fillColor="#FF000000"
android:pathData="M7.655,8.186a0.531,0.531 0,1 1,0.531 -0.531A0.531,0.531 0,0 1,7.655 8.186Z"
android:strokeLineJoin="round"
android:strokeWidth="1.5"
android:strokeColor="#000"
android:strokeLineCap="round"/>
</vector>

View File

@@ -254,8 +254,8 @@
android:gravity="center">
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_width="@dimen/_80sdp"
android:layout_height="@dimen/_80sdp"
android:contentDescription="@string/calls"
app:srcCompat="@drawable/img_doc_contact"/>
@@ -304,8 +304,8 @@
android:gravity="center">
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_width="@dimen/_80sdp"
android:layout_height="@dimen/_80sdp"
android:contentDescription="@string/chats"
app:srcCompat="@drawable/img_chats"/>
@@ -359,8 +359,8 @@
android:gravity="center">
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_width="@dimen/_80sdp"
android:layout_height="@dimen/_80sdp"
android:contentDescription="@string/apps"
app:srcCompat="@drawable/img_apps"/>
@@ -405,8 +405,8 @@
android:gravity="center">
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_width="@dimen/_80sdp"
android:layout_height="@dimen/_80sdp"
android:contentDescription="@string/direction"
app:srcCompat="@drawable/img_directions"/>

View File

@@ -7,6 +7,7 @@
android:background="@color/white_bg">
<com.google.android.material.card.MaterialCardView
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white_bg">
<ImageView
android:id="@+id/back_btn"
android:layout_width="35sp"
android:layout_height="35sp"
android:contentDescription="@string/back_button"
android:padding="5dp"
android:src="@drawable/arrow_back"
android:layout_margin="15dp"/>
<TextView
android:id="@+id/chat_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Akanksha surve"
android:fontFamily="@font/nunito_medium"
android:textAppearance="@style/TextAppearance.Material3.HeadlineMedium"
android:textColor="@color/black"
android:layout_marginHorizontal="15dp"
android:maxLines="1"
android:ellipsize="end"
android:maxEms="8"
/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.stfalcon.chatkit.messages.MessagesList
android:id="@+id/messageList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/message_et"
app:incomingDefaultBubbleColor="@color/color_accent"
app:incomingTextColor="@color/black"
app:outcomingDefaultBubbleColor="@color/color_primary"
app:outcomingTextColor="@color/white_bg"
app:outcomingTimeTextColor="@color/white"
/>
<EditText
android:id="@+id/message_et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="10dp"
android:layout_toStartOf="@id/send_btn"
android:autofillHints="@null"
android:background="@drawable/edit_text_bg_2"
android:drawableStart="@drawable/ic_smiley_outline"
android:drawablePadding="15dp"
android:fontFamily="@font/nunito_regular"
android:hint="@string/type_a_message"
android:inputType="textMultiLine|textCapSentences|textLongMessage"
android:maxHeight="@dimen/_100sdp"
android:padding="15dp"
android:paddingVertical="15dp"
android:layout_alignParentBottom="true"
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
android:textColor="@color/black"
android:textColorHint="@android:color/darker_gray" />
<com.google.android.material.button.MaterialButton
android:id="@+id/send_btn"
android:layout_width="wrap_content"
android:layout_height="65dp"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginVertical="5dp"
android:layout_marginEnd="15dp"
android:fontFamily="@font/nunito_regular"
android:text="@string/send"
android:textColor="@color/white_bg"
app:backgroundTint="@color/color_primary"
app:cornerRadius="5dp"
/>
</RelativeLayout>
</LinearLayout>

View File

@@ -98,6 +98,8 @@
android:inputType="numberPassword"
android:maxLines="1"
android:maxLength="4"
android:nextFocusDown="@id/confirm_pin"
/>
</com.google.android.material.textfield.TextInputLayout>

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
@@ -42,18 +43,65 @@
android:textColor="@color/black"
/>
<TextView
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="20dp"
android:background="@android:color/darker_gray"
android:text="@string/map_view"
android:fontFamily="@font/nunito_regular"
android:textColor="@color/white_bg"
android:textAlignment="center"
android:gravity="center"
/>
>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/map_frag_cont"
android:layout_width="match_parent"
android:layout_height="@dimen/_300sdp"
/>
<ImageView
android:id="@+id/trans_img"
android:layout_width="match_parent"
android:layout_height="@dimen/_300sdp"
android:background="@android:color/transparent"
/>
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/_10sdp"
android:layout_marginTop="@dimen/_10sdp"
app:cardBackgroundColor="@color/white"
app:cardElevation="5dp"
app:strokeWidth="0.5dp"
app:strokeColor="@color/color_accent"
app:cardCornerRadius="20dp"
>
<TextView
android:id="@+id/search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/search_places"
android:fontFamily="@string/register"
android:textColor="@android:color/darker_gray"
android:textSize="@dimen/_14ssp"
android:layout_marginVertical="10dp"
android:layout_marginHorizontal="15dp"
app:drawableStartCompat="@drawable/ic_search_outline"
android:drawablePadding="15dp"
/>
</com.google.android.material.card.MaterialCardView>
</RelativeLayout>
<TextView
android:layout_width="wrap_content"
@@ -66,6 +114,7 @@
/>
<EditText
android:id="@+id/street"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/edit_text_bg_2"
@@ -90,6 +139,7 @@
/>
<EditText
android:id="@+id/town"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/edit_text_bg_2"
@@ -237,6 +287,7 @@
</LinearLayout>
<EditText
android:id="@+id/zip_code"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/edit_text_bg_2"
@@ -249,8 +300,6 @@
android:textColorHint="@android:color/darker_gray"
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
android:maxLength="6"
android:paddingVertical="5dp"
android:padding="10dp"
@@ -282,4 +331,4 @@
</LinearLayout>
</ScrollView>
</androidx.core.widget.NestedScrollView>

View File

@@ -55,6 +55,7 @@
/>
<EditText
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/edit_text_bg_2"
@@ -184,6 +185,7 @@
android:layout_marginVertical="10dp"/>
<EditText
android:id="@+id/contact_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -222,19 +224,20 @@
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/optional"
android:fontFamily="@font/nunito_medium"
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
android:textColor="@android:color/darker_gray"
android:layout_marginStart="5dp"
/>
<!-- <TextView-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/optional"-->
<!-- android:fontFamily="@font/nunito_medium"-->
<!-- android:textAppearance="@style/TextAppearance.Material3.TitleMedium"-->
<!-- android:textColor="@android:color/darker_gray"-->
<!-- android:layout_marginStart="5dp"-->
<!-- />-->
</LinearLayout>
<EditText
android:id="@+id/email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/edit_text_bg_2"
@@ -257,20 +260,51 @@
android:inputType="textEmailAddress"
/>
<androidx.appcompat.widget.AppCompatCheckBox
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:orientation="horizontal"
android:layout_marginHorizontal="15dp"
android:text="@string/i_accept_terms_and_conditions"
android:textColor="@color/black"
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
android:fontFamily="@font/nunito_regular"
android:checked="false"
android:button="@drawable/remember_me_selector"
android:paddingHorizontal="10dp"
android:background="@android:color/transparent"
/>
android:gravity="center_vertical"
>
<androidx.appcompat.widget.AppCompatCheckBox
android:id="@+id/tncCheck"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:checked="false"
android:button="@drawable/remember_me_selector"
android:paddingHorizontal="10dp"
android:background="@android:color/transparent"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/i_accept"
android:fontFamily="@font/nunito_regular"
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
android:textColor="@color/black"
/>
<TextView
android:id="@+id/tnc_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/terms_n_conditions"
android:fontFamily="@font/nunito_regular"
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
android:textColor="@color/black"
android:padding="5dp"
/>
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/next_btn"

View File

@@ -0,0 +1,43 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp">
<LinearLayout
android:id="@+id/bubble"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toStartOf="@+id/messageUserAvatar_send"
android:layout_marginStart="40dp"
android:orientation="vertical">
<TextView
android:id="@+id/messageText"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/messageUserAvatar_send"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/static_3"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="8dp" />
<TextView
android:id="@+id/messageTime"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@+id/bubble"
android:textColor="@color/black"
android:layout_below="@+id/bubble"
android:layout_marginStart="16dp" />
</RelativeLayout>

View File

@@ -11,24 +11,15 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_centerInParent="true"
>
<ImageView
android:id="@+id/back_btn"
android:layout_width="35sp"
android:layout_height="35sp"
android:layout_margin="15dp"
android:contentDescription="@string/back_button"
android:padding="5dp"
android:layout_gravity="start"
android:src="@drawable/arrow_back" />
<ImageView
android:id="@+id/anim_iv"
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="25dp"
android:layout_marginTop="40dp"
android:layout_marginBottom="15dp"
android:layout_marginHorizontal="15dp"
android:contentDescription="@string/thank_you"/>
@@ -48,8 +39,8 @@
android:text="@string/let_s_add_your_caregiver_contact_information"
android:textColor="@color/black"
android:textAppearance="@style/TextAppearance.Material3.TitleLarge"
android:textAlignment="center"
android:fontFamily="@font/nunito_regular"
android:textAlignment="center"
android:layout_marginBottom="25dp"
android:layout_marginTop="5dp"/>

View File

@@ -15,5 +15,13 @@
<fragment
android:id="@+id/chatListFragment"
android:name="com.ssb.simplitend.careperson_dashboard.chats.ChatListFragment"
android:label="ChatListFragment" />
android:label="ChatListFragment" >
<action
android:id="@+id/action_chatListFragment_to_chatFragment"
app:destination="@id/chatFragment" />
</fragment>
<fragment
android:id="@+id/chatFragment"
android:name="com.ssb.simplitend.careperson_dashboard.chats.ChatFragment"
android:label="ChatFragment" />
</navigation>

View File

@@ -2,7 +2,7 @@
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/welcome_nav_graph"
app:startDestination="@id/profileProgressFragment">
app:startDestination="@id/thankYouFragment">
<fragment
android:id="@+id/welcomeFragment"
@@ -81,7 +81,10 @@
android:label="CreatePinFragment" >
<action
android:id="@+id/action_createPinFragment_to_thankYouFragment"
app:destination="@id/thankYouFragment" />
app:destination="@id/thankYouFragment"
app:popUpTo="@id/splashFragment"
app:popUpToInclusive="true"
/>
</fragment>
<fragment
android:id="@+id/thankYouFragment"

View File

@@ -23,7 +23,7 @@
<string name="login">Login</string>
<string name="welcome_to_simplitend">Welcome to SimpliTend</string>
<string name="sign_in_to_continue">Sign in to continue.</string>
<string name="email_address">Email address</string>
<string name="email_address">Email address*</string>
<string name="enter_your_email">Enter your email.</string>
<string name="enter_pin">Enter pin</string>
<string name="enter_your_pin">Enter your pin</string>
@@ -212,5 +212,18 @@
<string name="direction">Direction</string>
<string name="sos">sos</string>
<string name="search_chats">Search chats</string>
<string name="type_a_message">Type a message</string>
<string name="send">Send</string>
<string name="GPS_ENABLE_REQUIRED">Enable to fetch location</string>
<string name="GPS_ENABLE_MESSAGE">It seems like your Location is turned off.\n\nTap on Settings and turn Location on.</string>
<string name="SETTINGS">Settings</string>
<string name="NOT_NOW">Not now</string>
<string name="GOOGLE_MAPS_API_KEY">AIzaSyDQvd4THJsS62DeDidNzfP3rrnKe7zmM-4</string>
<string name="search_places">Search places</string>
<string name="i_accept">I accept</string>
<string name="terms_n_conditions"><u>terms and conditions</u></string>
</resources>