feat: agrega km y chasis al turno/auto, combobox de marcas y modelos
Deploy / deploy (push) Failing after 13m41s
Deploy / deploy (push) Failing after 13m41s
- Turno.kilometros (requerido al reservar) - Auto.nroChasis (opcional) - Combobox con 60 marcas mundiales y modelos precargados - Modelo se habilita al seleccionar marca Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,7 @@ model Auto {
|
|||||||
marca String
|
marca String
|
||||||
modelo String
|
modelo String
|
||||||
anio Int
|
anio Int
|
||||||
|
nroChasis String?
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
cliente Cliente @relation(fields: [clienteId], references: [id])
|
cliente Cliente @relation(fields: [clienteId], references: [id])
|
||||||
@@ -50,6 +51,7 @@ model Turno {
|
|||||||
tipoServicioId String
|
tipoServicioId String
|
||||||
fechaInicio DateTime
|
fechaInicio DateTime
|
||||||
fechaFin DateTime
|
fechaFin DateTime
|
||||||
|
kilometros Int
|
||||||
estado EstadoTurno @default(PENDIENTE)
|
estado EstadoTurno @default(PENDIENTE)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export async function POST(req: NextRequest) {
|
|||||||
const sesion = await verificarSesion("cliente_session");
|
const sesion = await verificarSesion("cliente_session");
|
||||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
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)
|
if (!patente || !marca || !modelo || !anio)
|
||||||
return NextResponse.json({ error: "Todos los campos son requeridos" }, { status: 400 });
|
return NextResponse.json({ error: "Todos los campos son requeridos" }, { status: 400 });
|
||||||
|
|
||||||
@@ -32,6 +32,7 @@ export async function POST(req: NextRequest) {
|
|||||||
marca,
|
marca,
|
||||||
modelo,
|
modelo,
|
||||||
anio: Number(anio),
|
anio: Number(anio),
|
||||||
|
nroChasis: nroChasis?.trim() || null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ export async function POST(req: NextRequest) {
|
|||||||
const sesion = await verificarSesion("cliente_session");
|
const sesion = await verificarSesion("cliente_session");
|
||||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||||
|
|
||||||
const { autoId, tipoServicioId, fechaInicio } = await req.json();
|
const { autoId, tipoServicioId, fechaInicio, kilometros } = await req.json();
|
||||||
if (!autoId || !tipoServicioId || !fechaInicio)
|
if (!autoId || !tipoServicioId || !fechaInicio || !kilometros)
|
||||||
return NextResponse.json({ error: "Datos incompletos" }, { status: 400 });
|
return NextResponse.json({ error: "Datos incompletos" }, { status: 400 });
|
||||||
|
|
||||||
// Verificar que el auto pertenece al cliente
|
// 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 });
|
return NextResponse.json({ error: "El horario ya no está disponible" }, { status: 409 });
|
||||||
|
|
||||||
const turno = await prisma.turno.create({
|
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 },
|
include: { auto: true, tipoServicio: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import Link from "next/link";
|
|||||||
import Button from "@/components/ui/Button";
|
import Button from "@/components/ui/Button";
|
||||||
import Card from "@/components/ui/Card";
|
import Card from "@/components/ui/Card";
|
||||||
import Input from "@/components/ui/Input";
|
import Input from "@/components/ui/Input";
|
||||||
|
import Combobox from "@/components/ui/Combobox";
|
||||||
|
import { MARCAS, getModelos } from "@/lib/marcas-modelos";
|
||||||
|
|
||||||
interface Auto {
|
interface Auto {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -12,6 +14,7 @@ interface Auto {
|
|||||||
marca: string;
|
marca: string;
|
||||||
modelo: string;
|
modelo: string;
|
||||||
anio: number;
|
anio: number;
|
||||||
|
nroChasis?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function DashboardPage() {
|
export default function DashboardPage() {
|
||||||
@@ -19,7 +22,8 @@ export default function DashboardPage() {
|
|||||||
const [autos, setAutos] = useState<Auto[]>([]);
|
const [autos, setAutos] = useState<Auto[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [mostrarForm, setMostrarForm] = useState(false);
|
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 [guardando, setGuardando] = useState(false);
|
||||||
const [errorForm, setErrorForm] = useState("");
|
const [errorForm, setErrorForm] = useState("");
|
||||||
|
|
||||||
@@ -51,7 +55,7 @@ export default function DashboardPage() {
|
|||||||
setGuardando(false);
|
setGuardando(false);
|
||||||
if (!res.ok) { setErrorForm(data.error || "Error al guardar"); return; }
|
if (!res.ok) { setErrorForm(data.error || "Error al guardar"); return; }
|
||||||
setMostrarForm(false);
|
setMostrarForm(false);
|
||||||
setForm({ patente: "", marca: "", modelo: "", anio: "" });
|
setForm({ patente: "", marca: "", modelo: "", anio: "", nroChasis: "" });
|
||||||
cargarAutos();
|
cargarAutos();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,10 +112,30 @@ export default function DashboardPage() {
|
|||||||
<Card title="Agregar auto">
|
<Card title="Agregar auto">
|
||||||
<form onSubmit={agregarAuto} className="flex flex-col gap-4">
|
<form onSubmit={agregarAuto} className="flex flex-col gap-4">
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<Input id="marca" label="Marca" placeholder="Ford" value={form.marca} onChange={set("marca")} required />
|
<Combobox
|
||||||
<Input id="modelo" label="Modelo" placeholder="Focus" value={form.modelo} onChange={set("modelo")} required />
|
id="marca"
|
||||||
|
label="Marca"
|
||||||
|
options={MARCAS}
|
||||||
|
value={form.marca}
|
||||||
|
onChange={(v) => setForm((f) => ({ ...f, marca: v, modelo: "" }))}
|
||||||
|
onSelect={(v) => setForm((f) => ({ ...f, marca: v, modelo: "" }))}
|
||||||
|
placeholder="Ford"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<Combobox
|
||||||
|
id="modelo"
|
||||||
|
label="Modelo"
|
||||||
|
options={modelosDisponibles}
|
||||||
|
value={form.modelo}
|
||||||
|
onChange={(v) => 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
|
||||||
|
/>
|
||||||
<Input id="anio" label="Año" type="number" placeholder="2018" value={form.anio} onChange={set("anio")} required min={1960} max={new Date().getFullYear() + 1} />
|
<Input id="anio" label="Año" type="number" placeholder="2018" value={form.anio} onChange={set("anio")} required min={1960} max={new Date().getFullYear() + 1} />
|
||||||
<Input id="patente" label="Patente" placeholder="AB123CD" value={form.patente} onChange={set("patente")} required className="uppercase" />
|
<Input id="patente" label="Patente" placeholder="AB123CD" value={form.patente} onChange={set("patente")} required className="uppercase" />
|
||||||
|
<Input id="nroChasis" label="Nº Chasis (opcional)" placeholder="8AFZZZ11ZYM569874" value={form.nroChasis} onChange={set("nroChasis")} className="col-span-2" />
|
||||||
</div>
|
</div>
|
||||||
{errorForm && <p className="text-sm text-red-500">{errorForm}</p>}
|
{errorForm && <p className="text-sm text-red-500">{errorForm}</p>}
|
||||||
<div className="flex gap-2 justify-end">
|
<div className="flex gap-2 justify-end">
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ function TurnosContent() {
|
|||||||
const [slots, setSlots] = useState<Slot[]>([]);
|
const [slots, setSlots] = useState<Slot[]>([]);
|
||||||
const [slotSel, setSlotSel] = useState<Slot | null>(null);
|
const [slotSel, setSlotSel] = useState<Slot | null>(null);
|
||||||
const [loadingSlots, setLoadingSlots] = useState(false);
|
const [loadingSlots, setLoadingSlots] = useState(false);
|
||||||
|
const [kilometros, setKilometros] = useState("");
|
||||||
const [reservando, setReservando] = useState(false);
|
const [reservando, setReservando] = useState(false);
|
||||||
const [turnoCreado, setTurnoCreado] = useState<Turno | null>(null);
|
const [turnoCreado, setTurnoCreado] = useState<Turno | null>(null);
|
||||||
const [misTurnos, setMisTurnos] = useState<Turno[]>([]);
|
const [misTurnos, setMisTurnos] = useState<Turno[]>([]);
|
||||||
@@ -56,12 +57,12 @@ function TurnosContent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function reservar() {
|
async function reservar() {
|
||||||
if (!slotSel || !servicioSel || !autoId) return;
|
if (!slotSel || !servicioSel || !autoId || !kilometros) return;
|
||||||
setReservando(true);
|
setReservando(true);
|
||||||
const res = await fetch("/api/cliente/turnos", {
|
const res = await fetch("/api/cliente/turnos", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
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();
|
const data = await res.json();
|
||||||
setReservando(false);
|
setReservando(false);
|
||||||
@@ -189,9 +190,23 @@ function TurnosContent() {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="mt-2">
|
||||||
|
<label htmlFor="kilometros" className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
|
Kilometraje actual <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="kilometros"
|
||||||
|
type="number"
|
||||||
|
min={0}
|
||||||
|
placeholder="Ej: 85000"
|
||||||
|
value={kilometros}
|
||||||
|
onChange={(e) => 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"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<Button
|
<Button
|
||||||
onClick={reservar}
|
onClick={reservar}
|
||||||
disabled={!slotSel}
|
disabled={!slotSel || !kilometros}
|
||||||
loading={reservando}
|
loading={reservando}
|
||||||
className="w-full mt-2"
|
className="w-full mt-2"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
"use client";
|
||||||
|
import { useState, useRef, useEffect } from "react";
|
||||||
|
|
||||||
|
interface ComboboxProps {
|
||||||
|
id?: string;
|
||||||
|
label?: string;
|
||||||
|
options: string[];
|
||||||
|
value: string;
|
||||||
|
onChange: (value: string) => void;
|
||||||
|
onSelect?: (value: string) => void;
|
||||||
|
placeholder?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
required?: boolean;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Combobox({
|
||||||
|
id, label, options, value, onChange, onSelect,
|
||||||
|
placeholder, disabled, required, className,
|
||||||
|
}: ComboboxProps) {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const filtered = value
|
||||||
|
? options.filter((o) => o.toLowerCase().includes(value.toLowerCase())).slice(0, 60)
|
||||||
|
: options.slice(0, 60);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function handleClick(e: MouseEvent) {
|
||||||
|
if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);
|
||||||
|
}
|
||||||
|
document.addEventListener("mousedown", handleClick);
|
||||||
|
return () => document.removeEventListener("mousedown", handleClick);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function handleSelect(option: string) {
|
||||||
|
onChange(option);
|
||||||
|
onSelect?.(option);
|
||||||
|
setOpen(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`relative ${className ?? ""}`} ref={ref}>
|
||||||
|
{label && (
|
||||||
|
<label htmlFor={id} className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
|
{label} {required && <span className="text-red-500">*</span>}
|
||||||
|
</label>
|
||||||
|
)}
|
||||||
|
<input
|
||||||
|
id={id}
|
||||||
|
type="text"
|
||||||
|
value={value}
|
||||||
|
onChange={(e) => { onChange(e.target.value); setOpen(true); }}
|
||||||
|
onFocus={() => setOpen(true)}
|
||||||
|
placeholder={placeholder}
|
||||||
|
disabled={disabled}
|
||||||
|
required={required}
|
||||||
|
autoComplete="off"
|
||||||
|
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 disabled:bg-gray-100 disabled:text-gray-400 disabled:cursor-not-allowed"
|
||||||
|
/>
|
||||||
|
{open && !disabled && filtered.length > 0 && (
|
||||||
|
<ul className="absolute z-50 w-full mt-1 bg-white border border-gray-200 rounded-lg shadow-lg max-h-52 overflow-y-auto">
|
||||||
|
{filtered.map((option) => (
|
||||||
|
<li
|
||||||
|
key={option}
|
||||||
|
onMouseDown={() => handleSelect(option)}
|
||||||
|
className="px-3 py-2 text-sm cursor-pointer hover:bg-blue-50 hover:text-blue-700"
|
||||||
|
>
|
||||||
|
{option}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
export const MARCAS_MODELOS: Record<string, string[]> = {
|
||||||
|
"Acura": ["ILX", "Integra", "MDX", "RDX", "TLX"],
|
||||||
|
"Alfa Romeo": ["147", "156", "159", "Brera", "Giulia", "Giulietta", "GT", "MiTo", "Spider", "Stelvio", "Tonale"],
|
||||||
|
"Aston Martin": ["DB11", "DB9", "DBX", "DBS", "Rapide", "Vantage", "Virage"],
|
||||||
|
"Audi": ["A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "e-tron", "e-tron GT", "Q2", "Q3", "Q4 e-tron", "Q5", "Q7", "Q8", "R8", "RS3", "RS4", "RS5", "RS6", "RS7", "S3", "S4", "S5", "S6", "S7", "S8", "SQ5", "SQ7", "SQ8", "TT", "TT RS", "TTS"],
|
||||||
|
"Bentley": ["Bentayga", "Continental GT", "Continental GTC", "Flying Spur", "Mulsanne"],
|
||||||
|
"BMW": ["116i", "118i", "120i", "218i", "220i", "316i", "318i", "320i", "325i", "330i", "335i", "418i", "420i", "430i", "440i", "520i", "525i", "530i", "540i", "545i", "550i", "630i", "740i", "750i", "M2", "M3", "M4", "M5", "M8", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "Z4"],
|
||||||
|
"BYD": ["Atto 3", "Dolphin", "Han", "Seal", "Song", "Song Plus", "Tang", "Yuan Plus"],
|
||||||
|
"Buick": ["Enclave", "Encore", "Encore GX", "Envision", "LaCrosse", "Regal"],
|
||||||
|
"Cadillac": ["ATS", "CT4", "CT5", "CTS", "Escalade", "SRX", "XT4", "XT5", "XT6"],
|
||||||
|
"Chery": ["Arrizo 5", "Arrizo 5 Pro", "Arrizo 6", "Arrizo 6 Pro", "Tiggo 2", "Tiggo 2 Pro", "Tiggo 3", "Tiggo 3X", "Tiggo 4", "Tiggo 4 Pro", "Tiggo 5X", "Tiggo 7", "Tiggo 7 Pro", "Tiggo 8", "Tiggo 8 Pro"],
|
||||||
|
"Chevrolet": ["Agile", "Blazer", "Bolt", "Camaro", "Captiva", "Colorado", "Corvette", "Cruze", "Equinox", "Montana", "Onix", "Onix Plus", "S10", "Silverado", "Spin", "Tahoe", "Tracker", "Trailblazer", "Traverse", "Trax"],
|
||||||
|
"Chrysler": ["300", "300C", "Pacifica", "Sebring", "Voyager"],
|
||||||
|
"Citroën": ["Berlingo", "C-Elysée", "C1", "C2", "C3", "C3 Aircross", "C4", "C4 Cactus", "C5", "C5 Aircross", "C5 X", "C6", "C8", "DS3", "DS4", "DS5", "Jumper", "Jumpy", "Nemo", "SpaceTourer", "Xantia", "Xsara"],
|
||||||
|
"Dacia": ["Duster", "Jogger", "Logan", "Sandero", "Spring"],
|
||||||
|
"Dodge": ["Challenger", "Charger", "Dart", "Durango", "Journey", "RAM 1000", "RAM 1500", "RAM 2500", "Viper"],
|
||||||
|
"DS": ["DS 3", "DS 3 Crossback", "DS 4", "DS 5", "DS 7", "DS 7 Crossback", "DS 9"],
|
||||||
|
"Ferrari": ["296 GTB", "296 GTS", "812 Competizione", "812 Superfast", "F8 Spider", "F8 Tributo", "GTC4Lusso", "Portofino", "Portofino M", "Purosangue", "Roma", "SF90 Spider", "SF90 Stradale"],
|
||||||
|
"Fiat": ["124 Spider", "500", "500L", "500X", "Argo", "Bravo", "Cronos", "Doblo", "Ducato", "Fiorino", "Linea", "Mobi", "Palio", "Punto", "Qubo", "Siena", "Strada", "Toro", "Tipo", "Uno"],
|
||||||
|
"Ford": ["Bronco", "Bronco Sport", "C-Max", "EcoSport", "Edge", "Escape", "Expedition", "Explorer", "F-150", "F-150 Lightning", "Fiesta", "Focus", "Fusion", "Galaxy", "Ka", "Ka+", "Kuga", "Maverick", "Mondeo", "Mustang", "Mustang Mach-E", "Puma", "Ranger", "S-Max", "Territory", "Transit", "Transit Connect", "Transit Custom"],
|
||||||
|
"Geely": ["Atlas", "Coolray", "Emgrand", "Monjaro", "Okavango", "Preface", "Tugella"],
|
||||||
|
"Genesis": ["G70", "G80", "G90", "GV70", "GV80"],
|
||||||
|
"GMC": ["Acadia", "Canyon", "Envoy", "Sierra", "Terrain", "Yukon"],
|
||||||
|
"Great Wall": ["Cannon", "Haval H1", "Haval H2", "Haval H4", "Haval H6", "Haval H9", "Haval Jolion", "Ora Funky Cat", "Poer", "Wingle"],
|
||||||
|
"Haval": ["F7", "H1", "H2", "H4", "H6", "H9", "Jolion"],
|
||||||
|
"Honda": ["Accord", "City", "Civic", "CR-V", "CR-Z", "Element", "Fit", "HR-V", "Insight", "Jazz", "Legend", "Odyssey", "Passport", "Pilot", "Ridgeline", "WR-V"],
|
||||||
|
"Hummer": ["EV", "H1", "H2", "H3"],
|
||||||
|
"Hyundai": ["Accent", "Azera", "Creta", "Elantra", "Getz", "HB20", "i10", "i20", "i30", "i40", "Ioniq", "Ioniq 5", "Ioniq 6", "ix35", "Kona", "Santa Cruz", "Santa Fe", "Sonata", "Terracan", "Tucson", "Veloster", "Venue"],
|
||||||
|
"Infiniti": ["Q30", "Q40", "Q50", "Q60", "Q70", "QX30", "QX50", "QX55", "QX60", "QX70", "QX80"],
|
||||||
|
"JAC": ["E10X", "J7", "JS4", "S2", "S3", "S4", "S7", "T6", "T8"],
|
||||||
|
"Jaguar": ["E-Pace", "F-Pace", "F-Type", "I-Pace", "XE", "XF", "XJ"],
|
||||||
|
"Jeep": ["Avenger", "Cherokee", "Commander", "Compass", "Gladiator", "Grand Cherokee", "Grand Cherokee 4xe", "Renegade", "Wagoneer", "Wrangler"],
|
||||||
|
"Kia": ["Carnival", "Cerato", "Ceed", "EV6", "Picanto", "Rio", "Seltos", "Sonet", "Sorento", "Soul", "Sportage", "Stinger", "Stonic", "Telluride"],
|
||||||
|
"Lamborghini": ["Aventador", "Huracán", "Revuelto", "Urus"],
|
||||||
|
"Land Rover": ["Defender", "Discovery", "Discovery Sport", "Freelander", "Range Rover", "Range Rover Evoque", "Range Rover Sport", "Range Rover Velar"],
|
||||||
|
"Lexus": ["CT", "ES", "GS", "GX", "IS", "LC", "LS", "LX", "NX", "RC", "RX", "UX"],
|
||||||
|
"Lifan": ["530", "620", "720", "820", "X50", "X60", "X70", "X80"],
|
||||||
|
"Lincoln": ["Aviator", "Corsair", "MKC", "MKT", "MKX", "MKZ", "Nautilus", "Navigator"],
|
||||||
|
"Lotus": ["Eletre", "Emira", "Evija"],
|
||||||
|
"Maserati": ["Ghibli", "GranCabrio", "GranTurismo", "Grecale", "Levante", "MC20", "Quattroporte"],
|
||||||
|
"Mazda": ["2", "3", "6", "BT-50", "CX-3", "CX-30", "CX-5", "CX-50", "CX-60", "CX-9", "MX-30", "MX-5", "RX-8"],
|
||||||
|
"McLaren": ["570S", "600LT", "650S", "720S", "750S", "Artura", "GT"],
|
||||||
|
"Mercedes-Benz": ["A 180", "A 200", "A 250", "AMG GT", "B 200", "C 180", "C 200", "C 300", "CLA 200", "CLA 250", "CLC 200", "CLE 200", "CLK 200", "CLS 350", "E 200", "E 250", "E 300", "E 350", "G 500", "G 63 AMG", "GLA 200", "GLA 250", "GLB 200", "GLC 200", "GLC 300", "GLE 350", "GLS 400", "ML 350", "S 400", "S 500", "Sprinter", "Vito"],
|
||||||
|
"MG": ["EZS", "GS", "HS", "MG3", "MG5", "RX5", "ZS", "ZS EV"],
|
||||||
|
"Mini": ["Clubman", "Convertible", "Cooper", "Cooper S", "Countryman", "JCW", "Paceman"],
|
||||||
|
"Mitsubishi": ["ASX", "Eclipse Cross", "Galant", "L200", "Lancer", "Montero", "Outlander", "Pajero", "Pajero Sport"],
|
||||||
|
"Nissan": ["370Z", "Frontier", "GT-R", "Juke", "Kicks", "Leaf", "March", "Micra", "Murano", "Note", "Pathfinder", "Qashqai", "Sentra", "Tiida", "Versa", "X-Trail"],
|
||||||
|
"Opel": ["Astra", "Corsa", "Crossland", "Grandland", "Insignia", "Meriva", "Mokka", "Vectra", "Vivaro", "Zafira"],
|
||||||
|
"Peugeot": ["1007", "107", "108", "2008", "206", "207", "208", "3008", "301", "307", "308", "408", "5008", "508", "Boxer", "Expert", "Partner", "Rifter"],
|
||||||
|
"Porsche": ["718 Boxster", "718 Cayman", "911", "Cayenne", "Macan", "Panamera", "Taycan"],
|
||||||
|
"RAM": ["700", "1000", "1500", "2500", "3500", "Promaster"],
|
||||||
|
"Renault": ["Alaskan", "Arkana", "Austral", "Captur", "Clio", "Duster", "Fluence", "Kadjar", "Kangoo", "Koleos", "Laguna", "Logan", "Master", "Megane", "Rafale", "Sandero", "Scenic", "Symbol", "Trafic", "Zoe"],
|
||||||
|
"Rolls-Royce": ["Cullinan", "Dawn", "Ghost", "Phantom", "Silver Shadow", "Spectre", "Wraith"],
|
||||||
|
"SEAT": ["Arona", "Ateca", "Ibiza", "León", "Tarraco"],
|
||||||
|
"Škoda": ["Fabia", "Kamiq", "Karoq", "Kodiaq", "Octavia", "Scala", "Superb"],
|
||||||
|
"Smart": ["EQ fortwo", "EQ forfour", "forfour", "fortwo"],
|
||||||
|
"Subaru": ["Ascent", "BRZ", "Crosstrek", "Forester", "Impreza", "Legacy", "Outback", "Solterra", "WRX", "XV"],
|
||||||
|
"Suzuki": ["Baleno", "Celerio", "Dzire", "Ertiga", "Grand Vitara", "Ignis", "Jimny", "S-Cross", "Splash", "SX4", "Swift", "Vitara"],
|
||||||
|
"Tesla": ["Cybertruck", "Model 3", "Model S", "Model X", "Model Y", "Roadster"],
|
||||||
|
"Toyota": ["4Runner", "86", "Aqua", "Avalon", "C-HR", "Camry", "Corolla", "Corolla Cross", "Crown", "Etios", "Fortuner", "GR86", "Hilux", "Land Cruiser", "Land Cruiser Prado", "Prius", "RAV4", "Rush", "Sequoia", "SW4", "Tacoma", "Tundra", "Vios", "Yaris"],
|
||||||
|
"Volkswagen": ["Amarok", "Bora", "Caddy", "Crafter", "Fox", "Gol", "Golf", "Jetta", "Nivus", "Passat", "Polo", "Saveiro", "Suran", "T-Cross", "T-Roc", "Taigo", "Taos", "Tiguan", "Touareg", "Touran", "Transporter", "Up!", "Vento", "Virtus"],
|
||||||
|
"Volvo": ["C30", "C40", "S40", "S60", "S80", "S90", "V40", "V60", "V90", "XC40", "XC60", "XC70", "XC90"],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MARCAS = Object.keys(MARCAS_MODELOS).sort((a, b) => a.localeCompare(b));
|
||||||
|
|
||||||
|
export function getModelos(marca: string): string[] {
|
||||||
|
return MARCAS_MODELOS[marca] ?? [];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user