Full app rebuild: FastAPI backend + React Native mobile with auth, championships, admin
Backend (FastAPI + SQLAlchemy + SQLite): - JWT auth with access/refresh tokens, bcrypt password hashing - User model with member/organizer/admin roles, auto-approve members - Championship, Registration, ParticipantList, Notification models - Alembic async migrations, seed data with test users - Registration endpoint returns tokens for members, pending for organizers - /registrations/my returns championship title/date/location via eager loading - Admin endpoints: list users, approve/reject organizers Mobile (React Native + Expo + TypeScript): - Zustand auth store, Axios client with token refresh interceptor - Role-based registration (Member vs Organizer) with contextual form labels - Tab navigation with Ionicons, safe area headers, admin tab for admin role - Championships list with status badges, detail screen with registration progress - My Registrations with championship title, progress bar, and tap-to-navigate - Admin panel with pending/all filter, approve/reject with confirmation - Profile screen with role badge, Ionicons info rows, sign out - Password visibility toggle (Ionicons), keyboard flow hints (returnKeyType) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
258
dancechamp-claude-code/docs/DESIGN-SYSTEM.md
Normal file
258
dancechamp-claude-code/docs/DESIGN-SYSTEM.md
Normal file
@@ -0,0 +1,258 @@
|
||||
# DanceChamp — Design System
|
||||
|
||||
## Theme: Dark Luxury
|
||||
|
||||
The app has a premium dark aesthetic. Think high-end dance competition branding — elegant, minimal, confident.
|
||||
|
||||
---
|
||||
|
||||
## Colors
|
||||
|
||||
### Core Palette
|
||||
```
|
||||
Background: #08070D (near-black with slight purple)
|
||||
Card: #12111A (elevated surface)
|
||||
Card Hover: #1A1926 (pressed/active state)
|
||||
Border: #1F1E2E (subtle separator)
|
||||
Text Primary: #F2F0FA (off-white)
|
||||
Text Dim: #5E5C72 (labels, placeholders)
|
||||
Text Mid: #8F8DA6 (secondary info)
|
||||
```
|
||||
|
||||
### Accent Colors
|
||||
```
|
||||
Pink (Primary): #D4145A ← Member app + Org app default
|
||||
Purple: #7C3AED ← Secondary accent (styles, alt champ branding)
|
||||
Indigo: #6366F1 ← Admin panel accent
|
||||
```
|
||||
|
||||
### Semantic Colors
|
||||
```
|
||||
Green: #10B981 (success, passed, active, confirmed)
|
||||
Yellow: #F59E0B (warning, pending, draft)
|
||||
Red: #EF4444 (error, failed, blocked, danger)
|
||||
Blue: #60A5FA (info, links, video)
|
||||
Orange: #F97316 (warned status, awaiting review)
|
||||
```
|
||||
|
||||
### Transparent Variants
|
||||
Each semantic color has a 10% opacity background:
|
||||
```
|
||||
Green Soft: rgba(16,185,129,0.10)
|
||||
Yellow Soft: rgba(245,158,11,0.10)
|
||||
Red Soft: rgba(239,68,68,0.10)
|
||||
Blue Soft: rgba(96,165,250,0.10)
|
||||
Purple Soft: rgba(139,92,246,0.10)
|
||||
```
|
||||
|
||||
For accent overlays use 15% opacity: `${color}15`
|
||||
For accent borders use 30% opacity: `${color}30`
|
||||
|
||||
### Per-Championship Branding
|
||||
Each championship can have its own accent color:
|
||||
- Zero Gravity: `#D4145A` (pink)
|
||||
- Pole Star: `#7C3AED` (purple)
|
||||
|
||||
This color is used for the championship's tab highlights, buttons, and member tags.
|
||||
|
||||
---
|
||||
|
||||
## Typography
|
||||
|
||||
### Font Stack
|
||||
```
|
||||
Display: 'Playfair Display', Georgia, serif ← Headings, numbers, titles
|
||||
Body: 'DM Sans', 'Segoe UI', sans-serif ← Body text, labels, buttons
|
||||
Mono: 'JetBrains Mono', monospace ← Badges, timestamps, codes, small labels
|
||||
```
|
||||
|
||||
### Sizes & Usage
|
||||
```
|
||||
Screen title: Playfair Display, 20px, 700 weight
|
||||
Section title: Playfair Display, 14px, 700 weight, Text Mid color
|
||||
Card title: DM Sans, 14-16px, 600 weight
|
||||
Body text: DM Sans, 12-13px, 400 weight
|
||||
Small label: JetBrains Mono, 9-10px, 500 weight, uppercase, letter-spacing 0.3-0.5
|
||||
Badge: JetBrains Mono, 8px, 700 weight, uppercase, letter-spacing 0.8
|
||||
Stat number: Playfair Display, 16-20px, 700 weight
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Components
|
||||
|
||||
### Card
|
||||
```
|
||||
Background: #12111A
|
||||
Border: 1px solid #1F1E2E
|
||||
Border Radius: 14px
|
||||
Padding: 16px
|
||||
```
|
||||
|
||||
### Status Badge
|
||||
Small pill with semantic color + soft background.
|
||||
```
|
||||
Font: JetBrains Mono, 8px, 700 weight, uppercase
|
||||
Padding: 3px 8px
|
||||
Border Radius: 4px
|
||||
```
|
||||
|
||||
Status mappings:
|
||||
| Status | Label | Color | Background |
|
||||
|---|---|---|---|
|
||||
| active / live | ACTIVE / LIVE | Green | Green Soft |
|
||||
| pending | PENDING | Yellow | Yellow Soft |
|
||||
| pending_approval | AWAITING REVIEW | Orange | Orange Soft |
|
||||
| draft | DRAFT | Dim | Dim 15% |
|
||||
| blocked | BLOCKED | Red | Red Soft |
|
||||
| warned | WARNED | Orange | Orange Soft |
|
||||
| passed | PASSED | Green | Green Soft |
|
||||
| failed | FAILED | Red | Red Soft |
|
||||
|
||||
### Tab Bar (in-screen tabs, not bottom nav)
|
||||
```
|
||||
Container: horizontal scroll, no scrollbar, gap 3px
|
||||
Tab: JetBrains Mono, 9px, 600 weight
|
||||
Active: accent color text, accent 15% bg, accent 30% border
|
||||
Inactive: Dim color text, transparent bg
|
||||
Border Radius: 16px (pill shape)
|
||||
Padding: 5px 10px
|
||||
```
|
||||
|
||||
Configurable tabs have a status dot (6px circle):
|
||||
- Green dot = section configured ✓
|
||||
- Yellow dot = section pending
|
||||
|
||||
### Input Field
|
||||
```
|
||||
Background: #08070D (same as page bg)
|
||||
Border: 1px solid #1F1E2E
|
||||
Border Radius: 10px
|
||||
Padding: 10px 12px
|
||||
Font: DM Sans, 13px
|
||||
Label: JetBrains Mono, 9px, uppercase, Dim color, 6px margin bottom
|
||||
```
|
||||
|
||||
### Action Button
|
||||
Two variants:
|
||||
- **Filled**: solid background, white text (for primary actions)
|
||||
- **Outline**: transparent bg, colored border 30%, colored text (for secondary/danger)
|
||||
|
||||
```
|
||||
Padding: 8px 14px
|
||||
Border Radius: 8px
|
||||
Font: DM Sans, 11px, 700 weight
|
||||
```
|
||||
|
||||
### Tag Editor
|
||||
For lists of editable items (rules, levels, styles):
|
||||
```
|
||||
Tag: DM Sans 11px, colored bg 10%, colored border 25%, 4px 10px padding, 16px radius
|
||||
Remove (×): 10px, Dim color
|
||||
Add input: same as Input Field but smaller (8px 12px, 12px font)
|
||||
Add button: colored bg, white "+" text, 8px 14px
|
||||
```
|
||||
|
||||
### Header
|
||||
```
|
||||
Padding: 14px 20px 6px
|
||||
Title: Playfair Display, 20px, 700
|
||||
Subtitle: DM Sans, 11px, Dim color
|
||||
Back button: 32×32px, Card bg, Border, 8px radius, "←" centered
|
||||
```
|
||||
|
||||
### Bottom Navigation
|
||||
```
|
||||
Border top: 1px solid #1F1E2E
|
||||
Padding: 10px 0 8px
|
||||
Items: flex, space-around
|
||||
Icon: 18px emoji
|
||||
Label: JetBrains Mono, 8px, letter-spacing 0.3
|
||||
Active: opacity 1
|
||||
Inactive: opacity 0.35
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Patterns
|
||||
|
||||
### Progress/Setup Checklist
|
||||
For configurable tabs on org side:
|
||||
```
|
||||
Each row:
|
||||
[Checkbox 22×22] [Label capitalize] [Configure › or ✓]
|
||||
|
||||
Checkbox: 6px radius, 2px border
|
||||
Done: Green border, Green Soft bg, "✓" inside
|
||||
Pending: Yellow border, transparent bg
|
||||
|
||||
Label done: Dim color, line-through
|
||||
Label pending: Text Primary, clickable → navigates to tab
|
||||
```
|
||||
|
||||
### Readiness Bar (dashboard cards)
|
||||
```
|
||||
Track: 4px height, Border color bg, 2px radius
|
||||
Fill: accent color, width = (done/total * 100)%
|
||||
Below: list of section names with ✓ (green) or ○ (yellow)
|
||||
```
|
||||
|
||||
### Member Card
|
||||
```
|
||||
Container: Card style, 12px padding
|
||||
Name: DM Sans 13px, 600 weight
|
||||
Instagram: JetBrains Mono 10px, accent color
|
||||
Tags: DM Sans 9px, Mid color, Mid 10% bg, 2px 7px padding, 10px radius
|
||||
Status badge: top-right corner
|
||||
```
|
||||
|
||||
### Stat Box
|
||||
```
|
||||
Container: Card style, 10px 6px padding, centered
|
||||
Number: Playfair Display, 16-20px, 700 weight, semantic color
|
||||
Label: JetBrains Mono, 7px, uppercase, Dim color
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phone Frame (for prototypes)
|
||||
|
||||
```
|
||||
Width: 375px
|
||||
Height: 740px
|
||||
Border Radius: 36px
|
||||
Border: 1.5px solid #1F1E2E
|
||||
Shadow: 0 0 80px rgba(accent, 0.06), 0 20px 40px rgba(0,0,0,0.5)
|
||||
|
||||
Status bar: 8px 24px padding
|
||||
Time: JetBrains Mono 11px, Dim
|
||||
Notch: 100×28px black, 14px radius
|
||||
Indicators: "●●●" JetBrains Mono 11px, Dim
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## React Native Adaptation
|
||||
|
||||
The prototypes use inline styles. For React Native:
|
||||
|
||||
| Prototype | React Native |
|
||||
|---|---|
|
||||
| `div` | `View` |
|
||||
| `span`, `p`, `h1` | `Text` |
|
||||
| `input` | `TextInput` |
|
||||
| `onClick` | `onPress` (via `Pressable` or `TouchableOpacity`) |
|
||||
| `overflow: auto` | `ScrollView` or `FlatList` |
|
||||
| `cursor: pointer` | Not needed |
|
||||
| `border: 1px solid` | `borderWidth: 1, borderColor:` |
|
||||
| `fontFamily: 'DM Sans'` | Loaded via `expo-font` |
|
||||
| `gap` | Use `marginBottom` on children (gap not fully supported) |
|
||||
| `overflowX: auto` with scrollbar hidden | `ScrollView horizontal showsHorizontalScrollIndicator={false}` |
|
||||
|
||||
### Fonts Loading (Expo)
|
||||
```typescript
|
||||
import { useFonts } from 'expo-font';
|
||||
import { PlayfairDisplay_700Bold } from '@expo-google-fonts/playfair-display';
|
||||
import { DMSans_400Regular, DMSans_500Medium, DMSans_600SemiBold } from '@expo-google-fonts/dm-sans';
|
||||
import { JetBrainsMono_400Regular, JetBrainsMono_500Medium, JetBrainsMono_700Bold } from '@expo-google-fonts/jetbrains-mono';
|
||||
```
|
||||
Reference in New Issue
Block a user