diff --git a/app/src/main/java/in/sminnovations/attendanceapp/screens/home/viewModel/homeVM.kt b/app/src/main/java/in/sminnovations/attendanceapp/screens/home/viewModel/homeVM.kt index c05c32d..c563b13 100644 --- a/app/src/main/java/in/sminnovations/attendanceapp/screens/home/viewModel/homeVM.kt +++ b/app/src/main/java/in/sminnovations/attendanceapp/screens/home/viewModel/homeVM.kt @@ -7,17 +7,14 @@ import androidx.lifecycle.viewModelScope import com.google.firebase.Timestamp import com.google.firebase.firestore.FirebaseFirestore import dagger.hilt.android.lifecycle.HiltViewModel -import `in`.sminnovations.attendanceapp.data.dataStore.EmployeeRepository import `in`.sminnovations.attendanceapp.screens.home.data.CheckInCheckOutDataStore import `in`.sminnovations.attendanceapp.screens.login.data.LoginDataStore import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import java.text.Format import java.text.SimpleDateFormat import java.time.LocalDate -import java.time.LocalTime import java.util.Date import java.util.Locale import javax.inject.Inject @@ -27,7 +24,6 @@ class HomeViewModel @Inject constructor( private val loginDataStore: LoginDataStore, private val checkInCheckOutDataStore: CheckInCheckOutDataStore, private val firebaseFirestore: FirebaseFirestore, - private val employeeRepository: EmployeeRepository ) : ViewModel() { private val _qrCodeValue = MutableStateFlow(null) @@ -36,20 +32,29 @@ class HomeViewModel @Inject constructor( private val _isScanning = MutableStateFlow(false) val isScanning: StateFlow = _isScanning.asStateFlow() - private val _checkedIn = MutableStateFlow("") - val checkedIn : StateFlow = _checkedIn.asStateFlow() + private val _checkedIn = MutableStateFlow("") + val checkedIn: StateFlow = _checkedIn.asStateFlow() - private val _checkedOut = MutableStateFlow("N /A ") - val checkedOut : StateFlow = _checkedOut.asStateFlow() + private val _checkedOut = MutableStateFlow("N/A") + val checkedOut: StateFlow = _checkedOut.asStateFlow() + private val _isCheckedIn = MutableStateFlow(false) + val isCheckedIn: StateFlow = _isCheckedIn.asStateFlow() - private val _isCheckedIn = MutableStateFlow(false) - val isCheckedIn : StateFlow = _isCheckedIn.asStateFlow() + private val _isCheckedOut = MutableStateFlow(false) + val isCheckedOut: StateFlow = _isCheckedOut.asStateFlow() - private val _isCheckedOut = MutableStateFlow(false) - val isCheckedOut : StateFlow = _isCheckedOut.asStateFlow() + private val _errorMessage = MutableStateFlow(null) + val errorMessage: StateFlow = _errorMessage.asStateFlow() + private val _isLoading = MutableStateFlow(false) + val isLoading: StateFlow = _isLoading.asStateFlow() + private fun postErrorMessage(message: String) { + viewModelScope.launch { + _errorMessage.emit(message) + } + } fun startScanning() { _isScanning.value = true @@ -67,33 +72,43 @@ class HomeViewModel @Inject constructor( } private fun formatTimestamp(timestamp: Timestamp): String { - val sdf = SimpleDateFormat("dd MMMM yyyy hh:mm:ss a", Locale.getDefault()) // Format with AM/PM + val sdf = + SimpleDateFormat("dd MMMM yyyy hh:mm:ss a", Locale.getDefault()) // Format with AM/PM return sdf.format(timestamp.toDate()) } init { viewModelScope.launch { - checkInCheckOutDataStore.checkInId.collect { checkIn -> - checkInCheckOutDataStore.checkOutId.collect { checkOut -> - _checkedIn.value= checkIn - _checkedOut.value = checkOut - } - } + getCheckInChekout() } } - private fun getIsCheckInCheckOut(){ + private fun getCheckInChekout() { viewModelScope.launch { - checkInCheckOutDataStore.isCheckedIn.collect { isCheckIn -> - checkInCheckOutDataStore.isCheckedOut.collect { isCheckOut -> - _isCheckedIn.value = isCheckIn - _isCheckedOut.value = isCheckOut - } + checkInCheckOutDataStore.checkInId.collect { checkIn -> + _checkedIn.value = checkIn } } + viewModelScope.launch { + checkInCheckOutDataStore.checkOutId.collect { checkOut -> + _checkedOut.value = checkOut + } + } + + viewModelScope.launch { + checkInCheckOutDataStore.checkInDate.collect {date -> + if (date == LocalDate.now().toString()) { + _isCheckedIn.value = true + } + } + + } + + } + private fun getFormattedDate(): String { val dateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()) return dateFormat.format(Date()) @@ -101,29 +116,37 @@ class HomeViewModel @Inject constructor( fun loginNow() { viewModelScope.launch { + _isLoading.value = true checkInCheckOutDataStore.checkInDate.collect { checkOutDate -> loginDataStore.loginId.collect { _ -> firebaseFirestore.collection("qr_key").whereEqualTo("id", getFormattedDate()) .get().addOnSuccessListener { querySnapshot -> + _isLoading.value = false if (!querySnapshot.isEmpty) { for (document in querySnapshot) { if (qrCodeValue.value == document.getString("key")) { viewModelScope.launch { - if (checkOutDate != LocalDate.now().toString() || checkOutDate =="") { + if (checkOutDate != LocalDate.now().toString() || checkOutDate == "" + ) { putCheckInAttendance("") } else { + viewModelScope.launch { + _isCheckedIn.value = true + } + putCheckOutAttendance() } } } else { - Log.d("loginNow", "Invalid QR code scanned") + postErrorMessage("Invalid QR code scanned") } } } else { - Log.d("loginNow", "No matching QR key found for today's date") + postErrorMessage("No matching QR key found for today's date") } }.addOnFailureListener { exception -> - Log.e("Firestore", "Error fetching QR key: ", exception) + _isLoading.value = false + postErrorMessage("Error fetching QR key: ${exception.message}") } } } @@ -133,101 +156,100 @@ class HomeViewModel @Inject constructor( private fun putCheckInAttendance(location: String) { viewModelScope.launch { - loginDataStore.loginId.collect { id -> - val currentDate = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).format(Date()) - val attendanceRef = firebaseFirestore.collection("attendance_$id").document(currentDate) - - attendanceRef.get().addOnSuccessListener { document -> - if (!document.exists()) { - val checkInData = hashMapOf( - "Status" to false, - "checkIn" to Timestamp.now(), - "location" to location - ) - - attendanceRef.set(checkInData).addOnSuccessListener { - // Save the check-in data to a local datastore if needed - viewModelScope.launch { - checkInCheckOutDataStore.saveLoginData( - formatTimestamp(Timestamp.now()), - "Not yet Done" - ) - checkInCheckOutDataStore.saveLoginDate(LocalDate.now().toString()) - checkInCheckOutDataStore.saveIsLogIn(true) - } - Log.d("Firestore", "Check-in successful") - _isCheckedIn.value = true - }.addOnFailureListener { e -> - Log.e("Firestore", "Error adding check-in", e) - } - } else { - // Document exists, check the checkOut field - val checkOut = document.getTimestamp("checkout") - if (checkOut == null) { - Log.d( - "Firestore", - "Check-in already exists for today. Cannot check in again." - ) - } else { - Log.d("Firestore", "Attendance already completed for today.") - } - } - }.addOnFailureListener { exception -> - Log.e("Firestore", "Error fetching document: ", exception) - } - } - } - } - - - fun putCheckOutAttendance() { - viewModelScope.launch { + _isLoading.value = true loginDataStore.loginId.collect { id -> val currentDate = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).format(Date()) val attendanceRef = firebaseFirestore.collection("attendance_$id").document(currentDate) attendanceRef.get().addOnSuccessListener { document -> - if (document.exists()) { + _isLoading.value = false + if (!document.exists()) { + val checkInData = hashMapOf( + "Status" to false, + "checkIn" to formatTimestamp(Timestamp.now()), + "location" to location, + "checkOut" to "NA" + ) - val checkIn = document.getTimestamp("checkIn") - val checkOut = document.getTimestamp("checkout") - - if (checkIn != null && checkOut == null) { - - val checkOutData = hashMapOf( - "checkout" to Timestamp.now(), "Status" to true - ) as Map - - attendanceRef.update(checkOutData).addOnSuccessListener { - viewModelScope.launch { - checkInCheckOutDataStore.saveLoginData(checkedIn.value,formatTimestamp(Timestamp.now())) - checkInCheckOutDataStore.saveIsLogIn(false) - } - Log.d("Firestore", "Check-out successful") - }.addOnFailureListener { e -> - Log.e("Firestore", "Error adding check-out", e) + attendanceRef.set(checkInData).addOnSuccessListener { + viewModelScope.launch { + checkInCheckOutDataStore.saveLoginDate( + checkDate = LocalDate.now().toString(), + checkInTime = formatTimestamp(Timestamp.now()) + ) } - } else if (checkOut != null) { - Log.d("Firestore", "Already checked out for today.") - } else { - Log.d("Firestore", "Cannot check out without checking in.") + Log.d("Firestore", "Check-in successful") + viewModelScope.launch { + _isCheckedIn.value = true + } + }.addOnFailureListener { e -> + postErrorMessage("Error adding check-in: ${e.message}") } } else { - Log.d( - "Firestore", "No attendance found for today. Please check in first." - ) + postErrorMessage("Check-in already exists for today. Cannot check in again.") + viewModelScope.launch { + _isCheckedIn.value = true + } } }.addOnFailureListener { exception -> - Log.e("Firestore", "Error fetching document: ", exception) + _isLoading.value = false + postErrorMessage("Error fetching document: ${exception.message}") } } } } + private fun putCheckOutAttendance() { + viewModelScope.launch { + _isLoading.value = true + loginDataStore.loginId.collect { id -> + val currentDate = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).format(Date()) + val attendanceRef = + firebaseFirestore.collection("attendance_$id").document(currentDate) + attendanceRef.get().addOnSuccessListener { document -> + _isLoading.value = false + if (document.exists()) { + val checkIn = document.getString("checkIn") + val checkOut = document.getString("checkOut") + if (checkIn != null && checkOut == "NA") { + val checkOutData = hashMapOf( + "checkOut" to formatTimestamp(Timestamp.now()), "Status" to true + ) as Map + attendanceRef.update(checkOutData).addOnSuccessListener { + viewModelScope.launch { + checkInCheckOutDataStore.saveLoginData( + checkOut = formatTimestamp( + Timestamp.now() + ) + ) + checkInCheckOutDataStore.saveIsLogIn(false) + } + Log.d("Firestore", "Check-out successful") + }.addOnFailureListener { e -> + postErrorMessage("Error adding check-out: ${e.message}") + } + } else if (checkOut != "NA") { + postErrorMessage("Already checked out for today.") + viewModelScope.launch { + _isCheckedOut.value = true + } + } else { + postErrorMessage("Cannot check out without checking in.") + } + } else { + postErrorMessage("No attendance found for today. Please check in first.") + } + }.addOnFailureListener { exception -> + _isLoading.value = false + postErrorMessage("Error fetching document: ${exception.message}") + } + } + } + } }