refactor: streamline ServizioContent layout and enhance ServizioInfos with pack details retrieval
This commit is contained in:
parent
cd2c96ad58
commit
b376de48bb
7 changed files with 173 additions and 61 deletions
|
|
@ -203,16 +203,9 @@ export const ServizioContent = () => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const annunciSelezionati = servizio.annunci.filter(
|
|
||||||
(a) => a.user_confirmed_at === null,
|
|
||||||
);
|
|
||||||
|
|
||||||
const annunciInConferma = servizio.annunci.filter(
|
|
||||||
(a) => a.user_confirmed_at !== null,
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ServizioCard
|
<ServizioCard
|
||||||
|
cardClassName="gap-y-2"
|
||||||
content={
|
content={
|
||||||
<>
|
<>
|
||||||
{annuncioConfermato.length > 0 && (
|
{annuncioConfermato.length > 0 && (
|
||||||
|
|
@ -252,8 +245,8 @@ export const ServizioContent = () => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div className="flex flex-col gap-2 overflow-y-auto">
|
<div className="grid grid-cols-1 gap-3 lg:grid-cols-2">
|
||||||
{annunciInConferma.map((data) => {
|
{servizio.annunci.map((data) => {
|
||||||
return (
|
return (
|
||||||
<ServizioAnnuncioProvider
|
<ServizioAnnuncioProvider
|
||||||
data={data}
|
data={data}
|
||||||
|
|
@ -261,35 +254,12 @@ export const ServizioContent = () => {
|
||||||
servizioId={servizio.servizio_id}
|
servizioId={servizio.servizio_id}
|
||||||
userId={userId}
|
userId={userId}
|
||||||
>
|
>
|
||||||
<AnnuncioCard className="border-2 border-green-500" />
|
<AnnuncioCard className="rounded-md border-primary" />
|
||||||
</ServizioAnnuncioProvider>
|
</ServizioAnnuncioProvider>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
{annunciSelezionati.length > 0 && (
|
|
||||||
<div className="flex flex-col gap-3">
|
|
||||||
<h2 className="px-1 font-semibold text-xl">
|
|
||||||
Annunci selezionati:
|
|
||||||
</h2>
|
|
||||||
<div className="grid grid-cols-1 gap-3 lg:grid-cols-2">
|
|
||||||
{annunciSelezionati.map((data) => {
|
|
||||||
return (
|
|
||||||
<ServizioAnnuncioProvider
|
|
||||||
data={data}
|
|
||||||
key={data.id}
|
|
||||||
servizioId={servizio.servizio_id}
|
|
||||||
userId={userId}
|
|
||||||
>
|
|
||||||
<AnnuncioCard className="rounded-md border-primary" />
|
|
||||||
</ServizioAnnuncioProvider>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{/* {annunciSelezionati.length > 0 && (
|
|
||||||
<AnnunciSelezionatiAccordion annunci={annunciSelezionati} />
|
|
||||||
)} */}
|
|
||||||
<div className="flex items-center justify-center">
|
<div className="flex items-center justify-center">
|
||||||
<AnnunciCompatibili />
|
<AnnunciCompatibili />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ import {
|
||||||
FormEditServizio,
|
FormEditServizio,
|
||||||
} from "~/forms/FormEditServizioAdmin";
|
} from "~/forms/FormEditServizioAdmin";
|
||||||
import { FormNewServizio, type FormValues } from "~/forms/FormNewServizio";
|
import { FormNewServizio, type FormValues } from "~/forms/FormNewServizio";
|
||||||
import { cn } from "~/lib/utils";
|
import { cn, formatCurrency } from "~/lib/utils";
|
||||||
import { useServizio } from "~/providers/ServizioProvider";
|
import { useServizio } from "~/providers/ServizioProvider";
|
||||||
import type { AnnunciId } from "~/schemas/public/Annunci";
|
import type { AnnunciId } from "~/schemas/public/Annunci";
|
||||||
import type { ServizioServizioId } from "~/schemas/public/Servizio";
|
import type { ServizioServizioId } from "~/schemas/public/Servizio";
|
||||||
|
|
@ -94,10 +94,13 @@ const ServizioInfos = () => {
|
||||||
add(servizio.decorrenza, { days: 60 }),
|
add(servizio.decorrenza, { days: 60 }),
|
||||||
).toLocaleDateString("it-IT");
|
).toLocaleDateString("it-IT");
|
||||||
return (
|
return (
|
||||||
<Collapsible className="space-y-3" onOpenChange={setOpen} open={open}>
|
<Collapsible className="space-y-2" onOpenChange={setOpen} open={open}>
|
||||||
<CollapsibleTrigger asChild>
|
<CollapsibleTrigger asChild>
|
||||||
{open ? (
|
{open ? (
|
||||||
<Button className="w-full justify-between" variant="outline">
|
<Button
|
||||||
|
className="w-full justify-between data-[state=open]:bg-accent dark:data-[state=open]:bg-input/50"
|
||||||
|
variant="outline"
|
||||||
|
>
|
||||||
<span className="flex items-center gap-2">
|
<span className="flex items-center gap-2">
|
||||||
<Info />
|
<Info />
|
||||||
<span>Informazioni servizio</span>
|
<span>Informazioni servizio</span>
|
||||||
|
|
@ -126,7 +129,7 @@ const ServizioInfos = () => {
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</CollapsibleTrigger>
|
</CollapsibleTrigger>
|
||||||
<CollapsibleContent className="flex w-full flex-col gap-8 rounded-md border bg-card p-2 sm:items-start sm:gap-4">
|
<CollapsibleContent className="mb-4 flex w-full flex-col gap-8 rounded-md border bg-card p-2 sm:items-start sm:gap-4">
|
||||||
<ServizioBasicActions />
|
<ServizioBasicActions />
|
||||||
<div className="flex w-full flex-col gap-8 sm:flex-row sm:items-start">
|
<div className="flex w-full flex-col gap-8 sm:flex-row sm:items-start">
|
||||||
<div className="flex flex-2 flex-col gap-2 sm:w-1/2">
|
<div className="flex flex-2 flex-col gap-2 sm:w-1/2">
|
||||||
|
|
@ -149,6 +152,7 @@ const ServizioInfos = () => {
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<ServizioPacksInfos />
|
||||||
</CollapsibleContent>
|
</CollapsibleContent>
|
||||||
</Collapsible>
|
</Collapsible>
|
||||||
);
|
);
|
||||||
|
|
@ -172,6 +176,49 @@ const ServizioBasicActions = ({ className }: { className?: string }) => {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ServizioPacksInfos = () => {
|
||||||
|
const { servizio } = useServizio();
|
||||||
|
const { data: packs } = api.servizio.getPacksSolution.useQuery({
|
||||||
|
servizioId: servizio.servizio_id,
|
||||||
|
});
|
||||||
|
if (!packs) return null;
|
||||||
|
return (
|
||||||
|
<div className="space-y-2">
|
||||||
|
<h3 className="font-semibold text-lg">Prezzi:</h3>
|
||||||
|
<div className="flex w-full flex-col gap-4 md:flex-row">
|
||||||
|
{packs.acconto && (
|
||||||
|
<div className="flex flex-1 flex-col gap-2 rounded-md bg-secondary/50 p-2">
|
||||||
|
<span className="font-medium">{packs.acconto.nome_it}</span>
|
||||||
|
<span className="text-muted-foreground text-sm">
|
||||||
|
{packs.acconto.desc_it}
|
||||||
|
</span>
|
||||||
|
<span className="font-semibold text-lg">
|
||||||
|
{formatCurrency(packs.acconto.prezzo_cent / 100)}
|
||||||
|
</span>
|
||||||
|
<span className="text-muted-foreground text-sm">
|
||||||
|
COD: {packs.acconto.idprezziario}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{packs.saldo && (
|
||||||
|
<div className="flex flex-1 flex-col gap-2 rounded-md bg-secondary/50 p-2">
|
||||||
|
<span className="font-medium">{packs.saldo.nome_it}</span>
|
||||||
|
<span className="text-muted-foreground text-sm">
|
||||||
|
{packs.saldo.desc_it}
|
||||||
|
</span>
|
||||||
|
<span className="font-semibold text-lg">
|
||||||
|
{formatCurrency(packs.saldo.prezzo_cent / 100)}
|
||||||
|
</span>
|
||||||
|
<span className="text-muted-foreground text-sm">
|
||||||
|
COD: {packs.saldo.idprezziario}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
export const AddAnnuncio = ({
|
export const AddAnnuncio = ({
|
||||||
servizioId,
|
servizioId,
|
||||||
userId,
|
userId,
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,6 @@ export const handleConsegna = ({
|
||||||
aggiornamento: string;
|
aggiornamento: string;
|
||||||
}) => {
|
}) => {
|
||||||
const currentMonth = new Date().getMonth() + 1;
|
const currentMonth = new Date().getMonth() + 1;
|
||||||
console.log("handleConsegna", {
|
|
||||||
consegna: consegna,
|
|
||||||
currentMonth: currentMonth,
|
|
||||||
});
|
|
||||||
if (consegna !== null) {
|
if (consegna !== null) {
|
||||||
if (consegna !== currentMonth) {
|
if (consegna !== currentMonth) {
|
||||||
return `${mesi[consegna]}`;
|
return `${mesi[consegna]}`;
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ export const prezziarioRouter = createTRPCRouter({
|
||||||
getPrezzoPerServizio: publicProcedure
|
getPrezzoPerServizio: publicProcedure
|
||||||
.input(z.object({ idprezziario: zPrezziarioId }))
|
.input(z.object({ idprezziario: zPrezziarioId }))
|
||||||
.query(async ({ input }) => {
|
.query(async ({ input }) => {
|
||||||
return await getPrezziarioByIdHandler({ db, input });
|
return await getPrezziarioByIdHandler({ id: input.idprezziario });
|
||||||
}),
|
}),
|
||||||
updatePrezziario: adminProcedure
|
updatePrezziario: adminProcedure
|
||||||
.input(
|
.input(
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import {
|
||||||
getCompatibileAnnunci,
|
getCompatibileAnnunci,
|
||||||
getDataPerAcquisto,
|
getDataPerAcquisto,
|
||||||
getOrdineRicevutaData,
|
getOrdineRicevutaData,
|
||||||
|
getPackPerServizio,
|
||||||
getPreOnboardData,
|
getPreOnboardData,
|
||||||
getServiziByUserId,
|
getServiziByUserId,
|
||||||
getServizioAnnuncio,
|
getServizioAnnuncio,
|
||||||
|
|
@ -50,6 +51,7 @@ import {
|
||||||
userAccettaConferma,
|
userAccettaConferma,
|
||||||
userSendConfermaIntent,
|
userSendConfermaIntent,
|
||||||
} from "~/server/controllers/servizio.controller";
|
} from "~/server/controllers/servizio.controller";
|
||||||
|
import { getPrezziarioByIdHandler } from "~/server/services/prezziario.service";
|
||||||
import {
|
import {
|
||||||
zAnnuncioId,
|
zAnnuncioId,
|
||||||
zOrdineId,
|
zOrdineId,
|
||||||
|
|
@ -340,7 +342,33 @@ export const servizioRouter = createTRPCRouter({
|
||||||
servizioId: input.servizioId,
|
servizioId: input.servizioId,
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
getPacksSolution: protectedProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
servizioId: zServizioId,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.query(async ({ input }) => {
|
||||||
|
const accontoId = await getPackPerServizio({
|
||||||
|
stage: "acconto",
|
||||||
|
servizioId: input.servizioId,
|
||||||
|
});
|
||||||
|
const saldoId = await getPackPerServizio({
|
||||||
|
stage: "saldo",
|
||||||
|
servizioId: input.servizioId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const acconto = accontoId.success
|
||||||
|
? await getPrezziarioByIdHandler({ id: accontoId.packId })
|
||||||
|
: null;
|
||||||
|
const saldo = saldoId.success
|
||||||
|
? await getPrezziarioByIdHandler({ id: saldoId.packId })
|
||||||
|
: null;
|
||||||
|
return {
|
||||||
|
acconto,
|
||||||
|
saldo,
|
||||||
|
};
|
||||||
|
}),
|
||||||
unlockServizioContatti: protectedProcedure
|
unlockServizioContatti: protectedProcedure
|
||||||
.input(
|
.input(
|
||||||
z.object({
|
z.object({
|
||||||
|
|
|
||||||
|
|
@ -506,6 +506,74 @@ const ConsulenzaPriceMapping = {
|
||||||
Transitorio: "CONS_TRAN" as PrezziarioIdprezziario,
|
Transitorio: "CONS_TRAN" as PrezziarioIdprezziario,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type GetPackError = { success: false; message: string };
|
||||||
|
type GetPackResult = { success: true; packId: PrezziarioIdprezziario };
|
||||||
|
|
||||||
|
export const getPackPerServizio = async ({
|
||||||
|
stage,
|
||||||
|
servizioId,
|
||||||
|
}: {
|
||||||
|
stage: "acconto" | "saldo";
|
||||||
|
servizioId: ServizioServizioId;
|
||||||
|
}): Promise<GetPackResult | GetPackError> => {
|
||||||
|
const servizio = await getServizioById(servizioId);
|
||||||
|
if (!servizio) {
|
||||||
|
return { success: false, message: "Servizio not found" };
|
||||||
|
}
|
||||||
|
switch (stage) {
|
||||||
|
case "acconto": {
|
||||||
|
switch (servizio.tipologia) {
|
||||||
|
case TipologiaPosizioneEnum.Transitorio: {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
packId: "ACCONTO_BD" as PrezziarioIdprezziario,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case TipologiaPosizioneEnum.Stabile: {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
packId: "ACCONTO_CA" as PrezziarioIdprezziario,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return { success: false, message: "Invalid tipologia" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "saldo": {
|
||||||
|
switch (servizio.tipologia) {
|
||||||
|
case TipologiaPosizioneEnum.Transitorio: {
|
||||||
|
const mpp =
|
||||||
|
servizio.permanenza && SaldoTransitorioMapping[servizio.permanenza];
|
||||||
|
if (!servizio.permanenza || !mpp) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Permanenza not set for transitorio servizio",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return { success: true, packId: mpp };
|
||||||
|
}
|
||||||
|
case TipologiaPosizioneEnum.Stabile: {
|
||||||
|
if (servizio.budget >= 500) {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
packId: "SALDOCA500+" as PrezziarioIdprezziario,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
packId: "SALDOCA500" as PrezziarioIdprezziario,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return { success: false, message: "Invalid tipologia" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return { success: false, message: "Invalid stage" };
|
||||||
|
}
|
||||||
|
};
|
||||||
type TipoEnum = keyof typeof ConsulenzaPriceMapping;
|
type TipoEnum = keyof typeof ConsulenzaPriceMapping;
|
||||||
export const setupSaldoConsulenzaServizio = async ({
|
export const setupSaldoConsulenzaServizio = async ({
|
||||||
servizioId,
|
servizioId,
|
||||||
|
|
@ -711,12 +779,12 @@ export const getAllServizioAnnunci = async (userId: UsersId) => {
|
||||||
//ignora annunci che non sono disponibili
|
//ignora annunci che non sono disponibili
|
||||||
.where("annunci.web", "=", true)
|
.where("annunci.web", "=", true)
|
||||||
.where("annunci.stato", "!=", "Sospeso")
|
.where("annunci.stato", "!=", "Sospeso")
|
||||||
// .orderBy("servizio_annunci.user_confirmed_at", (ob) =>
|
.orderBy("servizio_annunci.user_confirmed_at", (ob) =>
|
||||||
// ob.asc().nullsLast(),
|
ob.asc().nullsLast(),
|
||||||
// )
|
)
|
||||||
// .orderBy("servizio_annunci.open_contatti_at", (ob) =>
|
.orderBy("servizio_annunci.open_contatti_at", (ob) =>
|
||||||
// ob.asc().nullsFirst(),
|
ob.asc().nullsFirst(),
|
||||||
// )
|
)
|
||||||
.orderBy("servizio_annunci.created_at", "asc")
|
.orderBy("servizio_annunci.created_at", "asc")
|
||||||
.whereRef(
|
.whereRef(
|
||||||
"servizio_annunci.servizio_id",
|
"servizio_annunci.servizio_id",
|
||||||
|
|
|
||||||
|
|
@ -26,19 +26,22 @@ export const getPrezziario = async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getPrezziarioByIdHandler = async ({
|
export const getPrezziarioByIdHandler = async ({
|
||||||
db,
|
id,
|
||||||
input,
|
|
||||||
}: {
|
}: {
|
||||||
db: Querier;
|
id: PrezziarioIdprezziario;
|
||||||
input: {
|
|
||||||
idprezziario: PrezziarioIdprezziario;
|
|
||||||
};
|
|
||||||
}) => {
|
}) => {
|
||||||
return await db
|
try {
|
||||||
.selectFrom("prezziario")
|
return await db
|
||||||
.selectAll()
|
.selectFrom("prezziario")
|
||||||
.where("prezziario.idprezziario", "=", input.idprezziario)
|
.selectAll()
|
||||||
.executeTakeFirst();
|
.where("prezziario.idprezziario", "=", id)
|
||||||
|
.executeTakeFirst();
|
||||||
|
} catch (error) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
|
message: `Error getting prezziario by id: ${(error as Error).message}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addPrezziario = async ({
|
export const addPrezziario = async ({
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue