Compare commits

...

7 Commits

Author SHA1 Message Date
61a7f57f1f Update beans and deployment docs
Update epic checklist, mark completed tasks, fix Gitea username/domain
references, and update DEPLOYMENT.md with correct registry paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 18:28:56 +01:00
03f07ebee5 Add deploy script and update prod compose
Deploy script builds and pushes images to Gitea registry, then triggers
Portainer stack redeployment via API. Includes preflight checks for
branch and uncommitted changes. Also renames prod DB volume to avoid
conflicts with dev and changes frontend port to 9080.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 18:28:17 +01:00
972137acfb Fix TypeScript errors in frontend build
Cast boss type select value to union type and remove unused
AdvanceLegInput import.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 18:10:38 +01:00
fd23d89e71 Add production Dockerfiles and nginx config
Backend: installs non-editable, runs uvicorn without reload.
Frontend: multi-stage build, serves static files via nginx with
API proxy to the backend service and SPA fallback routing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 18:00:28 +01:00
d9d547ef53 Add production docker-compose file
Uses pre-built images from the Gitea container registry, runs Alembic
migrations before API startup, and keeps the database password configurable
via environment variable. No source mounts or debug mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 17:58:55 +01:00
349a0cb821 Add DEPLOYMENT.md as living deployment documentation
Covers architecture overview, Gitea container registry setup, branching
strategy, and deployment workflow. Sections not yet implemented are marked
with TODO to be filled in as the deployment epic progresses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 17:56:06 +01:00
ad4ac6cf8c Update deployment strategy to use Gitea instead of plain Docker registry
Gitea provides source hosting, container registry, and CI/CD in one package.
Images are pushed as user-level packages to the Gitea registry over SSL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 17:45:43 +01:00
17 changed files with 392 additions and 44 deletions

View File

@@ -5,7 +5,7 @@ status: todo
type: task
priority: normal
created_at: 2026-02-09T15:30:50Z
updated_at: 2026-02-09T15:31:15Z
updated_at: 2026-02-09T16:53:13Z
parent: nuzlocke-tracker-ahza
blocking:
- nuzlocke-tracker-vpn5

View File

