fix: fixed api error (duplicate unique key) and dialog closing

This commit is contained in:
Mouad Lahlal 2025-11-23 15:32:11 +01:00
parent fb6982da6b
commit fb57ae2701
7 changed files with 1675 additions and 337 deletions

1895
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -39,7 +39,7 @@
"@tailwindcss/postcss": "^4", "@tailwindcss/postcss": "^4",
"@types/leaflet": "^1.9.21", "@types/leaflet": "^1.9.21",
"@types/node": "^20", "@types/node": "^20",
"@types/react": "^19", "@types/react": "^19.2.6",
"@types/react-dom": "^19", "@types/react-dom": "^19",
"prisma": "^6.18.0", "prisma": "^6.18.0",
"tailwindcss": "^4", "tailwindcss": "^4",

View file

@ -1,4 +1,4 @@
import { Modello, PrismaClient } from "@/generated/prisma"; import { Cliente, Modello, PrismaClient, Prisma } from "@/generated/prisma";
export async function GET(request: Request) { export async function GET(request: Request) {
const prisma = new PrismaClient(); const prisma = new PrismaClient();
@ -35,8 +35,7 @@ export async function POST(request: Request) {
const data = await request.json(); const data = await request.json();
const [lat, lon] = extractLatLonFromGmapsUrl(data.sede_url); const [lat, lon] = extractLatLonFromGmapsUrl(data.sede_url);
await prisma.cliente.create({ const cliente = {
data: {
contratto: data.contratto, contratto: data.contratto,
email: data.email, email: data.email,
partita_iva: data.partita_iva, partita_iva: data.partita_iva,
@ -46,21 +45,22 @@ export async function POST(request: Request) {
telefono: data.telefono, telefono: data.telefono,
lat: lat, lat: lat,
lon: lon, lon: lon,
/*registratori: { };
create: {
id: "80E1758414",
modello: Modello.FORM100,
interventi: {
create: {
data: new Date("2025-10-30"),
fattura: true,
lavoro: "Boh, cazzeggiato tutto il tempo",
},
},
},
},*/
},
});
return Response.json({ message: "fatto bastardo" }); try {
await prisma.cliente.create({
data: cliente,
});
} catch (e) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (e.code == "P2002") {
return Response.json(
{ message: "Il cliente esista già" },
{ status: 400 },
);
}
}
}
return Response.json({ message: "Cliente creato" });
} }

View file

@ -12,9 +12,11 @@ import {
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Spinner } from "@/components/ui/spinner";
import { useState } from "react"; import { useState } from "react";
const AddClientDialog = () => { const AddClientDialog = () => {
const [wait, setWait] = useState(false);
const [open, setOpen] = useState<Boolean>(false); const [open, setOpen] = useState<Boolean>(false);
const [nome, setNome] = useState(""); const [nome, setNome] = useState("");
const [ragione_sociale, setRagione_sociale] = useState(""); const [ragione_sociale, setRagione_sociale] = useState("");
@ -120,6 +122,8 @@ const AddClientDialog = () => {
</DialogClose> </DialogClose>
<Button <Button
onClick={async () => { onClick={async () => {
setWait(true);
const res = await fetch("/api/clienti", { const res = await fetch("/api/clienti", {
method: "POST", method: "POST",
body: JSON.stringify({ body: JSON.stringify({
@ -134,12 +138,16 @@ const AddClientDialog = () => {
}), }),
}); });
setWait(false);
if (res.status == 200) { if (res.status == 200) {
setOpen(false); setOpen(false);
} }
}} }}
type="submit" type="submit"
disabled={wait}
> >
{wait ? <Spinner /> : <></>}
Aggiungi Aggiungi
</Button> </Button>
</DialogFooter> </DialogFooter>

View file

@ -24,14 +24,15 @@ import { Checkbox } from "@/components/ui/checkbox";
const AddInterventoDialog = ({ id }: { id: string }) => { const AddInterventoDialog = ({ id }: { id: string }) => {
//const [nome, setNome] = useState(""); //const [nome, setNome] = useState("");
const [open, setOpen] = useState(false); const [openDialog, setOpenDialog] = useState(false);
const [openDatePicker, setOpenDatePicker] = useState(false);
const [data, setData] = useState<Date | undefined>(new Date()); const [data, setData] = useState<Date | undefined>(new Date());
const [lavoro, setLavoro] = useState<string>(""); const [lavoro, setLavoro] = useState<string>("");
const [fattura, setFattura] = useState<Boolean>(false); const [fattura, setFattura] = useState<Boolean>(false);
return ( return (
<div> <div>
<Dialog> <Dialog open={openDialog} onOpenChange={setOpenDialog}>
<form className="z-10"> <form className="z-10">
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
@ -57,8 +58,8 @@ const AddInterventoDialog = ({ id }: { id: string }) => {
<div className="grid gap-3"> <div className="grid gap-3">
<Label htmlFor="date">Data</Label> <Label htmlFor="date">Data</Label>
<DatePicker <DatePicker
open={open} open={openDatePicker}
setOpen={setOpen} setOpen={setOpenDatePicker}
date={data} date={data}
setDate={setData} setDate={setData}
/> />
@ -91,8 +92,8 @@ const AddInterventoDialog = ({ id }: { id: string }) => {
<Button variant="outline">Cancella</Button> <Button variant="outline">Cancella</Button>
</DialogClose> </DialogClose>
<Button <Button
onClick={async () => onClick={async () => {
await fetch("/api/interventi", { const res = await fetch("/api/interventi", {
method: "POST", method: "POST",
body: JSON.stringify({ body: JSON.stringify({
id: id, id: id,
@ -100,8 +101,11 @@ const AddInterventoDialog = ({ id }: { id: string }) => {
fattura: fattura, fattura: fattura,
lavoro: lavoro, lavoro: lavoro,
}), }),
}) });
if (res.status == 200) {
setOpenDialog(false);
} }
}}
type="submit" type="submit"
> >
Aggiungi Aggiungi

View file

@ -25,6 +25,7 @@ import ModelPicker from "./model-picker";
const AddRegistratoreDialog = ({ id }: { id: Number }) => { const AddRegistratoreDialog = ({ id }: { id: Number }) => {
//const [nome, setNome] = useState(""); //const [nome, setNome] = useState("");
const [openDialog, setOpenDialog] = useState(false);
const [openData, setOpenData] = useState(false); const [openData, setOpenData] = useState(false);
const [openModello, setOpenModello] = useState(false); const [openModello, setOpenModello] = useState(false);
const [data, setData] = useState<Date | undefined>(); const [data, setData] = useState<Date | undefined>();
@ -53,7 +54,7 @@ const AddRegistratoreDialog = ({ id }: { id: Number }) => {
return ( return (
<div> <div>
<Dialog> <Dialog open={openDialog} onOpenChange={setOpenDialog}>
<form className="z-10"> <form className="z-10">
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
@ -106,8 +107,8 @@ const AddRegistratoreDialog = ({ id }: { id: Number }) => {
<Button variant="outline">Cancella</Button> <Button variant="outline">Cancella</Button>
</DialogClose> </DialogClose>
<Button <Button
onClick={async () => onClick={async () => {
await fetch("/api/registratori", { const res = await fetch("/api/registratori", {
method: "POST", method: "POST",
body: JSON.stringify({ body: JSON.stringify({
id: id, id: id,
@ -115,8 +116,12 @@ const AddRegistratoreDialog = ({ id }: { id: Number }) => {
data: data, data: data,
modello: modello, modello: modello,
}), }),
}) });
if (res.status == 200) {
setOpenDialog(false);
} }
}}
type="submit" type="submit"
> >
Aggiungi Aggiungi

View file

@ -0,0 +1,16 @@
import { Loader2Icon } from "lucide-react"
import { cn } from "@/lib/utils"
function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
return (
<Loader2Icon
role="status"
aria-label="Loading"
className={cn("size-4 animate-spin", className)}
{...props}
/>
)
}
export { Spinner }