Merge remote-tracking branch 'refs/remotes/origin/dev'

This commit is contained in:
chandrashekhar reddy
2025-01-20 12:38:22 +05:30
15 changed files with 112 additions and 110 deletions

View File

@@ -0,0 +1,6 @@
package `in`.sminnovations.smiadmin.data
object Constant {
const val COMPANY_NAME = "ShanMukha Innovations"
const val STORAGE_PERMISSION_CODE = 101
}

View File

@@ -1,41 +0,0 @@
package `in`.sminnovations.smiadmin.ui
import android.app.DatePickerDialog
import android.app.Dialog
import android.content.res.Resources
import android.os.Bundle
import android.view.View
import androidx.fragment.app.DialogFragment
import `in`.sminnovations.smiadmin.R
import java.util.Calendar
class MonthYearPickerDialog : DialogFragment() {
private var onDateSelected: ((Int, Int) -> Unit)? = null
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val calendar = Calendar.getInstance()
val year = calendar.get(Calendar.YEAR)
val month = calendar.get(Calendar.MONTH)
val dialog = DatePickerDialog(
requireContext(),
R.style.DialogTheme,
{ _, selectedYear, selectedMonth, _ ->
onDateSelected?.invoke(selectedYear, selectedMonth + 1)
},
year,
month,
1
)
// Hide the day picker as we only need month and year
val datePicker = dialog.datePicker
datePicker.findViewById<View>(Resources.getSystem().getIdentifier("day", "id", "android"))?.visibility = View.GONE
return dialog
}
fun setOnDateSelectedListener(listener: (Int, Int) -> Unit) {
onDateSelected = listener
}
}

View File

@@ -1,4 +1,4 @@
package `in`.sminnovations.smiadmin.ui.attendance package `in`.sminnovations.smiadmin.ui.adapter
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View

View File

