This commit is contained in:
sathwikcs
2025-02-04 12:00:42 +05:30
parent 7adc89b4f3
commit 945f9920fd

View File

@@ -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() {