diff --git a/apps/api/src/server.ts b/apps/api/src/server.ts index dff0a78..2a19db1 100644 --- a/apps/api/src/server.ts +++ b/apps/api/src/server.ts @@ -1,7 +1,7 @@ import Fastify from 'fastify'; import cookie from '@fastify/cookie'; import { fastifyTRPCPlugin, type FastifyTRPCPluginOptions } from '@trpc/server/adapters/fastify'; -import { runMigrations } from '@cockpit/db'; +import { runMigrations, ensureBaseAreas } from '@cockpit/db'; import { loadEnv } from './env.js'; import { logger } from './lib/logger.js'; import { registerAuthMiddleware } from './auth/middleware.js'; @@ -24,6 +24,15 @@ async function main() { process.exit(1); } + // Basis-Bereiche sicherstellen (idempotent), damit der „Neues Projekt"- + // Bereich-Dropdown auch auf einer nicht geseedeten Prod-DB nie leer ist. + try { + await ensureBaseAreas(env.DATABASE_URL); + logger.info('base areas ensured'); + } catch (err) { + logger.error({ err }, 'ensure base areas failed'); + } + const app = Fastify({ logger: { level: env.LOG_LEVEL, diff --git a/apps/web/src/routes/bereich.tsx b/apps/web/src/routes/bereich.tsx index a4780a8..da68f0a 100644 --- a/apps/web/src/routes/bereich.tsx +++ b/apps/web/src/routes/bereich.tsx @@ -1,5 +1,5 @@ import { Link, NavLink, useParams } from 'react-router'; -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import { trpc } from '../lib/trpc'; import { voice } from '../lib/voice'; import { Card } from '../components/ui/Card'; @@ -176,6 +176,15 @@ function ProjectCreateDialog({ const [name, setName] = useState(''); const [description, setDescription] = useState(''); const [areaId, setAreaId] = useState(defaultArea?.id ?? ''); + + // Areas werden asynchron geladen; sobald sie da sind und noch nichts gewählt + // wurde, sinnvollen Default setzen (Dropdown war sonst leer). + useEffect(() => { + if (!areaId && areas.length > 0) { + const fallback = areas.find((a) => a.slug === defaultSlug) ?? areas[0]; + if (fallback) setAreaId(fallback.id); + } + }, [areas, areaId, defaultSlug]); const [kind, setKind] = useState<'kundenprojekt' | 'internes_projekt'>('internes_projekt'); const [arbeitsmodus, setArbeitsmodus] = useState<'cycle' | 'kanban'>('kanban'); const [steckbrief, setSteckbrief] = useState(''); @@ -241,6 +250,9 @@ function ProjectCreateDialog({ onChange={(e) => setAreaId(e.target.value)} className="w-full rounded-[var(--radius-md)] border border-[var(--color-border)] bg-white px-3 py-2 text-sm" > + {areas.map((a) => (