Add supplements, kettlebell, calendar, push notifications, and PWA support

- Supplement tracking: CRUD endpoints, /today, /logs, Supplements page
- Kettlebell workouts: session tracking, analytics endpoint, ActiveSession page
- Calendar module: events CRUD, calendar components
- Push notifications: VAPID keys, PushSubscription model, APScheduler reminders,
  service worker with push/notificationclick handlers, Profile notifications UI
- PWA: vite-plugin-pwa, manifest, icons, service worker generation
- Frontend: TypeScript types, API modules, ConfirmModal, toast notifications
- Auth fixes: password hashing, nutrition endpoint auth
- CLAUDE.md: project documentation and development guide

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Carlos Escalante
2026-03-20 18:57:03 -06:00
parent bd91eb4171
commit f279907ae3
61 changed files with 9256 additions and 85 deletions

View File

@@ -0,0 +1,51 @@
import client from './client';
import type { KettlebellSession, KettlebellSetLog } from '../types/kettlebell';
export interface GenerateSessionRequest {
focus: string;
duration_minutes: number;
available_weights: number[];
}
export interface LogSetRequest {
exercise_order: number;
set_number: number;
actual_reps: number;
actual_weight_kg: number;
actual_duration_seconds: number;
perceived_effort: number;
}
export interface CompleteSessionRequest {
notes?: string;
}
export const generateSession = (data: GenerateSessionRequest) =>
client.post<KettlebellSession>('/kettlebell/generate', data).then(r => r.data);
export const getSessions = () =>
client.get<KettlebellSession[]>('/kettlebell/').then(r => r.data);
export const getSession = (id: number) =>
client.get<KettlebellSession>(`/kettlebell/${id}`).then(r => r.data);
export const startSession = (id: number) =>
client.patch<KettlebellSession>(`/kettlebell/${id}/start`).then(r => r.data);
export const logSet = (id: number, data: LogSetRequest) =>
client.post<KettlebellSetLog>(`/kettlebell/${id}/sets`, data).then(r => r.data);
export const getSets = (id: number) =>
client.get<KettlebellSetLog[]>(`/kettlebell/${id}/sets`).then(r => r.data);
export const completeSession = (id: number, data: CompleteSessionRequest = {}) =>
client.patch<KettlebellSession>(`/kettlebell/${id}/complete`, data).then(r => r.data);
export const retrySession = (id: number) =>
client.post<KettlebellSession>(`/kettlebell/${id}/retry`).then(r => r.data);
export const abandonSession = (id: number) =>
client.patch<KettlebellSession>(`/kettlebell/${id}/abandon`).then(r => r.data);
export const deleteSession = (id: number) =>
client.delete(`/kettlebell/${id}`);