diff --git a/app/.idea/.gitignore b/app/.idea/.gitignore new file mode 100644 index 000000000..26d33521a --- /dev/null +++ b/app/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/app/.idea/AndroidProjectSystem.xml b/app/.idea/AndroidProjectSystem.xml new file mode 100644 index 000000000..4a53bee8c --- /dev/null +++ b/app/.idea/AndroidProjectSystem.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/.idea/caches/deviceStreaming.xml b/app/.idea/caches/deviceStreaming.xml new file mode 100644 index 000000000..c31fe546b --- /dev/null +++ b/app/.idea/caches/deviceStreaming.xml @@ -0,0 +1,1574 @@ + + + + + + \ No newline at end of file diff --git a/app/.idea/gradle.xml b/app/.idea/gradle.xml new file mode 100644 index 000000000..9d8ba93b9 --- /dev/null +++ b/app/.idea/gradle.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/.idea/migrations.xml b/app/.idea/migrations.xml new file mode 100644 index 000000000..f8051a6f9 --- /dev/null +++ b/app/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/.idea/misc.xml b/app/.idea/misc.xml new file mode 100644 index 000000000..0573b9e5c --- /dev/null +++ b/app/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/.idea/runConfigurations.xml b/app/.idea/runConfigurations.xml new file mode 100644 index 000000000..16660f1d8 --- /dev/null +++ b/app/.idea/runConfigurations.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/app/.idea/vcs.xml b/app/.idea/vcs.xml new file mode 100644 index 000000000..6c0b86358 --- /dev/null +++ b/app/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/java/deakin/gopher/.idea/.gitignore b/app/src/main/java/deakin/gopher/.idea/.gitignore new file mode 100644 index 000000000..26d33521a --- /dev/null +++ b/app/src/main/java/deakin/gopher/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/app/src/main/java/deakin/gopher/.idea/caches/deviceStreaming.xml b/app/src/main/java/deakin/gopher/.idea/caches/deviceStreaming.xml new file mode 100644 index 000000000..c31fe546b --- /dev/null +++ b/app/src/main/java/deakin/gopher/.idea/caches/deviceStreaming.xml @@ -0,0 +1,1574 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/java/deakin/gopher/.idea/libraries/KotlinJavaScript.xml b/app/src/main/java/deakin/gopher/.idea/libraries/KotlinJavaScript.xml new file mode 100644 index 000000000..4b01461bc --- /dev/null +++ b/app/src/main/java/deakin/gopher/.idea/libraries/KotlinJavaScript.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/deakin/gopher/.idea/misc.xml b/app/src/main/java/deakin/gopher/.idea/misc.xml new file mode 100644 index 000000000..0abfbc5d3 --- /dev/null +++ b/app/src/main/java/deakin/gopher/.idea/misc.xml @@ -0,0 +1,19 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/deakin/gopher/.idea/modules.xml b/app/src/main/java/deakin/gopher/.idea/modules.xml new file mode 100644 index 000000000..aa13c142d --- /dev/null +++ b/app/src/main/java/deakin/gopher/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/deakin/gopher/.idea/vcs.xml b/app/src/main/java/deakin/gopher/.idea/vcs.xml new file mode 100644 index 000000000..821e530dd --- /dev/null +++ b/app/src/main/java/deakin/gopher/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/java/deakin/gopher/guardian/services/api/ApiClient.kt b/app/src/main/java/deakin/gopher/guardian/services/api/ApiClient.kt index 48eff44c6..b98828cc9 100644 --- a/app/src/main/java/deakin/gopher/guardian/services/api/ApiClient.kt +++ b/app/src/main/java/deakin/gopher/guardian/services/api/ApiClient.kt @@ -7,7 +7,7 @@ import retrofit2.converter.gson.GsonConverterFactory object RetrofitClient { // private const val BASE_URL = "http://10.0.2.2:3000/api/v1/" - private const val BASE_URL = "https://guardian-backend-opal.vercel.app/api/v1/" + private const val BASE_URL = "https://guardian-backend-ashen.vercel.app/api/v1/" private val client = OkHttpClient() private val interceptor = HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY) diff --git a/app/src/main/java/deakin/gopher/guardian/view/general/TaskAddActivity.kt b/app/src/main/java/deakin/gopher/guardian/view/general/TaskAddActivity.kt index cb8c1aed8..e8da4fab0 100644 --- a/app/src/main/java/deakin/gopher/guardian/view/general/TaskAddActivity.kt +++ b/app/src/main/java/deakin/gopher/guardian/view/general/TaskAddActivity.kt @@ -4,7 +4,7 @@ import android.os.Bundle import android.view.View import android.widget.Button import android.widget.EditText -import android.widget.RadioGroup +import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.core.view.GravityCompat @@ -18,8 +18,6 @@ class TaskAddActivity : AppCompatActivity() { private lateinit var taskDescriptionEditText: EditText private lateinit var patientIdEditText: EditText private lateinit var taskSubDescEditText: EditText - private lateinit var assignedNurseEditText: EditText - private lateinit var priorityRadioGroup: RadioGroup private var taskPriority: Priority = Priority.MEDIUM private var task: Task? = null @@ -31,16 +29,12 @@ class TaskAddActivity : AppCompatActivity() { taskSubDescEditText = findViewById(R.id.tasksubDescEditText) patientIdEditText = findViewById(R.id.taskPatientIdEditText) - priorityRadioGroup.setOnCheckedChangeListener { _, checkedId -> - taskPriority = - when (checkedId) { - else -> Priority.MEDIUM - } - } - val submitButton: Button = findViewById(R.id.newTaskSubmitButton) submitButton.setOnClickListener { - showSaveDialog() + // ADDED: Validate input before save + if (validateInputs()) { + showSaveDialog() + } } val customHeader: CustomHeader = findViewById(R.id.taskCustomHeader) @@ -56,15 +50,39 @@ class TaskAddActivity : AppCompatActivity() { } } + // ADDED: Basic validation to improve task creation flow + private fun validateInputs(): Boolean { + val patientId = patientIdEditText.text.toString().trim() + val taskDescription = taskDescriptionEditText.text.toString().trim() + + if (patientId.isEmpty()) { + patientIdEditText.error = "Patient ID is required" + patientIdEditText.requestFocus() + return false + } + + if (taskDescription.isEmpty()) { + taskDescriptionEditText.error = "Task description is required" + taskDescriptionEditText.requestFocus() + return false + } + + return true + } + private fun showSaveDialog() { val builder = AlertDialog.Builder(this) builder.setTitle(getString(R.string.saving_changes)) + // ADDED: Clearer confirmation message + builder.setMessage("Do you want to save this task?") builder.setPositiveButton(getString(R.string.yes)) { _, _ -> saveInFirebase() } builder.setNegativeButton(getString(R.string.no), null) val dialog = builder.create() dialog.setOnShowListener { - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(resources.getColor(R.color.colorGreen)) - dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(resources.getColor(R.color.colorRed)) + dialog.getButton(AlertDialog.BUTTON_POSITIVE) + .setTextColor(resources.getColor(R.color.colorGreen)) + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) + .setTextColor(resources.getColor(R.color.colorRed)) } dialog.show() } @@ -76,12 +94,22 @@ class TaskAddActivity : AppCompatActivity() { val patientId = patientIdEditText.text.toString().trim() val taskDescription = taskDescriptionEditText.text.toString().trim() val taskSubDesc = taskSubDescEditText.text.toString().trim() - val assignedNurse = assignedNurseEditText.text.toString().trim() + + // ADDED: No nurse input exists in current UI, so default value is used + val assignedNurse = "Not Assigned" + + // IMPROVED: Merge sub description with main description when provided + val finalDescription = + if (taskSubDesc.isNotEmpty()) { + "$taskDescription - $taskSubDesc" + } else { + taskDescription + } val newTask = Task( taskId = "", - description = taskDescription, + description = finalDescription, assignedNurse = assignedNurse, priority = taskPriority, patientId = patientId, @@ -90,22 +118,34 @@ class TaskAddActivity : AppCompatActivity() { val taskId = caretakerTaskRef.push().key ?: "" newTask.taskId = taskId + // ADDED: Prevent repeated taps during save + val submitButton: Button = findViewById(R.id.newTaskSubmitButton) + submitButton.isEnabled = false + caretakerTaskRef.child(taskId).setValue(newTask).addOnCompleteListener { task -> if (task.isSuccessful) { updatePatientTasks(taskId) - finish() + + // IMPROVED: Also save to nurse tasks and show feedback + val nurseTaskRef = databaseRef.child("nurse_tasks") + nurseTaskRef.child(taskId).setValue(newTask).addOnCompleteListener { nurseTask -> + if (nurseTask.isSuccessful) { + Toast.makeText(this, "Task saved successfully", Toast.LENGTH_SHORT).show() + finish() + } else { + Toast.makeText(this, "Task saved partially", Toast.LENGTH_SHORT).show() + submitButton.isEnabled = true + } + } } else { - // Handle the error + Toast.makeText(this, "Failed to save task", Toast.LENGTH_SHORT).show() + submitButton.isEnabled = true } } - - // Save under nurse tasks as well - val nurseTaskRef = databaseRef.child("nurse_tasks") - nurseTaskRef.child(taskId).setValue(newTask) } private fun updatePatientTasks(taskId: String) { val patientTasksRef = FirebaseDatabase.getInstance().reference.child("patient_tasks") patientTasksRef.child(taskId).setValue(true) } -} +} \ No newline at end of file diff --git a/app/src/main/java/deakin/gopher/guardian/view/general/TaskDetailActivity.kt b/app/src/main/java/deakin/gopher/guardian/view/general/TaskDetailActivity.kt index 962ede6c2..f92781282 100644 --- a/app/src/main/java/deakin/gopher/guardian/view/general/TaskDetailActivity.kt +++ b/app/src/main/java/deakin/gopher/guardian/view/general/TaskDetailActivity.kt @@ -14,97 +14,147 @@ import deakin.gopher.guardian.R import deakin.gopher.guardian.model.Task class TaskDetailActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_task_detail) - var taskDescriptionTextView: TextView = findViewById(R.id.task_detail_description_text_view) - var taskAssignedNurseTextView: TextView = findViewById(R.id.task_text_view_nurse_name) - var taskPriorityTextView: TextView = findViewById(R.id.task_text_view_priority) - var completeButton: Button = findViewById(R.id.task_button_mark_complete) - var backButton: Button = findViewById(R.id.task_detail_back_button) - var deleteButton: Button = findViewById(R.id.task_button_mark_delete) - var incompleteButton: Button = findViewById(R.id.task_button_mark_incomplete) + + val taskDescriptionTextView: TextView = findViewById(R.id.task_detail_description_text_view) + val taskAssignedNurseTextView: TextView = findViewById(R.id.task_text_view_nurse_name) + val taskPriorityTextView: TextView = findViewById(R.id.task_text_view_priority) + + val completeButton: Button = findViewById(R.id.task_button_mark_complete) + val incompleteButton: Button = findViewById(R.id.task_button_mark_incomplete) + val deleteButton: Button = findViewById(R.id.task_button_mark_delete) + val backButton: Button = findViewById(R.id.task_detail_back_button) + val taskId = intent.getStringExtra("taskId") - if (taskId != null) { - val taskRef = FirebaseDatabase.getInstance().getReference("nurse-tasks").child(taskId) - taskRef.addListenerForSingleValueEvent( - object : ValueEventListener { - override fun onDataChange(dataSnapshot: DataSnapshot) { - if (dataSnapshot.exists()) { - val task = - dataSnapshot.getValue( - Task::class.java, - ) - if (task != null) { - var textdesc = getString(R.string.task_description_prefix) + " " + task.description - var textnur = getString(R.string.assigned_nurse_prefix) + " " + task.assignedNurse - var textprior = getString(R.string.priority_prefix) + " " + task.priority.toString() - - taskDescriptionTextView.setText(textdesc) - taskAssignedNurseTextView.setText(textnur) - taskPriorityTextView.setText(textprior) - - if (task.completed) { - completeButton.visibility = View.GONE - incompleteButton.visibility = View.VISIBLE - } else { - incompleteButton.visibility = View.GONE - completeButton.visibility = View.VISIBLE - } - } - } - } - override fun onCancelled(databaseError: DatabaseError) { + // ADDED: Handle missing taskId (prevents crash / blank screen) + if (taskId == null) { + Toast.makeText(this, "Task not found", Toast.LENGTH_SHORT).show() + finish() + return + } + + val taskRef = FirebaseDatabase.getInstance().getReference("nurse-tasks").child(taskId) + + // ADDED: Show loading state (basic UX improvement) + taskDescriptionTextView.text = "Loading..." + taskAssignedNurseTextView.text = "" + taskPriorityTextView.text = "" + + taskRef.addListenerForSingleValueEvent( + object : ValueEventListener { + override fun onDataChange(dataSnapshot: DataSnapshot) { + + // ADDED: Handle empty snapshot (task deleted or missing) + if (!dataSnapshot.exists()) { Toast.makeText( this@TaskDetailActivity, - databaseError.toString(), - Toast.LENGTH_SHORT, + "Task not found", + Toast.LENGTH_SHORT ).show() - } - }, - ) - - fun markAsCompleted() { - val taskRef = FirebaseDatabase.getInstance().getReference("nurse-tasks").child(taskId) - taskRef.child("completed").setValue(true) - Toast.makeText(this@TaskDetailActivity, "Task marked as completed", Toast.LENGTH_SHORT).show() - completeButton.visibility = View.GONE - incompleteButton.visibility = View.VISIBLE - } - - fun markAsIncomplete() { - val taskRef = FirebaseDatabase.getInstance().getReference("nurse-tasks").child(taskId) - taskRef.child("completed").setValue(false) - Toast.makeText(this@TaskDetailActivity, "Task marked as incomplete", Toast.LENGTH_SHORT).show() - incompleteButton.visibility = View.GONE - completeButton.visibility = View.VISIBLE - } - - fun deleteTask() { - val taskRef = - FirebaseDatabase.getInstance().getReference("nurse-tasks").child(taskId) - taskRef.removeValue() - .addOnSuccessListener { - Toast.makeText(this, "Task deleted", Toast.LENGTH_SHORT).show() finish() + return } - .addOnFailureListener { - Toast.makeText(this, "Failed to delete task", Toast.LENGTH_SHORT).show() + + val task = dataSnapshot.getValue(Task::class.java) + + if (task != null) { + + val textdesc = + getString(R.string.task_description_prefix) + " " + task.description + val textnur = + getString(R.string.assigned_nurse_prefix) + " " + task.assignedNurse + val textprior = + getString(R.string.priority_prefix) + " " + task.priority.toString() + + taskDescriptionTextView.text = textdesc + taskAssignedNurseTextView.text = textnur + taskPriorityTextView.text = textprior + + // IMPROVED: Clearer button state handling + if (task.completed) { + completeButton.visibility = View.GONE + incompleteButton.visibility = View.VISIBLE + } else { + incompleteButton.visibility = View.GONE + completeButton.visibility = View.VISIBLE + } } - } - completeButton.setOnClickListener { - markAsCompleted() - } - incompleteButton.setOnClickListener { - markAsIncomplete() - } - backButton.setOnClickListener { - finish() - } - deleteButton.setOnClickListener { - deleteTask() - } + } + + override fun onCancelled(databaseError: DatabaseError) { + // IMPROVED: Better error message + Toast.makeText( + this@TaskDetailActivity, + "Failed to load task", + Toast.LENGTH_SHORT + ).show() + } + }, + ) + + // IMPROVED: Disable button during action to prevent multiple clicks + fun markAsCompleted() { + completeButton.isEnabled = false + + taskRef.child("completed").setValue(true) + .addOnSuccessListener { + Toast.makeText(this, "Task marked as completed", Toast.LENGTH_SHORT).show() + completeButton.visibility = View.GONE + incompleteButton.visibility = View.VISIBLE + } + .addOnFailureListener { + Toast.makeText(this, "Failed to update task", Toast.LENGTH_SHORT).show() + completeButton.isEnabled = true + } + } + + fun markAsIncomplete() { + incompleteButton.isEnabled = false + + taskRef.child("completed").setValue(false) + .addOnSuccessListener { + Toast.makeText(this, "Task marked as incomplete", Toast.LENGTH_SHORT).show() + incompleteButton.visibility = View.GONE + completeButton.visibility = View.VISIBLE + } + .addOnFailureListener { + Toast.makeText(this, "Failed to update task", Toast.LENGTH_SHORT).show() + incompleteButton.isEnabled = true + } + } + + fun deleteTask() { + deleteButton.isEnabled = false + + taskRef.removeValue() + .addOnSuccessListener { + Toast.makeText(this, "Task deleted", Toast.LENGTH_SHORT).show() + finish() + } + .addOnFailureListener { + Toast.makeText(this, "Failed to delete task", Toast.LENGTH_SHORT).show() + deleteButton.isEnabled = true + } + } + + completeButton.setOnClickListener { + markAsCompleted() + } + + incompleteButton.setOnClickListener { + markAsIncomplete() + } + + deleteButton.setOnClickListener { + deleteTask() + } + + backButton.setOnClickListener { + finish() } } -} +} \ No newline at end of file diff --git a/app/src/main/java/deakin/gopher/guardian/view/general/TasksListActivity.kt b/app/src/main/java/deakin/gopher/guardian/view/general/TasksListActivity.kt index 0661d6955..83621ea07 100644 --- a/app/src/main/java/deakin/gopher/guardian/view/general/TasksListActivity.kt +++ b/app/src/main/java/deakin/gopher/guardian/view/general/TasksListActivity.kt @@ -3,10 +3,12 @@ package deakin.gopher.guardian.view.general import android.content.Intent import android.os.Bundle import android.view.MenuItem +import android.view.View import android.widget.Button import android.widget.ImageButton import android.widget.ImageView import android.widget.SearchView +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.cardview.widget.CardView import androidx.core.view.GravityCompat @@ -31,39 +33,51 @@ class TasksListActivity : AppCompatActivity() { private var overviewCardview: CardView? = null private lateinit var plusButton: ImageButton + // ADDED: Keep a reference to the Firebase listener to avoid duplicate listeners + private var taskValueEventListener: ValueEventListener? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_tasks_list) + val navigationView: NavigationView = findViewById(R.id.nav_view) val taskListMenuBtn: ImageView = findViewById(R.id.task_list_manu_button) val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout) plusButton = findViewById(R.id.imageView62) navigationView.setItemIconTintList(null) - taskListMenuBtn.setOnClickListener { - drawerLayout.openDrawer(GravityCompat.START) - navigationView.setNavigationItemSelectedListener { menuItem: MenuItem -> - val id = menuItem.itemId - when (id) { - R.id.nav_home -> - startActivity( - Intent(this@TasksListActivity, Homepage4caretaker::class.java), - ) -// R.id.nav_settings -> startActivity( -// Intent(this@TasksListActivity, Setting::class.java) -// ) - R.id.add_task -> - startActivity( - Intent(this@TasksListActivity, TaskAddActivity::class.java), - ) - R.id.nav_signout -> { - FirebaseAuth.getInstance().signOut() - startActivity(Intent(this@TasksListActivity, LoginActivity::class.java)) - finish() - } + + // FIXED: Navigation item listener moved outside menu button click + // This prevents the listener from being attached again every time the menu button is pressed + navigationView.setNavigationItemSelectedListener { menuItem: MenuItem -> + val id = menuItem.itemId + when (id) { + R.id.nav_home -> + startActivity( + Intent(this@TasksListActivity, Homepage4caretaker::class.java), + ) + +// R.id.nav_settings -> startActivity( +// Intent(this@TasksListActivity, Setting::class.java) +// ) + + R.id.add_task -> + startActivity( + Intent(this@TasksListActivity, TaskAddActivity::class.java), + ) + + R.id.nav_signout -> { + FirebaseAuth.getInstance().signOut() + startActivity(Intent(this@TasksListActivity, LoginActivity::class.java)) + finish() } - true } + true + } + + // SIMPLIFIED: Menu button only opens the drawer + taskListMenuBtn.setOnClickListener { + drawerLayout.openDrawer(GravityCompat.START) } plusButton.setOnClickListener { @@ -74,6 +88,7 @@ class TasksListActivity : AppCompatActivity() { overviewCardview = findViewById(R.id.task_list_task_overview) val taskSearchView: SearchView = findViewById(R.id.task_list_searchView) val addTaskButton: Button = findViewById(R.id.add_task_button) + addTaskButton.setOnClickListener { NavigationService(this).onLaunchTaskCreator() } @@ -108,6 +123,8 @@ class TasksListActivity : AppCompatActivity() { .endAt(s + "\uf8ff") .limitToFirst(10) } + + // REFRESH: Reload Firebase data when search text changes fetchDataFromFirebase() return true } @@ -116,23 +133,52 @@ class TasksListActivity : AppCompatActivity() { } private fun fetchDataFromFirebase() { - query?.addValueEventListener( + // ADDED: Remove previous listener before attaching a new one + // This avoids duplicate callbacks when search text changes + taskValueEventListener?.let { listener -> + query?.removeEventListener(listener) + } + + taskValueEventListener = object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { val taskList = mutableListOf() + for (taskSnapshot in dataSnapshot.children) { val task = taskSnapshot.getValue(Task::class.java) if (task != null) { taskList.add(task) } } + taskListAdapter?.updateTaskList(taskList) + + // ADDED: Basic empty-state handling using existing CardView + if (taskList.isEmpty()) { + overviewCardview?.visibility = View.GONE + } else { + overviewCardview?.visibility = View.VISIBLE + } } override fun onCancelled(databaseError: DatabaseError) { - // Handle possible errors. + // ADDED: Show simple error feedback to improve user experience + Toast.makeText( + this@TasksListActivity, + "Failed to load tasks: ${databaseError.message}", + Toast.LENGTH_SHORT, + ).show() } - }, - ) + } + + query?.addValueEventListener(taskValueEventListener!!) + } + + // ADDED: Remove listener when activity is destroyed to improve stability + override fun onDestroy() { + super.onDestroy() + taskValueEventListener?.let { listener -> + query?.removeEventListener(listener) + } } -} +} \ No newline at end of file diff --git a/app/src/main/java/deakin/gopher/guardian/view/patient/careplan/CarePlanActivity.java b/app/src/main/java/deakin/gopher/guardian/view/patient/careplan/CarePlanActivity.java index 5d97ac573..e47bee051 100644 --- a/app/src/main/java/deakin/gopher/guardian/view/patient/careplan/CarePlanActivity.java +++ b/app/src/main/java/deakin/gopher/guardian/view/patient/careplan/CarePlanActivity.java @@ -6,6 +6,7 @@ import android.widget.ImageView; import android.widget.RadioButton; import android.widget.RadioGroup; +import android.widget.Toast; // ADDED import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; @@ -22,295 +23,333 @@ import java.util.HashMap; public class CarePlanActivity extends AppCompatActivity { - final HashMap supportRequirementsCheckBox = new HashMap<>(); - final HashMap drinkLikesCheckBox = new HashMap<>(); - final HashMap painCheckBox = new HashMap<>(); - final HashMap behavioralManagementCheckBox = new HashMap<>(); - - RadioGroup carePlanTypeRadioGroup; - HashMap carePlanTypesRadioButtons = new HashMap<>(); - - RadioGroup nutritionRadioGroup; - HashMap nutritionRadioButtons = new HashMap<>(); - - RadioGroup dietTimeRadioGroup; - HashMap dietTimeRadioButtons = new HashMap<>(); - - RadioGroup sleepPatternRadioGroup; - HashMap sleepPatternRadioButtons = new HashMap<>(); - - RadioGroup painScoreRadioGroup; - HashMap painScoreRadioButtons = new HashMap<>(); - - Button submitButton; - ImageView carePlanMenuButton; - DatabaseReference carePlanRef; - String patientId; - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - patientId = getIntent().getStringExtra("patientId"); - setContentView(R.layout.activity_care_plan); - - submitButton = findViewById(R.id.carePlanSubmitButton); - - final NavigationView navigationView = findViewById(R.id.nav_view); - carePlanMenuButton = findViewById(R.id.menuButton11); - final DrawerLayout drawerLayout = findViewById(R.id.drawer_layout); - navigationView.setItemIconTintList(null); - - carePlanMenuButton.setOnClickListener( - v -> { - drawerLayout.openDrawer(GravityCompat.START); - }); - - // careplan type - carePlanTypeRadioGroup = findViewById(R.id.carePlanTypeRGroup); - carePlanTypesRadioButtons.put((RadioButton) findViewById(R.id.radioButton2), "Home"); - carePlanTypesRadioButtons.put((RadioButton) findViewById(R.id.radioButton), "Hospital"); - - nutritionRadioGroup = findViewById(R.id.nutritionHydrationRGroup); - nutritionRadioButtons.put((RadioButton) findViewById(R.id.radioButton6), "Yes"); - nutritionRadioButtons.put((RadioButton) findViewById(R.id.radioButton7), "No"); - nutritionRadioButtons.put((RadioButton) findViewById(R.id.radioButton8), "NA"); - - dietTimeRadioGroup = findViewById((R.id.dietTimingRGroup)); - dietTimeRadioButtons.put((RadioButton) findViewById(R.id.radioButton9), "8AM-BR"); - dietTimeRadioButtons.put((RadioButton) findViewById(R.id.radioButton5), "12PM-LN"); - dietTimeRadioButtons.put((RadioButton) findViewById(R.id.radioButton10), "6PM-DN"); - - sleepPatternRadioGroup = findViewById(R.id.sleepPatternsRGroup); - sleepPatternRadioButtons.put((RadioButton) findViewById(R.id.radioButton61), "10PM-6AM"); - sleepPatternRadioButtons.put((RadioButton) findViewById(R.id.radioButton71), "8PM-4AM"); - sleepPatternRadioButtons.put((RadioButton) findViewById(R.id.radioButton81), "11PM-7AM"); - - painScoreRadioGroup = findViewById(R.id.ratingGroup); - painScoreRadioButtons.put((RadioButton) findViewById((R.id.radioButton21)), "1"); - painScoreRadioButtons.put((RadioButton) findViewById((R.id.radioButton22)), "2"); - painScoreRadioButtons.put((RadioButton) findViewById((R.id.radioButton23)), "3"); - painScoreRadioButtons.put((RadioButton) findViewById((R.id.radioButton24)), "4"); - painScoreRadioButtons.put((RadioButton) findViewById((R.id.radioButton25)), "5"); - painScoreRadioButtons.put((RadioButton) findViewById((R.id.radioButton26)), "6"); - painScoreRadioButtons.put((RadioButton) findViewById((R.id.radioButton27)), "7"); - painScoreRadioButtons.put((RadioButton) findViewById((R.id.radioButton28)), "8"); - painScoreRadioButtons.put((RadioButton) findViewById((R.id.radioButton29)), "9"); - painScoreRadioButtons.put((RadioButton) findViewById((R.id.radioButton30)), "10"); - - // support requirements - supportRequirementsCheckBox.put((CheckBox) findViewById(R.id.selfCareCheckBox), "Self Care"); - supportRequirementsCheckBox.put((CheckBox) findViewById(R.id.walkingCheckBox), "Walking"); - supportRequirementsCheckBox.put((CheckBox) findViewById(R.id.activitiesCheckBox), "Activities"); - supportRequirementsCheckBox.put((CheckBox) findViewById(R.id.bathroomCheckBox), "Bathroom"); - supportRequirementsCheckBox.put((CheckBox) findViewById(R.id.shoppingCheckBox), "Shopping"); - - // drinks - drinkLikesCheckBox.put((CheckBox) findViewById(R.id.coffeeCheckBox), "Coffee"); - drinkLikesCheckBox.put((CheckBox) findViewById(R.id.teaCheckBox), "Tea"); - drinkLikesCheckBox.put((CheckBox) findViewById(R.id.waterCheckBox), "Water"); - - // pain - painCheckBox.put((CheckBox) findViewById(R.id.chronicCheckBox), "Chronic"); - painCheckBox.put((CheckBox) findViewById(R.id.massageRequiredCheckBox), "Massage Required"); - painCheckBox.put((CheckBox) findViewById(R.id.pillowSupportCheckBox), "Pillow Support"); - painCheckBox.put((CheckBox) findViewById(R.id.heatPackCheckBox), "Heat Pack"); - painCheckBox.put((CheckBox) findViewById(R.id.NAcheckBox), "NA"); - - // behavior - behavioralManagementCheckBox.put( - (CheckBox) findViewById(R.id.dollTherapyCheckBox), "Doll Therapy"); - behavioralManagementCheckBox.put( - (CheckBox) findViewById(R.id.petTherapyCheckBox), "Pet Therapy"); - behavioralManagementCheckBox.put( - (CheckBox) findViewById(R.id.dementiaCheckBox), "Dementia Management"); - behavioralManagementCheckBox.put( - (CheckBox) findViewById(R.id.lightsOnBedroomCB), "Lights on Bedroom"); - behavioralManagementCheckBox.put( - (CheckBox) findViewById(R.id.lightsOnBathroomCB), "Lights on Bathroom"); - - // Firebase initialization - FirebaseDatabase database = FirebaseDatabase.getInstance(); - carePlanRef = database.getReference("careplan"); - // Load care plan summary data from Firebase - if (!"".equals(patientId) && null != patientId) { - loadCarePlanDataForPatient(patientId); + final HashMap supportRequirementsCheckBox = new HashMap<>(); + final HashMap drinkLikesCheckBox = new HashMap<>(); + final HashMap painCheckBox = new HashMap<>(); + final HashMap behavioralManagementCheckBox = new HashMap<>(); + + RadioGroup carePlanTypeRadioGroup; + HashMap carePlanTypesRadioButtons = new HashMap<>(); + + RadioGroup nutritionRadioGroup; + HashMap nutritionRadioButtons = new HashMap<>(); + + RadioGroup dietTimeRadioGroup; + HashMap dietTimeRadioButtons = new HashMap<>(); + + RadioGroup sleepPatternRadioGroup; + HashMap sleepPatternRadioButtons = new HashMap<>(); + + RadioGroup painScoreRadioGroup; + HashMap painScoreRadioButtons = new HashMap<>(); + + Button submitButton; + ImageView carePlanMenuButton; + DatabaseReference carePlanRef; + String patientId; + + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + patientId = getIntent().getStringExtra("patientId"); + + // ADDED: Prevent invalid screen state if patientId is missing + if (patientId == null || patientId.isEmpty()) { + Toast.makeText(this, "Invalid patient", Toast.LENGTH_SHORT).show(); + finish(); + return; + } + + setContentView(R.layout.activity_care_plan); + + submitButton = findViewById(R.id.carePlanSubmitButton); + + final NavigationView navigationView = findViewById(R.id.nav_view); + carePlanMenuButton = findViewById(R.id.menuButton11); + final DrawerLayout drawerLayout = findViewById(R.id.drawer_layout); + navigationView.setItemIconTintList(null); + + carePlanMenuButton.setOnClickListener( + v -> { + drawerLayout.openDrawer(GravityCompat.START); + }); + + // careplan type + carePlanTypeRadioGroup = findViewById(R.id.carePlanTypeRGroup); + carePlanTypesRadioButtons.put((RadioButton) findViewById(R.id.radioButton2), "Home"); + carePlanTypesRadioButtons.put((RadioButton) findViewById(R.id.radioButton), "Hospital"); + + nutritionRadioGroup = findViewById(R.id.nutritionHydrationRGroup); + nutritionRadioButtons.put((RadioButton) findViewById(R.id.radioButton6), "Yes"); + nutritionRadioButtons.put((RadioButton) findViewById(R.id.radioButton7), "No"); + nutritionRadioButtons.put((RadioButton) findViewById(R.id.radioButton8), "NA"); + + dietTimeRadioGroup = findViewById(R.id.dietTimingRGroup); + dietTimeRadioButtons.put((RadioButton) findViewById(R.id.radioButton9), "8AM-BR"); + dietTimeRadioButtons.put((RadioButton) findViewById(R.id.radioButton5), "12PM-LN"); + dietTimeRadioButtons.put((RadioButton) findViewById(R.id.radioButton10), "6PM-DN"); + + sleepPatternRadioGroup = findViewById(R.id.sleepPatternsRGroup); + sleepPatternRadioButtons.put((RadioButton) findViewById(R.id.radioButton61), "10PM-6AM"); + sleepPatternRadioButtons.put((RadioButton) findViewById(R.id.radioButton71), "8PM-4AM"); + sleepPatternRadioButtons.put((RadioButton) findViewById(R.id.radioButton81), "11PM-7AM"); + + painScoreRadioGroup = findViewById(R.id.ratingGroup); + painScoreRadioButtons.put((RadioButton) findViewById(R.id.radioButton21), "1"); + painScoreRadioButtons.put((RadioButton) findViewById(R.id.radioButton22), "2"); + painScoreRadioButtons.put((RadioButton) findViewById(R.id.radioButton23), "3"); + painScoreRadioButtons.put((RadioButton) findViewById(R.id.radioButton24), "4"); + painScoreRadioButtons.put((RadioButton) findViewById(R.id.radioButton25), "5"); + painScoreRadioButtons.put((RadioButton) findViewById(R.id.radioButton26), "6"); + painScoreRadioButtons.put((RadioButton) findViewById(R.id.radioButton27), "7"); + painScoreRadioButtons.put((RadioButton) findViewById(R.id.radioButton28), "8"); + painScoreRadioButtons.put((RadioButton) findViewById(R.id.radioButton29), "9"); + painScoreRadioButtons.put((RadioButton) findViewById(R.id.radioButton30), "10"); + + // support requirements + supportRequirementsCheckBox.put((CheckBox) findViewById(R.id.selfCareCheckBox), "Self Care"); + supportRequirementsCheckBox.put((CheckBox) findViewById(R.id.walkingCheckBox), "Walking"); + supportRequirementsCheckBox.put((CheckBox) findViewById(R.id.activitiesCheckBox), "Activities"); + supportRequirementsCheckBox.put((CheckBox) findViewById(R.id.bathroomCheckBox), "Bathroom"); + supportRequirementsCheckBox.put((CheckBox) findViewById(R.id.shoppingCheckBox), "Shopping"); + + // drinks + drinkLikesCheckBox.put((CheckBox) findViewById(R.id.coffeeCheckBox), "Coffee"); + drinkLikesCheckBox.put((CheckBox) findViewById(R.id.teaCheckBox), "Tea"); + drinkLikesCheckBox.put((CheckBox) findViewById(R.id.waterCheckBox), "Water"); + + // pain + painCheckBox.put((CheckBox) findViewById(R.id.chronicCheckBox), "Chronic"); + painCheckBox.put((CheckBox) findViewById(R.id.massageRequiredCheckBox), "Massage Required"); + painCheckBox.put((CheckBox) findViewById(R.id.pillowSupportCheckBox), "Pillow Support"); + painCheckBox.put((CheckBox) findViewById(R.id.heatPackCheckBox), "Heat Pack"); + painCheckBox.put((CheckBox) findViewById(R.id.NAcheckBox), "NA"); + + // behavior + behavioralManagementCheckBox.put( + (CheckBox) findViewById(R.id.dollTherapyCheckBox), "Doll Therapy"); + behavioralManagementCheckBox.put( + (CheckBox) findViewById(R.id.petTherapyCheckBox), "Pet Therapy"); + behavioralManagementCheckBox.put( + (CheckBox) findViewById(R.id.dementiaCheckBox), "Dementia Management"); + behavioralManagementCheckBox.put( + (CheckBox) findViewById(R.id.lightsOnBedroomCB), "Lights on Bedroom"); + behavioralManagementCheckBox.put( + (CheckBox) findViewById(R.id.lightsOnBathroomCB), "Lights on Bathroom"); + + // Firebase initialization + FirebaseDatabase database = FirebaseDatabase.getInstance(); + carePlanRef = database.getReference("careplan"); + + // Load care plan summary data from Firebase + loadCarePlanDataForPatient(patientId); + + submitButton.setOnClickListener( + v -> { + // ADDED: Basic validation before confirmation + if (!validateInputs()) { + return; + } + + final AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext()); + builder.setTitle("Saving Changes?"); + // ADDED: Clearer confirmation message + builder.setMessage("Do you want to save this care plan?"); + builder.setPositiveButton( + "YES", + (dialog, whichButton) -> { + CarePlan updatedCarePlan = createUpdatedCarePlan(); + + // ADDED: Prevent repeated taps during save + submitButton.setEnabled(false); + + // Save the updated CarePlan to Firebase + saveCarePlanToFirebase(updatedCarePlan); + }); + builder.setNegativeButton("No", null); + + final AlertDialog dialog = builder.create(); + dialog.setOnShowListener( + arg0 -> { + dialog + .getButton(AlertDialog.BUTTON_POSITIVE) + .setTextColor(getResources().getColor(R.color.colorGreen)); + dialog + .getButton(AlertDialog.BUTTON_NEGATIVE) + .setTextColor(getResources().getColor(R.color.colorRed)); + }); + dialog.show(); + }); } - submitButton.setOnClickListener( - v -> { - final AlertDialog.Builder builder = - new AlertDialog.Builder(v.getContext()); // new AlertDialog.Builder(this); - builder.setTitle("Saving Changes?"); - builder.setPositiveButton( - "YES", - (dialog, whichButton) -> { - CarePlan updatedCarePlan = createUpdatedCarePlan(); - // Save the updated CarePlan to Firebase - saveCarePlanToFirebase(updatedCarePlan); - - // final Intent intent = - // new Intent(getApplicationContext(), - // CarePlanSummaryActivity.class); - // startActivity(intent); - }); - builder.setNegativeButton("No", null); - - final AlertDialog dialog = builder.create(); - dialog.setOnShowListener( - arg0 -> { - dialog - .getButton(AlertDialog.BUTTON_POSITIVE) - .setTextColor(getResources().getColor(R.color.colorGreen)); - dialog - .getButton(AlertDialog.BUTTON_NEGATIVE) - .setTextColor(getResources().getColor(R.color.colorRed)); - }); - dialog.show(); - }); - } - - private void loadCarePlanDataForPatient(final String patientId) { - DatabaseReference patientRef = carePlanRef.child(patientId); - patientRef.addListenerForSingleValueEvent( - new ValueEventListener() { - @Override - public void onDataChange(@NonNull DataSnapshot dataSnapshot) { - if (dataSnapshot.exists()) { - CarePlan carePlan = dataSnapshot.getValue(CarePlan.class); - if (carePlan != null) { - - String carePlanType = carePlan.carePlanType; - selectRadioButton(carePlanTypeRadioGroup, carePlanTypesRadioButtons, carePlanType); - - String nutriHydration = carePlan.nutritionHydration; - selectRadioButton(nutritionRadioGroup, nutritionRadioButtons, nutriHydration); - - String dietTime = carePlan.dietTimings; - selectRadioButton(dietTimeRadioGroup, dietTimeRadioButtons, dietTime); - - String sleepPattern = carePlan.sleepPattern; - selectRadioButton(sleepPatternRadioGroup, sleepPatternRadioButtons, sleepPattern); - - String painScore = String.valueOf(carePlan.painScore); - selectRadioButton(painScoreRadioGroup, painScoreRadioButtons, painScore); - - // Pre-fill support requirements checkboxes - for (CheckBox checkBox : supportRequirementsCheckBox.keySet()) { - String requirement = supportRequirementsCheckBox.get(checkBox); - if (carePlan.supportRequirement.contains(requirement)) { - checkBox.setChecked(true); - } - } - - // Pre-fill drink likes checkboxes - for (CheckBox checkBox : drinkLikesCheckBox.keySet()) { - String drink = drinkLikesCheckBox.get(checkBox); - if (carePlan.drinkLikings.contains(drink)) { - checkBox.setChecked(true); - } - } - - // Pre-fill pain checkboxes - for (CheckBox checkBox : painCheckBox.keySet()) { - String pain = painCheckBox.get(checkBox); - if (carePlan.painCategories.contains(pain)) { - checkBox.setChecked(true); - } - } - - // Pre-fill behavioral management checkboxes - for (CheckBox checkBox : behavioralManagementCheckBox.keySet()) { - String behavior = behavioralManagementCheckBox.get(checkBox); - if (carePlan.behavioralManagement.contains(behavior)) { - checkBox.setChecked(true); - } - } - } - } - } - - @Override - public void onCancelled(@NonNull DatabaseError error) { - // Handle error - } - }); - } - - private String getSelectedRadioButtonValue( - RadioGroup radioGroup, HashMap radioButtons) { - int selectedId = radioGroup.getCheckedRadioButtonId(); - if (selectedId != -1) { - RadioButton radioButton = findViewById(selectedId); - return radioButtons.get(radioButton); + // ADDED: Simple validation to improve form flow + private boolean validateInputs() { + if (carePlanTypeRadioGroup.getCheckedRadioButtonId() == -1) { + Toast.makeText(this, "Please select care plan type", Toast.LENGTH_SHORT).show(); + return false; + } + return true; } - return null; - } - - private void selectRadioButton( - RadioGroup radioGroup, HashMap radioButtons, String selectedValue) { - for (RadioButton radioButton : radioButtons.keySet()) { - if (radioButtons.get(radioButton).equals(selectedValue)) { - radioGroup.check(radioButton.getId()); - break; - } + + private void loadCarePlanDataForPatient(final String patientId) { + DatabaseReference patientRef = carePlanRef.child(patientId); + patientRef.addListenerForSingleValueEvent( + new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + if (dataSnapshot.exists()) { + CarePlan carePlan = dataSnapshot.getValue(CarePlan.class); + if (carePlan != null) { + + String carePlanType = carePlan.carePlanType; + selectRadioButton(carePlanTypeRadioGroup, carePlanTypesRadioButtons, carePlanType); + + String nutriHydration = carePlan.nutritionHydration; + selectRadioButton(nutritionRadioGroup, nutritionRadioButtons, nutriHydration); + + String dietTime = carePlan.dietTimings; + selectRadioButton(dietTimeRadioGroup, dietTimeRadioButtons, dietTime); + + String sleepPattern = carePlan.sleepPattern; + selectRadioButton(sleepPatternRadioGroup, sleepPatternRadioButtons, sleepPattern); + + String painScore = String.valueOf(carePlan.painScore); + selectRadioButton(painScoreRadioGroup, painScoreRadioButtons, painScore); + + // Pre-fill support requirements checkboxes + for (CheckBox checkBox : supportRequirementsCheckBox.keySet()) { + String requirement = supportRequirementsCheckBox.get(checkBox); + if (carePlan.supportRequirement != null + && carePlan.supportRequirement.contains(requirement)) { + checkBox.setChecked(true); + } + } + + // Pre-fill drink likes checkboxes + for (CheckBox checkBox : drinkLikesCheckBox.keySet()) { + String drink = drinkLikesCheckBox.get(checkBox); + if (carePlan.drinkLikings != null && carePlan.drinkLikings.contains(drink)) { + checkBox.setChecked(true); + } + } + + // Pre-fill pain checkboxes + for (CheckBox checkBox : painCheckBox.keySet()) { + String pain = painCheckBox.get(checkBox); + if (carePlan.painCategories != null && carePlan.painCategories.contains(pain)) { + checkBox.setChecked(true); + } + } + + // Pre-fill behavioral management checkboxes + for (CheckBox checkBox : behavioralManagementCheckBox.keySet()) { + String behavior = behavioralManagementCheckBox.get(checkBox); + if (carePlan.behavioralManagement != null + && carePlan.behavioralManagement.contains(behavior)) { + checkBox.setChecked(true); + } + } + } + } + } + + @Override + public void onCancelled(@NonNull DatabaseError error) { + // IMPROVED: Show error to user + Toast.makeText(CarePlanActivity.this, "Failed to load care plan", Toast.LENGTH_SHORT) + .show(); + } + }); } - } - private CarePlan createUpdatedCarePlan() { - CarePlan carePlan = new CarePlan(); + private String getSelectedRadioButtonValue( + RadioGroup radioGroup, HashMap radioButtons) { + int selectedId = radioGroup.getCheckedRadioButtonId(); + if (selectedId != -1) { + RadioButton radioButton = findViewById(selectedId); + return radioButtons.get(radioButton); + } + return null; + } - // Set care plan type - carePlan.carePlanType = - getSelectedRadioButtonValue(carePlanTypeRadioGroup, carePlanTypesRadioButtons); + private void selectRadioButton( + RadioGroup radioGroup, HashMap radioButtons, String selectedValue) { + for (RadioButton radioButton : radioButtons.keySet()) { + if (radioButtons.get(radioButton).equals(selectedValue)) { + radioGroup.check(radioButton.getId()); + break; + } + } + } - // Set nutrition hydration - carePlan.nutritionHydration = - getSelectedRadioButtonValue(nutritionRadioGroup, nutritionRadioButtons); + private CarePlan createUpdatedCarePlan() { + CarePlan carePlan = new CarePlan(); - // Set diet timings - carePlan.dietTimings = getSelectedRadioButtonValue(dietTimeRadioGroup, dietTimeRadioButtons); + // Set care plan type + carePlan.carePlanType = + getSelectedRadioButtonValue(carePlanTypeRadioGroup, carePlanTypesRadioButtons); - // Set sleep pattern - carePlan.sleepPattern = - getSelectedRadioButtonValue(sleepPatternRadioGroup, sleepPatternRadioButtons); + // Set nutrition hydration + carePlan.nutritionHydration = + getSelectedRadioButtonValue(nutritionRadioGroup, nutritionRadioButtons); - // Set pain score - String painScore = getSelectedRadioButtonValue(painScoreRadioGroup, painScoreRadioButtons); - if (painScore != null) { - carePlan.painScore = Integer.parseInt(painScore); - } + // Set diet timings + carePlan.dietTimings = getSelectedRadioButtonValue(dietTimeRadioGroup, dietTimeRadioButtons); - // Set support requirements checkboxes - carePlan.supportRequirement = getCheckedItemsAsString(supportRequirementsCheckBox); + // Set sleep pattern + carePlan.sleepPattern = + getSelectedRadioButtonValue(sleepPatternRadioGroup, sleepPatternRadioButtons); - // Set drink likes checkboxes - carePlan.drinkLikings = getCheckedItemsAsString(drinkLikesCheckBox); + // Set pain score + String painScore = getSelectedRadioButtonValue(painScoreRadioGroup, painScoreRadioButtons); + if (painScore != null) { + carePlan.painScore = Integer.parseInt(painScore); + } - // Set pain checkboxes - carePlan.painCategories = getCheckedItemsAsString(painCheckBox); + // Set support requirements checkboxes + carePlan.supportRequirement = getCheckedItemsAsString(supportRequirementsCheckBox); - // Set behavioral management checkboxes - carePlan.behavioralManagement = getCheckedItemsAsString(behavioralManagementCheckBox); + // Set drink likes checkboxes + carePlan.drinkLikings = getCheckedItemsAsString(drinkLikesCheckBox); - return carePlan; - } + // Set pain checkboxes + carePlan.painCategories = getCheckedItemsAsString(painCheckBox); - private String getCheckedItemsAsString(HashMap checkBoxHashMap) { - StringBuilder stringBuilder = new StringBuilder(); - for (CheckBox checkBox : checkBoxHashMap.keySet()) { - if (checkBox.isChecked()) { - stringBuilder.append(checkBoxHashMap.get(checkBox)).append(", "); - } + // Set behavioral management checkboxes + carePlan.behavioralManagement = getCheckedItemsAsString(behavioralManagementCheckBox); + + return carePlan; } - // Remove trailing comma and space if any - if (stringBuilder.length() > 0) { - stringBuilder.setLength(stringBuilder.length() - 2); + + private String getCheckedItemsAsString(HashMap checkBoxHashMap) { + StringBuilder stringBuilder = new StringBuilder(); + for (CheckBox checkBox : checkBoxHashMap.keySet()) { + if (checkBox.isChecked()) { + stringBuilder.append(checkBoxHashMap.get(checkBox)).append(", "); + } + } + // Remove trailing comma and space if any + if (stringBuilder.length() > 0) { + stringBuilder.setLength(stringBuilder.length() - 2); + } + return stringBuilder.toString(); + } + + private void saveCarePlanToFirebase(CarePlan carePlan) { + // IMPROVED: Show success/failure feedback and re-enable button if needed + carePlanRef + .child(patientId) + .setValue(carePlan) + .addOnSuccessListener( + unused -> { + Toast.makeText(this, "Care plan saved successfully", Toast.LENGTH_SHORT).show(); + finish(); + }) + .addOnFailureListener( + e -> { + Toast.makeText(this, "Failed to save care plan", Toast.LENGTH_SHORT).show(); + submitButton.setEnabled(true); + }); } - return stringBuilder.toString(); - } - - private void saveCarePlanToFirebase(CarePlan carePlan) { - // Update care plan in Firebase - carePlanRef.child(patientId).setValue(carePlan); - } -} +} \ No newline at end of file diff --git a/app/src/main/java/deakin/gopher/guardian/view/patient/careplan/CarePlanSummaryActivity.java b/app/src/main/java/deakin/gopher/guardian/view/patient/careplan/CarePlanSummaryActivity.java index 6ceab1203..9f2a4fc85 100644 --- a/app/src/main/java/deakin/gopher/guardian/view/patient/careplan/CarePlanSummaryActivity.java +++ b/app/src/main/java/deakin/gopher/guardian/view/patient/careplan/CarePlanSummaryActivity.java @@ -1,7 +1,6 @@ package deakin.gopher.guardian.view.patient.careplan; import android.annotation.SuppressLint; -import android.content.Intent; import android.os.Bundle; import android.widget.Button; import android.widget.ImageView; @@ -12,27 +11,29 @@ import deakin.gopher.guardian.R; public class CarePlanSummaryActivity extends AppCompatActivity { - Button prevButton; - ImageView carePlanSummaryMenuButton; + Button prevButton; + ImageView carePlanSummaryMenuButton; - @SuppressLint("MissingInflatedId") - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_care_plan_summary); - prevButton = findViewById(R.id.carePlanPrevButton); + @SuppressLint("MissingInflatedId") + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_care_plan_summary); - prevButton.setOnClickListener( - view -> startActivity(new Intent(CarePlanSummaryActivity.this, CarePlanActivity.class))); + prevButton = findViewById(R.id.carePlanPrevButton); - final NavigationView navigationView = findViewById(R.id.nav_view); - carePlanSummaryMenuButton = findViewById(R.id.menuButton); - final DrawerLayout drawerLayout = findViewById(R.id.drawer_layout); - navigationView.setItemIconTintList(null); + // IMPROVED: Go back to previous screen instead of creating a new CarePlanActivity + prevButton.setOnClickListener(view -> finish()); - carePlanSummaryMenuButton.setOnClickListener( - v -> { - drawerLayout.openDrawer(GravityCompat.START); - }); - } -} + final NavigationView navigationView = findViewById(R.id.nav_view); + carePlanSummaryMenuButton = findViewById(R.id.menuButton); + final DrawerLayout drawerLayout = findViewById(R.id.drawer_layout); + navigationView.setItemIconTintList(null); + + // KEPT: Drawer open interaction + carePlanSummaryMenuButton.setOnClickListener( + v -> { + drawerLayout.openDrawer(GravityCompat.START); + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/deakin/gopher/guardian/view/patient/careplan/CarePlanSummaryActivityFragment.java b/app/src/main/java/deakin/gopher/guardian/view/patient/careplan/CarePlanSummaryActivityFragment.java index 2740d787b..88810c85e 100644 --- a/app/src/main/java/deakin/gopher/guardian/view/patient/careplan/CarePlanSummaryActivityFragment.java +++ b/app/src/main/java/deakin/gopher/guardian/view/patient/careplan/CarePlanSummaryActivityFragment.java @@ -2,6 +2,7 @@ import android.content.Intent; import android.os.Bundle; +import android.text.TextUtils; // ADDED import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -9,6 +10,7 @@ import android.widget.ImageView; import android.widget.RatingBar; import android.widget.TextView; +import android.widget.Toast; // ADDED import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; @@ -21,108 +23,134 @@ import deakin.gopher.guardian.model.CarePlan; public class CarePlanSummaryActivityFragment extends Fragment { - Button prevButton; - Button editButton; - ImageView carePlanSummaryMenuButton; - - // Firebase - DatabaseReference carePlanRef; - - TextView carePlanSummaryTextView; - TextView carePlanNutHyd; - TextView suppReq; - TextView dietTime; - TextView drinkLike; - TextView sleepPat; - TextView pain; - TextView behaveMng; - RatingBar ratingBar; - String patientId; - - View view; - - public CarePlanSummaryActivityFragment(final String patientId) { - this.patientId = patientId; - } - - @Nullable - @Override - public View onCreateView( - @NonNull LayoutInflater inflater, - @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - - view = inflater.inflate(R.layout.fragment_careplan_summary, container, false); - - editButton = view.findViewById(R.id.save); - carePlanSummaryTextView = view.findViewById(R.id.carePlanSummary); - carePlanNutHyd = view.findViewById(R.id.nutritionHydrationSummary); - suppReq = view.findViewById(R.id.supportReqSummary1); - dietTime = view.findViewById(R.id.dietTimingSummary); - drinkLike = view.findViewById(R.id.drinkLikesSummary); - sleepPat = view.findViewById(R.id.sleepPatternSummary); - pain = view.findViewById(R.id.painSummary); - ratingBar = view.findViewById(R.id.painRatingBarSummary); - behaveMng = view.findViewById(R.id.behaviouralManagement); - - // Set onClickListener for editButton - editButton.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - // Open CarePlanActivity - final CarePlanActivity carePlanActivity = new CarePlanActivity(); - final Intent intent = new Intent(getActivity(), carePlanActivity.getClass()); - intent.putExtra("patientId", patientId); - startActivity(intent); - } - }); - - // Firebase initialization - FirebaseDatabase database = FirebaseDatabase.getInstance(); - carePlanRef = database.getReference("careplan"); - // Load care plan summary data from Firebase - loadCarePlanDataForPatient(patientId); - return view; - } - - private void loadCarePlanDataForPatient(final String patientId) { - DatabaseReference patientRef = carePlanRef.child(patientId); - patientRef.addListenerForSingleValueEvent( - new ValueEventListener() { - @Override - public void onDataChange(@NonNull DataSnapshot dataSnapshot) { - if (dataSnapshot.exists()) { - CarePlan carePlan = dataSnapshot.getValue(CarePlan.class); - if (carePlan != null) { - carePlanSummaryTextView.setText(carePlan.carePlanType); - carePlanNutHyd.setText(carePlan.nutritionHydration); - suppReq.setText(carePlan.supportRequirement); - dietTime.setText(carePlan.dietTimings); - drinkLike.setText(carePlan.drinkLikings); - sleepPat.setText(carePlan.sleepPattern); - ratingBar.setRating((float) carePlan.painScore / 2); - behaveMng.setText(carePlan.behavioralManagement); - } - } else { - carePlanSummaryTextView.setText("Add new one"); - carePlanNutHyd.setVisibility(View.GONE); - suppReq.setVisibility(View.GONE); - dietTime.setVisibility(View.GONE); - drinkLike.setVisibility(View.GONE); - sleepPat.setVisibility(View.GONE); - } - } - - @Override - public void onCancelled(@NonNull DatabaseError error) { - // Handle error - } - }); - } - - // Interface to notify data load status - private interface OnDataLoadListener { - void onDataLoaded(boolean dataFound); - } -} + Button prevButton; + Button editButton; + ImageView carePlanSummaryMenuButton; + + // Firebase + DatabaseReference carePlanRef; + + TextView carePlanSummaryTextView; + TextView carePlanNutHyd; + TextView suppReq; + TextView dietTime; + TextView drinkLike; + TextView sleepPat; + TextView pain; + TextView behaveMng; + RatingBar ratingBar; + String patientId; + + View view; + + public CarePlanSummaryActivityFragment(final String patientId) { + this.patientId = patientId; + } + + @Nullable + @Override + public View onCreateView( + @NonNull LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + + view = inflater.inflate(R.layout.fragment_careplan_summary, container, false); + + editButton = view.findViewById(R.id.save); + carePlanSummaryTextView = view.findViewById(R.id.carePlanSummary); + carePlanNutHyd = view.findViewById(R.id.nutritionHydrationSummary); + suppReq = view.findViewById(R.id.supportReqSummary1); + dietTime = view.findViewById(R.id.dietTimingSummary); + drinkLike = view.findViewById(R.id.drinkLikesSummary); + sleepPat = view.findViewById(R.id.sleepPatternSummary); + pain = view.findViewById(R.id.painSummary); + ratingBar = view.findViewById(R.id.painRatingBarSummary); + behaveMng = view.findViewById(R.id.behaviouralManagement); + + // ADDED: Validate patientId before trying to load data + if (TextUtils.isEmpty(patientId)) { + Toast.makeText(getActivity(), "Invalid patient", Toast.LENGTH_SHORT).show(); + return view; + } + + // IMPROVED: Simplified edit navigation + editButton.setOnClickListener( + v -> { + Intent intent = new Intent(getActivity(), CarePlanActivity.class); + intent.putExtra("patientId", patientId); + startActivity(intent); + }); + + // Firebase initialization + FirebaseDatabase database = FirebaseDatabase.getInstance(); + carePlanRef = database.getReference("careplan"); + + // ADDED: Basic loading state + carePlanSummaryTextView.setText("Loading care plan..."); + + // Load care plan summary data from Firebase + loadCarePlanDataForPatient(patientId); + return view; + } + + private void loadCarePlanDataForPatient(final String patientId) { + DatabaseReference patientRef = carePlanRef.child(patientId); + patientRef.addListenerForSingleValueEvent( + new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + if (dataSnapshot.exists()) { + CarePlan carePlan = dataSnapshot.getValue(CarePlan.class); + if (carePlan != null) { + // IMPROVED: Use fallback text for null or empty values + carePlanSummaryTextView.setText(getSafeText(carePlan.carePlanType)); + carePlanNutHyd.setText(getSafeText(carePlan.nutritionHydration)); + suppReq.setText(getSafeText(carePlan.supportRequirement)); + dietTime.setText(getSafeText(carePlan.dietTimings)); + drinkLike.setText(getSafeText(carePlan.drinkLikings)); + sleepPat.setText(getSafeText(carePlan.sleepPattern)); + pain.setText(getSafeText(carePlan.painCategories)); + behaveMng.setText(getSafeText(carePlan.behavioralManagement)); + + // IMPROVED: Ensure rating is set safely + ratingBar.setRating((float) carePlan.painScore / 2); + } else { + showEmptyState(); + } + } else { + showEmptyState(); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError error) { + // ADDED: Show user-friendly error feedback + Toast.makeText(getActivity(), "Failed to load care plan", Toast.LENGTH_SHORT).show(); + showEmptyState(); + } + }); + } + + // ADDED: Reusable fallback for null/empty text values + private String getSafeText(String value) { + return TextUtils.isEmpty(value) ? "Not available" : value; + } + + // ADDED: Cleaner empty state handling + private void showEmptyState() { + carePlanSummaryTextView.setText("No care plan available"); + carePlanNutHyd.setText("Not available"); + suppReq.setText("Not available"); + dietTime.setText("Not available"); + drinkLike.setText("Not available"); + sleepPat.setText("Not available"); + pain.setText("Not available"); + behaveMng.setText("Not available"); + ratingBar.setRating(0); + } + + // Interface to notify data load status + private interface OnDataLoadListener { + void onDataLoaded(boolean dataFound); + } +} \ No newline at end of file diff --git a/app/src/main/java/deakin/gopher/guardian/view/patient/dailyreport/DailyReportActivity.java b/app/src/main/java/deakin/gopher/guardian/view/patient/dailyreport/DailyReportActivity.java index 44b42c62a..98e45bd29 100644 --- a/app/src/main/java/deakin/gopher/guardian/view/patient/dailyreport/DailyReportActivity.java +++ b/app/src/main/java/deakin/gopher/guardian/view/patient/dailyreport/DailyReportActivity.java @@ -1,40 +1,176 @@ package deakin.gopher.guardian.view.patient.dailyreport; +import android.content.Intent; import android.os.Bundle; +import android.widget.Button; +import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; +import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; import com.google.android.material.navigation.NavigationView; import deakin.gopher.guardian.R; + public class DailyReportActivity extends AppCompatActivity { - ImageView dailyReportMenuButton; + ImageView dailyReportMenuButton; + + DrawerLayout drawerLayout; + NavigationView navigationView; + + TextView usernameTextView; + TextView reportedByTextView; + + EditText progressNotesEditText; + + TextView urgentMedicalAttentionTextView; + TextView requiresHospitalisationTextView; + TextView notApplicableTextView; + TextView requiresHourlyAttentionTextView; + + Button submitButton; + + String patientId; + String patientName; + String selectedAlert = "Not Applicable"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_daily_report); + + drawerLayout = findViewById(R.id.drawer_layout); + navigationView = findViewById(R.id.nav_view); + dailyReportMenuButton = findViewById(R.id.menuButton11); + + usernameTextView = findViewById(R.id.username); + reportedByTextView = findViewById(R.id.save); + progressNotesEditText = findViewById(R.id.patientNnormal); + + urgentMedicalAttentionTextView = findViewById(R.id.urgentMedicalAttentionTextView); + requiresHospitalisationTextView = findViewById(R.id.requiresHospitalisationTextView); + notApplicableTextView = findViewById(R.id.notApplicableTextView); + requiresHourlyAttentionTextView = findViewById(R.id.requiresHourlyAttentionTextView); + + submitButton = findViewById(R.id.loginBtn); + + // ADDED: Keep original menu icon colours + navigationView.setItemIconTintList(null); + + // Open drawer when menu button is clicked + dailyReportMenuButton.setOnClickListener( + v -> drawerLayout.openDrawer(GravityCompat.START)); + + // Get patient data from intent + String patientNameExtra = getIntent().getStringExtra("patientName"); + patientId = getIntent().getStringExtra("patientId"); + + // ADDED: Safe handling for null or empty patient name + if (patientNameExtra != null && !patientNameExtra.isEmpty()) { + patientName = patientNameExtra.split(" ")[0]; + } else { + patientName = "Patient"; + } + + usernameTextView.setText(patientName); + + // ADDED: Dummy frontend data for now + reportedByTextView.setText("Nurse John"); + progressNotesEditText.setText("Patient is stable and doing well."); + + // ADDED: Default selected alert + highlightSelectedAlert(notApplicableTextView); + + // ADDED: Alert selection handling + urgentMedicalAttentionTextView.setOnClickListener(v -> { + selectedAlert = "Urgent Medical Attention"; + highlightSelectedAlert(urgentMedicalAttentionTextView); + showToast(selectedAlert); + }); + + requiresHospitalisationTextView.setOnClickListener(v -> { + selectedAlert = "Requires Hospitalisation"; + highlightSelectedAlert(requiresHospitalisationTextView); + showToast(selectedAlert); + }); + + notApplicableTextView.setOnClickListener(v -> { + selectedAlert = "Not Applicable"; + highlightSelectedAlert(notApplicableTextView); + showToast(selectedAlert); + }); + + requiresHourlyAttentionTextView.setOnClickListener(v -> { + selectedAlert = "Requires Hourly Attention"; + highlightSelectedAlert(requiresHourlyAttentionTextView); + showToast(selectedAlert); + }); + + // ADDED: Basic validation before submission + submitButton.setOnClickListener(v -> { + String notes = progressNotesEditText.getText().toString().trim(); + + if (notes.isEmpty()) { + Toast.makeText(this, "Please enter progress notes", Toast.LENGTH_SHORT).show(); + } else { + // IMPROVED: Show submitted values for demo feedback + Toast.makeText( + this, + "Daily Report Submitted\nAlert: " + selectedAlert, + Toast.LENGTH_SHORT + ).show(); + } + }); + + // ADDED: Navigation handling using actual menu ids + navigationView.setNavigationItemSelectedListener(item -> { + int id = item.getItemId(); + + if (id == R.id.nav_home) { + Toast.makeText(this, "Going to Home", Toast.LENGTH_SHORT).show(); + + // Uncomment when your Home activity is ready + // Intent intent = new Intent(DailyReportActivity.this, PatientHomeActivity.class); + // intent.putExtra("patientId", patientId); + // intent.putExtra("patientName", patientNameExtra); + // startActivity(intent); + + } else if (id == R.id.add_task) { + Toast.makeText(this, "Going to Add Task", Toast.LENGTH_SHORT).show(); + + // Uncomment when your Add Task activity is ready + // Intent intent = new Intent(DailyReportActivity.this, TaskAddActivity.class); + // intent.putExtra("patientId", patientId); + // intent.putExtra("patientName", patientNameExtra); + // startActivity(intent); - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_daily_report); + } else if (id == R.id.nav_signout) { + // ADDED: Placeholder sign out behaviour + Toast.makeText(this, "Signed Out", Toast.LENGTH_SHORT).show(); - final NavigationView navigationView = findViewById(R.id.nav_view); - dailyReportMenuButton = findViewById(R.id.menuButton11); - final DrawerLayout drawerLayout = findViewById(R.id.drawer_layout); - navigationView.setItemIconTintList(null); + // Add real sign out logic here later + } - dailyReportMenuButton.setOnClickListener( - v -> { - drawerLayout.openDrawer(GravityCompat.START); + drawerLayout.closeDrawer(GravityCompat.START); + return true; }); + } - final String patientNameExtra = getIntent().getStringExtra("patientName"); - final String patientName = patientNameExtra != null ? patientNameExtra.split(" ")[0] : ""; + // ADDED: Reusable toast method for cleaner code + private void showToast(String message) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); + } - final TextView usernameTextView = findViewById(R.id.username); + // ADDED: Simple visual feedback for selected alert + private void highlightSelectedAlert(TextView selectedTextView) { + urgentMedicalAttentionTextView.setAlpha(0.6f); + requiresHospitalisationTextView.setAlpha(0.6f); + notApplicableTextView.setAlpha(0.6f); + requiresHourlyAttentionTextView.setAlpha(0.6f); - /*if (null != patientName) { - usernameTextView.setText(patientName); - }*/ - } -} + selectedTextView.setAlpha(1.0f); + } +} \ No newline at end of file diff --git a/app/src/main/java/deakin/gopher/guardian/view/patient/dailyreport/DailyReportSummaryActivity.java b/app/src/main/java/deakin/gopher/guardian/view/patient/dailyreport/DailyReportSummaryActivity.java index 712605861..c464bd5fd 100644 --- a/app/src/main/java/deakin/gopher/guardian/view/patient/dailyreport/DailyReportSummaryActivity.java +++ b/app/src/main/java/deakin/gopher/guardian/view/patient/dailyreport/DailyReportSummaryActivity.java @@ -18,56 +18,74 @@ public class DailyReportSummaryActivity extends AppCompatActivity { - private final StringBuilder statuses = new StringBuilder(); - private long dateMs; - - ImageView dailyReportSummaryMenuButton; - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_daily_report_summary); - - final NavigationView navigationView = findViewById(R.id.nav_view); - dailyReportSummaryMenuButton = findViewById(R.id.menuButton101); - final DrawerLayout drawerLayout = findViewById(R.id.drawer_layout); - navigationView.setItemIconTintList(null); - - dailyReportSummaryMenuButton.setOnClickListener( - v -> { - drawerLayout.openDrawer(GravityCompat.START); - }); - - final TextView currentStatusSummary = findViewById(R.id.currentStatusSummary); - final TextView progressNotesSummary = findViewById(R.id.progressNotesSummary); - final CalendarView patientReportSummaryCalendarView = - findViewById(R.id.patientReportSummaryCalendarView); - - final Intent intent = getIntent(); - final String date = intent.getStringExtra(Util.DAILY_REPORT_DATE); - final String notes = intent.getStringExtra(Util.DAILY_REPORT_STATUS_NOTES); - final String[] statusList = intent.getStringArrayExtra(Util.DAILY_REPORT_STATUS_LIST); - if (null != statusList && 0 != statusList.length) { - for (int i = 0; i < statusList.length - 1; i++) { - statuses.append(statusList[i]).append("\n"); - } - statuses.append(statusList[statusList.length - 1]); - } + private final StringBuilder statuses = new StringBuilder(); + private long dateMs; - if (android.os.Build.VERSION_CODES.N <= android.os.Build.VERSION.SDK_INT) { - final SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()); + ImageView dailyReportSummaryMenuButton; - try { - final Date d; - d = formatter.parse(date); - dateMs = d.getTime(); - } catch (final ParseException e) { - e.printStackTrace(); - } - } + TextView currentStatusSummary; + TextView progressNotesSummary; + CalendarView patientReportSummaryCalendarView; + + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_daily_report_summary); + + final NavigationView navigationView = findViewById(R.id.nav_view); + final DrawerLayout drawerLayout = findViewById(R.id.drawer_layout); + dailyReportSummaryMenuButton = findViewById(R.id.menuButton101); + + currentStatusSummary = findViewById(R.id.currentStatusSummary); + progressNotesSummary = findViewById(R.id.progressNotesSummary); + patientReportSummaryCalendarView = findViewById(R.id.patientReportSummaryCalendarView); + + // ADDED: Keep original navigation icon colours + navigationView.setItemIconTintList(null); + + // Open drawer when menu button is clicked + dailyReportSummaryMenuButton.setOnClickListener( + v -> drawerLayout.openDrawer(GravityCompat.START)); - progressNotesSummary.setText(notes); - currentStatusSummary.setText(statuses); - patientReportSummaryCalendarView.setDate(dateMs); - } -} + final Intent intent = getIntent(); + final String date = intent.getStringExtra(Util.DAILY_REPORT_DATE); + final String notes = intent.getStringExtra(Util.DAILY_REPORT_STATUS_NOTES); + final String[] statusList = intent.getStringArrayExtra(Util.DAILY_REPORT_STATUS_LIST); + + // ADDED: Format selected status values for summary display + if (statusList != null && statusList.length > 0) { + for (int i = 0; i < statusList.length - 1; i++) { + statuses.append(statusList[i]).append("\n"); + } + statuses.append(statusList[statusList.length - 1]); + } else { + // ADDED: Fallback text when no statuses are passed + statuses.append("No status selected"); + } + + // IMPROVED: Safely parse date before updating CalendarView + if (date != null && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { + final SimpleDateFormat formatter = + new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()); + + try { + final Date parsedDate = formatter.parse(date); + if (parsedDate != null) { + dateMs = parsedDate.getTime(); + patientReportSummaryCalendarView.setDate(dateMs); + } + } catch (final ParseException e) { + e.printStackTrace(); + } + } + + // ADDED: Fallback text for missing notes + if (notes != null && !notes.isEmpty()) { + progressNotesSummary.setText(notes); + } else { + progressNotesSummary.setText("No progress notes available"); + } + + currentStatusSummary.setText(statuses.toString()); + } +} \ No newline at end of file