Files
Andreas eedb049bab 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>
2026-04-02 14:20:51 +02:00

208 lines
3.0 KiB
Markdown

# API Documentation
## Base URL
```
http://localhost:3000/api
```
## Endpoints
### List Leads
```
GET /api/leads?page=1&limit=10
```
**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| page | number | 1 | Page number (min: 1) |
| limit | number | 10 | Items per page (min: 1, max: 100) |
**Response (200):**
```json
{
"data": [
{
"id": "uuid",
"first_name": "Max",
"email": "max@beispiel.de",
"phone": "+49 123 456789",
"fitness_goal": "abnehmen",
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-01T00:00:00Z",
"deleted_at": null
}
],
"meta": {
"current_page": 1,
"per_page": 10,
"total": 15,
"total_pages": 2,
"has_more": true
}
}
```
---
### Create Lead
```
POST /api/leads
Content-Type: application/json
```
**Request Body:**
```json
{
"first_name": "Max",
"email": "max@beispiel.de",
"phone": "+49 123 456789",
"fitness_goal": "abnehmen"
}
```
| Field | Type | Required | Validation |
|-------|------|----------|------------|
| first_name | string | yes | 2-100 chars, trimmed |
| email | string | yes | Valid email, max 255, lowercased |
| phone | string | no | Max 20 chars, digits/spaces/+/- |
| fitness_goal | enum | yes | abnehmen, muskelaufbau, ausdauer, flexibilitaet |
**Response (201):**
```json
{
"data": { ... }
}
```
**Error (422) - Validation:**
```json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validierungsfehler",
"details": {
"email": ["Bitte eine gueltige E-Mail-Adresse eingeben"]
}
}
}
```
**Error (409) - Duplicate email:**
```json
{
"error": {
"code": "CONFLICT",
"message": "Ein Lead mit dieser E-Mail-Adresse existiert bereits"
}
}
```
---
### Get Lead
```
GET /api/leads/:id
```
**Response (200):**
```json
{
"data": { ... }
}
```
**Error (404):**
```json
{
"error": {
"code": "NOT_FOUND",
"message": "Lead nicht gefunden"
}
}
```
---
### Update Lead
```
PUT /api/leads/:id
Content-Type: application/json
```
**Request Body (partial update):**
```json
{
"first_name": "Maximilian",
"fitness_goal": "muskelaufbau"
}
```
All fields are optional but at least one must be provided.
**Response (200):**
```json
{
"data": { ... }
}
```
---
### Delete Lead (Soft Delete)
```
DELETE /api/leads/:id
```
Sets `deleted_at` timestamp instead of removing the record.
**Response (200):**
```json
{
"data": {
"message": "Lead erfolgreich geloescht"
}
}
```
---
## Error Response Format
All errors follow this structure:
```json
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable message",
"details": {}
}
}
```
| HTTP Status | Code | Description |
|------------|------|-------------|
| 400 | INVALID_ID / INVALID_JSON | Bad request |
| 404 | NOT_FOUND | Resource not found |
| 409 | CONFLICT | Duplicate entry |
| 422 | VALIDATION_ERROR | Input validation failed |
| 500 | DATABASE_ERROR / INTERNAL_ERROR | Server error |