Commit graph

69 commits

Author SHA1 Message Date
dac787b81b test(auth): add multi-user regression coverage
- Enable backend tests in CI (remove if: false)
- Fix test_products_helpers.py to pass current_user parameter
- Fix test_routines_helpers.py to include short_id in products
- Fix llm_context.py to use product_effect_profile correctly
- All 221 tests passing
2026-03-12 16:42:00 +01:00
b11f64d5a1 refactor(frontend): route protected API access through server session 2026-03-12 16:27:24 +01:00
cd8e39939a feat(frontend): add Authelia OIDC session flow 2026-03-12 15:40:55 +01:00
e29d62f949 feat(frontend): auto-generate TypeScript types from backend OpenAPI schema
Replace manually maintained types in src/lib/types.ts with auto-generated
types from FastAPI's OpenAPI schema using @hey-api/openapi-ts. The bridge
file re-exports generated types with renames, Require<> augmentations for
fields that are optional in the schema but always present in responses, and
manually added relationship fields excluded from OpenAPI.

- Add openapi-ts.config.ts and generate:api npm script
- Generate types into src/lib/api/generated/types.gen.ts
- Rewrite src/lib/types.ts as bridge with re-exports and augmentations
- Fix null vs undefined mismatches in consumer components
- Remove unused manual type definitions from api.ts
- Update AGENTS.md docs with type generation workflow
2026-03-12 09:17:40 +01:00
470d49b061 docs: restructure AGENTS.md into hierarchical knowledge base 2026-03-11 11:35:47 +01:00
157cbc425e feat(frontend): improve lab result filter ergonomics 2026-03-10 12:44:19 +01:00
0253b2377d feat(frontend): unify page shell and move create flows to dedicated routes 2026-03-10 12:25:25 +01:00
d91d06455b feat(products): improve replenishment-aware shopping suggestions
Replace product weight and repurchase intent fields with per-package remaining levels and inventory-first restock signals. Enrich shopping suggestions with usage-aware replenishment scoring so the frontend and LLM can prioritize real gaps and near-empty staples more reliably.
2026-03-09 13:37:40 +01:00
bb5d402c15 feat(products): improve shopping suggestion decision support 2026-03-08 22:30:30 +01:00
d228b44209 feat(i18n): add Phase 3 observability translations (EN + PL)
Added translations for all observability components:
- Validation warnings panel
- Auto-fixes badge
- AI reasoning process viewer
- Debug information panel
- Structured error display

English translations (en.json):
- observability_validationWarnings: "Validation Warnings"
- observability_autoFixesApplied: "Automatically adjusted"
- observability_aiReasoningProcess: "AI Reasoning Process"
- observability_debugInfo: "Debug Information"
- observability_model/duration/tokenUsage: Debug panel labels
- observability_validationFailed: "Safety validation failed"

Polish translations (pl.json):
- observability_validationWarnings: "Ostrzeżenia walidacji"
- observability_autoFixesApplied: "Automatycznie dostosowano"
- observability_aiReasoningProcess: "Proces rozumowania AI"
- observability_debugInfo: "Informacje debugowania"
- All debug panel labels translated
- observability_validationFailed: "Walidacja bezpieczeństwa nie powiodła się"

Updated components:
- ValidationWarningsAlert: Uses m.observability_validationWarnings()
- AutoFixBadge: Uses m.observability_autoFixesApplied()
- ReasoningChainViewer: Uses m.observability_aiReasoningProcess()
- MetadataDebugPanel: All labels now use i18n
- StructuredErrorDisplay: Translates error prefixes

All components now fully support English and Polish locales.
2026-03-06 16:28:23 +01:00
b2886c2f2b refactor(frontend): align observability panels with editorial design system
Replace hardcoded gray-* colors with design system tokens:
- border-gray-200 → border-muted
- bg-gray-50 → bg-muted/30
- text-gray-600/700 → text-muted-foreground/foreground
- hover:bg-gray-100 → hover:bg-muted/50

Updated components:
- MetadataDebugPanel: now matches Card aesthetic
- ReasoningChainViewer: now uses warm editorial tones

Benefits:
- Consistent with existing reasoning/summary cards
- Matches warm editorial aesthetic (hsl(42...) palette)
- DRY: reuses design system tokens
- Documented collapsible panel pattern in cookbook