@@ -1,11 +1,11 @@
---
# nuzlocke-tracker-ahza
title: Deployment Strategy
status: todo
status: in-progress
type: epic
priority: normal
created_at: 2026-02-09T14:03:53Z
updated_at: 2026-02-09T15:08:29Z
updated_at: 2026-02-09T16:53:58Z
---
Define and implement a deployment strategy for running the nuzlocke-tracker in production on a local Unraid server while keeping laptop/PC as the development environment.
@@ -20,14 +20,14 @@ Define and implement a deployment strategy for running the nuzlocke-tracker in p
## Decided Approach
**Docker Compose + Portainer + Local Docker Registry**
**Docker Compose + Portainer + Gitea (source hosting, container registry, CI/CD)**
1. **A local Docker registry** runs on Unraid as a container, accessible on the LAN (e.g., `unraid:5000` or behind Nginx Proxy Manager).
2. **Images are built on the dev machine** and pushed to the local registry.
3. **Production runs docker-compose** on Unraid, pulling images from the local registry instead of mounting source.
1. **Gitea** runs on Unraid behind Nginx Proxy Manager with SSL (e.g., `gitea.nerdboden.de`). It serves as the self-hosted Git remote, container registry, and (optionally) CI/CD via Gitea Actions.
2. **Images are built on the dev machine** and pushed to Gitea's container registry as **user-level packages** (e.g., `gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest`, `gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest`).
3. **Production runs docker-compose** on Unraid, pulling images from the Gitea container registry instead of mounting source.
4. **Portainer** is installed on Unraid to manage stacks, provide a web UI, and enable webhook-triggered redeployments.
5. **A deploy script** on the dev machine automates the full flow: build images → push to local registry → trigger Portainer webhook to redeploy.
6. **Nginx Proxy Manager** handles routing on the LAN (e.g., `nuzlocke.local` → frontend container).
5. **A deploy script** on the dev machine automates the full flow: build images → push to Gitea registry → trigger Portainer webhook to redeploy.
6. **Nginx Proxy Manager** handles routing on the LAN (e.g., `nuzlocke.nerdboden.de` → frontend container, `gitea.nerdboden.de` → Gitea).
7. **Database** uses a named Docker volume for persistence; migrations run automatically on API container startup.
## Branching Strategy
@@ -42,19 +42,19 @@ Define and implement a deployment strategy for running the nuzlocke-tracker in p
1. Create `feature/xyz` from `develop`
2. Work on the feature, commit, merge into `develop`
3. When ready to deploy: merge `develop``main`
4. Run `./deploy.sh` (builds from `main`, pushes to local registry, triggers Portainer webhook)
4. Run `./deploy.sh` (builds from `main`, pushes to Gitea registry, triggers Portainer webhook)
## Checklist
- [ ] **Set up branching structure** — create `develop` branch from `main`, establish the `main`/`develop`/`feature/*` workflow
- [ ] **Update CLAUDE.md with branching rules** — once the branching structure is in place, add instructions to CLAUDE.md that the branching strategy must be adhered to (always work on feature branches, never commit directly to `main`, merge flow is `feature/*``develop``main`)
- [ ] **Set up local Docker registry on Unraid** — run the `registry:2` container, configure storage volume, optionally put it behind Nginx Proxy Manager with a hostname (e.g., `registry.local`)
- [ ] **Create production docker-compose file** (`docker-compose.prod.yml`) — uses images from the local registry, production env vars, no source volume mounts, proper restart policies
- [ ] **Create production Dockerfiles (or multi-stage builds)** — ensure frontend is built and served statically (e.g., via the API or a lightweight nginx container), API runs without debug mode
- [ ] **Set up Portainer on Unraid** — install Portainer CE as a Docker container, configure the stack from the production compose file
- [ ] **Configure Portainer webhook for automated redeployment**add a webhook trigger in Portainer that pulls latest images and restarts the stack
- [ ] **Create deploy script** a script (e.g., `./deploy.sh`) that builds images from `main`, tags them for the local registry, pushes them, and triggers the Portainer webhook to redeploy
- [ ] **Configure Nginx Proxy Manager** — add proxy host entry pointing to the frontend/API containers on the appropriate ports
- [ ] **Configure Gitea container registry** — create an access token with `read:package` and `write:package` scopes, verify `docker login gitea.nerdboden.de` works, test pushing and pulling an image as a user-level package
- [x] **Create production docker-compose file** (`docker-compose.prod.yml`) — uses images from the Gitea container registry, production env vars, no source volume mounts, proper restart policies
- [x] **Create production Dockerfiles (or multi-stage builds)** — ensure frontend is built and served statically (e.g., via the API or a lightweight nginx container), API runs without debug mode
- [x] **Set up Portainer on Unraid** — install Portainer CE as a Docker container, configure the stack from the production compose file
- [x] **Configure Portainer API for automated redeployment**deploy script uses Portainer CE REST API to pull latest images and restart the stack
- [x] **Create deploy script**`./deploy.sh` builds images, pushes to Gitea registry, triggers Portainer API redeployment
- [ ] **Configure Nginx Proxy Manager** — add proxy host entries for Gitea and the nuzlocke-tracker frontend/API on the appropriate ports
- [ ] **Environment & secrets management** — create a `.env.prod` template, document required variables, decide on secret handling (`.env` file on Unraid, Portainer env vars, etc.)
- [ ] **Database backup strategy** — set up a simple scheduled backup for the PostgreSQL volume/data (e.g., cron + `pg_dump` script on Unraid)
- [ ] **Document the deployment workflow** — README or docs covering how to deploy, redeploy, rollback, and manage the production instance

View File

@@ -1,11 +1,11 @@
---
# nuzlocke-tracker-aiw6
title: Create deploy script
status: todo
status: completed
type: task
priority: normal
created_at: 2026-02-09T15:30:48Z
updated_at: 2026-02-09T15:31:15Z
updated_at: 2026-02-09T17:28:22Z
parent: nuzlocke-tracker-ahza
blocking:
- nuzlocke-tracker-izf6

View File

@@ -1,10 +1,11 @@
---
# nuzlocke-tracker-hwyk
title: Set up Portainer on Unraid
status: todo
status: completed
type: task
priority: normal
created_at: 2026-02-09T15:30:44Z
updated_at: 2026-02-09T15:30:44Z
updated_at: 2026-02-09T16:53:41Z
parent: nuzlocke-tracker-ahza
---

View File

