# Pokedexter ⚡ Pokémon TCG-samlerwebapp — bygget med **FastAPI**, **PostgreSQL**, **Nginx** og **Docker**. Administratorer opretter serier, kort og brugere. Brugere kan logge ind, browse og søge. Ingen åben registrering. --- ## Arkitektur ``` Browser ──► Nginx (:8080) ──► FastAPI (:8000) ──► PostgreSQL (:5432) ▲ │ └─── static/ ───────┘ ``` - **Nginx** — reverse proxy, serverer statiske filer - **FastAPI** — async Python backend, Jinja2 templates - **PostgreSQL 16** — database med SQLAlchemy (async) --- ## Kom i gang ### Docker ```bash docker compose up -d --build ``` ### Podman ```bash ./start.sh ``` ### Stop ```bash ./stop.sh # podman docker compose down # docker ``` Data i `pgdata`-volumen bevares mellem genstarter. --- ## Login | Brugernavn | Adgangskode | Rolle | |------------|-------------|-------| | `admin` | `admin123` | Admin | Brugeren oprettes automatisk ved første opstart. Skift adgangskoden efter første login. --- ## Sådan bruges det ### Opret en serie (set) 1. Log ind på `/login` med `admin` / `admin123` 2. Gå til **Admin → Serier** 3. Indtast **kode** (f.eks. `CRI`) og **navn** (f.eks. `Chaos Rising`) 4. Tryk **Opret** ### Tilføj kort til en serie 1. Gå til **Admin → Serier** 2. Klik **Vis kort** på det ønskede sæt 3. Udfyld kortets detaljer (nummer, navn, type, sjældenhed, HP, stadie) 4. Tryk **Tilføj kort** Eksempel: | Felt | Værdi | |------------|-----------------| | Nummer | `068` | | Navn | `Chaos Dragon` | | Type | `Dragon` | | Rarity | `Rare` | | HP | `120` | | Stadie | `Basic` | Kortet får automatisk koden `CRI-068`. ### Opret brugere (admin) API — ingen HTML-side endnu: ```bash curl -X POST http://localhost:8080/api/admin/users \ -H "Content-Type: application/json" \ -b "token=DIN_JWT_TOKEN" \ -d '{"username":"glenn","password":"hemmeligt","role":"user"}' ``` ### Browse kort - `/sets` — liste alle serier - `/sets/CRI` — se alle kort i serie `CRI` - `/card/CRI-068` — detaljer om et specifikt kort ### Søg - `/search?q=CRI-068` — søg på fuld kortkode - `/search?q=dragon` — søg på kortnavn --- ## API-oversigt ### Offentlige endpoints | Metode | Sti | Beskrivelse | |--------|----------------|------------------------| | GET | `/` | Forside | | GET | `/sets` | Liste alle serier | | GET | `/sets/{code}` | Kort i en serie | | GET | `/search` | Søgeside | | GET | `/api/search` | Søg (JSON) | | GET | `/api/cards/{full_code}` | Enkelt kort (JSON) | ### Auth endpoints | Metode | Sti | Beskrivelse | |--------|----------------|------------------------------| | GET | `/login` | Loginside | | POST | `/api/login` | Login (sætter cookie) | | GET | `/logout` | Logout | ### Admin endpoints (kræver admin) | Metode | Sti | Beskrivelse | |--------|-------------------------------------|--------------------------------| | GET | `/admin` | Admin dashboard | | GET | `/admin/sets` | Administrér serier | | GET | `/admin/cards/{code}` | Administrér kort i serie | | POST | `/api/admin/users` | Opret bruger | | GET | `/api/admin/users` | List brugere | | POST | `/api/admin/sets` | Opret serie | | GET | `/api/admin/sets` | List serier | | DELETE | `/api/admin/sets/{id}` | Slet serie | | POST | `/api/admin/sets/{code}/cards` | Opret kort | | GET | `/api/admin/sets/{code}/cards` | List kort i serie | | DELETE | `/api/admin/cards/{id}` | Slet kort | --- ## Datamodel ``` User id Integer (PK) username String (unique) password_hash String (bcrypt) role String ("admin" | "user") created_at DateTime Set id Integer (PK) code String (unique) — "CRI" name String — "Chaos Rising" release_date String (optional) description Text (optional) created_at DateTime cards ► Card[] Card id Integer (PK) set_id Integer (FK → sets.id) number String — "068" name String — "Chaos Dragon" type String — "Dragon", "Fire", ... rarity String — "Common", "Uncommon", "Rare", ... hp Integer stage String — "Basic", "Stage 1", "Stage 2" description Text image_url String (optional) set ► Set full_code [property] — "CRI-068" ``` --- ## Miljøvariable | Variabel | Standard | Beskrivelse | |---------------|----------------------------------|----------------------| | `DATABASE_URL` | `postgresql+asyncpg://...` | PostgreSQL forbindelse | | `SECRET_KEY` | `skift-mig-til-en-sikker-noegle` | JWT signeringsnøgle | --- ## Projektstruktur ``` pokedexter/ ├── docker-compose.yml ├── start.sh # podman start ├── stop.sh # podman stop ├── backend/ │ ├── Dockerfile │ ├── requirements.txt │ └── app/ │ ├── main.py # FastAPI app, middleware │ ├── database.py # async engine + session │ ├── models.py # SQLAlchemy modeller │ ├── auth.py # bcrypt + JWT │ ├── routers/ │ │ ├── auth.py # login/logout + admin user mgmt │ │ ├── admin.py # admin CRUD for sets/cards │ │ └── cards.py # browse + search │ ├── templates/ # Jinja2 HTML templates │ └── static/ # CSS, JS, billeder ├── nginx/ │ ├── Dockerfile │ └── nginx.conf └── db/ └── init.sql ``` --- ## Udvikling Genstart backend efter kodeændringer: ```bash docker compose up -d --build backend # eller med podman: podman stop pokedexter-backend && podman rm pokedexter-backend podman build -t pokedexter-backend ./backend # ... og kør igen med podman run ... ``` --- ## Planlagte features - [ ] Personlig mappe — brugere kan markere kort de ejer/samler - [ ] Kortbilleder (upload eller URL) - [ ] Filtrering på type, sjældenhed, HP - [ ] Dark mode toggle gemt i localStorage *(done)* - [ ] Mobilvenlig navigation *(done)*