Commit graph

345 commits

Author SHA1 Message Date
c2cabc01d3 feat(g1-g4): design system, memories pipeline, medical tracking, AI brain
G1 — Design System: 14 UI primitives (Button, Card, Modal, Sheet, Input,
Textarea, Select, EmptyState, LoadingShimmer, ConfirmDialog, WashiTape,
Badge, Avatar, Tabs), PageTransition with Framer Motion, sun/moon CSS vars,
Caveat font, /dev/components visual showcase.

G2 — Memories Pipeline: R2 presigned uploads, Sharp thumbnail generation,
LiteLLM vision captions + pgvector embeddings, CSS masonry gallery with
infinite scroll, private toggle, semantic search fallback to ILIKE.

G3 — Medical: dose log + correction audit trail, IAP vaccine bulk import,
emergency escalation page, pediatrician phone in settings.

G4 — AI Brain: keyword guardrail → LLM classifier → structured DB tool-use
(7 tools) → memory search → general parenting handler; ai_usage table;
22-case medical bypass safety test suite.

DB migrations: 0011_memories, 0012_medical_doses, 0013_ai_usage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 17:48:34 +05:30
c787caa821 fix: add Resend for password reset emails + install F1-F2 deps
- Wire Resend to /api/auth/reset-request with fallback for dev
- Install: sharp, recharts, next-pwa, resend, @react-pdf/renderer, @types/sharp

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 16:42:45 +05:30
c459b4411a fix: secure /api/ai endpoint and remove debug routes
- Add auth to /api/ai via requireFamily middleware
- Remove /api/ai and /api/auth/debug from public routes
- Delete debug/test routes that expose internal state

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 16:41:47 +05:30
797c970d81 Fix Quick Log save and diaper icon
- Fix handleSubmit to properly wait for API response before closing
- Change diaper icon from 🧷 to 👶
- Update activity scroller diaper icon

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 16:23:11 +05:30
9e258d74b4 Add activity scroller to home page
- Add time-based activity scroller showing lastFeed, lastSleep, lastDiaper times
- Scrolling marquee animation below vaccine reminders
- Fix diaper icon to 🧷
- Link baby profile card to growth page
- Add loading state for recent logs

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 16:15:20 +05:30
b10bfb0e2f docs: add growth page features to CLAUDE.md
Document the growth page components, state management, color codes, and layout order.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 15:47:52 +05:30
7fc33a791c fix(growth): add form conditional on latest like goals
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 15:29:13 +05:30
52a46de86b fix(growth): move add form below latest, reorder layout
- Add form now appears between Latest Reading and WHO card
- Remove duplicate form below WHO card
- Similar pattern to Goals card

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 15:21:29 +05:30
f82fca224d style(growth): collapsible WHO+Chart, collapsed view with icons, collapsible history
- WHO card shows icons + values when collapsed (⚖️ 📏 )
- Chart is collapsible inside expanded WHO view
- History is collapsible with scroll for many records
- Add formatAge to history items

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 15:05:01 +05:30
a3d0b06501 fix(growth): show age in years+months format
- Show age as "1y 4mo" instead of just months
- Add formatAge helper function
- Apply to Latest Reading and WHO card

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 14:57:51 +05:30
38e18c12f3 style(growth): collapsible WHO+Chart card, form after latest
- Merge WHO Standards and Chart into single collapsible card
- Add +Add button shows form below Latest Reading
- Collapsible sections with expand/collapse toggle

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 14:54:00 +05:30
a76738689b style(growth): card-style layouts with hover effects
- Latest Reading card with gradient and card-style metrics
- WHO Standards card with cards and hover shadows
- History cards with badges and hover effects
- Color-coded zones legend simplified

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 14:49:40 +05:30
0ea81b329a fix(growth): move latest card to top, remove duplicate
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 14:46:11 +05:30
dcb510964e fix(growth): add Cancel button to add form
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 14:41:01 +05:30
796b6d8004 fix(growth): disable RLS on growth table
Growth table had RLS blocking writes. API has requireOwnership checks,
so disabling RLS is secure. Changed table owner to tia_app.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 14:36:15 +05:30
855541f4e2 fix(growth): convert dates to strings before SQL query
Postgres driver expects strings, not Date objects

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 14:00:42 +05:30
abbaaf8874 fix(growth): fix add button and form submission
- Fix + Add button to properly open form (was closing immediately)
- Add error handling and saving state to form
- Add visual feedback (Saving... text, error messages)
- Clear form state properly when opening

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 13:58:04 +05:30
318b277e44 feat(growth): add edit/delete, goals, CSV export, and WHO percentile enhancements
- Add PUT and DELETE endpoints for growth records
- Add CSV export for pediatrician visits
- Add goal tracking with localStorage persistence
- Color-coded percentiles (green/yellow/red zones)
- Show WHO percentile lines (15th, 50th, 85th) on chart
- Growth velocity indicator (kg/month between readings)
- Enhanced WHO standards card with actual vs target + goal progress
- Better empty state with encouraging prompt
- Fix UUID type for growth record IDs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 13:52:02 +05:30
1628588d5a fix(ai): correct env var names and fresh session per home modal open
AI route was reading LITELLM_URL/LITELLM_KEY but env vars are named
LITELLM_BASE_URL/LITELLM_API_KEY — causing 503 on every request.