This fixes the cool gray panels that looked out of place among the warm beige editorial UI.
2026-03-06 16:25:47 +01:00
c8fa80be99 fix(api): rename 'metadata' to 'response_metadata' to avoid Pydantic conflict
The field name 'metadata' conflicts with Pydantic's internal ClassVar.
Renamed to 'response_metadata' throughout:
- Backend: RoutineSuggestion, BatchSuggestion, ShoppingSuggestionResponse
- Frontend: TypeScript types and component usages

This fixes the AttributeError when setting metadata on SQLModel instances.
2026-03-06 16:16:35 +01:00
5d3f876bec feat(frontend): add Phase 3 UI components for observability
Components created:
- ValidationWarningsAlert: Display validation warnings with collapsible list
- StructuredErrorDisplay: Parse and display HTTP 502 errors as bullet points
- AutoFixBadge: Show automatically applied fixes
- ReasoningChainViewer: Collapsible panel for LLM thinking process
- MetadataDebugPanel: Collapsible debug info (model, duration, token metrics)

CSS changes:
- Add .editorial-alert--warning and .editorial-alert--info variants

Integration:
- Update routines/suggest page to show warnings, auto-fixes, reasoning, and metadata
- Update products/suggest page with same observability components
- Replace plain error divs with StructuredErrorDisplay for better UX

All components follow design system and pass svelte-check with 0 errors
2026-03-06 15:53:46 +01:00
3c3248c2ea feat(api): add Phase 3 observability - expose validation warnings and metadata to frontend
Backend changes:
- Create ResponseMetadata and TokenMetrics models for API responses
- Modify call_gemini() and call_gemini_with_function_tools() to return (response, log_id) tuple
- Add _build_response_metadata() helper to extract metadata from AICallLog
- Update routines API (/suggest, /suggest-batch) to populate validation_warnings, auto_fixes_applied, and metadata
- Update products API (/suggest) to populate observability fields
- Update skincare API to handle new return signature

Frontend changes:
- Add TypeScript types: TokenMetrics, ResponseMetadata
- Update RoutineSuggestion, BatchSuggestion, ShoppingSuggestionResponse with observability fields

Next: Create UI components to display warnings, reasoning chains, and token metrics
2026-03-06 15:50:28 +01:00
b99b9ed68e feat(profile): add profile settings and LLM user context 2026-03-05 15:57:21 +01:00
db3d9514d5 fix(routines): remove dose from AI routine suggestions 2026-03-05 14:19:18 +01:00
c4be7dd1be refactor(frontend): align lab results filters with products style 2026-03-05 13:14:33 +01:00
7eca2391a9 perf(frontend): trim unused Cormorant Google font weight 2026-03-05 12:53:14 +01:00
0a4ccefe28 feat(repo): expand lab results workflows across backend and frontend 2026-03-05 12:46:49 +01:00
013492ec2b refactor(products): remove usage notes and contraindications fields 2026-03-05 10:11:24 +01:00
9df241a6a9 feat(frontend): localize skin active concerns with enum multi-select 2026-03-04 23:37:14 +01:00
0e439b4ca7 feat(backend): move product pricing to async persisted jobs 2026-03-04 22:46:16 +01:00
693c6a9626 feat(frontend): unify editorial UI and DRY form architecture 2026-03-04 21:43:37 +01:00
d4fbc1faf5 feat(frontend): streamline AI workflows and localize remaining UI copy
Move product and skin AI helpers into modal flows, simplify product edit/inventory navigation, and improve responsive actions so core forms are faster to use. Localize remaining frontend labels/placeholders and strip deprecated Rollup output options to remove deploy-time build warnings.
2026-03-04 18:13:49 +01:00
83ba4cc5c0 feat(products): compute price tiers from objective price/use 2026-03-04 14:47:18 +01:00
c5ea38880c refactor(products): remove obsolete interaction fields across stack 2026-03-04 12:42:12 +01:00
a7ad956a62 fix(frontend): correct plural forms for count labels 2026-03-04 01:30:56 +01:00
820d58ea37 feat(routines): enrich single AI suggestions with concise context 2026-03-04 01:22:57 +01:00
067e460dd2 chore(frontend): format files with prettier 2026-03-03 20:51:34 +01:00
098b158b75 feat(frontend): add ESLint and Prettier with Svelte support
- Install eslint, prettier and related plugins
- Add lint and format npm scripts
- Configure eslint.config.js with Svelte + TypeScript rules
- Configure .prettierrc with Svelte plugin
- Fix code to comply with lint rules:
  - Use resolve() for navigation links
  - Use SvelteMap for reactive maps
  - Use writable  instead of  +
  - Remove unused imports and variables

