diff --git a/client/lib/features/home/home_screen.dart b/client/lib/features/home/home_screen.dart index f6b6382..0a122c5 100644 --- a/client/lib/features/home/home_screen.dart +++ b/client/lib/features/home/home_screen.dart @@ -12,6 +12,7 @@ import '../../core/storage/local_preferences_provider.dart'; import '../../core/theme/app_colors.dart'; import '../../shared/models/diary_entry.dart'; import '../../shared/models/home_summary.dart'; +import '../../shared/constants/date_limits.dart'; import '../../shared/models/meal_type.dart'; import '../../shared/models/menu.dart'; import '../diary/food_search_sheet.dart'; @@ -128,8 +129,6 @@ class HomeScreen extends ConsumerWidget { ], const SizedBox(height: 16), _QuickActionsRow(), - const SizedBox(height: 8), - _PlanMenuButton(), if (!isFutureDate && recommendations.isNotEmpty) ...[ const SizedBox(height: 20), _SectionTitle(l10n.recommendCook), @@ -191,10 +190,10 @@ class _DateSelector extends StatefulWidget { } class _DateSelectorState extends State<_DateSelector> { - // Strip covers 7 future days + today + 364 past days = 372 items total. + // Strip covers kPlanningHorizonDays future days + today + 364 past days. // With reverse: true, index 0 is rendered at the RIGHT edge (newest). - // index 0 = today + 7, index 7 = today, index 371 = today - 364. - static const _futureDays = 7; + // index 0 = today + kPlanningHorizonDays, index kPlanningHorizonDays = today. + static const _futureDays = kPlanningHorizonDays; static const _pastDays = 364; static const _totalDays = _futureDays + 1 + _pastDays; // 372 static const _pillWidth = 48.0; @@ -1156,125 +1155,26 @@ class _FutureDayHeader extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final l10n = AppLocalizations.of(context)!; - final date = DateTime.parse(dateString); - final weekString = isoWeekString(date); - final menuState = ref.watch(menuProvider(weekString)); + final plannedMeals = ref.watch(plannedMealsProvider(dateString)); return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ _PlanningBanner(dateString: dateString), const SizedBox(height: 8), - menuState.when( - loading: () => _GenerateLoadingCard(l10n: l10n), - error: (_, __) => _GenerateActionCard( - l10n: l10n, - onGenerate: () => - ref.read(menuProvider(weekString).notifier).generate(), - ), - data: (plan) => plan == null - ? _GenerateActionCard( - l10n: l10n, - onGenerate: () => - ref.read(menuProvider(weekString).notifier).generate(), - ) - : _WeekPlannedChip(l10n: l10n), - ), + _FutureDayPlanButton(dateString: dateString), + if (plannedMeals.isNotEmpty) ...[ + const SizedBox(height: 8), + _DayPlannedChip(l10n: l10n), + ], ], ); } } -class _GenerateActionCard extends StatelessWidget { +class _DayPlannedChip extends StatelessWidget { final AppLocalizations l10n; - final VoidCallback onGenerate; - const _GenerateActionCard({required this.l10n, required this.onGenerate}); - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: theme.colorScheme.surfaceContainerLow, - borderRadius: BorderRadius.circular(12), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon(Icons.auto_awesome, - color: theme.colorScheme.primary, size: 20), - const SizedBox(width: 8), - Expanded( - child: Text( - l10n.generateWeekLabel, - style: theme.textTheme.titleSmall?.copyWith( - color: theme.colorScheme.onSurface, - fontWeight: FontWeight.w600, - ), - ), - ), - ], - ), - const SizedBox(height: 4), - Text( - l10n.generateWeekSubtitle, - style: theme.textTheme.bodySmall?.copyWith( - color: theme.colorScheme.onSurfaceVariant, - ), - ), - const SizedBox(height: 12), - FilledButton( - onPressed: onGenerate, - child: Text(l10n.generateWeekLabel), - ), - ], - ), - ); - } -} - -class _GenerateLoadingCard extends StatelessWidget { - final AppLocalizations l10n; - const _GenerateLoadingCard({required this.l10n}); - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - return Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), - decoration: BoxDecoration( - color: theme.colorScheme.surfaceContainerLow, - borderRadius: BorderRadius.circular(12), - ), - child: Row( - children: [ - SizedBox( - width: 18, - height: 18, - child: CircularProgressIndicator.adaptive( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation(theme.colorScheme.primary), - ), - ), - const SizedBox(width: 12), - Text( - l10n.generatingMenu, - style: theme.textTheme.bodyMedium?.copyWith( - color: theme.colorScheme.onSurfaceVariant, - ), - ), - ], - ), - ); - } -} - -class _WeekPlannedChip extends StatelessWidget { - final AppLocalizations l10n; - const _WeekPlannedChip({required this.l10n}); + const _DayPlannedChip({required this.l10n}); @override Widget build(BuildContext context) { @@ -1292,7 +1192,7 @@ class _WeekPlannedChip extends StatelessWidget { color: theme.colorScheme.onSecondaryContainer, size: 18), const SizedBox(width: 8), Text( - l10n.weekPlannedLabel, + l10n.dayPlannedLabel, style: theme.textTheme.bodySmall?.copyWith( color: theme.colorScheme.onSecondaryContainer, fontWeight: FontWeight.w600, @@ -1647,8 +1547,9 @@ class _ActionButton extends StatelessWidget { // ── Plan menu button ────────────────────────────────────────── -class _PlanMenuButton extends ConsumerWidget { - const _PlanMenuButton(); +class _FutureDayPlanButton extends ConsumerWidget { + final String dateString; + const _FutureDayPlanButton({required this.dateString}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -1682,16 +1583,13 @@ class _PlanMenuButton extends ConsumerWidget { } void _openPlanSheet(BuildContext context, WidgetRef ref) { + final defaultStart = DateTime.parse(dateString); showModalBottomSheet( context: context, isScrollControlled: true, useSafeArea: true, builder: (_) => PlanMenuSheet( onModeSelected: (mode) { - final lastPlanned = ref.read(lastPlannedDateProvider); - final defaultStart = lastPlanned != null - ? lastPlanned.add(const Duration(days: 1)) - : DateTime.now().add(const Duration(days: 1)); showModalBottomSheet( context: context, isScrollControlled: true, diff --git a/client/lib/features/menu/menu_provider.dart b/client/lib/features/menu/menu_provider.dart index 2c0c19c..73b600b 100644 --- a/client/lib/features/menu/menu_provider.dart +++ b/client/lib/features/menu/menu_provider.dart @@ -16,22 +16,27 @@ final menuServiceProvider = Provider((ref) { /// The ISO week string for the currently displayed week, e.g. "2026-W08". final currentWeekProvider = StateProvider((ref) { - final now = DateTime.now().toUtc(); + final now = DateTime.now(); final (y, w) = _isoWeek(now); return '$y-W${w.toString().padLeft(2, '0')}'; }); (int year, int week) _isoWeek(DateTime dt) { - // Shift to Thursday to get ISO week year. - final thu = dt.add(Duration(days: 4 - (dt.weekday == 7 ? 0 : dt.weekday))); - final jan1 = DateTime.utc(thu.year, 1, 1); - final week = ((thu.difference(jan1).inDays) / 7).ceil(); + // Shift to Thursday of the same ISO week. + // Monday=1…Saturday=6 → add (4 - weekday) days; Sunday=7 → subtract 3 days. + final int shift = dt.weekday == 7 ? -3 : 4 - dt.weekday; + final thu = dt.add(Duration(days: shift)); + // Use the same timezone as the input to avoid offset drift on the difference. + final jan1 = dt.isUtc + ? DateTime.utc(thu.year, 1, 1) + : DateTime(thu.year, 1, 1); + final week = (thu.difference(jan1).inDays ~/ 7) + 1; return (thu.year, week); } /// Returns the ISO 8601 week string for [date], e.g. "2026-W12". String isoWeekString(DateTime date) { - final (year, week) = _isoWeek(date.toUtc()); + final (year, week) = _isoWeek(date); return '$year-W${week.toString().padLeft(2, '0')}'; } diff --git a/client/lib/features/menu/menu_screen.dart b/client/lib/features/menu/menu_screen.dart index 152787f..9a3dfb5 100644 --- a/client/lib/features/menu/menu_screen.dart +++ b/client/lib/features/menu/menu_screen.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; +import '../../shared/constants/date_limits.dart'; import '../../shared/models/menu.dart'; import 'menu_provider.dart'; @@ -95,31 +96,48 @@ class _WeekNavBar extends StatelessWidget implements PreferredSizeWidget { } (int, int) _isoWeekOf(DateTime dt) { - final thu = dt.add(Duration(days: 4 - (dt.weekday == 7 ? 0 : dt.weekday))); - final jan1 = DateTime.utc(thu.year, 1, 1); - final w = ((thu.difference(jan1).inDays) / 7).ceil(); + final int shift = dt.weekday == 7 ? -3 : 4 - dt.weekday; + final thu = dt.add(Duration(days: shift)); + final jan1 = dt.isUtc + ? DateTime.utc(thu.year, 1, 1) + : DateTime(thu.year, 1, 1); + final w = (thu.difference(jan1).inDays ~/ 7) + 1; return (thu.year, w); } + String _currentWeekString(DateTime date) { + final (y, w) = _isoWeekOf(date); + return '$y-W${w.toString().padLeft(2, '0')}'; + } + @override Widget build(BuildContext context) { + final now = DateTime.now(); + final maxWeek = _currentWeekString( + now.add(const Duration(days: kPlanningHorizonDays))); + final minWeek = _currentWeekString( + now.subtract(Duration(days: kMenuPastWeeks * 7))); return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( icon: const Icon(Icons.chevron_left), - onPressed: () { - ref.read(currentWeekProvider.notifier).state = - _offsetWeek(week, -1); - }, + onPressed: week.compareTo(minWeek) <= 0 + ? null + : () { + ref.read(currentWeekProvider.notifier).state = + _offsetWeek(week, -1); + }, ), Text(_weekLabel(week), style: Theme.of(context).textTheme.bodyMedium), IconButton( icon: const Icon(Icons.chevron_right), - onPressed: () { - ref.read(currentWeekProvider.notifier).state = - _offsetWeek(week, 1); - }, + onPressed: week.compareTo(maxWeek) >= 0 + ? null + : () { + ref.read(currentWeekProvider.notifier).state = + _offsetWeek(week, 1); + }, ), ], ); diff --git a/client/lib/features/menu/plan_date_picker_sheet.dart b/client/lib/features/menu/plan_date_picker_sheet.dart index 7d8f74d..a5f73f6 100644 --- a/client/lib/features/menu/plan_date_picker_sheet.dart +++ b/client/lib/features/menu/plan_date_picker_sheet.dart @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:food_ai/l10n/app_localizations.dart'; import 'package:intl/intl.dart'; +import '../../shared/constants/date_limits.dart'; import '../../shared/models/meal_type.dart'; import '../profile/profile_provider.dart'; import 'menu_provider.dart'; @@ -279,8 +280,8 @@ class _DateStripSelector extends StatefulWidget { class _DateStripSelectorState extends State<_DateStripSelector> { late final ScrollController _scrollController; - // Show 30 upcoming days (today excluded, starts tomorrow). - static const _futureDays = 30; + // Show upcoming days up to the planning horizon (today excluded, starts tomorrow). + static const _futureDays = kPlanningHorizonDays; static const _itemWidth = 64.0; DateTime get _tomorrow => @@ -407,12 +408,22 @@ class _CalendarRangePickerState extends State<_CalendarRangePicker> { } void _nextMonth() { + final horizon = DateTime.now().add(const Duration(days: kPlanningHorizonDays)); + final limitMonth = DateTime(horizon.year, horizon.month); + if (!DateTime(_displayMonth.year, _displayMonth.month).isBefore(limitMonth)) return; setState(() { _displayMonth = DateTime(_displayMonth.year, _displayMonth.month + 1); }); } + bool _isBeyondHorizon(DateTime date) { + final today = DateTime.now(); + final horizon = DateTime(today.year, today.month, today.day) + .add(const Duration(days: kPlanningHorizonDays)); + return date.isAfter(horizon); + } + bool _isInRange(DateTime date) { final dayOnly = DateTime(date.year, date.month, date.day); final start = @@ -510,11 +521,13 @@ class _CalendarRangePickerState extends State<_CalendarRangePicker> { final isStart = _isRangeStart(date); final isEnd = _isRangeEnd(date); final isPast = _isPast(date); + final isBeyond = _isBeyondHorizon(date); + final isDisabled = isPast || isBeyond; Color bgColor = Colors.transparent; Color textColor = theme.colorScheme.onSurface; - if (isPast) { + if (isDisabled) { // ignore: deprecated_member_use textColor = theme.colorScheme.onSurface.withOpacity(0.3); } else if (isStart || isEnd) { @@ -526,7 +539,7 @@ class _CalendarRangePickerState extends State<_CalendarRangePicker> { } return GestureDetector( - onTap: isPast ? null : () => widget.onDayTapped(date), + onTap: isDisabled ? null : () => widget.onDayTapped(date), child: Container( decoration: BoxDecoration( color: bgColor, diff --git a/client/lib/l10n/app_ar.arb b/client/lib/l10n/app_ar.arb index c615961..6a0b838 100644 --- a/client/lib/l10n/app_ar.arb +++ b/client/lib/l10n/app_ar.arb @@ -135,7 +135,7 @@ "generateWeekLabel": "تخطيط الأسبوع", "generateWeekSubtitle": "سيقوم الذكاء الاصطناعي بإنشاء قائمة طعام تشمل الإفطار والغداء والعشاء لكامل الأسبوع", "generatingMenu": "جارٍ إنشاء القائمة...", - "weekPlannedLabel": "تم تخطيط الأسبوع", + "dayPlannedLabel": "تم تخطيط اليوم", "planMenuButton": "تخطيط الوجبات", "planMenuTitle": "ماذا تريد تخطيطه؟", diff --git a/client/lib/l10n/app_de.arb b/client/lib/l10n/app_de.arb index 2eab697..5b382a2 100644 --- a/client/lib/l10n/app_de.arb +++ b/client/lib/l10n/app_de.arb @@ -135,7 +135,7 @@ "generateWeekLabel": "Woche planen", "generateWeekSubtitle": "KI erstellt einen Menüplan mit Frühstück, Mittagessen und Abendessen für die ganze Woche", "generatingMenu": "Menü wird erstellt...", - "weekPlannedLabel": "Woche geplant", + "dayPlannedLabel": "Tag geplant", "planMenuButton": "Mahlzeiten planen", "planMenuTitle": "Was planen?", diff --git a/client/lib/l10n/app_en.arb b/client/lib/l10n/app_en.arb index 0ae94e6..fead0a7 100644 --- a/client/lib/l10n/app_en.arb +++ b/client/lib/l10n/app_en.arb @@ -133,7 +133,7 @@ "generateWeekLabel": "Plan the week", "generateWeekSubtitle": "AI will create a menu with breakfast, lunch and dinner for the whole week", "generatingMenu": "Generating menu...", - "weekPlannedLabel": "Week planned", + "dayPlannedLabel": "Day planned", "planMenuButton": "Plan meals", "planMenuTitle": "What to plan?", diff --git a/client/lib/l10n/app_es.arb b/client/lib/l10n/app_es.arb index 5cbb154..b4968d7 100644 --- a/client/lib/l10n/app_es.arb +++ b/client/lib/l10n/app_es.arb @@ -135,7 +135,7 @@ "generateWeekLabel": "Planificar la semana", "generateWeekSubtitle": "La IA creará un menú con desayuno, comida y cena para toda la semana", "generatingMenu": "Generando menú...", - "weekPlannedLabel": "Semana planificada", + "dayPlannedLabel": "Día planificado", "planMenuButton": "Planificar comidas", "planMenuTitle": "¿Qué planificar?", diff --git a/client/lib/l10n/app_fr.arb b/client/lib/l10n/app_fr.arb index 4e49951..3d83613 100644 --- a/client/lib/l10n/app_fr.arb +++ b/client/lib/l10n/app_fr.arb @@ -135,7 +135,7 @@ "generateWeekLabel": "Planifier la semaine", "generateWeekSubtitle": "L'IA créera un menu avec petit-déjeuner, déjeuner et dîner pour toute la semaine", "generatingMenu": "Génération du menu...", - "weekPlannedLabel": "Semaine planifiée", + "dayPlannedLabel": "Jour planifié", "planMenuButton": "Planifier les repas", "planMenuTitle": "Que planifier ?", diff --git a/client/lib/l10n/app_hi.arb b/client/lib/l10n/app_hi.arb index 5d1f96a..7c7601b 100644 --- a/client/lib/l10n/app_hi.arb +++ b/client/lib/l10n/app_hi.arb @@ -135,7 +135,7 @@ "generateWeekLabel": "सप्ताह की योजना बनाएं", "generateWeekSubtitle": "AI पूरे सप्ताह के लिए नाश्ता, दोपहर का खाना और रात के खाने के साथ मेनू बनाएगा", "generatingMenu": "मेनू बना रहे हैं...", - "weekPlannedLabel": "सप्ताह की योजना बनाई गई", + "dayPlannedLabel": "दिन की योजना बनाई गई", "planMenuButton": "भोजन की योजना बनाएं", "planMenuTitle": "क्या योजना बनानी है?", diff --git a/client/lib/l10n/app_it.arb b/client/lib/l10n/app_it.arb index 80dc5b2..f4d6bcd 100644 --- a/client/lib/l10n/app_it.arb +++ b/client/lib/l10n/app_it.arb @@ -135,7 +135,7 @@ "generateWeekLabel": "Pianifica la settimana", "generateWeekSubtitle": "L'AI creerà un menu con colazione, pranzo e cena per tutta la settimana", "generatingMenu": "Generazione menu...", - "weekPlannedLabel": "Settimana pianificata", + "dayPlannedLabel": "Giorno pianificato", "planMenuButton": "Pianifica i pasti", "planMenuTitle": "Cosa pianificare?", diff --git a/client/lib/l10n/app_ja.arb b/client/lib/l10n/app_ja.arb index b6185fc..884fdc2 100644 --- a/client/lib/l10n/app_ja.arb +++ b/client/lib/l10n/app_ja.arb @@ -135,7 +135,7 @@ "generateWeekLabel": "週を計画する", "generateWeekSubtitle": "AIが一週間の朝食・昼食・夕食のメニューを作成します", "generatingMenu": "メニューを生成中...", - "weekPlannedLabel": "週の計画済み", + "dayPlannedLabel": "日の計画済み", "planMenuButton": "食事を計画する", "planMenuTitle": "何を計画する?", diff --git a/client/lib/l10n/app_ko.arb b/client/lib/l10n/app_ko.arb index 40c4cf8..fde3c49 100644 --- a/client/lib/l10n/app_ko.arb +++ b/client/lib/l10n/app_ko.arb @@ -135,7 +135,7 @@ "generateWeekLabel": "주간 계획하기", "generateWeekSubtitle": "AI가 한 주 동안 아침, 점심, 저녁 식사 메뉴를 만들어 드립니다", "generatingMenu": "메뉴 생성 중...", - "weekPlannedLabel": "주간 계획 완료", + "dayPlannedLabel": "일일 계획 완료", "planMenuButton": "식사 계획하기", "planMenuTitle": "무엇을 계획하시겠어요?", diff --git a/client/lib/l10n/app_localizations.dart b/client/lib/l10n/app_localizations.dart index 564ff31..4e17d4a 100644 --- a/client/lib/l10n/app_localizations.dart +++ b/client/lib/l10n/app_localizations.dart @@ -826,11 +826,11 @@ abstract class AppLocalizations { /// **'Generating menu...'** String get generatingMenu; - /// No description provided for @weekPlannedLabel. + /// No description provided for @dayPlannedLabel. /// /// In en, this message translates to: - /// **'Week planned'** - String get weekPlannedLabel; + /// **'Day planned'** + String get dayPlannedLabel; /// No description provided for @planMenuButton. /// diff --git a/client/lib/l10n/app_localizations_ar.dart b/client/lib/l10n/app_localizations_ar.dart index 61fae2a..13fd59a 100644 --- a/client/lib/l10n/app_localizations_ar.dart +++ b/client/lib/l10n/app_localizations_ar.dart @@ -371,7 +371,7 @@ class AppLocalizationsAr extends AppLocalizations { String get generatingMenu => 'جارٍ إنشاء القائمة...'; @override - String get weekPlannedLabel => 'تم تخطيط الأسبوع'; + String get dayPlannedLabel => 'تم تخطيط اليوم'; @override String get planMenuButton => 'تخطيط الوجبات'; diff --git a/client/lib/l10n/app_localizations_de.dart b/client/lib/l10n/app_localizations_de.dart index 233938e..1f20ec8 100644 --- a/client/lib/l10n/app_localizations_de.dart +++ b/client/lib/l10n/app_localizations_de.dart @@ -373,7 +373,7 @@ class AppLocalizationsDe extends AppLocalizations { String get generatingMenu => 'Menü wird erstellt...'; @override - String get weekPlannedLabel => 'Woche geplant'; + String get dayPlannedLabel => 'Tag geplant'; @override String get planMenuButton => 'Mahlzeiten planen'; diff --git a/client/lib/l10n/app_localizations_en.dart b/client/lib/l10n/app_localizations_en.dart index f46fba5..dbc151d 100644 --- a/client/lib/l10n/app_localizations_en.dart +++ b/client/lib/l10n/app_localizations_en.dart @@ -371,7 +371,7 @@ class AppLocalizationsEn extends AppLocalizations { String get generatingMenu => 'Generating menu...'; @override - String get weekPlannedLabel => 'Week planned'; + String get dayPlannedLabel => 'Day planned'; @override String get planMenuButton => 'Plan meals'; diff --git a/client/lib/l10n/app_localizations_es.dart b/client/lib/l10n/app_localizations_es.dart index 65d03ea..d6ea969 100644 --- a/client/lib/l10n/app_localizations_es.dart +++ b/client/lib/l10n/app_localizations_es.dart @@ -373,7 +373,7 @@ class AppLocalizationsEs extends AppLocalizations { String get generatingMenu => 'Generando menú...'; @override - String get weekPlannedLabel => 'Semana planificada'; + String get dayPlannedLabel => 'Día planificado'; @override String get planMenuButton => 'Planificar comidas'; diff --git a/client/lib/l10n/app_localizations_fr.dart b/client/lib/l10n/app_localizations_fr.dart index d586eea..0b1f233 100644 --- a/client/lib/l10n/app_localizations_fr.dart +++ b/client/lib/l10n/app_localizations_fr.dart @@ -374,7 +374,7 @@ class AppLocalizationsFr extends AppLocalizations { String get generatingMenu => 'Génération du menu...'; @override - String get weekPlannedLabel => 'Semaine planifiée'; + String get dayPlannedLabel => 'Jour planifié'; @override String get planMenuButton => 'Planifier les repas'; diff --git a/client/lib/l10n/app_localizations_hi.dart b/client/lib/l10n/app_localizations_hi.dart index 8a88e96..f899d6f 100644 --- a/client/lib/l10n/app_localizations_hi.dart +++ b/client/lib/l10n/app_localizations_hi.dart @@ -372,7 +372,7 @@ class AppLocalizationsHi extends AppLocalizations { String get generatingMenu => 'मेनू बना रहे हैं...'; @override - String get weekPlannedLabel => 'सप्ताह की योजना बनाई गई'; + String get dayPlannedLabel => 'दिन की योजना बनाई गई'; @override String get planMenuButton => 'भोजन की योजना बनाएं'; diff --git a/client/lib/l10n/app_localizations_it.dart b/client/lib/l10n/app_localizations_it.dart index a43466f..ca56c9f 100644 --- a/client/lib/l10n/app_localizations_it.dart +++ b/client/lib/l10n/app_localizations_it.dart @@ -373,7 +373,7 @@ class AppLocalizationsIt extends AppLocalizations { String get generatingMenu => 'Generazione menu...'; @override - String get weekPlannedLabel => 'Settimana pianificata'; + String get dayPlannedLabel => 'Giorno pianificato'; @override String get planMenuButton => 'Pianifica i pasti'; diff --git a/client/lib/l10n/app_localizations_ja.dart b/client/lib/l10n/app_localizations_ja.dart index 8991ccf..653c314 100644 --- a/client/lib/l10n/app_localizations_ja.dart +++ b/client/lib/l10n/app_localizations_ja.dart @@ -369,7 +369,7 @@ class AppLocalizationsJa extends AppLocalizations { String get generatingMenu => 'メニューを生成中...'; @override - String get weekPlannedLabel => '週の計画済み'; + String get dayPlannedLabel => '日の計画済み'; @override String get planMenuButton => '食事を計画する'; diff --git a/client/lib/l10n/app_localizations_ko.dart b/client/lib/l10n/app_localizations_ko.dart index c77b316..7a1b39a 100644 --- a/client/lib/l10n/app_localizations_ko.dart +++ b/client/lib/l10n/app_localizations_ko.dart @@ -369,7 +369,7 @@ class AppLocalizationsKo extends AppLocalizations { String get generatingMenu => '메뉴 생성 중...'; @override - String get weekPlannedLabel => '주간 계획 완료'; + String get dayPlannedLabel => '일일 계획 완료'; @override String get planMenuButton => '식사 계획하기'; diff --git a/client/lib/l10n/app_localizations_pt.dart b/client/lib/l10n/app_localizations_pt.dart index 941ea84..02e07e2 100644 --- a/client/lib/l10n/app_localizations_pt.dart +++ b/client/lib/l10n/app_localizations_pt.dart @@ -373,7 +373,7 @@ class AppLocalizationsPt extends AppLocalizations { String get generatingMenu => 'Gerando menu...'; @override - String get weekPlannedLabel => 'Semana planejada'; + String get dayPlannedLabel => 'Dia planejado'; @override String get planMenuButton => 'Planejar refeições'; diff --git a/client/lib/l10n/app_localizations_ru.dart b/client/lib/l10n/app_localizations_ru.dart index bf28095..da19b4e 100644 --- a/client/lib/l10n/app_localizations_ru.dart +++ b/client/lib/l10n/app_localizations_ru.dart @@ -371,7 +371,7 @@ class AppLocalizationsRu extends AppLocalizations { String get generatingMenu => 'Генерируем меню...'; @override - String get weekPlannedLabel => 'Неделя запланирована'; + String get dayPlannedLabel => 'День запланирован'; @override String get planMenuButton => 'Спланировать меню'; diff --git a/client/lib/l10n/app_localizations_zh.dart b/client/lib/l10n/app_localizations_zh.dart index be1a17e..b33e61d 100644 --- a/client/lib/l10n/app_localizations_zh.dart +++ b/client/lib/l10n/app_localizations_zh.dart @@ -369,7 +369,7 @@ class AppLocalizationsZh extends AppLocalizations { String get generatingMenu => '正在生成菜单...'; @override - String get weekPlannedLabel => '本周已规划'; + String get dayPlannedLabel => '今日已规划'; @override String get planMenuButton => '规划餐食'; diff --git a/client/lib/l10n/app_pt.arb b/client/lib/l10n/app_pt.arb index c552cbf..cb3f9f3 100644 --- a/client/lib/l10n/app_pt.arb +++ b/client/lib/l10n/app_pt.arb @@ -135,7 +135,7 @@ "generateWeekLabel": "Planejar a semana", "generateWeekSubtitle": "A IA criará um menu com café da manhã, almoço e jantar para a semana inteira", "generatingMenu": "Gerando menu...", - "weekPlannedLabel": "Semana planejada", + "dayPlannedLabel": "Dia planejado", "planMenuButton": "Planejar refeições", "planMenuTitle": "O que planejar?", diff --git a/client/lib/l10n/app_ru.arb b/client/lib/l10n/app_ru.arb index 01e0315..d4cf741 100644 --- a/client/lib/l10n/app_ru.arb +++ b/client/lib/l10n/app_ru.arb @@ -133,7 +133,7 @@ "generateWeekLabel": "Запланировать неделю", "generateWeekSubtitle": "AI составит меню с завтраком, обедом и ужином на всю неделю", "generatingMenu": "Генерируем меню...", - "weekPlannedLabel": "Неделя запланирована", + "dayPlannedLabel": "День запланирован", "planMenuButton": "Спланировать меню", "planMenuTitle": "Что запланировать?", diff --git a/client/lib/l10n/app_zh.arb b/client/lib/l10n/app_zh.arb index 2e79bda..0131a66 100644 --- a/client/lib/l10n/app_zh.arb +++ b/client/lib/l10n/app_zh.arb @@ -135,7 +135,7 @@ "generateWeekLabel": "规划本周", "generateWeekSubtitle": "AI将为整周创建含早餐、午餐和晚餐的菜单", "generatingMenu": "正在生成菜单...", - "weekPlannedLabel": "本周已规划", + "dayPlannedLabel": "今日已规划", "planMenuButton": "规划餐食", "planMenuTitle": "规划什么?", diff --git a/client/lib/shared/constants/date_limits.dart b/client/lib/shared/constants/date_limits.dart new file mode 100644 index 0000000..96978f8 --- /dev/null +++ b/client/lib/shared/constants/date_limits.dart @@ -0,0 +1,5 @@ +/// How many days into the future the app allows planning and browsing. +const int kPlanningHorizonDays = 28; + +/// How many weeks into the past the menu screen allows backward navigation. +const int kMenuPastWeeks = 8;