fix: fixed api error (duplicate unique key) and dialog closing
This commit is contained in:
parent
fb6982da6b
commit
fb57ae2701
7 changed files with 1675 additions and 337 deletions
1895
package-lock.json
generated
1895
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -39,7 +39,7 @@
|
|||
"@tailwindcss/postcss": "^4",
|
||||
"@types/leaflet": "^1.9.21",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^19",
|
||||
"@types/react": "^19.2.6",
|
||||
"@types/react-dom": "^19",
|
||||
"prisma": "^6.18.0",
|
||||
"tailwindcss": "^4",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Modello, PrismaClient } from "@/generated/prisma";
|
||||
import { Cliente, Modello, PrismaClient, Prisma } from "@/generated/prisma";
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const prisma = new PrismaClient();
|
||||
|
|
@ -35,32 +35,32 @@ export async function POST(request: Request) {
|
|||
const data = await request.json();
|
||||
const [lat, lon] = extractLatLonFromGmapsUrl(data.sede_url);
|
||||
|
||||
await prisma.cliente.create({
|
||||
data: {
|
||||
contratto: data.contratto,
|
||||
email: data.email,
|
||||
partita_iva: data.partita_iva,
|
||||
ragione_sociale: data.ragione_sociale,
|
||||
sede: data.sede,
|
||||
sede_url: data.sede_url,
|
||||
telefono: data.telefono,
|
||||
lat: lat,
|
||||
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",
|
||||
},
|
||||
},
|
||||
},
|
||||
},*/
|
||||
},
|
||||
});
|
||||
const cliente = {
|
||||
contratto: data.contratto,
|
||||
email: data.email,
|
||||
partita_iva: data.partita_iva,
|
||||
ragione_sociale: data.ragione_sociale,
|
||||
sede: data.sede,
|
||||
sede_url: data.sede_url,
|
||||
telefono: data.telefono,
|
||||
lat: lat,
|
||||
lon: lon,
|
||||
};
|
||||
|
||||
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" });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,11 @@ import {
|
|||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { useState } from "react";
|
||||
|
||||
const AddClientDialog = () => {
|
||||
const [wait, setWait] = useState(false);
|
||||
const [open, setOpen] = useState<Boolean>(false);
|
||||
const [nome, setNome] = useState("");
|
||||
const [ragione_sociale, setRagione_sociale] = useState("");
|
||||
|
|
@ -120,6 +122,8 @@ const AddClientDialog = () => {
|
|||
</DialogClose>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
setWait(true);
|
||||
|
||||
const res = await fetch("/api/clienti", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
|
|
@ -134,12 +138,16 @@ const AddClientDialog = () => {
|
|||
}),
|
||||
});
|
||||
|
||||
setWait(false);
|
||||
|
||||
if (res.status == 200) {
|
||||
setOpen(false);
|
||||
}
|
||||
}}
|
||||
type="submit"
|
||||
disabled={wait}
|
||||
>
|
||||
{wait ? <Spinner /> : <></>}
|
||||
Aggiungi
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
|
|
|||
|
|
@ -24,14 +24,15 @@ import { Checkbox } from "@/components/ui/checkbox";
|
|||
|
||||
const AddInterventoDialog = ({ id }: { id: string }) => {
|
||||
//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 [lavoro, setLavoro] = useState<string>("");
|
||||
const [fattura, setFattura] = useState<Boolean>(false);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Dialog>
|
||||
<Dialog open={openDialog} onOpenChange={setOpenDialog}>
|
||||
<form className="z-10">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
|
|
@ -57,8 +58,8 @@ const AddInterventoDialog = ({ id }: { id: string }) => {
|
|||
<div className="grid gap-3">
|
||||
<Label htmlFor="date">Data</Label>
|
||||
<DatePicker
|
||||
open={open}
|
||||
setOpen={setOpen}
|
||||
open={openDatePicker}
|
||||
setOpen={setOpenDatePicker}
|
||||
date={data}
|
||||
setDate={setData}
|
||||
/>
|
||||
|
|
@ -91,8 +92,8 @@ const AddInterventoDialog = ({ id }: { id: string }) => {
|
|||
<Button variant="outline">Cancella</Button>
|
||||
</DialogClose>
|
||||
<Button
|
||||
onClick={async () =>
|
||||
await fetch("/api/interventi", {
|
||||
onClick={async () => {
|
||||
const res = await fetch("/api/interventi", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
id: id,
|
||||
|
|
@ -100,8 +101,11 @@ const AddInterventoDialog = ({ id }: { id: string }) => {
|
|||
fattura: fattura,
|
||||
lavoro: lavoro,
|
||||
}),
|
||||
})
|
||||
}
|
||||
});
|
||||
if (res.status == 200) {
|
||||
setOpenDialog(false);
|
||||
}
|
||||
}}
|
||||
type="submit"
|
||||
>
|
||||
Aggiungi
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import ModelPicker from "./model-picker";
|
|||
|
||||
const AddRegistratoreDialog = ({ id }: { id: Number }) => {
|
||||
//const [nome, setNome] = useState("");
|
||||
const [openDialog, setOpenDialog] = useState(false);
|
||||
const [openData, setOpenData] = useState(false);
|
||||
const [openModello, setOpenModello] = useState(false);
|
||||
const [data, setData] = useState<Date | undefined>();
|
||||
|
|
@ -53,7 +54,7 @@ const AddRegistratoreDialog = ({ id }: { id: Number }) => {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<Dialog>
|
||||
<Dialog open={openDialog} onOpenChange={setOpenDialog}>
|
||||
<form className="z-10">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
|
|
@ -106,8 +107,8 @@ const AddRegistratoreDialog = ({ id }: { id: Number }) => {
|
|||
<Button variant="outline">Cancella</Button>
|
||||
</DialogClose>
|
||||
<Button
|
||||
onClick={async () =>
|
||||
await fetch("/api/registratori", {
|
||||
onClick={async () => {
|
||||
const res = await fetch("/api/registratori", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
id: id,
|
||||
|
|
@ -115,8 +116,12 @@ const AddRegistratoreDialog = ({ id }: { id: Number }) => {
|
|||
data: data,
|
||||
modello: modello,
|
||||
}),
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
if (res.status == 200) {
|
||||
setOpenDialog(false);
|
||||
}
|
||||
}}
|
||||
type="submit"
|
||||
>
|
||||
Aggiungi
|
||||
|
|
|
|||
16
src/components/ui/spinner.tsx
Normal file
16
src/components/ui/spinner.tsx
Normal 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 }
|
||||
Loading…
Reference in a new issue