Commit graph

23 commits

Author SHA1 Message Date
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
95fbdeb212 feat: add deployment guide, nginx/systemd configs, switch to adapter-node
- Add docs/DEPLOYMENT.md: step-by-step Proxmox LXC guide (Debian 13,
  PostgreSQL, nginx reverse proxy, systemd services)
- Add nginx/innercontext.conf: proxy /api/ → uvicorn, /mcp/ → uvicorn
  with SSE streaming support, / → SvelteKit Node server
- Add systemd/innercontext.service and innercontext-node.service
- Switch frontend from adapter-auto to adapter-node (required for
  +page.server.ts form actions); install adapter-node 5.5.4
- Update README.md: add frontend, MCP sections; fix /skin-snapshots →
  /skincare; update repo layout
- Replace frontend/README.md generic Svelte template with project docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 20:09:00 +01:00
142fbe8530 fix(frontend): resolve TypeScript type errors from skin model refactor
- 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>
2026-02-28 18:01:17 +01:00
4954d4f449 refactor(skin): replace trend with texture field on SkinConditionSnapshot
Remove the derived `trend` field (better computed from history by the MCP
agent) and add `texture: smooth|rough|flaky|bumpy` which LLM can reliably
assess from photos. Updates model, API, system prompt, tests, and frontend.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 13:25:57 +01:00
ac28eb30d1 fix: remove redundant assignments to \$derived variables before goto
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 13:00:19 +01:00
853019075d fix: remove AM/PM filter from routines, add keyed each blocks
Remove the All/AM/PM filter buttons and part_of_day param from
the routines list page — date-based sorting/filtering is preferred.

Add missing keyed {#each} blocks across all pages to follow
Svelte 5 best practice (dashboard, products, medications,
lab results, routines list and detail, skin).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 12:57:56 +01:00
66ee473deb feat: AI photo analysis for skin snapshots
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>
2026-02-28 12:47:51 +01:00
cc25ac4e65 fix: redirect to product list after creating a product
Previously redirected to /products/{id} (edit page) which looks
identical to the create form, making it appear as if nothing happened.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 23:11:41 +01:00
31e030eaac feat: AI pre-fill for product form via Gemini API
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>
2026-02-27 23:04:24 +01:00
c413e27768 fix: suppress state_referenced_locally warnings in ProductForm
Wrap all prop-derived $state initializers with untrack() to explicitly
signal that one-time capture from the product prop is intentional.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 16:37:00 +01:00
43fcba4de6 feat: add full/empty weight fields to Product and last_weighed_at to ProductInventory
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>
2026-02-27 16:35:08 +01:00
2b73dc63ac fix: scroll form error into view on product create failure
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 16:05:24 +01:00
c132bc836f fix: uniform 2-col classification grid and fix effect profile label overflow
- Classification: replace fragmented layout (full-width + 3-col + full-width)
  with a single 2-column grid; Category spans full width via col-span-2
- Effect profile: replace flex + fixed w-40 label with CSS grid using
  minmax(7rem,10rem) label column to prevent overflow at narrow viewports

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 15:55:58 +01:00
479be25112 feat: complete product create/edit form with all fields
Extract shared ProductForm.svelte component covering actives (dynamic
rows with ingredient function checkboxes), product_effect_profile
(range sliders 0–5), context_rules (tristate selects), synergizes_with,
incompatible_with (dynamic rows), and contraindications.

Replace the Quick edit stub on the product detail page with the full
edit form pre-populated from the existing product. Update both server
actions to parse all new fields including JSON payloads for complex
nested objects.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 11:43:56 +01:00
6333c6678a refactor: remove personal_rating, DRY get_or_404, fix ty errors
- Drop Product.personal_rating from model, API schemas, and all frontend
  views (list table, detail view, quick-edit form, new-product form)
- Extract get_or_404 into backend/innercontext/api/utils.py; remove five
  duplicate copies from individual API modules
- Fix all ty type errors: generic get_or_404 with TypeVar, cast() in
  coerce_effect_profile validator, col() for ilike on SQLModel column,
  dict[str, Any] annotation in test helper, ty: ignore for CORSMiddleware

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 11:20:13 +01:00
5e3c0c97e5 fix: re-export WithElementRef, WithoutChild, WithoutChildrenOrChild from utils
shadcn-svelte components import these types from \$lib/utils — add
re-exports from bits-ui to resolve 25 type errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 10:24:34 +01:00
9a069508af refactor: remove routine_role, recommended_frequency, evidence_level, cumulative_with
Drop fields identified as redundant or low-value from the Product model,
API schemas, frontend types, and forms. Raise effect_profile threshold in
to_llm_context() from >0 to >=2 to suppress noise values. Remove sku/barcode
from LLM context output (kept on model for catalog use).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 10:22:59 +01:00
9bf94a979c fix: resolve frontend/backend integration bugs
- Rename skincare route prefix /skin-snapshots → /skincare to match API client
- Add redirect_slashes=False to FastAPI app; change collection routes from "/" to ""
  to eliminate 307 redirects on POST/GET without trailing slash
- Fix redirect() inside try/catch in products/new and routines/new server actions
  (SvelteKit redirect() throws and was being caught as a 500 error)
- Eagerly load inventory and steps relationships via explicit SELECT + model_dump(mode="json"),
  working around SQLModel 0.0.37 not serializing Relationship fields in response_model
- Add field_validator for product_effect_profile to coerce DB-returned dict → ProductEffectProfile,
  eliminating Pydantic serializer warning
- Update all tests to use routes without trailing slash

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 21:53:17 +01:00
b140c55cda feat: add API client, types, layout, and all page routes 2026-02-26 20:45:54 +01:00
2e4e3fba50 feat: add SvelteKit frontend scaffold with Tailwind CSS 2026-02-26 20:34:34 +01:00