From f57cd956bd72a00b22c891dc3833abceca70fe2e Mon Sep 17 00:00:00 2001 From: "Andrey K. Choi" Date: Wed, 15 Oct 2025 21:57:19 +0900 Subject: [PATCH] UI refactor --- .../wellshe/ui/components/CommonComponents.kt | 4 +- .../wellshe/ui/cycle/CycleScreen.kt | 23 +- .../ui/cycle/components/CycleAnalytics.kt | 244 ++++++++++++++++++ .../ui/cycle/components/CycleCalendar.kt | 81 ++++-- .../wellshe/ui/navigation/BottomNavigation.kt | 132 +++++----- .../ui/navigation/WellSheNavigation.kt | 6 +- .../kr/smartsoltech/wellshe/ui/theme/Color.kt | 25 +- 7 files changed, 391 insertions(+), 124 deletions(-) create mode 100644 app/src/main/java/kr/smartsoltech/wellshe/ui/cycle/components/CycleAnalytics.kt diff --git a/app/src/main/java/kr/smartsoltech/wellshe/ui/components/CommonComponents.kt b/app/src/main/java/kr/smartsoltech/wellshe/ui/components/CommonComponents.kt index e274835..5a1784b 100644 --- a/app/src/main/java/kr/smartsoltech/wellshe/ui/components/CommonComponents.kt +++ b/app/src/main/java/kr/smartsoltech/wellshe/ui/components/CommonComponents.kt @@ -1,5 +1,6 @@ package kr.smartsoltech.wellshe.ui.components +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape @@ -95,7 +96,8 @@ fun PhasePill( Surface( modifier = modifier, shape = RoundedCornerShape(50), - color = color.copy(alpha = 0.2f) + color = Color.Transparent, + border = BorderStroke(1.dp, color) ) { Text( text = label, diff --git a/app/src/main/java/kr/smartsoltech/wellshe/ui/cycle/CycleScreen.kt b/app/src/main/java/kr/smartsoltech/wellshe/ui/cycle/CycleScreen.kt index 70cf52f..34b0aa7 100644 --- a/app/src/main/java/kr/smartsoltech/wellshe/ui/cycle/CycleScreen.kt +++ b/app/src/main/java/kr/smartsoltech/wellshe/ui/cycle/CycleScreen.kt @@ -139,6 +139,13 @@ fun CycleScreenPreview() { modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(12.dp) ) { + QuickActionsCard( + onMarkStart = { }, + onMarkEnd = { }, + onAddSymptom = { }, + onAddNote = { } + ) + StatCard( title = "След. менструация", value = previewState.forecast?.nextPeriodStart?.format( @@ -158,22 +165,6 @@ fun CycleScreenPreview() { ) } - QuickActionsCard( - onMarkStart = { }, - onMarkEnd = { }, - onAddSymptom = { }, - onAddNote = { } - ) - - InfoCard( - title = "Симптомы сегодня", - content = previewState.todaySymptoms - ) - - InfoCard( - title = "Прогноз недели", - content = previewState.weekInsight - ) } } } diff --git a/app/src/main/java/kr/smartsoltech/wellshe/ui/cycle/components/CycleAnalytics.kt b/app/src/main/java/kr/smartsoltech/wellshe/ui/cycle/components/CycleAnalytics.kt new file mode 100644 index 0000000..62b32d7 --- /dev/null +++ b/app/src/main/java/kr/smartsoltech/wellshe/ui/cycle/components/CycleAnalytics.kt @@ -0,0 +1,244 @@ +package kr.smartsoltech.wellshe.ui.cycle.components + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import kr.smartsoltech.wellshe.model.CycleForecast +import kr.smartsoltech.wellshe.ui.theme.* +import java.time.LocalDate +import java.time.format.DateTimeFormatter +import java.time.temporal.ChronoUnit +import java.util.* + +/** + * Вычисление аналитики цикла для отображения текущего статуса + */ +@Composable +fun CycleStatusCard( + forecast: CycleForecast?, + modifier: Modifier = Modifier +) { + if (forecast == null) return + + val today = LocalDate.now() + val cycleAnalytics = computeCycleAnalytics(today, forecast) + val dateFormatter = DateTimeFormatter.ofPattern("dd MMM", Locale("ru")) + + Card( + modifier = modifier.fillMaxWidth(), + shape = RoundedCornerShape(20.dp), + colors = CardDefaults.cardColors( + containerColor = CycleTabColor.copy(alpha = 0.15f) + ) + ) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + text = "Статус на сегодня", + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.SemiBold + ) + + // Текущий день цикла и фаза + Text( + text = "День цикла ${cycleAnalytics.cycleDay} (${cycleAnalytics.phaseName} фаза)", + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Medium + ) + + Divider(modifier = Modifier.padding(vertical = 4.dp)) + + // Ближайшие события + Text( + text = "Ближайшие события:", + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Medium + ) + + // Показываем информацию о фертильном окне + if (!cycleAnalytics.flags.isFertileToday) { + val fertileStartFormatted = cycleAnalytics.ranges.fertile.first.format(dateFormatter) + val fertileEndFormatted = cycleAnalytics.ranges.fertile.second.format(dateFormatter) + Text( + text = "• Фертильное окно: $fertileStartFormatted–$fertileEndFormatted", + style = MaterialTheme.typography.bodyMedium + ) + } else { + Text( + text = "• Фертильное окно: сейчас", + style = MaterialTheme.typography.bodyMedium + ) + } + + // Информация о дне овуляции + val ovulationFormatted = cycleAnalytics.next.ovulation.format(dateFormatter) + val daysToOvulation = cycleAnalytics.deltas.daysToOvulation + val ovulationText = when { + daysToOvulation < 0 -> "• Овуляция: была $ovulationFormatted (${-daysToOvulation} дн. назад)" + daysToOvulation == 0 -> "• Овуляция: сегодня" + else -> "• Овуляция: $ovulationFormatted (через $daysToOvulation дн.)" + } + Text( + text = ovulationText, + style = MaterialTheme.typography.bodyMedium + ) + + // Информация о ПМС + if (cycleAnalytics.flags.isPMSToday) { + Text( + text = "• ПМС: сейчас", + style = MaterialTheme.typography.bodyMedium + ) + } else if (today.isBefore(cycleAnalytics.ranges.pms.first)) { + val pmsStartFormatted = cycleAnalytics.ranges.pms.first.format(dateFormatter) + Text( + text = "• ПМС: с $pmsStartFormatted", + style = MaterialTheme.typography.bodyMedium + ) + } + + // Информация о следующей менструации + val nextPeriodFormatted = cycleAnalytics.next.nextPeriodStart.format(dateFormatter) + val daysToNextPeriod = cycleAnalytics.deltas.daysToNextPeriod + val nextPeriodText = when { + cycleAnalytics.flags.isMenstruationToday -> "• Менструация: сейчас" + else -> "• След. менструация: $nextPeriodFormatted (через $daysToNextPeriod дн.)" + } + Text( + text = nextPeriodText, + style = MaterialTheme.typography.bodyMedium + ) + + // Дополнительная подсказка о текущем статусе + if (cycleAnalytics.flags.isMenstruationToday || + cycleAnalytics.flags.isFertileToday || + cycleAnalytics.flags.isOvulationToday || + cycleAnalytics.flags.isPMSToday) { + + Divider(modifier = Modifier.padding(vertical = 4.dp)) + + val tipText = when { + cycleAnalytics.flags.isOvulationToday -> "Пик вероятности зачатия сегодня. Важно следить за самочувствием, возможны изменения настроения и энергии." + cycleAnalytics.flags.isMenstruationToday -> "В эти дни важно обеспечить организму покой и комфорт. Следите за самочувствием и избегайте чрезмерных нагрузок." + cycleAnalytics.flags.isFertileToday -> "Повышенная вероятность зачатия. Хорошее время для физической активности и новых начинаний." + cycleAnalytics.flags.isPMSToday -> "Возможны колебания настроения и некоторый дискомфорт. Важно следить за гидратацией и сбалансированным питанием." + else -> "" + } + + Text( + text = tipText, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + } + } +} + +/** + * Вычисление аналитических данных цикла + */ +private fun computeCycleAnalytics(today: LocalDate, forecast: CycleForecast): CycleAnalytics { + // Используем поля из модели CycleForecast + val nextPeriodStart = forecast.nextPeriodStart + val ovulation = forecast.nextOvulation + val fertileStart = forecast.fertileStart + val fertileEnd = forecast.fertileEnd + val pmsStart = forecast.pmsStart + val periodEnd = forecast.periodEnd + + // Вычисляем примерную дату начала текущего цикла + val estimatedCycleStart = if (today < nextPeriodStart) { + nextPeriodStart.minusDays(28) // Примерная длина цикла, если точных данных нет + } else { + nextPeriodStart + } + + // Считаем текущий день цикла + val cycleDay = ChronoUnit.DAYS.between(estimatedCycleStart, today) + 1 + + // Определяем фазы + val isMenstruationToday = today in nextPeriodStart..periodEnd + val isFertileToday = today in fertileStart..fertileEnd + val isOvulationToday = today == ovulation + val isPMSToday = today in pmsStart..nextPeriodStart.minusDays(1) + + // Определяем текущую фазу + val phaseName = when { + isMenstruationToday -> "Менструация" + today.isBefore(ovulation) -> "Фолликулярная" + today == ovulation -> "Овуляция" + today.isAfter(ovulation) -> "Лютеиновая" + else -> "Неопределена" + } + + // Вычисляем дни до следующих событий + val daysToOvulation = ChronoUnit.DAYS.between(today, ovulation) + val daysToNextPeriod = ChronoUnit.DAYS.between(today, nextPeriodStart) + + return CycleAnalytics( + cycleDay = cycleDay.toInt(), + phaseName = phaseName, + ranges = CycleRanges( + period = Pair(nextPeriodStart, periodEnd), + fertile = Pair(fertileStart, fertileEnd), + pms = Pair(pmsStart, nextPeriodStart.minusDays(1)) + ), + next = NextEvents( + ovulation = ovulation, + nextPeriodStart = nextPeriodStart + ), + flags = CycleFlags( + isMenstruationToday = isMenstruationToday, + isFertileToday = isFertileToday, + isOvulationToday = isOvulationToday, + isPMSToday = isPMSToday + ), + deltas = TimingDeltas( + daysToOvulation = daysToOvulation.toInt(), + daysToNextPeriod = daysToNextPeriod.toInt() + ) + ) +} + +/** + * Класс для аналитики цикла + */ +data class CycleAnalytics( + val cycleDay: Int, + val phaseName: String, + val ranges: CycleRanges, + val next: NextEvents, + val flags: CycleFlags, + val deltas: TimingDeltas +) + +data class CycleRanges( + val period: Pair, + val fertile: Pair, + val pms: Pair +) + +data class NextEvents( + val ovulation: LocalDate, + val nextPeriodStart: LocalDate +) + +data class CycleFlags( + val isMenstruationToday: Boolean, + val isFertileToday: Boolean, + val isOvulationToday: Boolean, + val isPMSToday: Boolean +) + +data class TimingDeltas( + val daysToOvulation: Int, + val daysToNextPeriod: Int +) diff --git a/app/src/main/java/kr/smartsoltech/wellshe/ui/cycle/components/CycleCalendar.kt b/app/src/main/java/kr/smartsoltech/wellshe/ui/cycle/components/CycleCalendar.kt index 98fdc84..1812a7a 100644 --- a/app/src/main/java/kr/smartsoltech/wellshe/ui/cycle/components/CycleCalendar.kt +++ b/app/src/main/java/kr/smartsoltech/wellshe/ui/cycle/components/CycleCalendar.kt @@ -9,9 +9,11 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.KeyboardArrowLeft import androidx.compose.material.icons.filled.KeyboardArrowRight +import androidx.compose.material.icons.filled.Tune import androidx.compose.material.icons.filled.WbSunny import androidx.compose.material3.* import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -38,7 +40,8 @@ fun CycleCalendarCard( onPrev: () -> Unit, onNext: () -> Unit, forecast: CycleForecast?, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + onOpenSettings: () -> Unit = {} // Добавлен новый параметр для обработки нажатия на кнопку настроек ) { val daysOfWeek = listOf("Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс") val monthFormat = DateTimeFormatter.ofPattern("LLLL yyyy", Locale("ru")) @@ -47,14 +50,14 @@ fun CycleCalendarCard( modifier = modifier.fillMaxWidth(), shape = RoundedCornerShape(20.dp), colors = CardDefaults.cardColors( - containerColor = CycleTabColor.copy(alpha = 0.3f) + containerColor = Color.Transparent ) ) { Column( modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { - // Заголовок карточки с иконкой + // Заголовок карточки с иконкой и кнопкой настроек Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, @@ -72,6 +75,15 @@ fun CycleCalendarCard( fontWeight = FontWeight.SemiBold ) } + + // Кнопка настроек цикла + IconButton(onClick = onOpenSettings) { + Icon( + imageVector = Icons.Filled.Tune, + contentDescription = "Настройки цикла", + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) + } } // Заголовок месяца с кнопками навигации @@ -129,10 +141,16 @@ fun CycleCalendarCard( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { - PhasePill(label = "Менструация", color = Color(0xFFE57373)) - PhasePill(label = "Фертильное окно", color = Color(0xFF4CAF50)) - PhasePill(label = "Овуляция", color = Color(0xFF3F51B5)) - PhasePill(label = "ПМС", color = Color(0xFFFFA726)) + PhasePill(label = "Менструация", color = PeriodColor) + PhasePill(label = "Фертильное окно", color = FertileColor) + PhasePill(label = "Овуляция", color = OvulationColor) + PhasePill(label = "ПМС", color = PmsColor) + } + + // Блок расширенной аналитики "Статус на сегодня" + if (forecast != null) { + Spacer(modifier = Modifier.height(16.dp)) + CycleStatusCard(forecast = forecast) } } } @@ -155,7 +173,7 @@ fun CalendarGrid( // Вычисляем смещение первого дня месяца val dayOfWeekValue = firstDay.dayOfWeek.value // 1 для понедельника, 7 для воскресенья - val firstDayOffset = if (dayOfWeekValue == 7) 0 else dayOfWeekValue + val firstDayOffset = dayOfWeekValue - 1 // Смещение (0 для понедельника) // Создаем полную сетку календаря (6 недель по 7 дней) Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { @@ -170,7 +188,7 @@ fun CalendarGrid( if (isValidDay) { val date = month.atDay(dayNumber) - CalendarDay(date = date, today = today, forecast = forecast) + CalendarDay(date = date, today = today, forecast = forecast, modifier = Modifier.weight(1f)) } else { // Пустая ячейка для выравнивания Box( @@ -192,7 +210,8 @@ fun CalendarGrid( fun CalendarDay( date: LocalDate, today: LocalDate, - forecast: CycleForecast? + forecast: CycleForecast?, + modifier: Modifier = Modifier ) { // Определяем, в какой фазе цикла находится день val isPeriod = forecast?.let { date in it.nextPeriodStart..it.periodEnd } ?: false @@ -201,25 +220,31 @@ fun CalendarDay( val isOvulation = forecast?.let { date == it.nextOvulation } ?: false val isToday = date == today - // Определяем цвет фона - val backgroundColor = when { - isPeriod -> PeriodColor - isFertile -> FertileColor - isPms -> PmsColor - else -> Color.Transparent + // Создаем базовый модификатор для всех дней + var finalModifier = modifier + .size(36.dp) + .clip(RoundedCornerShape(8.dp)) + + // Добавляем контур в зависимости от фазы (приоритет: Ovulation > Period > Fertile > PMS) + finalModifier = when { + isOvulation -> finalModifier + .border(BorderStroke(2.dp, OvulationColor), RoundedCornerShape(8.dp)) + isPeriod -> finalModifier + .border(BorderStroke(1.dp, PeriodColor), RoundedCornerShape(8.dp)) + isFertile -> finalModifier + .border(BorderStroke(1.dp, FertileColor), RoundedCornerShape(8.dp)) + isPms -> finalModifier + .border(BorderStroke(1.dp, PmsColor), RoundedCornerShape(8.dp)) + else -> finalModifier + .border(BorderStroke(1.dp, Color.Transparent), RoundedCornerShape(8.dp)) } - // Добавляем модификаторы в зависимости от фазы - val baseModifier = Modifier - .size(36.dp) - .clip(CircleShape) - .background(backgroundColor) - - // Особое выделение для овуляции - val finalModifier = if (isOvulation) { - baseModifier.border(BorderStroke(2.dp, OvulationBorder), CircleShape) - } else { - baseModifier + // Добавляем дополнительный тонкий контур для выделения сегодняшнего дня + if (isToday && !isOvulation && !isPeriod && !isFertile && !isPms) { + finalModifier = finalModifier.border( + BorderStroke(1.dp, MaterialTheme.colorScheme.outline.copy(alpha = 0.6f)), + RoundedCornerShape(8.dp) + ) } Box( @@ -230,7 +255,7 @@ fun CalendarDay( text = date.dayOfMonth.toString(), style = MaterialTheme.typography.labelMedium, fontWeight = if (isToday) FontWeight.Bold else FontWeight.Normal, - color = if (isToday) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface + color = MaterialTheme.colorScheme.onSurface ) } } diff --git a/app/src/main/java/kr/smartsoltech/wellshe/ui/navigation/BottomNavigation.kt b/app/src/main/java/kr/smartsoltech/wellshe/ui/navigation/BottomNavigation.kt index e4794ca..e4e0369 100644 --- a/app/src/main/java/kr/smartsoltech/wellshe/ui/navigation/BottomNavigation.kt +++ b/app/src/main/java/kr/smartsoltech/wellshe/ui/navigation/BottomNavigation.kt @@ -1,24 +1,13 @@ package kr.smartsoltech.wellshe.ui.navigation import androidx.compose.foundation.background -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Analytics -import androidx.compose.material.icons.filled.Favorite -import androidx.compose.material.icons.filled.Home -import androidx.compose.material.icons.filled.Person -import androidx.compose.material.icons.filled.WbSunny -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.NavigationBar -import androidx.compose.material3.NavigationBarItem -import androidx.compose.material3.NavigationBarItemDefaults -import androidx.compose.material3.Text +import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color @@ -36,82 +25,93 @@ fun BottomNavigation( modifier: Modifier = Modifier ) { NavigationBar( - modifier = modifier.fillMaxWidth(), + modifier = modifier + .fillMaxWidth() + .height(80.dp), // Минимальная высота Material3 containerColor = MaterialTheme.colorScheme.background, - tonalElevation = 8.dp + tonalElevation = 8.dp, + windowInsets = WindowInsets(0.dp) // Убираем стандартные отступы ) { val navBackStackEntry by navController.currentBackStackEntryAsState() val currentDestination = navBackStackEntry?.destination - val items = listOf( - BottomNavItem.Cycle, - BottomNavItem.Body, - BottomNavItem.Mood, - BottomNavItem.Analytics, - BottomNavItem.Profile - ) + val items = BottomNavItem.items - items.forEach { item -> - val selected = currentDestination?.hierarchy?.any { it.route == item.route } == true + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + items.forEach { item -> + val selected = currentDestination?.hierarchy?.any { it.route == item.route } == true - // Определяем цвет фона для выбранного элемента - val backgroundColor = when (item) { - BottomNavItem.Cycle -> CycleTabColor - BottomNavItem.Body -> BodyTabColor - BottomNavItem.Mood -> MoodTabColor - BottomNavItem.Analytics -> AnalyticsTabColor - BottomNavItem.Profile -> ProfileTabColor - } + // Определяем цвет фона для выбранного элемента + val backgroundColor = when (item) { + BottomNavItem.Cycle -> CycleTabColor + BottomNavItem.Body -> BodyTabColor + BottomNavItem.Mood -> MoodTabColor + BottomNavItem.Analytics -> AnalyticsTabColor + BottomNavItem.Profile -> ProfileTabColor + } - NavigationBarItem( - icon = { + // Создаем кастомный элемент навигации с привязкой к верхнему краю + Column( + modifier = Modifier + .weight(1f) + .clickable { + navController.navigate(item.route) { + // Pop up to the start destination of the graph to + // avoid building up a large stack of destinations + popUpTo(navController.graph.findStartDestination().id) { + saveState = true + } + // Avoid multiple copies of the same destination + launchSingleTop = true + // Restore state when reselecting + restoreState = true + } + } + .padding(4.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Top // Привязываем контент к верхнему краю + ) { + // Иконка - размещаем вверху if (selected) { Icon( imageVector = item.icon, contentDescription = item.title, modifier = Modifier - .size(24.dp) - .clip(RoundedCornerShape(4.dp)) + .padding(top = 4.dp) + .size(36.dp) + .clip(RoundedCornerShape(6.dp)) .background(backgroundColor) - .padding(2.dp) + .padding(4.dp), + tint = MaterialTheme.colorScheme.onPrimaryContainer ) } else { Icon( imageVector = item.icon, contentDescription = item.title, - modifier = Modifier.size(24.dp) + modifier = Modifier + .padding(top = 4.dp) + .size(32.dp), + tint = MaterialTheme.colorScheme.onSurfaceVariant ) } - }, - label = { + + // Текстовая метка + Spacer(modifier = Modifier.height(2.dp)) Text( text = item.title, style = MaterialTheme.typography.labelSmall, - textAlign = TextAlign.Center + color = if (selected) + MaterialTheme.colorScheme.onSurface + else + MaterialTheme.colorScheme.onSurfaceVariant, + textAlign = TextAlign.Center, + maxLines = 1 ) - }, - selected = selected, - onClick = { - navController.navigate(item.route) { - // Pop up to the start destination of the graph to - // avoid building up a large stack of destinations - popUpTo(navController.graph.findStartDestination().id) { - saveState = true - } - // Avoid multiple copies of the same destination when - // reselecting the same item - launchSingleTop = true - // Restore state when reselecting a previously selected item - restoreState = true - } - }, - colors = NavigationBarItemDefaults.colors( - selectedIconColor = MaterialTheme.colorScheme.onPrimaryContainer, - selectedTextColor = MaterialTheme.colorScheme.onSurface, - unselectedIconColor = MaterialTheme.colorScheme.onSurfaceVariant, - unselectedTextColor = MaterialTheme.colorScheme.onSurfaceVariant - ) - ) + } + } } } } diff --git a/app/src/main/java/kr/smartsoltech/wellshe/ui/navigation/WellSheNavigation.kt b/app/src/main/java/kr/smartsoltech/wellshe/ui/navigation/WellSheNavigation.kt index 639abc8..694d127 100644 --- a/app/src/main/java/kr/smartsoltech/wellshe/ui/navigation/WellSheNavigation.kt +++ b/app/src/main/java/kr/smartsoltech/wellshe/ui/navigation/WellSheNavigation.kt @@ -8,10 +8,14 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.navigation.compose.rememberNavController import androidx.compose.ui.tooling.preview.Preview +import androidx.navigation.compose.rememberNavController import kr.smartsoltech.wellshe.ui.theme.WellSheTheme +// Добавляем явный импорт для BottomNavigation из того же пакета +// Важно импортировать именно эту функцию, а не Material3 компонент с тем же именем +import kr.smartsoltech.wellshe.ui.navigation.BottomNavigation + @OptIn(ExperimentalMaterial3Api::class) @Composable fun WellSheNavigation() { diff --git a/app/src/main/java/kr/smartsoltech/wellshe/ui/theme/Color.kt b/app/src/main/java/kr/smartsoltech/wellshe/ui/theme/Color.kt index ec26047..3fd3fab 100644 --- a/app/src/main/java/kr/smartsoltech/wellshe/ui/theme/Color.kt +++ b/app/src/main/java/kr/smartsoltech/wellshe/ui/theme/Color.kt @@ -39,8 +39,6 @@ val ErrorRedLight = Color(0xFFFFCDD2) // Фоновые цвета val BackgroundPrimary = Color(0xFFFFFFFF) -val BackgroundSecondary = Color(0xFFFAFAFA) -val BackgroundTertiary = Color(0xFFF5F5F5) // Цвета для графиков и статистики val ChartPink = Color(0xFFE91E63) @@ -51,17 +49,20 @@ val ChartOrange = Color(0xFFFF9800) val ChartRed = Color(0xFFF44336) // Цвета для фаз цикла -val PeriodColor = Color(0xFFFFD6E0) // Розовый для менструации -val FertileColor = Color(0xFFD6F5E3) // Зелёный для фертильного окна -val PmsColor = Color(0xFFFFF2CC) // Янтарный для ПМС -val OvulationBorder = Color(0xFF6366F1) // Индиго для обводки дня овуляции +val PeriodColor = Color(0xFFE57373) // Менструация (розовый) +val FertileColor = Color(0xFF4CAF50) // Фертильное окно (зеленый) +val OvulationColor = Color(0xFF3F51B5) // Овуляция (синий) +val OvulationBorder = Color(0xFF3F51B5) // Граница для дня овуляции +val PmsColor = Color(0xFFFFA726) // ПМС (оранжевый/янтарный) -// Цвета для вкладок -val CycleTabColor = Color(0xFFFFF8E1) // Янтарный для вкладки Цикл -val BodyTabColor = Color(0xFFE3F2FD) // Синий для вкладки Тело -val MoodTabColor = Color(0xFFFCE4EC) // Розовый для вкладки Настроение -val AnalyticsTabColor = Color(0xFFE0F2F1) // Изумрудный для вкладки Аналитика -val ProfileTabColor = Color(0xFFF5F5F5) // Серый для вкладки Профиль +// Цвет вкладки цикла +val CycleTabColor = Color(0xFFFFD54F) // Янтарный цвет для вкладки цикла + +// Цвета для вкладок приложения +val AnalyticsTabColor = Color(0xFFB2DFDB) // Бирюзовый для вкладки Аналитика +val BodyTabColor = Color(0xFFBBDEFB) // Голубой для вкладки Тело +val MoodTabColor = Color(0xFFF8BBD0) // Розовый для вкладки Настроение +val ProfileTabColor = Color(0xFFD1C4E9) // Лавандовый для вкладки Профиль // Акцентные цвета для разделов val WaterColor = Color(0xFF2196F3) // Синий для воды