Note: ignoreGoto is set to true due to eslint-plugin-svelte#1327
2026-03-03 01:21:50 +01:00
609995732b feat(routines): add minimize_products option for batch suggestions 2026-03-03 00:50:49 +01:00
40f9a353bb feat(products): add shopping suggestions feature
- Add POST /api/products/suggest endpoint that analyzes skin condition
  and inventory to suggest product types (e.g., 'Salicylic Acid 2% Masque')
- Add MCP tool get_shopping_suggestions() for MCP clients
- Add 'Suggest' button to Products page in frontend
- Add /products/suggest page with suggestion cards
- Include product type, key ingredients, target concerns, why_needed,
  recommended_time, and frequency in suggestions
- Fix stock logic: sealed products now count as available inventory
- Add legend to clarify ✓ (in stock) vs ✗ (not in stock) markers
2026-03-02 22:38:08 +01:00
679e4e81f4 feat(frontend): responsive design for mobile (RWD)
- Layout: mobile hamburger + drawer nav (backdrop button + sibling nav),
  desktop sidebar hidden on small screens, p-4 md:p-8 main padding
- Products: card list view on mobile, flex-wrap filters
- Lab results: card list view on mobile
- ProductForm: responsive grids (grid-cols-1 sm:grid-cols-2), skin
  profile checkboxes 2→3 cols, active ingredient row restructured
  (name+✕ in flex row, percent/strength/irritation in 3-col grid),
  section headers stack on mobile
- Skin snapshots: date+icons on one row, badges on separate row below
- Product [id] header: back link stacked above title, redundant badge removed
- Routines header: flex-col on mobile, sm:flex-row

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 13:35:25 +01:00
c85ca355df refactor(routines): streamline suggest prompt — merge inventory context, add leaving_home SPF hint
- Remove _build_inventory_context; fold pao_months into DOSTĘPNE PRODUKTY entries
- Remove "Otwarte równolegle" duplicate section from prompt
- Rename OSTATNIE RUTYNY (7 dni) → OSTATNIE RUTYNY
- Add _build_day_context and SuggestRoutineRequest.leaving_home (optional bool)
- System prompt: replace unconditional PAO rule with conditional; add SPF factor
  selection logic based on KONTEKST DNIA leaving_home value
- Frontend: leaving_home checkbox (AM only) + i18n keys pl/en

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 23:47:54 +01:00
d3bd2ff30d feat(skincare): allow HEIC/HEIF uploads in skin analysis 2026-03-01 23:23:04 +01:00
921fe3ef61 fix(frontend): pick freshest skin snapshot on dashboard 2026-03-01 21:51:07 +01:00
18683925a1 fix(frontend): use /api proxy for skin photo upload in browser context
analyzeSkinPhotos was hardcoding PUBLIC_API_BASE, causing browser-side
requests to hit localhost:8000 directly instead of going through nginx.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 20:01:16 +01:00
17eaa5d1bd fix(frontend): add missing priorities field to skin snapshots UI
priorities was present in the model, API, and LLM prompt but never
surfaced in the frontend — add it to create/edit forms, read view,
AI photo pre-fill, and page.server.ts actions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 19:58:38 +01:00
75ef1bca56 feat(routines): add minoxidil beard/mustache option to routine suggestions
- Add include_minoxidil_beard flag to SuggestRoutineRequest and SuggestBatchRequest
- Detect minoxidil products by scanning name, brand, INCI and actives; pass them
  to the LLM even though they are medications
- Inject CELE UŻYTKOWNIKA context block into prompts when flag is enabled
- Add _build_objectives_context() returning empty string when flag is off
- Add call_gemini() helper that centralises Gemini API calls and logs every
  request/response to a new ai_call_logs table (AICallLog model + /ai-logs router)
- Nginx: raise client_max_body_size to 16 MB for photo uploads

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 19:46:07 +01:00
3aa03b412b feat(frontend): group product selector by category in routine step forms
Products in the Add/Edit step dropdowns are now grouped by category
(Cleanser → Serum → Moisturizer → …) using SelectGroup/SelectGroupHeading,
and sorted alphabetically by brand then name within each group.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 18:22:51 +01:00
d4e3040674 fix(frontend): fix step numbering and client-side API base URL
- Step numbers now use each-block index (i+1) instead of order_index+1,
  fixing display when order_index starts from 1 in existing data
