expandable attendance list and network check
This commit is contained in:
33
.idea/other.xml
generated
33
.idea/other.xml
generated
@@ -47,6 +47,17 @@
|
|||||||
<option name="screenX" value="1840" />
|
<option name="screenX" value="1840" />
|
||||||
<option name="screenY" value="2944" />
|
<option name="screenY" value="2944" />
|
||||||
</PersistentDeviceSelectionData>
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="a15" />
|
||||||
|
<option name="id" value="a15" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="A15" />
|
||||||
|
<option name="screenDensity" value="450" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2340" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
<PersistentDeviceSelectionData>
|
<PersistentDeviceSelectionData>
|
||||||
<option name="api" value="31" />
|
<option name="api" value="31" />
|
||||||
<option name="brand" value="samsung" />
|
<option name="brand" value="samsung" />
|
||||||
@@ -69,6 +80,17 @@
|
|||||||
<option name="screenX" value="1080" />
|
<option name="screenX" value="1080" />
|
||||||
<option name="screenY" value="2400" />
|
<option name="screenY" value="2400" />
|
||||||
</PersistentDeviceSelectionData>
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="motorola" />
|
||||||
|
<option name="codename" value="arcfox" />
|
||||||
|
<option name="id" value="arcfox" />
|
||||||
|
<option name="manufacturer" value="Motorola" />
|
||||||
|
<option name="name" value="razr plus 2024" />
|
||||||
|
<option name="screenDensity" value="360" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="1272" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
<PersistentDeviceSelectionData>
|
<PersistentDeviceSelectionData>
|
||||||
<option name="api" value="33" />
|
<option name="api" value="33" />
|
||||||
<option name="brand" value="samsung" />
|
<option name="brand" value="samsung" />
|
||||||
@@ -223,6 +245,17 @@
|
|||||||
<option name="screenX" value="720" />
|
<option name="screenX" value="720" />
|
||||||
<option name="screenY" value="1600" />
|
<option name="screenY" value="1600" />
|
||||||
</PersistentDeviceSelectionData>
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="g0q" />
|
||||||
|
<option name="id" value="g0q" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="SM-S906U1" />
|
||||||
|
<option name="screenDensity" value="450" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2340" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
<PersistentDeviceSelectionData>
|
<PersistentDeviceSelectionData>
|
||||||
<option name="api" value="33" />
|
<option name="api" value="33" />
|
||||||
<option name="brand" value="samsung" />
|
<option name="brand" value="samsung" />
|
||||||
|
|||||||
81
app/src/main/java/in/sminnovations/smiadmin/BaseActivity.kt
Normal file
81
app/src/main/java/in/sminnovations/smiadmin/BaseActivity.kt
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
package `in`.sminnovations.smiadmin
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.Network
|
||||||
|
import android.net.NetworkCapabilities
|
||||||
|
import android.net.NetworkRequest
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.provider.Settings
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import `in`.sminnovations.smiadmin.ui.utils.NetworkUtils
|
||||||
|
|
||||||
|
abstract class BaseActivity : AppCompatActivity() {
|
||||||
|
private var internetDialog: AlertDialog? = null
|
||||||
|
private lateinit var networkUtils: NetworkUtils
|
||||||
|
private lateinit var connectivityCallback: ConnectivityManager.NetworkCallback
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
networkUtils = NetworkUtils(this)
|
||||||
|
setupNetworkCallback()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupNetworkCallback() {
|
||||||
|
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||||
|
connectivityCallback = object : ConnectivityManager.NetworkCallback() {
|
||||||
|
override fun onAvailable(network: Network) {
|
||||||
|
runOnUiThread {
|
||||||
|
internetDialog?.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLost(network: Network) {
|
||||||
|
runOnUiThread {
|
||||||
|
showNoInternetDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
connectivityManager.registerDefaultNetworkCallback(connectivityCallback)
|
||||||
|
} else {
|
||||||
|
val request = NetworkRequest.Builder()
|
||||||
|
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||||
|
.build()
|
||||||
|
connectivityManager.registerNetworkCallback(request, connectivityCallback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showNoInternetDialog() {
|
||||||
|
if (internetDialog?.isShowing == true) return
|
||||||
|
|
||||||
|
internetDialog = AlertDialog.Builder(this)
|
||||||
|
.setTitle("No Internet Connection")
|
||||||
|
.setMessage("Please turn on your mobile data or connect to Wi-Fi")
|
||||||
|
.setCancelable(false)
|
||||||
|
.setPositiveButton("Open Settings") { _, _ ->
|
||||||
|
startActivity(Intent(Settings.ACTION_WIRELESS_SETTINGS))
|
||||||
|
}
|
||||||
|
.create()
|
||||||
|
|
||||||
|
internetDialog?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if (!networkUtils.isInternetAvailable()) {
|
||||||
|
showNoInternetDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||||
|
connectivityManager.unregisterNetworkCallback(connectivityCallback)
|
||||||
|
internetDialog?.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ import androidx.navigation.ui.setupWithNavController
|
|||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
import `in`.sminnovations.smiadmin.databinding.ActivityMainBinding
|
import `in`.sminnovations.smiadmin.databinding.ActivityMainBinding
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : BaseActivity() {
|
||||||
private lateinit var binding: ActivityMainBinding
|
private lateinit var binding: ActivityMainBinding
|
||||||
private lateinit var navController: NavController
|
private lateinit var navController: NavController
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package `in`.sminnovations.smiadmin.data
|
|||||||
|
|
||||||
data class AttendanceData(
|
data class AttendanceData(
|
||||||
val date: String = "",
|
val date: String = "",
|
||||||
val checkIn: String = "",
|
val checkIns: Map<String, String>,
|
||||||
val checkOut: String = ""
|
val checkOuts: Map<String, String>,
|
||||||
|
var isExpanded: Boolean = false
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package `in`.sminnovations.smiadmin.data
|
|||||||
data class Employee(
|
data class Employee(
|
||||||
var Id: String = "",
|
var Id: String = "",
|
||||||
var Name: String = "",
|
var Name: String = "",
|
||||||
var EmployeeStatus: Boolean = false,
|
var EmployeeStatus: Boolean = true,
|
||||||
var Designation:String = "",
|
var Designation:String = "",
|
||||||
var DateOfJoining: String = "",
|
var DateOfJoining: String = "",
|
||||||
var dateOfBirth: String = "",
|
var dateOfBirth: String = "",
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package `in`.sminnovations.smiadmin.ui.adapter
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.cardview.widget.CardView
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import `in`.sminnovations.smiadmin.R
|
import `in`.sminnovations.smiadmin.R
|
||||||
import `in`.sminnovations.smiadmin.data.AttendanceData
|
import `in`.sminnovations.smiadmin.data.AttendanceData
|
||||||
@@ -13,8 +15,9 @@ class AttendanceAdapter : RecyclerView.Adapter<AttendanceAdapter.ViewHolder>() {
|
|||||||
|
|
||||||
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
val dateTextView: TextView = itemView.findViewById(R.id.textViewDate)
|
val dateTextView: TextView = itemView.findViewById(R.id.textViewDate)
|
||||||
val checkInTextView: TextView = itemView.findViewById(R.id.textViewCheckIn)
|
val checkInsLayout: LinearLayout = itemView.findViewById(R.id.layoutCheckIns)
|
||||||
val checkOutTextView: TextView = itemView.findViewById(R.id.textViewCheckOut)
|
val expandableLayout: LinearLayout = itemView.findViewById(R.id.expandableLayout)
|
||||||
|
val cardView: CardView = itemView.findViewById(R.id.cardView)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
@@ -26,13 +29,41 @@ class AttendanceAdapter : RecyclerView.Adapter<AttendanceAdapter.ViewHolder>() {
|
|||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val attendance = attendanceList[position]
|
val attendance = attendanceList[position]
|
||||||
holder.dateTextView.text = attendance.date
|
holder.dateTextView.text = attendance.date
|
||||||
holder.checkInTextView.text = "Check In: ${attendance.checkIn}"
|
|
||||||
holder.checkOutTextView.text = "Check Out: ${attendance.checkOut}"
|
// Clear previous views
|
||||||
|
holder.checkInsLayout.removeAllViews()
|
||||||
|
|
||||||
|
// Create check-in/check-out pairs dynamically
|
||||||
|
val context = holder.itemView.context
|
||||||
|
for (i in 1..attendance.checkIns.size) {
|
||||||
|
val checkInKey = "checkIn$i"
|
||||||
|
val checkOutKey = "checkOut$i"
|
||||||
|
|
||||||
|
if (attendance.checkIns.containsKey(checkInKey)) {
|
||||||
|
val pairLayout = LayoutInflater.from(context)
|
||||||
|
.inflate(R.layout.item_checkin_checkout_pair, holder.checkInsLayout, false)
|
||||||
|
|
||||||
|
val checkInView = pairLayout.findViewById<TextView>(R.id.textViewCheckIn)
|
||||||
|
val checkOutView = pairLayout.findViewById<TextView>(R.id.textViewCheckOut)
|
||||||
|
|
||||||
|
checkInView.text = "Check In: ${attendance.checkIns[checkInKey]}"
|
||||||
|
checkOutView.text = "Check Out: ${attendance.checkOuts[checkOutKey] ?: "Pending"}"
|
||||||
|
|
||||||
|
holder.checkInsLayout.addView(pairLayout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up expansion/collapse
|
||||||
|
holder.expandableLayout.visibility = if (attendance.isExpanded) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
|
holder.cardView.setOnClickListener {
|
||||||
|
attendance.isExpanded = !attendance.isExpanded
|
||||||
|
notifyItemChanged(position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount() = attendanceList.size
|
override fun getItemCount() = attendanceList.size
|
||||||
|
|
||||||
// In AttendanceAdapter.kt
|
|
||||||
fun updateAttendance(newAttendance: List<AttendanceData>) {
|
fun updateAttendance(newAttendance: List<AttendanceData>) {
|
||||||
attendanceList.clear()
|
attendanceList.clear()
|
||||||
// Convert date string to comparable format and sort
|
// Convert date string to comparable format and sort
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ class AddEmployeeFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateEmployeeId(name: String, phone: String): String {
|
private fun generateEmployeeId(name: String, phone: String): String {
|
||||||
val namePrefix = name.take(4).uppercase()
|
val namePrefix = name.take(4).lowercase()
|
||||||
val phoneSuffix = phone.takeLast(4)
|
val phoneSuffix = phone.takeLast(4)
|
||||||
return "$namePrefix$phoneSuffix"
|
return "$namePrefix$phoneSuffix"
|
||||||
}
|
}
|
||||||
@@ -136,16 +136,29 @@ class AddEmployeeFragment : Fragment() {
|
|||||||
val phone = binding.etEmployeePhone.text.toString().trim()
|
val phone = binding.etEmployeePhone.text.toString().trim()
|
||||||
val employeeId = generateEmployeeId(name, phone)
|
val employeeId = generateEmployeeId(name, phone)
|
||||||
|
|
||||||
val employee = Employee(
|
// val employee = Employee(
|
||||||
Id = employeeId,
|
// Id = employeeId,
|
||||||
Name = name,
|
// Name = name,
|
||||||
Email = binding.etEmployeeEmail.text.toString().trim(),
|
// Email = binding.etEmployeeEmail.text.toString().trim(),
|
||||||
Mobile = phone,
|
// Mobile = phone,
|
||||||
Designation = binding.etEmployeePosition.text.toString().trim(),
|
// Designation = binding.etEmployeePosition.text.toString().trim(),
|
||||||
dateOfBirth = dateFormatter.format(dateOfBirth?.time ?: Date()),
|
// dateOfBirth = dateFormatter.format(dateOfBirth?.time ?: Date()),
|
||||||
DateOfJoining = dateFormatter.format(dateOfJoining?.time ?: Date()),
|
// DateOfJoining = dateFormatter.format(dateOfJoining?.time ?: Date()),
|
||||||
CreatedAt = dateFormatter.format(Date()), // Current date in dd/MM/yyyy format
|
// CreatedAt = dateFormatter.format(Date()), // Current date in dd/MM/yyyy format
|
||||||
from = binding.etEmployeeFrom.text.toString().trim(),
|
// from = binding.etEmployeeFrom.text.toString().trim(),
|
||||||
|
// )
|
||||||
|
val employee = hashMapOf(
|
||||||
|
"Id" to employeeId,
|
||||||
|
"Name" to name,
|
||||||
|
"EmployeeStatus" to true,
|
||||||
|
"Email" to binding.etEmployeeEmail.text.toString().trim(),
|
||||||
|
"Mobile" to phone,
|
||||||
|
"Designation" to binding.etEmployeePosition.text.toString().trim(),
|
||||||
|
"dateOfBirth" to dateFormatter.format(dateOfBirth?.time ?: Date()),
|
||||||
|
"DateOfJoining" to dateFormatter.format(dateOfJoining?.time ?: Date()),
|
||||||
|
"CreatedAt" to dateFormatter.format(Date()),
|
||||||
|
"from" to binding.etEmployeeFrom.text.toString().trim(),
|
||||||
|
"role" to "user"
|
||||||
)
|
)
|
||||||
|
|
||||||
db.collection("employees")
|
db.collection("employees")
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package `in`.sminnovations.smiadmin.ui.fragments.attendance
|
|||||||
|
|
||||||
import android.R
|
import android.R
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@@ -123,13 +124,38 @@ class AttendanceDetailFragment : Fragment() {
|
|||||||
|
|
||||||
// Only include records for selected month and year
|
// Only include records for selected month and year
|
||||||
if (docMonth == month && docYear == year) {
|
if (docMonth == month && docYear == year) {
|
||||||
|
// Get all fields from the document
|
||||||
|
val data = doc.data ?: return@mapNotNull null
|
||||||
|
|
||||||
|
// Create maps to store check-ins and check-outs
|
||||||
|
val checkIns = mutableMapOf<String, String>()
|
||||||
|
val checkOuts = mutableMapOf<String, String>()
|
||||||
|
|
||||||
|
// Iterate through all fields in the document
|
||||||
|
data.forEach { (key, value) ->
|
||||||
|
when {
|
||||||
|
// Match checkIn1, checkIn2, etc.
|
||||||
|
key.startsWith("checkIn") -> {
|
||||||
|
checkIns[key] = (value as? String) ?: "N/A"
|
||||||
|
}
|
||||||
|
// Match checkOut1, checkOut2, etc.
|
||||||
|
key.startsWith("checkOut") -> {
|
||||||
|
checkOuts[key] = (value as? String) ?: "N/A"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only create AttendanceData if there's at least one check-in
|
||||||
|
if (checkIns.isNotEmpty()) {
|
||||||
AttendanceData(
|
AttendanceData(
|
||||||
date = doc.id,
|
date = doc.id,
|
||||||
checkIn = doc.getString("checkIn") ?: "N/A",
|
checkIns = checkIns,
|
||||||
checkOut = doc.getString("checkOut") ?: "N/A"
|
checkOuts = checkOuts
|
||||||
)
|
)
|
||||||
} else null
|
} else null
|
||||||
|
} else null
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
Log.e("AttendanceMapping", "Error mapping document: ${doc.id}", e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package `in`.sminnovations.smiadmin.ui.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.NetworkCapabilities
|
||||||
|
import android.os.Build
|
||||||
|
|
||||||
|
class NetworkUtils(private val context: Context) {
|
||||||
|
fun isInternetAvailable(): Boolean {
|
||||||
|
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
val network = connectivityManager.activeNetwork ?: return false
|
||||||
|
val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
|
||||||
|
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||||
|
} else {
|
||||||
|
val networkInfo = connectivityManager.activeNetworkInfo ?: return false
|
||||||
|
return networkInfo.isConnected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M7,10l5,5 5,-5z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
android:id="@+id/spinnerMonth"
|
android:id="@+id/spinnerMonth"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="5dp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/textViewEmployeeName" />
|
app:layout_constraintTop_toBottomOf="@id/textViewEmployeeName" />
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
android:id="@+id/spinnerYear"
|
android:id="@+id/spinnerYear"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="5dp"
|
||||||
app:layout_constraintStart_toEndOf="@id/spinnerMonth"
|
app:layout_constraintStart_toEndOf="@id/spinnerMonth"
|
||||||
app:layout_constraintTop_toTopOf="@id/spinnerMonth" />
|
app:layout_constraintTop_toTopOf="@id/spinnerMonth" />
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +1,71 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.cardview.widget.CardView
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
android:id="@+id/cardView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="8dp"
|
android:layout_margin="8dp"
|
||||||
app:cardCornerRadius="8dp"
|
app:cardCornerRadius="8dp"
|
||||||
app:cardElevation="4dp">
|
app:cardElevation="4dp"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical">
|
||||||
android:padding="16dp">
|
|
||||||
|
<!-- Header Layout -->
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/headerLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textViewDate"
|
android:id="@+id/textViewDate"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="16sp"
|
android:layout_alignParentStart="true"
|
||||||
android:textStyle="bold" />
|
android:layout_centerVertical="true"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imageViewArrow"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:src="@drawable/baseline_arrow_drop_down_24"
|
||||||
|
android:rotation="0" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<!-- Divider -->
|
||||||
|
<View
|
||||||
|
android:id="@+id/divider"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="?android:attr/listDivider"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<!-- Expandable Content -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/expandableLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:orientation="vertical"
|
||||||
android:orientation="horizontal">
|
android:visibility="gone"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:id="@+id/textViewCheckIn"
|
android:id="@+id/layoutCheckIns"
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1" />
|
android:orientation="vertical" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textViewCheckOut"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
21
app/src/main/res/layout/item_checkin_checkout_pair.xml
Normal file
21
app/src/main/res/layout/item_checkin_checkout_pair.xml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="8dp"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textViewCheckIn"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@android:color/black" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textViewCheckOut"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:textColor="@android:color/black" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
Reference in New Issue
Block a user