homeVM
This commit is contained in:
@@ -9,10 +9,11 @@ import com.google.firebase.Timestamp
|
||||
import com.google.firebase.firestore.DocumentSnapshot
|
||||
import com.google.firebase.firestore.FirebaseFirestore
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import `in`.sminnovations.attendanceapp.main.AppUpdater
|
||||
import `in`.sminnovations.attendanceapp.main.NetworkMonitor
|
||||
import `in`.sminnovations.attendanceapp.main.UpdateChecker
|
||||
import `in`.sminnovations.attendanceapp.main.UpdateInfo
|
||||
import `in`.sminnovations.attendanceapp.utils.AppUpdater
|
||||
import `in`.sminnovations.attendanceapp.utils.NetworkMonitor
|
||||
import `in`.sminnovations.attendanceapp.utils.UpdateInfo
|
||||
import `in`.sminnovations.attendanceapp.screens.home.data.AttendanceUiState
|
||||
import `in`.sminnovations.attendanceapp.utils.UpdateChecker
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
@@ -27,7 +28,6 @@ import java.time.format.DateTimeFormatter
|
||||
import java.time.temporal.ChronoUnit
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
||||
@@ -154,19 +154,17 @@ class HomeViewModel @Inject constructor(
|
||||
processQRCode(value)
|
||||
}
|
||||
}
|
||||
|
||||
private fun processQRCode(userId: String) {
|
||||
private fun processQRCode(userId: String) {
|
||||
if (userId.isBlank()) return
|
||||
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
setLoading(true)
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
errorMessage = null, userName = null // Reset userName before processing
|
||||
)
|
||||
it.copy(errorMessage = null, userName = null) // Reset UI state
|
||||
}
|
||||
|
||||
// Fetch Employee Document
|
||||
val employeeDoc = getEmployeeDocument(userId)
|
||||
if (employeeDoc == null) {
|
||||
handleError("Invalid employee ID")
|
||||
@@ -174,7 +172,6 @@ class HomeViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
if (!employeeDoc.getBoolean("EmployeeStatus")!!) {
|
||||
// Set userName only for expired ID case
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
userName = employeeDoc.getString("Name"),
|
||||
@@ -186,17 +183,17 @@ class HomeViewModel @Inject constructor(
|
||||
|
||||
_uiState.update { it.copy(userName = employeeDoc.getString("Name")) }
|
||||
|
||||
// Fetch Attendance Document
|
||||
val currentDate = getCurrentFormattedDate()
|
||||
val attendanceDoc = getAttendanceDocument(userId, currentDate)
|
||||
|
||||
if (attendanceDoc?.exists() == true) {
|
||||
val checkIn = attendanceDoc.getString("checkIn")
|
||||
if (isTimeDifferenceGreaterThanMinutes(givenTimeStr = checkIn!!, minutes = 5L)) {
|
||||
handleExistingAttendance(attendanceDoc)
|
||||
}else{
|
||||
val checkIn = attendanceDoc.getString("checkIn1") // Using first check-in for time validation
|
||||
if (checkIn != null && !isTimeDifferenceGreaterThanMinutes(givenTimeStr = checkIn, minutes = 0L)) {
|
||||
handleError("Wait 5 minutes before logging off")
|
||||
return@launch
|
||||
}
|
||||
|
||||
handleExistingAttendance(attendanceDoc)
|
||||
} else {
|
||||
handleNewAttendance(userId, currentDate)
|
||||
}
|
||||
@@ -209,6 +206,7 @@ class HomeViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun handleError(message: String) {
|
||||
viewModelScope.launch {
|
||||
_uiState.update {
|
||||
@@ -221,64 +219,6 @@ class HomeViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun handleExistingAttendance(document: DocumentSnapshot) {
|
||||
val checkOut = document.getString("checkOut")
|
||||
|
||||
when {
|
||||
checkOut == "NA" -> processCheckOut(document)
|
||||
checkOut != null -> {
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
checkedOutTime = checkOut, errorMessage = "Already checked out for today."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
else -> handleError("Invalid attendance record")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private suspend fun handleNewAttendance(userId: String, currentDate: String) {
|
||||
try {
|
||||
val checkInData = hashMapOf(
|
||||
"DayCompleted" to false,
|
||||
"checkIn" to formatTimestamp(Timestamp.now()),
|
||||
"checkOut" to "NA"
|
||||
)
|
||||
|
||||
firebaseFirestore.collection("attendance_$userId").document(currentDate)
|
||||
.set(checkInData).await()
|
||||
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
isCheckedIn = true, qrCodeValue = null
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
handleError("Failed to check in: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun processCheckOut(document: DocumentSnapshot) {
|
||||
|
||||
try {
|
||||
val checkOutData = hashMapOf(
|
||||
"checkOut" to formatTimestamp(Timestamp.now()), "DayCompleted" to true
|
||||
)
|
||||
|
||||
document.reference.update(checkOutData as Map<String, Any>).await()
|
||||
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
isCheckedOut = true, qrCodeValue = null
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
handleError("Failed to check out: ${e.message}")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private suspend fun getEmployeeDocument(userId: String): DocumentSnapshot? {
|
||||
return try {
|
||||
@@ -322,8 +262,40 @@ class HomeViewModel @Inject constructor(
|
||||
// println(a)
|
||||
// return true
|
||||
// }
|
||||
// fun processAttendance(userId: String) {
|
||||
// if (userId.isBlank()) return
|
||||
//
|
||||
// viewModelScope.launch {
|
||||
// try {
|
||||
// val currentDate = getCurrentFormattedDate()
|
||||
// val attendanceDoc = getAttendanceDocument(userId, currentDate)
|
||||
//
|
||||
// if (attendanceDoc?.exists() == true) {
|
||||
// handleExistingAttendance(attendanceDoc)
|
||||
// } else {
|
||||
// handleNewAttendance(userId, currentDate)
|
||||
// }
|
||||
// } catch (e: Exception) {
|
||||
// handleError("Error: ${e.message}")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
fun isTimeDifferenceGreaterThanMinutes(givenTimeStr: String, currentTimeStr: String = formatTimestamp(Timestamp.now()), minutes: Long): Boolean {
|
||||
|
||||
|
||||
private suspend fun handleExistingAttendance(document: DocumentSnapshot) {
|
||||
val data = document.data ?: return
|
||||
val checkIns = data.filterKeys { it.startsWith("checkIn") }.size
|
||||
val checkOuts = data.filterKeys { it.startsWith("checkOut") }.size
|
||||
|
||||
if (checkIns > checkOuts) {
|
||||
processCheckOut(document, checkIns)
|
||||
} else {
|
||||
processCheckIn(document, checkIns + 1)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isTimeDifferenceGreaterThanMinutes(givenTimeStr: String, currentTimeStr: String = formatTimestamp(Timestamp.now()), minutes: Long): Boolean {
|
||||
val formatter = DateTimeFormatter.ofPattern("dd MMMM yyyy hh:mm:ss a")
|
||||
|
||||
val givenTime = LocalDateTime.parse(givenTimeStr, formatter)
|
||||
@@ -334,7 +306,61 @@ class HomeViewModel @Inject constructor(
|
||||
return timeDifference > minutes
|
||||
}
|
||||
|
||||
private suspend fun handleNewAttendance(userId: String, currentDate: String) {
|
||||
try {
|
||||
val checkInData = hashMapOf(
|
||||
"DayCompleted" to false,
|
||||
"checkIn1" to formatTimestamp(Timestamp.now()),
|
||||
"totalWork" to "00:00:00"
|
||||
)
|
||||
|
||||
firebaseFirestore.collection("attendance_$userId").document(currentDate)
|
||||
.set(checkInData).await()
|
||||
} catch (e: Exception) {
|
||||
handleError("Failed to check in: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private suspend fun processCheckIn(document: DocumentSnapshot, checkInCount: Int) {
|
||||
try {
|
||||
document.reference.update("checkIn$checkInCount", formatTimestamp(Timestamp.now())).await()
|
||||
} catch (e: Exception) {
|
||||
handleError("Failed to check in: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun processCheckOut(document: DocumentSnapshot, checkInCount: Int) {
|
||||
try {
|
||||
val checkOutTime = formatTimestamp(Timestamp.now())
|
||||
document.reference.update("checkOut$checkInCount", checkOutTime).await()
|
||||
|
||||
val updatedDocument = document.reference.get().await()
|
||||
val totalWork = calculateTotalWork(updatedDocument)
|
||||
document.reference.update("totalWork", totalWork).await()
|
||||
|
||||
} catch (e: Exception) {
|
||||
handleError("Failed to check out: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateTotalWork(document: DocumentSnapshot): String {
|
||||
val formatter = DateTimeFormatter.ofPattern("dd MMMM yyyy hh:mm:ss a", Locale.getDefault())
|
||||
var totalMinutes = 0L
|
||||
|
||||
for (i in 1..10) {
|
||||
val checkIn = document.getString("checkIn$i") ?: break
|
||||
val checkOut = document.getString("checkOut$i") ?: continue
|
||||
|
||||
val checkInTime = LocalDateTime.parse(checkIn, formatter)
|
||||
val checkOutTime = LocalDateTime.parse(checkOut, formatter)
|
||||
totalMinutes += ChronoUnit.MINUTES.between(checkInTime, checkOutTime)
|
||||
}
|
||||
|
||||
val hours = totalMinutes / 60
|
||||
val minutes = totalMinutes % 60
|
||||
return String.format("%02d:%02d:00", hours, minutes)
|
||||
}
|
||||
|
||||
|
||||
override fun onCleared() {
|
||||
|
||||
Reference in New Issue
Block a user