Files
PoleDanceApp/dance-champ-app.md
Dianaka123 9eb68695e9 Clear project — starting fresh from spec
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 14:36:47 +03:00

10 KiB

Pole Dance Championships App — Technical Document

1. Project Overview

Problem

Pole dance championships lack dedicated tools for organizers and participants. Organizers rely on Instagram posts to announce events, and registrations are managed via Google Forms — leading to:

  • No visibility — Participants can't track their registration status in one place.
  • Scattered info — Dates, rules, and results are buried across Instagram posts.
  • No access control — Anyone can register; organizers need a way to accept or reject participants.

Solution

A members-only mobile app for pole dance championship participants and organizers.

  • New users register and wait for admin approval before accessing the app.
  • Championship announcements are auto-imported from Instagram (Graph API).
  • Members browse championships, submit registrations, and track their status.
  • Organizers accept, reject, or waitlist participants and publish the final participant list.
  • Push notifications alert members when results are published.

2. User Roles

Role Access
Member Browse championships, register, track own registration status
Organizer All of the above + manage registrations, publish participant lists
Admin All of the above + approve/reject new member accounts

New accounts start as pending and must be approved by an admin before they can use the app.


3. Tech Stack

Layer Technology
Mobile React Native + TypeScript (Expo managed workflow)
Navigation React Navigation v6
Server state TanStack React Query v5
Client state Zustand
Backend FastAPI (Python, async)
ORM SQLAlchemy 2.0 async
Database SQLite (local dev) / PostgreSQL (production)
Migrations Alembic
Auth JWT — access tokens (15 min) + refresh tokens (7 days, rotation-based)
Instagram sync Instagram Graph API, polled every 30 min via APScheduler
Push notifications Expo Push API (routes to FCM + APNs)
Token storage expo-secure-store (with in-memory cache for reliability)

4. Architecture

┌─────────────────────┐        ┌──────────────────────────────┐
│   React Native App  │◄──────►│   FastAPI Backend            │
│   (Expo Go / APK)   │  HTTPS │   /api/v1/...                │
└─────────────────────┘        │                              │
                               │  ┌──────────────────────┐   │
                               │  │  APScheduler         │   │
                               │  │  - Instagram poll/30m│   │
                               │  │  - Token refresh/7d  │   │
                               │  └──────────────────────┘   │
                               │                              │
                               │  ┌──────────────────────┐   │
                               │  │  SQLite / PostgreSQL  │   │
                               │  └──────────────────────┘   │
                               └──────────────────────────────┘

5. Data Model

User

id            UUID (PK)
email         String (unique)
full_name     String
phone         String (nullable)
hashed_password String
role          Enum: member | organizer | admin
status        Enum: pending | approved | rejected
expo_push_token String (nullable)
created_at    DateTime
updated_at    DateTime

Championship

id                    UUID (PK)
title                 String
description           String (nullable)
location              String (nullable)
event_date            DateTime (nullable)
registration_open_at  DateTime (nullable)
registration_close_at DateTime (nullable)
status                Enum: draft | open | closed | completed
source                Enum: manual | instagram
instagram_media_id    String (nullable, unique)
image_url             String (nullable)
raw_caption_text      Text (nullable)
created_at            DateTime
updated_at            DateTime

Registration

id               UUID (PK)
championship_id  UUID (FK → Championship)
user_id          UUID (FK → User)
category         String (nullable)
level            String (nullable)
notes            Text (nullable)
status           Enum: submitted | accepted | rejected | waitlisted
submitted_at     DateTime
decided_at       DateTime (nullable)

ParticipantList

id               UUID (PK)
championship_id  UUID (FK → Championship, unique)
published_by     UUID (FK → User)
is_published     Boolean
published_at     DateTime (nullable)
notes            Text (nullable)

RefreshToken

id           UUID (PK)
user_id      UUID (FK → User)
token_hash   String (SHA-256, unique)
expires_at   DateTime
revoked      Boolean
created_at   DateTime

NotificationLog

id               UUID (PK)
user_id          UUID (FK → User)
championship_id  UUID (FK → Championship, nullable)
title            String
body             String
sent_at          DateTime
status           String

6. API Endpoints

Auth

Method Path Description
POST /api/v1/auth/register Register new account (status=pending)
POST /api/v1/auth/login Login, get access + refresh tokens
POST /api/v1/auth/refresh Refresh access token
POST /api/v1/auth/logout Revoke refresh token
GET /api/v1/auth/me Get current user

