feat: add EditServizioAdmin component and integrate into ServizioActions
This commit is contained in:
parent
47ff703be8
commit
4982d064e3
2 changed files with 343 additions and 2 deletions
|
|
@ -25,7 +25,7 @@ import {
|
|||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "~/components/ui/alert-dialog";
|
||||
import { Calculator, ClockAlert, Plus } from "lucide-react";
|
||||
import { Calculator, ClockAlert, Plus, Wrench } from "lucide-react";
|
||||
import { FormNewServizio, type FormValues } from "~/forms/FormNewServizio";
|
||||
import {
|
||||
Credenza,
|
||||
|
|
@ -41,6 +41,10 @@ import { useState } from "react";
|
|||
import { useServizio } from "~/providers/ServizioProvider";
|
||||
import type { ServizioServizioId } from "~/schemas/public/Servizio";
|
||||
import type { UsersId } from "~/schemas/public/Users";
|
||||
import {
|
||||
FormEditServizio,
|
||||
type FormValues as EditFormValues,
|
||||
} from "~/forms/FormEditServizioAdmin";
|
||||
|
||||
export const ServizioActions = () => {
|
||||
const { servizio, isAdmin, userId } = useServizio();
|
||||
|
|
@ -62,7 +66,10 @@ export const ServizioActions = () => {
|
|||
</>
|
||||
)}
|
||||
{isAdmin && (
|
||||
<AddAnnuncio servizioId={servizio.servizio_id} userId={userId} />
|
||||
<>
|
||||
<AddAnnuncio servizioId={servizio.servizio_id} userId={userId} />
|
||||
<EditServizioAdmin />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
@ -306,3 +313,63 @@ const EditPreferenze = () => {
|
|||
</Credenza>
|
||||
);
|
||||
};
|
||||
|
||||
const EditServizioAdmin = () => {
|
||||
const { servizioId, userId } = useServizio();
|
||||
const [open, setOpen] = useState(false);
|
||||
const { data, isLoading } = api.servizio.getServizio.useQuery({ servizioId });
|
||||
const utils = api.useUtils();
|
||||
|
||||
const { mutate: update } = api.servizio.updateServizio.useMutation({
|
||||
onSuccess: async () => {
|
||||
toast.success("Servizio modificato con successo");
|
||||
await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
|
||||
await utils.servizio.getServizio.invalidate({ servizioId });
|
||||
await utils.servizio.getCompatibileAnnunci.invalidate({
|
||||
servizioId,
|
||||
});
|
||||
setOpen(false);
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(error.message);
|
||||
},
|
||||
});
|
||||
|
||||
function onSubmit(fields: EditFormValues) {
|
||||
update({
|
||||
servizioId,
|
||||
data: {
|
||||
...fields,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<Credenza open={open} onOpenChange={setOpen}>
|
||||
<CredenzaTrigger asChild>
|
||||
<Button
|
||||
aria-label="Modifica Servizio Admin"
|
||||
className="items-center gap-2"
|
||||
>
|
||||
<Wrench />
|
||||
Admin
|
||||
</Button>
|
||||
</CredenzaTrigger>
|
||||
<CredenzaContent className="max-h-[90vh] w-full sm:max-w-5xl">
|
||||
<CredenzaHeader>
|
||||
<CredenzaTitle>Modifica Servizio Admin</CredenzaTitle>
|
||||
<CredenzaDescription className="sr-only">
|
||||
Modifica
|
||||
</CredenzaDescription>
|
||||
</CredenzaHeader>
|
||||
<CredenzaBody className="max-h-[80vh] w-full overflow-y-auto pb-5">
|
||||
{isLoading ? (
|
||||
<LoadingPage />
|
||||
) : (
|
||||
<FormEditServizio initialData={data} onSubmit={onSubmit} />
|
||||
)}
|
||||
</CredenzaBody>
|
||||
</CredenzaContent>
|
||||
</Credenza>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
274
apps/infoalloggi/src/forms/FormEditServizioAdmin.tsx
Normal file
274
apps/infoalloggi/src/forms/FormEditServizioAdmin.tsx
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
import { z } from "zod/v4";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "~/components/custom_ui/form";
|
||||
import { useZodForm } from "~/lib/zodForm";
|
||||
import { Button } from "~/components/ui/button";
|
||||
import { useTranslation } from "~/providers/I18nProvider";
|
||||
import { cn } from "~/lib/utils";
|
||||
import { Switch } from "~/components/ui/switch";
|
||||
import type { Servizio } from "~/schemas/public/Servizio";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "~/components/ui/popover";
|
||||
import { format } from "date-fns";
|
||||
import { CalendarIcon, X } from "lucide-react";
|
||||
import { Calendar } from "~/components/ui/calendar";
|
||||
import { enUS, it } from "date-fns/locale";
|
||||
import { Label } from "~/components/ui/label";
|
||||
|
||||
const Schema = z.object({
|
||||
isSent: z.boolean(),
|
||||
decorrenza: z.date().nullable(),
|
||||
isInterrotto: z.boolean(),
|
||||
isOkAcconto: z.boolean(),
|
||||
isOkSaldo: z.boolean(),
|
||||
isOkConsulenza: z.boolean(),
|
||||
});
|
||||
|
||||
export type FormValues = z.infer<typeof Schema>;
|
||||
|
||||
export const FormEditServizio = ({
|
||||
initialData,
|
||||
onSubmit,
|
||||
}: {
|
||||
initialData: Servizio | undefined;
|
||||
onSubmit: (fields: FormValues) => void;
|
||||
}) => {
|
||||
// This can come from your database or API.
|
||||
let defaultValues: FormValues;
|
||||
|
||||
if (initialData) {
|
||||
defaultValues = {
|
||||
...initialData,
|
||||
};
|
||||
} else {
|
||||
defaultValues = {
|
||||
isSent: false,
|
||||
decorrenza: null,
|
||||
isInterrotto: false,
|
||||
isOkAcconto: false,
|
||||
isOkSaldo: false,
|
||||
isOkConsulenza: false,
|
||||
};
|
||||
}
|
||||
const { locale, t } = useTranslation();
|
||||
|
||||
z.config(z.locales[locale]());
|
||||
|
||||
const form = useZodForm(Schema, {
|
||||
defaultValues: defaultValues,
|
||||
});
|
||||
|
||||
const DatePickerLocale = locale === "it" ? it : enUS;
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8 px-0.5">
|
||||
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="isSent"
|
||||
render={({ field }) => (
|
||||
<FormItem className="w-full">
|
||||
<div className="flex flex-wrap items-center gap-x-2">
|
||||
<FormLabel htmlFor="isSent">Inviato</FormLabel>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
id="isSent"
|
||||
className="data-[state=checked]:bg-neutral-700"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</div>
|
||||
|
||||
<FormDescription>
|
||||
La mail di benvenuto al cliente è stata inviata
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="isInterrotto"
|
||||
render={({ field }) => (
|
||||
<FormItem className="w-full">
|
||||
<div className="flex flex-wrap items-center gap-x-2">
|
||||
<FormLabel htmlFor="isInterrotto">Interrotto</FormLabel>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
id="isInterrotto"
|
||||
className="data-[state=checked]:bg-neutral-700"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</div>
|
||||
|
||||
<FormDescription>Il servizio è interrotto</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="decorrenza"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex w-full flex-col">
|
||||
<div className="flex flex-wrap items-center gap-x-2">
|
||||
<FormLabel htmlFor="decorrenza">
|
||||
Decorrenza Servizio
|
||||
</FormLabel>
|
||||
<FormMessage />
|
||||
</div>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl>
|
||||
<Button
|
||||
variant={"outline"}
|
||||
id="decorrenza"
|
||||
className={cn(
|
||||
"h-[42px] w-full pl-3 text-left font-medium",
|
||||
!field.value && "text-muted-foreground",
|
||||
`text-primary dark:bg-primary rounded-lg border border-neutral-300 bg-white shadow-xs outline-hidden file:border-0 file:bg-transparent file:text-sm file:font-medium hover:border-neutral-400 focus:border-neutral-400 disabled:cursor-not-allowed disabled:opacity-50 aria-expanded:border-neutral-400 dark:border-neutral-500 dark:text-white dark:placeholder:text-neutral-400 dark:hover:border-neutral-400 dark:focus:border-transparent dark:aria-expanded:border-neutral-400`,
|
||||
)}
|
||||
>
|
||||
{field.value ? (
|
||||
format(field.value, "PPP", {
|
||||
locale: DatePickerLocale,
|
||||
})
|
||||
) : (
|
||||
<span>{t.anagrafica.scegli_data}</span>
|
||||
)}
|
||||
<CalendarIcon className="ml-auto size-4 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-auto p-0" align="start">
|
||||
<Calendar
|
||||
locale={DatePickerLocale}
|
||||
endMonth={new Date()}
|
||||
mode="single"
|
||||
defaultMonth={field.value || new Date()}
|
||||
captionLayout="dropdown"
|
||||
selected={field.value || undefined}
|
||||
onSelect={field.onChange}
|
||||
disabled={(date) =>
|
||||
date > new Date() || date < new Date("1900-01-01")
|
||||
}
|
||||
// eslint-disable-next-line jsx-a11y/no-autofocus
|
||||
autoFocus
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex flex-col items-start gap-2">
|
||||
<Label htmlFor="reset_decorrenza">Reset Decorrenza</Label>
|
||||
<Button
|
||||
type="button"
|
||||
variant="destructive"
|
||||
id="reset_decorrenza"
|
||||
onClick={() => form.setValue("decorrenza", null)}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<X className="size-5" />
|
||||
Reset Decorrenza
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="isOkAcconto"
|
||||
render={({ field }) => (
|
||||
<FormItem className="w-full">
|
||||
<div className="flex flex-wrap items-center gap-x-2">
|
||||
<FormLabel htmlFor="isOkAcconto">Acconto Pagato</FormLabel>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
id="isOkAcconto"
|
||||
className="data-[state=checked]:bg-neutral-700"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</div>
|
||||
|
||||
<FormDescription>
|
||||
I'acconto è stato pagato o attivato manualmente
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="isOkSaldo"
|
||||
render={({ field }) => (
|
||||
<FormItem className="w-full">
|
||||
<div className="flex flex-wrap items-center gap-x-2">
|
||||
<FormLabel htmlFor="isOkSaldo">Saldo Pagato</FormLabel>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
id="isOkSaldo"
|
||||
className="data-[state=checked]:bg-neutral-700"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</div>
|
||||
|
||||
<FormDescription>
|
||||
Il saldo è stato pagato o attivato manualmente
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="isOkConsulenza"
|
||||
render={({ field }) => (
|
||||
<FormItem className="w-full">
|
||||
<div className="flex flex-wrap items-center gap-x-2">
|
||||
<FormLabel htmlFor="isOkConsulenza">
|
||||
Consulenza Pagata
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
id="isOkConsulenza"
|
||||
className="data-[state=checked]:bg-neutral-700"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</div>
|
||||
|
||||
<FormDescription>
|
||||
La consulenza è stata pagata o attivata manualmente
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Button type="submit">Salva</Button>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
Loading…
Add table
Reference in a new issue