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
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@
<activity
android:name=".view.general.TasksListActivity"
android:exported="false" />
<activity android:name=".view.patient.PatientLogsActivity"/>

<activity android:name=".ModulesActivity" />

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package deakin.gopher.guardian.adapter

import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import deakin.gopher.guardian.databinding.ItemPatientLogBinding
import deakin.gopher.guardian.model.PatientLog
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.TimeZone

class PatientLogAdapter(
private var logs: List<PatientLog>,
private val onDeleteClick: (PatientLog) -> Unit
) : RecyclerView.Adapter<PatientLogAdapter.ViewHolder>() {

inner class ViewHolder(val binding: ItemPatientLogBinding) :
RecyclerView.ViewHolder(binding.root)

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemPatientLogBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
return ViewHolder(binding)
}

override fun getItemCount() = logs.size

@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val log = logs[position]

holder.binding.title.text = log.title
holder.binding.description.text = log.description
holder.binding.meta.text =
"${log.createdBy.fullname} • ${formatDate(log.createdAt)}"

holder.binding.deleteBtn.setOnClickListener {
onDeleteClick(log)
}
}

fun updateData(newLogs: List<PatientLog>) {
logs = newLogs
notifyDataSetChanged()
}

private fun formatDate(dateString: String): String {

return try {

val inputFormat =
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())

inputFormat.timeZone = TimeZone.getTimeZone("UTC")

val outputFormat =
SimpleDateFormat("dd MMM yyyy, hh:mm a", Locale.getDefault())

val date = inputFormat.parse(dateString)

outputFormat.format(date!!)

} catch (e: Exception) {

dateString
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package deakin.gopher.guardian.model

data class CreatePatientLogRequest(
val patient: String,
val title: String,
val description: String
)
16 changes: 16 additions & 0 deletions app/src/main/java/deakin/gopher/guardian/model/PatientLog.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package deakin.gopher.guardian.model

data class PatientLog(
val _id: String,
val patient: String,
val title: String,
val description: String,
val createdBy: CreatedBy,
val createdAt: String
)

data class CreatedBy(
val _id: String,
val fullname: String,
val role: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import deakin.gopher.guardian.view.general.RegisterActivity
import deakin.gopher.guardian.view.general.Setting
import deakin.gopher.guardian.view.general.TaskAddActivity
import deakin.gopher.guardian.view.general.TasksListActivity
import deakin.gopher.guardian.view.patient.PatientLogsActivity

class NavigationService(val activity: Activity) {
fun toHomeScreenForRole(role: Role) {
Expand Down Expand Up @@ -74,6 +75,15 @@ class NavigationService(val activity: Activity) {
)
}

fun onPatientLogs() {
activity.startActivity(
Intent(
activity.applicationContext,
PatientLogsActivity::class.java
)
)
}

fun onSignOut() {
activity.startActivity(
Intent(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package deakin.gopher.guardian.services

class PatientLogService {
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package deakin.gopher.guardian.services.api
import deakin.gopher.guardian.model.AddPatientActivityResponse
import deakin.gopher.guardian.model.AddPatientResponse
import deakin.gopher.guardian.model.BaseModel
import deakin.gopher.guardian.model.CreatePatientLogRequest
import deakin.gopher.guardian.model.Patient
import deakin.gopher.guardian.model.PatientActivity
import deakin.gopher.guardian.model.register.AuthResponse
import deakin.gopher.guardian.model.register.RegisterRequest
import deakin.gopher.guardian.model.PatientLog
import okhttp3.MultipartBody
import okhttp3.RequestBody
import retrofit2.Call
Expand Down Expand Up @@ -91,4 +93,23 @@ interface ApiService {
@Header("Authorization") token: String,
@Path("id") patientId: String,
): Response<BaseModel>

//For Patient Logs
@GET("patient-logs/{patientId}")
suspend fun getPatientLogs(
@Header("Authorization") token: String,
@Path("patientId") patientId: String,
): Response<List<PatientLog>>

@POST("patient-logs")
suspend fun createPatientLog(
@Header("Authorization") token: String,
@Body log: CreatePatientLogRequest,
): Response<PatientLog>

@DELETE("patient-logs/{id}")
suspend fun deletePatientLog(
@Header("Authorization") token: String,
@Path("id") id: String,
): Response<BaseModel>
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
package deakin.gopher.guardian.view.general

import android.app.DatePickerDialog
import android.app.TimePickerDialog
import android.os.Bundle
import android.view.View
import android.widget.ArrayAdapter
import android.widget.Toast
import com.google.gson.Gson
import deakin.gopher.guardian.R
import deakin.gopher.guardian.databinding.ActivityAddPatientActivityBinding
import deakin.gopher.guardian.model.ApiErrorResponse
import deakin.gopher.guardian.model.CreatePatientLogRequest
import deakin.gopher.guardian.model.login.SessionManager
import deakin.gopher.guardian.services.api.ApiClient
import deakin.gopher.guardian.view.hide
Expand Down Expand Up @@ -57,48 +53,39 @@ class AddPatientLogActivity : BaseActivity() {
}

// Set default date and time
val calendar = Calendar.getInstance()
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val timeFormat = SimpleDateFormat("HH:mm", Locale.getDefault())

binding.txtDate.setText(dateFormat.format(calendar.time))
binding.txtTime.setText(timeFormat.format(calendar.time))

// Date picker dialog
binding.txtDate.setOnClickListener {
val dpd =
DatePickerDialog(
this,
{ _, year, month, dayOfMonth ->
calendar.set(year, month, dayOfMonth)
binding.txtDate.setText(dateFormat.format(calendar.time))
},
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH),
)
dpd.datePicker.maxDate = System.currentTimeMillis()
dpd.show()
}
// Keep current date/time visible but prevent editing
binding.txtDate.isFocusable = false
binding.txtDate.isClickable = false

binding.txtTime.isFocusable = false
binding.txtTime.isClickable = false

// Live updating current date and time
val handler = android.os.Handler(mainLooper)

val updateTimeRunnable = object : Runnable {

override fun run() {

val currentCalendar = Calendar.getInstance()

val currentDate =
SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
.format(currentCalendar.time)

val currentTime =
SimpleDateFormat("HH:mm:ss", Locale.getDefault())
.format(currentCalendar.time)

binding.txtDate.setText(currentDate)
binding.txtTime.setText(currentTime)

// Time picker dialog
binding.txtTime.setOnClickListener {
val tpd =
TimePickerDialog(this, { _, hour, minute ->
calendar.set(Calendar.HOUR_OF_DAY, hour)
calendar.set(Calendar.MINUTE, minute)
binding.txtTime.setText(
String.format(
Locale.getDefault(),
"%02d:%02d",
hour,
minute,
),
)
}, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), true)
tpd.show()
handler.postDelayed(this, 1000)
}
}

handler.post(updateTimeRunnable)

binding.txtReporter.setText(SessionManager.getCurrentUser().name)

binding.btnSave.setOnClickListener {
Expand All @@ -107,62 +94,75 @@ class AddPatientLogActivity : BaseActivity() {
}

private fun savePatientActivity() {
val activityType =

val title =
if (binding.txtActivityType.text.toString().trim() == "Other") {
binding.txtOtherActivity.text.toString().trim()
} else {
binding.txtActivityType.text.toString().trim()
}

if (activityType.trim().isEmpty()) {
showMessage(getString(R.string.validation_empty_activity_type))
val description = binding.txtComment.text.toString().trim()

if (title.isEmpty()) {
showMessage("Please enter title")
return
}

val date = binding.txtDate.text.toString()
val time = binding.txtTime.text.toString()
// Build ISO timestamp
val isoTimestamp = "${date}T$time:00Z"

val comments = binding.txtComment.text.toString().trim()
if (description.isEmpty()) {
showMessage("Please enter description")
return
}

val patientId = intent.getStringExtra("patientId").orEmpty()
val token = "Bearer ${SessionManager.getToken()}"

val request = CreatePatientLogRequest(
patient = patientId,
title = title,
description = description
)

CoroutineScope(Dispatchers.IO).launch {

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

val response =
ApiClient.apiService.logPatientActivity(
token,
patientId,
activityType,
isoTimestamp,
comments,
try {

val response = ApiClient.apiService.createPatientLog(
"Bearer ${SessionManager.getToken()}",
request
)

withContext(Dispatchers.Main) {
withContext(Dispatchers.Main) {

binding.progressBar.hide()
binding.btnSave.visibility = View.VISIBLE
}
if (response.isSuccessful) {
if (response.body() != null) {
showMessage(response.body()?.apiMessage ?: response.message())
onBackPressedDispatcher.onBackPressed()

if (response.isSuccessful) {

showMessage("Log created successfully")

finish()

} else {
showMessage(response.body()?.apiError ?: "Failed to add patient activity")
}
} else {
// Handle error
val errorResponse =
Gson().fromJson(
response.errorBody()?.string(),
ApiErrorResponse::class.java,

showMessage(
response.errorBody()?.string() ?: "Failed to create log"
)
showMessage(errorResponse.apiError ?: response.message())
}
}

} catch (e: Exception) {

withContext(Dispatchers.Main) {

binding.progressBar.hide()
binding.btnSave.visibility = View.VISIBLE

showMessage(e.message ?: "Unknown error")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,17 @@ class Homepage4nurse : AppCompatActivity() {
val patientsButton: Button = findViewById(R.id.patientsButton_nurse)
val settingsButton: Button = findViewById(R.id.settingsButton_nurse)
val signOutButton: Button = findViewById(R.id.sighOutButton_nurse)
val logsButton: Button = findViewById(R.id.logsButton_nurse)


patientsButton.setOnClickListener {
NavigationService(this).onLaunchPatientList()
}

logsButton.setOnClickListener {
NavigationService(this).onPatientLogs()
}

// settings button
settingsButton.setOnClickListener {
NavigationService(this).onSettings()
Expand Down
Loading
Loading