- 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>
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>
- 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>
- 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>
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>
- 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>
- Remove s.trend from dashboard (field removed from SkinConditionSnapshot)
- Replace trend with texture in SkinPhotoAnalysisResponse (api.ts)
- Use record_id instead of id for LabResult and MedicationEntry keyed each blocks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add POST /skincare/analyze-photos endpoint that accepts 1–3 skin
photos, sends them to Gemini vision, and returns a structured
SkinPhotoAnalysisResponse for pre-filling the snapshot form.
Extract shared Gemini client setup into innercontext/llm.py
(get_gemini_client) so both products and skincare use a single
default model (gemini-flash-latest) and API key check.
Frontend: AI photo card on /skin page with file picker, previews,
and auto-fill of all form fields from the analysis result.
New fields (skin_type, sebum_tzone, sebum_cheeks) added to form
and server action.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add POST /products/parse-text endpoint that accepts raw product text,
calls Gemini (google-genai) with a structured extraction prompt, and
returns a partial ProductParseResponse. Frontend gains a collapsible
"AI pre-fill" card at the top of ProductForm that merges the LLM
response into all form fields reactively.
- Backend: ProductParseRequest/Response schemas, system prompt with
enum constraints, temperature=0.0 for deterministic extraction,
effect_profile always returned in full
- Frontend: parseProductText() in api.ts; controlled $state bindings
for all text/number/checkbox inputs; applyAiResult() merges response
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds full_weight_g and empty_weight_g to ProductBase (inherited by Product
and response models) so per-product package weight specs are captured.
Adds last_weighed_at to ProductInventory to record when a package was last
weighed. Wires up all fields through API schemas, frontend types, forms, and
the product detail page (add/edit/display).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>