From 0ae8fa19bc3b45392563d70f9bc9f1184a998cb1 Mon Sep 17 00:00:00 2001 From: AmirmahdiNourkazemi Date: Sun, 7 Jun 2026 23:53:51 +0330 Subject: [PATCH] style --- .../pharmacy/presentation/common/CustomBox.kt | 28 +- .../presentation/screens/DrugDetailScreen.kt | 603 ++++++++---------- .../approagency/pharmacy/ui/theme/Color.kt | 2 +- .../approagency/pharmacy/ui/theme/Theme.kt | 124 ++-- 4 files changed, 373 insertions(+), 384 deletions(-) diff --git a/app/src/main/java/com/approagency/pharmacy/presentation/common/CustomBox.kt b/app/src/main/java/com/approagency/pharmacy/presentation/common/CustomBox.kt index f165366..2592014 100644 --- a/app/src/main/java/com/approagency/pharmacy/presentation/common/CustomBox.kt +++ b/app/src/main/java/com/approagency/pharmacy/presentation/common/CustomBox.kt @@ -1,25 +1,31 @@ package com.approagency.pharmacy.presentation.common + import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.layout.Box import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.unit.dp @Composable - fun CustomBox( - modifier: Modifier? = Modifier, - child: @Composable ()-> Unit + modifier: Modifier = Modifier, + child: @Composable () -> Unit ) { - if (modifier != null) { - Box( - modifier = modifier.clip(shape = MaterialTheme.shapes.large).background( - color = MaterialTheme.colorScheme.surfaceContainer + val shape = MaterialTheme.shapes.large + Box( + modifier = modifier + .clip(shape) + .background(color = MaterialTheme.colorScheme.surfaceContainerLowest) + .border( + width = 1.dp, + color = MaterialTheme.colorScheme.outlineVariant, + shape = shape ) - ) { - child() - } + ) { + child() } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/approagency/pharmacy/presentation/screens/DrugDetailScreen.kt b/app/src/main/java/com/approagency/pharmacy/presentation/screens/DrugDetailScreen.kt index 6b73200..73fda80 100644 --- a/app/src/main/java/com/approagency/pharmacy/presentation/screens/DrugDetailScreen.kt +++ b/app/src/main/java/com/approagency/pharmacy/presentation/screens/DrugDetailScreen.kt @@ -1,8 +1,12 @@ package com.approagency.pharmacy.presentation.screens +import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -15,9 +19,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.Info -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.Divider import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -39,8 +40,10 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.draw.clip import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -52,6 +55,7 @@ import com.approagency.pharmacy.presentation.common.Loading import com.approagency.pharmacy.presentation.viewModel.DrugDetailViewModel import com.approagency.pharmacy.presentation.viewModel.DrugDetailYabState import com.vada.caller.ui.theme.LocalDime +import com.vada.caller.ui.theme.dime import org.koin.androidx.compose.koinViewModel @OptIn(ExperimentalMaterial3Api::class) @@ -85,17 +89,21 @@ fun DrugDetailScreen( ) if (state.drugDetail.englishName.isNotEmpty()) { Text( - text = state.drugDetail.englishName.take(30), - fontSize = 11.sp, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f), - maxLines = 1 + text = state.drugDetail.englishName, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + maxLines = 1, + overflow = TextOverflow.Ellipsis ) } } } else -> { - Text("جزئیات دارو", fontSize = 16.sp) + Text( + text = "جزئیات دارو", + style = MaterialTheme.typography.titleMedium + ) } } }, @@ -157,7 +165,7 @@ fun DrugDetailScreen( text = { Text( text = title, - fontSize = 13.sp, + style = MaterialTheme.typography.labelLarge, fontWeight = if (selectedTab == index) FontWeight.Bold else FontWeight.Normal, maxLines = 1 ) @@ -170,8 +178,8 @@ fun DrugDetailScreen( LazyColumn( modifier = Modifier .fillMaxSize() - .padding(horizontal = dime.md) - .padding(top = dime.md), + .padding(horizontal = dime.md), + contentPadding = PaddingValues(top = dime.md, bottom = dime.xxl), verticalArrangement = Arrangement.spacedBy(dime.md) ) { when (selectedTab) { @@ -219,63 +227,60 @@ fun ManufacturerInfoCard( modifier: Modifier = Modifier ) { val dime = LocalDime.current + val onContainer = MaterialTheme.colorScheme.onSecondaryContainer - Card( - modifier = modifier.fillMaxWidth(), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.15f) - ), - shape = RoundedCornerShape(dime.sm) + Column( + modifier = modifier + .fillMaxWidth() + .clip(MaterialTheme.shapes.large) + .background(MaterialTheme.colorScheme.secondaryContainer) + .padding(dime.md), + verticalArrangement = Arrangement.spacedBy(dime.sm) ) { - Column( - modifier = Modifier.padding(dime.md), - verticalArrangement = Arrangement.spacedBy(dime.xs) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(dime.sm) ) { + Icon( + imageVector = Icons.Default.Info, + contentDescription = null, + modifier = Modifier.size(18.dp), + tint = onContainer + ) + Text( + text = "سازنده:", + style = MaterialTheme.typography.labelLarge, + color = onContainer + ) + Text( + text = manufacturer, + style = MaterialTheme.typography.bodyMedium, + color = onContainer + ) + } + + if (genericInfo != null) { Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(dime.xs) + horizontalArrangement = Arrangement.spacedBy(dime.sm) ) { Icon( imageVector = Icons.Default.Info, contentDescription = null, modifier = Modifier.size(18.dp), - tint = MaterialTheme.colorScheme.primary + tint = onContainer ) Text( - text = "سازنده:", - fontWeight = FontWeight.Bold, - fontSize = 13.sp + text = "ماده موثره:", + style = MaterialTheme.typography.labelLarge, + color = onContainer ) Text( - text = manufacturer, - fontSize = 13.sp, - color = MaterialTheme.colorScheme.primary + text = genericInfo.persianName, + style = MaterialTheme.typography.bodyMedium, + color = onContainer ) } - - if (genericInfo != null) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(dime.xs) - ) { - Icon( - imageVector = Icons.Default.Info, - contentDescription = null, - modifier = Modifier.size(18.dp), - tint = MaterialTheme.colorScheme.primary - ) - Text( - text = "ماده موثره:", - fontWeight = FontWeight.Bold, - fontSize = 13.sp - ) - Text( - text = genericInfo.persianName, - fontSize = 13.sp, - color = MaterialTheme.colorScheme.primary - ) - } - } } } } @@ -308,44 +313,13 @@ fun GeneralInfoTabContent(drugDetail: DrugDetail) { else { // Categories Card if (drugDetail.drugClass != null || drugDetail.therapeuticClass != null) { - Card( - modifier = Modifier.fillMaxWidth(), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.2f) - ), - shape = RoundedCornerShape(dime.sm) - ) { - Column( - modifier = Modifier.padding(dime.md), - verticalArrangement = Arrangement.spacedBy(dime.xs) - ) { + DetailCard { + Column(verticalArrangement = Arrangement.spacedBy(dime.xs)) { drugDetail.drugClass?.let { - Row { - Text( - text = "طبقه بندی مارتیندل: ", - fontWeight = FontWeight.Bold, - fontSize = 13.sp - ) - Text( - text = it, - fontSize = 13.sp, - color = MaterialTheme.colorScheme.primary - ) - } + LabeledRow(label = "طبقه بندی مارتیندل", value = it) } drugDetail.therapeuticClass?.let { - Row { - Text( - text = "طبقه درمانی: ", - fontWeight = FontWeight.Bold, - fontSize = 13.sp - ) - Text( - text = it, - fontSize = 13.sp, - color = MaterialTheme.colorScheme.primary - ) - } + LabeledRow(label = "طبقه درمانی", value = it) } } } @@ -353,39 +327,36 @@ fun GeneralInfoTabContent(drugDetail: DrugDetail) { // Pregnancy Card if (drugDetail.pregnancyCategory != null || drugDetail.pregnancyDescription != null) { - Card( - modifier = Modifier.fillMaxWidth(), - colors = CardDefaults.cardColors( - containerColor = Color(0xFFFFF3E0) - ), - shape = RoundedCornerShape(dime.sm) + val onContainer = MaterialTheme.colorScheme.onTertiaryContainer + Column( + modifier = Modifier + .fillMaxWidth() + .clip(MaterialTheme.shapes.large) + .background(MaterialTheme.colorScheme.tertiaryContainer) + .padding(dime.md), + verticalArrangement = Arrangement.spacedBy(dime.xs) ) { - Column( - modifier = Modifier.padding(dime.md), - verticalArrangement = Arrangement.spacedBy(dime.xs) - ) { + Text( + text = "مصرف در بارداری", + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.Bold, + color = onContainer + ) + drugDetail.pregnancyCategory?.let { Text( - text = "مصرف در بارداری", - fontWeight = FontWeight.Bold, - fontSize = 15.sp, - color = Color(0xFFE65100) + text = "گروه: $it", + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Medium, + color = onContainer + ) + } + drugDetail.pregnancyDescription?.let { + Text( + text = it, + style = MaterialTheme.typography.bodySmall, + lineHeight = 18.sp, + color = onContainer.copy(alpha = 0.9f) ) - drugDetail.pregnancyCategory?.let { - Text( - text = "گروه: $it", - fontSize = 13.sp, - fontWeight = FontWeight.Medium - ) - } - drugDetail.pregnancyDescription?.let { - Spacer(modifier = Modifier.height(dime.xs)) - Text( - text = it, - fontSize = 12.sp, - lineHeight = 18.sp, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.8f) - ) - } } } } @@ -427,19 +398,7 @@ fun GeneralInfoTabContent(drugDetail: DrugDetail) { drugDetail.generalInfo.isNullOrBlank() && drugDetail.specializedInfo.isNullOrBlank() ) { - Box( - modifier = Modifier - .fillMaxWidth() - .padding(32.dp), - contentAlignment = Alignment.Center - ) { - Text( - text = "اطلاعات عمومی برای این دارو ثبت نشده است", - fontSize = 13.sp, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f), - textAlign = TextAlign.Center - ) - } + DetailEmptyState(text = "اطلاعات عمومی برای این دارو ثبت نشده است") } } else { // ========== صفحات برند (Brand) ========== @@ -465,19 +424,9 @@ fun GeneralInfoTabContent(drugDetail: DrugDetail) { drugDetail.sideEffects == null && drugDetail.warnings == null ) { - Box( - modifier = Modifier - .fillMaxWidth() - .padding(32.dp), - contentAlignment = Alignment.Center - ) { - Text( - text = "اطلاعات عمومی برای این برند ثبت نشده است.\nبرای مشاهده اطلاعات کامل، به صفحه داروی ژنریک مراجعه کنید.", - fontSize = 13.sp, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f), - textAlign = TextAlign.Center - ) - } + DetailEmptyState( + text = "اطلاعات عمومی برای این برند ثبت نشده است.\nبرای مشاهده اطلاعات کامل، به صفحه داروی ژنریک مراجعه کنید." + ) } } } @@ -525,22 +474,12 @@ fun SpecializedInfoTabContent(drugDetail: DrugDetail) { drugDetail.sideEffects == null && drugDetail.warnings == null ) { - Box( - modifier = Modifier - .fillMaxWidth() - .padding(32.dp), - contentAlignment = Alignment.Center - ) { - Text( - text = if (drugDetail.isGeneric) - "اطلاعات تخصصی برای این دارو ثبت نشده است" - else - "اطلاعات تخصصی برای این برند ثبت نشده است.\nبرای مشاهده اطلاعات کامل، به صفحه داروی ژنریک مراجعه کنید.", - fontSize = 13.sp, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f), - textAlign = TextAlign.Center - ) - } + DetailEmptyState( + text = if (drugDetail.isGeneric) + "اطلاعات تخصصی برای این دارو ثبت نشده است" + else + "اطلاعات تخصصی برای این برند ثبت نشده است.\nبرای مشاهده اطلاعات کامل، به صفحه داروی ژنریک مراجعه کنید." + ) } } } @@ -551,89 +490,54 @@ fun DosageFormsTabContent(drugDetail: DrugDetail) { val dosageForms = drugDetail.dosageForms if (dosageForms.isEmpty()) { - Box( - modifier = Modifier - .fillMaxWidth() - .padding(32.dp), - contentAlignment = Alignment.Center - ) { - Text( - text = if (drugDetail.isGeneric) - "اشکال دارویی برای این دارو ثبت نشده است" - else - "سایر اشکال دارویی این برند ثبت نشده است", - fontSize = 13.sp, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f), - textAlign = TextAlign.Center - ) - } + DetailEmptyState( + text = if (drugDetail.isGeneric) + "اشکال دارویی برای این دارو ثبت نشده است" + else + "سایر اشکال دارویی این برند ثبت نشده است" + ) } else { Column(verticalArrangement = Arrangement.spacedBy(dime.sm)) { // اگر صفحه برند است، عنوان متفاوت نشان بده if (!drugDetail.isGeneric) { - Text( - text = "سایر محصولات این برند", - fontWeight = FontWeight.Bold, - fontSize = 14.sp, - color = MaterialTheme.colorScheme.primary, + SectionHeader( + title = "سایر محصولات این برند", modifier = Modifier.padding(bottom = dime.xs) ) } dosageForms.forEach { form -> - Card( - modifier = Modifier.fillMaxWidth(), - elevation = CardDefaults.cardElevation(defaultElevation = 1.dp), - shape = RoundedCornerShape(dime.sm) - ) { - Column( - modifier = Modifier.padding(dime.md), - verticalArrangement = Arrangement.spacedBy(dime.xs) - ) { + DetailCard { + Text( + text = form.persianName, + style = MaterialTheme.typography.titleSmall + ) + if (form.englishName.isNotBlank()) { + Spacer(modifier = Modifier.height(dime.xxs)) Text( - text = form.persianName, - fontWeight = FontWeight.Medium, - fontSize = 14.sp + text = form.englishName, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant ) - if (form.englishName.isNotBlank()) { - Text( - text = form.englishName, - fontSize = 11.sp, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) - ) - } + } - // نشانگرهای خطر - if (form.isHighRisk || form.isVital) { - Row( - horizontalArrangement = Arrangement.spacedBy(dime.xs) - ) { - if (form.isHighRisk) { - androidx.compose.material3.Surface( - shape = RoundedCornerShape(4.dp), - color = Color(0xFFFFEBEE) - ) { - Text( - text = "پرخطر", - fontSize = 10.sp, - color = Color(0xFFC62828), - modifier = Modifier.padding(horizontal = 6.dp, vertical = dime.xxs) - ) - } - } - if (form.isVital) { - androidx.compose.material3.Surface( - shape = RoundedCornerShape(4.dp), - color = Color(0xFFE8F5E9) - ) { - Text( - text = "حیاتی", - fontSize = 10.sp, - color = Color(0xFF2E7D32), - modifier = Modifier.padding(horizontal = 6.dp, vertical = dime.xxs) - ) - } - } + // نشانگرهای خطر + if (form.isHighRisk || form.isVital) { + Spacer(modifier = Modifier.height(dime.sm)) + Row(horizontalArrangement = Arrangement.spacedBy(dime.xs)) { + if (form.isHighRisk) { + TagChip( + text = "پرخطر", + container = MaterialTheme.colorScheme.errorContainer, + onContainer = MaterialTheme.colorScheme.onErrorContainer + ) + } + if (form.isVital) { + TagChip( + text = "حیاتی", + container = MaterialTheme.colorScheme.primaryContainer, + onContainer = MaterialTheme.colorScheme.onPrimaryContainer + ) } } } @@ -648,83 +552,31 @@ fun BrandNamesTabContent(drugDetail: DrugDetail) { val dime = LocalDime.current if (drugDetail.isGeneric && drugDetail.brandNames.isEmpty()) { - Box( - modifier = Modifier - .fillMaxWidth() - .padding(32.dp), - contentAlignment = Alignment.Center - ) { - Text( - text = "اسامی تجاری برای این دارو ثبت نشده است", - fontSize = 13.sp, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f), - textAlign = TextAlign.Center - ) - } + DetailEmptyState(text = "اسامی تجاری برای این دارو ثبت نشده است") } else if (drugDetail.isGeneric && drugDetail.brandNames.isNotEmpty()) { Column(verticalArrangement = Arrangement.spacedBy(dime.sm)) { drugDetail.brandNames.forEach { brand -> - Card( - modifier = Modifier.fillMaxWidth(), - elevation = CardDefaults.cardElevation(defaultElevation = 1.dp), - shape = RoundedCornerShape(dime.sm) - ) { - Column( - modifier = Modifier.padding(dime.md), - verticalArrangement = Arrangement.spacedBy(dime.xs) - ) { - Text( - text = brand.persianName, - fontWeight = FontWeight.Medium, - fontSize = 14.sp - ) - brand.manufacturer?.let { - Row { - Text( - text = "تولید کننده: ", - fontSize = 12.sp, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) - ) - Text( - text = it, - fontSize = 12.sp, - color = MaterialTheme.colorScheme.primary - ) - } - } - brand.importer?.let { - Row { - Text( - text = "وارد کننده: ", - fontSize = 12.sp, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) - ) - Text( - text = it, - fontSize = 12.sp, - color = MaterialTheme.colorScheme.primary - ) - } - } + DetailCard { + Text( + text = brand.persianName, + style = MaterialTheme.typography.titleSmall + ) + brand.manufacturer?.let { + Spacer(modifier = Modifier.height(dime.xs)) + LabeledRow(label = "تولید کننده", value = it) + } + brand.importer?.let { + Spacer(modifier = Modifier.height(dime.xxs)) + LabeledRow(label = "وارد کننده", value = it) } } } } } else { // صفحه برند است - اسامی تجاری برای برند معنی ندارد - Box( - modifier = Modifier - .fillMaxWidth() - .padding(32.dp), - contentAlignment = Alignment.Center - ) { - Text( - text = "این صفحه مربوط به یک محصول تجاری است. برای مشاهده اسامی تجاری سایر برندها، به صفحه داروی ژنریک مراجعه کنید.", - fontSize = 13.sp, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f), - textAlign = TextAlign.Center - ) - } + DetailEmptyState( + text = "این صفحه مربوط به یک محصول تجاری است. برای مشاهده اسامی تجاری سایر برندها، به صفحه داروی ژنریک مراجعه کنید." + ) } } @@ -736,29 +588,136 @@ fun InfoSectionCard( ) { val dime = LocalDime.current - Card( - modifier = modifier.fillMaxWidth(), - elevation = CardDefaults.cardElevation(defaultElevation = 1.dp), - shape = RoundedCornerShape(dime.sm) - ) { - Column( - modifier = Modifier.padding(dime.md), - verticalArrangement = Arrangement.spacedBy(dime.xs) - ) { - Text( - text = title, - fontWeight = FontWeight.Bold, - fontSize = 15.sp, - color = MaterialTheme.colorScheme.primary - ) - Divider(color = MaterialTheme.colorScheme.outline.copy(alpha = 0.2f)) - Text( - text = content, - fontSize = 13.sp, - lineHeight = 20.sp, - textAlign = TextAlign.Justify, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.85f) - ) - } + DetailCard(modifier = modifier) { + SectionHeader(title = title) + Spacer(modifier = Modifier.height(dime.sm)) + Text( + text = content, + style = MaterialTheme.typography.bodyMedium, + lineHeight = 22.sp, + textAlign = TextAlign.Justify, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) } +} + +/** + * کارت پایه‌ی صفحه‌ی جزئیات — ظاهر یکدست با بقیه‌ی برنامه: + * سطح روشن + قاب نازک هم‌رنگ تم، بدون سایه‌ی سنگین. + */ +@Composable +private fun DetailCard( + modifier: Modifier = Modifier, + content: @Composable ColumnScope.() -> Unit +) { + val shape = MaterialTheme.shapes.large + Column( + modifier = modifier + .fillMaxWidth() + .clip(shape) + .background(MaterialTheme.colorScheme.surfaceContainerLowest) + .border( + width = 1.dp, + color = MaterialTheme.colorScheme.outlineVariant, + shape = shape + ) + .padding(MaterialTheme.dime.md), + content = content + ) +} + +/** سربرگ بخش با نوار تأکید کوچک کنار عنوان. */ +@Composable +private fun SectionHeader( + title: String, + modifier: Modifier = Modifier +) { + val dime = LocalDime.current + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(dime.sm) + ) { + Box( + modifier = Modifier + .size(width = 4.dp, height = 18.dp) + .clip(RoundedCornerShape(dime.xxs)) + .background(MaterialTheme.colorScheme.primary) + ) + Text( + text = title, + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colorScheme.primary + ) + } +} + +/** حالت «اطلاعاتی ثبت نشده» با آیکن، یکدست در همه‌ی تب‌ها. */ +@Composable +private fun DetailEmptyState( + text: String, + modifier: Modifier = Modifier +) { + val dime = LocalDime.current + Column( + modifier = modifier + .fillMaxWidth() + .padding(vertical = dime.xxl, horizontal = dime.lg), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(dime.sm) + ) { + Icon( + imageVector = Icons.Default.Info, + contentDescription = null, + modifier = Modifier.size(40.dp), + tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f) + ) + Text( + text = text, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + textAlign = TextAlign.Center + ) + } +} + +/** ردیف «برچسب: مقدار» با تایپوگرافی یکدست. */ +@Composable +private fun LabeledRow( + label: String, + value: String, + modifier: Modifier = Modifier +) { + Row(modifier = modifier) { + Text( + text = "$label: ", + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onSurface + ) + Text( + text = value, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.primary, + modifier = Modifier.weight(1f) + ) + } +} + +/** برچسب کوچک رنگی (مثل «پرخطر» / «حیاتی»). */ +@Composable +private fun TagChip( + text: String, + container: Color, + onContainer: Color +) { + Text( + text = text, + style = MaterialTheme.typography.labelSmall, + color = onContainer, + modifier = Modifier + .clip(RoundedCornerShape(MaterialTheme.dime.xs)) + .background(container) + .padding(horizontal = MaterialTheme.dime.sm, vertical = MaterialTheme.dime.xxs) + ) } \ No newline at end of file diff --git a/app/src/main/java/com/approagency/pharmacy/ui/theme/Color.kt b/app/src/main/java/com/approagency/pharmacy/ui/theme/Color.kt index 4c18201..1da8c87 100644 --- a/app/src/main/java/com/approagency/pharmacy/ui/theme/Color.kt +++ b/app/src/main/java/com/approagency/pharmacy/ui/theme/Color.kt @@ -1,3 +1,3 @@ package com.approagency.pharmacy.ui.theme -// رنگ‌های برنامه در MaterialThemeExt.kt (MedicalColors و ColorScheme ها) تعریف شده‌اند. +// رنگ‌های برنامه به‌صورت ColorScheme کامل (Light/Dark) در Theme.kt تعریف شده‌اند. diff --git a/app/src/main/java/com/approagency/pharmacy/ui/theme/Theme.kt b/app/src/main/java/com/approagency/pharmacy/ui/theme/Theme.kt index 0d60de4..3b08609 100644 --- a/app/src/main/java/com/approagency/pharmacy/ui/theme/Theme.kt +++ b/app/src/main/java/com/approagency/pharmacy/ui/theme/Theme.kt @@ -14,72 +14,96 @@ import androidx.compose.ui.platform.LocalContext import com.fabirt.podcastapp.ui.theme.Shapes import com.vada.caller.ui.theme.Dime import com.vada.caller.ui.theme.LocalDime -object MedicalColors { +// پالت کامل و هماهنگ بر پایه‌ی سبز-آبی پزشکی (teal). +// همه‌ی نقش‌های surface/container/outline تعریف شده‌اند تا کانتینرها (کارت‌ها، +// تکست‌فیلدها، باتم‌شیت‌ها) رنگ یکدست و متناسب با برند داشته باشند و به مقادیر +// پیش‌فرض بنفش‌گون Material برنگردند. +private val LightColorScheme = lightColorScheme( + primary = Color(0xFF0F766E), + onPrimary = Color(0xFFFFFFFF), + primaryContainer = Color(0xFFC7ECE6), + onPrimaryContainer = Color(0xFF00201D), - val Primary = Color(0xFF0F766E) - val PrimaryContainer = Color(0xFFD7F3EF) + secondary = Color(0xFF4C6360), + onSecondary = Color(0xFFFFFFFF), + secondaryContainer = Color(0xFFCEE8E3), + onSecondaryContainer = Color(0xFF09201D), - val Secondary = Color(0xFF5B8E8A) - val SecondaryContainer = Color(0xFFE3F3F1) + tertiary = Color(0xFF3D6373), + onTertiary = Color(0xFFFFFFFF), + tertiaryContainer = Color(0xFFC0E8FB), + onTertiaryContainer = Color(0xFF001F2A), - val Tertiary = Color(0xFF8FBFB8) + background = Color(0xFFF5FBF9), + onBackground = Color(0xFF171D1C), - val Background = Color(0xFFF8FCFB) - val Surface = Color(0xFFFFFFFF) + surface = Color(0xFFF5FBF9), + onSurface = Color(0xFF171D1C), + surfaceVariant = Color(0xFFDAE5E1), + onSurfaceVariant = Color(0xFF3F4947), - val DarkBackground = Color(0xFF0F1720) - val DarkSurface = Color(0xFF17232B) + surfaceContainerLowest = Color(0xFFFFFFFF), + surfaceContainerLow = Color(0xFFEFF6F3), + surfaceContainer = Color(0xFFE9F1EE), + surfaceContainerHigh = Color(0xFFE3ECE9), + surfaceContainerHighest = Color(0xFFDEE7E4), - val OnDark = Color(0xFFF5FAF9) - val OnLight = Color(0xFF102A2A) + outline = Color(0xFF6F7977), + outlineVariant = Color(0xFFBEC9C5), - val Error = Color(0xFFD64545) + error = Color(0xFFBA1A1A), + onError = Color(0xFFFFFFFF), + errorContainer = Color(0xFFFFDAD6), + onErrorContainer = Color(0xFF410002), - val Outline = Color(0xFFD0E2DF) -} -private val DarkColorScheme = darkColorScheme( - primary = Color(0xFF5DD4C3), - onPrimary = Color(0xFF003733), - - secondary = Color(0xFF8CC9C1), - onSecondary = Color(0xFF0D2B29), - - tertiary = Color(0xFFA7DCD4), - onTertiary = Color(0xFF102A2A), - - background = MedicalColors.DarkBackground, - onBackground = MedicalColors.OnDark, - - surface = MedicalColors.DarkSurface, - onSurface = MedicalColors.OnDark, - - primaryContainer = Color(0xFF124A45), - secondaryContainer = Color(0xFF1D3D3A), - - error = Color(0xFFFF8A80) + inverseSurface = Color(0xFF2B3231), + inverseOnSurface = Color(0xFFECF2EF), + inversePrimary = Color(0xFF80D5CB), + scrim = Color(0xFF000000), ) -private val LightColorScheme = lightColorScheme( - primary = MedicalColors.Primary, - onPrimary = Color.White, +private val DarkColorScheme = darkColorScheme( + primary = Color(0xFF5DD4C3), + onPrimary = Color(0xFF00382F), + primaryContainer = Color(0xFF005048), + onPrimaryContainer = Color(0xFF7FF8E6), - secondary = MedicalColors.Secondary, - onSecondary = Color.White, + secondary = Color(0xFFB0CCC6), + onSecondary = Color(0xFF1B3531), + secondaryContainer = Color(0xFF324B47), + onSecondaryContainer = Color(0xFFCCE8E2), - tertiary = MedicalColors.Tertiary, - onTertiary = MedicalColors.OnLight, + tertiary = Color(0xFFA4CCDE), + onTertiary = Color(0xFF053543), + tertiaryContainer = Color(0xFF234C5B), + onTertiaryContainer = Color(0xFFC0E8FB), - background = MedicalColors.Background, - onBackground = MedicalColors.OnLight, + background = Color(0xFF0E1514), + onBackground = Color(0xFFDDE4E1), - surface = MedicalColors.Surface, - onSurface = MedicalColors.OnLight, + surface = Color(0xFF0E1514), + onSurface = Color(0xFFDDE4E1), + surfaceVariant = Color(0xFF3F4947), + onSurfaceVariant = Color(0xFFBEC9C5), - primaryContainer = MedicalColors.PrimaryContainer, - secondaryContainer = MedicalColors.SecondaryContainer, + surfaceContainerLowest = Color(0xFF090F0E), + surfaceContainerLow = Color(0xFF171D1C), + surfaceContainer = Color(0xFF1B211F), + surfaceContainerHigh = Color(0xFF252B2A), + surfaceContainerHighest = Color(0xFF303635), - outline = MedicalColors.Outline, - error = MedicalColors.Error + outline = Color(0xFF899390), + outlineVariant = Color(0xFF3F4947), + + error = Color(0xFFFFB4AB), + onError = Color(0xFF690005), + errorContainer = Color(0xFF93000A), + onErrorContainer = Color(0xFFFFDAD6), + + inverseSurface = Color(0xFFDDE4E1), + inverseOnSurface = Color(0xFF2B3231), + inversePrimary = Color(0xFF0F766E), + scrim = Color(0xFF000000), ) @Composable