feat: Wahl-Phasen, Verantwortliche-Invites, Auth fixes, GRUPPE chat #1
@@ -0,0 +1,35 @@
|
||||
/* Minimal dev seed: one KC + Gemeinde + open Wahl with workshops.
|
||||
Run: node prisma/seed-dev.js (backend/.env must point at the dev DB) */
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
const kc = await prisma.kc.upsert({
|
||||
where: { inviteCode: 'DEV123' },
|
||||
update: {},
|
||||
create: { name: 'KC Dev 2026', inviteCode: 'DEV123' },
|
||||
});
|
||||
const gem = await prisma.gemeinde.upsert({
|
||||
where: { kcId_name: { kcId: kc.id, name: 'Mustergemeinde' } },
|
||||
update: {},
|
||||
create: { kcId: kc.id, name: 'Mustergemeinde' },
|
||||
});
|
||||
let wahl = await prisma.wahl.findFirst({ where: { kcId: kc.id } });
|
||||
if (!wahl) {
|
||||
wahl = await prisma.wahl.create({
|
||||
data: { kcId: kc.id, name: 'Samstag Teil 1', datumsSchluessel: '2026-06-13', teil: '1' },
|
||||
});
|
||||
await prisma.workshop.createMany({
|
||||
data: [
|
||||
{ wahlId: wahl.id, name: 'Töpfern', kapazitaet: 12, minTeilnehmer: 4 },
|
||||
{ wahlId: wahl.id, name: 'Fußball', kapazitaet: 20, minTeilnehmer: 6 },
|
||||
{ wahlId: wahl.id, name: 'Bandworkshop', kapazitaet: 8, minTeilnehmer: 3 },
|
||||
],
|
||||
});
|
||||
}
|
||||
console.log('KC', kc.id, 'invite', kc.inviteCode);
|
||||
console.log('Gemeinde', gem.id);
|
||||
console.log('Wahl', wahl.id);
|
||||
}
|
||||
|
||||
main().finally(() => prisma.$disconnect());
|
||||
@@ -69,6 +69,15 @@ export class WahlController {
|
||||
return this.wahl.createForceZuteilung(wahlId, dto.teilnehmerId, dto.workshopId);
|
||||
}
|
||||
|
||||
/// Everything a guest needs to fill in the Wahl: open Wahlen for their KC,
|
||||
/// each with its workshops and the guest's own current priorities (if any).
|
||||
@Get('guest/overview')
|
||||
@UseGuards(AuthGuard('guest'))
|
||||
guestOverview(@Req() req: GuestAuthenticatedRequest) {
|
||||
const guest = req.user!;
|
||||
return this.wahl.guestOverview(guest.kcId, guest.guestId);
|
||||
}
|
||||
|
||||
/// Guests submit their own workshop preferences (guest JWT, not Authentik).
|
||||
@Post(':wahlId/teilnehmer')
|
||||
@UseGuards(AuthGuard('guest'))
|
||||
|
||||
@@ -22,6 +22,40 @@ export class WahlService {
|
||||
return this.prisma.wahl.findMany({ where: { kcId } });
|
||||
}
|
||||
|
||||
/// Guest-facing view: open Wahlen for the guest's KC, each with its
|
||||
/// workshops and the guest's own current priorities (null if not submitted).
|
||||
async guestOverview(kcId: string, guestAccountId: string) {
|
||||
const [kc, wahlen] = await Promise.all([
|
||||
this.prisma.kc.findUnique({ where: { id: kcId }, select: { id: true, name: true } }),
|
||||
this.prisma.wahl.findMany({
|
||||
where: { kcId, isOpen: true },
|
||||
orderBy: { createdAt: 'asc' },
|
||||
include: {
|
||||
workshops: {
|
||||
select: { id: true, name: true, kapazitaet: true },
|
||||
orderBy: { name: 'asc' },
|
||||
},
|
||||
teilnehmer: {
|
||||
where: { guestAccountId },
|
||||
select: { prioritaeten: true },
|
||||
},
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
return {
|
||||
kc,
|
||||
wahlen: wahlen.map((w) => ({
|
||||
id: w.id,
|
||||
name: w.name,
|
||||
datumsSchluessel: w.datumsSchluessel,
|
||||
teil: w.teil,
|
||||
workshops: w.workshops,
|
||||
meinePrioritaeten: (w.teilnehmer[0]?.prioritaeten as string[] | undefined) ?? null,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
async createWorkshop(
|
||||
wahlId: string,
|
||||
name: string,
|
||||
|
||||
Reference in New Issue
Block a user