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:
Dianaka123
2026-02-25 22:46:50 +03:00
parent 9eb68695e9
commit 789d2bf0a6
81 changed files with 16283 additions and 310 deletions

View File

@@ -0,0 +1,357 @@
# DanceChamp — Database Schema
## Overview
Backend: **Supabase** (PostgreSQL + Auth + Storage + Realtime)
All tables use `uuid` primary keys generated by `gen_random_uuid()`.
All tables have `created_at` and `updated_at` timestamps.
---
## Tables
### users
Extended from Supabase Auth. This is a `public.users` table that mirrors `auth.users` via trigger.
```sql
create table public.users (
id uuid primary key references auth.users(id) on delete cascade,
email text not null,
name text not null,
role text not null check (role in ('admin', 'organization', 'member')),
city text,
instagram_handle text,
experience_years integer,
disciplines text[] default '{}', -- ['Pole Exotic', 'Pole Art']
auth_provider text default 'email', -- 'email' | 'google' | 'instagram'
avatar_url text,
status text not null default 'active' check (status in ('active', 'warned', 'blocked')),
warn_reason text,
block_reason text,
created_at timestamptz default now(),
updated_at timestamptz default now()
);
```
### organizations
One-to-one with a user (role = 'organization').
```sql
create table public.organizations (
id uuid primary key default gen_random_uuid(),
user_id uuid not null references public.users(id) on delete cascade,
name text not null,
instagram_handle text,
email text,
city text,
logo_url text,
verified boolean not null default false,
status text not null default 'pending' check (status in ('active', 'pending', 'blocked')),
block_reason text,
created_at timestamptz default now(),
updated_at timestamptz default now()
);
```
### championships
Belongs to an organization. Core entity.
```sql
create table public.championships (
id uuid primary key default gen_random_uuid(),
org_id uuid not null references public.organizations(id) on delete cascade,
name text not null,
subtitle text,
event_date text, -- "May 30, 2026" or ISO date
reg_start text, -- registration opens
reg_end text, -- registration closes (must be before event_date)
location text, -- "Minsk, Belarus"
venue text, -- "Prime Hall"
accent_color text default '#D4145A',
image_emoji text default '💃',
status text not null default 'draft' check (status in ('draft', 'pending_approval', 'live', 'completed', 'blocked')),
-- configurable sections progress
config_info boolean not null default false,
config_categories boolean not null default false,
config_fees boolean not null default false,
config_rules boolean not null default false,
config_judges boolean not null default false,
-- links
form_url text, -- Google Forms URL
rules_doc_url text, -- Rules document URL
created_at timestamptz default now(),
updated_at timestamptz default now()
);
```
### disciplines
Championship has many disciplines. Each discipline has levels.
```sql
create table public.disciplines (
id uuid primary key default gen_random_uuid(),
championship_id uuid not null references public.championships(id) on delete cascade,
name text not null, -- "Exotic Pole Dance"
levels text[] default '{}', -- ['Beginners', 'Amateur', 'Semi-Pro', 'Profi', 'Elite']
sort_order integer default 0,
created_at timestamptz default now()
);
```
### styles
Championship-level styles (not per-discipline).
```sql
create table public.styles (
id uuid primary key default gen_random_uuid(),
championship_id uuid not null references public.championships(id) on delete cascade,
name text not null, -- "Classic", "Flow", "Theater"
sort_order integer default 0,
created_at timestamptz default now()
);
```
### fees
One-to-one with championship.
```sql
create table public.fees (
id uuid primary key default gen_random_uuid(),
championship_id uuid not null unique references public.championships(id) on delete cascade,
video_selection text, -- "50 BYN / 1,500 RUB"
solo text, -- "280 BYN / 7,500 RUB"
duet text, -- "210 BYN / 5,800 RUB pp"
"group" text, -- "190 BYN / 4,500 RUB pp"
refund_note text,
created_at timestamptz default now(),
updated_at timestamptz default now()
);
```
### rules
Championship has many rules across sections.
```sql
create table public.rules (
id uuid primary key default gen_random_uuid(),
championship_id uuid not null references public.championships(id) on delete cascade,
section text not null check (section in ('general', 'costume', 'scoring', 'penalty')),
name text not null, -- rule text or criterion name
value text, -- for scoring: "10" (max), for penalty: "-2" or "DQ"
sort_order integer default 0,
created_at timestamptz default now()
);
```
### judges
Championship has many judges.
```sql
create table public.judges (
id uuid primary key default gen_random_uuid(),
championship_id uuid not null references public.championships(id) on delete cascade,
name text not null,
instagram text,
bio text,
photo_url text,
sort_order integer default 0,
created_at timestamptz default now()
);
```
### registrations
Links a member to a championship. Tracks the 10-step progress.
```sql
create table public.registrations (
id uuid primary key default gen_random_uuid(),
user_id uuid not null references public.users(id) on delete cascade,
championship_id uuid not null references public.championships(id) on delete cascade,
discipline_id uuid references public.disciplines(id),
level text, -- "Semi-Pro"
style text, -- "Classic"
participation_type text default 'solo' check (participation_type in ('solo', 'duet', 'group')),
-- Progress steps (step 110)
step_rules_reviewed boolean default false,
step_category_selected boolean default false,
step_video_recorded boolean default false,
step_form_submitted boolean default false,
step_video_fee_paid boolean default false, -- confirmed by org
step_video_fee_receipt_url text, -- uploaded receipt
step_results text check (step_results in ('pending', 'passed', 'failed')),
step_champ_fee_paid boolean default false,
step_champ_fee_receipt_url text,
step_about_me_submitted boolean default false,
step_insurance_confirmed boolean default false,
step_insurance_doc_url text,
-- Video
video_url text,
-- Meta
current_step integer default 1,
created_at timestamptz default now(),
updated_at timestamptz default now(),
unique(user_id, championship_id)
);
```
### notifications
Push to member's in-app feed.
```sql
create table public.notifications (
id uuid primary key default gen_random_uuid(),
user_id uuid not null references public.users(id) on delete cascade,
championship_id uuid references public.championships(id) on delete set null,
type text not null check (type in (
'category_changed', 'payment_confirmed', 'results',
'deadline_reminder', 'registration_confirmed', 'announcement',
'champ_approved', 'champ_rejected', 'org_approved', 'org_rejected'
)),
title text not null,
message text not null,
read boolean not null default false,
created_at timestamptz default now()
);
```
### activity_logs
Admin audit trail.
```sql
create table public.activity_logs (
id uuid primary key default gen_random_uuid(),
actor_id uuid references public.users(id) on delete set null,
action text not null, -- "org_approved", "user_blocked", "champ_auto_approved"
target_type text not null, -- "organization", "championship", "user"
target_id uuid,
target_name text, -- denormalized for display
details jsonb, -- extra context
created_at timestamptz default now()
);
```
---
## Relationships Diagram
```
users (1) ──── (1) organizations
│ has many
championships
┌────┼────┬────┬────┐
│ │ │ │ │
disciplines styles fees rules judges
registrations ─┘
(user + championship)
notifications
```
---
## Row Level Security (RLS)
Enable RLS on all tables.
### users
```sql
-- Members can read/update their own row
create policy "Users can read own" on users for select using (auth.uid() = id);
create policy "Users can update own" on users for update using (auth.uid() = id);
-- Org admins can read members registered to their championships
create policy "Orgs can read their members" on users for select using (
id in (
select r.user_id from registrations r
join championships c on r.championship_id = c.id
join organizations o on c.org_id = o.id
where o.user_id = auth.uid()
)
);
-- Admin can read/update all
create policy "Admin full access" on users for all using (
exists (select 1 from users where id = auth.uid() and role = 'admin')
);
```
### championships
```sql
-- Anyone can read live championships
create policy "Public read live" on championships for select using (status = 'live');
-- Org can CRUD their own
create policy "Org manages own" on championships for all using (
org_id in (select id from organizations where user_id = auth.uid())
);
-- Admin full access
create policy "Admin full access" on championships for all using (
exists (select 1 from users where id = auth.uid() and role = 'admin')
);
```
### registrations
```sql
-- Members can read/create their own
create policy "Member own registrations" on registrations for select using (user_id = auth.uid());
create policy "Member can register" on registrations for insert with check (user_id = auth.uid());
-- Org can read/update registrations for their championships
create policy "Org manages registrations" on registrations for all using (
championship_id in (
select c.id from championships c
join organizations o on c.org_id = o.id
where o.user_id = auth.uid()
)
);
-- Admin full access
create policy "Admin full access" on registrations for all using (
exists (select 1 from users where id = auth.uid() and role = 'admin')
);
```
### notifications
```sql
-- Users can read their own notifications
create policy "Read own" on notifications for select using (user_id = auth.uid());
-- Users can mark their own as read
create policy "Update own" on notifications for update using (user_id = auth.uid());
```
---
## Storage Buckets
```
receipts/ -- Payment receipt screenshots
{user_id}/{registration_id}/receipt.jpg
insurance/ -- Insurance documents
{user_id}/{registration_id}/insurance.pdf
judge-photos/ -- Judge profile photos
{championship_id}/{judge_id}.jpg
org-logos/ -- Organization logos
{org_id}/logo.jpg
```
---
## Seed Data
For development, seed with:
- 1 admin user
- 2 organizations (1 verified, 1 unverified/pending)
- 2 championships for verified org (1 live, 1 draft)
- 1 championship for unverified org (pending_approval)
- 7 member users with registrations at various progress stages
- Sample notifications, activity logs
This matches the prototype demo data.

