From af0e7a76de3f1a20c8e05cc5b6579c2d7e89757d Mon Sep 17 00:00:00 2001 From: Oqba Date: Fri, 16 Oct 2026 20:25:58 +0330 Subject: [PATCH] =?UTF-8?q?=D8=A7=D8=B5=D9=84=D8=A7=D8=AD=20=D8=A7=D8=B3?= =?UTF-8?q?=DA=A9=D8=B1=D9=88=D9=84=20=D8=B5=D9=81=D8=AD=D9=87=20=D8=AA?= =?UTF-8?q?=D9=86=D8=B8=DB=8C=D9=85=D8=A7=D8=AA=D8=8C=20=D8=B2=DB=8C=D8=A8?= =?UTF-8?q?=D8=A7=D8=B3=D8=A7=D8=B2=DB=8C=20=D8=AD=D8=A7=D9=84=D8=AA=20?= =?UTF-8?q?=D8=A7=D9=BE=D8=B1=D8=A7=D8=AA=D9=88=D8=B1=20=D9=88=20=D8=A7?= =?UTF-8?q?=D9=86=D8=AA=D9=82=D8=A7=D9=84=20=D9=84=DB=8C=D8=B3=D8=AA=20?= =?UTF-8?q?=D8=A7=D8=B3=D8=A7=D9=85=DB=8C=20=D8=A8=D8=AF=D9=87=DA=A9=D8=A7?= =?UTF-8?q?=D8=B1=D8=A7=D9=86=20=D8=A8=D9=87=20=DA=AF=D8=B2=D8=A7=D8=B1?= =?UTF-8?q?=D8=B4=20=D9=85=D8=A7=D9=84=DB=8C=20(=D9=86=D8=B3=D8=AE=D9=87?= =?UTF-8?q?=201.0.9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 4 +- .../ui/screens/PersonScreen.kt | 71 ++++++---- .../ui/screens/SettingsScreen.kt | 130 +++++++++++------- update.json | 8 +- 4 files changed, 129 insertions(+), 84 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3d17582..21994dd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -30,8 +30,8 @@ android { applicationId = "com.oqba26.monthlypaymentapp" minSdk = 25 targetSdk = 34 - versionCode = 9 - versionName = "1.0.8" + versionCode = 10 + versionName = "1.0.9" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary = true } } diff --git a/app/src/main/java/com/oqba26/monthlypaymentapp/ui/screens/PersonScreen.kt b/app/src/main/java/com/oqba26/monthlypaymentapp/ui/screens/PersonScreen.kt index f559da7..21cf272 100644 --- a/app/src/main/java/com/oqba26/monthlypaymentapp/ui/screens/PersonScreen.kt +++ b/app/src/main/java/com/oqba26/monthlypaymentapp/ui/screens/PersonScreen.kt @@ -1117,39 +1117,22 @@ fun DashboardCard( if (financialReportData.totalOverdueDebt > 0 || financialReportData.debtors.isNotEmpty()) { HorizontalDivider(modifier = Modifier.padding(vertical = 2.dp)) - Column( + Row( modifier = Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(4.dp) + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = "🔴 مجموع بدهی‌های معوقه:", - style = MaterialTheme.typography.titleSmall, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.error - ) - Text( - text = "${formatNumberAsPersian(financialReportData.totalOverdueDebt)} تومان", - style = MaterialTheme.typography.bodyMedium, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.error - ) - } - - val debtorNamesText = financialReportData.debtors.joinToString("، ") { - "${it.personName} (${formatNumberAsPersian(it.totalDebtAmount)})" - } - Text( - text = "بدهکاران (${financialReportData.totalDebtorsCount.toString().toPersianDigits()} نفر): $debtorNamesText", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - maxLines = 3, - overflow = TextOverflow.Ellipsis + text = "🔴 مجموع بدهی‌های معوقه:", + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colorScheme.error + ) + Text( + text = "${formatNumberAsPersian(financialReportData.totalOverdueDebt)} تومان", + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colorScheme.error ) } } @@ -1237,6 +1220,34 @@ fun FinancialReportDialog( } } + if (data.debtors.isNotEmpty()) { + Spacer(modifier = Modifier.height(8.dp)) + Card( + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.errorContainer.copy(alpha = 0.15f)) + ) { + Column( + modifier = Modifier.padding(12.dp), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = "لیست بدهکاران (${data.totalDebtorsCount.toString().toPersianDigits()} نفر):", + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colorScheme.error + ) + val debtorNamesText = data.debtors.joinToString("، ") { + "${it.personName} (${formatNumberAsPersian(it.totalDebtAmount)})" + } + Text( + text = debtorNamesText, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + } + } + Spacer(modifier = Modifier.height(12.dp)) HorizontalDivider() Spacer(modifier = Modifier.height(8.dp)) diff --git a/app/src/main/java/com/oqba26/monthlypaymentapp/ui/screens/SettingsScreen.kt b/app/src/main/java/com/oqba26/monthlypaymentapp/ui/screens/SettingsScreen.kt index aebfa90..68df4d2 100644 --- a/app/src/main/java/com/oqba26/monthlypaymentapp/ui/screens/SettingsScreen.kt +++ b/app/src/main/java/com/oqba26/monthlypaymentapp/ui/screens/SettingsScreen.kt @@ -5,24 +5,32 @@ import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.animation.AnimatedContent import androidx.compose.foundation.clickable +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.Logout import androidx.compose.material.icons.filled.Add +import androidx.compose.material.icons.filled.AdminPanelSettings import androidx.compose.material.icons.filled.ArrowDropDown import androidx.compose.material.icons.filled.ContentCopy import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Edit +import androidx.compose.material.icons.filled.Lock +import androidx.compose.material.icons.filled.LockOpen import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.input.PasswordVisualTransformation @@ -136,16 +144,18 @@ fun SettingsScreen(onLogout: () -> Unit) { } ) + val scrollState = rememberScrollState() + Column( modifier = Modifier - .padding(horizontal = 16.dp, vertical = 8.dp) - .fillMaxWidth() - .fillMaxHeight() + .fillMaxSize() + .verticalScroll(scrollState) + .padding(horizontal = 16.dp, vertical = 12.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) ) { Text( stringResource(R.string.settings), - style = MaterialTheme.typography.titleMedium, - modifier = Modifier.padding(bottom = 8.dp) + style = MaterialTheme.typography.titleMedium ) DefaultAmountSetting( @@ -163,16 +173,12 @@ fun SettingsScreen(onLogout: () -> Unit) { onChangePin = { viewModel.setAdminPin(it) } ) - Spacer(Modifier.weight(1f)) - val reminderDay by viewModel.reminderDay.collectAsState() ReminderDaySetting( currentDay = reminderDay, onSave = { viewModel.saveReminderDay(it) } ) - Spacer(Modifier.weight(1f)) - val cardNumbers by viewModel.cardNumbers.collectAsState() CardNumbersSetting( cardNumbers = cardNumbers, @@ -181,20 +187,17 @@ fun SettingsScreen(onLogout: () -> Unit) { onRemove = { viewModel.removeCardNumber(it) } ) - Spacer(Modifier.weight(1f)) - FontSelectionDropdown( selectedFont = selectedFont, onFontSelected = { viewModel.onFontSelected(it) } ) if (!isOperatorMode) { - HorizontalDivider(modifier = Modifier.padding(vertical = 16.dp)) + HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp)) Text( "پشتیبان‌گیری و بازیابی", - style = MaterialTheme.typography.titleMedium, - modifier = Modifier.padding(bottom = 8.dp) + style = MaterialTheme.typography.titleMedium ) Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) { @@ -224,24 +227,26 @@ fun SettingsScreen(onLogout: () -> Unit) { viewModel.loadSnapshots() showSnapshotDialog = true }, - modifier = Modifier.fillMaxWidth().padding(top = 8.dp) + modifier = Modifier.fillMaxWidth() ) { Text(stringResource(R.string.auto_backup_button), fontSize = 13.sp) } } - Spacer(Modifier.weight(1f)) + Spacer(Modifier.height(8.dp)) Button( onClick = onLogout, modifier = Modifier.fillMaxWidth(), colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.error), - contentPadding = androidx.compose.foundation.layout.PaddingValues(vertical = 8.dp) + contentPadding = PaddingValues(vertical = 12.dp) ) { Icon(Icons.AutoMirrored.Filled.Logout, contentDescription = null) Spacer(Modifier.width(8.dp)) Text(stringResource(R.string.logout)) } + + Spacer(Modifier.height(16.dp)) } if (showSnapshotDialog) { @@ -621,43 +626,71 @@ fun OperatorModeSetting( Card( modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(16.dp), colors = CardDefaults.cardColors( - containerColor = if (isOperatorMode) MaterialTheme.colorScheme.errorContainer.copy(alpha = 0.2f) else MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.2f) + containerColor = if (isOperatorMode) MaterialTheme.colorScheme.errorContainer.copy(alpha = 0.15f) else MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f) ) ) { - Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) { - Row(verticalAlignment = Alignment.CenterVertically) { - Column(modifier = Modifier.weight(1f)) { - Text("حالت دسترسی برنامه", style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.Bold) - Text( - if (isOperatorMode) "وضعیت فعلی: حالت اپراتور (محدود)" else "وضعیت فعلی: حالت مدیریت (کامل)", - style = MaterialTheme.typography.bodySmall, - color = if (isOperatorMode) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth() + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + Icon( + imageVector = if (isOperatorMode) Icons.Default.Lock else Icons.Default.AdminPanelSettings, + contentDescription = null, + tint = if (isOperatorMode) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary, + modifier = Modifier.size(24.dp) ) + Spacer(modifier = Modifier.width(8.dp)) + Column { + Text( + text = "حالت دسترسی برنامه", + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Bold + ) + Text( + text = if (isOperatorMode) "وضعیت فعلی: حالت اپراتور (محدود)" else "وضعیت فعلی: حالت مدیریت (کامل)", + style = MaterialTheme.typography.bodySmall, + color = if (isOperatorMode) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary + ) + } } } - Row(horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.fillMaxWidth()) { - if (isOperatorMode) { + HorizontalDivider(thickness = 0.5.dp) + + if (isOperatorMode) { + Button( + onClick = { + pinAction = PinAction.UNLOCK_ADMIN + enteredPin = "" + errorMessage = "" + showPinDialog = true + }, + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(10.dp) + ) { + Icon(Icons.Default.LockOpen, contentDescription = null, modifier = Modifier.size(18.dp)) + Spacer(modifier = Modifier.width(6.dp)) + Text("خروج از حالت اپراتور (ورود رمز مدیر)") + } + } else { + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + modifier = Modifier.fillMaxWidth() + ) { Button( - onClick = { - pinAction = PinAction.UNLOCK_ADMIN - enteredPin = "" - errorMessage = "" - showPinDialog = true - }, - modifier = Modifier.fillMaxWidth() + onClick = { onToggleMode(true) }, + modifier = Modifier.weight(1f), + shape = RoundedCornerShape(10.dp) ) { - Text("خروج از حالت اپراتور") - } - } else { - Button( - onClick = { - onToggleMode(true) - }, - modifier = Modifier.weight(1f) - ) { - Text("فعال‌سازی حالت اپراتور") + Text("فعال‌سازی حالت اپراتور", style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Bold) } OutlinedButton( @@ -668,9 +701,10 @@ fun OperatorModeSetting( errorMessage = "" showPinDialog = true }, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), + shape = RoundedCornerShape(10.dp) ) { - Text("تغییر رمز مدیر") + Text("تغییر رمز مدیر", style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Bold) } } } diff --git a/update.json b/update.json index 25931f9..7c7eb25 100644 --- a/update.json +++ b/update.json @@ -1,7 +1,7 @@ { - "versionCode": 9, - "versionName": "1.0.8", - "url": "https://github.com/oqba26/MonthlyPaymentApp/releases/download/v1.0.8/MonthlyPaymentApp-v1.0.8.apk", - "releaseNotes": "بهبودهای تب مسجد و افزودن حالت اپراتور (محدودسازی دسترسی)", + "versionCode": 10, + "versionName": "1.0.9", + "url": "https://github.com/oqba26/MonthlyPaymentApp/releases/download/v1.0.9/MonthlyPaymentApp-v1.0.9.apk", + "releaseNotes": "اصلاح اسکرول صفحه تنظیمات، بهبود ظاهری کارت حالت دسترسی و انتقال لیست اسامی بدهکاران به گزارش مالی", "isForceUpdate": false }