@@ -1,4 +1,4 @@
package `in`.sminnovations.smiadmin package `in`.sminnovations.smiadmin.ui.adapter
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@@ -6,6 +6,7 @@ import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.switchmaterial.SwitchMaterial import com.google.android.material.switchmaterial.SwitchMaterial
import `in`.sminnovations.smiadmin.R
import `in`.sminnovations.smiadmin.data.Employee import `in`.sminnovations.smiadmin.data.Employee
class EmployeeListAdapter( class EmployeeListAdapter(

View File

@@ -1,4 +1,4 @@
package `in`.sminnovations.smiadmin.ui.attendance package `in`.sminnovations.smiadmin.ui.adapter
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@@ -8,9 +8,9 @@ import androidx.recyclerview.widget.RecyclerView
import `in`.sminnovations.smiadmin.R import `in`.sminnovations.smiadmin.R
import `in`.sminnovations.smiadmin.data.Employee import `in`.sminnovations.smiadmin.data.Employee
class EmployeeListAdapter( class EmployeeStatusListAdapter(
private val onEmployeeClick: (Employee) -> Unit private val onEmployeeClick: (Employee) -> Unit
) : RecyclerView.Adapter<EmployeeListAdapter.ViewHolder>() { ) : RecyclerView.Adapter<EmployeeStatusListAdapter.ViewHolder>() {
private val employees = mutableListOf<Employee>() private val employees = mutableListOf<Employee>()

View File

@@ -1,16 +1,13 @@
package `in`.sminnovations.smiadmin.ui package `in`.sminnovations.smiadmin.ui.fragments
import android.Manifest import android.Manifest
import android.app.ProgressDialog import android.app.ProgressDialog
import android.content.ActivityNotFoundException
import android.content.ContentUris
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.provider.MediaStore
import android.provider.Settings import android.provider.Settings
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@@ -18,23 +15,16 @@ import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.cardview.widget.CardView import androidx.cardview.widget.CardView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.google.firebase.Firebase import `in`.sminnovations.smiadmin.data.Constant.STORAGE_PERMISSION_CODE
import com.google.firebase.firestore.firestore
import `in`.sminnovations.smiadmin.R import `in`.sminnovations.smiadmin.R
import `in`.sminnovations.smiadmin.data.Employee import `in`.sminnovations.smiadmin.ui.utils.ExportTask
import kotlinx.coroutines.Dispatchers import `in`.sminnovations.smiadmin.ui.utils.MonthYearPickerDialog
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.tasks.await
import kotlinx.coroutines.withContext
class HomeFragment : Fragment() { class HomeFragment : Fragment() {
private lateinit var exportTask: ExportTask private lateinit var exportTask: ExportTask
private val STORAGE_PERMISSION_CODE = 101
private var currentExcelTask: Job? = null private var currentExcelTask: Job? = null
override fun onCreateView( override fun onCreateView(
@@ -84,39 +74,6 @@ class HomeFragment : Fragment() {
} }
exportTask.exportAttendance(year, month) exportTask.exportAttendance(year, month)
progressDialog.dismiss() progressDialog.dismiss()
// currentExcelTask = lifecycleScope.launch {
// try {
// // First get all employees
// val employeesSnapshot = withContext(Dispatchers.IO) {
// db.collection("employees").get().await()
// }
//
// val employees = employeesSnapshot.documents.map { doc ->
// Employee(
// Id = doc.getString("Id") ?: "Unknown",
// Name = doc.getString("Name") ?: "Unknown"
// )
// }.sortedBy { it.Name }
//
// // Generate CSV file
// val pdfGenerator = PDFGenerator(requireContext(), "ShanMukha Innovations")
// val pdfFile = pdfGenerator.generateAttendanceReport(employees, year, month)
//
// progressDialog.dismiss()
//
// // Show success message with file location
// Toast.makeText(
// context,
// "Report saved in Downloads folder: ${pdfFile.name}",
// Toast.LENGTH_LONG
// ).show()
//
// } catch (e: Exception) {
// progressDialog.dismiss()
// Toast.makeText(context, "Error: ${e.message}", Toast.LENGTH_LONG).show()
// }
// }
} }
private fun checkStoragePermission(): Boolean { private fun checkStoragePermission(): Boolean {

View File

@@ -1,4 +1,4 @@
package `in`.sminnovations.smiadmin.ui package `in`.sminnovations.smiadmin.ui.fragments
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Bundle import android.os.Bundle

View File

@@ -1,4 +1,4 @@
package `in`.sminnovations.smiadmin.ui.attendance package `in`.sminnovations.smiadmin.ui.fragments.attendance
import android.R import android.R
import android.os.Bundle import android.os.Bundle
@@ -12,6 +12,7 @@ import androidx.fragment.app.Fragment
import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.FirebaseFirestore
import `in`.sminnovations.smiadmin.data.AttendanceData import `in`.sminnovations.smiadmin.data.AttendanceData
import `in`.sminnovations.smiadmin.databinding.FragmentAttendanceDetailBinding import `in`.sminnovations.smiadmin.databinding.FragmentAttendanceDetailBinding
import `in`.sminnovations.smiadmin.ui.adapter.AttendanceAdapter
import java.util.Calendar import java.util.Calendar
class AttendanceDetailFragment : Fragment() { class AttendanceDetailFragment : Fragment() {

View File

@@ -1,4 +1,4 @@
package `in`.sminnovations.smiadmin.ui.attendance package `in`.sminnovations.smiadmin.ui.fragments.attendance
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@@ -11,12 +11,13 @@ import com.google.firebase.firestore.FirebaseFirestore
import `in`.sminnovations.smiadmin.R import `in`.sminnovations.smiadmin.R
import `in`.sminnovations.smiadmin.data.Employee import `in`.sminnovations.smiadmin.data.Employee
import `in`.sminnovations.smiadmin.databinding.FragmentEmployeeAttendanceListBinding import `in`.sminnovations.smiadmin.databinding.FragmentEmployeeAttendanceListBinding
import `in`.sminnovations.smiadmin.ui.adapter.EmployeeStatusListAdapter
class EmployeeAttendanceListFragment : Fragment() { class EmployeeAttendanceListFragment : Fragment() {
private var _binding: FragmentEmployeeAttendanceListBinding? = null private var _binding: FragmentEmployeeAttendanceListBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private lateinit var adapter: EmployeeListAdapter private lateinit var adapter: EmployeeStatusListAdapter
private val db = FirebaseFirestore.getInstance() private val db = FirebaseFirestore.getInstance()
override fun onCreateView( override fun onCreateView(
@@ -36,7 +37,7 @@ class EmployeeAttendanceListFragment : Fragment() {
} }
private fun setupRecyclerView() { private fun setupRecyclerView() {
adapter = EmployeeListAdapter { employee -> adapter = EmployeeStatusListAdapter { employee ->
val bundle = Bundle().apply { val bundle = Bundle().apply {
putString("employeeId", employee.Id) putString("employeeId", employee.Id)
putString("employeeName", employee.Name) putString("employeeName", employee.Name)

View File

@@ -1,4 +1,4 @@
package `in`.sminnovations.smiadmin.ui package `in`.sminnovations.smiadmin.ui.fragments.attendance
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
@@ -7,7 +7,7 @@ import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.FirebaseFirestore
import `in`.sminnovations.smiadmin.EmployeeListAdapter import `in`.sminnovations.smiadmin.ui.adapter.EmployeeListAdapter
import `in`.sminnovations.smiadmin.data.Employee import `in`.sminnovations.smiadmin.data.Employee
import `in`.sminnovations.smiadmin.databinding.FragmentEmployeeListBinding import `in`.sminnovations.smiadmin.databinding.FragmentEmployeeListBinding

View File

@@ -1,12 +1,12 @@
package `in`.sminnovations.smiadmin.ui package `in`.sminnovations.smiadmin.ui.utils
import android.app.ProgressDialog import android.app.ProgressDialog
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.google.android.gms.common.internal.Constants
import com.google.firebase.Firebase import com.google.firebase.Firebase
import com.google.firebase.firestore.firestore import com.google.firebase.firestore.firestore
import `in`.sminnovations.smiadmin.data.Constant
import `in`.sminnovations.smiadmin.data.Employee import `in`.sminnovations.smiadmin.data.Employee
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@@ -15,7 +15,6 @@ import kotlinx.coroutines.tasks.await
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
class ExportTask(private val fragment: Fragment) { class ExportTask(private val fragment: Fragment) {
private val companyName = "ShanMukha Innovations"
private val db = Firebase.firestore private val db = Firebase.firestore
private var currentExcelTask: Job? = null private var currentExcelTask: Job? = null
@@ -49,7 +48,7 @@ class ExportTask(private val fragment: Fragment) {
// Switch to IO dispatcher for file operations // Switch to IO dispatcher for file operations
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
val pdfGenerator = PDFGenerator(fragment.requireContext(), companyName) val pdfGenerator = PDFGenerator(fragment.requireContext(), Constant.COMPANY_NAME)
pdfGenerator.generateAttendanceReport(employees, year, month) pdfGenerator.generateAttendanceReport(employees, year, month)
}.also { pdfFile -> }.also { pdfFile ->
// Switch back to Main dispatcher for UI updates // Switch back to Main dispatcher for UI updates

View File

@@ -0,0 +1,57 @@
package `in`.sminnovations.smiadmin.ui.utils
import android.app.AlertDialog
import android.app.DatePickerDialog
import android.app.Dialog
import android.content.res.Resources
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.NumberPicker
import androidx.fragment.app.DialogFragment
import `in`.sminnovations.smiadmin.R
import java.util.Calendar
class MonthYearPickerDialog : DialogFragment() {
private var onDateSelected: ((Int, Int) -> Unit)? = null
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
// Inflate the custom layout
val view = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_month_year_picker, null)
// Initialize NumberPickers for Month and Year
val monthPicker = view.findViewById<NumberPicker>(R.id.month_picker)
val yearPicker = view.findViewById<NumberPicker>(R.id.year_picker)
// Set up the Month Picker
monthPicker.minValue = 1
monthPicker.maxValue = 12
monthPicker.displayedValues = arrayOf(
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
)
// Set up the Year Picker
val currentYear = Calendar.getInstance().get(Calendar.YEAR)
yearPicker.minValue = currentYear - 100 // 100 years in the past
yearPicker.maxValue = currentYear + 100 // 100 years in the future
yearPicker.value = currentYear
// Build the Dialog
val dialog = AlertDialog.Builder(requireContext())
.setView(view)
.setPositiveButton("OK") { _, _ ->
val selectedMonth = monthPicker.value
val selectedYear = yearPicker.value
onDateSelected?.invoke(selectedYear, selectedMonth)
}
.setNegativeButton("Cancel", null)
.create()
return dialog
}
fun setOnDateSelectedListener(listener: (Int, Int) -> Unit) {
onDateSelected = listener
}
}

View File

@@ -1,4 +1,4 @@
package `in`.sminnovations.smiadmin.ui package `in`.sminnovations.smiadmin.ui.utils
import android.content.Context import android.content.Context
import android.graphics.Color import android.graphics.Color

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- Month Picker -->
<NumberPicker
android:id="@+id/month_picker"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- Year Picker -->
<NumberPicker
android:id="@+id/year_picker"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>

View File

@@ -6,7 +6,7 @@
<fragment <fragment
android:id="@+id/navigation_home" android:id="@+id/navigation_home"
android:name="in.sminnovations.smiadmin.ui.HomeFragment" android:name="in.sminnovations.smiadmin.ui.fragments.HomeFragment"
android:label="Home"> android:label="Home">
<action <action
android:id="@+id/action_home_to_employee_list" android:id="@+id/action_home_to_employee_list"
@@ -18,17 +18,17 @@
<fragment <fragment
android:id="@+id/navigation_settings" android:id="@+id/navigation_settings"
android:name="in.sminnovations.smiadmin.ui.SettingsFragment" android:name="in.sminnovations.smiadmin.ui.fragments.SettingsFragment"
android:label="Settings" /> android:label="Settings" />
<fragment <fragment
android:id="@+id/navigation_employee_list" android:id="@+id/navigation_employee_list"
android:name="in.sminnovations.smiadmin.ui.EmployeeListFragment" android:name="in.sminnovations.smiadmin.ui.fragments.attendance.EmployeeListFragment"
android:label="Employee List" /> android:label="Employee List" />
<fragment <fragment
android:id="@+id/navigation_employee_attendance_list" android:id="@+id/navigation_employee_attendance_list"
android:name="in.sminnovations.smiadmin.ui.attendance.EmployeeAttendanceListFragment" android:name="in.sminnovations.smiadmin.ui.fragments.attendance.EmployeeAttendanceListFragment"
android:label="Employee List"> android:label="Employee List">
<action <action
android:id="@+id/action_employee_list_to_attendance_detail" android:id="@+id/action_employee_list_to_attendance_detail"
@@ -37,7 +37,7 @@
<fragment <fragment
android:id="@+id/navigation_attendance_detail" android:id="@+id/navigation_attendance_detail"
android:name="in.sminnovations.smiadmin.ui.attendance.AttendanceDetailFragment" android:name="in.sminnovations.smiadmin.ui.fragments.attendance.AttendanceDetailFragment"
android:label="Attendance Detail"> android:label="Attendance Detail">
<argument <argument
android:name="employeeId" android:name="employeeId"