View 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';
```

View File

@@ -0,0 +1,316 @@
# DanceChamp — Vibe Coding Plan
## How to use this plan
- Work phase by phase, top to bottom
- Check off tasks as you go: `[ ]``[x]`
- Each phase has a **"Done when"** — don't move on until it's met
- 🔴 = blocker (must do), 🟡 = important, 🟢 = nice to have for MVP
- Estimated time is for vibe coding with AI (Claude Code / Cursor)
---
## Phase 0: Project Setup
**Time: ~1 hour**
- [ ] 🔴 Init Expo project (React Native): `npx create-expo-app DanceChamp --template blank-typescript`
- [ ] 🔴 Init Web admin panel: `npm create vite@latest admin-panel -- --template react-ts`
- [ ] 🔴 Setup Supabase project (or Firebase): create account, new project
- [ ] 🔴 Setup database tables (see Phase 1)
- [ ] 🔴 Install core deps: `react-navigation`, `zustand`, `supabase-js`
- [ ] 🟡 Setup Git repo + `.gitignore`
- [ ] 🟡 Create `/apps/mobile`, `/apps/admin`, `/packages/shared` monorepo structure
- [ ] 🟢 Add ESLint + Prettier
**Done when:** Both apps run locally, Supabase dashboard is accessible
---
## Phase 1: Database & Auth
**Time: ~2-3 hours**
### 1.1 Database Tables
- [ ] 🔴 `users` — id, email, name, role (admin | organization | member), city, instagram_handle, experience_years, disciplines[], auth_provider, status, created_at
- [ ] 🔴 `organizations` — id, user_id (FK), name, instagram_handle, email, city, logo_url, verified (bool), status (active | pending | blocked), block_reason, created_at
- [ ] 🔴 `championships` — id, org_id (FK), name, subtitle, event_date, reg_start, reg_end, location, venue, status (draft | pending_approval | live | completed | blocked), accent_color, created_at
- [ ] 🔴 `disciplines` — id, championship_id (FK), name, levels[], styles[]
- [ ] 🔴 `fees` — id, championship_id (FK), video_selection, solo, duet, group, refund_note
- [ ] 🔴 `rules` — id, championship_id (FK), section (general | costume | scoring | penalty), text, value (for penalties)
- [ ] 🔴 `judges` — id, championship_id (FK), name, instagram, bio, photo_url
- [ ] 🔴 `registrations` — id, user_id (FK), championship_id (FK), discipline_id, level, style, type (solo | duet | group), current_step, video_url, fee_paid, receipt_uploaded, insurance_uploaded, passed (null | true | false), created_at
- [ ] 🔴 `notifications` — id, user_id (FK), championship_id, type, title, message, read (bool), created_at
- [ ] 🟡 `activity_logs` — id, actor_id, action, target_type, target_id, details, created_at
### 1.2 Auth
- [ ] 🔴 Supabase Auth: enable Email + Google OAuth
- [ ] 🔴 Role-based access: Row Level Security (RLS) policies
- Members see only their own registrations
- Orgs see only their own championships & members
- Admin sees everything
- [ ] 🔴 Sign up / Sign in screens (mobile)
- [ ] 🔴 Admin login (web panel)
- [ ] 🟡 Instagram OAuth (for member profiles)
- [ ] 🟡 Onboarding flow: name → city → discipline → experience → done
**Done when:** Can sign up as member, org, and admin. RLS blocks cross-access.
---
## Phase 2: Member App — Core Screens
**Time: ~4-5 hours**
### 2.1 Navigation
- [ ] 🔴 Bottom tab nav: Home, My Champs, Search, Profile
- [ ] 🔴 Stack navigation: screens → detail → sub-screens
### 2.2 Home Screen
- [ ] 🔴 "Upcoming championships" feed — cards with name, date, location, status badge
- [ ] 🔴 "My active registrations" section with progress bars
- [ ] 🟡 Bell icon → notifications feed
- [ ] 🟡 Deadline urgency banners ("Registration closes in 3 days!")
### 2.3 Championship Detail
- [ ] 🔴 Header: name, dates, location, venue, registration period
- [ ] 🔴 Tab: Overview (info + registration funnel)
- [ ] 🔴 Tab: Categories (disciplines, levels, styles + eligibility)
- [ ] 🔴 Tab: Rules (general, costume, scoring criteria, penalties)
- [ ] 🔴 Tab: Fees (video selection + championship fees)
- [ ] 🔴 Tab: Judges (judge profiles with photo, instagram, bio)
- [ ] 🔴 "Register" button → starts onboarding
### 2.4 Search & Discover
- [ ] 🔴 Search by championship name
- [ ] 🔴 Filter by: discipline, location, status (open/upcoming/past)
- [ ] 🟡 Sort by: date, popularity
### 2.5 Profile
- [ ] 🔴 View/edit: name, city, instagram, disciplines, experience
- [ ] 🔴 "My Championships" list (past + active)
- [ ] 🟢 Competition history
**Done when:** Can browse championships, view full details across all tabs, search/filter, see profile.
---
## Phase 3: Member App — Registration & Progress Tracker
**Time: ~4-5 hours**
### 3.1 Registration Flow
- [ ] 🔴 Choose discipline → level → style → solo/duet/group
- [ ] 🔴 Create `registration` record in DB
- [ ] 🔴 Show 10-step progress checklist
### 3.2 Progress Steps (per championship)
- [ ] 🔴 Step 1: Review rules — mark done when user opens Rules tab
- [ ] 🔴 Step 2: Select category — saved from registration
- [ ] 🔴 Step 3: Record video — manual toggle ("I've recorded my video")
- [ ] 🔴 Step 4: Submit video form — manual toggle or link to Google Form
- [ ] 🔴 Step 5: Pay video fee — upload receipt screenshot
- [ ] 🔴 Step 6: Wait for results — shows "pending" until org decides
- [ ] 🔴 Step 7: Results — auto-updates when org passes/fails
- [ ] 🔴 Step 8: Pay championship fee — upload receipt (only if passed)
- [ ] 🔴 Step 9: Submit "About Me" — manual toggle or link
- [ ] 🔴 Step 10: Confirm insurance — upload document
### 3.3 Receipt & Document Upload
- [ ] 🔴 Camera / gallery picker for receipt photos
- [ ] 🔴 Upload to Supabase Storage
- [ ] 🔴 Show upload status (pending org confirmation)
### 3.4 Notifications
- [ ] 🔴 In-app notification feed (bell icon + unread count)
- [ ] 🔴 Notification types: category changed, payment confirmed, results, deadline reminder, announcement
- [ ] 🟡 Push notifications via Expo Notifications
- [ ] 🟢 Notification preferences (toggle on/off)
**Done when:** Can register for a championship, track all 10 steps, upload receipts, receive notifications.
---
## Phase 4: Org App — Dashboard & Championship Management
**Time: ~5-6 hours**
### 4.1 Org Dashboard
- [ ] 🔴 Championship cards: name, dates, status badge, member count, progress bar (if draft)
- [ ] 🔴 "+" button → Quick Create (name, date, location → creates draft)
- [ ] 🔴 Tap card → championship detail
### 4.2 Championship Detail (tabbed, configurable)
- [ ] 🔴 Overview tab: setup progress checklist, event info (editable), stats (if live)
- [ ] 🔴 Categories tab: add/remove levels, add/remove styles → "Mark as Done"
- [ ] 🔴 Fees tab: video selection + solo/duet/group fees → "Mark as Done"
- [ ] 🔴 Rules tab: general rules + costume rules + scoring criteria + penalties → "Mark as Done"
- [ ] 🔴 Judges tab: add judge profiles (name, instagram, bio) → "Mark as Done"
- [ ] 🔴 "Go Live" button — appears when all sections are done
- [ ] 🔴 If org is verified → status = `live` (auto-approved)
- [ ] 🔴 If org is unverified → status = `pending_approval` (needs admin)
### 4.3 Members Tab (only for live championships)
- [ ] 🔴 Member list with search + filters (All, Receipts, Videos, Passed)
- [ ] 🔴 Member card: name, instagram, level, style, status badge, progress
- [ ] 🔴 Tap member → member detail
### 4.4 Member Detail
- [ ] 🔴 Profile info, registration details
- [ ] 🔴 Edit level (picker + "member will be notified" warning)
- [ ] 🔴 Edit style (picker + notification)
- [ ] 🔴 Video section: view link + Pass/Fail buttons
- [ ] 🔴 Payment section: view receipt + Confirm button
- [ ] 🔴 "Send Notification" button
### 4.5 Results Tab
- [ ] 🔴 Pending review list with Pass/Fail buttons per member
- [ ] 🔴 Decided list (passed/failed)
- [ ] 🔴 "Publish Results" button → notifies all members
### 4.6 Org Settings
- [ ] 🔴 Edit org profile (name, instagram)
- [ ] 🔴 Notification preferences (toggles)
- [ ] 🟡 Connected accounts (Instagram, Gmail, Telegram)
**Done when:** Org can create championship, configure all tabs, go live, manage members, pass/fail videos, publish results.
---
## Phase 5: Admin Panel (Web)
**Time: ~3-4 hours**
### 5.1 Dashboard
- [ ] 🔴 Platform stats: orgs count, live champs, total users
- [ ] 🔴 "Needs Attention" section: pending orgs, pending champs (from unverified orgs)
- [ ] 🔴 Platform health: revenue, blocked users
- [ ] 🔴 Recent activity log
### 5.2 Organizations Management
- [ ] 🔴 List with search + filters (Active, Pending, Blocked)
- [ ] 🔴 Org detail: profile, championships list, approval policy
- [ ] 🔴 Actions: Approve / Reject, Block / Unblock, Verify, Delete
### 5.3 Championships Management
- [ ] 🔴 List with search + filters (Live, Awaiting Review, Draft, Blocked)
- [ ] 🔴 Champ detail: stats, approval policy indicator
- [ ] 🔴 Actions: Approve / Reject (for unverified orgs), Suspend, Reinstate, Delete
### 5.4 Users Management
- [ ] 🔴 List with search + filters (Active, Warned, Blocked, Org Admins)
- [ ] 🔴 User detail: profile, role, championships joined
- [ ] 🔴 Actions: Warn, Block / Unblock, Delete
**Done when:** Admin can approve/reject orgs, review championships from unverified orgs, manage users.
---
## Phase 6: Connecting It All
**Time: ~3-4 hours**
### 6.1 Real-Time Sync
- [ ] 🔴 Supabase Realtime: members see status updates instantly (pass/fail, payment confirmed)
- [ ] 🔴 Org dashboard updates when new member registers
- [ ] 🟡 Admin panel live counters
### 6.2 Notification Triggers
- [ ] 🔴 Org passes/fails video → member gets notification
- [ ] 🔴 Org confirms receipt → member gets notification
- [ ] 🔴 Org changes member's level/style → member gets notification
- [ ] 🔴 Org publishes results → all members get notification
- [ ] 🟡 Auto deadline reminders (cron job: 7 days, 3 days, 1 day before)
### 6.3 Approval Flow
- [ ] 🔴 Unverified org clicks "Go Live" → status = pending_approval
- [ ] 🔴 Admin sees it in "Needs Attention"
- [ ] 🔴 Admin approves → status = live, org gets notification
- [ ] 🔴 Admin rejects → status = blocked, org gets notification with reason
### 6.4 File Uploads
- [ ] 🔴 Receipt photo upload → Supabase Storage → org sees thumbnail in member detail
- [ ] 🔴 Insurance doc upload → same flow
- [ ] 🟢 Judge profile photos
**Done when:** All three apps talk to the same DB. Actions in one app reflect in others in real time.
---
## Phase 7: Polish & UX
**Time: ~2-3 hours**
- [ ] 🟡 Loading states (skeletons, spinners)
- [ ] 🟡 Empty states ("No championships yet", "No members match")
- [ ] 🟡 Error handling (network errors, failed uploads, toast messages)
- [ ] 🟡 Pull-to-refresh on lists
- [ ] 🟡 Haptic feedback on key actions (pass/fail, payment confirm)
- [ ] 🟡 Dark theme consistency across all screens
- [ ] 🟡 Animations: tab transitions, card press, progress bar fill
- [ ] 🟢 Onboarding walkthrough (first-time user tips)
- [ ] 🟢 Swipe gestures on member cards (swipe right = pass, left = fail)
**Done when:** App feels smooth and professional. No raw errors shown to users.
---
## Phase 8: Integrations (Post-MVP)
**Time: varies**
### 8.1 Instagram Parsing
- [ ] 🟢 Apify Instagram scraper setup
- [ ] 🟢 Claude API: extract structured data from post captions
- [ ] 🟢 OCR (Google Vision): parse results from photo posts
- [ ] 🟢 "Import from Instagram" button in org's championship creation
### 8.2 Gmail Integration
- [ ] 🟢 Google OAuth for members
- [ ] 🟢 Detect Google Forms confirmation emails → auto-mark steps
### 8.3 Payments
- [ ] 🟢 In-app payment tracking
- [ ] 🟢 Replace receipt uploads with direct payment
### 8.4 Multi-Language
- [ ] 🟢 i18n setup (Russian + English)
---
## Phase 9: Testing & Launch
**Time: ~2-3 hours**
- [ ] 🔴 Test full flow: member registers → org reviews → admin monitors
- [ ] 🔴 Test approval flow: unverified org → pending → admin approves → live
- [ ] 🔴 Test notifications: level change, payment confirm, results
- [ ] 🔴 Test on real device (iOS + Android via Expo Go)
- [ ] 🟡 Test edge cases: empty championships, blocked orgs, duplicate registrations
- [ ] 🟡 Performance check: list with 50+ members, 10+ championships
- [ ] 🟡 Expo build: `eas build` for iOS/Android
- [ ] 🟢 TestFlight / Google Play internal testing
- [ ] 🟢 Admin panel deploy (Vercel / Netlify)
**Done when:** All three roles can complete their full flow without bugs.
---
## Quick Reference: What Goes Where
| Feature | Member App | Org App | Admin Panel |
|---|:---:|:---:|:---:|
| Browse championships | ✅ | — | ✅ (view all) |
| Register for championship | ✅ | — | — |
| Progress tracker | ✅ | — | — |
| Create/edit championship | — | ✅ | ✅ (edit/delete) |
| Review members | — | ✅ | ✅ (view) |
| Pass/Fail videos | — | ✅ | — |
| Confirm payments | — | ✅ | — |
| Approve orgs & champs | — | — | ✅ |
| Block/warn users | — | — | ✅ |
| Notifications | ✅ (receive) | ✅ (send) | — |
---
## Priority Order (if short on time)
If you need to ship fast, do these phases in order and stop when you have enough:
1. **Phase 0 + 1** — Foundation (can't skip)
2. **Phase 2** — Member app core (users need to see something)
3. **Phase 4** — Org app (orgs need to create championships)
4. **Phase 3** — Registration flow (connects member ↔ org)
5. **Phase 6** — Wire it together
6. **Phase 5** — Admin panel (can manage via Supabase dashboard temporarily)
7. **Phase 7** — Polish
8. **Phase 8** — Integrations (post-launch)

View File

@@ -0,0 +1,371 @@
# DanceChamp — Screen Reference
## Member App Screens
### Navigation: Bottom Tabs
`Home` | `My Champs` | `Search` | `Profile`
---
### M1: Home
**Purpose:** Dashboard for the dancer
**Elements:**
- Header: "DanceChamp" title + bell icon (🔔) with unread count badge
- "Your Active" section: cards for championships they're registered in, showing progress bar (e.g. "Step 5/10")
- "Upcoming Championships" section: browseable cards for live championships
- Each card: championship name, org name, dates, location, status badge, accent color bar
**Data:** `championships` (status = 'live') + `registrations` (for current user)
**Navigation:**
- Tap card → M5 (Championship Detail)
- Tap bell → M7 (Notifications)
---
### M2: My Champs
**Purpose:** All championships user is registered for
**Elements:**
- Tabs: Active | Past
- Championship cards with progress indicator
- Status per card: "Step 3/10 — Pay video fee" or "✅ Registered" or "❌ Failed"
**Data:** `registrations` joined with `championships`
**Navigation:**
- Tap card → M6 (Progress Tracker)
---
### M3: Search
**Purpose:** Discover championships
**Elements:**
- Search bar (text input)
- Filter chips: All, Pole Exotic, Pole Art, Registration Open, Upcoming
- Championship result cards
**Data:** `championships` + `organizations` (for org name)
**Navigation:**
- Tap card → M5 (Championship Detail)
---
### M4: Profile
**Purpose:** User profile and settings
**Elements:**
- Avatar, name, instagram handle, city
- Dance profile: disciplines, experience years
- "My Championships" summary (X active, Y completed)
- Settings list: Edit Profile, Notification Preferences, Connected Accounts, Help, Log Out
**Data:** `users` (current user)
---
### M5: Championship Detail
**Purpose:** Full championship info — 5 tabs
**Header:** Championship name, org name, back button
**Tabs:** Overview | Categories | Rules | Fees | Judges
#### Tab: Overview
- Event info: date, location, venue, registration period (start → end)
- Stats: members registered, spots left (if limited)
- "Register" button (if registration open and user not registered)
- If already registered: shows current progress step
#### Tab: Categories
- Disciplines list, each with levels
- Styles list
- If registered: user's selected level/style highlighted
#### Tab: Rules
- General rules (expandable list)
- Costume rules
- Scoring criteria: name + max score (010)
- Penalties: name + deduction / DQ
#### Tab: Fees
- Video selection fee
- Championship fees: solo, duet, group
- Refund note
#### Tab: Judges
- Judge profile cards: photo/emoji, name, instagram link, bio
**Data:** Full championship with all related tables
**Navigation:**
- "Register" → M6 (starts registration flow, then shows Progress Tracker)
---
### M6: Progress Tracker
**Purpose:** 10-step registration checklist for a specific championship
**Header:** Championship name, back button
**Elements:**
- Vertical step list (110)
- Each step: number, icon, title, status (locked/available/done/failed)
- Current step expanded with action area:
- Step 3 "Record Video": toggle "I've recorded my video"
- Step 5 "Pay Video Fee": upload receipt button, status after upload
- Step 7 "Results": shows PASS ✅ / FAIL ❌ / ⏳ Pending
- Step 10 "Insurance": upload document button
- Progress bar at top: X/10 completed
**Data:** `registrations` (single record for this user + championship)
**Actions:** Update step fields in `registrations` table
---
### M7: Notifications
**Purpose:** In-app notification feed
**Header:** "Notifications" + "Read all" button
**Elements:**
- Notification cards: icon, type badge, championship name, message, time ago
- Unread: colored left border + accent background tint + dot indicator
- Tap: marks as read
**Types:** 🔄 Category Changed, ✅ Payment Confirmed, 🏆 Results, ⏰ Deadline, 📋 Registered, 📢 Announcement
**Data:** `notifications` (for current user, ordered by created_at desc)
---
## Org App Screens
### Navigation: Bottom Tabs
`Dashboard` | `Settings`
---
### O1: Dashboard
**Purpose:** Overview of all org's championships
**Elements:**
- Header: "Dashboard" + org name + org logo
- "New Championship" card (accent gradient, "+" icon)
- Championship cards: name, dates, location, status badge (LIVE / SETUP 3/5 / AWAITING REVIEW)
- For drafts: readiness bar + section checklist (info ✓, categories ○, fees ○, etc.)
- For live: mini stats (Members, Passed, Pending)
**Data:** `championships` (where org_id = current org) + `registrations` (counts)
**Navigation:**
- Tap "New Championship" → O2 (Quick Create)
- Tap championship card → O3 (Championship Detail)
---
### O2: Quick Create
**Purpose:** Minimal form to create a draft championship
**Elements:**
- Header: "New Championship" + back button
- 3 inputs: Championship Name, Event Date, Location
- Info card: "Your championship will be created as a draft. Configure details later."
- "✨ Create Draft" button (disabled until name filled)
**Action:** Creates championship with status = 'draft', navigates to O3
---
### O3: Championship Detail (Tabbed)
**Purpose:** Configure and manage a championship
**Header:** Championship name, subtitle, back button, "🚀 Go Live" (if all config done)
**Tabs (with config status dots):**
`Overview` | `Categories` (🟢/🟡) | `Fees` (🟢/🟡) | `Rules` (🟢/🟡) | `Judges` (🟢/🟡)
For live championships, add: | `Members (N)` | `Results`
#### Tab: Overview
- **If draft:** Setup Progress checklist (5 items with checkmarks, tap incomplete → jumps to tab)
- **If all done:** "🚀 Open Registration" button (or "Go Live")
- Event Info card: inline edit (✎ Edit / ✕ Close toggle)
- Editable fields: name, subtitle, event date, location, venue
- Registration period: Opens (date) + Closes (date), side by side
- Warning: "⚠️ Registration close date must be before event date"
- **If live:** Stats boxes (Members, Passed, Failed, Pending) + "⚡ Needs Action" (receipts to review, videos to review)
#### Tab: Categories
- Levels: tag editor (add/remove levels)
- Styles: tag editor (add/remove styles)
- "✓ Mark Categories as Done" button (shown when at least 1 level + 1 style)
#### Tab: Fees
- Video Selection Fee input
- Championship Fees: Solo, Duet (pp), Group (pp) inputs
- "✓ Mark Fees as Done" button (shown when video fee filled)
#### Tab: Rules
- General Rules: tag editor
- Costume Rules: tag editor
- Scoring Criteria (010): list + tag editor to add new
- Penalties: list with colored values (-2 yellow, DQ red) + tag editor
- "✓ Mark Rules as Done" button (shown when at least 1 rule)
#### Tab: Judges
- Judge profile cards: emoji avatar, name, instagram, bio, × to remove
- "Add Judge" form: name, instagram, bio inputs + "+ Add Judge" button
- "✓ Mark Judges as Done" button (shown when at least 1 judge)
#### Tab: Members (live only)
- Search bar
- Filter chips: All (N), 📸 Receipts (N), 🎬 Videos (N), ✅ Passed (N)
- Member cards: name, instagram, level, style, city tags, status badge
- Tap member → O4 (Member Detail)
#### Tab: Results (live only)
- Stat boxes: Pending, Passed, Failed
- Pending review cards: member name/level + "🎥 View" + Pass/Fail buttons
- Decided list: member name + badge
- "📢 Publish Results" button
---
### O4: Member Detail
**Purpose:** View/edit a single member's registration
**Header:** Member name, championship + instagram, back button
**Elements:**
- Profile card: avatar, name, instagram, city, status badge
- Registration section:
- Discipline (read-only)
- Type: solo/duet/group (read-only)
- **Level:** value + "✎ Edit" button → expands picker with ⚠️ "Member will be notified"
- **Style:** value + "✎ Edit" button → expands picker with ⚠️ warning
- Video section: link display + Pass/Fail buttons (if pending) or status badge
- Payment section: fee amount, receipt status, "📸 Confirm" button (if receipt uploaded)
- "🔔 Send Notification" button
**Actions:** Update `registrations` fields + create `notifications` record
---
### O5: Org Settings
**Purpose:** Organization profile and preferences
**Elements:**
- Org profile: logo, name, instagram (editable inline when "Edit Organization Profile" tapped)
- Menu items:
- ✎ Edit Organization Profile → inline form (name + instagram) replaces menu
- 🔔 Notification Preferences → sub-screen with toggle switches
- 🔗 Connected Accounts → sub-screen (Instagram ✅, Gmail ✅, Telegram ❌)
- ❓ Help & Support
- 🚪 Log Out (red text)
---
## Admin Panel Screens (Web)
### Navigation: Bottom Tabs (mobile-style for prototype, sidebar for production)
`Overview` | `Orgs` | `Champs` | `Users`
---
### A1: Overview (Dashboard)
**Purpose:** Platform health at a glance
**Elements:**
- Header: "Admin Panel" + platform name + version
- Stat boxes: Active Orgs, Live Champs, Total Users
- "⚡ Needs Attention" card (yellow tint):
- 🏢 Organizations awaiting approval (count) → tap goes to A2
- 🏆 Champs awaiting approval from unverified orgs (count) → tap goes to A4
- Platform Health table: total revenue, active/total orgs, blocked users, avg members/champ
- Recent Activity log: action + target (colored by type) + date + actor
---
### A2: Organizations List
**Purpose:** All organizations on the platform
**Elements:**
- Search bar
- Filter chips: All (N), ✅ Active (N), ⏳ Pending (N), 🚫 Blocked (N)
- Org cards: logo, name, instagram, status badge, city, champs count, members count
- Tap → A3 (Org Detail)
---
### A3: Organization Detail
**Purpose:** Review and manage a single org
**Elements:**
- Profile card: logo, name, instagram, email, city, status badge
- Details table: Joined, Championships, Total members, Verified (✅/❌)
- Approval Policy card:
- Verified: "🛡️ Verified — Auto-approve events" (green tint)
- Unverified: "⏳ Unverified — Events need manual approval" (yellow tint)
- Championships list (belonging to this org)
- Block reason card (if blocked, red tint)
- Actions:
- Pending: [Approve ✅] [Reject ❌]
- Active: [Block 🚫] + [Verify 🛡️] (if not verified)
- Blocked: [Unblock ✅]
- Always: [Delete 🗑️]
---
### A4: Championships List
**Purpose:** All championships across all orgs
**Elements:**
- Search bar
- Filter chips: All (N), 🟢 Live (N), ⏳ Awaiting (N), 📝 Draft (N), 🚫 Blocked (N)
- Champ cards: name, "by Org Name 🛡️" (shield if verified), status badge, dates, location, members count
- Tap → A5 (Champ Detail)
---
### A5: Championship Detail
**Purpose:** Review and manage a single championship
**Elements:**
- Profile card: trophy emoji, name, org name, dates, location, status badge
- Stats table: Members, Passed, Pending, Revenue
- Approval Policy card: explains why auto-approved or needs review
- Actions:
- Pending approval: [Approve ✅] [Reject ❌]
- Live: [Suspend ⏸️]
- Blocked: [Reinstate ✅]
- Always: [Delete 🗑️]
---
### A6: Users List
**Purpose:** All platform users
**Elements:**
- Search bar (name, @handle, email)
- Filter chips: All (N), ✅ Active (N), ⚠️ Warned (N), 🚫 Blocked (N), 🏢 Org Admins (N)
- User cards: avatar (👤 or 🏢 for org admins), name, instagram, city, status badge
- Tap → A7 (User Detail)
---
### A7: User Detail
**Purpose:** Review and manage a single user
**Elements:**
- Profile card: avatar, name, instagram, email, status badge
- Info table: City, Joined, Championships joined, Role (Member or Org Admin + org name)
- Warning/Block reason card (if applicable, orange or red tint)
- Actions:
- Active: [Warn ⚠️] [Block 🚫]
- Warned: [Remove Warning ✅] [Block 🚫]
- Blocked: [Unblock ✅]
- Always: [Delete 🗑️]

View File

@@ -0,0 +1,267 @@
# DanceChamp — Technical Specification
## 1. Overview
A mobile platform for pole dance championships. Dancers discover events and track registration. Organizers create and manage championships. Platform admin oversees everything.
### The Problem
Championship info is scattered across Instagram posts, Telegram chats, and Google Docs. Dancers miss deadlines, lose track of multi-step registration, and can't verify submissions went through. Organizers manually manage everything via spreadsheets and DMs.
### The Solution
One app with three roles:
- **Members** browse championships, register, track 10-step progress
- **Organizations** create championships, configure rules/fees/categories, review videos, confirm payments
- **Admin** approves organizations, reviews championships from unverified orgs, manages users
### Real-World Reference: "Zero Gravity"
International Pole Exotic Championship, Minsk, Belarus. Two disciplines (Exotic Pole Dance + Pole Art), 6+ levels per discipline, two-stage payment (video selection fee + championship fee), video selection with pass/fail, detailed judging criteria (6 categories, 010), strict costume/equipment rules, insurance required.
---
## 2. Roles & Permissions
### Member (Dancer)
**Access:** Mobile app (member view)
- Browse & search championships
- View full details (rules, fees, categories, judges)
- Register for championships
- Track 10-step progress per championship
- Upload receipts & documents
- Receive notifications (results, deadline reminders, announcements)
- View past participation history
**Cannot:** Create/edit championships, see other members' data, access org/admin features
### Organization
**Access:** Mobile app (org view)
- Create championships (quick create → configure tabs)
- Manage disciplines, levels, styles, fees, rules, scoring, judges
- View & manage registered members per championship
- Review videos (pass/fail)
- Confirm receipt payments
- Edit member's level/style (triggers notification)
- Publish results
- Send announcements
**Cannot:** See other orgs' data, access admin features
### Admin
**Access:** Web admin panel
- View all orgs, championships, users
- Approve/reject pending organizations
- Approve/reject championships from unverified orgs
- Block/unblock orgs and users
- Warn users
- Verify organizations (changes approval policy)
- Delete any entity
- View platform stats and activity logs
---
## 3. Championship Lifecycle
```
[Org: Quick Create]
name + date + location → status: DRAFT
[Org: Configure Tabs]
Categories ✓ → Fees ✓ → Rules ✓ → Judges ✓
(any order, mark each as done)
[Org: "Go Live"]
├── Org is VERIFIED (🛡️)
│ → status: LIVE (auto-approved)
│ → visible to members immediately
└── Org is UNVERIFIED
→ status: PENDING_APPROVAL
→ admin sees in "Needs Attention"
→ admin approves → LIVE
→ admin rejects → BLOCKED
[LIVE — Registration Open]
reg_start ≤ today ≤ reg_end
Members can register
[Registration Closed]
today > reg_end
No new registrations
[Event Day]
event_date
[COMPLETED]
```
---
## 4. Championship Data Structure
Each championship contains:
### Event Info
- Name, subtitle
- Event date (when it happens)
- Registration period: start date → end date (must be before event date)
- Location (city, country)
- Venue name
- Accent color (for branding)
### Categories (configurable tab)
- Disciplines: e.g. "Exotic Pole Dance", "Pole Art"
- Levels per discipline: e.g. "Beginners", "Amateur", "Semi-Pro", "Profi", "Elite", "Duets & Groups"
- Styles: e.g. "Classic", "Flow", "Theater"
### Fees (configurable tab)
- Video selection fee (e.g. "50 BYN / 1,500 RUB")
- Championship fees by type:
- Solo (e.g. "280 BYN / 7,500 RUB")
- Duet per person (e.g. "210 BYN / 5,800 RUB pp")
- Group per person (e.g. "190 BYN / 4,500 RUB pp")
- Refund note (typically non-refundable)
### Rules (configurable tab)
- General rules (list of text items)
- Costume rules (list of text items)
- Scoring criteria: name + max score (e.g. "Artistry: 010", "Technique: 010")
- Penalties: name + value (e.g. "Fall: -2", "Exposure: DQ")
### Judges (configurable tab)
- Judge profiles: name, Instagram handle, bio/description
- These are people, not scoring criteria
### Members (only when LIVE)
- Registered members scoped to this championship
- Each with: discipline, level, style, type (solo/duet/group), progress steps, video URL, payment status, pass/fail result
---
## 5. Member Registration Flow (10 Steps)
```
Step 1: 📋 Review Rules → Auto (tracked when user opens Rules tab)
Step 2: 🎯 Select Category → Auto (saved from registration picker)
Step 3: 🎬 Record Video → Manual toggle ("I've recorded my video")
Step 4: 📝 Submit Video Form → Manual / link to Google Form
Step 5: 💳 Pay Video Fee → Upload receipt screenshot → Org confirms
Step 6: ⏳ Wait for Results → Pending until org decides
Step 7: 🏆 Results → Auto-updates on pass/fail
├── FAIL → Flow ends
└── PASS → Continue ▼
Step 8: 💰 Pay Championship Fee → Upload receipt → Org confirms
Step 9: 📄 Submit "About Me" → Manual / link to form
Step 10: 🛡️ Confirm Insurance → Upload document → Org confirms
└── ✅ REGISTERED!
```
### Detection Methods
| Step | Method |
|---|---|
| Review rules | Auto — tracked on tab open |
| Select category | Auto — saved from picker |
| Record video | Manual toggle |
| Submit video form | Manual or Gmail auto-detect (future) |
| Pay video fee | Receipt upload → org confirms |
| Results | Auto — org pass/fail updates member |
| Pay championship fee | Receipt upload → org confirms |
| About Me form | Manual or Gmail auto-detect (future) |
| Insurance | Document upload → org confirms |
---
## 6. Notifications
### Types
| Type | Trigger | Direction |
|---|---|---|
| 🔄 Category Changed | Org changes member's level/style | Org → Member |
| ✅ Payment Confirmed | Org confirms uploaded receipt | Org → Member |
| 🏆 Results | Org passes/fails video selection | Org → Member |
| ⏰ Deadline Reminder | Auto (7d, 3d, 1d before reg_end) | System → Member |
| 📋 Registration Confirmed | All 10 steps complete | System → Member |
| 📢 Announcement | Org sends broadcast | Org → All Members |
### Delivery
- In-app: Bell icon with unread count, notification feed
- Push: Expo Notifications for critical updates
- Email: Future enhancement
---
## 7. Org App — Configurable Tabs
When org creates a championship, it starts as DRAFT with 5 configurable sections:
| Section | Tab | What to configure | Mark as Done when |
|---|---|---|---|
| Info | Overview | Name, dates, location, venue, reg period | Has date + location |
| Categories | Categories | Levels + styles | At least 1 level + 1 style |
| Fees | Fees | Video fee + championship fees | Video fee filled |
| Rules | Rules | General rules, costume rules, scoring criteria, penalties | At least 1 rule |
| Judges | Judges | Judge profiles (name, instagram, bio) | At least 1 judge |
Setup progress shown on Overview tab as checklist. Each section shows green dot (done) or yellow dot (pending) in tab bar. "Go Live" button appears when all 5 sections are ✓.
---
## 8. Admin — Approval Flow
### Organization Approval
- New org registers → status: `pending`
- Admin reviews → Approve (status: `active`) or Reject (status: `blocked`)
- Admin can also **verify** an active org (🛡️ badge)
### Championship Approval
- Depends on org's verification status:
- **Verified org** → Go Live = instant `live`
- **Unverified org** → Go Live = `pending_approval` → admin reviews
### Admin Actions
| Entity | Actions |
|---|---|
| Organization | Approve, Reject, Block, Unblock, Verify, Delete |
| Championship | Approve, Reject, Suspend, Reinstate, Delete |
| User | Warn, Block, Unblock, Delete |
---
## 9. Org Settings
- **Edit Organization Profile**: name, instagram (inline edit form)
- **Notification Preferences**: toggles for push, email, registration alerts, payment alerts, deadline reminders
- **Connected Accounts**: Instagram (connected/not), Gmail, Telegram
- Help & Support
- Log Out
---
## 10. Search & Discovery (Member)
Members can find championships by:
- Text search (name, org name)
- Filters: discipline, location, status (Registration Open / Upcoming / Past)
- Sort: by date, by popularity
Championship cards show: name, org, dates, location, status badge, member count.
---
## 11. Future Features (Out of MVP Scope)
- Instagram parsing: auto-import championship data from org's posts
- Gmail integration: auto-detect Google Forms confirmations
- OCR results detection: parse results from Instagram photo posts
- In-app payments: replace receipt uploads
- In-app forms: replace Google Forms links
- Telegram monitoring: detect results from Telegram chats
- Category recommendation engine
- Calendar sync (export to phone calendar)
- Social features (see which friends are registered)
- Multi-language (Russian + English)