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>
42 lines
1.3 KiB
Python
42 lines
1.3 KiB
Python
from contextlib import asynccontextmanager
|
|
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
from app.config import settings
|
|
from app.routers import auth, championships, registrations, participant_lists, users
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
# Start Instagram sync scheduler if configured
|
|
if settings.INSTAGRAM_USER_ID and settings.INSTAGRAM_ACCESS_TOKEN:
|
|
from app.services.instagram_service import start_scheduler
|
|
scheduler = start_scheduler()
|
|
yield
|
|
scheduler.shutdown()
|
|
else:
|
|
yield
|
|
|
|
|
|
app = FastAPI(title="Pole Dance Championships API", version="1.0.0", lifespan=lifespan)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.cors_origins_list,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
app.include_router(auth.router, prefix="/api/v1/auth", tags=["auth"])
|
|
app.include_router(users.router, prefix="/api/v1/users", tags=["users"])
|
|
app.include_router(championships.router, prefix="/api/v1/championships", tags=["championships"])
|
|
app.include_router(registrations.router, prefix="/api/v1/registrations", tags=["registrations"])
|
|
app.include_router(participant_lists.router, prefix="/api/v1", tags=["participant-lists"])
|
|
|
|
|
|
@app.get("/internal/health", tags=["health"])
|
|
async def health():
|
|
return {"status": "ok"}
|