diff --git a/app/src/main/java/deakin/gopher/guardian/view/general/AddNewPatientActivity.kt b/app/src/main/java/deakin/gopher/guardian/view/general/AddNewPatientActivity.kt
index df96346ac..f188a993b 100644
--- a/app/src/main/java/deakin/gopher/guardian/view/general/AddNewPatientActivity.kt
+++ b/app/src/main/java/deakin/gopher/guardian/view/general/AddNewPatientActivity.kt
@@ -8,8 +8,11 @@ import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
+import android.text.InputFilter
import android.view.View
import android.widget.ArrayAdapter
+import android.widget.CheckBox
+import android.widget.ImageView
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ActivityCompat
@@ -46,30 +49,38 @@ class AddNewPatientActivity : BaseActivity() {
private const val CAMERA_PERMISSION_CODE = 1001
}
- // Launcher for picking image from gallery
private val galleryLauncher =
registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
if (uri != null) {
selectedPhotoUri = uri
capturedPhotoBitmap = null
- val localBinding = binding
- when (localBinding) {
- is ActivityAddNewPatientBinding -> localBinding.imgPreview.setImageURI(uri)
- is ActivityAddNewPatientNurseBinding -> localBinding.imgPreview.setImageURI(uri)
+
+ when (val localBinding = binding) {
+ is ActivityAddNewPatientBinding -> {
+ localBinding.imgPreview.setImageURI(uri)
+ localBinding.checkNoPhoto.isChecked = false
+ }
+ is ActivityAddNewPatientNurseBinding -> {
+ localBinding.imgPreview.setImageURI(uri)
+ }
}
}
}
- // Launcher for taking photo with camera (returns Bitmap)
private val cameraLauncher =
registerForActivityResult(ActivityResultContracts.TakePicturePreview()) { bitmap: Bitmap? ->
if (bitmap != null) {
capturedPhotoBitmap = bitmap
selectedPhotoUri = null
- val localBinding = binding
- when (localBinding) {
- is ActivityAddNewPatientBinding -> localBinding.imgPreview.setImageBitmap(bitmap)
- is ActivityAddNewPatientNurseBinding -> localBinding.imgPreview.setImageBitmap(bitmap)
+
+ when (val localBinding = binding) {
+ is ActivityAddNewPatientBinding -> {
+ localBinding.imgPreview.setImageBitmap(bitmap)
+ localBinding.checkNoPhoto.isChecked = false
+ }
+ is ActivityAddNewPatientNurseBinding -> {
+ localBinding.imgPreview.setImageBitmap(bitmap)
+ }
}
}
}
@@ -89,8 +100,7 @@ class AddNewPatientActivity : BaseActivity() {
setContentView(caretakerBinding.root)
}
- val localBinding = binding
- when (localBinding) {
+ when (val localBinding = binding) {
is ActivityAddNewPatientBinding -> {
setSupportActionBar(localBinding.toolbar)
localBinding.toolbar.setNavigationOnClickListener {
@@ -108,19 +118,27 @@ class AddNewPatientActivity : BaseActivity() {
}
}
- // Common UI setup for both bindings
private fun setupUI(localBinding: ViewBinding) {
when (localBinding) {
is ActivityAddNewPatientBinding -> {
setupGenderSpinner(localBinding.genderSpinner)
setupDOBPicker(localBinding.txtDob)
+ setupNameValidation(localBinding.txtName)
+ setupNoPhotoCheckbox(
+ localBinding.checkNoPhoto,
+ localBinding.btnSelectFromGallery,
+ localBinding.btnTakePhoto,
+ localBinding.imgPreview
+ )
localBinding.btnSelectFromGallery.setOnClickListener { openGallery() }
localBinding.btnTakePhoto.setOnClickListener { checkCameraPermissionAndOpen() }
localBinding.btnSave.setOnClickListener { savePatientInfo() }
}
+
is ActivityAddNewPatientNurseBinding -> {
setupGenderSpinner(localBinding.genderSpinner)
setupDOBPicker(localBinding.txtDob)
+ setupNameValidation(localBinding.txtName)
localBinding.btnSelectFromGallery.setOnClickListener { openGallery() }
localBinding.btnTakePhoto.setOnClickListener { checkCameraPermissionAndOpen() }
localBinding.btnSave.setOnClickListener { savePatientInfo() }
@@ -128,6 +146,40 @@ class AddNewPatientActivity : BaseActivity() {
}
}
+ private fun setupNoPhotoCheckbox(
+ checkBox: CheckBox,
+ galleryButton: View,
+ cameraButton: View,
+ imageView: ImageView,
+ ) {
+ checkBox.setOnCheckedChangeListener { _, isChecked ->
+ galleryButton.isEnabled = !isChecked
+ cameraButton.isEnabled = !isChecked
+
+ galleryButton.alpha = if (isChecked) 0.5f else 1f
+ cameraButton.alpha = if (isChecked) 0.5f else 1f
+
+ if (isChecked) {
+ selectedPhotoUri = null
+ capturedPhotoBitmap = null
+ imageView.setImageResource(R.drawable.profile)
+ }
+ }
+ }
+
+ private fun setupNameValidation(txtName: android.widget.EditText) {
+ txtName.filters = arrayOf(
+ InputFilter { source, _, _, _, _, _ ->
+ if (source.any { it.isDigit() }) {
+ showMessage("Name should not contain numbers")
+ ""
+ } else {
+ null
+ }
+ },
+ )
+ }
+
private fun setupGenderSpinner(genderSpinner: android.widget.Spinner) {
val genderOptions = listOf("Select gender", "Male", "Female", "Other")
val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, genderOptions)
@@ -156,13 +208,23 @@ class AddNewPatientActivity : BaseActivity() {
selectedDay,
)
txtDob.setText(formattedDate)
+
+ val age = calculateAge(selectedYear, selectedMonth, selectedDay)
+
+ when (val localBinding = binding) {
+ is ActivityAddNewPatientBinding -> {
+ localBinding.txtAge.setText(age.toString())
+ }
+ is ActivityAddNewPatientNurseBinding -> {
+ localBinding.txtAge.setText(age.toString())
+ }
+ }
},
year,
month,
day,
)
- // Force spinner mode (for API 21+)
try {
val datePickerField = datePickerDialog.datePicker.javaClass.getDeclaredField("mDelegate")
datePickerField.isAccessible = true
@@ -171,7 +233,7 @@ class AddNewPatientActivity : BaseActivity() {
val spinnerDelegateClass = Class.forName("android.widget.DatePickerSpinnerDelegate")
if (delegate.javaClass != spinnerDelegateClass) {
- datePickerField.set(datePickerDialog.datePicker, null) // Clear the current delegate
+ datePickerField.set(datePickerDialog.datePicker, null)
val constructor =
datePickerDialog.datePicker.javaClass.getDeclaredConstructor(
@@ -191,11 +253,10 @@ class AddNewPatientActivity : BaseActivity() {
)
datePickerField.set(datePickerDialog.datePicker, spinnerDelegate)
- // Re-initialize the date picker with current date
datePickerDialog.datePicker.updateDate(year, month, day)
}
} catch (e: Exception) {
- e.printStackTrace() // Fallback gracefully if reflection fails
+ e.printStackTrace()
}
datePickerDialog.datePicker.maxDate = System.currentTimeMillis()
@@ -203,7 +264,6 @@ class AddNewPatientActivity : BaseActivity() {
}
}
- // Permission check before opening camera
private fun checkCameraPermissionAndOpen() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED
@@ -225,7 +285,7 @@ class AddNewPatientActivity : BaseActivity() {
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == CAMERA_PERMISSION_CODE) {
- if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
+ if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
openCamera()
} else {
showMessage("Camera permission is required to take photos")
@@ -272,9 +332,25 @@ class AddNewPatientActivity : BaseActivity() {
val genderPart = gender.toRequestBody("text/plain".toMediaTypeOrNull())
val photoPart: MultipartBody.Part? =
- when {
- selectedPhotoUri != null -> prepareFilePart("photo", selectedPhotoUri!!, this)
- capturedPhotoBitmap != null -> prepareBitmapPart("photo", capturedPhotoBitmap!!)
+ when (localBinding) {
+ is ActivityAddNewPatientBinding -> {
+ if (localBinding.checkNoPhoto.isChecked) {
+ null
+ } else {
+ when {
+ selectedPhotoUri != null -> prepareFilePart("photo", selectedPhotoUri!!, this)
+ capturedPhotoBitmap != null -> prepareBitmapPart("photo", capturedPhotoBitmap!!)
+ else -> null
+ }
+ }
+ }
+ is ActivityAddNewPatientNurseBinding -> {
+ when {
+ selectedPhotoUri != null -> prepareFilePart("photo", selectedPhotoUri!!, this)
+ capturedPhotoBitmap != null -> prepareBitmapPart("photo", capturedPhotoBitmap!!)
+ else -> null
+ }
+ }
else -> null
}
@@ -331,33 +407,52 @@ class AddNewPatientActivity : BaseActivity() {
val localBinding = binding
return when (localBinding) {
is ActivityAddNewPatientBinding -> {
- if (localBinding.txtName.text.toString().trim().isEmpty()) {
- showMessage(getString(R.string.validation_empty_name))
+ val name = localBinding.txtName.text.toString().trim()
+
+ if (name.isEmpty()) {
+ showMessage("Please enter full name")
+ false
+ } else if (name.any { it.isDigit() }) {
+ showMessage("Name should not contain numbers")
false
} else if (localBinding.txtDob.text.toString().trim().isEmpty()) {
- showMessage(getString(R.string.validation_empty_dob))
+ showMessage("Please select date of birth")
false
} else if (localBinding.genderSpinner.selectedItemPosition == 0) {
- showMessage(getString(R.string.validation_empty_gender))
+ showMessage("Please select gender")
+ false
+ } else if (
+ !localBinding.checkNoPhoto.isChecked &&
+ selectedPhotoUri == null &&
+ capturedPhotoBitmap == null
+ ) {
+ showMessage("Please upload photo or tick 'No photo available'")
false
} else {
true
}
}
+
is ActivityAddNewPatientNurseBinding -> {
- if (localBinding.txtName.text.toString().trim().isEmpty()) {
- showMessage(getString(R.string.validation_empty_name))
+ val name = localBinding.txtName.text.toString().trim()
+
+ if (name.isEmpty()) {
+ showMessage("Please enter full name")
+ false
+ } else if (name.any { it.isDigit() }) {
+ showMessage("Name should not contain numbers")
false
} else if (localBinding.txtDob.text.toString().trim().isEmpty()) {
- showMessage(getString(R.string.validation_empty_dob))
+ showMessage("Please select date of birth")
false
} else if (localBinding.genderSpinner.selectedItemPosition == 0) {
- showMessage(getString(R.string.validation_empty_gender))
+ showMessage("Please select gender")
false
} else {
true
}
}
+
else -> false
}
}
@@ -374,12 +469,13 @@ class AddNewPatientActivity : BaseActivity() {
val today = Calendar.getInstance()
val birthDate = Calendar.getInstance()
birthDate.set(year, month, day)
+
var age = today.get(Calendar.YEAR) - birthDate.get(Calendar.YEAR)
- // If birthday hasn't happened yet this year, subtract one
if (today.get(Calendar.DAY_OF_YEAR) < birthDate.get(Calendar.DAY_OF_YEAR)) {
age--
}
+
return age
}
@@ -406,4 +502,4 @@ class AddNewPatientActivity : BaseActivity() {
val requestFile = byteArray.toRequestBody("image/jpeg".toMediaTypeOrNull())
return MultipartBody.Part.createFormData(partName, "profile.jpg", requestFile)
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_add_new_patient.xml b/app/src/main/res/layout/activity_add_new_patient.xml
index b4e68527a..f5e184411 100644
--- a/app/src/main/res/layout/activity_add_new_patient.xml
+++ b/app/src/main/res/layout/activity_add_new_patient.xml
@@ -9,7 +9,6 @@
android:background="@color/white"
tools:context="deakin.gopher.guardian.view.general.AddNewPatientActivity">
-
-
-
-
-
-
-
-
+ app:iconTint="@color/purple_700" />
-
-
+ app:iconTint="@color/purple_700" />
-
+
-
+ android:spinnerMode="dropdown" />
-
+ app:cornerRadius="8dp" />
-
-
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_homepage4doctor.xml b/app/src/main/res/layout/activity_homepage4doctor.xml
index 6e7936f35..941f0d871 100644
--- a/app/src/main/res/layout/activity_homepage4doctor.xml
+++ b/app/src/main/res/layout/activity_homepage4doctor.xml
@@ -1,29 +1,118 @@
-
-
-
+
+
+
+ app:layout_constraintEnd_toEndOf="parent">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:layout_width="120dp"
+ android:layout_height="120dp"
+ android:layout_marginStart="204dp"
+ android:layout_marginTop="300dp"
+ android:backgroundTint="#156A80"
+ android:text="Log Out"
+ android:textColor="#FFFFFF"
+ app:layout_constraintTop_toBottomOf="@id/headerCard"
+ app:layout_constraintStart_toStartOf="parent"/>
-
+
\ No newline at end of file