Commit graph

121 commits

Author SHA1 Message Date
abf9593857 fix: correct Part.from_text() call and increase max_output_tokens for skin analysis
Pass `text=` as keyword arg to Part.from_text() and raise max_output_tokens
from 1024 to 2048 to prevent JSON truncation in the notes field.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 13:17:22 +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
e60dee5015 style: reformat import block in main.py
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 23:05:14 +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
c09acc7c81 refactor: split table models into Base/Table/Public for proper FastAPI serialization
Add ProductBase, ProductPublic, ProductWithInventory and
SkinConditionSnapshotBase, SkinConditionSnapshotPublic. Table models now inherit
from their Base counterpart and override JSON fields with sa_column. All
field_serializer hacks removed; FastAPI response models use the non-table Public
classes so Pydantic coerces raw DB dicts → typed models cleanly. ProductCreate
and SnapshotCreate now simply inherit their respective Base classes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 15:37:46 +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
8d4f9d1fc6 fix: load .env via python-dotenv; SQLite default for local dev 2026-02-26 20:51:13 +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
8f7d893a63 Initial commit: backend API, data models, and test suite
FastAPI backend for personal health and skincare data with MCP export.
Includes SQLModel models for products, inventory, medications, lab results,
routines, and skin condition snapshots. Pytest suite with 111 tests running
on SQLite in-memory (no PostgreSQL required).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 15:10:24 +01:00