feat: enhance UI components and improve functionality across various modules

This commit is contained in:
Marco Pedone 2025-12-04 17:16:49 +01:00
parent 7ae27d8e30
commit a268afee74
12 changed files with 225 additions and 111 deletions

View file

@ -53,7 +53,7 @@ export const AccordionComp = forwardRef<HTMLDivElement, AccordionCompProps>(
key={`ac-item-${index}`} key={`ac-item-${index}`}
value={`item-${index}`} value={`item-${index}`}
> >
<AccordionTrigger className="cursor-pointer gap-4 text-left text-lg"> <AccordionTrigger className="cursor-pointer gap-4 text-left text-md">
{text.title} {text.title}
</AccordionTrigger> </AccordionTrigger>
<AccordionContent className="text-base"> <AccordionContent className="text-base">

View file

@ -174,13 +174,8 @@ export const InteressatoButtonServizio = ({
const { isAdmin, servizioId, userId } = useServizio(); const { isAdmin, servizioId, userId } = useServizio();
const utils = api.useUtils(); const utils = api.useUtils();
const { mutate: adminAdd, isPending: isAdminPending } = const invalidateAll = async () => {
api.servizio.addServizioAnnunci.useMutation({ await utils.intrests.getUserInterests.invalidate();
onError: (error) => {
console.error(error);
toast.error("Errore durante l'aggiunta dell'annuncio");
},
onSuccess: async () => {
await utils.servizio.getAllServizioAnnunci.invalidate({ userId }); await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
await utils.servizio.getAnnunciAvailableToAdd.invalidate({ await utils.servizio.getAnnunciAvailableToAdd.invalidate({
servizioId, servizioId,
@ -191,6 +186,15 @@ export const InteressatoButtonServizio = ({
await utils.servizio.getCompatibileAnnunci.invalidate({ await utils.servizio.getCompatibileAnnunci.invalidate({
servizioId, servizioId,
}); });
};
const { mutate: adminAdd, isPending: isAdminPending } =
api.servizio.addServizioAnnunci.useMutation({
onError: (error) => {
console.error(error);
toast.error("Errore durante l'aggiunta dell'annuncio");
},
onSuccess: async () => {
await invalidateAll();
toast.success("Annuncio aggiunto alla ricerca"); toast.success("Annuncio aggiunto alla ricerca");
}, },
@ -198,7 +202,7 @@ export const InteressatoButtonServizio = ({
const { mutate: add, isPending } = api.intrests.addIntrest.useMutation({ const { mutate: add, isPending } = api.intrests.addIntrest.useMutation({
onSuccess: async () => { onSuccess: async () => {
await utils.intrests.getUserInterests.invalidate(); await invalidateAll();
toast.success("Richiesta di interesse inviata con successo!"); toast.success("Richiesta di interesse inviata con successo!");
}, },
}); });

View file

@ -1,3 +1,4 @@
import { CircleHelp } from "lucide-react";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
import { AccordionComp } from "~/components/accordionComp"; import { AccordionComp } from "~/components/accordionComp";
import { LoadingPage } from "~/components/loading"; import { LoadingPage } from "~/components/loading";
@ -12,6 +13,16 @@ import {
import { useTranslation } from "~/providers/I18nProvider"; import { useTranslation } from "~/providers/I18nProvider";
import type { UsersId } from "~/schemas/public/Users"; import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import {
Credenza,
CredenzaBody,
CredenzaContent,
CredenzaDescription,
CredenzaHeader,
CredenzaTitle,
CredenzaTrigger,
} from "../custom_ui/credenza";
import { Button } from "../ui/button";
const TimeserieBarChart = dynamic( const TimeserieBarChart = dynamic(
() => import("~/components/timeserieBarChart").then((mod) => mod.default), () => import("~/components/timeserieBarChart").then((mod) => mod.default),
@ -82,37 +93,39 @@ export const AdminDashboard = () => {
}; };
export const UserDashboard = ({ userId }: { userId: UsersId }) => { export const UserDashboard = ({ userId }: { userId: UsersId }) => {
// const { data: servizi, isLoading: loadingServizi } =
// api.servizio.getAllServizioAnnunci.useQuery({ userId });
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div className="mx-1 flex-1 overflow-auto"> <div className="mt-2 flex w-full flex-1 flex-col items-start justify-center gap-4 overflow-auto p-2 md:gap-6">
<div className="mx-auto pt-4">
<div className="mx-3 items-start justify-between md:flex">
<div className="flex max-w-lg items-center gap-3">
<h3 className="font-bold text-2xl">Le tue ricerche</h3> <h3 className="font-bold text-2xl">Le tue ricerche</h3>
</div>
</div>
<div className="flex flex-col space-y-5 px-2"> <div className="flex w-full flex-1 grow flex-col space-y-5">
<TabRicerca isAdmin={false} userId={userId} /> <TabRicerca isAdmin={false} userId={userId} />
{/* {loadingServizi ? (
<LoadingPage />
) : (
servizi?.map((servizio, idx) => (
<ServizioContainer
key={idx}
servizio={servizio}
userId={userId}
isAdmin={false}
/>
))
)} */}
</div> </div>
<div className="mx-auto">
<Credenza>
<CredenzaTrigger asChild>
<Button variant="secondary">
<span>Domande frequenti</span>
<CircleHelp />
</Button>
</CredenzaTrigger>
<CredenzaContent className="max-h-[90vh]">
<CredenzaHeader>
<CredenzaTitle className="text-center font-semibold text-2xl">
Domande frequenti
</CredenzaTitle>
<CredenzaDescription className="sr-only">
Domande frequenti
</CredenzaDescription>
</CredenzaHeader>
<CredenzaBody className="max-h-[80vh] overflow-auto pb-5">
<AccordionComp <AccordionComp
className="w-full max-w-full px-2 pt-4" className="w-full max-w-full"
texts={t.area_riservata.dash_accordion_minifaq} texts={t.area_riservata.dash_accordion_minifaq}
/> />
</CredenzaBody>
</CredenzaContent>
</Credenza>
</div> </div>
</div> </div>
); );

View file

@ -1,9 +1,11 @@
import { CheckCircle } from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import { useServizio } from "~/providers/ServizioProvider"; import { useServizio } from "~/providers/ServizioProvider";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { CardAnnuncio } from "../annuncio_card"; import { CardAnnuncio } from "../annuncio_card";
import { InteressatoButtonServizio } from "../annuncio-interactions/annuncio_interactions"; import { InteressatoButtonServizio } from "../annuncio-interactions/annuncio_interactions";
import { LoadingPage } from "../loading"; import { LoadingPage } from "../loading";
import { Badge } from "../ui/badge";
import { Button } from "../ui/button"; import { Button } from "../ui/button";
import { import {
Dialog, Dialog,
@ -65,7 +67,7 @@ export const AnnunciCompatibili = () => {
trovare annunci compatibili. trovare annunci compatibili.
</span> </span>
) : ( ) : (
<div className="relative z-0 mx-auto grid max-w-full grid-flow-row grid-cols-1 gap-4 sm:grid-cols-2 sm:gap-6 sm:gap-y-10 lg:grid-cols-3 2xl:grid-cols-4"> <div className="relative z-0 mx-auto grid max-w-full grid-flow-row grid-cols-1 gap-14 sm:grid-cols-2 sm:gap-6 sm:gap-y-10 lg:grid-cols-3 2xl:grid-cols-4">
{data.map((annuncio) => ( {data.map((annuncio) => (
<div <div
className="flex flex-col justify-center gap-1" className="flex flex-col justify-center gap-1"
@ -82,7 +84,19 @@ export const AnnunciCompatibili = () => {
<AnnuncioDettaglio data={annuncio} /> <AnnuncioDettaglio data={annuncio} />
</div> </div>
<div className="w-full"> <div className="w-full">
<InteressatoButtonServizio annuncioId={annuncio.id} /> {annuncio.alreadyRequested ? (
<Badge
className="flex h-9 w-full items-center justify-center gap-2 text-base [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0"
variant="success"
>
<span>Richiesta inviata</span>
<CheckCircle />
</Badge>
) : (
<InteressatoButtonServizio
annuncioId={annuncio.id}
/>
)}
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,5 +1,4 @@
import { add } from "date-fns"; import { ArrowRight, Package, PackageCheck } from "lucide-react";
import { CalendarClock, Package, PackageCheck, UserCircle } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useEffect } from "react"; import { useEffect } from "react";
@ -15,7 +14,6 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "~/components/ui/card"; } from "~/components/ui/card";
import { Progress } from "~/components/ui/progress";
import { cn } from "~/lib/utils"; import { cn } from "~/lib/utils";
import { import {
ServizioAnnuncioProvider, ServizioAnnuncioProvider,
@ -44,7 +42,7 @@ const ServizioCard = ({
return ( return (
<Card <Card
className={cn( className={cn(
"gap-2 rounded-t-none border-primary border-t-0", "gap-2 rounded-none rounded-b-md border-primary border-t-0",
cardClassName, cardClassName,
)} )}
> >
@ -134,7 +132,10 @@ export const ServizioContent = () => {
aria-label="Attiva Servizio" aria-label="Attiva Servizio"
href={`/servizio/onboard/${servizio.servizio_id}`} href={`/servizio/onboard/${servizio.servizio_id}`}
> >
<Button>Procedi all&apos;attivazione</Button> <Button variant="success">
<span>Attiva il Servizio Ora!</span>
<ArrowRight />
</Button>
</Link> </Link>
{isAdmin && ( {isAdmin && (
<Button <Button
@ -158,9 +159,7 @@ export const ServizioContent = () => {
} }
header={ header={
<div className="flex w-full flex-col gap-2"> <div className="flex w-full flex-col gap-2">
<span className="text-foreground/70 text-lg"> <span className="text-lg">Servizio non ancora attivato</span>
Servizio non attivo
</span>
<ServizioActions /> <ServizioActions />
</div> </div>
} }
@ -202,9 +201,6 @@ export const ServizioContent = () => {
const annunciSelezionati = servizio.annunci.filter( const annunciSelezionati = servizio.annunci.filter(
(a) => a.user_confirmed_at === null, (a) => a.user_confirmed_at === null,
); );
const openContattiAnnunci = servizio.annunci.filter(
(a) => a.open_contatti_at !== null,
);
const annunciInConferma = servizio.annunci.filter( const annunciInConferma = servizio.annunci.filter(
(a) => a.user_confirmed_at !== null, (a) => a.user_confirmed_at !== null,
@ -214,7 +210,7 @@ export const ServizioContent = () => {
<ServizioCard <ServizioCard
content={ content={
<> <>
<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:max-w-1/2"> <div className="flex flex-2 flex-col gap-2 sm:max-w-1/2">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
@ -239,7 +235,7 @@ export const ServizioContent = () => {
{`${new Date(servizio.decorrenza).toLocaleDateString("it-IT")} - ${new Date(add(servizio.decorrenza, { days: 60 })).toLocaleDateString("it-IT")}`} {`${new Date(servizio.decorrenza).toLocaleDateString("it-IT")} - ${new Date(add(servizio.decorrenza, { days: 60 })).toLocaleDateString("it-IT")}`}
</span> </span>
</div> </div>
</div> </div> */}
{annuncioConfermato.length > 0 && ( {annuncioConfermato.length > 0 && (
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
@ -291,8 +287,9 @@ export const ServizioContent = () => {
); );
})} })}
</div> </div>
{annunciSelezionati.length > 0 && (
<AnnunciSelezionatiAccordion annunci={annunciSelezionati} /> <AnnunciSelezionatiAccordion annunci={annunciSelezionati} />
)}
<div className="flex items-center justify-center"> <div className="flex items-center justify-center">
<AnnunciCompatibili /> <AnnunciCompatibili />
</div> </div>
@ -304,6 +301,7 @@ export const ServizioContent = () => {
<ServizioActions /> <ServizioActions />
</> </>
} }
headerClassName="pb-0"
/> />
); );
}; };

View file

@ -1,5 +1,16 @@
import { add } from "date-fns"; import { add } from "date-fns";
import { Bug, Calculator, ClockAlert, Plus, ShieldUser } from "lucide-react"; import {
Bug,
Calculator,
CalendarClock,
ChevronDown,
ChevronUp,
ClockAlert,
Cog,
Info,
Plus,
UserCircle,
} from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { import {
@ -44,40 +55,122 @@ 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 { 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";
import type { UsersId } from "~/schemas/public/Users"; import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { Progress } from "../ui/progress";
export const ServizioActions = () => { export const ServizioActions = () => {
const { servizio, isAdmin, userId } = useServizio(); const { servizio, isAdmin, userId } = useServizio();
return (
<div className="flex w-full flex-col flex-wrap justify-between gap-3">
{isAdmin && (
<div className="flex items-center gap-3">
<span className="font-semibold">Azioni Admin:</span>
<AddAnnuncio servizioId={servizio.servizio_id} userId={userId} />
<EditServizioAdmin />
</div>
)}
<ServizioInfos />
</div>
);
};
const ServizioInfos = () => {
const { servizio } = useServizio();
const [open, setOpen] = useState(false);
const openContattiAnnunci = servizio.annunci.filter(
(a) => a.open_contatti_at !== null,
);
if (!servizio.decorrenza) return null;
const dec_txt = new Date(servizio.decorrenza).toLocaleDateString("it-IT");
const end_txt = new Date(
add(servizio.decorrenza, { days: 60 }),
).toLocaleDateString("it-IT");
return (
<Collapsible className="space-y-3" onOpenChange={setOpen} open={open}>
<CollapsibleTrigger asChild>
{open ? (
<Button className="w-full justify-between" variant="outline">
<span className="flex items-center gap-2">
<Info />
<span>Informazioni servizio</span>
</span>
<span>
<ChevronUp />
</span>
</Button>
) : (
<Button className="w-full justify-between" variant="outline">
<div className="flex items-center gap-6">
<span className="flex items-center gap-2">
<UserCircle className="size-4 text-primary" />
<span>{openContattiAnnunci.length} / 10</span>
</span>
<span className="flex items-center gap-2">
<CalendarClock className="size-4 text-primary" />
<span>{end_txt}</span>
</span>
</div>
<div className="flex items-center gap-2">
<span>Dettagli</span>
<ChevronDown />
</div>
</Button>
)}
</CollapsibleTrigger>
<CollapsibleContent className="flex w-full flex-col gap-8 rounded-md border bg-card p-2 sm:items-start sm:gap-4">
<ServizioBasicActions />
<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 items-center justify-between">
<div className="flex items-center gap-2">
<UserCircle className="text-primary" />
<span className="font-medium">Contatti sbloccati</span>
</div>
<span className="text-sm">{openContattiAnnunci.length} / 10</span>
</div>
<Progress className="h-2" value={openContattiAnnunci.length * 10} />
</div>
<div className="flex flex-col flex-wrap gap-2 sm:w-1/2 sm:flex-row sm:items-center">
<div className="flex items-center gap-2">
<CalendarClock className="text-primary" />
<span className="font-medium">Durata servizio:</span>
</div>
<span>
{dec_txt} - {end_txt}
</span>
</div>
</div>
</CollapsibleContent>
</Collapsible>
);
};
export const ServizioBasicActions = ({ className }: { className?: string }) => {
const { servizio, isAdmin } = useServizio();
const canUserEdit = const canUserEdit =
servizio.isOkAcconto && servizio.isOkAcconto &&
servizio.decorrenza !== null && servizio.decorrenza !== null &&
!servizio.annunci.some((a) => a.user_confirmed_at !== null); !servizio.annunci.some((a) => a.user_confirmed_at !== null);
if (!isAdmin && !canUserEdit) { if (isAdmin || canUserEdit) {
return null; // If the user is not an admin and cannot edit, do not render the actions
}
return ( return (
<div className="flex w-full flex-col flex-wrap justify-between gap-3 sm:flex-row"> <div className={cn("flex flex-wrap items-center gap-3", className)}>
{(isAdmin || canUserEdit) && (
<div className="flex flex-wrap items-center gap-3">
{/* <span className="hidden sm:block">Azioni: </span> */}
<EditPreferenze /> <EditPreferenze />
<InterruzioneServizio /> <InterruzioneServizio />
</div> </div>
)}
{isAdmin && (
<div className="flex items-center gap-3">
<AddAnnuncio servizioId={servizio.servizio_id} userId={userId} />
<EditServizioAdmin />
</div>
)}
</div>
); );
}
return null;
}; };
export const AddAnnuncio = ({ export const AddAnnuncio = ({
servizioId, servizioId,
@ -300,6 +393,7 @@ const EditPreferenze = () => {
(servizio.isInterrotto || (servizio.isInterrotto ||
servizio.annunci.some((a) => a.hasConfermaAdmin)) servizio.annunci.some((a) => a.hasConfermaAdmin))
} }
variant="secondary"
> >
<Calculator /> <Calculator />
Preferenze Preferenze
@ -362,8 +456,8 @@ const EditServizioAdmin = () => {
<Credenza onOpenChange={setOpen} open={open}> <Credenza onOpenChange={setOpen} open={open}>
<CredenzaTrigger asChild> <CredenzaTrigger asChild>
<Button aria-label="Modifica Servizio Admin"> <Button aria-label="Modifica Servizio Admin">
<ShieldUser /> <Cog />
Admin Modifica
</Button> </Button>
</CredenzaTrigger> </CredenzaTrigger>
<CredenzaContent className="max-h-[90vh] w-full sm:max-w-5xl"> <CredenzaContent className="max-h-[90vh] w-full sm:max-w-5xl">

View file

@ -1,4 +1,4 @@
import { ChevronDownCircle, ChevronRightCircle, Package } from "lucide-react"; import { Building, ChevronDown, ChevronUp } from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import { LoadingPage } from "~/components/loading"; import { LoadingPage } from "~/components/loading";
import { ServizioContent } from "~/components/servizio/main"; import { ServizioContent } from "~/components/servizio/main";
@ -84,24 +84,13 @@ const Row = ({
isOpen && "rounded-b-none", isOpen && "rounded-b-none",
)} )}
> >
<CollapsibleTrigger className="grid w-full cursor-pointer grid-cols-8 items-center"> <CollapsibleTrigger className="flex w-full cursor-pointer items-center justify-between gap-4 px-3 sm:px-4">
<div className="col-span-2 flex items-center justify-center text-primary sm:col-span-1"> <div className="flex items-center gap-2 font-semibold text-primary sm:text-lg">
{isOpen ? ( <Building className="size-6 fill-background" />
<ChevronDownCircle className="fill-background" />
) : (
<ChevronRightCircle className="fill-background" />
)}
</div>
<div className="col-span-6 flex items-center gap-2 font-semibold text-primary sm:text-lg">
<Package className="size-6" />
Affitto {servizio.tipologia} Affitto {servizio.tipologia}
</div> </div>
<div className="float-end flex items-center justify-start pl-2 text-primary">
<div className="hidden text-primary text-sm sm:col-span-2 sm:contents sm:text-base"> {isOpen ? <ChevronUp /> : <ChevronDown />}
{servizio.created_at.toLocaleDateString("it", {
day: "2-digit",
month: "short",
})}
</div> </div>
</CollapsibleTrigger> </CollapsibleTrigger>
</div> </div>

View file

@ -20,6 +20,8 @@ const badgeVariants = cva(
"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground", "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
secondary: secondary:
"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
success:
"bg-success border-transparent text-white [a&]hover:bg-success/90 dark:text-white",
}, },
}, },
}, },

View file

@ -70,7 +70,7 @@ const Annunci = ({ options }: AnnunciPageProps) => {
<meta content={t.heads.annunci_description} name="description" /> <meta content={t.heads.annunci_description} name="description" />
</Head> </Head>
<main className="relative mx-auto w-full max-w-10xl space-y-5 bg-background2 px-2 py-5 md:px-8"> <main className="relative mx-auto w-full max-w-10xl space-y-5 bg-background px-2 py-5 md:px-8">
<Badge className="bg-muted py-1 text-foreground text-sm outline outline-muted-foreground"> <Badge className="bg-muted py-1 text-foreground text-sm outline outline-muted-foreground">
{t.annunci.titolo} {t.annunci.titolo}
</Badge> </Badge>
@ -89,14 +89,7 @@ const Annunci = ({ options }: AnnunciPageProps) => {
export default Annunci; export default Annunci;
Annunci.getLayout = (page: React.ReactNode) => { Annunci.getLayout = (page: React.ReactNode) => {
return ( return <Layout>{page}</Layout>;
<Layout
containerClassName="bg-background2"
footerClassName="bg-background2"
>
{page}
</Layout>
);
}; };
export const getServerSideProps = (async () => { export const getServerSideProps = (async () => {

View file

@ -52,7 +52,7 @@ const SessionWrapper = ({ userId }: { userId: UsersId }) => {
if (!data) return <Status500 />; if (!data) return <Status500 />;
return ( return (
<main className="mx-1 mt-2 flex flex-1 flex-col items-start gap-4 p-2 md:gap-8"> <main className="mx-1 mt-2 flex flex-1 flex-col items-start gap-4 p-2 md:gap-6">
<div className="grid w-full auto-rows-max items-start gap-2 md:gap-4"> <div className="grid w-full auto-rows-max items-start gap-2 md:gap-4">
<div className="overflow-auto border-none"> <div className="overflow-auto border-none">
<h3 className="font-bold text-2xl">Ordini</h3> <h3 className="font-bold text-2xl">Ordini</h3>

View file

@ -42,6 +42,7 @@ import { db } from "~/server/db";
import { NewMail, type NewMailProps } from "~/server/services/mailer"; import { NewMail, type NewMailProps } from "~/server/services/mailer";
import { getUser } from "~/server/services/user.service"; import { getUser } from "~/server/services/user.service";
import { withImages, withVideos } from "~/utils/kysely-helper"; import { withImages, withVideos } from "~/utils/kysely-helper";
import { GetUserInterests } from "../services/interests.service";
import type { AnnuncioRicerca } from "./annunci.controller"; import type { AnnuncioRicerca } from "./annunci.controller";
export const addServizio = async (data: NewServizio) => { export const addServizio = async (data: NewServizio) => {
@ -1622,7 +1623,7 @@ export const getCompatibileAnnunci = async ({
}: { }: {
servizioId: ServizioServizioId; servizioId: ServizioServizioId;
adminOverride?: boolean; adminOverride?: boolean;
}): Promise<AnnuncioRicerca[]> => { }): Promise<(AnnuncioRicerca & { alreadyRequested: boolean })[]> => {
try { try {
const servizio = await getServizioById(servizioId); const servizio = await getServizioById(servizioId);
if (!servizio) { if (!servizio) {
@ -1632,10 +1633,12 @@ export const getCompatibileAnnunci = async ({
}); });
} }
const interests = await GetUserInterests(servizio.user_id);
let qry = db let qry = db
.selectFrom("annunci") .selectFrom("annunci")
.distinctOn("annunci.id") .distinctOn("annunci.id")
.select((_eb) => [ .select((eb) => [
"id", "id",
"codice", "codice",
"comune", "comune",
@ -1657,6 +1660,13 @@ export const getCompatibileAnnunci = async ({
"modificato_il", "modificato_il",
withImages(), withImages(),
withVideos(), withVideos(),
eb
.case()
.when("id", "in", interests)
.then(true)
.else(false)
.end()
.as("alreadyRequested"),
]) ])
.where("web", "=", true) .where("web", "=", true)
.where("stato", "!=", "Sospeso") .where("stato", "!=", "Sospeso")

View file

@ -44,7 +44,6 @@
--radius-lg: var(--radius); --radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px); --radius-xl: calc(var(--radius) + 4px);
--color-background: var(--background); --color-background: var(--background);
--color-background2: var(--background2);
--color-foreground: var(--foreground); --color-foreground: var(--foreground);
--color-card: var(--card); --color-card: var(--card);
--color-card-foreground: var(--card-foreground); --color-card-foreground: var(--card-foreground);
@ -281,8 +280,6 @@
--radius: 0.625rem; --radius: 0.625rem;
--backgroundbkp: oklch(1 0 0); --backgroundbkp: oklch(1 0 0);
--background: oklch(70.716% 0.07403 219.01); --background: oklch(70.716% 0.07403 219.01);
--background2bkp: oklch(91.587% 0.08721 83.88);
--background2: oklch(70.716% 0.07403 219.01);
--foreground: oklch(0.145 0 0); --foreground: oklch(0.145 0 0);
--card: oklch(1 0 0); --card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0); --card-foreground: oklch(0.145 0 0);