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:
@@ -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();
|
||||
@@ -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');
|
||||
Reference in New Issue
Block a user