Refactor: move useAuth from store/ into hooks/

store/ folder removed — single file doesn't justify its own folder.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Dianaka123
2026-02-26 20:41:49 +03:00
parent 9fcd7c1d63
commit 5b7260de84
9 changed files with 355 additions and 7 deletions

348
LINEAR-ROADMAP.md Normal file
View File

@@ -0,0 +1,348 @@
# DanceChamp — Linear Roadmap
> Development plan for the Pole Dance Championships app.
> Tech: FastAPI + SQLAlchemy (async) + Expo (React Native) + PostgreSQL.
> Copy each section as a **Project** in Linear, each checkbox as an **Issue**.
---
## Status Legend
- ✅ = Already implemented (current MVP)
- 🔴 = Blocker (must have)
- 🟡 = Important
- 🟢 = Nice to have
---
## Project 1: Database & Models Expansion
> Expand the database schema from 4 tables to the full 12+ table schema required by the spec.
-`users` table (id, email, password, full_name, phone, role, status)
-`refresh_tokens` table (JWT refresh rotation)
-`championships` table (basic: title, description, location, event_date, status)
-`registrations` table (basic: user_id, championship_id, category, level, status)
- [ ] 🔴 Add `organizations` table — id, user_id (FK), name, instagram, email, city, logo_url, verified, status, block_reason
- [ ] 🔴 Expand `championships` — add subtitle, reg_start, reg_end, venue, accent_color, source (manual/instagram), instagram_media_id, image_url, raw_caption_text
- [ ] 🔴 Add `disciplines` table — id, championship_id (FK), name, levels (JSON array)
- [ ] 🔴 Add `styles` table — id, championship_id (FK), name
- [ ] 🔴 Add `fees` table — id, championship_id (FK), video_selection, solo, duet, group, refund_note
- [ ] 🔴 Add `rules` table — id, championship_id (FK), section (general/costume/scoring/penalty), name, value
- [ ] 🔴 Add `judges` table — id, championship_id (FK), name, instagram, bio, photo_url
- [ ] 🔴 Expand `registrations` — add discipline_id, style, participation_type (solo/duet/group), current_step (1-10), video_url, receipt_url, insurance_url, passed (null/true/false)
- [ ] 🔴 Add `participant_lists` table — id, championship_id (FK), published_by, is_published, published_at, notes
- [ ] 🔴 Add `notifications` table — id, user_id (FK), championship_id, type, title, message, read, created_at
- [ ] 🟡 Add `activity_logs` table — id, actor_id, action, target_type, target_id, details (JSON), created_at
- [ ] 🟡 Add `sync_state` table — key, value, updated_at (for Instagram sync tracking)
- [ ] 🔴 Create Alembic migration for all new tables
- [ ] 🔴 Update Pydantic schemas for all new/expanded models
- [ ] 🟡 Add seed data for new tables (disciplines, fees, rules, judges)
---
## Project 2: Organization System
> Organizations are separate entities from users. An organizer user creates/manages an organization.
- [ ] 🔴 Organization CRUD API — POST /api/v1/organizations, GET, PATCH
- [ ] 🔴 Organization approval flow — pending → admin approves → active
- [ ] 🔴 Organization verification system — verified orgs auto-approve championships
- [ ] 🔴 Link championships to organizations (not directly to users)
- [ ] 🔴 `get_org_owner` dependency — checks user owns the organization
- [ ] 🟡 Organization profile with logo upload
- [ ] 🟡 Mobile: Organization setup screen (name, instagram, city)
- [ ] 🟡 Mobile: Organization dashboard (list own championships)
---
## Project 3: Championship Configuration (Org Side)
> Organizers configure championships through tabbed interface with 5 sections.
- ✅ Basic championship CRUD (title, description, location, date)
- [ ] 🔴 Quick Create — minimal 3-field form (name, date, location) → creates draft
- [ ] 🔴 Championship setup progress tracking — 5 sections (info, categories, fees, rules, judges)
- [ ] 🔴 Categories API — CRUD for disciplines + levels per championship
- [ ] 🔴 Styles API — CRUD for styles per championship
- [ ] 🔴 Fees API — set video_selection, solo, duet, group fees
- [ ] 🔴 Rules API — add/remove general rules, costume rules, scoring criteria, penalties
- [ ] 🔴 Judges API — CRUD for judge profiles per championship
- [ ] 🔴 "Go Live" endpoint — validates all sections done, sets status
- [ ] 🔴 Registration period — reg_start, reg_end dates; auto-close when expired
- [ ] 🔴 Mobile: Championship config tabs (Overview, Categories, Fees, Rules, Judges)
- [ ] 🔴 Mobile: Tag editor component (for rules, levels, styles)
- [ ] 🔴 Mobile: "Mark as Done" per section + progress checklist
- [ ] 🟡 Mobile: Inline editing for championship info fields
- [ ] 🟡 Championship status guard — prevent edits on live championships
---
## Project 4: Enhanced Member Experience
> Rich championship browsing with 5-tab detail view, search, and filtering.
- ✅ Championship list screen
- ✅ Basic championship detail screen
- [ ] 🔴 Championship Detail — 5 tabs: Overview, Categories, Rules, Fees, Judges
- [ ] 🔴 Overview tab — event info, registration period, member count, "Register" button
- [ ] 🔴 Categories tab — show disciplines with levels and styles
- [ ] 🔴 Rules tab — general rules, costume rules, scoring criteria, penalties
- [ ] 🔴 Fees tab — video selection + championship fees breakdown
- [ ] 🔴 Judges tab — judge profiles with photo, instagram, bio
- [ ] 🔴 Search championships — full-text search by name/org
- [ ] 🔴 Filter championships — by discipline, location, status (open/upcoming/past)
- [ ] 🟡 Sort championships — by date, by popularity
- [ ] 🟡 Home screen dashboard — active registrations with progress, upcoming championships
- [ ] 🟡 Pull-to-refresh on all list screens
- [ ] 🟢 Championship image/poster display
---
## Project 5: 10-Step Registration Progress Tracker
> Members track their championship registration through 10 steps with uploads and auto-updates.
- ✅ Basic registration (submit application)
- ✅ Registration status display (submitted/accepted/rejected)
- [ ] 🔴 10-step progress model — current_step field on registration
- [ ] 🔴 Step 1: Review rules — auto-mark when user opens Rules tab
- [ ] 🔴 Step 2: Select category — saved from registration form (discipline + level + style)
- [ ] 🔴 Step 3: Record video — manual toggle
- [ ] 🔴 Step 4: Submit video form — manual toggle or external link
- [ ] 🔴 Step 5: Pay video fee — upload receipt screenshot
- [ ] 🔴 Step 6: Wait for results — pending state until org decides
- [ ] 🔴 Step 7: Results — auto-updates when org passes/fails video
- [ ] 🔴 Step 8: Pay championship fee — upload receipt (only if passed)
- [ ] 🔴 Step 9: Submit "About Me" — manual toggle or external link
- [ ] 🔴 Step 10: Confirm insurance — upload insurance document
- [ ] 🔴 Mobile: Vertical step list with icons, status (locked/available/done/failed)
- [ ] 🔴 Mobile: Progress bar (X/10 completed)
- [ ] 🔴 Mobile: Step detail expansion with action area
- [ ] 🟡 Mobile: "My Championships" with Active/Past tabs and progress bars
---
## Project 6: File Upload System
> Receipt photos, insurance documents, judge photos, org logos.
- [ ] 🔴 File upload API endpoint — POST /api/v1/uploads
- [ ] 🔴 Local file storage (dev) with configurable S3/Supabase Storage (prod)
- [ ] 🔴 Receipt photo upload — camera/gallery picker → upload → pending confirmation
- [ ] 🔴 Insurance document upload — same flow
- [ ] 🔴 Serve uploaded files — GET /api/v1/uploads/{filename}
- [ ] 🟡 Judge profile photo upload
- [ ] 🟡 Organization logo upload
- [ ] 🟡 Image compression before upload (mobile side)
- [ ] 🟡 File type validation (images only for receipts, PDF/images for insurance)
---
## Project 7: Organizer — Member Management
> Organizers review members, pass/fail videos, confirm payments, publish results.
- [ ] 🔴 Members list per championship — GET /api/v1/championships/{id}/members
- [ ] 🔴 Member detail — registration info, video link, receipt, progress
- [ ] 🔴 Edit member's level/style (with notification trigger)
- [ ] 🔴 Video review — Pass/Fail buttons per member
- [ ] 🔴 Payment confirmation — Confirm receipt button
- [ ] 🔴 Results tab — pending/passed/failed counts, "Publish Results" button
- [ ] 🔴 Mobile: Member list with search + filter chips (All, Receipts, Videos, Passed)
- [ ] 🔴 Mobile: Member detail screen with action buttons
- [ ] 🔴 Mobile: Results screen with Pass/Fail workflow
- [ ] 🟡 Filter members by status (pending receipt, pending video, passed, failed)
- [ ] 🟡 Bulk actions — pass/fail multiple members at once
---
## Project 8: Notification System
> In-app notifications + push notifications via Expo Push Service.
- [ ] 🔴 Notification model + CRUD API
- [ ] 🔴 In-app notification feed — GET /api/v1/notifications
- [ ] 🔴 Mark notification as read — PATCH /api/v1/notifications/{id}/read
- [ ] 🔴 Mark all as read — POST /api/v1/notifications/read-all
- [ ] 🔴 Notification triggers:
- Video passed/failed → member notification
- Payment confirmed → member notification
- Level/style changed → member notification
- Results published → all registrants notified
- User approved → welcome notification
- Championship goes live → all platform notification
- [ ] 🔴 Expo Push Token registration — PATCH /api/v1/users/me/push-token
- [ ] 🔴 Expo Push Service integration — send push on notification create
- [ ] 🔴 Mobile: Bell icon with unread count badge
- [ ] 🔴 Mobile: Notification feed screen (cards with icon, type, message, timestamp)
- [ ] 🟡 Push notification preferences (toggles for each type)
- [ ] 🟡 Deadline reminders — auto-send 7d, 3d, 1d before registration closes
- [ ] 🟢 Email notifications (secondary channel)
---
## Project 9: Instagram Integration
> Automatically sync championship announcements from organizer's Instagram Business account.
- [ ] 🔴 Instagram Graph API client — fetch recent posts from Business/Creator account
- [ ] 🔴 Caption parser — extract title (first line), location, date from caption text
- [ ] 🔴 Date parser — support Russian ("15 марта 2025") and English ("March 15 2025") + numeric (15.03.2025)
- [ ] 🔴 Location parser — detect "Место:", "Адрес:", "Location:", "Venue:", "Зал:"
- [ ] 🔴 Championship upsert — use instagram_media_id as dedup key, create as draft
- [ ] 🔴 APScheduler polling — run every 30 min via FastAPI lifespan event
- [ ] 🔴 Sync state tracking — store last sync timestamp, only process new posts
- [ ] 🔴 Long-lived token management — store in .env, auto-refresh before 60-day expiry
- [ ] 🔴 Token refresh scheduler — weekly job to call Graph API token exchange
- [ ] 🟡 Image sync — save media_url as championship image
- [ ] 🟡 Manual import button — "Import from Instagram" in org dashboard
- [ ] 🟡 Error handling — failed parsing saves raw caption for manual review
- [ ] 🟢 Multiple Instagram accounts support (one per org)
---
## Project 10: Enhanced Admin Panel
> Full admin capabilities: org management, championship moderation, user management.
- ✅ Basic admin panel (approve/reject pending users)
- [ ] 🔴 Admin dashboard — stats (active orgs, live champs, total users)
- [ ] 🔴 "Needs Attention" section — pending orgs + pending championships
- [ ] 🔴 Organization management — list, detail, approve/reject/block/unblock/verify
- [ ] 🔴 Championship moderation — list, detail, approve/reject (from unverified orgs), suspend/reinstate
- [ ] 🔴 Enhanced user management — warn, block/unblock, view activity
- [ ] 🔴 Activity log — recent actions across the platform
- [ ] 🟡 Mobile: Admin dashboard with stat cards
- [ ] 🟡 Mobile: Organization list + detail screens
- [ ] 🟡 Mobile: Championship moderation screens
- [ ] 🟢 Web admin panel (React + Vite, same API)
---
## Project 11: Auth & Security Hardening
> Production-ready auth, rate limiting, CORS, input validation.
- ✅ JWT access + refresh token rotation
- ✅ bcrypt password hashing
- ✅ Role-based route protection (dependency chain)
- [ ] 🔴 Rate limiting on auth endpoints (slowapi)
- [ ] 🔴 CORS configuration (whitelist mobile app + admin panel origins)
- [ ] 🔴 Input validation — Pydantic strict mode, length limits, email format
- [ ] 🔴 Password strength requirements (min 8 chars, mixed case, number)
- [ ] 🟡 Account lockout after N failed login attempts
- [ ] 🟡 HTTPS enforcement in production
- [ ] 🟡 Audit logging — log all admin actions
- [ ] 🟢 Google OAuth login (alternative to email/password)
- [ ] 🟢 Two-factor authentication
---
## Project 12: PostgreSQL & Production Infrastructure
> Migrate from SQLite to PostgreSQL, containerize with Docker.
- [ ] 🔴 PostgreSQL support in database.py (async via asyncpg)
- [ ] 🔴 docker-compose.yml — PostgreSQL 16 + FastAPI containers
- [ ] 🔴 Dockerfile for backend
- [ ] 🔴 Environment config — .env.example with all required variables
- [ ] 🔴 Alembic migration compatibility — ensure all migrations work on PostgreSQL
- [ ] 🔴 Production ASGI server — gunicorn + uvicorn workers
- [ ] 🟡 Health check endpoint improvements
- [ ] 🟡 Structured logging (JSON format for production)
- [ ] 🟡 Database connection pooling
- [ ] 🟢 CI/CD pipeline (GitHub Actions — lint, test, build)
- [ ] 🟢 Deployment to cloud (VPS / Railway / Fly.io)
---
## Project 13: Testing
> Comprehensive test coverage for backend and mobile.
- [ ] 🔴 pytest setup with async fixtures (httpx + AsyncClient)
- [ ] 🔴 Auth tests — register, login, refresh, logout, me, role checks
- [ ] 🔴 Championship tests — CRUD, status transitions, permission checks
- [ ] 🔴 Registration tests — submit, duplicate guard, closed registration guard
- [ ] 🔴 Admin tests — approve/reject users, org management
- [ ] 🔴 Instagram parser tests — various caption formats, edge cases
- [ ] 🔴 Notification tests — trigger conditions, push delivery
- [ ] 🟡 Integration tests — full flows (register → apply → review → publish)
- [ ] 🟡 Mobile: TypeScript strict mode + path aliases (@api/*, @store/*, @screens/*)
- [ ] 🟢 E2E tests (Detox or Maestro for mobile)
- [ ] 🟢 Load testing (locust or k6)
---
## Project 14: Design System & UI Polish
> Consistent dark luxury theme across all screens, smooth animations.
- [ ] 🟡 Design tokens — colors, typography, spacing constants file
- [ ] 🟡 Typography — Playfair Display (headings) + DM Sans (body) + JetBrains Mono (badges)
- [ ] 🟡 Component library — Button, Card, Badge, TabBar, TagEditor, LoadingOverlay
- [ ] 🟡 Dark luxury theme — dark backgrounds (#08070D), pink/purple accents
- [ ] 🟡 Loading skeletons on all list screens
- [ ] 🟡 Empty states — custom illustrations per screen
- [ ] 🟡 Error states — friendly messages + retry buttons
- [ ] 🟡 Animations — tab transitions, card press, progress bar fill
- [ ] 🟢 Haptic feedback on key actions
- [ ] 🟢 Swipe gestures on member cards (pass/fail)
- [ ] 🟢 Onboarding walkthrough for first-time users
---
## Project 15: Internationalization (Post-MVP)
> Russian + English language support.
- [ ] 🟢 i18n setup (react-i18next or similar)
- [ ] 🟢 Extract all strings to translation files
- [ ] 🟢 Russian translations
- [ ] 🟢 Language switcher in profile settings
- [ ] 🟢 Date/time formatting per locale
---
## Recommended Priority Order
If you need to ship fast, work in this order:
| Priority | Project | Why |
|:---:|---|---|
| 1 | Project 1: Database Expansion | Foundation for everything else |
| 2 | Project 2: Organization System | Core business entity |
| 3 | Project 3: Championship Config | Orgs need to create proper championships |
| 4 | Project 4: Enhanced Member UX | Members need to see championship details |
| 5 | Project 5: 10-Step Progress | Core differentiator — step-by-step registration |
| 6 | Project 6: File Uploads | Required for receipts + insurance steps |
| 7 | Project 7: Member Management | Orgs need to review and manage members |
| 8 | Project 8: Notifications | Users need to know what's happening |
| 9 | Project 9: Instagram Sync | Automate championship creation |
| 10 | Project 10: Enhanced Admin | Full platform control |
| 11 | Project 11: Security | Production hardening |
| 12 | Project 12: PostgreSQL + Docker | Production deployment |
| 13 | Project 13: Testing | Quality assurance |
| 14 | Project 14: Design System | Visual polish |
| 15 | Project 15: i18n | Post-launch |
---
## Current State Summary
### What's Built (MVP)
- FastAPI backend with SQLite (async)
- JWT auth with refresh token rotation
- 4 tables: users, refresh_tokens, championships, registrations
- Member auto-approve, organizer requires admin approval
- Championship list + basic detail
- Registration form + "My Registrations" with championship info
- Admin panel (approve/reject pending users)
- Profile screen with role badges
- Tab navigation with Ionicons
### What's Next (Sprint 1 recommended)
1. Database expansion (Project 1)
2. Organization system (Project 2)
3. Championship configuration tabs (Project 3)

View File

@@ -2,7 +2,7 @@
import { useState } from "react"; import { useState } from "react";
import { useUsers, useUserActions } from "@/hooks/useUsers"; import { useUsers, useUserActions } from "@/hooks/useUsers";
import { useAuth } from "@/store/useAuth"; import { useAuth } from "@/hooks/useAuth";
import { UserCard } from "@/components/UserCard"; import { UserCard } from "@/components/UserCard";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useEffect } from "react"; import { useEffect } from "react";

View File

@@ -4,7 +4,7 @@ import { use } from "react";
import { useChampionship } from "@/hooks/useChampionship"; import { useChampionship } from "@/hooks/useChampionship";
import { useMyRegistrations } from "@/hooks/useMyRegistrations"; import { useMyRegistrations } from "@/hooks/useMyRegistrations";
import { useRegisterForChampionship } from "@/hooks/useRegisterForChampionship"; import { useRegisterForChampionship } from "@/hooks/useRegisterForChampionship";
import { useAuth } from "@/store/useAuth"; import { useAuth } from "@/hooks/useAuth";
import { RegistrationTimeline } from "@/components/RegistrationTimeline"; import { RegistrationTimeline } from "@/components/RegistrationTimeline";
import { StatusBadge } from "@/components/StatusBadge"; import { StatusBadge } from "@/components/StatusBadge";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";

View File

@@ -1,7 +1,7 @@
"use client"; "use client";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useAuth } from "@/store/useAuth"; import { useAuth } from "@/hooks/useAuth";
import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";

View File

@@ -2,7 +2,7 @@
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { useAuth } from "@/store/useAuth"; import { useAuth } from "@/hooks/useAuth";
function AuthInitializer({ children }: { children: React.ReactNode }) { function AuthInitializer({ children }: { children: React.ReactNode }) {
const initialize = useAuth((s) => s.initialize); const initialize = useAuth((s) => s.initialize);

View File

@@ -2,7 +2,7 @@
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useAuth } from "@/store/useAuth"; import { useAuth } from "@/hooks/useAuth";
import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { import {
DropdownMenu, DropdownMenu,

View File

@@ -2,7 +2,7 @@
import { useState } from "react"; import { useState } from "react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useAuth } from "@/store/useAuth"; import { useAuth } from "@/hooks/useAuth";
export function useLoginForm() { export function useLoginForm() {
const router = useRouter(); const router = useRouter();

View File

@@ -2,7 +2,7 @@
import { useState } from "react"; import { useState } from "react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useAuth } from "@/store/useAuth"; import { useAuth } from "@/hooks/useAuth";
export function useRegisterForm() { export function useRegisterForm() {
const router = useRouter(); const router = useRouter();