feat(p0): prix/nuit + booking form public + /inscription + /reservations/[id]
This commit is contained in:
parent
f09a680059
commit
e79b6dd141
15 changed files with 590 additions and 9 deletions
64
src/app/api/signup/route.ts
Normal file
64
src/app/api/signup/route.ts
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
import { NextResponse } from "next/server";
|
||||
import { z } from "zod";
|
||||
|
||||
import { UserRole } from "@/generated/prisma/enums";
|
||||
import { hashPassword } from "@/lib/password";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { recordAudit } from "@/lib/admin/audit";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
|
||||
const schema = z.object({
|
||||
email: z.string().trim().toLowerCase().email().max(200),
|
||||
password: z.string().min(8).max(200),
|
||||
firstName: z.string().trim().min(1).max(100),
|
||||
lastName: z.string().trim().min(1).max(100),
|
||||
phone: z.string().trim().max(40).optional().nullable(),
|
||||
role: z.enum([UserRole.TOURIST, UserRole.OWNER]).default(UserRole.TOURIST),
|
||||
});
|
||||
|
||||
export async function POST(req: Request) {
|
||||
let body: unknown;
|
||||
try {
|
||||
body = await req.json();
|
||||
} catch {
|
||||
return NextResponse.json({ error: "Corps JSON invalide." }, { status: 400 });
|
||||
}
|
||||
const parsed = schema.safeParse(body);
|
||||
if (!parsed.success) {
|
||||
return NextResponse.json(
|
||||
{ error: parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join(" · ") },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
const data = parsed.data;
|
||||
|
||||
const existing = await prisma.user.findUnique({ where: { email: data.email }, select: { id: true } });
|
||||
if (existing) {
|
||||
return NextResponse.json({ error: "Un compte existe déjà avec cet email." }, { status: 409 });
|
||||
}
|
||||
|
||||
const passwordHash = await hashPassword(data.password);
|
||||
const user = await prisma.user.create({
|
||||
data: {
|
||||
email: data.email,
|
||||
passwordHash,
|
||||
firstName: data.firstName,
|
||||
lastName: data.lastName,
|
||||
phone: data.phone?.trim() || null,
|
||||
role: data.role,
|
||||
isActive: true,
|
||||
},
|
||||
select: { id: true, email: true, role: true },
|
||||
});
|
||||
|
||||
await recordAudit({
|
||||
scope: "public.signup",
|
||||
event: "user.create",
|
||||
target: user.id,
|
||||
actorEmail: user.email,
|
||||
details: { role: user.role },
|
||||
});
|
||||
|
||||
return NextResponse.json({ ok: true, userId: user.id });
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue