diff --git a/app/src/main/java/pl/firmatpp/kierowca/data/model/DriverModels.kt b/app/src/main/java/pl/firmatpp/kierowca/data/model/DriverModels.kt index 0fa2a09..33e0f32 100644 --- a/app/src/main/java/pl/firmatpp/kierowca/data/model/DriverModels.kt +++ b/app/src/main/java/pl/firmatpp/kierowca/data/model/DriverModels.kt @@ -88,6 +88,13 @@ data class DriverAppSettingsDto( data class LeaveRequestsConfigDto( val enabled: Boolean = false, val types: List = listOf("URLOP"), + val usagePoolCodes: List = listOf( + "ANNUAL", + "ANNUAL_DISABILITY", + "FORCE_MAJEURE", + "CHILD_CARE_14", + "CARE_LEAVE", + ), ) data class DispatchSheetReminderDto( @@ -252,6 +259,13 @@ data class DriverLeaveSummaryDto( val dailyNormMinutes: Int = 480, val balanceConfigured: Boolean = false, val overdueQuantity: Int = 0, + val visibleUsagePoolCodes: List = listOf( + "ANNUAL", + "ANNUAL_DISABILITY", + "FORCE_MAJEURE", + "CHILD_CARE_14", + "CARE_LEAVE", + ), val availableTypes: List = emptyList(), val reminders: List = emptyList(), ) diff --git a/app/src/main/java/pl/firmatpp/kierowca/ui/DriverApp.kt b/app/src/main/java/pl/firmatpp/kierowca/ui/DriverApp.kt index 76e24ee..0339120 100644 --- a/app/src/main/java/pl/firmatpp/kierowca/ui/DriverApp.kt +++ b/app/src/main/java/pl/firmatpp/kierowca/ui/DriverApp.kt @@ -1547,6 +1547,12 @@ private fun LeaveBalanceOverview(state: DriverUiState) { val summary = state.leaveSummary val totals = DriverLeaveRequestUiRules.annualTotals(summary) val norm = summary?.dailyNormMinutes ?: 480 + val showAnnualUsage = DriverLeaveRequestUiRules.isUsageVisible(summary, "ANNUAL") + val otherPools = DriverLeaveRequestUiRules.otherEntitlementPools(summary) + + if (summary != null && !showAnnualUsage && otherPools.isEmpty()) { + return + } Card( colors = CardDefaults.cardColors(containerColor = TppTheme.colors.card), @@ -1555,99 +1561,107 @@ private fun LeaveBalanceOverview(state: DriverUiState) { modifier = Modifier.fillMaxWidth(), ) { Column(Modifier.padding(18.dp), verticalArrangement = Arrangement.spacedBy(14.dp)) { - Text("Twój urlop wypoczynkowy", color = TppTheme.colors.ink, fontWeight = FontWeight.Bold, fontSize = 20.sp) + Text( + if (showAnnualUsage) "Twój urlop wypoczynkowy" else "Twoje limity nieobecności", + color = TppTheme.colors.ink, + fontWeight = FontWeight.Bold, + fontSize = 20.sp, + ) - when { - summary == null -> { - Text("Pobieramy aktualne saldo…", color = TppTheme.colors.muted) - } - !summary.balanceConfigured -> { - Text( - "Kadry przygotowują Twoje saldo", - color = Color(0xFF7A5A00), - fontWeight = FontWeight.Bold, - ) - Text( - "Możesz zapisać wniosek, ale jego godziny zostaną odjęte dopiero po potwierdzeniu puli urlopu.", - color = TppTheme.colors.muted, - ) - } - else -> { - Text("Pozostało do wykorzystania", color = TppTheme.colors.muted, fontWeight = FontWeight.SemiBold) - Text( - DriverLeaveRequestUiRules.formatQuantity(totals.availableMinutes, "minutes", norm), - color = TppTheme.colors.forest, - fontWeight = FontWeight.Bold, - fontSize = 26.sp, - ) - val denominator = (totals.grantedMinutes).coerceAtLeast(1) - LinearProgressIndicator( - progress = { (totals.usedMinutes.toFloat() / denominator).coerceIn(0f, 1f) }, - modifier = Modifier.fillMaxWidth().height(7.dp), - color = TppTheme.colors.forest, - trackColor = TppTheme.colors.successContainer, - ) - Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(10.dp)) { - LeaveBalanceStat( - title = "Wykorzystano", - value = DriverLeaveRequestUiRules.formatQuantity(totals.usedMinutes, "minutes", norm), - modifier = Modifier.weight(1f), - ) - LeaveBalanceStat( - title = "W przyszłych urlopach", - value = DriverLeaveRequestUiRules.formatQuantity(totals.reservedMinutes, "minutes", norm), - modifier = Modifier.weight(1f), - ) + if (showAnnualUsage) { + when { + summary == null -> { + Text("Pobieramy aktualne saldo…", color = TppTheme.colors.muted) } - } - } - - if (totals.overdueMinutes > 0) { - Row( - Modifier - .fillMaxWidth() - .background(TppTheme.colors.warningContainer, RoundedCornerShape(6.dp)) - .border(1.dp, TppTheme.colors.warningOutline, RoundedCornerShape(6.dp)) - .padding(12.dp), - horizontalArrangement = Arrangement.spacedBy(10.dp), - verticalAlignment = Alignment.Top, - ) { - Icon(Icons.Outlined.Info, contentDescription = null, tint = Color(0xFF7A5A00)) - Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(3.dp)) { - Text("Masz zaległy urlop", color = Color(0xFF7A5A00), fontWeight = FontWeight.Bold) + !summary.balanceConfigured -> { Text( - "${DriverLeaveRequestUiRules.formatQuantity(totals.overdueMinutes, "minutes", norm)} zaplanuj możliwie szybko, najpóźniej do 30 września. Saldo nie zniknie automatycznie.", + "Kadry przygotowują Twoje saldo", color = Color(0xFF7A5A00), - fontSize = 13.sp, + fontWeight = FontWeight.Bold, + ) + Text( + "Możesz zapisać wniosek, ale jego godziny zostaną odjęte dopiero po potwierdzeniu puli urlopu.", + color = TppTheme.colors.muted, + ) + } + else -> { + Text("Pozostało do wykorzystania", color = TppTheme.colors.muted, fontWeight = FontWeight.SemiBold) + Text( + DriverLeaveRequestUiRules.formatQuantity(totals.availableMinutes, "minutes", norm), + color = TppTheme.colors.forest, + fontWeight = FontWeight.Bold, + fontSize = 26.sp, + ) + val denominator = (totals.grantedMinutes).coerceAtLeast(1) + LinearProgressIndicator( + progress = { (totals.usedMinutes.toFloat() / denominator).coerceIn(0f, 1f) }, + modifier = Modifier.fillMaxWidth().height(7.dp), + color = TppTheme.colors.forest, + trackColor = TppTheme.colors.successContainer, + ) + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(10.dp)) { + LeaveBalanceStat( + title = "Wykorzystano", + value = DriverLeaveRequestUiRules.formatQuantity(totals.usedMinutes, "minutes", norm), + modifier = Modifier.weight(1f), + ) + LeaveBalanceStat( + title = "W przyszłych urlopach", + value = DriverLeaveRequestUiRules.formatQuantity(totals.reservedMinutes, "minutes", norm), + modifier = Modifier.weight(1f), + ) + } + } + } + + if (totals.overdueMinutes > 0) { + Row( + Modifier + .fillMaxWidth() + .background(TppTheme.colors.warningContainer, RoundedCornerShape(6.dp)) + .border(1.dp, TppTheme.colors.warningOutline, RoundedCornerShape(6.dp)) + .padding(12.dp), + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.Top, + ) { + Icon(Icons.Outlined.Info, contentDescription = null, tint = Color(0xFF7A5A00)) + Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(3.dp)) { + Text("Masz zaległy urlop", color = Color(0xFF7A5A00), fontWeight = FontWeight.Bold) + Text( + "${DriverLeaveRequestUiRules.formatQuantity(totals.overdueMinutes, "minutes", norm)} zaplanuj możliwie szybko, najpóźniej do 30 września. Saldo nie zniknie automatycznie.", + color = Color(0xFF7A5A00), + fontSize = 13.sp, + ) + } + } + } + + DriverLeaveRequestUiRules.annualPools(summary).forEach { pool -> + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { + Text( + if (pool.year < LocalDate.now().year) "Urlop zaległy z ${pool.year} r." else "Pula na ${pool.year} r.", + color = TppTheme.colors.muted, + ) + Text( + DriverLeaveRequestUiRules.formatQuantity(pool.availableQuantity, pool.unit, norm), + color = TppTheme.colors.ink, + fontWeight = FontWeight.Bold, + textAlign = TextAlign.End, ) } } } - DriverLeaveRequestUiRules.annualPools(summary).forEach { pool -> - Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { + if (otherPools.isNotEmpty()) { + if (showAnnualUsage) { + HorizontalDivider(color = TppTheme.colors.outline) Text( - if (pool.year < LocalDate.now().year) "Urlop zaległy z ${pool.year} r." else "Pula na ${pool.year} r.", - color = TppTheme.colors.muted, - ) - Text( - DriverLeaveRequestUiRules.formatQuantity(pool.availableQuantity, pool.unit, norm), + "Pozostałe dostępne limity", color = TppTheme.colors.ink, fontWeight = FontWeight.Bold, - textAlign = TextAlign.End, + fontSize = 17.sp, ) } - } - - val otherPools = DriverLeaveRequestUiRules.otherEntitlementPools(summary) - if (otherPools.isNotEmpty()) { - HorizontalDivider(color = TppTheme.colors.outline) - Text( - "Pozostałe dostępne limity", - color = TppTheme.colors.ink, - fontWeight = FontWeight.Bold, - fontSize = 17.sp, - ) Text( "Te limity są rozliczane osobno i nie zmniejszają zwykłego urlopu wypoczynkowego.", color = TppTheme.colors.muted, diff --git a/app/src/main/java/pl/firmatpp/kierowca/ui/DriverLeaveRequestUiRules.kt b/app/src/main/java/pl/firmatpp/kierowca/ui/DriverLeaveRequestUiRules.kt index ce0467f..445831c 100644 --- a/app/src/main/java/pl/firmatpp/kierowca/ui/DriverLeaveRequestUiRules.kt +++ b/app/src/main/java/pl/firmatpp/kierowca/ui/DriverLeaveRequestUiRules.kt @@ -106,6 +106,9 @@ object DriverLeaveRequestUiRules { .filter { it.poolCode == "ANNUAL" && it.status == "active" } .sortedByDescending { it.year } + fun isUsageVisible(summary: DriverLeaveSummaryDto?, poolCode: String): Boolean = + summary?.visibleUsagePoolCodes?.contains(poolCode) ?: true + fun otherEntitlementPools(summary: DriverLeaveSummaryDto?): List = summary?.pools.orEmpty() .filter { it.poolCode != "ANNUAL" && it.status == "active" } diff --git a/app/src/test/java/pl/firmatpp/kierowca/data/DriverLeaveApiContractTest.kt b/app/src/test/java/pl/firmatpp/kierowca/data/DriverLeaveApiContractTest.kt index b3a1f47..a9486dc 100644 --- a/app/src/test/java/pl/firmatpp/kierowca/data/DriverLeaveApiContractTest.kt +++ b/app/src/test/java/pl/firmatpp/kierowca/data/DriverLeaveApiContractTest.kt @@ -19,6 +19,7 @@ class DriverLeaveApiContractTest { "dailyNormMinutes": 480, "balanceConfigured": true, "overdueQuantity": 480, + "visibleUsagePoolCodes": ["ANNUAL", "CHILD_CARE_14"], "pools": [{ "id": 7, "poolCode": "ANNUAL", @@ -49,6 +50,7 @@ class DriverLeaveApiContractTest { ) assertEquals(480, response.data.dailyNormMinutes) + assertEquals(listOf("ANNUAL", "CHILD_CARE_14"), response.data.visibleUsagePoolCodes) assertEquals(7680, response.data.pools.single().availableQuantity) assertEquals("URLOP", response.data.availableTypes.single().value) assertEquals("ANNUAL", response.data.availableTypes.single().code) diff --git a/app/src/test/java/pl/firmatpp/kierowca/ui/DriverLeaveRequestUiRulesTest.kt b/app/src/test/java/pl/firmatpp/kierowca/ui/DriverLeaveRequestUiRulesTest.kt index 22b3b84..0a90fd4 100644 --- a/app/src/test/java/pl/firmatpp/kierowca/ui/DriverLeaveRequestUiRulesTest.kt +++ b/app/src/test/java/pl/firmatpp/kierowca/ui/DriverLeaveRequestUiRulesTest.kt @@ -124,6 +124,13 @@ class DriverLeaveRequestUiRulesTest { assertEquals(listOf("CHILD_CARE_14", "CARE_LEAVE"), pools.map { it.poolCode }) assertEquals("Urlop opiekuńczy", DriverLeaveRequestUiRules.poolLabel("CARE_LEAVE")) assertEquals("Rodzina i opieka", DriverLeaveRequestUiRules.categoryLabel("family")) + assertTrue(DriverLeaveRequestUiRules.isUsageVisible(summary, "ANNUAL")) + assertFalse( + DriverLeaveRequestUiRules.isUsageVisible( + summary.copy(visibleUsagePoolCodes = emptyList()), + "ANNUAL", + ), + ) } @Test