- api.ts: browser-side requests use /api (nginx proxy) instead of
  PUBLIC_API_BASE (localhost:8000), fixing PATCH/client calls on remote hosts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 17:34:00 +01:00
4b0fedde35 feat(frontend): add drag-and-drop reordering and inline editing for routine steps
- Install svelte-dnd-action v0.9.69
- Use dragHandleZone + dragHandle for per-step ⋮⋮ drag handles
- PATCH only steps whose order_index changed after a drop
- Inline edit mode (✎ button) expands step in-place: product steps show product/dose/region selects; action steps show action_type/notes
- DnD disabled while a step is being edited

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 17:21:59 +01:00
99584521a1 feat(frontend): add PL/EN i18n using @inlang/paraglide-js v2
- Install @inlang/paraglide-js v2 with Vite plugin and paraglideMiddleware hook
- Add messages/pl.json and messages/en.json with ~400 translation keys
- Create project.inlang/settings.json (PL as base locale)
- Add LanguageSwitcher component (cookie-based, no URL prefix needed)
- Replace all hardcoded strings across 14 pages/components with m.*() calls
- ProductForm uses derived label maps for all enum types (category, texture, etc.)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 13:20:34 +01:00
9524e4df54 fix(frontend): fix routine step numbering and product name display
Steps were numbered from 2 due to off-by-one (order_index + 1).
Product steps showed "Unknown step" because the template checked
step.product (never returned by API) instead of looking up by
step.product_id in the already-loaded products list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 01:04:28 +01:00
832676bcfa fix(frontend): fix routines list crash and AI save redirect
- Make Routine.steps optional in types.ts — list endpoint does not
  eager-load steps, so the field is absent from the JSON response
- Guard routine.steps?.length ?? 0 in routines list page to prevent
  SSR TypeError when steps is undefined
- Move redirect() outside try/catch in suggest save action; SvelteKit
  redirect throws internally and was being caught, causing a 500 error
  instead of navigating to the new routine

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 00:54:54 +01:00
6e7f715ef2 feat: AI-generated skincare routine suggestions (single + batch)
Add Gemini-powered endpoints and frontend pages for proposing skincare
routines based on skin state, product compatibility, grooming schedule,
and recent history.

Backend (routines.py):
- POST /routines/suggest — single AM/PM routine for a date
- POST /routines/suggest-batch — AM+PM plan for up to 14 days
- Prompt context: skin snapshot, grooming schedule, 7-day history,
  filtered product list with effects/incompatibilities/context rules
- Respects retinoid frequency limits, acid/retinoid separation,
  grooming-aware safe_after_shaving rules

Frontend:
- /routines/suggest page with tab switcher (single / batch)
- Single tab: date + AM/PM + optional notes → generate → preview → save
- Batch tab: date range + notes → collapsible day cards (AM+PM) → save all
- Loading spinner during Gemini calls; product names resolved from map
- "Zaproponuj rutynę AI" button added to routines list page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 00:34:43 +01:00
a3b25d5e46 feat(frontend): add grooming schedule CRUD page
- New route /routines/grooming-schedule with load + create/update/delete actions
- Entries grouped by day of week with inline editing
- 4 API functions added to api.ts (get/create/update/delete)
- Nav: add Grooming link, fix isActive to not highlight parent when child matches
- Nav: replace ⌂ text char with 🏠 emoji for Dashboard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 23:46:33 +01:00
1b1566e6d7 feat(frontend): group products by category with ownership filter
Replace category filter dropdown with client-side grouping and a
3-way ownership toggle (All / Owned / Not owned). Products are grouped
by category with header rows as visual dividers, sorted brand → name
within each group. Category column removed (redundant with headings).

Backend: GET /products now returns ProductWithInventory so inventory
data is available for ownership filtering (bulk-loaded in one query).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 23:07:37 +01:00
ef8334b93c feat(frontend): add anti_aging to IngredientFunction type and form selector
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 22:35:39 +01:00
d938c9999b feat(frontend): add edit and delete for skin snapshots
Add inline edit form and delete button to each snapshot card on /skin.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 21:37:15 +01:00