fixed so many issues regarding the qr state and check in checkout added date remember state and optimised code
This commit is contained in:
@@ -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<String?>(null)
|
||||
@@ -36,20 +32,29 @@ class HomeViewModel @Inject constructor(
|
||||
private val _isScanning = MutableStateFlow(false)
|
||||
val isScanning: StateFlow<Boolean> = _isScanning.asStateFlow()
|
||||
|
||||
private val _checkedIn = MutableStateFlow<String>("")
|
||||
val checkedIn : StateFlow<String> = _checkedIn.asStateFlow()
|
||||
private val _checkedIn = MutableStateFlow("")
|
||||
val checkedIn: StateFlow<String> = _checkedIn.asStateFlow()
|
||||
|
||||
private val _checkedOut = MutableStateFlow<String>("N /A ")
|
||||
val checkedOut : StateFlow<String> = _checkedOut.asStateFlow()
|
||||
private val _checkedOut = MutableStateFlow("N/A")
|
||||
val checkedOut: StateFlow<String> = _checkedOut.asStateFlow()
|
||||
|
||||
private val _isCheckedIn = MutableStateFlow(false)
|
||||
val isCheckedIn: StateFlow<Boolean> = _isCheckedIn.asStateFlow()
|
||||
|
||||
private val _isCheckedIn = MutableStateFlow<Boolean>(false)
|
||||
val isCheckedIn : StateFlow<Boolean> = _isCheckedIn.asStateFlow()
|
||||
private val _isCheckedOut = MutableStateFlow(false)
|
||||
val isCheckedOut: StateFlow<Boolean> = _isCheckedOut.asStateFlow()
|
||||
|
||||
private val _isCheckedOut = MutableStateFlow<Boolean>(false)
|
||||
val isCheckedOut : StateFlow<Boolean> = _isCheckedOut.asStateFlow()
|
||||
private val _errorMessage = MutableStateFlow<String?>(null)
|
||||
val errorMessage: StateFlow<String?> = _errorMessage.asStateFlow()
|
||||
|
||||
private val _isLoading = MutableStateFlow(false)
|
||||
val isLoading: StateFlow<Boolean> = _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<String, Any>
|
||||
|
||||
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<String, Any>
|
||||
|
||||
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}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user