Home page chat now creates a fresh session each time the modal opens
and resets homeSessionId on close, so conversations don't pile into
the same old session.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 13:31:30 +05:30
299e878e38 fix(ai): proper chat layout, mobile sidebar, empty states, loading dots
- h-screen with overflow-hidden so messages scroll within viewport
- Sidebar is slide-over on mobile (fixed + overlay) with translate animation
- Sidebar defaults closed; auto-selects first session on load
- Empty state when no session selected with "New Chat" CTA
- Typing indicator with animated bouncing dots
- Chat bubbles properly aligned (user right, AI left) with rounded corners
- Delete confirm moved to its own modal (not nested in session list item)
- Removed stale debug console.log
- Dark mode fixes: border, hover states, disabled button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 13:24:33 +05:30
70aa35384b fix(medical): dark mode support and tab wrapping fix
Added dark: variants to all cards, inputs, selects, text, and buttons
throughout the medical page. Added whitespace-nowrap + flex-shrink-0 to
all tab buttons to prevent labels like "Doctor Visit" from wrapping.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 13:22:14 +05:30
bc2eb9a50f feat(home): full age breakdown and dark mode fixes
Age now shows years, months and days (e.g. "1 year, 3 months, 5 days").
Added dark: variants to all white cards, inputs, selects, and text on the
home page so dark mode no longer shows white boxes on a dark background.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 13:11:03 +05:30
75afc177ce fix(home): move useEffect hooks above early returns to fix Rules of Hooks violation
All three useEffect calls were placed after an early return when childId was
null, causing React error #310 on the home page. Moved them above the
conditional returns and guarded each body with if (!childId) return.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 13:01:26 +05:30
50a6827bfd fix(admin): use bcrypt in admin password set to match signin verification
Simple hash_ format stored by admin PATCH was incompatible with bcrypt
verification in /api/auth/signin, causing "Invalid password" on login.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 12:57:33 +05:30
6ce459e4f6 fix(admin): restore stats API from debug stub
Route was returning { test: "ok", count: N } instead of the expected
overview/conversions/growth/childrenByAge structure, crashing the dashboard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 12:27:36 +05:30
85d313bc86 fix(admin): use correct column name 'expires' in admin_sessions queries
verifyAdminSession() and requireAdmin() both used expires_at but the
admin_sessions table column is named expires — causing every session
check to silently fail and always redirect to /admin-login.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 12:22:17 +05:30
fc0e75b5ad fix(admin): scope FamilyProvider out of admin routes, ensure cookies on admin fetches
Root causes:
- tia_admin_session is httpOnly so document.cookie could never read it → all
  client-side cookie checks always failed and redirected before any data fetched
- Sub-pages used localStorage.getItem("admin_token") which was never stored,
  and passed Authorization: Bearer null headers the server ignores

Fixes:
- FamilyProvider: use usePathname() hook instead of window.location.pathname
- admin/layout.tsx: rewrite as server component using verifyAdminSession()
  (new lib/admin-auth.ts helper that uses next/headers cookies()) → server-side
  redirect to /admin-login if session invalid; extract sidebar to AdminSidebar.tsx
- admin/page.tsx: remove broken document.cookie guard (layout handles auth now)
- admin-login/page.tsx: replace document.cookie check with GET /api/admin/auth call
- All 7 admin sub-pages: remove localStorage guard, remove Authorization: Bearer
  headers, add credentials: include to every fetch call

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 12:16:10 +05:30
5e36c8a848 remove: /api/setup route — bootstrap should be done via psql, not HTTP
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 11:58:01 +05:30
07bb149dd8 fix: notifications IDOR — verify child belongs to caller's family
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 11:57:57 +05:30
389f66955c fix: stop leaking password reset tokens in response
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 11:57:54 +05:30
8e7a3fbe35 Clean up debug logs 2026-05-17 11:26:01 +05:30
480de976ef Verify session server-side before redirect 2026-05-17 11:24:46 +05:30
6247bb42bc Fix hydration - check typeof window 2026-05-17 11:22:43 +05:30
4212c1f632 Debug login flow 2026-05-17 11:20:53 +05:30
754a602e48 Add debug logging to FamilyProvider
Move admin check to top-level useEffect before any async calls.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 11:13:01 +05:30
e7539468c1 Fix FamilyProvider admin check - move inside useEffect
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 11:03:54 +05:30
70376d2e96 Fix FamilyProvider redirect for admin pages
Skip family check when pathname starts with /admin
to prevent redirect to onboarding

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 11:01:37 +05:30
d94a15e38e Fix admin login: redirect path, add logout, remove unused code
- Fix redirect from /admin/login to /admin-login
- Add DELETE endpoint for logout
- Connect logout button to API
- Remove unused admin state/localStorage

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 10:54:15 +05:30
ffaa92cd13 Revert: Remove token from response (HttpOnly cookie is sufficient)
Login page checks cookie on load via useEffect, no need for
localStorage token. More secure this way.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 10:52:08 +05:30
73cfd2a761 Fix admin login response missing token
The API was setting the session token as a cookie but not
returning it in the JSON response. Login page expects token
in the response to store in localStorage.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 10:50:35 +05:30
d18213fc7d Test route 2026-05-17 10:47:35 +05:30
dc54fd31c6 Debug route 2026-05-17 10:45:11 +05:30
724a914fa7 Add debug 2026-05-17 10:43:32 +05:30
a2bc6b6857 Simplify admin stats 2026-05-17 09:47:36 +05:30
5f80ec4570 Fix admin pages to use cookie auth 2026-05-17 01:20:26 +05:30
c11484b910 Fix rate limit variable scope 2026-05-17 01:14:32 +05:30
e47001365e Rate limit controlled via RATE_LIMIT_ENABLED env 2026-05-17 01:12:15 +05:30
f84ee96e2b Enhanced debug 2026-05-17 00:52:39 +05:30
082c2bcdd8 Add debug endpoint 2026-05-17 00:46:12 +05:30
cb7d9411ff Fix JOIN - sessions directly to family_members 2026-05-17 00:38:15 +05:30