Championships

Method Path Access
GET /api/v1/championships Approved members
GET /api/v1/championships/{id} Approved members
POST /api/v1/championships Organizer+
PATCH /api/v1/championships/{id} Organizer+
DELETE /api/v1/championships/{id} Admin

Registrations

Method Path Access
POST /api/v1/championships/{id}/register Approved member
GET /api/v1/championships/{id}/registrations Organizer+
PATCH /api/v1/registrations/{id}/status Organizer+
GET /api/v1/registrations/mine Member (own only)
DELETE /api/v1/registrations/{id} Member (own, before decision)

Participant Lists

Method Path Access
GET /api/v1/championships/{id}/participant-list Approved member
PUT /api/v1/championships/{id}/participant-list Organizer+
POST /api/v1/championships/{id}/participant-list/publish Organizer+
POST /api/v1/championships/{id}/participant-list/unpublish Organizer+

Users (Admin)

Method Path Description
GET /api/v1/users List all users
PATCH /api/v1/users/{id}/status Approve/reject member
PATCH /api/v1/users/me/push-token Register push token

7. Mobile Screens

Auth Flow

  • LoginScreen — Email + password login
  • RegisterScreen — Full name, phone, email, password
  • PendingApprovalScreen — Shown after register until admin approves

App (approved members)

  • ChampionshipListScreen — All championships with status badges
  • ChampionshipDetailScreen — Full info + registration button
  • RegistrationFormScreen — Category, level, notes
  • ProfileScreen — User info, logout

Navigation

No user ──► AuthStack (Login / Register)
Pending ──► PendingApprovalScreen
Approved ──► AppStack (Championships / Profile)

8. Instagram Integration

How It Works

  1. Admin configures INSTAGRAM_USER_ID and INSTAGRAM_ACCESS_TOKEN in .env.
  2. APScheduler polls the Instagram Graph API every 30 minutes.
  3. New media posts are parsed: title (first line of caption), location (Место: / Location: prefix), dates (regex for RU + EN date formats).
  4. New championships are created with status=draft for admin review.
  5. Long-lived tokens are refreshed weekly automatically.

Parsing Logic

  • Title — First non-empty line of the caption.
  • Location — Line starting with Место: or Location:.
  • Date — Regex matches formats like 15 апреля 2026, April 15, 2026, 15.04.2026.
  • Deduplication — Championships are matched by instagram_media_id.

9. Local Development Setup

Prerequisites

  • Python 3.11+
  • Node.js 18+
  • Expo Go app on phone

Backend

cd backend
python -m venv .venv
.venv\Scripts\pip install -r requirements.txt
alembic upgrade head
python scripts/create_admin.py   # creates admin@poledance.app / Admin1234
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload

Or use: start-backend.bat

Mobile

cd mobile
npm install
npx expo start --lan --clear

Or use: start-mobile.bat

Environment (backend/.env)

DATABASE_URL=sqlite+aiosqlite:///./poledance.db
SECRET_KEY=dev-secret-key-change-before-production-32x
INSTAGRAM_USER_ID=
INSTAGRAM_ACCESS_TOKEN=
INSTAGRAM_POLL_INTERVAL=1800

Environment (mobile/.env)

EXPO_PUBLIC_API_URL=http://<your-local-ip>:8000/api/v1

Test Accounts

Email Password Role Status
admin@poledance.app Admin1234 admin approved
anna@example.com Member1234 member approved
maria@example.com Member1234 member approved
elena@example.com Member1234 member pending

10. Known Limitations (Local Dev)

  • SQLite is used instead of PostgreSQL — change DATABASE_URL for production.
  • Push notifications don't work in Expo Go SDK 53 — requires a development build.
  • Instagram polling requires a valid Business/Creator account token.
  • Windows Firewall must allow inbound TCP on port 8000 for phone to reach the backend.

11. Future Features

  • Web admin panel — Browser-based dashboard for organizers to manage registrations and championships.
  • In-app notifications feed — History of received push notifications.
  • Calendar sync — Export championship dates to phone calendar.
  • Production deployment — Docker + PostgreSQL + nginx + SSL.
  • OCR / LLM parsing — Better extraction of championship details from Instagram images and captions.
  • Multi-organizer — Support multiple Instagram accounts for different championships.