Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class PatientListAdapter(
private val onAssignNurseClick: ((Patient) -> Unit)? = null,
private val onDeleteClick: ((Patient) -> Unit)? = null,
) : RecyclerView.Adapter<PatientListAdapter.PatientViewHolder>() {

inner class PatientViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val nameText: TextView = itemView.findViewById(R.id.tvName)
val ageText: TextView = itemView.findViewById(R.id.tvAge)
Expand All @@ -31,9 +32,8 @@ class PatientListAdapter(
parent: ViewGroup,
viewType: Int,
): PatientViewHolder {
val view =
LayoutInflater.from(parent.context)
.inflate(R.layout.item_patient, parent, false)
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_patient, parent, false)
return PatientViewHolder(view)
}

Expand All @@ -42,18 +42,17 @@ class PatientListAdapter(
position: Int,
) {
val patient = patients[position]

holder.nameText.text = patient.fullname
holder.ageText.text = "Age: ${patient.age}"
holder.genderText.text = "Gender: ${
patient.gender.replaceFirstChar {
if (it.isLowerCase()) it.titlecase() else it.toString()
}
}"
holder.ageText.text = "${patient.age} years"
holder.genderText.text = patient.gender.replaceFirstChar {
if (it.isLowerCase()) it.titlecase() else it.toString()
}

// Load image using Glide
Glide.with(holder.itemView.context)
.load(patient.photoUrl)
.placeholder(R.drawable.profile)
.error(R.drawable.profile)
.circleCrop()
.into(holder.image)

Expand All @@ -71,10 +70,12 @@ class PatientListAdapter(
onAssignNurseClick?.invoke(patient)
true
}
R.id.action_delete -> { // Handle delete click

R.id.action_delete -> {
onDeleteClick?.invoke(patient)
true
}

else -> false
}
}
Expand All @@ -89,4 +90,4 @@ class PatientListAdapter(
patients = newPatients
notifyDataSetChanged()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,86 +38,124 @@ class PatientDetailsActivity : BaseActivity() {

if (currentUser.role == Role.Nurse) {
binding.toolbar.setBackgroundColor(getColor(R.color.TG_blue))
binding.containerPatientInfo.setBackgroundColor(getColor(R.color.TG_blue))
// binding.containerPatientInfo.setBackgroundColor(getColor(R.color.TG_blue))
}

val patient = intent.getSerializableExtra("patient") as Patient

// Set patient info views
binding.tvName.text = patient.fullname
binding.tvAge.text = "Age: ${patient.age}"
binding.tvDob.text = "Date of Birth: ${patient.dateOfBirth?.substringBefore("T")}"
binding.tvGender.text = "Gender: ${
patient.gender.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString()
}
}"

if (patient.healthConditions.isNotEmpty()) {
val formattedConditions =
patient.healthConditions.joinToString(", ") { condition ->
condition.split(" ").joinToString(" ") { word ->
word.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }
}
}
binding.tvHealthConditions.text = "Health Conditions: $formattedConditions"
} else {
binding.tvHealthConditions.text = "Health Conditions: No conditions listed"
val patient = intent.getSerializableExtra("patient") as? Patient
if (patient == null) {
showMessage("Patient details not available")
finish()
return
}

Glide.with(this)
.load(patient.photoUrl)
.placeholder(R.drawable.profile)
.circleCrop()
.into(binding.imagePatient)
bindPatientDetails(patient)

// Load the assigned nurses fragment dynamically and pass the nurses
val nursesFragment = PatientAssignedNursesFragment()
nursesFragment.setAssignedNurses(patient.assignedNurses ?: emptyList())
supportFragmentManager.beginTransaction()
.replace(R.id.fragmentAssignedNursesContainer, nursesFragment)
.commit()

// Setup RecyclerView for activity logs
activitiesAdapter = PatientActivityAdapter(emptyList())
binding.recyclerViewActivities.layoutManager = LinearLayoutManager(this)
binding.recyclerViewActivities.adapter = activitiesAdapter

fetchPatientActivities(patient.id)
}

@SuppressLint("SetTextI18n")
private fun bindPatientDetails(patient: Patient) {
val formattedGender = patient.gender.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString()
}

val dob = patient.dateOfBirth?.substringBefore("T") ?: "Not available"

val healthConditionsText =
if (!patient.healthConditions.isNullOrEmpty()) {
patient.healthConditions.joinToString(", ") { condition ->
condition.split(" ").joinToString(" ") { word ->
word.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString()
}
}
}
} else {
"No conditions listed"
}

binding.tvName.text = patient.fullname
binding.tvAge.text = "${patient.age} years"
binding.tvDob.text = "Date of Birth: $dob"
binding.tvGender.text = formattedGender
binding.tvHealthConditions.text = "Health Conditions: $healthConditionsText"

Glide.with(this)
.load(patient.photoUrl)
.placeholder(R.drawable.profile)
.error(R.drawable.profile)
.circleCrop()
.into(binding.imagePatient)
}

