diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f7ec48b..efa27a0 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -26,6 +26,7 @@ model Auto { marca String modelo String anio Int + nroChasis String? createdAt DateTime @default(now()) cliente Cliente @relation(fields: [clienteId], references: [id]) @@ -50,6 +51,7 @@ model Turno { tipoServicioId String fechaInicio DateTime fechaFin DateTime + kilometros Int estado EstadoTurno @default(PENDIENTE) createdAt DateTime @default(now()) diff --git a/src/app/api/cliente/autos/route.ts b/src/app/api/cliente/autos/route.ts index 764fb17..1a47947 100644 --- a/src/app/api/cliente/autos/route.ts +++ b/src/app/api/cliente/autos/route.ts @@ -18,7 +18,7 @@ export async function POST(req: NextRequest) { const sesion = await verificarSesion("cliente_session"); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 }); - const { patente, marca, modelo, anio } = await req.json(); + const { patente, marca, modelo, anio, nroChasis } = await req.json(); if (!patente || !marca || !modelo || !anio) return NextResponse.json({ error: "Todos los campos son requeridos" }, { status: 400 }); @@ -32,6 +32,7 @@ export async function POST(req: NextRequest) { marca, modelo, anio: Number(anio), + nroChasis: nroChasis?.trim() || null, }, }); diff --git a/src/app/api/cliente/turnos/route.ts b/src/app/api/cliente/turnos/route.ts index d35a706..233a15f 100644 --- a/src/app/api/cliente/turnos/route.ts +++ b/src/app/api/cliente/turnos/route.ts @@ -20,8 +20,8 @@ export async function POST(req: NextRequest) { const sesion = await verificarSesion("cliente_session"); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 }); - const { autoId, tipoServicioId, fechaInicio } = await req.json(); - if (!autoId || !tipoServicioId || !fechaInicio) + const { autoId, tipoServicioId, fechaInicio, kilometros } = await req.json(); + if (!autoId || !tipoServicioId || !fechaInicio || !kilometros) return NextResponse.json({ error: "Datos incompletos" }, { status: 400 }); // Verificar que el auto pertenece al cliente @@ -42,7 +42,7 @@ export async function POST(req: NextRequest) { return NextResponse.json({ error: "El horario ya no está disponible" }, { status: 409 }); const turno = await prisma.turno.create({ - data: { clienteId: sesion.sub, autoId, tipoServicioId, fechaInicio: inicio, fechaFin: fin }, + data: { clienteId: sesion.sub, autoId, tipoServicioId, fechaInicio: inicio, fechaFin: fin, kilometros: Number(kilometros) }, include: { auto: true, tipoServicio: true }, }); diff --git a/src/app/cliente/dashboard/page.tsx b/src/app/cliente/dashboard/page.tsx index 8e7eadb..9365a31 100644 --- a/src/app/cliente/dashboard/page.tsx +++ b/src/app/cliente/dashboard/page.tsx @@ -5,6 +5,8 @@ import Link from "next/link"; import Button from "@/components/ui/Button"; import Card from "@/components/ui/Card"; import Input from "@/components/ui/Input"; +import Combobox from "@/components/ui/Combobox"; +import { MARCAS, getModelos } from "@/lib/marcas-modelos"; interface Auto { id: string; @@ -12,6 +14,7 @@ interface Auto { marca: string; modelo: string; anio: number; + nroChasis?: string | null; } export default function DashboardPage() { @@ -19,7 +22,8 @@ export default function DashboardPage() { const [autos, setAutos] = useState([]); const [loading, setLoading] = useState(true); const [mostrarForm, setMostrarForm] = useState(false); - const [form, setForm] = useState({ patente: "", marca: "", modelo: "", anio: "" }); + const [form, setForm] = useState({ patente: "", marca: "", modelo: "", anio: "", nroChasis: "" }); + const modelosDisponibles = getModelos(form.marca); const [guardando, setGuardando] = useState(false); const [errorForm, setErrorForm] = useState(""); @@ -51,7 +55,7 @@ export default function DashboardPage() { setGuardando(false); if (!res.ok) { setErrorForm(data.error || "Error al guardar"); return; } setMostrarForm(false); - setForm({ patente: "", marca: "", modelo: "", anio: "" }); + setForm({ patente: "", marca: "", modelo: "", anio: "", nroChasis: "" }); cargarAutos(); } @@ -108,10 +112,30 @@ export default function DashboardPage() {
- - + setForm((f) => ({ ...f, marca: v, modelo: "" }))} + onSelect={(v) => setForm((f) => ({ ...f, marca: v, modelo: "" }))} + placeholder="Ford" + required + /> + setForm((f) => ({ ...f, modelo: v }))} + onSelect={(v) => setForm((f) => ({ ...f, modelo: v }))} + placeholder={form.marca ? "Focus" : "Primero elegí la marca"} + disabled={modelosDisponibles.length === 0} + required + /> +
{errorForm &&

{errorForm}

}
diff --git a/src/app/cliente/turnos/page.tsx b/src/app/cliente/turnos/page.tsx index 7180747..dd35196 100644 --- a/src/app/cliente/turnos/page.tsx +++ b/src/app/cliente/turnos/page.tsx @@ -30,6 +30,7 @@ function TurnosContent() { const [slots, setSlots] = useState([]); const [slotSel, setSlotSel] = useState(null); const [loadingSlots, setLoadingSlots] = useState(false); + const [kilometros, setKilometros] = useState(""); const [reservando, setReservando] = useState(false); const [turnoCreado, setTurnoCreado] = useState(null); const [misTurnos, setMisTurnos] = useState([]); @@ -56,12 +57,12 @@ function TurnosContent() { } async function reservar() { - if (!slotSel || !servicioSel || !autoId) return; + if (!slotSel || !servicioSel || !autoId || !kilometros) return; setReservando(true); const res = await fetch("/api/cliente/turnos", { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ autoId, tipoServicioId: servicioSel.id, fechaInicio: slotSel.fechaInicio }), + body: JSON.stringify({ autoId, tipoServicioId: servicioSel.id, fechaInicio: slotSel.fechaInicio, kilometros: Number(kilometros) }), }); const data = await res.json(); setReservando(false); @@ -189,9 +190,23 @@ function TurnosContent() { ); })}
+
+ + setKilometros(e.target.value)} + className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" + /> +