@@ -1,16 +1,20 @@
---
# nuzlocke-tracker-izf6
title: Set up local Docker registry on Unraid
status: todo
title: Configure Gitea container registry
status: completed
type: task
priority: normal
created_at: 2026-02-09T15:30:40Z
updated_at: 2026-02-09T15:30:40Z
updated_at: 2026-02-09T16:53:09Z
parent: nuzlocke-tracker-ahza
---
Run a `registry:2` container on the Unraid server for storing production Docker images locally.
Set up and verify the Gitea container registry for hosting Docker images as user-level packages.
- Run `registry:2` as a Docker container on Unraid
- Configure a persistent storage volume for the registry data
- Optionally put it behind Nginx Proxy Manager with a hostname (e.g., `registry.local`)
- Verify pushing/pulling images from the dev machine works
## Checklist
- [ ] Create a Gitea access token with `read:package` and `write:package` scopes
- [ ] Verify `docker login gitea.nerdboden.de` works from the dev machine
- [ ] Test pushing a Docker image as a user-level package (e.g., `gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest`)
- [ ] Verify the image appears under the user's Packages tab in Gitea
- [ ] Test pulling the image back (from Unraid or dev machine)

View File

@@ -1,18 +1,28 @@
---
# nuzlocke-tracker-jzqz
title: Configure Portainer webhook for automated redeployment
status: todo
title: Configure Portainer API for automated redeployment
status: completed
type: task
priority: normal
created_at: 2026-02-09T15:30:45Z
updated_at: 2026-02-09T15:31:15Z
updated_at: 2026-02-09T17:28:22Z
parent: nuzlocke-tracker-ahza
blocking:
- nuzlocke-tracker-hwyk
---
Set up a webhook in Portainer that triggers a stack redeployment when called.
Use the Portainer CE REST API to trigger stack redeployments from the deploy script.
- Create a webhook trigger in Portainer for the nuzlocke-tracker stack
- The webhook should pull the latest images from the local registry and restart the stack
- Note the webhook URL for use in the deploy script
Portainer webhooks are a Business-only feature, so we use the API directly instead.
## Approach
1. Authenticate with the Portainer API to get a JWT token
2. Call the stack update endpoint with `pullImage: true` to pull latest images and recreate containers
## Checklist
- [ ] Identify the stack ID in Portainer (via API or UI)
- [ ] Test API authentication (`POST /api/auth`)
- [ ] Test triggering a stack redeploy via API
- [ ] Integrate into the deploy script

View File

@@ -1,11 +1,11 @@
---
# nuzlocke-tracker-re0m
title: Document the deployment workflow
status: todo
status: in-progress
type: task
priority: normal
created_at: 2026-02-09T15:30:57Z
updated_at: 2026-02-09T15:31:15Z
updated_at: 2026-02-09T16:55:02Z
parent: nuzlocke-tracker-ahza
blocking:
- nuzlocke-tracker-aiw6

View File

@@ -1,10 +1,11 @@
---
# nuzlocke-tracker-vpn5
title: Create production docker-compose file
status: todo
status: completed
type: task
priority: normal
created_at: 2026-02-09T15:30:41Z
updated_at: 2026-02-09T15:30:41Z
updated_at: 2026-02-09T16:59:00Z
parent: nuzlocke-tracker-ahza
---

View File

@@ -1,10 +1,11 @@
---
# nuzlocke-tracker-xmyh
title: Create production Dockerfiles
status: todo
status: completed
type: task
priority: normal
created_at: 2026-02-09T15:30:42Z
updated_at: 2026-02-09T15:30:42Z
updated_at: 2026-02-09T17:00:32Z
parent: nuzlocke-tracker-ahza
---

152
DEPLOYMENT.md Normal file
View File

