Flutter client:
- Progress dialog: redesigned with pulsing animated icon, info hint about
background mode, full-width Minimize button; dismiss signal via ValueNotifier
so the dialog always closes regardless of widget lifecycle
- Background recognition: when user taps Minimize, wasMinimizedByUser flag is
set; on completion a snackbar is shown instead of opening DishResultSheet
directly; snackbar action opens the sheet on demand
- Fix dialog spinning forever: finally block guarantees dismissSignal=true on
all exit paths including early returns from context.mounted checks
- Fix DishResultSheet not appearing: add ValueKey to _DailyMealsSection and
meal card Padding so Flutter reuses elements when _TodayJobsWidget is
inserted/removed from the SliverChildListDelegate list
- todayJobsProvider refresh: added refresh() method; called after job submit
and on DishJobDone; all ref.read() calls guarded with context.mounted checks
- food_search_sheet: scan buttons replaced with full-width stacked OutlinedButtons
- app.dart: WidgetsBindingObserver refreshes scan providers on app resume
- L10n: added dishRecognitionHint and minimize keys to all 12 locales
Backend:
- migrations/003: ALTER TYPE recipe_source ADD VALUE 'recommendation' to fix
22P02 error in GET /home/summary -> getRecommendations()
- item_enricher: normalizeProductCategory() validates AI-returned category
against known slugs, falls back to "other" — fixes products_category_fkey
FK violation during receipt recognition
- recognition prompt: enumerate valid categories so AI returns correct values
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Phase 1: date strip now covers today + 7 future days; right chevron enabled;
future pills rendered in lighter style.
Phase 2: home screen shows DateContext (past/today/future):
- future dates: hide calorie ring + macros, show PlanningBanner
- plannedMealsProvider derives from cached menuProvider (no extra API call)
- _MealCard shows ghost PlannedSlotTile for unconfirmed menu slots
- "Mark as eaten" creates a diary entry (source: menu_plan) via existing API
New l10n keys (12 locales): planningForDate, markAsEaten, plannedMealLabel
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add flutter_localizations + intl, 12 ARB files (en/ru/es/de/fr/it/pt/zh/ja/ko/ar/hi),
replace all hardcoded Russian UI strings with AppLocalizations, detect system locale
on first launch, localise bottom nav bar labels, document rule in CLAUDE.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend:
- Rename recognition_jobs → dish_recognition_jobs; add target_date and
target_meal_type columns to capture scan context at submission time
- Add job_id FK on meal_diary so entries are linked to their origin job
- New GET /ai/jobs endpoint returns today's unlinked jobs for the current user
- diary.Entry and CreateRequest gain job_id field; repository reads/writes it
- CORS middleware: allow Accept-Language and Cache-Control headers
- Logging middleware: implement http.Flusher on responseWriter (needed for SSE)
- Consolidate migrations into a single 001_initial_schema.sql
Flutter:
- POST /ai/recognize-dish now sends target_date and target_meal_type
- DishResultSheet accepts jobId; _addToDiary includes it in the diary payload,
saves last-used meal type to SharedPreferences, invalidates todayJobsProvider
- TodayJobsNotifier + todayJobsProvider: loads unlinked jobs via GET /ai/jobs
- Home screen shows _TodayJobsWidget (up to 3 tiles) between macros and meals;
tapping a done tile reopens DishResultSheet with the stored result
- Quick Actions row: third button "История" → /scan/history
- New RecognitionHistoryScreen: full-screen list of today's unlinked jobs
- LocalPreferences wrapper over SharedPreferences (last_used_meal_type)
- app_theme: apply Google Fonts Roboto as default font family
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend:
- Translate all recognition prompts (receipt, products, dish) from Russian to English
- Add lang parameter to Recognizer interface and pass locale.FromContext in handlers
- DishResult type uses candidates array for multi-candidate responses
Client:
- Add meal tracking: diary provider, date selector, meal type model
- DishResult parser: backward-compatible with legacy flat format and new candidates format
- DishResultScreen: sticky bottom button, full-width portion/meal-type inputs,
КБЖУ disclaimer moved under nutrition card, add date field to diary POST body
- Recognition prompts now return dish/product names in user's preferred language
- Onboarding, profile, home screen visual updates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend:
- internal/home: GET /home/summary endpoint
- Today's meal plan from menu_plans/menu_items
- Logged calories sum from meal_diary
- Daily goal from user profile (default 2000)
- Expiring products within 3 days
- Last 3 saved recommendations (no AI call on home load)
- Wire homeHandler in server.go and main.go
Flutter:
- shared/models/home_summary.dart: HomeSummary, TodaySummary,
TodayMealPlan, ExpiringSoon, HomeRecipe
- features/home/home_service.dart + home_provider.dart
- features/home/home_screen.dart: greeting, calorie progress bar,
today's meals card, expiring banner, quick actions row,
recommendations horizontal list
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>