expandable attendance list bug fix
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
package `in`.sminnovations.smiadmin.ui.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.cardview.widget.CardView
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import `in`.sminnovations.smiadmin.R
|
||||
import `in`.sminnovations.smiadmin.data.AttendanceData
|
||||
@@ -33,31 +35,45 @@ class AttendanceAdapter : RecyclerView.Adapter<AttendanceAdapter.ViewHolder>() {
|
||||
// Clear previous views
|
||||
holder.checkInsLayout.removeAllViews()
|
||||
|
||||
// Create check-in/check-out pairs dynamically
|
||||
val context = holder.itemView.context
|
||||
for (i in 1..attendance.checkIns.size) {
|
||||
val checkInKey = "checkIn$i"
|
||||
val checkOutKey = "checkOut$i"
|
||||
|
||||
if (attendance.checkIns.containsKey(checkInKey)) {
|
||||
val pairLayout = LayoutInflater.from(context)
|
||||
.inflate(R.layout.item_checkin_checkout_pair, holder.checkInsLayout, false)
|
||||
|
||||
val checkInView = pairLayout.findViewById<TextView>(R.id.textViewCheckIn)
|
||||
val checkOutView = pairLayout.findViewById<TextView>(R.id.textViewCheckOut)
|
||||
|
||||
checkInView.text = "Check In: ${attendance.checkIns[checkInKey]}"
|
||||
checkOutView.text = "Check Out: ${attendance.checkOuts[checkOutKey] ?: "Pending"}"
|
||||
|
||||
holder.checkInsLayout.addView(pairLayout)
|
||||
}
|
||||
}
|
||||
// Display all attendance records
|
||||
displayAttendanceRecords(holder.itemView.context, holder, attendance)
|
||||
|
||||
// Set up expansion/collapse
|
||||
holder.expandableLayout.visibility = if (attendance.isExpanded) View.VISIBLE else View.GONE
|
||||
holder.expandableLayout.apply {
|
||||
visibility = if (attendance.isExpanded) View.VISIBLE else View.GONE
|
||||
// Add animation for smooth expansion/collapse
|
||||
alpha = if (attendance.isExpanded) 1.0f else 0.0f
|
||||
animate()
|
||||
.alpha(if (attendance.isExpanded) 1.0f else 0.0f)
|
||||
.setDuration(200)
|
||||
.start()
|
||||
}
|
||||
|
||||
holder.cardView.setOnClickListener {
|
||||
attendance.isExpanded = !attendance.isExpanded
|
||||
// Toggle expansion state
|
||||
val wasExpanded = attendance.isExpanded
|
||||
attendance.isExpanded = !wasExpanded
|
||||
|
||||
// Animate the change
|
||||
if (!wasExpanded) {
|
||||
holder.expandableLayout.visibility = View.VISIBLE
|
||||
holder.expandableLayout.alpha = 0.0f
|
||||
holder.expandableLayout.animate()
|
||||
.alpha(1.0f)
|
||||
.setDuration(200)
|
||||
.start()
|
||||
} else {
|
||||
holder.expandableLayout.animate()
|
||||
.alpha(0.0f)
|
||||
.setDuration(200)
|
||||
.withEndAction {
|
||||
if (!attendance.isExpanded) {
|
||||
holder.expandableLayout.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
.start()
|
||||
}
|
||||
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
@@ -65,16 +81,114 @@ class AttendanceAdapter : RecyclerView.Adapter<AttendanceAdapter.ViewHolder>() {
|
||||
override fun getItemCount() = attendanceList.size
|
||||
|
||||
fun updateAttendance(newAttendance: List<AttendanceData>) {
|
||||
val diffCallback = AttendanceDiffCallback(attendanceList, newAttendance)
|
||||
val diffResult = DiffUtil.calculateDiff(diffCallback)
|
||||
|
||||
attendanceList.clear()
|
||||
// Convert date string to comparable format and sort
|
||||
attendanceList.addAll(newAttendance.sortedByDescending {
|
||||
// Convert dd-MM-yyyy to comparable format
|
||||
val parts = it.date.split("-")
|
||||
val day = parts[0].toInt()
|
||||
val month = parts[1].toInt()
|
||||
val year = parts[2].toInt()
|
||||
String.format("%04d%02d%02d", year, month, day)
|
||||
})
|
||||
notifyDataSetChanged()
|
||||
attendanceList.addAll(newAttendance.sortedByDescending { it.getComparableDate() })
|
||||
|
||||
diffResult.dispatchUpdatesTo(this)
|
||||
}
|
||||
|
||||
private fun displayAttendanceRecords(
|
||||
context: Context,
|
||||
holder: ViewHolder,
|
||||
attendance: AttendanceData
|
||||
) {
|
||||
// Create a set of all unique check-in keys
|
||||
val allCheckInKeys = attendance.checkIns.keys
|
||||
|
||||
// Handle numbered check-ins
|
||||
for (i in 1..attendance.checkIns.size) {
|
||||
val checkInKey = "checkIn$i"
|
||||
val checkOutKey = "checkOut$i"
|
||||
|
||||
if (attendance.checkIns.containsKey(checkInKey)) {
|
||||
addCheckInPair(
|
||||
context,
|
||||
holder,
|
||||
checkInKey,
|
||||
checkOutKey,
|
||||
attendance.checkIns[checkInKey]!!,
|
||||
attendance.checkOuts[checkOutKey]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle non-numbered check-ins
|
||||
allCheckInKeys
|
||||
.filter { !it.matches(Regex("checkIn\\d+")) }
|
||||
.forEach { checkInKey ->
|
||||
val baseKey = checkInKey.replace("checkIn", "")
|
||||
val checkOutKey = "checkOut$baseKey"
|
||||
|
||||
addCheckInPair(
|
||||
context,
|
||||
holder,
|
||||
checkInKey,
|
||||
checkOutKey,
|
||||
attendance.checkIns[checkInKey]!!,
|
||||
attendance.checkOuts[checkOutKey]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addCheckInPair(
|
||||
context: Context,
|
||||
holder: ViewHolder,
|
||||
checkInKey: String,
|
||||
checkOutKey: String,
|
||||
checkInValue: String,
|
||||
checkOutValue: String?
|
||||
) {
|
||||
val pairLayout = LayoutInflater.from(context)
|
||||
.inflate(R.layout.item_checkin_checkout_pair, holder.checkInsLayout, false)
|
||||
|
||||
val checkInView = pairLayout.findViewById<TextView>(R.id.textViewCheckIn)
|
||||
val checkOutView = pairLayout.findViewById<TextView>(R.id.textViewCheckOut)
|
||||
|
||||
// Display the original key name for non-standard keys
|
||||
val checkInLabel = if (checkInKey.matches(Regex("checkIn\\d+"))) {
|
||||
"Check In"
|
||||
} else {
|
||||
"Check In (${checkInKey.replace("checkIn", "")})"
|
||||
}
|
||||
|
||||
val checkOutLabel = if (checkOutKey.matches(Regex("checkOut\\d+"))) {
|
||||
"Check Out"
|
||||
} else {
|
||||
"Check Out (${checkOutKey.replace("checkOut", "")})"
|
||||
}
|
||||
|
||||
checkInView.text = "$checkInLabel: $checkInValue"
|
||||
checkOutView.text = "$checkOutLabel: ${checkOutValue ?: "Pending"}"
|
||||
|
||||
holder.checkInsLayout.addView(pairLayout)
|
||||
}
|
||||
}
|
||||
|
||||
// DiffUtil callback for efficient updates
|
||||
private class AttendanceDiffCallback(
|
||||
private val oldList: List<AttendanceData>,
|
||||
private val newList: List<AttendanceData>
|
||||
) : DiffUtil.Callback() {
|
||||
override fun getOldListSize() = oldList.size
|
||||
override fun getNewListSize() = newList.size
|
||||
|
||||
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
||||
return oldList[oldItemPosition].date == newList[newItemPosition].date
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
||||
return oldList[oldItemPosition] == newList[newItemPosition]
|
||||
}
|
||||
}
|
||||
|
||||
// Extension function for AttendanceData to get comparable date
|
||||
private fun AttendanceData.getComparableDate(): String {
|
||||
val parts = date.split("-")
|
||||
val day = parts[0].toInt()
|
||||
val month = parts[1].toInt()
|
||||
val year = parts[2].toInt()
|
||||
return String.format("%04d%02d%02d", year, month, day)
|
||||
}
|
||||
Reference in New Issue
Block a user