@@ -0,0 +1,152 @@
# Deployment
This document describes the deployment architecture and workflows for the nuzlocke-tracker. It is a living document — sections marked with **TODO** are planned but not yet implemented.
## Architecture Overview
| Component | Dev (Laptop/PC) | Production (Unraid) |
|---|---|---|
| API | `docker-compose.yml` (hot reload) | `docker-compose.prod.yml` (built image) |
| Frontend | `docker-compose.yml` (Vite dev server) | `docker-compose.prod.yml` (built image) |
| Database | PostgreSQL 16 (Docker volume) | PostgreSQL 16 (Docker volume) |
| Container Registry | — | Gitea (user-level packages) |
| Container Management | — | Portainer CE |
| Reverse Proxy | — | Nginx Proxy Manager |
### Services
- **Gitea** — self-hosted Git server, container registry, and (future) CI/CD. Accessible at `gitea.nerdboden.de` via SSL.
- **Portainer** — Docker management UI. Accessible at `portainer.nerdboden.de` via SSL. Manages the production stack and provides webhook-triggered redeployments.
- **Nginx Proxy Manager** — reverse proxy with SSL termination for all services on the Unraid server.
## Container Registry
Docker images are hosted on Gitea's built-in container registry as **user-level packages**.
### Image naming
Images use the format `gitea.nerdboden.de/<user>/<image>:<tag>`:
```
gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest
gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest
```
### Authentication
1. Create a Gitea access token at **Settings > Applications** with `read:package` and `write:package` scopes.
2. Log in from the dev machine:
```bash
docker login gitea.nerdboden.de
```
Use your Gitea username and the access token as password.
### Pushing images
```bash
# Build and tag
docker build -t gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest ./backend
docker build -t gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest ./frontend
# Push
docker push gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest
docker push gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest
```
Pushed images are visible under the **Packages** tab on your Gitea user profile.
## Branching Strategy
The project uses a `main` / `develop` / `feature/*` branching model.
| Branch | Purpose |
|---|---|
| `main` | Always production-ready. Deploy script builds from here. |
| `develop` | Integration branch for day-to-day work. |
| `feature/*` | Short-lived branches off `develop` for individual features/fixes. |
### Workflow
1. Create `feature/xyz` from `develop`
2. Work on the feature, commit, merge into `develop`
3. When ready to deploy: merge `develop` into `main`
4. Run the deploy script (see below)
## Deploying
> **TODO** — deploy script (`./deploy.sh`) not yet created.
The deploy script will automate:
1. Build Docker images from `main`
2. Tag and push to the Gitea container registry
3. Trigger the Portainer webhook to pull new images and restart the stack
### Manual deployment
Until the deploy script is in place, deploy manually:
```bash
# 1. Ensure you're on main with latest changes
git checkout main
# 2. Build and push images
docker build -t gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest ./backend
docker build -t gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest ./frontend
docker push gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest
docker push gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest
# 3. On Unraid (or via Portainer): pull and restart
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d
```
## Production Compose
> **TODO** — `docker-compose.prod.yml` not yet created.
The production compose file will differ from the dev compose in:
- Uses pre-built images from the Gitea registry (no source volume mounts)
- No hot reload / debug mode
- Production environment variables
- Proper restart policies
- Frontend served as a static build (not Vite dev server)
## Portainer
Portainer CE is running on Unraid at `portainer.nerdboden.de`.
- Manages the production Docker stack
- **TODO**: Configure a webhook for automated redeployment (pull latest images + restart on trigger)
## Nginx Proxy Manager
NPM runs on Unraid and handles SSL termination and routing for:
- `gitea.nerdboden.de` → Gitea
- `portainer.nerdboden.de` → Portainer
- **TODO**: `nuzlocke.nerdboden.de` (or similar) → nuzlocke-tracker frontend/API
## Environment & Secrets
> **TODO** — `.env.prod` template not yet created.
Production environment variables to configure:
- `DATABASE_URL` — PostgreSQL connection string
- `DEBUG` — must be `false` in production
- Additional secrets TBD
## Database
PostgreSQL 16 with data stored in a named Docker volume.
- Migrations run automatically on API container startup (Alembic)
- **TODO**: Set up scheduled backups (`pg_dump` cron job on Unraid)
## Rollback
> **TODO** — rollback procedure to be documented once image tagging strategy is finalized.
General approach: tag images with version/commit hash in addition to `latest`, so rolling back means redeploying a previous tag.

19
backend/Dockerfile.prod Normal file
View File

