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",
|
"@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",
|
||||||
|
|
|
||||||
|
|
@ -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" });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
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