5 Commits

Author SHA1 Message Date
dbastrikin
205edbdade feat: rename ingredients→products, products→user_products; add barcode/OFF import
- Rename catalog: ingredient/* → product/* (canonical_name, barcode, nutrition per 100g)
- Rename pantry: product/* → userproduct/* (user-owned items with expiry)
- Squash migrations into single 001_initial_schema.sql (clean-db baseline)
- product_categories: add English canonical name column; fix COALESCE in queries
- Remove product_translations: product names are stored in their original language
- Add default_unit_name to product API responses via unit_translations JOIN
- Add cmd/importoff: bulk import from OpenFoodFacts JSONL dump (COPY + ON CONFLICT)
- Diary: support product_id entries alongside dish_id (CHECK num_nonnulls = 1)
- Home: getLoggedCalories joins both recipes and catalog products
- Flutter: rename models/providers/services to match backend rename
- Flutter: add barcode scan flow for diary (mobile_scanner, product_portion_sheet)
- Flutter: localise 6 new keys across 12 languages (barcode scan, portion weight)
- Routes: GET /products/search, GET /products/barcode/{barcode}, /user-products

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 12:45:48 +02:00
dbastrikin
54b10d51e2 feat: Flutter client localisation (12 languages)
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>
2026-03-19 22:22:52 +02:00
dbastrikin
cf69a4a3d9 feat: dish recognition job context, diary linkage, home widget, history page
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>
2026-03-19 16:11:21 +02:00
dbastrikin
deceedd4a7 feat: implement Iteration 3 — product/receipt/dish recognition
Backend:
- gemini/client.go: refactor to shared callGroq transport; add
  generateVisionContent using llama-3.2-11b-vision-preview model
- gemini/recognition.go: RecognizeReceipt, RecognizeProducts,
  RecognizeDish (vision), ClassifyIngredient (text); shared parseJSON helper
- ingredient/repository.go: add FuzzyMatch (wraps Search, returns best hit)
- recognition/handler.go: POST /ai/recognize-receipt, /ai/recognize-products,
  /ai/recognize-dish; enrichItems with fuzzy match + AI classify fallback;
  parallel multi-image processing with deduplication
- server.go + main.go: wire recognition handler under /ai routes

Flutter:
- pubspec.yaml: add image_picker ^1.1.0
- AndroidManifest.xml: add CAMERA and READ_EXTERNAL_STORAGE permissions
- Info.plist: add NSCameraUsageDescription and NSPhotoLibraryUsageDescription
- recognition_service.dart: RecognitionService wrapping /ai/* endpoints;
  RecognizedItem, ReceiptResult, DishResult models
- scan_screen.dart: mode selector (receipt / products / dish / manual);
  image source picker; loading overlay; navigates to confirm or dish screen
- recognition_confirm_screen.dart: editable list of recognized items;
  inline qty/unit editing; swipe-to-delete; batch-add to pantry
- dish_result_screen.dart: dish name, KBZHU breakdown, similar dishes chips
- app_router.dart: /scan, /scan/confirm, /scan/dish routes (no bottom nav)
- products_screen.dart: FAB now shows bottom sheet with Manual / Scan options

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 10:54:03 +02:00
dbastrikin
24219b611e feat: implement Iteration 0 foundation (backend + Flutter client)
Backend (Go):
- Project structure with chi router, pgxpool, goose migrations
- JWT auth (access/refresh tokens) with Firebase token verification
- NoopTokenVerifier for local dev without Firebase credentials
- PostgreSQL user repository with atomic profile updates (transactions)
- Mifflin-St Jeor calorie calculation based on profile data
- REST API: POST /auth/login, /auth/refresh, /auth/logout, GET/PUT /profile, GET /health
- Middleware: auth, CORS (localhost wildcard), logging, recovery, request_id
- Unit tests (51 passing) and integration tests (testcontainers)
- Docker Compose setup with postgres healthcheck and graceful shutdown

Flutter client:
- Riverpod state management with GoRouter navigation
- Firebase Auth (email/password + Google sign-in with web popup support)
- Platform-aware API URLs (web/Android/iOS)
- Dio HTTP client with JWT auth interceptor and concurrent refresh handling
- Secure token storage
- Screens: Login, Register, Home (tabs: Menu, Recipes, Products, Profile)
- Unit tests (17 passing)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 13:14:58 +02:00