private fun fetchPatientActivities(patientId: String) {
val token = "Bearer ${SessionManager.getToken()}"

CoroutineScope(Dispatchers.IO).launch {
withContext(Dispatchers.Main) {
binding.progressBar.visibility = View.VISIBLE
binding.tvEmptyMessage.visibility = View.GONE
binding.recyclerViewActivities.visibility = View.VISIBLE
}
val response =
try {
deakin.gopher.guardian.services.api.ApiClient.apiService.getPatientActivities(token, patientId)
} catch (e: Exception) {
null
}
withContext(Dispatchers.Main) {
binding.progressBar.visibility = View.GONE

if (response?.isSuccessful == true) {
val activities = response.body()
if (!activities.isNullOrEmpty()) {
activitiesAdapter.updateData(activities)
binding.tvEmptyMessage.visibility = View.GONE
try {
val response = deakin.gopher.guardian.services.api.ApiClient
.apiService
.getPatientActivities(token, patientId)

withContext(Dispatchers.Main) {
binding.progressBar.visibility = View.GONE

if (response.isSuccessful) {
val activities = response.body()

if (!activities.isNullOrEmpty()) {
activitiesAdapter.updateData(activities)
binding.recyclerViewActivities.visibility = View.VISIBLE
binding.tvEmptyMessage.visibility = View.GONE
} else {
binding.recyclerViewActivities.visibility = View.GONE
binding.tvEmptyMessage.visibility = View.VISIBLE
binding.tvEmptyMessage.text = "No patient activities found"
}
} else {
val errorBody = response.errorBody()?.string()

val errorResponse: ApiErrorResponse? =
if (!errorBody.isNullOrBlank()) {
try {
Gson().fromJson(errorBody, ApiErrorResponse::class.java)
} catch (e: Exception) {
null
}
} else {
null
}

binding.recyclerViewActivities.visibility = View.GONE
binding.tvEmptyMessage.visibility = View.VISIBLE
binding.tvEmptyMessage.text = "Unable to load patient activities"

showMessage(errorResponse?.apiError ?: "Failed to load activities")
}
} else {
val errorBody = response?.errorBody()?.string()
val errorResponse =
try {
Gson().fromJson(errorBody, ApiErrorResponse::class.java)
} catch (ex: Exception) {
null
}
showMessage(errorResponse?.apiError ?: "Failed to load activities")
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
binding.progressBar.visibility = View.GONE
binding.recyclerViewActivities.visibility = View.GONE
binding.tvEmptyMessage.visibility = View.VISIBLE
binding.tvEmptyMessage.text = "Network error occurred"
showMessage("Network error occurred")
}
}
}
Expand All @@ -126,4 +164,4 @@ class PatientDetailsActivity : BaseActivity() {
private fun showMessage(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,41 +95,68 @@ class PatientListActivity : BaseActivity() {

private fun fetchPatients() {
val token = "Bearer ${SessionManager.getToken()}"

CoroutineScope(Dispatchers.IO).launch {
if (patientListAdapter.itemCount <= 0) {
withContext(Dispatchers.Main) {
withContext(Dispatchers.Main) {
if (patientListAdapter.itemCount <= 0) {
binding.progressBar.show()
}
binding.tvEmptyMessage.visibility = View.GONE
binding.recyclerViewPatients.visibility = View.VISIBLE
}
val response = ApiClient.apiService.getAssignedPatients(token)
withContext(Dispatchers.Main) {

try {
val response = ApiClient.apiService.getAssignedPatients(token)

withContext(Dispatchers.Main) {
binding.progressBar.hide()
}
if (response.isSuccessful) {
if (!response.body().isNullOrEmpty()) {
patientListAdapter.updateData(response.body()!!)
withContext(Dispatchers.Main) {

if (response.isSuccessful) {
val patients = response.body()

if (!patients.isNullOrEmpty()) {
patientListAdapter.updateData(patients)
binding.recyclerViewPatients.visibility = View.VISIBLE
binding.tvEmptyMessage.visibility = View.GONE
}
} else {
withContext(Dispatchers.Main) {
} else {
patientListAdapter.updateData(emptyList())
binding.recyclerViewPatients.visibility = View.GONE
binding.tvEmptyMessage.visibility = View.VISIBLE
binding.tvEmptyMessage.text = "No patients found"
}
} else {
patientListAdapter.updateData(emptyList())
binding.recyclerViewPatients.visibility = View.GONE
binding.tvEmptyMessage.visibility = View.VISIBLE
binding.tvEmptyMessage.text = "Unable to load patients"

val errorBody = response.errorBody()?.string()
val errorResponse =
if (!errorBody.isNullOrBlank()) {
try {
Gson().fromJson(errorBody, ApiErrorResponse::class.java)
} catch (e: Exception) {
null
}
} else {
null
}

showMessage(errorResponse?.apiError ?: response.message())
}
} else {
// Handle error
val errorResponse =
Gson().fromJson(
response.errorBody()?.string(),
ApiErrorResponse::class.java,
)
showMessage(errorResponse.apiError ?: response.message())
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
binding.progressBar.hide()
patientListAdapter.updateData(emptyList())
binding.recyclerViewPatients.visibility = View.GONE
binding.tvEmptyMessage.visibility = View.VISIBLE
binding.tvEmptyMessage.text = "Network error occurred"
showMessage("Network error occurred")
}
}
}
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
if (currentUser.organization != null) {
return false
Expand Down
Loading
Loading