Showing
28 changed files
with
994 additions
and
21 deletions
| 1 | +package com.sw.laryngoscope.FHIR.adapter; | ||
| 2 | + | ||
| 3 | +import android.view.ViewGroup; | ||
| 4 | + | ||
| 5 | +import androidx.annotation.NonNull; | ||
| 6 | +import androidx.recyclerview.widget.RecyclerView; | ||
| 7 | + | ||
| 8 | +import com.sw.laryngoscope.FHIR.model.PatientModel; | ||
| 9 | + | ||
| 10 | +import java.util.ArrayList; | ||
| 11 | +import java.util.HashMap; | ||
| 12 | + | ||
| 13 | +public abstract class BaseAdapter<H extends BaseViewHolder> extends RecyclerView.Adapter<BaseViewHolder> { | ||
| 14 | + private HashMap<String, PatientModel> patientsHashMap; | ||
| 15 | + private ArrayList<PatientModel> uniquePatients = new ArrayList<>(); | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * Constructor. | ||
| 19 | + */ | ||
| 20 | + BaseAdapter(HashMap<String, PatientModel> patientsHashMap) { | ||
| 21 | + this.patientsHashMap = patientsHashMap; | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * Getter for PatientHashMap | ||
| 26 | + * @return the patientHashMap | ||
| 27 | + */ | ||
| 28 | + HashMap<String, PatientModel> getPatientsHashMap() { | ||
| 29 | + return patientsHashMap; | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * Setter for PatientHashMap | ||
| 34 | + * @param patientsHashMap new PatientHashMap | ||
| 35 | + */ | ||
| 36 | + void setPatientsHashMap(HashMap<String, PatientModel> patientsHashMap) { | ||
| 37 | + this.patientsHashMap = patientsHashMap; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * Getter for uniquePatients | ||
| 43 | + * @return uniquePatients | ||
| 44 | + */ | ||
| 45 | + ArrayList<PatientModel> getUniquePatients() { | ||
| 46 | + return uniquePatients; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * Setter for uniquePatients | ||
| 51 | + * @param uniquePatients new uniquePatients list | ||
| 52 | + */ | ||
| 53 | + void setUniquePatients(ArrayList<PatientModel> uniquePatients) { | ||
| 54 | + this.uniquePatients = uniquePatients; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + /** | ||
| 58 | + * onCreateViewHolder overrides it superclass's ( RecyclerView ) method | ||
| 59 | + * subclass of this class must implement this method. | ||
| 60 | + */ | ||
| 61 | + @NonNull | ||
| 62 | + @Override | ||
| 63 | + public abstract BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType); | ||
| 64 | + | ||
| 65 | + /** | ||
| 66 | + * onBindViewHolder overrides it superclass's ( RecyclerView ) method | ||
| 67 | + * subclass of this class must implement this method. | ||
| 68 | + */ | ||
| 69 | + @Override | ||
| 70 | + public abstract void onBindViewHolder(@NonNull BaseViewHolder holder, int position); | ||
| 71 | + | ||
| 72 | + /** | ||
| 73 | + * onGetItemCount overrides it superclass's ( RecyclerView ) method | ||
| 74 | + * subclass of this class must implement this method. | ||
| 75 | + */ | ||
| 76 | + @Override | ||
| 77 | + public abstract int getItemCount(); | ||
| 78 | +} |
| 1 | +package com.sw.laryngoscope.FHIR.adapter; | ||
| 2 | + | ||
| 3 | +import android.view.View; | ||
| 4 | + | ||
| 5 | +import androidx.annotation.NonNull; | ||
| 6 | +import androidx.recyclerview.widget.RecyclerView; | ||
| 7 | + | ||
| 8 | +public abstract class BaseViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ | ||
| 9 | + /** | ||
| 10 | + * Constructor. | ||
| 11 | + * @param itemView | ||
| 12 | + */ | ||
| 13 | + BaseViewHolder(@NonNull View itemView) { | ||
| 14 | + super(itemView); | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * On click method from View.OnClickListener interface | ||
| 19 | + * Subclass that inherits from this class must implement this method. | ||
| 20 | + */ | ||
| 21 | + @Override | ||
| 22 | + public abstract void onClick(View v); | ||
| 23 | + | ||
| 24 | +} |
| 1 | +package com.sw.laryngoscope.FHIR.adapter; | ||
| 2 | + | ||
| 3 | +import android.view.LayoutInflater; | ||
| 4 | +import android.view.View; | ||
| 5 | +import android.view.ViewGroup; | ||
| 6 | +import android.widget.CheckBox; | ||
| 7 | +import android.widget.TextView; | ||
| 8 | + | ||
| 9 | +import androidx.annotation.NonNull; | ||
| 10 | +import androidx.constraintlayout.widget.ConstraintLayout; | ||
| 11 | + | ||
| 12 | +import com.google.android.material.chip.Chip; | ||
| 13 | +import com.sw.laryngoscope.R; | ||
| 14 | +import com.sw.laryngoscope.FHIR.model.PatientModel; | ||
| 15 | +import com.sw.laryngoscope.FHIR.model.observation.ObservationType; | ||
| 16 | + | ||
| 17 | +import java.util.ArrayList; | ||
| 18 | +import java.util.HashMap; | ||
| 19 | +import java.util.Objects; | ||
| 20 | + | ||
| 21 | +public class SelectPatientsAdapter extends BaseAdapter<SelectPatientsAdapter.SelectPatientViewHolder>{ | ||
| 22 | + // select patients adapter on pcl | ||
| 23 | + private OnPatientClickListener onPatientClickListener; | ||
| 24 | + private ArrayList<PatientModel> selectedPatients; | ||
| 25 | + // A list to remember a patient's state | ||
| 26 | + // ( true when patient is selected , otherwise false) | ||
| 27 | + private ArrayList<Boolean> patientState = new ArrayList<>(); | ||
| 28 | + /** | ||
| 29 | + * The SelectPatient Adapter constructor, this initialises the adapter that | ||
| 30 | + * will be used to update the SelectPatient fragment UI. | ||
| 31 | + * | ||
| 32 | + * @param patientsHashMap list of patients that is under HealthPractitioner | ||
| 33 | + * @param onPatientClickListener the listener that is listening to each patient's card clicks | ||
| 34 | + * @param selectedPatients a list of selected patients | ||
| 35 | + */ | ||
| 36 | + public SelectPatientsAdapter(HashMap<String, PatientModel> patientsHashMap, OnPatientClickListener onPatientClickListener, ArrayList<PatientModel> selectedPatients) { | ||
| 37 | + super(patientsHashMap); | ||
| 38 | + this.selectedPatients = selectedPatients; | ||
| 39 | + this.onPatientClickListener = onPatientClickListener; | ||
| 40 | + | ||
| 41 | + ArrayList<PatientModel> uniquePatients = new ArrayList<>(); | ||
| 42 | + | ||
| 43 | + // loop through the patient hash map to get a list of unique patients | ||
| 44 | + patientsHashMap.forEach((patientID, patientModel) -> { | ||
| 45 | + if (patientModel != null) { | ||
| 46 | + | ||
| 47 | + PatientModel selectedPatient = isSelectedPatient(patientModel); | ||
| 48 | + if (selectedPatient != null) { | ||
| 49 | + uniquePatients.add(selectedPatient); | ||
| 50 | + patientState.add(true); | ||
| 51 | + } | ||
| 52 | + else { | ||
| 53 | + uniquePatients.add(patientModel); | ||
| 54 | + patientState.add(false); | ||
| 55 | + } | ||
| 56 | + } | ||
| 57 | + }); | ||
| 58 | + setUniquePatients(uniquePatients); | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + /** | ||
| 62 | + * This method checks if patient is already in the selected patient list. | ||
| 63 | + * @param patient - the patient model object | ||
| 64 | + * @return true - if patient is already in the selected patient list | ||
| 65 | + * false - if patient is not in the selected patient list | ||
| 66 | + */ | ||
| 67 | + private PatientModel isSelectedPatient(PatientModel patient) { | ||
| 68 | + for (PatientModel p: selectedPatients) { | ||
| 69 | + if(p.getPatientID().equals(patient.getPatientID())) { | ||
| 70 | + return p; | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | + return null; | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + /** | ||
| 77 | + * This method overrides its superclass's onCreateViewHolder method | ||
| 78 | + * It is responsible for creating new card view holders that will be used to hold | ||
| 79 | + * and display patient'name | ||
| 80 | + | ||
| 81 | + * @return a ViewHolder Object | ||
| 82 | + */ | ||
| 83 | + @NonNull | ||
| 84 | + @Override | ||
| 85 | + public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { | ||
| 86 | + View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.select_patients_cardview, parent, false); | ||
| 87 | + return new SelectPatientsAdapter.SelectPatientViewHolder(v, onPatientClickListener); | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + /** | ||
| 91 | + * This method overrides its superclass's onBindViewHolder method | ||
| 92 | + * This method is used to update the contents of the SelectPatientViewHolder to reflect the patient | ||
| 93 | + * at the given position. | ||
| 94 | + * | ||
| 95 | + * This method also checks if patient is a selected patient and do the following: | ||
| 96 | + * 1. if true -> highlight the patient's card view in green | ||
| 97 | + * 2. else -> don't highlight the patient's card view | ||
| 98 | + * | ||
| 99 | + * @param baseHolder the reference to the holder that will be used to display the patient's name | ||
| 100 | + * @param position the position of the adapter | ||
| 101 | + */ | ||
| 102 | + @Override | ||
| 103 | + public void onBindViewHolder(@NonNull BaseViewHolder baseHolder, int position) { | ||
| 104 | + SelectPatientViewHolder holder = (SelectPatientViewHolder) baseHolder; | ||
| 105 | + holder.checkBox.setChecked(patientState.get(position)); | ||
| 106 | + holder.background.setBackgroundResource(R.drawable.cardv_nonselected_bg); | ||
| 107 | + holder.patientName.setText(getUniquePatients().get(position).getName()); | ||
| 108 | + PatientModel patient = getUniquePatients().get(position); | ||
| 109 | + if (isSelectedPatient(patient) != null){ | ||
| 110 | + holder.checkBox.setChecked(true); | ||
| 111 | + holder.background.setBackgroundResource(R.drawable.cardv_selected_bg); | ||
| 112 | + patientState.set(position,true); | ||
| 113 | + onPatientClickListener.onPatientClick(holder.checkBox.isChecked(), getUniquePatients().get(position)); | ||
| 114 | + // set chip to be checked if selected for monitoring observation(s) previously | ||
| 115 | + for (ObservationType type: ObservationType.values()) { | ||
| 116 | + switch (type) { | ||
| 117 | + case CHOLESTEROL: | ||
| 118 | + if (Objects.requireNonNull(isSelectedPatient(patient)).isObservationMonitored(type)) { | ||
| 119 | + holder.cholesterolChip.setChecked(true); | ||
| 120 | + } | ||
| 121 | + else { | ||
| 122 | + holder.cholesterolChip.setChecked(false); | ||
| 123 | + } | ||
| 124 | + case BLOOD_PRESSURE: | ||
| 125 | + if (Objects.requireNonNull(isSelectedPatient(patient)).isObservationMonitored(type)) { | ||
| 126 | + holder.bloodPressureChip.setChecked(true); | ||
| 127 | + } | ||
| 128 | + else { | ||
| 129 | + holder.bloodPressureChip.setChecked(false); | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | + } | ||
| 133 | + } | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + /** | ||
| 137 | + * This method overrides its superclass's method, | ||
| 138 | + * It gets the total number of patients that is under HeathPractitioner | ||
| 139 | + * @return total number of patients | ||
| 140 | + */ | ||
| 141 | + @Override | ||
| 142 | + public int getItemCount() { | ||
| 143 | + return getUniquePatients().size(); | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + /** | ||
| 147 | + * The SelectPatientViewHolder class are objects that holds the reference to the individual | ||
| 148 | + * card views that is reused to display different patient's data in the recycler view. | ||
| 149 | + * | ||
| 150 | + * This class implements View.OnClickListener interface. | ||
| 151 | + */ | ||
| 152 | + public class SelectPatientViewHolder extends BaseViewHolder { | ||
| 153 | + private TextView patientName; | ||
| 154 | + private CheckBox checkBox; //hidden checkbox | ||
| 155 | + private SelectPatientsAdapter.OnPatientClickListener onPatientClickListener; | ||
| 156 | + private ConstraintLayout background; | ||
| 157 | + private Chip cholesterolChip; | ||
| 158 | + private Chip bloodPressureChip; | ||
| 159 | + | ||
| 160 | + /** | ||
| 161 | + * The SelectPatientViewHolder constructor | ||
| 162 | + * initialise SelectPatientViewHolder object that will be used to hold patient's data | ||
| 163 | + * @param onPatientClickListener the listener that is listening to patient's card clicks | ||
| 164 | + */ | ||
| 165 | + SelectPatientViewHolder(@NonNull View itemView, OnPatientClickListener onPatientClickListener) { | ||
| 166 | + super(itemView); | ||
| 167 | + patientName = itemView.findViewById(R.id.all_patient_txt_name); | ||
| 168 | + checkBox = itemView.findViewById(R.id.checkBox); | ||
| 169 | + background = itemView.findViewById(R.id.card_backgroud); | ||
| 170 | + cholesterolChip = itemView.findViewById(R.id.cholesterol_chip); | ||
| 171 | + bloodPressureChip = itemView.findViewById(R.id.blood_pressure_chip); | ||
| 172 | + this.onPatientClickListener = onPatientClickListener; | ||
| 173 | + itemView.setOnClickListener(this); | ||
| 174 | + cholesterolChip.setOnClickListener(this); | ||
| 175 | + bloodPressureChip.setOnClickListener(this); | ||
| 176 | + } | ||
| 177 | + | ||
| 178 | + private void observationStatus(Chip chip, int position, ObservationType observationType) { | ||
| 179 | + if (chip.isChecked()) { | ||
| 180 | + getUniquePatients().get(position).monitorObservation(observationType, true); | ||
| 181 | + background.setBackgroundResource(R.drawable.cardv_selected_bg); | ||
| 182 | + checkBox.setChecked(true); | ||
| 183 | + patientState.set(position,true); | ||
| 184 | + } | ||
| 185 | + else { | ||
| 186 | + if (!cholesterolChip.isChecked() && !bloodPressureChip.isChecked()) { | ||
| 187 | + patientState.set(position,false); | ||
| 188 | + background.setBackgroundResource(R.drawable.cardv_nonselected_bg); | ||
| 189 | + checkBox.setChecked(false); | ||
| 190 | + } | ||
| 191 | + getUniquePatients().get(position).monitorObservation(observationType, false); | ||
| 192 | + } | ||
| 193 | + } | ||
| 194 | + | ||
| 195 | + /** | ||
| 196 | + * This method is called when user clicks on a patient's card-view. | ||
| 197 | + * It notifies its onClickListener (SelectPatientFragment) to add the patient into the | ||
| 198 | + * selected patient list/ remove the patient form the selected patient list | ||
| 199 | + */ | ||
| 200 | + @Override | ||
| 201 | + public void onClick(View v) { | ||
| 202 | + switch (v.getId()) { | ||
| 203 | + case R.id.cholesterol_chip: | ||
| 204 | + observationStatus(cholesterolChip, getAdapterPosition(), ObservationType.CHOLESTEROL); | ||
| 205 | + break; | ||
| 206 | + case R.id.blood_pressure_chip: | ||
| 207 | + observationStatus(bloodPressureChip, getAdapterPosition(), ObservationType.BLOOD_PRESSURE); | ||
| 208 | + break; | ||
| 209 | + } | ||
| 210 | + onPatientClickListener.onPatientClick(checkBox.isChecked(), getUniquePatients().get(getAdapterPosition())); | ||
| 211 | + } | ||
| 212 | + } | ||
| 213 | + | ||
| 214 | + /** | ||
| 215 | + * Class the uses this interface must implement their own onPatientClick method. | ||
| 216 | + * onPatientClick is handle the events that should happen when a patient's card-view is clicked. | ||
| 217 | + */ | ||
| 218 | + public interface OnPatientClickListener { | ||
| 219 | + void onPatientClick(boolean checked, PatientModel patient); | ||
| 220 | + } | ||
| 221 | + | ||
| 222 | +} |
| 1 | +package com.sw.laryngoscope.FHIR.fragment; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import android.content.Context; | ||
| 5 | +import android.os.Bundle; | ||
| 6 | +import android.view.LayoutInflater; | ||
| 7 | +import android.view.View; | ||
| 8 | +import android.view.ViewGroup; | ||
| 9 | +import android.widget.Toast; | ||
| 10 | + | ||
| 11 | +import androidx.annotation.NonNull; | ||
| 12 | +import androidx.annotation.Nullable; | ||
| 13 | +import androidx.appcompat.widget.Toolbar; | ||
| 14 | +import androidx.fragment.app.Fragment; | ||
| 15 | +import androidx.lifecycle.Observer; | ||
| 16 | +import androidx.lifecycle.ViewModelProvider; | ||
| 17 | +import androidx.recyclerview.widget.LinearLayoutManager; | ||
| 18 | + | ||
| 19 | +import com.sw.laryngoscope.R; | ||
| 20 | +import com.sw.laryngoscope.FHIR.adapter.SelectPatientsAdapter; | ||
| 21 | +import com.sw.laryngoscope.databinding.FgPatientFragmentBinding; | ||
| 22 | +import com.sw.laryngoscope.FHIR.model.PatientModel; | ||
| 23 | +import com.sw.laryngoscope.FHIR.viewModel.SharedViewModel; | ||
| 24 | + | ||
| 25 | +import java.util.ArrayList; | ||
| 26 | +import java.util.HashMap; | ||
| 27 | + | ||
| 28 | +public class SelectPatientsFragment extends Fragment implements SelectPatientsAdapter.OnPatientClickListener{ | ||
| 29 | + private String practitionerID; | ||
| 30 | + private SelectPatientsFragment thisFrag; // a reference to this fragment | ||
| 31 | +// private Toolbar toolbar; | ||
| 32 | + private SharedViewModel sharedViewModel; | ||
| 33 | +// private RecyclerView recyclerView; | ||
| 34 | + private ArrayList<PatientModel> selectedPatients = new ArrayList<>(); | ||
| 35 | +// private TextView title; | ||
| 36 | +// private TextView loadingTextView; | ||
| 37 | +// private ImageButton backButton; | ||
| 38 | +// private ProgressBar loadingSpinner; | ||
| 39 | + | ||
| 40 | + private FgPatientFragmentBinding binding; | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * Constructor | ||
| 44 | + * @param practitionerID the Health Practitioner's ID | ||
| 45 | + */ | ||
| 46 | + public SelectPatientsFragment(String practitionerID) { | ||
| 47 | + this.practitionerID = practitionerID; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + @Override | ||
| 51 | + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, | ||
| 52 | + @Nullable Bundle savedInstanceState) { | ||
| 53 | + | ||
| 54 | + binding = FgPatientFragmentBinding.inflate(inflater, container, false); | ||
| 55 | + | ||
| 56 | + return binding.getRoot(); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + public void onViewCreatred(@NonNull View view,@Nullable Bundle savedInstanceState){ | ||
| 60 | + | ||
| 61 | + sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); | ||
| 62 | + | ||
| 63 | + // find all the graphical components | ||
| 64 | +// recyclerView = root.findViewById(R.id.select_patients_recycler_view); | ||
| 65 | +// backButton = root.findViewById(R.id.btn_back); | ||
| 66 | +// toolbar = root.findViewById(R.id.select_patients_toolbar); | ||
| 67 | +// title = toolbar.findViewById(R.id.toolbar_title); | ||
| 68 | +// loadingTextView = root.findViewById(R.id.select_patients_txt_loading); | ||
| 69 | +// loadingSpinner = root.findViewById(R.id.select_patients_progressBar); | ||
| 70 | + | ||
| 71 | + binding.selectPatientsTxtLoading.setVisibility(View.VISIBLE); | ||
| 72 | + binding.selectPatientsProgressBar.setVisibility(View.VISIBLE); | ||
| 73 | + | ||
| 74 | + sharedViewModel.setPractitionerID(practitionerID); | ||
| 75 | + setUpToolBar(); | ||
| 76 | + | ||
| 77 | + //update UI when there's new patient under Health Practitioner | ||
| 78 | + sharedViewModel.getAllPatients().observe(getViewLifecycleOwner(),patientUpdatedObserver); | ||
| 79 | + | ||
| 80 | + thisFrag = this; | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + /** | ||
| 84 | + * This observer observes for changes in patient list | ||
| 85 | + * ( The list that contains all patients under Health Practitioner ) | ||
| 86 | + * It displays a loading screen when the app is still fetching data from the server, | ||
| 87 | + * It immediately updates the UI to display the patients when the system completes | ||
| 88 | + * the data fetching process. | ||
| 89 | + */ | ||
| 90 | + private Observer<HashMap<String,PatientModel>> patientUpdatedObserver = new Observer<HashMap<String,PatientModel >>() { | ||
| 91 | + @Override | ||
| 92 | + public void onChanged( HashMap < String, PatientModel > patientHashMap) { | ||
| 93 | + if (patientHashMap.size() == 0) { | ||
| 94 | + binding.selectPatientsTxtLoading.setText(R.string.zero_patients_message); | ||
| 95 | + } | ||
| 96 | + else{ | ||
| 97 | + binding.selectPatientsProgressBar.setVisibility(View.GONE); | ||
| 98 | + binding.selectPatientsTxtLoading.setVisibility(View.GONE); | ||
| 99 | + binding.selectPatientsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); | ||
| 100 | + binding.selectPatientsRecyclerView.setAdapter( new SelectPatientsAdapter(patientHashMap,thisFrag, selectedPatients)); | ||
| 101 | + } | ||
| 102 | + } | ||
| 103 | + }; | ||
| 104 | + | ||
| 105 | + private void setUpToolBar() { | ||
| 106 | + binding.selectPatientsToolbar.toolbarTitle.setText(R.string.title_patient_selection); | ||
| 107 | + binding.selectPatientsToolbar.getRoot().inflateMenu(R.menu.select_patients_menu); | ||
| 108 | + Toolbar.OnMenuItemClickListener menuItemClickListener = item -> { | ||
| 109 | + if (selectedPatients.size() > 0) { | ||
| 110 | + // save list into view model | ||
| 111 | + sharedViewModel.setSelectedPatients(selectedPatients); | ||
| 112 | +// MainActivity main = (MainActivity) getActivity(); | ||
| 113 | +// Objects.requireNonNull(main).findFragment(MainActivity.home_fragment); | ||
| 114 | + } else { | ||
| 115 | + String message = "Please select AT LEAST 1 patient"; | ||
| 116 | + Context context = getContext(); | ||
| 117 | + Toast toast = Toast.makeText(context, message, Toast.LENGTH_LONG); | ||
| 118 | + toast.show(); | ||
| 119 | + } | ||
| 120 | + return true; | ||
| 121 | + }; | ||
| 122 | + binding.selectPatientsToolbar.getRoot().setOnMenuItemClickListener(menuItemClickListener); | ||
| 123 | + | ||
| 124 | + binding.selectPatientsToolbar.btnBack.setOnClickListener(v -> { | ||
| 125 | +// MainActivity main = (MainActivity) getActivity(); | ||
| 126 | +// Objects.requireNonNull(main).findFragment(MainActivity.login_fragment); | ||
| 127 | + }); | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + public void onPatientClick(boolean checked, PatientModel patient) { | ||
| 131 | + PatientModel patientWithSameID = null; | ||
| 132 | + boolean found = false; | ||
| 133 | + for (PatientModel p : selectedPatients){ | ||
| 134 | + if(p.getPatientID().equals(patient.getPatientID())){ | ||
| 135 | + found = true; | ||
| 136 | + patientWithSameID = p; | ||
| 137 | + break; | ||
| 138 | + } | ||
| 139 | + } | ||
| 140 | + if (checked) { | ||
| 141 | + if (!found) { | ||
| 142 | + selectedPatients.add(patient); | ||
| 143 | + } | ||
| 144 | + } else if (!checked) { | ||
| 145 | + if(found){ | ||
| 146 | + selectedPatients.remove(patientWithSameID); | ||
| 147 | + }else{ | ||
| 148 | + selectedPatients.remove(patient); | ||
| 149 | + } | ||
| 150 | + } | ||
| 151 | + updateToolbar(); | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + /** | ||
| 155 | + * This method updates the tool bar to display the total number of patients that is currently | ||
| 156 | + * being selected | ||
| 157 | + */ | ||
| 158 | + private void updateToolbar() { | ||
| 159 | + String text = selectedPatients.size() + " Patients Selected"; | ||
| 160 | + // Log.d("Select_Patient_Fragment","current sellected patient : " + selected_patients.toString()); | ||
| 161 | + binding.selectPatientsToolbar.toolbarTitle.setText(text); | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | +} |
| 1 | -package com.sw.laryngoscope.model; | 1 | +package com.sw.laryngoscope.FHIR.model; |
| 2 | 2 | ||
| 3 | import android.text.format.DateFormat; | 3 | import android.text.format.DateFormat; |
| 4 | 4 | ||
| 5 | -import com.sw.laryngoscope.model.observation.BloodPressureObservationModel; | 5 | +import com.sw.laryngoscope.FHIR.model.observation.BloodPressureObservationModel; |
| 6 | -import com.sw.laryngoscope.model.observation.ObservationModel; | 6 | +import com.sw.laryngoscope.FHIR.model.observation.ObservationModel; |
| 7 | -import com.sw.laryngoscope.model.observation.ObservationType; | 7 | +import com.sw.laryngoscope.FHIR.model.observation.ObservationType; |
| 8 | 8 | ||
| 9 | import org.hl7.fhir.r4.model.Enumerations; | 9 | import org.hl7.fhir.r4.model.Enumerations; |
| 10 | 10 | ... | ... |
| 1 | -package com.sw.laryngoscope.service.repository; | 1 | +package com.sw.laryngoscope.FHIR.service.repository; |
| 2 | 2 | ||
| 3 | -import com.sw.laryngoscope.model.observation.BloodPressureObservationModel; | 3 | +import com.sw.laryngoscope.FHIR.model.observation.BloodPressureObservationModel; |
| 4 | -import com.sw.laryngoscope.model.observation.CholesterolObservationModel; | 4 | +import com.sw.laryngoscope.FHIR.model.observation.CholesterolObservationModel; |
| 5 | -import com.sw.laryngoscope.model.observation.ObservationModel; | 5 | +import com.sw.laryngoscope.FHIR.model.observation.ObservationModel; |
| 6 | -import com.sw.laryngoscope.model.observation.ObservationType; | 6 | +import com.sw.laryngoscope.FHIR.model.observation.ObservationType; |
| 7 | -import com.sw.laryngoscope.service.FhirService; | 7 | +import com.sw.laryngoscope.FHIR.service.FhirService; |
| 8 | 8 | ||
| 9 | import org.hl7.fhir.r4.model.Bundle; | 9 | import org.hl7.fhir.r4.model.Bundle; |
| 10 | import org.hl7.fhir.r4.model.Observation; | 10 | import org.hl7.fhir.r4.model.Observation; | ... | ... |
| 1 | -package com.sw.laryngoscope.service.repository; | 1 | +package com.sw.laryngoscope.FHIR.service.repository; |
| 2 | 2 | ||
| 3 | -import com.sw.laryngoscope.model.PatientAddressModel; | 3 | +import com.sw.laryngoscope.FHIR.model.PatientAddressModel; |
| 4 | -import com.sw.laryngoscope.model.PatientModel; | 4 | +import com.sw.laryngoscope.FHIR.model.PatientModel; |
| 5 | -import com.sw.laryngoscope.service.FhirService; | 5 | +import com.sw.laryngoscope.FHIR.service.FhirService; |
| 6 | 6 | ||
| 7 | import org.hl7.fhir.r4.model.Bundle; | 7 | import org.hl7.fhir.r4.model.Bundle; |
| 8 | import org.hl7.fhir.r4.model.Encounter; | 8 | import org.hl7.fhir.r4.model.Encounter; | ... | ... |
| 1 | +package com.sw.laryngoscope.FHIR.viewModel; | ||
| 2 | + | ||
| 3 | +import android.util.Log; | ||
| 4 | + | ||
| 5 | +import android.os.Handler; | ||
| 6 | +import android.os.HandlerThread; | ||
| 7 | + | ||
| 8 | + | ||
| 9 | +import androidx.lifecycle.MutableLiveData; | ||
| 10 | +import androidx.lifecycle.ViewModel; | ||
| 11 | +import androidx.lifecycle.LiveData; | ||
| 12 | + | ||
| 13 | +import com.sw.laryngoscope.FHIR.model.PatientModel; | ||
| 14 | +import com.sw.laryngoscope.FHIR.model.observation.ObservationModel; | ||
| 15 | +import com.sw.laryngoscope.FHIR.model.observation.ObservationType; | ||
| 16 | +import com.sw.laryngoscope.FHIR.service.repository.ObservationRepositoryFactory; | ||
| 17 | +import com.sw.laryngoscope.FHIR.service.repository.PatientRepository; | ||
| 18 | + | ||
| 19 | +import java.util.ArrayList; | ||
| 20 | +import java.util.HashMap; | ||
| 21 | +import java.util.Objects; | ||
| 22 | + | ||
| 23 | +public class SharedViewModel extends ViewModel implements Poll { | ||
| 24 | + // for polling | ||
| 25 | + private MutableLiveData<HashMap<String, PatientModel>> patientObservations = new MutableLiveData<>(); | ||
| 26 | + // to get all the patients under practitioner | ||
| 27 | + private MutableLiveData<HashMap<String, PatientModel>> allPatients = new MutableLiveData<>(); | ||
| 28 | + private String practitionerID = ""; | ||
| 29 | + private PatientRepository patientRepository; | ||
| 30 | + private ObservationRepositoryFactory observationRepositoryFactory; | ||
| 31 | + private MutableLiveData<String> selectedFrequency = new MutableLiveData<>() ; | ||
| 32 | + private MutableLiveData<ArrayList<PatientModel>> selectedPatients = new MutableLiveData<>(); | ||
| 33 | + | ||
| 34 | + private void initShareViewModel() { | ||
| 35 | + patientRepository = new PatientRepository(practitionerID); | ||
| 36 | + observationRepositoryFactory = new ObservationRepositoryFactory(); | ||
| 37 | + fetchAllPatients(); | ||
| 38 | + setSelectedPatients(new ArrayList<>()); | ||
| 39 | + selectedFrequency.setValue("10"); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + public void setPractitionerID(String practitionerID) { | ||
| 43 | + this.practitionerID = practitionerID; | ||
| 44 | + initShareViewModel(); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + public LiveData<String> getSelectedFrequency() { | ||
| 48 | + return selectedFrequency; | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + public void updateCurrentSelected(String currentSelected) { | ||
| 52 | + this.selectedFrequency.setValue(currentSelected); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + public LiveData<HashMap<String, PatientModel>> getAllPatientObservations() { | ||
| 56 | + return patientObservations; | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + public void setSelectedPatients(ArrayList<PatientModel> selectedPatientsArray) { | ||
| 60 | + selectedPatients.setValue(selectedPatientsArray); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + public LiveData<HashMap<String, PatientModel>> getAllPatients() { | ||
| 64 | + return allPatients; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + private ObservationModel getObservation(String id, ObservationType observationType) { | ||
| 68 | + return observationRepositoryFactory.getObservationModel(id, observationType); | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + private void fetchAllPatients() { | ||
| 72 | + // run asynchronous tasks on background thread to prevent network on main exception | ||
| 73 | + HandlerThread backgroundThread = new HandlerThread("Background Thread"); | ||
| 74 | + backgroundThread.start(); | ||
| 75 | + Handler timer = new Handler(backgroundThread.getLooper()); | ||
| 76 | + | ||
| 77 | + timer.post(() -> { | ||
| 78 | + HashMap < String, PatientModel > patientHashMap = new HashMap<>(); | ||
| 79 | + // loop through all patients | ||
| 80 | + for (PatientModel patient : patientRepository.getAllPatients()) { | ||
| 81 | + try { | ||
| 82 | + // only show patients with cholesterol and bp values | ||
| 83 | + for (ObservationType type: ObservationType.values()) { | ||
| 84 | + patient.setObservation(type, getObservation(patient.getPatientID(), type)); | ||
| 85 | + patientHashMap.put(patient.getPatientID(), patient); | ||
| 86 | + } | ||
| 87 | + patient.addLatestBPReadings(observationRepositoryFactory.getLatestBloodPressureReadings(patient.getPatientID(),5)); | ||
| 88 | + | ||
| 89 | + } | ||
| 90 | + // patient does not have the observation type | ||
| 91 | + catch (Exception e) { | ||
| 92 | + Log.e("Patient ", "No observation type"); | ||
| 93 | + } | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + // update LiveData and notify observers - used by select patient | ||
| 97 | + allPatients.postValue(patientHashMap); | ||
| 98 | + }); | ||
| 99 | + | ||
| 100 | + polling(); | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + public void polling() { | ||
| 104 | + | ||
| 105 | + // run asynchronous tasks on background thread to prevent network on main exception | ||
| 106 | + HandlerThread backgroundThread = new HandlerThread("Background Thread"); | ||
| 107 | + backgroundThread.start(); | ||
| 108 | + Handler timer = new Handler(backgroundThread.getLooper()); | ||
| 109 | + | ||
| 110 | + timer.post(new Runnable() { | ||
| 111 | + @Override | ||
| 112 | + public void run() { | ||
| 113 | + HashMap<String, PatientModel> poHashMap = new HashMap<>(); | ||
| 114 | + | ||
| 115 | + // loop through all patients. update observations if observation is selected to be monitored | ||
| 116 | + for (PatientModel patientModel: Objects.requireNonNull(selectedPatients.getValue())) { | ||
| 117 | + for (ObservationType type: ObservationType.values()) { | ||
| 118 | + if (patientModel.isObservationMonitored(type)) { | ||
| 119 | + patientModel.setObservation(type, getObservation(patientModel.getPatientID(), type)); | ||
| 120 | + poHashMap.put(patientModel.getPatientID(), patientModel); | ||
| 121 | + if (type == ObservationType.BLOOD_PRESSURE) { | ||
| 122 | + patientModel.addLatestBPReadings(observationRepositoryFactory.getLatestBloodPressureReadings(patientModel.getPatientID(),5)); | ||
| 123 | + } | ||
| 124 | + } | ||
| 125 | + } | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + // update LiveData and notify observers | ||
| 129 | + patientObservations.postValue(poHashMap); | ||
| 130 | + timer.postDelayed(this, Integer.parseInt(Objects.requireNonNull(getSelectedFrequency().getValue()))*1000); | ||
| 131 | + }}); | ||
| 132 | + } | ||
| 133 | +} |
app/src/main/res/drawable/cardv_grey_bg.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<shape xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | + android:shape="rectangle"> | ||
| 4 | + <solid android:color="@color/unselected" /> | ||
| 5 | + <corners android:radius="50dp" /> | ||
| 6 | +</shape> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<shape xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | + android:shape="rectangle"> | ||
| 4 | + <solid android:color="@color/color_accent" /> | ||
| 5 | + <corners android:radius="10dp" /> | ||
| 6 | +</shape> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +<vector android:height="24dp" android:tint="#FFFFFF" | ||
| 2 | + android:viewportHeight="24.0" android:viewportWidth="24.0" | ||
| 3 | + android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 4 | + <path android:fillColor="#FF000000" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/> | ||
| 5 | +</vector> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | + xmlns:tools="http://schemas.android.com/tools" | ||
| 4 | + android:layout_width="match_parent" | ||
| 5 | + android:layout_height="wrap_content" | ||
| 6 | + xmlns:card_view="http://schemas.android.com/apk/res-auto" | ||
| 7 | + android:id="@+id/card_layout" | ||
| 8 | + android:foreground="?selectableItemBackground" | ||
| 9 | + card_view:cardBackgroundColor="@color/color_accent" | ||
| 10 | + card_view:cardCornerRadius="12dp" | ||
| 11 | + card_view:cardElevation="3dp" | ||
| 12 | + android:layout_margin="5dp" | ||
| 13 | + > | ||
| 14 | + | ||
| 15 | + <androidx.constraintlayout.widget.ConstraintLayout | ||
| 16 | + android:id="@+id/card_backgroud" | ||
| 17 | + android:layout_width="match_parent" | ||
| 18 | + android:layout_height="94dp"> | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + <LinearLayout | ||
| 22 | + android:id="@+id/linear_layout" | ||
| 23 | + android:layout_width="wrap_content" | ||
| 24 | + android:layout_height="wrap_content" | ||
| 25 | + card_view:layout_constraintBottom_toBottomOf="parent" | ||
| 26 | + card_view:layout_constraintEnd_toStartOf="@id/guideline2" | ||
| 27 | + card_view:layout_constraintHorizontal_bias="0" | ||
| 28 | + card_view:layout_constraintStart_toStartOf="parent" | ||
| 29 | + card_view:layout_constraintTop_toTopOf="parent" | ||
| 30 | + card_view:layout_constraintVertical_bias="0.5"> | ||
| 31 | + | ||
| 32 | + <CheckBox | ||
| 33 | + android:id="@+id/checkBox" | ||
| 34 | + android:layout_width="wrap_content" | ||
| 35 | + android:layout_height="wrap_content" | ||
| 36 | + android:theme="@style/checkBoxStyle" | ||
| 37 | + android:visibility="gone" /> | ||
| 38 | + | ||
| 39 | + </LinearLayout> | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + <TextView | ||
| 43 | + android:id="@+id/all_patient_txt_name" | ||
| 44 | + android:layout_width="0dp" | ||
| 45 | + android:layout_height="wrap_content" | ||
| 46 | + android:text="@string/patient_name" | ||
| 47 | + android:textSize="25sp" | ||
| 48 | + card_view:layout_constraintBottom_toBottomOf="@id/linear_layout" | ||
| 49 | + card_view:layout_constraintEnd_toStartOf="@id/guideline2" | ||
| 50 | + card_view:layout_constraintHorizontal_bias="0.0" | ||
| 51 | + card_view:layout_constraintStart_toEndOf="@id/guideline" | ||
| 52 | + card_view:layout_constraintTop_toTopOf="parent" | ||
| 53 | + card_view:layout_constraintVertical_bias="0.285" /> | ||
| 54 | + | ||
| 55 | + <androidx.constraintlayout.widget.Guideline | ||
| 56 | + android:id="@+id/guideline" | ||
| 57 | + android:layout_width="wrap_content" | ||
| 58 | + android:layout_height="wrap_content" | ||
| 59 | + android:orientation="vertical" | ||
| 60 | + card_view:layout_constraintGuide_percent="0.04" /> | ||
| 61 | + | ||
| 62 | + <androidx.constraintlayout.widget.Guideline | ||
| 63 | + android:id="@+id/guideline2" | ||
| 64 | + android:layout_width="wrap_content" | ||
| 65 | + android:layout_height="wrap_content" | ||
| 66 | + android:orientation="vertical" | ||
| 67 | + card_view:layout_constraintGuide_percent="0.96" /> | ||
| 68 | + | ||
| 69 | + <com.google.android.material.chip.Chip | ||
| 70 | + android:id="@+id/cholesterol_chip" | ||
| 71 | + android:layout_width="wrap_content" | ||
| 72 | + android:layout_height="wrap_content" | ||
| 73 | + android:layout_marginStart="45dp" | ||
| 74 | + android:layout_marginTop="8dp" | ||
| 75 | + android:layout_marginEnd="267dp" | ||
| 76 | + android:checkable="true" | ||
| 77 | + android:text="@string/cholesterol" | ||
| 78 | + card_view:chipIcon="@drawable/cardv_grey_bg" | ||
| 79 | + card_view:layout_constraintBottom_toBottomOf="parent" | ||
| 80 | + card_view:layout_constraintEnd_toEndOf="parent" | ||
| 81 | + card_view:layout_constraintStart_toStartOf="parent" | ||
| 82 | + card_view:layout_constraintTop_toBottomOf="@+id/all_patient_txt_name" /> | ||
| 83 | + | ||
| 84 | + <com.google.android.material.chip.Chip | ||
| 85 | + android:id="@+id/blood_pressure_chip" | ||
| 86 | + android:layout_width="wrap_content" | ||
| 87 | + android:layout_height="wrap_content" | ||
| 88 | + android:layout_marginStart="25dp" | ||
| 89 | + android:layout_marginTop="8dp" | ||
| 90 | + android:layout_marginEnd="100dp" | ||
| 91 | + android:checkable="true" | ||
| 92 | + android:text="@string/blood_pressure" | ||
| 93 | + card_view:chipIcon="@drawable/cardv_grey_bg" | ||
| 94 | + card_view:layout_constraintEnd_toEndOf="parent" | ||
| 95 | + card_view:layout_constraintStart_toEndOf="@+id/cholesterol_chip" | ||
| 96 | + card_view:layout_constraintTop_toBottomOf="@+id/all_patient_txt_name" /> | ||
| 97 | + | ||
| 98 | + | ||
| 99 | + </androidx.constraintlayout.widget.ConstraintLayout> | ||
| 100 | + | ||
| 101 | + | ||
| 102 | +</androidx.cardview.widget.CardView> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | + android:layout_width="match_parent" | ||
| 4 | + android:layout_height="match_parent" | ||
| 5 | + xmlns:app="http://schemas.android.com/apk/res-auto"> | ||
| 6 | + | ||
| 7 | + <include | ||
| 8 | + android:id="@+id/select_patients_toolbar" | ||
| 9 | + layout = "@layout/toolbar"/> | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + <TextView | ||
| 13 | + android:id="@+id/select_patients_txt_loading" | ||
| 14 | + android:layout_width="match_parent" | ||
| 15 | + android:layout_height="match_parent" | ||
| 16 | + android:text="@string/loading_patients" | ||
| 17 | + android:textSize="20sp" | ||
| 18 | + android:layout_marginStart="8dp" | ||
| 19 | + android:layout_marginTop="8dp" | ||
| 20 | + android:layout_marginEnd="8dp" | ||
| 21 | + android:layout_marginBottom="8dp" | ||
| 22 | + app:layout_constraintBottom_toBottomOf="parent" | ||
| 23 | + app:layout_constraintEnd_toEndOf="parent" | ||
| 24 | + app:layout_constraintStart_toStartOf="parent" | ||
| 25 | + app:layout_constraintTop_toBottomOf="@id/select_patients_toolbar" | ||
| 26 | + app:layout_constraintVertical_bias="0"/> | ||
| 27 | + | ||
| 28 | + <ProgressBar | ||
| 29 | + android:id="@+id/select_patients_progressBar" | ||
| 30 | + style="?android:attr/progressBarStyleLarge" | ||
| 31 | + android:layout_width="wrap_content" | ||
| 32 | + android:layout_height="wrap_content" | ||
| 33 | + android:layout_centerHorizontal="true" | ||
| 34 | + app:layout_constraintBottom_toBottomOf="parent" | ||
| 35 | + app:layout_constraintEnd_toEndOf="parent" | ||
| 36 | + app:layout_constraintStart_toStartOf="parent" | ||
| 37 | + app:layout_constraintTop_toBottomOf="@id/select_patients_toolbar" | ||
| 38 | + /> | ||
| 39 | + | ||
| 40 | + <androidx.recyclerview.widget.RecyclerView | ||
| 41 | + android:id="@+id/select_patients_recycler_view" | ||
| 42 | + android:layout_width="0dp" | ||
| 43 | + android:layout_height="0dp" | ||
| 44 | + android:layout_marginStart="8dp" | ||
| 45 | + android:layout_marginTop="8dp" | ||
| 46 | + android:layout_marginEnd="8dp" | ||
| 47 | + android:layout_marginBottom="8dp" | ||
| 48 | + app:layout_constraintBottom_toBottomOf="parent" | ||
| 49 | + app:layout_constraintEnd_toEndOf="parent" | ||
| 50 | + app:layout_constraintHorizontal_bias="0.0" | ||
| 51 | + app:layout_constraintStart_toStartOf="parent" | ||
| 52 | + app:layout_constraintTop_toBottomOf="@+id/select_patients_toolbar" | ||
| 53 | + app:layout_constraintVertical_bias="0.0" /> | ||
| 54 | +</androidx.constraintlayout.widget.ConstraintLayout> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | + xmlns:tools="http://schemas.android.com/tools" | ||
| 4 | + android:layout_width="match_parent" | ||
| 5 | + android:layout_height="wrap_content" | ||
| 6 | + xmlns:card_view="http://schemas.android.com/apk/res-auto" | ||
| 7 | + android:id="@+id/card_layout" | ||
| 8 | + android:foreground="?selectableItemBackground" | ||
| 9 | + card_view:cardBackgroundColor="@color/color_accent" | ||
| 10 | + card_view:cardCornerRadius="12dp" | ||
| 11 | + card_view:cardElevation="3dp" | ||
| 12 | + android:layout_margin="5dp" | ||
| 13 | + > | ||
| 14 | + | ||
| 15 | + <androidx.constraintlayout.widget.ConstraintLayout | ||
| 16 | + android:id="@+id/card_backgroud" | ||
| 17 | + android:layout_width="match_parent" | ||
| 18 | + android:layout_height="94dp"> | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + <LinearLayout | ||
| 22 | + android:id="@+id/linear_layout" | ||
| 23 | + android:layout_width="wrap_content" | ||
| 24 | + android:layout_height="wrap_content" | ||
| 25 | + card_view:layout_constraintBottom_toBottomOf="parent" | ||
| 26 | + card_view:layout_constraintEnd_toStartOf="@id/guideline2" | ||
| 27 | + card_view:layout_constraintHorizontal_bias="0" | ||
| 28 | + card_view:layout_constraintStart_toStartOf="parent" | ||
| 29 | + card_view:layout_constraintTop_toTopOf="parent" | ||
| 30 | + card_view:layout_constraintVertical_bias="0.5"> | ||
| 31 | + | ||
| 32 | + <CheckBox | ||
| 33 | + android:id="@+id/checkBox" | ||
| 34 | + android:layout_width="wrap_content" | ||
| 35 | + android:layout_height="wrap_content" | ||
| 36 | + android:theme="@style/checkBoxStyle" | ||
| 37 | + android:visibility="gone" /> | ||
| 38 | + | ||
| 39 | + </LinearLayout> | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + <TextView | ||
| 43 | + android:id="@+id/all_patient_txt_name" | ||
| 44 | + android:layout_width="0dp" | ||
| 45 | + android:layout_height="wrap_content" | ||
| 46 | + android:text="@string/patient_name" | ||
| 47 | + android:textSize="25sp" | ||
| 48 | + card_view:layout_constraintBottom_toBottomOf="@id/linear_layout" | ||
| 49 | + card_view:layout_constraintEnd_toStartOf="@id/guideline2" | ||
| 50 | + card_view:layout_constraintHorizontal_bias="0.0" | ||
| 51 | + card_view:layout_constraintStart_toEndOf="@id/guideline" | ||
| 52 | + card_view:layout_constraintTop_toTopOf="parent" | ||
| 53 | + card_view:layout_constraintVertical_bias="0.285" /> | ||
| 54 | + | ||
| 55 | + <androidx.constraintlayout.widget.Guideline | ||
| 56 | + android:id="@+id/guideline" | ||
| 57 | + android:layout_width="wrap_content" | ||
| 58 | + android:layout_height="wrap_content" | ||
| 59 | + android:orientation="vertical" | ||
| 60 | + card_view:layout_constraintGuide_percent="0.04" /> | ||
| 61 | + | ||
| 62 | + <androidx.constraintlayout.widget.Guideline | ||
| 63 | + android:id="@+id/guideline2" | ||
| 64 | + android:layout_width="wrap_content" | ||
| 65 | + android:layout_height="wrap_content" | ||
| 66 | + android:orientation="vertical" | ||
| 67 | + card_view:layout_constraintGuide_percent="0.96" /> | ||
| 68 | + | ||
| 69 | + <com.google.android.material.chip.Chip | ||
| 70 | + android:id="@+id/cholesterol_chip" | ||
| 71 | + android:layout_width="wrap_content" | ||
| 72 | + android:layout_height="wrap_content" | ||
| 73 | + android:layout_marginStart="45dp" | ||
| 74 | + android:layout_marginTop="8dp" | ||
| 75 | + android:layout_marginEnd="267dp" | ||
| 76 | + android:checkable="true" | ||
| 77 | + android:text="@string/cholesterol" | ||
| 78 | + card_view:chipIcon="@drawable/cardv_grey_bg" | ||
| 79 | + card_view:layout_constraintBottom_toBottomOf="parent" | ||
| 80 | + card_view:layout_constraintEnd_toEndOf="parent" | ||
| 81 | + card_view:layout_constraintStart_toStartOf="parent" | ||
| 82 | + card_view:layout_constraintTop_toBottomOf="@+id/all_patient_txt_name" /> | ||
| 83 | + | ||
| 84 | + <com.google.android.material.chip.Chip | ||
| 85 | + android:id="@+id/blood_pressure_chip" | ||
| 86 | + android:layout_width="wrap_content" | ||
| 87 | + android:layout_height="wrap_content" | ||
| 88 | + android:layout_marginStart="25dp" | ||
| 89 | + android:layout_marginTop="8dp" | ||
| 90 | + android:layout_marginEnd="100dp" | ||
| 91 | + android:checkable="true" | ||
| 92 | + android:text="@string/blood_pressure" | ||
| 93 | + card_view:chipIcon="@drawable/cardv_grey_bg" | ||
| 94 | + card_view:layout_constraintEnd_toEndOf="parent" | ||
| 95 | + card_view:layout_constraintStart_toEndOf="@+id/cholesterol_chip" | ||
| 96 | + card_view:layout_constraintTop_toBottomOf="@+id/all_patient_txt_name" /> | ||
| 97 | + | ||
| 98 | + | ||
| 99 | + </androidx.constraintlayout.widget.ConstraintLayout> | ||
| 100 | + | ||
| 101 | + | ||
| 102 | +</androidx.cardview.widget.CardView> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
app/src/main/res/layout/toolbar.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | + android:layout_width="match_parent" | ||
| 4 | + android:layout_height="wrap_content" | ||
| 5 | + xmlns:app="http://schemas.android.com/apk/res-auto" | ||
| 6 | + android:background="@color/colorPrimary" | ||
| 7 | + android:elevation="6dp" | ||
| 8 | + android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" | ||
| 9 | + app:popupTheme="@style/ThemeOverlay.AppCompat.Light"> | ||
| 10 | + | ||
| 11 | + <RelativeLayout | ||
| 12 | + android:layout_width="match_parent" | ||
| 13 | + android:layout_height="wrap_content"> | ||
| 14 | + | ||
| 15 | + <ImageButton | ||
| 16 | + android:id="@+id/btn_back" | ||
| 17 | + android:layout_width="wrap_content" | ||
| 18 | + android:layout_height="wrap_content" | ||
| 19 | + android:background="@android:color/transparent" | ||
| 20 | + android:src="@drawable/ic_arrow_back_24dp" | ||
| 21 | + android:layout_centerVertical="true" | ||
| 22 | + android:layout_marginRight="20dp" | ||
| 23 | + /> | ||
| 24 | + | ||
| 25 | + <TextView | ||
| 26 | + android:id="@+id/toolbar_title" | ||
| 27 | + android:layout_width="wrap_content" | ||
| 28 | + android:layout_height="wrap_content" | ||
| 29 | + android:layout_toRightOf="@id/btn_back" | ||
| 30 | + android:text="Title Here" | ||
| 31 | + android:textSize="23sp" | ||
| 32 | + android:textColor="@color/color_white" | ||
| 33 | + android:layout_centerVertical="true"> | ||
| 34 | + </TextView> | ||
| 35 | + | ||
| 36 | + </RelativeLayout> | ||
| 37 | + | ||
| 38 | +</androidx.appcompat.widget.Toolbar> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<menu xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | + xmlns:app="http://schemas.android.com/apk/res-auto"> | ||
| 4 | + <item | ||
| 5 | + android:id="@+id/patient_add" | ||
| 6 | + app:showAsAction="always" | ||
| 7 | + android:title="@string/start_monitoring" /> | ||
| 8 | + | ||
| 9 | +</menu> |
| ... | @@ -368,4 +368,6 @@ | ... | @@ -368,4 +368,6 @@ |
| 368 | <string name="string_check_date">检查日期:</string> | 368 | <string name="string_check_date">检查日期:</string> |
| 369 | <string name="string_examination_doctor">检查医生:</string> | 369 | <string name="string_examination_doctor">检查医生:</string> |
| 370 | 370 | ||
| 371 | + | ||
| 372 | + | ||
| 371 | </resources> | 373 | </resources> |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -61,6 +61,10 @@ | ... | @@ -61,6 +61,10 @@ |
| 61 | <color name="color_4f4f4f">#4F4F4F</color> | 61 | <color name="color_4f4f4f">#4F4F4F</color> |
| 62 | <color name="color_565656">#565656</color> | 62 | <color name="color_565656">#565656</color> |
| 63 | <color name="color_737373">#737373</color> | 63 | <color name="color_737373">#737373</color> |
| 64 | - | 64 | + <color name="color_accent">#E0E9FF</color> |
| 65 | + <color name="color_accent_text">#35375A</color> | ||
| 66 | + <color name="color_selected_patient">#bedec5</color> | ||
| 67 | + <color name="unselected">#8c92ac</color> | ||
| 68 | + <color name="colorPrimary">#5C4AE4</color> | ||
| 65 | 69 | ||
| 66 | </resources> | 70 | </resources> |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -388,4 +388,12 @@ | ... | @@ -388,4 +388,12 @@ |
| 388 | <string name="normal_mode">标定模式</string> | 388 | <string name="normal_mode">标定模式</string> |
| 389 | <string name="single_mode">单帧模式</string> | 389 | <string name="single_mode">单帧模式</string> |
| 390 | 390 | ||
| 391 | + <string name="loading_patients">Loading Patients…</string> | ||
| 392 | + <string name="patient_name">Patient Name</string> | ||
| 393 | + <string name="cholesterol">cholesterol</string> | ||
| 394 | + <string name="blood_pressure">blood pressure</string> | ||
| 395 | + <string name="zero_patients_message">You have 0 patients</string> | ||
| 396 | + <string name="title_patient_selection">Select Patients</string> | ||
| 397 | + <string name="start_monitoring">Start</string> | ||
| 398 | + | ||
| 391 | </resources> | 399 | </resources> |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -53,4 +53,9 @@ | ... | @@ -53,4 +53,9 @@ |
| 53 | <item name="colorControlActivated">@color/color_42bf58</item> | 53 | <item name="colorControlActivated">@color/color_42bf58</item> |
| 54 | </style> | 54 | </style> |
| 55 | 55 | ||
| 56 | + <style name="checkBoxStyle" parent="Base.Theme.AppCompat"> | ||
| 57 | + <item name="colorAccent">@color/color_accent_text</item> | ||
| 58 | + <item name="android:textColorSecondary">@color/color_accent_text</item> | ||
| 59 | + </style> | ||
| 60 | + | ||
| 56 | </resources> | 61 | </resources> |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment