- Remove 📥 export button from growth page header (less clutter)
- Add "Export Growth Data" row in settings with child name and CSV download
- Fetches growth records on demand, shows loading state while exporting
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Measurement form now appears directly below the header (not buried
after WHO card) so it's immediately visible when + Add is tapped
- Removed `&& latest` guard — form now works even with zero records
- Goals and Add are mutually exclusive: opening one closes the other
- 3-column grid for measurement inputs (weight / height / head on one row)
- Sticky header with backdrop-blur, smaller title (text-sm), icon-style
export and goals buttons
- All cards use rounded-2xl + shadow-sm for consistent look
- "Add First Measurement" in empty state scrolls to top and opens the form
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- grid-cols-4 (~40% smaller than 3-col) with gap-1 and rounded-xl corners
- Hover: scale-110 image + dark overlay + expand icon (⤢)
- Subtle shadow + ring border on each tile
- Folder emoji + name shown below each tile (when assigned)
- Filter out tiles with no URL and remove tiles that fail to load (onError → null)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Header title reduced to text-xs (~50% smaller)
- Tap image in viewer to zoom 2x; tap again to zoom out
- Tap outside image area to toggle UI chrome (top bar / captions)
- "New folder" pill at end of folder row and in upload picker
- Custom folders saved to localStorage (tia_custom_folders)
- Custom folders appear in folder pills, upload picker, and move-to-folder sheet
- Emoji picker (15 options) + name input for new folders
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Direct PUT to R2 presigned URL is cross-origin, causing "Failed to fetch"
in browsers without R2 CORS configured. Use the existing PUT /api/upload
proxy handler instead — file goes client → Next.js → R2 server-side.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Extract offline queue to src/lib/offline-queue.ts
- Extract shared LogModal with time presets (Just now/5/15/30min/Custom)
and smart default pre-fill from last log of same type
- Replace ActivityScroller with TodaySummary (today's counts + last time)
- Fix activity page: GET /api/logs without type param now returns all logs merged
- Fix field naming: log.loggedAt / log.amount (camelCase throughout)
- Add FAB to activity page for zero-navigation quick logging
- Recent Activity shows 5 most recent entries with correct field names
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Swap 👶 → 🚼 (baby-changing symbol) in all four diaper-specific spots:
activity page getIcon(), homepage ActivityScroller, quick log button,
and recent activity list. Other 👶 usages (child profiles, onboarding,
admin children nav) are left unchanged as they represent babies, not diapers.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Month grid with Su–Sa columns, colored activity dots per day (rose=feed,
blue=sleep, amber=diaper). Tapping a day opens a detail panel below the
grid with the full log list for that day. Month navigation with prev/next
arrows; future months are disabled. Filter pills apply to both views.
Limit raised to 200 entries so calendar data spans multiple months.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three bugs fixed:
1. GET /api/logs required a `type` param; activity page calls without one,
always receiving {error} → empty list. Fixed: when type is omitted,
merge feeds + diapers_logs + sleeps, sort by time, return camelCase
fields (loggedAt, subType, amount) matching the activity page interface.
2. Type-specific queries (used by homepage) still return raw snake_case
rows unchanged so the homepage "Recent Activity" section is unaffected.
3. LogModal initialised subType as "breast_milk" regardless of log type.
Adding a useEffect to reset it (breast_milk / wet / nap) when type
changes prevents bad enum values from being sent for diaper/sleep logs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rose gradient background instead of flat gray
- Header with ← back link and child name subtitle
- Active filter/category pills use bg-rose-400 instead of purple
- Progress bar gradient updated to rose-to-pink
- Full-width px-4 layout (removed max-w-2xl wrapper)
- Date picker uses design system Input + Button components
- Empty state with icon, consistent with other pages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace raw <input>/<button>/<select> elements with Button, Card, Input,
Select, Modal, Badge, and ConfirmDialog from @/components/ui in all
non-admin and admin pages. Removes ~550 lines of inline Tailwind utility
classes from form elements while keeping all business logic intact.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- 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>
- 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>
- 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>
- 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>
- 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>
- 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>
- 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>
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>
- 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>
- 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>
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>
- 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>
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>
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>
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>
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>
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>
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>
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>