fix: update payment method type in PurchaseData and related components

This commit is contained in:
Marco Pedone 2026-03-09 18:14:22 +01:00
parent 50ba1d4c5d
commit a9a9104711
5 changed files with 185 additions and 118 deletions

View file

@ -77,7 +77,7 @@ export type PurchaseData = {
clienteNome: string; clienteNome: string;
clienteIndirizzo: string; clienteIndirizzo: string;
paymentMethod: string; paymentMethod: PaymentType;
packName: string; packName: string;
sconto: number; sconto: number;
@ -186,7 +186,7 @@ function Receipt({ data }: ReceiptProps) {
<div className="flex justify-between"> <div className="flex justify-between">
<div> <div>
<h3 className="mb-1 font-semibold">Metodo di pagamento</h3> <h3 className="mb-1 font-semibold">Metodo di pagamento</h3>
<p>{PaymentMethodToString(data.paymentMethod as PaymentType)}</p> <p>{PaymentMethodToString(data.paymentMethod)}</p>
</div> </div>
<div className="text-right"> <div className="text-right">
<h3 className="mb-1 font-semibold">Status pagamento</h3> <h3 className="mb-1 font-semibold">Status pagamento</h3>

View file

@ -15,7 +15,6 @@ import { Button } from "~/components/ui/button";
import { FormEditOrder } from "~/forms/FormEditOrdine"; import { FormEditOrder } from "~/forms/FormEditOrdine";
import { formatCurrency } from "~/lib/utils"; import { formatCurrency } from "~/lib/utils";
import type { OrdiniOrdineId } from "~/schemas/public/Ordini"; import type { OrdiniOrdineId } from "~/schemas/public/Ordini";
import PaymentStatusEnum from "~/schemas/public/PaymentStatusEnum";
import type { Prezziario } from "~/schemas/public/Prezziario"; import type { Prezziario } from "~/schemas/public/Prezziario";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
@ -68,14 +67,16 @@ const AdminOrdiniModal = ({
<CredenzaBody className="max-h-[80vh] space-y-2 overflow-auto pb-5"> <CredenzaBody className="max-h-[80vh] space-y-2 overflow-auto pb-5">
<p>Id Ordine: {data.ordine_id}</p> <p>Id Ordine: {data.ordine_id}</p>
{data.isActive && ( {data.isActive && (
<Link <div>
href={`/servizio/ricevuta-cortesia/${data.ordine_id}`} <Link
target="_blank" href={`/servizio/ricevuta-cortesia/${data.ordine_id}`}
> target="_blank"
<Button variant="outline"> >
Ricevuta di cortesia <ReceiptText /> <Button variant="outline">
</Button> Ricevuta di cortesia <ReceiptText />
</Link> </Button>
</Link>
</div>
)} )}
<FormEditOrder <FormEditOrder
close={() => setSelected(null)} close={() => setSelected(null)}
@ -139,19 +140,18 @@ export const UserOrdiniModal = ({
Importo: {formatCurrency(data.amount_cent / 100)}{" "} Importo: {formatCurrency(data.amount_cent / 100)}{" "}
{data.sconto > 0 && <span>({data.sconto}%)</span>} {data.sconto > 0 && <span>({data.sconto}%)</span>}
</p> </p>
{data.isActive && {data.isActive && (
data.paymentstatus === PaymentStatusEnum.success && ( <div>
<div> <Link
<Link href={`/servizio/ricevuta-cortesia/${data.ordine_id}`}
href={`/servizio/ricevuta-cortesia/${data.ordine_id}`} target="_blank"
target="_blank" >
> <Button variant="outline">
<Button variant="outline"> Ricevuta di cortesia <ReceiptText />
Ricevuta di cortesia <ReceiptText /> </Button>
</Button> </Link>
</Link> </div>
</div> )}
)}
</CredenzaBody> </CredenzaBody>
<CredenzaFooter className="flex w-full sm:justify-end"> <CredenzaFooter className="flex w-full sm:justify-end">
<CredenzaClose asChild> <CredenzaClose asChild>

View file

@ -35,7 +35,7 @@ function SelectTrigger({
return ( return (
<SelectPrimitive.Trigger <SelectPrimitive.Trigger
className={cn( className={cn(
"flex w-fit items-center justify-between gap-2 whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs outline-hidden transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[size=default]:h-9 data-[size=sm]:h-8 data-placeholder:text-muted-foreground *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:hover:bg-input/50 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0", "flex w-fit items-center justify-between gap-2 whitespace-nowrap rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs outline-hidden transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[size=default]:h-9 data-[size=sm]:h-8 data-placeholder:text-muted-foreground *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:hover:bg-input/50 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0",
className, className,
)} )}
data-size={size} data-size={size}

View file

@ -107,99 +107,101 @@ export const FormEditOrder = ({ prezziario, data, close }: FormProps) => {
<> <>
<Form {...form}> <Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}> <form onSubmit={form.handleSubmit(onSubmit)}>
<CredenzaBody className="max-h-[80vh] w-full pb-5"> <CredenzaBody className="max-h-[80vh] w-full px-0 py-4">
<div className="space-y-8 px-0.5"> <div className="flex flex-col gap-4 sm:gap-6 sm:px-0.5">
<FormField <div className="grid grid-cols-1 items-center gap-4 sm:grid-cols-2 sm:gap-6">
control={form.control} <FormField
name="packid" control={form.control}
render={({ field }) => { name="packid"
const pack = prezziario.find( render={({ field }) => {
(p) => p.idprezziario === field.value, const pack = prezziario.find(
); (p) => p.idprezziario === field.value,
return ( );
<FormItem className="w-full"> return (
<FormItem className="w-full">
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="select-pack">Servizio</FormLabel>
<FormMessage />
</div>
<FormControl>
<MultiSelect
defaultValue={
field.value
? {
label: pack?.nome_it || "",
value: field.value,
}
: undefined
}
elementId="select-pack"
elementName="packid"
isMulti={false}
onValueChange={(value) => {
const selected = zPrezziarioId.safeParse(
value.value,
);
if (selected.success) {
field.onChange(selected.data);
const selectedPrezzo = prezziario.find(
(p) => p.idprezziario === selected.data,
);
if (selectedPrezzo) {
form.setValue(
"amount_cent",
selectedPrezzo.prezzo_cent,
);
}
} else {
console.error(
"Invalid packid selected",
value.value,
);
}
}}
options={prezziario.map((p) => ({
label: `${p.idprezziario} - ${p.nome_it} (${formatCurrency(p.prezzo_cent / 100)})`,
value: p.idprezziario,
}))}
placeholder="Seleziona..."
/>
</FormControl>
</FormItem>
);
}}
/>
<FormField
control={form.control}
name="type"
render={({ field }) => (
<FormItem>
<div className="flex flex-wrap items-center gap-x-2"> <div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="select-pack">Servizio</FormLabel> <FormLabel htmlFor="titolo">Tipologia</FormLabel>
<FormMessage /> <FormMessage />
</div> </div>
<FormControl> <FormControl>
<MultiSelect <Select
defaultValue={ defaultValue={field.value || ""}
field.value onValueChange={field.onChange}
? { >
label: pack?.nome_it || "", <FormControl>
value: field.value, <SelectTrigger className="w-full">
} <SelectValue placeholder="Seleziona tipologia" />
: undefined </SelectTrigger>
} </FormControl>
elementId="select-pack" <SelectContent id="select-color">
elementName="packid" {Object.values(OrderTypeEnum).map((option) => (
isMulti={false} <SelectItem key={option} value={option}>
onValueChange={(value) => { {option}
const selected = zPrezziarioId.safeParse( </SelectItem>
value.value, ))}
); </SelectContent>
if (selected.success) { </Select>
field.onChange(selected.data);
const selectedPrezzo = prezziario.find(
(p) => p.idprezziario === selected.data,
);
if (selectedPrezzo) {
form.setValue(
"amount_cent",
selectedPrezzo.prezzo_cent,
);
}
} else {
console.error(
"Invalid packid selected",
value.value,
);
}
}}
options={prezziario.map((p) => ({
label: `${p.idprezziario} - ${p.nome_it} (${formatCurrency(p.prezzo_cent / 100)})`,
value: p.idprezziario,
}))}
placeholder="Seleziona..."
/>
</FormControl> </FormControl>
</FormItem> </FormItem>
); )}
}} />
/> </div>
<FormField
control={form.control}
name="type"
render={({ field }) => (
<FormItem>
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="titolo">Tipologia</FormLabel>
<FormMessage />
</div>
<FormControl>
<Select
defaultValue={field.value || ""}
onValueChange={field.onChange}
>
<FormControl>
<SelectTrigger className="w-full">
<SelectValue placeholder="Seleziona tipologia" />
</SelectTrigger>
</FormControl>
<SelectContent id="select-color">
{Object.values(OrderTypeEnum).map((option) => (
<SelectItem key={option} value={option}>
{option}
</SelectItem>
))}
</SelectContent>
</Select>
</FormControl>
</FormItem>
)}
/>
<FormField <FormField
control={form.control} control={form.control}
name="created_at" name="created_at"
@ -254,7 +256,7 @@ export const FormEditOrder = ({ prezziario, data, close }: FormProps) => {
render={({ field }) => ( render={({ field }) => (
<FormItem className="w-full"> <FormItem className="w-full">
<div className="flex flex-wrap items-center gap-x-2"> <div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="isActive">Pagato</FormLabel> <FormLabel htmlFor="isActive">Attivo</FormLabel>
<FormControl> <FormControl>
<Switch <Switch
className="data-[state=checked]:bg-neutral-700" className="data-[state=checked]:bg-neutral-700"
@ -272,6 +274,72 @@ export const FormEditOrder = ({ prezziario, data, close }: FormProps) => {
</FormItem> </FormItem>
)} )}
/> />
<div className="grid grid-cols-1 items-center gap-4 sm:grid-cols-2 sm:gap-6">
<FormField
control={form.control}
name="paymentstatus"
render={({ field }) => (
<FormItem>
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="titolo">Stato Pagameto</FormLabel>
<FormMessage />
</div>
<FormControl>
<Select
defaultValue={field.value || ""}
onValueChange={field.onChange}
>
<FormControl>
<SelectTrigger className="w-full">
<SelectValue placeholder="Seleziona tipologia" />
</SelectTrigger>
</FormControl>
<SelectContent id="select-paymentstatus">
{Object.values(PaymentStatusEnum).map((option) => (
<SelectItem key={option} value={option}>
{option}
</SelectItem>
))}
</SelectContent>
</Select>
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name="paymentmethod"
render={({ field }) => (
<FormItem>
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="titolo">
Metodo di Pagamento
</FormLabel>
<FormMessage />
</div>
<FormControl>
<Select
defaultValue={field.value || ""}
onValueChange={field.onChange}
>
<FormControl>
<SelectTrigger className="w-full">
<SelectValue placeholder="Seleziona tipologia" />
</SelectTrigger>
</FormControl>
<SelectContent id="select-paymentmethod">
{Object.values(PAYMENT_TYPES).map((option) => (
<SelectItem key={option} value={option}>
{option}
</SelectItem>
))}
</SelectContent>
</Select>
</FormControl>
</FormItem>
)}
/>
</div>
<FormField <FormField
control={form.control} control={form.control}
name="sconto" name="sconto"

View file

@ -2,12 +2,11 @@ import { TRPCError } from "@trpc/server";
import { add } from "date-fns"; import { add } from "date-fns";
import { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/postgres"; import { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/postgres";
import { z } from "zod/v4"; import { z } from "zod/v4";
import type { PurchaseData } from "~/components/acquisto_receipt";
import { env } from "~/env"; import { env } from "~/env";
import type { PaymentType } from "~/i18n/stripe";
import type { Annunci, AnnunciId } from "~/schemas/public/Annunci"; import type { Annunci, AnnunciId } from "~/schemas/public/Annunci";
import OrderTypeEnum from "~/schemas/public/OrderTypeEnum"; import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
import type { Ordini, OrdiniOrdineId } from "~/schemas/public/Ordini"; import type { Ordini, OrdiniOrdineId } from "~/schemas/public/Ordini";
import PaymentStatusEnum from "~/schemas/public/PaymentStatusEnum";
import type { Prezziario } from "~/schemas/public/Prezziario"; import type { Prezziario } from "~/schemas/public/Prezziario";
import type { import type {
Servizio, Servizio,
@ -1348,7 +1347,7 @@ export const getOrdineRicevutaData = async ({
.innerJoin("prezziario", "prezziario.idprezziario", "ordini.packid") .innerJoin("prezziario", "prezziario.idprezziario", "ordini.packid")
.select("prezziario.nome_it") .select("prezziario.nome_it")
.where("ordini.ordine_id", "=", ordineId) .where("ordini.ordine_id", "=", ordineId)
.where("ordini.paymentstatus", "=", PaymentStatusEnum.success) //.where("ordini.paymentstatus", "=", PaymentStatusEnum.success)
.executeTakeFirstOrThrow( .executeTakeFirstOrThrow(
() => new Error(`Ordine not found - ordineId: ${ordineId}`), () => new Error(`Ordine not found - ordineId: ${ordineId}`),
@ -1381,8 +1380,8 @@ export const getOrdineRicevutaData = async ({
amount_cent: data.amount_cent, amount_cent: data.amount_cent,
ordineId: data.ordine_id, ordineId: data.ordine_id,
paymentMethod: data.paymentmethod, paymentMethod: (data.paymentmethod || "manual") as PaymentType,
} as PurchaseData; };
} catch (e) { } catch (e) {
throw new TRPCError({ throw new TRPCError({
code: "INTERNAL_SERVER_ERROR", code: "INTERNAL_SERVER_ERROR",