feat: initial FitCoach Pro lead management app

Next.js 16 app with full CRUD lead management:
- REST API (/api/leads) with GET (pagination), POST, PUT, DELETE (soft delete)
- Zod validation (server + client), Supabase (PostgreSQL)
- Responsive UI: leads table (desktop) + cards (mobile), modal form, toast notifications
- 43 tests (Vitest + React Testing Library): validation, components, pagination
- Docker setup (multi-stage build, health check)
- Supabase migration + 15 seed leads
- Documentation (CLAUDE.md, README, API docs)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-02 14:20:51 +02:00
commit eedb049bab
39 changed files with 7997 additions and 0 deletions
@@ -0,0 +1,32 @@
-- Create leads table for FitCoach Pro lead management
CREATE TABLE IF NOT EXISTS leads (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
first_name VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL,
phone VARCHAR(20),
fitness_goal VARCHAR(20) NOT NULL CHECK (
fitness_goal IN ('abnehmen', 'muskelaufbau', 'ausdauer', 'flexibilitaet')
),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
deleted_at TIMESTAMPTZ
);
-- Indexes
CREATE UNIQUE INDEX idx_leads_email_active ON leads (email) WHERE deleted_at IS NULL;
CREATE INDEX idx_leads_fitness_goal ON leads (fitness_goal) WHERE deleted_at IS NULL;
CREATE INDEX idx_leads_created_at ON leads (created_at DESC) WHERE deleted_at IS NULL;
-- Auto-update updated_at trigger
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE TRIGGER update_leads_updated_at
BEFORE UPDATE ON leads
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
+17
View File
@@ -0,0 +1,17 @@
-- Seed data: realistic test leads for FitCoach Pro
INSERT INTO leads (first_name, email, phone, fitness_goal) VALUES
('Max', 'max.mueller@beispiel.de', '+49 151 12345678', 'abnehmen'),
('Anna', 'anna.schmidt@beispiel.de', '+49 170 98765432', 'muskelaufbau'),
('Lukas', 'lukas.fischer@beispiel.de', '+49 162 55544433', 'ausdauer'),
('Sophie', 'sophie.weber@beispiel.de', NULL, 'flexibilitaet'),
('Leon', 'leon.wagner@beispiel.de', '+49 157 11122233', 'abnehmen'),
('Emma', 'emma.becker@beispiel.de', '+49 176 44455566', 'muskelaufbau'),
('Jonas', 'jonas.hoffmann@beispiel.de', '+49 155 77788899', 'ausdauer'),
('Mia', 'mia.schaefer@beispiel.de', '+49 163 22233344', 'abnehmen'),
('Felix', 'felix.koch@beispiel.de', NULL, 'muskelaufbau'),
('Lina', 'lina.richter@beispiel.de', '+49 172 66677788', 'flexibilitaet'),
('Paul', 'paul.klein@beispiel.de', '+49 152 33344455', 'abnehmen'),
('Hannah', 'hannah.wolf@beispiel.de', '+49 178 99900011', 'ausdauer'),
('Tim', 'tim.schroeder@beispiel.de', NULL, 'muskelaufbau'),
('Laura', 'laura.neumann@beispiel.de', '+49 160 55566677', 'flexibilitaet'),
('Niklas', 'niklas.braun@beispiel.de', '+49 171 88899900', 'abnehmen');