@@ -0,0 +1,19 @@
# Production Dockerfile for the backend API
FROM python:3.14-slim
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
&& rm -rf /var/lib/apt/lists/*
# Install Python dependencies
COPY pyproject.toml README.md alembic.ini ./
COPY src/ ./src/
RUN pip install --no-cache-dir .
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--app-dir", "src"]

81
deploy.sh Executable file
View File

@@ -0,0 +1,81 @@
#!/usr/bin/env bash
set -euo pipefail
# ── Configuration ──────────────────────────────────────────────
REGISTRY="gitea.nerdboden.de"
OWNER="thefurya"
IMAGES=("nuzlocke-tracker-api" "nuzlocke-tracker-frontend")
DOCKERFILES=("backend/Dockerfile.prod" "frontend/Dockerfile.prod")
CONTEXTS=("./backend" "./frontend")
PORTAINER_URL="${PORTAINER_URL:-https://portainer.nerdboden.de}"
PORTAINER_API_KEY="${PORTAINER_API_KEY:-}"
PORTAINER_STACK_ID="${PORTAINER_STACK_ID:-}"
PORTAINER_ENDPOINT_ID="${PORTAINER_ENDPOINT_ID:-1}"
# ── Helpers ────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
info() { echo -e "${GREEN}[✓]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
error() { echo -e "${RED}[✗]${NC} $1"; exit 1; }
# ── Preflight checks ──────────────────────────────────────────
BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [[ "$BRANCH" != "main" ]]; then
warn "You are on branch '$BRANCH', not 'main'."
read -rp "Continue anyway? [y/N] " confirm
[[ "$confirm" =~ ^[Yy]$ ]] || exit 0
fi
if ! git diff --quiet || ! git diff --cached --quiet; then
warn "You have uncommitted changes."
read -rp "Continue anyway? [y/N] " confirm
[[ "$confirm" =~ ^[Yy]$ ]] || exit 0
fi
# ── Build and push images ─────────────────────────────────────
for i in "${!IMAGES[@]}"; do
IMAGE="${REGISTRY}/${OWNER}/${IMAGES[$i]}:latest"
info "Building ${IMAGES[$i]}..."
docker build -t "$IMAGE" -f "${DOCKERFILES[$i]}" "${CONTEXTS[$i]}"
info "Pushing ${IMAGES[$i]}..."
docker push "$IMAGE"
done
info "All images built and pushed."
# ── Trigger Portainer redeployment ─────────────────────────────
if [[ -z "$PORTAINER_API_KEY" ]]; then
warn "PORTAINER_API_KEY not set — skipping Portainer redeployment."
warn "Set it in your environment or .env.deploy file to enable auto-redeploy."
exit 0
fi
if [[ -z "$PORTAINER_STACK_ID" ]]; then
warn "PORTAINER_STACK_ID not set — skipping Portainer redeployment."
warn "Find your stack ID in Portainer and set it in your environment."
exit 0
fi
info "Fetching stack file from Portainer..."
STACK_FILE=$(curl -sf \
-H "X-API-Key: ${PORTAINER_API_KEY}" \
"${PORTAINER_URL}/api/stacks/${PORTAINER_STACK_ID}/file") \
|| error "Failed to fetch stack file from Portainer."
STACK_CONTENT=$(echo "$STACK_FILE" | jq -r '.StackFileContent')
info "Triggering stack redeployment..."
curl -sf -X PUT \
-H "X-API-Key: ${PORTAINER_API_KEY}" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg content "$STACK_CONTENT" '{"pullImage": true, "stackFileContent": $content}')" \
"${PORTAINER_URL}/api/stacks/${PORTAINER_STACK_ID}?endpointId=${PORTAINER_ENDPOINT_ID}" \
> /dev/null \
|| error "Failed to trigger Portainer redeployment."
info "Stack redeployment triggered successfully!"

38
docker-compose.prod.yml Normal file
View File

@@ -0,0 +1,38 @@
services:
api:
image: gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest
command: >
sh -c "alembic upgrade head && uvicorn app.main:app --host 0.0.0.0 --port 8000 --app-dir src"
environment:
- DEBUG=false
- DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@db:5432/nuzlocke
depends_on:
db:
condition: service_healthy
restart: unless-stopped
frontend:
image: gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest
ports:
- "9080:80"
depends_on:
- api
restart: unless-stopped
db:
image: postgres:16-alpine
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=nuzlocke
volumes:
- prod_postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
restart: unless-stopped
volumes:
prod_postgres_data:

21
frontend/Dockerfile.prod Normal file
View File

@@ -0,0 +1,21 @@
# Production Dockerfile for the frontend
# Stage 1: Build
FROM node:24-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: Serve
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

20
frontend/nginx.conf Normal file
View File

@@ -0,0 +1,20 @@
server {
listen 80;
root /usr/share/nginx/html;
index index.html;
# Proxy API requests to the backend service
location /api/ {
proxy_pass http://api:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Serve static files, fall back to index.html for SPA routing
location / {
try_files $uri $uri/ /index.html;
}
}

View File

@@ -107,7 +107,7 @@ export function BossBattleFormModal({
<label className="block text-sm font-medium mb-1">Type</label>
<select
value={bossType}
onChange={(e) => setBossType(e.target.value)}
onChange={(e) => setBossType(e.target.value as typeof bossType)}
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
>
{BOSS_TYPES.map((t) => (

View File

@@ -1,6 +1,6 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { advanceLeg, createGenlocke, getGamesByRegion, getGenlockes, getGenlocke, getGenlockeGraveyard, getGenlockeLineages, getLegSurvivors } from '../api/genlockes'
import type { AdvanceLegInput, CreateGenlockeInput } from '../types/game'
import type { CreateGenlockeInput } from '../types/game'
export function useGenlockes() {
return useQuery({