Refactor AnnuncioCard to use AdminActions and UserActions based on user role; remove unused Interactions component; update button sizes and styles across various components; enhance ServizioContent with mutation handling; improve user feedback on actions; update confirmation messages for clarity; adjust layout for better responsiveness in AnnunciRichiesti; streamline form submissions with updated data structures.
This commit is contained in:
parent
804b4fef90
commit
1baca2997a
30 changed files with 512 additions and 538 deletions
|
|
@ -30,10 +30,10 @@ export const MappaDialogFullscreen = ({
|
||||||
<Dialog onOpenChange={setOpen} open={open}>
|
<Dialog onOpenChange={setOpen} open={open}>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button className="w-auto grow" disabled={!lat || !long}>
|
<Button className="w-auto grow" disabled={!lat || !long}>
|
||||||
<MapIcon className="size-5" /> {t.mappa}
|
<MapIcon /> {t.mappa}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className="[&_[data-slot=dialog-close]>svg]:!size-6 h-full w-screen max-w-[100vw] p-0 sm:max-h-[60vh] sm:max-w-2xl [&_[data-slot=dialog-close]]:cursor-pointer [&_[data-slot=dialog-close]]:rounded-md [&_[data-slot=dialog-close]]:bg-white [&_[data-slot=dialog-close]]:opacity-100">
|
<DialogContent className="h-full w-screen max-w-[100vw] p-0 **:data-[slot=dialog-close]:cursor-pointer **:data-[slot=dialog-close]:rounded-md **:data-[slot=dialog-close]:bg-white **:data-[slot=dialog-close]:opacity-100 sm:max-h-[60vh] sm:max-w-2xl [&_[data-slot=dialog-close]>svg]:size-6!">
|
||||||
<DialogHeader className="hidden h-0">
|
<DialogHeader className="hidden h-0">
|
||||||
<DialogTitle className="sr-only">{t.mappa}</DialogTitle>
|
<DialogTitle className="sr-only">{t.mappa}</DialogTitle>
|
||||||
<DialogDescription className="sr-only">{t.mappa}</DialogDescription>
|
<DialogDescription className="sr-only">{t.mappa}</DialogDescription>
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ export const CTA_TipologiaModal = () => {
|
||||||
>
|
>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button className="h-9">
|
<Button className="h-9">
|
||||||
<CircleHelp className="size-5" />{" "}
|
<CircleHelp />{" "}
|
||||||
<span className="hidden sm:block">
|
<span className="hidden sm:block">
|
||||||
{t.tipologia_tutorial.btn_title}
|
{t.tipologia_tutorial.btn_title}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ export const AnnuncioInteractions = ({
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button className="w-full">
|
<Button className="w-full">
|
||||||
<LogIn className="size-5" />
|
<LogIn />
|
||||||
<span>Accedi se hai un account</span>
|
<span>Accedi se hai un account</span>
|
||||||
</Button>
|
</Button>
|
||||||
</Link> */}
|
</Link> */}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ export const ContattoAnnuncio = () => {
|
||||||
<Credenza>
|
<Credenza>
|
||||||
<CredenzaTrigger asChild>
|
<CredenzaTrigger asChild>
|
||||||
<Button className="w-full" variant="destructive">
|
<Button className="w-full" variant="destructive">
|
||||||
<MessageCirclePlus className="size-5" /> Contattaci
|
<MessageCirclePlus /> Contattaci
|
||||||
</Button>
|
</Button>
|
||||||
</CredenzaTrigger>
|
</CredenzaTrigger>
|
||||||
<CredenzaContent className="max-h-[90vh]">
|
<CredenzaContent className="max-h-[90vh]">
|
||||||
|
|
|
||||||
|
|
@ -71,11 +71,7 @@ export const Sidebar = ({
|
||||||
onClick={() => toggleSidebar(!minimized)}
|
onClick={() => toggleSidebar(!minimized)}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
>
|
>
|
||||||
{minimized ? (
|
{minimized ? <Expand /> : <Minimize2 />}
|
||||||
<Expand className="size-5" />
|
|
||||||
) : (
|
|
||||||
<Minimize2 className="size-5" />
|
|
||||||
)}
|
|
||||||
<span className="sr-only">Toggle Menu</span>
|
<span className="sr-only">Toggle Menu</span>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ export const ComeFunziona = () => {
|
||||||
>
|
>
|
||||||
<ExpandableScreenTrigger className="w-full">
|
<ExpandableScreenTrigger className="w-full">
|
||||||
<Button className="w-full">
|
<Button className="w-full">
|
||||||
<HelpCircle className="size-5" />
|
<HelpCircle />
|
||||||
<span>Scopri come funziona</span>
|
<span>Scopri come funziona</span>
|
||||||
</Button>
|
</Button>
|
||||||
</ExpandableScreenTrigger>
|
</ExpandableScreenTrigger>
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ export const UserHeaderSection = ({
|
||||||
>
|
>
|
||||||
{inSidebar && t.auth.login.titolo}
|
{inSidebar && t.auth.login.titolo}
|
||||||
|
|
||||||
<LogIn className="size-5" />
|
<LogIn />
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<DropdownMenu onOpenChange={setOpen} open={open}>
|
<DropdownMenu onOpenChange={setOpen} open={open}>
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export function RicercaCommand() {
|
||||||
<Dialog onOpenChange={setOpen} open={open}>
|
<Dialog onOpenChange={setOpen} open={open}>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button aria-label="ricercaBtn" className="p-2" variant="ghost">
|
<Button aria-label="ricercaBtn" className="p-2" variant="ghost">
|
||||||
<Search className="size-5" />
|
<Search />
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className="border-none bg-transparent **:data-[slot=dialog-close]:hidden sm:max-w-xl">
|
<DialogContent className="border-none bg-transparent **:data-[slot=dialog-close]:hidden sm:max-w-xl">
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ export const SettingsPopover = () => {
|
||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
<Button aria-label="Settings" className="p-2" variant="ghost">
|
<Button aria-label="Settings" className="p-2" variant="ghost">
|
||||||
<Settings className="size-5" />
|
<Settings />
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent className="flex w-fit justify-center gap-4 p-4">
|
<PopoverContent className="flex w-fit justify-center gap-4 p-4">
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ export const OnboardTutorial = () => {
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<Button onClick={handleClose} size="lg" variant="success">
|
<Button onClick={handleClose} size="lg" variant="success">
|
||||||
<span>{t.onboarding_tutorial.button_text}</span>
|
<span>{t.onboarding_tutorial.button_text}</span>
|
||||||
<ArrowRight className="size-5" />
|
<ArrowRight />
|
||||||
</Button>
|
</Button>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
|
|
|
||||||
|
|
@ -40,13 +40,13 @@ export const PricingChoice = () => {
|
||||||
<Tabs className="mb-2 w-full max-w-xl" defaultValue="transitorio">
|
<Tabs className="mb-2 w-full max-w-xl" defaultValue="transitorio">
|
||||||
<TabsList className="flex h-auto w-full items-center justify-between gap-1 p-1 dark:bg-primary">
|
<TabsList className="flex h-auto w-full items-center justify-between gap-1 p-1 dark:bg-primary">
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
className="w-full cursor-pointer border-0 bg-transitorio px-2 text-xl sm:px-3 dark:border-0 dark:text-fxd-foreground [&[data-state=active]]:border-0 [&[data-state=active]]:bg-transitorio dark:[&[data-state=active]]:border-0 dark:[&[data-state=active]]:bg-transitorio dark:[&[data-state=active]]:text-fxd-foreground"
|
className="w-full cursor-pointer border-0 bg-transitorio px-2 text-xl data-[state=active]:border-0 data-[state=active]:bg-transitorio sm:px-3 dark:border-0 dark:text-fxd-foreground dark:data-[state=active]:border-0 dark:data-[state=active]:bg-transitorio dark:data-[state=active]:text-fxd-foreground"
|
||||||
value="transitorio"
|
value="transitorio"
|
||||||
>
|
>
|
||||||
Transitorio
|
Transitorio
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
className="w-full cursor-pointer border-0 bg-stabile px-2 text-xl sm:px-3 dark:border-0 dark:text-fxd-foreground [&[data-state=active]]:border-0 [&[data-state=active]]:bg-stabile dark:[&[data-state=active]]:border-0 dark:[&[data-state=active]]:bg-stabile dark:[&[data-state=active]]:text-fxd-foreground"
|
className="w-full cursor-pointer border-0 bg-stabile px-2 text-xl data-[state=active]:border-0 data-[state=active]:bg-stabile sm:px-3 dark:border-0 dark:text-fxd-foreground dark:data-[state=active]:border-0 dark:data-[state=active]:bg-stabile dark:data-[state=active]:text-fxd-foreground"
|
||||||
value="stabile"
|
value="stabile"
|
||||||
>
|
>
|
||||||
Stabile
|
Stabile
|
||||||
|
|
@ -86,7 +86,7 @@ export const PricingChoice = () => {
|
||||||
<Link aria-label="Link to pricing page" href="/prezzi">
|
<Link aria-label="Link to pricing page" href="/prezzi">
|
||||||
<Button className="flex h-12 flex-row gap-2 px-6 py-4 text-2xl hover:underline">
|
<Button className="flex h-12 flex-row gap-2 px-6 py-4 text-2xl hover:underline">
|
||||||
<span>Scopri di più sui prezzi</span>
|
<span>Scopri di più sui prezzi</span>
|
||||||
<ExternalLink className="size-5" />
|
<ExternalLink />
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -66,14 +66,11 @@ export const AdminLavoraConferma = () => {
|
||||||
<Button
|
<Button
|
||||||
aria-label="Open Lavora Conferma Section"
|
aria-label="Open Lavora Conferma Section"
|
||||||
className="w-fit"
|
className="w-fit"
|
||||||
variant={data.hasConfermaAdmin ? "success" : "secondary"}
|
size="sm"
|
||||||
|
variant={data.hasConfermaAdmin ? "success" : "orange"}
|
||||||
>
|
>
|
||||||
{data.hasConfermaAdmin ? (
|
{data.hasConfermaAdmin ? <CircleCheck /> : <Wrench />}
|
||||||
<CircleCheck className="size-6" />
|
<span>Conferma</span>
|
||||||
) : (
|
|
||||||
<Wrench className="size-6" />
|
|
||||||
)}
|
|
||||||
Conferma
|
|
||||||
</Button>
|
</Button>
|
||||||
</CredenzaTrigger>
|
</CredenzaTrigger>
|
||||||
<CredenzaContent className="max-h-[90vh] w-full px-3 sm:max-w-6xl">
|
<CredenzaContent className="max-h-[90vh] w-full px-3 sm:max-w-6xl">
|
||||||
|
|
@ -823,7 +820,7 @@ const SendConferma = () => {
|
||||||
<StabileSection />
|
<StabileSection />
|
||||||
)}
|
)}
|
||||||
<GeneralSection />
|
<GeneralSection />
|
||||||
<ServizioPacksInfos title="Prezzi in base a parametri:" />
|
<ServizioPacksInfos />
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{!docOk && (
|
{!docOk && (
|
||||||
|
|
|
||||||
|
|
@ -38,13 +38,10 @@ export const AdminContratto = () => {
|
||||||
<Button
|
<Button
|
||||||
aria-label="Open Contratto Section"
|
aria-label="Open Contratto Section"
|
||||||
className="w-fit"
|
className="w-fit"
|
||||||
|
size="sm"
|
||||||
variant={data.doc_contratto_added ? "success" : "secondary"}
|
variant={data.doc_contratto_added ? "success" : "secondary"}
|
||||||
>
|
>
|
||||||
{data.doc_contratto_added ? (
|
{data.doc_contratto_added ? <CircleCheck /> : <Wrench />}
|
||||||
<CircleCheck className="size-6" />
|
|
||||||
) : (
|
|
||||||
<Wrench className="size-6" />
|
|
||||||
)}
|
|
||||||
Contratto
|
Contratto
|
||||||
</Button>
|
</Button>
|
||||||
</CredenzaTrigger>
|
</CredenzaTrigger>
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,35 @@
|
||||||
import { ExternalLink, FolderKanban, ShieldUser, Trash2 } from "lucide-react";
|
|
||||||
import Link from "next/link";
|
|
||||||
import toast from "react-hot-toast";
|
|
||||||
import { Confirm } from "~/components/confirm";
|
|
||||||
import { Button } from "~/components/ui/button";
|
|
||||||
import {
|
import {
|
||||||
Popover,
|
ExternalLink,
|
||||||
PopoverContent,
|
Eye,
|
||||||
PopoverTrigger,
|
FileBadge,
|
||||||
} from "~/components/ui/popover";
|
FileText,
|
||||||
|
FolderKanban,
|
||||||
|
PackageCheck,
|
||||||
|
Pointer,
|
||||||
|
Printer,
|
||||||
|
Trash2,
|
||||||
|
} from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
import toast from "react-hot-toast";
|
||||||
|
import { Button, type ButtonConfigs } from "~/components/ui/button";
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "~/components/ui/tooltip";
|
||||||
|
import { cn } from "~/lib/utils";
|
||||||
import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider";
|
import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider";
|
||||||
|
import type { AnnunciId } from "~/schemas/public/Annunci";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
|
import { Confirm } from "../confirm";
|
||||||
import { AdminLavoraConferma } from "./admin_conferma";
|
import { AdminLavoraConferma } from "./admin_conferma";
|
||||||
import { AdminContratto } from "./admin_contratto";
|
import { AdminContratto } from "./admin_contratto";
|
||||||
|
import { ConfermaAnnuncioModal, ConfermaInLavorazioneModal } from "./conferma";
|
||||||
|
import { ContattiProprietarioModal } from "./modale_contatti";
|
||||||
|
|
||||||
export const AnnuncioActions = () => {
|
export const AdminActions = () => {
|
||||||
const { servizioId, userId, isAdmin } = useServizio();
|
const { servizioId, userId, isAdmin } = useServizio();
|
||||||
const { data, annuncioId } = useServizioAnnuncio();
|
const { data, annuncioId } = useServizioAnnuncio();
|
||||||
|
|
||||||
|
|
@ -31,79 +47,330 @@ export const AnnuncioActions = () => {
|
||||||
toast.success("Annuncio rimosso");
|
toast.success("Annuncio rimosso");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
if (!isAdmin) return null;
|
||||||
|
|
||||||
if ((!isAdmin && data.open_contatti_at == null) || isAdmin) {
|
return (
|
||||||
return (
|
<div className="flex w-full max-w-fit flex-wrap justify-start gap-3 sm:justify-end">
|
||||||
<div className="flex w-full max-w-fit flex-wrap justify-start gap-3 sm:justify-end">
|
{data.user_confirmed_at != null && <AdminLavoraConferma />}
|
||||||
{isAdmin && data.user_confirmed_at != null && <AdminLavoraConferma />}
|
{data.accettato_conferma_at != null && (
|
||||||
{isAdmin && data.accettato_conferma_at != null && (
|
<>
|
||||||
<>
|
<AdminContratto />
|
||||||
<AdminContratto />
|
{data.gestionale_id && (
|
||||||
{data.gestionale_id && (
|
<Link
|
||||||
<Link
|
aria-label="Open Gestionale"
|
||||||
aria-label="Open Gestionale"
|
href={`https://win-jk822fggr6b:480/id/${data.gestionale_id}`}
|
||||||
href={`https://win-jk822fggr6b:480/id/${data.gestionale_id}`}
|
target="_blank"
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<Button>
|
|
||||||
<FolderKanban className="size-5" /> Gestionale
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{isAdmin && (
|
|
||||||
<Popover>
|
|
||||||
<PopoverTrigger asChild>
|
|
||||||
<Button>
|
|
||||||
<ShieldUser />
|
|
||||||
<span>Admin</span>
|
|
||||||
</Button>
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent
|
|
||||||
align="end"
|
|
||||||
className="flex w-fit flex-col items-center gap-4"
|
|
||||||
>
|
>
|
||||||
<Link
|
<Button size="sm">
|
||||||
href={`/area-riservata/admin/edit-annuncio/${annuncioId}`}
|
<FolderKanban /> Gestionale
|
||||||
target="_blank"
|
</Button>
|
||||||
>
|
</Link>
|
||||||
<Button
|
)}
|
||||||
aria-label="Edit Annuncio"
|
</>
|
||||||
className="w-full"
|
)}
|
||||||
size="sm"
|
<Link href={`/annuncio/${data.codice}`} target="_blank">
|
||||||
variant="secondary"
|
<Button size="sm" type="button" variant="outline">
|
||||||
>
|
<Eye /> pubblica
|
||||||
<ExternalLink />
|
</Button>
|
||||||
<span>Modifica Annuncio</span>
|
</Link>
|
||||||
</Button>
|
<Link
|
||||||
</Link>
|
href={`/area-riservata/admin/edit-annuncio/${annuncioId}`}
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
aria-label="Edit Annuncio"
|
||||||
|
className="w-fit"
|
||||||
|
size="sm"
|
||||||
|
variant="secondary"
|
||||||
|
>
|
||||||
|
<ExternalLink />
|
||||||
|
<span>Modifica</span>
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
|
||||||
<Confirm
|
<Link
|
||||||
description="Sei sicuro di voler eliminare l'annuncio?"
|
href={`/area-riservata/admin/scheda-annuncio-stampa/${data.id}`}
|
||||||
onConfirm={() => {
|
target="_blank"
|
||||||
mutate({
|
>
|
||||||
annuncioId,
|
<Button size="sm" type="button" variant="outline">
|
||||||
servizioId,
|
<Printer /> Scheda
|
||||||
});
|
</Button>
|
||||||
}}
|
</Link>
|
||||||
title="Elimina annuncio"
|
|
||||||
>
|
<Confirm
|
||||||
<Button
|
description="Sei sicuro di voler eliminare l'annuncio?"
|
||||||
aria-label="Delete Annuncio"
|
onConfirm={() => {
|
||||||
className="w-full"
|
mutate({
|
||||||
size="sm"
|
annuncioId,
|
||||||
variant="destructive"
|
servizioId,
|
||||||
>
|
});
|
||||||
<Trash2 />
|
}}
|
||||||
<span>Elimina</span>
|
title="Elimina annuncio"
|
||||||
</Button>
|
>
|
||||||
</Confirm>
|
<Button
|
||||||
</PopoverContent>
|
aria-label="Delete Annuncio"
|
||||||
</Popover>
|
className="w-fit"
|
||||||
|
size="sm"
|
||||||
|
variant="destructive"
|
||||||
|
>
|
||||||
|
<Trash2 />
|
||||||
|
<span>Elimina</span>
|
||||||
|
</Button>
|
||||||
|
</Confirm>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const UserActions = () => {
|
||||||
|
const { servizioId } = useServizio();
|
||||||
|
const { data, annuncioId } = useServizioAnnuncio();
|
||||||
|
|
||||||
|
const ContattiSbloccati = data.open_contatti_at !== null;
|
||||||
|
const ConfermaUtente = data.user_confirmed_at !== null;
|
||||||
|
const ConfermaLavorata = data.doc_conferma_added && data.hasConfermaAdmin;
|
||||||
|
const AccettatoConferma = data.accettato_conferma_at !== null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="flex w-full flex-col flex-wrap gap-2 sm:flex-row">
|
||||||
|
<ContattiProprietarioModal />
|
||||||
|
|
||||||
|
{ContattiSbloccati && !ConfermaUtente && <ConfermaAnnuncioModal />}
|
||||||
|
{ConfermaUtente && !data.hasConfermaAdmin && (
|
||||||
|
<ConfermaInLavorazioneModal />
|
||||||
)}
|
)}
|
||||||
|
{AccettatoConferma && (
|
||||||
|
<Link
|
||||||
|
aria-label="Conferma immobile"
|
||||||
|
href={`/servizio/riapri-conferma/${servizioId}/${annuncioId}`}
|
||||||
|
>
|
||||||
|
<Button className="w-full sm:w-fit" variant="success">
|
||||||
|
<Pointer />
|
||||||
|
Rivedi la conferma
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
{ConfermaLavorata &&
|
||||||
|
(data.doc_conferma_ref ? (
|
||||||
|
<Link
|
||||||
|
aria-label="Conferma immobile"
|
||||||
|
href={`/servizio/conferma-immobile/${servizioId}/${annuncioId}`}
|
||||||
|
>
|
||||||
|
<Button className="w-full sm:w-fit" variant="success">
|
||||||
|
<Pointer />
|
||||||
|
Confermato - Procedi ora
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<TooltipProvider delayDuration={0}>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button
|
||||||
|
className="w-full cursor-not-allowed opacity-50 sm:w-fit"
|
||||||
|
variant="success"
|
||||||
|
>
|
||||||
|
<Pointer />
|
||||||
|
Confermato - Procedi ora
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>Il documento non è più disponibile</p>
|
||||||
|
<p>
|
||||||
|
Se hai bisogno di una copia, contattaci via email o chat.
|
||||||
|
</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{data.accettato_conferma_at != null && <PostConfermaSection />}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const PostConfermaSection = () => {
|
||||||
|
const { servizio, servizioId } = useServizio();
|
||||||
|
const { data, annuncioId } = useServizioAnnuncio();
|
||||||
|
|
||||||
|
const saldoPaid = servizio.isOkSaldo;
|
||||||
|
const consulenzaPaid = servizio.isOkConsulenza;
|
||||||
|
|
||||||
|
if (!saldoPaid) {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<h3 className="font-semibold">
|
||||||
|
Questo annuncio è stato confermato, procedi al saldo:
|
||||||
|
</h3>
|
||||||
|
<SaldoButton annuncioId={annuncioId} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
if (!data.doc_contratto_added) {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<h3 className="font-semibold text-green-500">
|
||||||
|
Ci siamo quasi! Stiamo preparando il contratto per te.
|
||||||
|
</h3>
|
||||||
|
<h3 className="font-semibold">
|
||||||
|
Una volta pronto, riceverai una notifica via email.
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<h3 className="font-semibold">
|
||||||
|
{consulenzaPaid
|
||||||
|
? "Il contratto è pronto, puoi visualizzarlo:"
|
||||||
|
: "Il contratto è pronto, puoi visualizzarlo e procedere al saldo:"}
|
||||||
|
</h3>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
{data.doc_contratto_ref ? (
|
||||||
|
<Link
|
||||||
|
aria-label="Visualizza contratto"
|
||||||
|
href={`/servizio/contratto/${servizioId}/${annuncioId}`}
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<Button className="w-full sm:w-fit">
|
||||||
|
<FileText />
|
||||||
|
Visualizza il contratto
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<TooltipProvider delayDuration={0}>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button className="w-fit cursor-not-allowed opacity-50">
|
||||||
|
<FileText />
|
||||||
|
Visualizza il contratto
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>Il documento non è più disponibile</p>
|
||||||
|
<p>Se hai bisogno di una copia, contattaci via email o chat.</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!consulenzaPaid && data.contratto_tipo && <SaldoConsulenzaButton />}
|
||||||
|
|
||||||
|
{data.doc_registrazione_added &&
|
||||||
|
(data.doc_registrazione_ref ? (
|
||||||
|
<Link
|
||||||
|
aria-label="Visualizza registrazione"
|
||||||
|
href={`/servizio/contratto-registrazione/${servizioId}/${annuncioId}`}
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<Button className="w-fit">
|
||||||
|
<FileBadge />
|
||||||
|
Visualizza la registrazione
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<TooltipProvider delayDuration={0}>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button className="w-fit cursor-not-allowed opacity-50">
|
||||||
|
<FileBadge />
|
||||||
|
Visualizza la registrazione
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>Il documento non è più disponibile</p>
|
||||||
|
<p>
|
||||||
|
Se hai bisogno di una copia, contattaci via email o chat.
|
||||||
|
</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SaldoButton = ({
|
||||||
|
annuncioId,
|
||||||
|
variant = "info",
|
||||||
|
className,
|
||||||
|
}: {
|
||||||
|
annuncioId: AnnunciId;
|
||||||
|
variant?: ButtonConfigs["variant"];
|
||||||
|
className?: string;
|
||||||
|
}) => {
|
||||||
|
const { servizioId } = useServizio();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const { mutate } = api.servizio.setupSaldoServizio.useMutation({
|
||||||
|
onMutate: () => {
|
||||||
|
toast.loading("Caricamento ...", { id: "preparazioneSaldo" });
|
||||||
|
},
|
||||||
|
onSuccess: async (data) => {
|
||||||
|
toast.success("Pagamento saldo preparato", {
|
||||||
|
id: "preparazioneSaldo",
|
||||||
|
});
|
||||||
|
|
||||||
|
await router.push(`/servizio/pagamento/${data}`);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
aria-label="Procedi al saldo"
|
||||||
|
className={cn("w-fit", className)}
|
||||||
|
onClick={() => {
|
||||||
|
mutate({
|
||||||
|
annuncioId,
|
||||||
|
servizioId,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
variant={variant}
|
||||||
|
>
|
||||||
|
<PackageCheck />
|
||||||
|
Procedi al saldo
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SaldoConsulenzaButton = ({
|
||||||
|
variant = "info",
|
||||||
|
className,
|
||||||
|
}: {
|
||||||
|
variant?: ButtonConfigs["variant"];
|
||||||
|
className?: string;
|
||||||
|
}) => {
|
||||||
|
const { annuncioId } = useServizioAnnuncio();
|
||||||
|
const { servizioId } = useServizio();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const { mutate } = api.servizio.setupSaldoConsulenzaServizio.useMutation({
|
||||||
|
onMutate: () => {
|
||||||
|
toast.loading("Caricamento ...", { id: "preparazioneSaldo" });
|
||||||
|
},
|
||||||
|
onSuccess: async (data) => {
|
||||||
|
toast.success("Pagamento saldo preparato", {
|
||||||
|
id: "preparazioneSaldo",
|
||||||
|
});
|
||||||
|
|
||||||
|
await router.push(`/servizio/pagamento/${data}`);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
aria-label="Procedi al saldo consulenza"
|
||||||
|
className={cn("w-fit", className)}
|
||||||
|
onClick={() => {
|
||||||
|
mutate({
|
||||||
|
annuncioId,
|
||||||
|
servizioId,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
variant={variant}
|
||||||
|
>
|
||||||
|
<PackageCheck />
|
||||||
|
Procedi al saldo della consulenza
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { AnnuncioActions } from "~/components/servizio/annuncio_actions";
|
import {
|
||||||
import { Interactions } from "~/components/servizio/interactions";
|
AdminActions,
|
||||||
|
UserActions,
|
||||||
|
} from "~/components/servizio/annuncio_actions";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
|
||||||
import { handleConsegna } from "~/lib/annuncio_details";
|
import { handleConsegna } from "~/lib/annuncio_details";
|
||||||
import { getStorageUrl } from "~/lib/storage_utils";
|
import { getStorageUrl } from "~/lib/storage_utils";
|
||||||
import { cn, formatCurrency } from "~/lib/utils";
|
import { cn, formatCurrency } from "~/lib/utils";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
import { useServizioAnnuncio } from "~/providers/ServizioProvider";
|
import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider";
|
||||||
import type { AnnuncioRicerca } from "~/server/controllers/annunci.controller";
|
import type { AnnuncioRicerca } from "~/server/controllers/annunci.controller";
|
||||||
import { AnnuncioDettaglio, TipoBadge } from "./annuncio_dettaglio";
|
import { AnnuncioDettaglio, TipoBadge } from "./annuncio_dettaglio";
|
||||||
|
|
||||||
|
|
@ -17,11 +19,11 @@ export const AnnuncioCard = ({
|
||||||
className?: string;
|
className?: string;
|
||||||
confirming?: boolean;
|
confirming?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { isAdmin } = useServizio();
|
||||||
const { data } = useServizioAnnuncio();
|
const { data } = useServizioAnnuncio();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BasicAnnuncioCard
|
<BasicAnnuncioCard
|
||||||
actions={<AnnuncioActions />}
|
|
||||||
className={className}
|
className={className}
|
||||||
confirming={confirming}
|
confirming={confirming}
|
||||||
data={{
|
data={{
|
||||||
|
|
@ -31,7 +33,7 @@ export const AnnuncioCard = ({
|
||||||
? new Date(data.media_updated_at)
|
? new Date(data.media_updated_at)
|
||||||
: null,
|
: null,
|
||||||
}}
|
}}
|
||||||
interactions={<Interactions />}
|
interactions={isAdmin ? <AdminActions /> : <UserActions />}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -103,13 +105,11 @@ export const AnnuncioDisplay = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BasicAnnuncioCard = ({
|
export const BasicAnnuncioCard = ({
|
||||||
actions,
|
|
||||||
interactions,
|
interactions,
|
||||||
className,
|
className,
|
||||||
data,
|
data,
|
||||||
confirming,
|
confirming,
|
||||||
}: {
|
}: {
|
||||||
actions?: React.ReactNode;
|
|
||||||
interactions?: React.ReactNode;
|
interactions?: React.ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
data: AnnuncioRicerca;
|
data: AnnuncioRicerca;
|
||||||
|
|
@ -119,7 +119,6 @@ export const BasicAnnuncioCard = ({
|
||||||
<Card className={cn("w-full gap-2 border-white py-3", className)}>
|
<Card className={cn("w-full gap-2 border-white py-3", className)}>
|
||||||
<CardHeader className="flex flex-row flex-wrap items-center justify-between space-y-0 px-3 pb-2">
|
<CardHeader className="flex flex-row flex-wrap items-center justify-between space-y-0 px-3 pb-2">
|
||||||
<CardTitle className="text-2xl">Annuncio {data.codice}</CardTitle>
|
<CardTitle className="text-2xl">Annuncio {data.codice}</CardTitle>
|
||||||
{actions}
|
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="px-3">
|
<CardContent className="px-3">
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ export const ConfermaAnnuncioModal = () => {
|
||||||
<Credenza onOpenChange={setOpen} open={open}>
|
<Credenza onOpenChange={setOpen} open={open}>
|
||||||
<CredenzaTrigger asChild>
|
<CredenzaTrigger asChild>
|
||||||
<Button aria-label="Conferma immobile" className="w-full sm:w-fit">
|
<Button aria-label="Conferma immobile" className="w-full sm:w-fit">
|
||||||
<Handshake className="size-5" /> {t.richieste.cta}
|
<Handshake /> {t.richieste.cta}
|
||||||
</Button>
|
</Button>
|
||||||
</CredenzaTrigger>
|
</CredenzaTrigger>
|
||||||
<CredenzaContent className="max-h-[90vh]">
|
<CredenzaContent className="max-h-[90vh]">
|
||||||
|
|
@ -218,7 +218,7 @@ export const ConfermaInLavorazioneModal = () => {
|
||||||
aria-label="Conferma in lavorazione"
|
aria-label="Conferma in lavorazione"
|
||||||
className="w-full sm:w-fit"
|
className="w-full sm:w-fit"
|
||||||
>
|
>
|
||||||
<CircleCheck className="size-5" />
|
<CircleCheck />
|
||||||
Conferma in lavorazione
|
Conferma in lavorazione
|
||||||
</Button>
|
</Button>
|
||||||
</CredenzaTrigger>
|
</CredenzaTrigger>
|
||||||
|
|
|
||||||
|
|
@ -1,286 +0,0 @@
|
||||||
import { FileBadge, FileText, PackageCheck, Pointer } from "lucide-react";
|
|
||||||
import Link from "next/link";
|
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import toast from "react-hot-toast";
|
|
||||||
import { Button, type ButtonConfigs } from "~/components/ui/button";
|
|
||||||
import {
|
|
||||||
Tooltip,
|
|
||||||
TooltipContent,
|
|
||||||
TooltipProvider,
|
|
||||||
TooltipTrigger,
|
|
||||||
} from "~/components/ui/tooltip";
|
|
||||||
import { cn } from "~/lib/utils";
|
|
||||||
import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider";
|
|
||||||
import type { AnnunciId } from "~/schemas/public/Annunci";
|
|
||||||
import { api } from "~/utils/api";
|
|
||||||
import { ConfermaAnnuncioModal, ConfermaInLavorazioneModal } from "./conferma";
|
|
||||||
import { ContattiProprietarioModal } from "./modale_contatti";
|
|
||||||
|
|
||||||
const SezioneConferma = () => {
|
|
||||||
const { servizioId } = useServizio();
|
|
||||||
const { data, annuncioId } = useServizioAnnuncio();
|
|
||||||
|
|
||||||
const ContattiSbloccati = data.open_contatti_at !== null;
|
|
||||||
const ConfermaUtente = data.user_confirmed_at !== null;
|
|
||||||
const ConfermaLavorata = data.doc_conferma_added && data.hasConfermaAdmin;
|
|
||||||
const AccettatoConferma = data.accettato_conferma_at !== null;
|
|
||||||
|
|
||||||
if (ContattiSbloccati && !ConfermaUtente) {
|
|
||||||
return <ConfermaAnnuncioModal />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ConfermaUtente && !data.hasConfermaAdmin) {
|
|
||||||
return <ConfermaInLavorazioneModal />;
|
|
||||||
}
|
|
||||||
if (AccettatoConferma) {
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
aria-label="Conferma immobile"
|
|
||||||
href={`/servizio/riapri-conferma/${servizioId}/${annuncioId}`}
|
|
||||||
>
|
|
||||||
<Button className="w-full sm:w-fit" variant="success">
|
|
||||||
<Pointer className="size-5" />
|
|
||||||
Rivedi la conferma
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (ConfermaLavorata) {
|
|
||||||
if (data.doc_conferma_ref) {
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
aria-label="Conferma immobile"
|
|
||||||
href={`/servizio/conferma-immobile/${servizioId}/${annuncioId}`}
|
|
||||||
>
|
|
||||||
<Button className="w-full sm:w-fit" variant="success">
|
|
||||||
<Pointer className="size-5" />
|
|
||||||
Confermato - Procedi ora
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<TooltipProvider delayDuration={0}>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<Button
|
|
||||||
className="w-full cursor-not-allowed opacity-50 sm:w-fit"
|
|
||||||
variant="success"
|
|
||||||
>
|
|
||||||
<Pointer className="size-5" />
|
|
||||||
Confermato - Procedi ora
|
|
||||||
</Button>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>
|
|
||||||
<p>Il documento non è più disponibile</p>
|
|
||||||
<p>Se hai bisogno di una copia, contattaci via email o chat.</p>
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const PostConfermaSection = () => {
|
|
||||||
const { servizio, servizioId } = useServizio();
|
|
||||||
const { data, annuncioId } = useServizioAnnuncio();
|
|
||||||
|
|
||||||
const saldoPaid = servizio.isOkSaldo;
|
|
||||||
const consulenzaPaid = servizio.isOkConsulenza;
|
|
||||||
|
|
||||||
if (!saldoPaid) {
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col gap-1">
|
|
||||||
<h3 className="font-semibold">
|
|
||||||
Questo annuncio è stato confermato, procedi al saldo:
|
|
||||||
</h3>
|
|
||||||
<SaldoButton annuncioId={annuncioId} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!data.doc_contratto_added) {
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col gap-1">
|
|
||||||
<h3 className="font-semibold text-green-500">
|
|
||||||
Ci siamo quasi! Stiamo preparando il contratto per te.
|
|
||||||
</h3>
|
|
||||||
<h3 className="font-semibold">
|
|
||||||
Una volta pronto, riceverai una notifica via email.
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col gap-2">
|
|
||||||
<h3 className="font-semibold">
|
|
||||||
{consulenzaPaid
|
|
||||||
? "Il contratto è pronto, puoi visualizzarlo:"
|
|
||||||
: "Il contratto è pronto, puoi visualizzarlo e procedere al saldo:"}
|
|
||||||
</h3>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
{data.doc_contratto_ref ? (
|
|
||||||
<Link
|
|
||||||
aria-label="Visualizza contratto"
|
|
||||||
href={`/servizio/contratto/${servizioId}/${annuncioId}`}
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<Button className="w-full sm:w-fit">
|
|
||||||
<FileText className="size-5" />
|
|
||||||
Visualizza il contratto
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
) : (
|
|
||||||
<TooltipProvider delayDuration={0}>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<Button className="w-fit cursor-not-allowed opacity-50">
|
|
||||||
<FileText className="size-5" />
|
|
||||||
Visualizza il contratto
|
|
||||||
</Button>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>
|
|
||||||
<p>Il documento non è più disponibile</p>
|
|
||||||
<p>Se hai bisogno di una copia, contattaci via email o chat.</p>
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!consulenzaPaid && data.contratto_tipo && <SaldoConsulenzaButton />}
|
|
||||||
|
|
||||||
{data.doc_registrazione_added &&
|
|
||||||
(data.doc_registrazione_ref ? (
|
|
||||||
<Link
|
|
||||||
aria-label="Visualizza registrazione"
|
|
||||||
href={`/servizio/contratto-registrazione/${servizioId}/${annuncioId}`}
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<Button className="w-fit">
|
|
||||||
<FileBadge className="size-5" />
|
|
||||||
Visualizza la registrazione
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
) : (
|
|
||||||
<TooltipProvider delayDuration={0}>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<Button className="w-fit cursor-not-allowed opacity-50">
|
|
||||||
<FileBadge className="size-5" />
|
|
||||||
Visualizza la registrazione
|
|
||||||
</Button>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>
|
|
||||||
<p>Il documento non è più disponibile</p>
|
|
||||||
<p>
|
|
||||||
Se hai bisogno di una copia, contattaci via email o chat.
|
|
||||||
</p>
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Interactions = () => {
|
|
||||||
const { data } = useServizioAnnuncio();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="flex w-full flex-col flex-wrap gap-2 sm:flex-row">
|
|
||||||
<ContattiProprietarioModal />
|
|
||||||
|
|
||||||
<SezioneConferma />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{data.accettato_conferma_at != null && <PostConfermaSection />}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SaldoButton = ({
|
|
||||||
annuncioId,
|
|
||||||
variant = "info",
|
|
||||||
className,
|
|
||||||
}: {
|
|
||||||
annuncioId: AnnunciId;
|
|
||||||
variant?: ButtonConfigs["variant"];
|
|
||||||
className?: string;
|
|
||||||
}) => {
|
|
||||||
const { servizioId } = useServizio();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const { mutate } = api.servizio.setupSaldoServizio.useMutation({
|
|
||||||
onMutate: () => {
|
|
||||||
toast.loading("Caricamento ...", { id: "preparazioneSaldo" });
|
|
||||||
},
|
|
||||||
onSuccess: async (data) => {
|
|
||||||
toast.success("Pagamento saldo preparato", {
|
|
||||||
id: "preparazioneSaldo",
|
|
||||||
});
|
|
||||||
|
|
||||||
await router.push(`/servizio/pagamento/${data}`);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
aria-label="Procedi al saldo"
|
|
||||||
className={cn("w-fit", className)}
|
|
||||||
onClick={() => {
|
|
||||||
mutate({
|
|
||||||
annuncioId,
|
|
||||||
servizioId,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
variant={variant}
|
|
||||||
>
|
|
||||||
<PackageCheck className="size-5" />
|
|
||||||
Procedi al saldo
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const SaldoConsulenzaButton = ({
|
|
||||||
variant = "info",
|
|
||||||
className,
|
|
||||||
}: {
|
|
||||||
variant?: ButtonConfigs["variant"];
|
|
||||||
className?: string;
|
|
||||||
}) => {
|
|
||||||
const { annuncioId } = useServizioAnnuncio();
|
|
||||||
const { servizioId } = useServizio();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const { mutate } = api.servizio.setupSaldoConsulenzaServizio.useMutation({
|
|
||||||
onMutate: () => {
|
|
||||||
toast.loading("Caricamento ...", { id: "preparazioneSaldo" });
|
|
||||||
},
|
|
||||||
onSuccess: async (data) => {
|
|
||||||
toast.success("Pagamento saldo preparato", {
|
|
||||||
id: "preparazioneSaldo",
|
|
||||||
});
|
|
||||||
|
|
||||||
await router.push(`/servizio/pagamento/${data}`);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
aria-label="Procedi al saldo consulenza"
|
|
||||||
className={cn("w-fit", className)}
|
|
||||||
onClick={() => {
|
|
||||||
mutate({
|
|
||||||
annuncioId,
|
|
||||||
servizioId,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
variant={variant}
|
|
||||||
>
|
|
||||||
<PackageCheck className="size-5" />
|
|
||||||
Procedi al saldo della consulenza
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -4,11 +4,11 @@ import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
|
import { SaldoButton } from "~/components/servizio/annuncio_actions";
|
||||||
import {
|
import {
|
||||||
AnnuncioCard,
|
AnnuncioCard,
|
||||||
AnnuncioDisplay,
|
AnnuncioDisplay,
|
||||||
} from "~/components/servizio/annuncio_card";
|
} from "~/components/servizio/annuncio_card";
|
||||||
import { SaldoButton } from "~/components/servizio/interactions";
|
|
||||||
import { ServizioActions } from "~/components/servizio/servizio_actions";
|
import { ServizioActions } from "~/components/servizio/servizio_actions";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import {
|
import {
|
||||||
|
|
@ -65,7 +65,30 @@ const ServizioCard = ({
|
||||||
|
|
||||||
export const ServizioContent = () => {
|
export const ServizioContent = () => {
|
||||||
const { servizio, isAdmin, userId, servizioId } = useServizio();
|
const { servizio, isAdmin, userId, servizioId } = useServizio();
|
||||||
|
const utils = api.useUtils();
|
||||||
|
const { mutate: updateServizio } = api.servizio.updateServizio.useMutation({
|
||||||
|
onError: (error) => {
|
||||||
|
toast.error(error.message);
|
||||||
|
},
|
||||||
|
onSuccess: async () => {
|
||||||
|
toast.success("Servizio modificato con successo");
|
||||||
|
await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
|
||||||
|
await utils.servizio.getPacksSolution.invalidate({ servizioId });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const { mutate } = api.servizio.removeAnnuncioServizio.useMutation({
|
||||||
|
onError: (error) => {
|
||||||
|
console.error(error);
|
||||||
|
toast.error("Errore durante la rimozione dell'annuncio");
|
||||||
|
},
|
||||||
|
onSuccess: async () => {
|
||||||
|
await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
|
||||||
|
await utils.servizio.getCompatibileAnnunci.invalidate({
|
||||||
|
servizioId,
|
||||||
|
});
|
||||||
|
toast.success("Annuncio rimosso");
|
||||||
|
},
|
||||||
|
});
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const id = router.asPath.split("#")[1];
|
const id = router.asPath.split("#")[1];
|
||||||
|
|
@ -115,30 +138,6 @@ export const ServizioContent = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!servizio.isOkAcconto || servizio.decorrenza === null) {
|
if (!servizio.isOkAcconto || servizio.decorrenza === null) {
|
||||||
const utils = api.useUtils();
|
|
||||||
const { mutate: updateServizio } = api.servizio.updateServizio.useMutation({
|
|
||||||
onError: (error) => {
|
|
||||||
toast.error(error.message);
|
|
||||||
},
|
|
||||||
onSuccess: async () => {
|
|
||||||
toast.success("Servizio modificato con successo");
|
|
||||||
await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
|
|
||||||
await utils.servizio.getPacksSolution.invalidate({ servizioId });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const { mutate } = api.servizio.removeAnnuncioServizio.useMutation({
|
|
||||||
onError: (error) => {
|
|
||||||
console.error(error);
|
|
||||||
toast.error("Errore durante la rimozione dell'annuncio");
|
|
||||||
},
|
|
||||||
onSuccess: async () => {
|
|
||||||
await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
|
|
||||||
await utils.servizio.getCompatibileAnnunci.invalidate({
|
|
||||||
servizioId,
|
|
||||||
});
|
|
||||||
toast.success("Annuncio rimosso");
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return (
|
return (
|
||||||
<ServizioCard
|
<ServizioCard
|
||||||
content={
|
content={
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { CircleUser, Navigation, Phone, TriangleAlert } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useMemo, useState } from "react";
|
import { useMemo, useState } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
|
import { cn } from "~/lib/utils";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider";
|
import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider";
|
||||||
import type { UsersStorageUserStorageId } from "~/schemas/public/UsersStorage";
|
import type { UsersStorageUserStorageId } from "~/schemas/public/UsersStorage";
|
||||||
|
|
@ -20,7 +21,7 @@ import {
|
||||||
} from "../custom_ui/credenza";
|
} from "../custom_ui/credenza";
|
||||||
import { LoadingPage } from "../loading";
|
import { LoadingPage } from "../loading";
|
||||||
import { WhatsAppIcon2 } from "../svgs";
|
import { WhatsAppIcon2 } from "../svgs";
|
||||||
import { Button } from "../ui/button";
|
import { Button, buttonVariants } from "../ui/button";
|
||||||
|
|
||||||
export const ContattiProprietarioModal = () => {
|
export const ContattiProprietarioModal = () => {
|
||||||
const { servizio } = useServizio();
|
const { servizio } = useServizio();
|
||||||
|
|
@ -47,7 +48,7 @@ export const ContattiProprietarioModal = () => {
|
||||||
className="w-full md:w-fit"
|
className="w-full md:w-fit"
|
||||||
variant="success"
|
variant="success"
|
||||||
>
|
>
|
||||||
<CircleUser className="size-5" />
|
<CircleUser />
|
||||||
Contatti
|
Contatti
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -56,7 +57,7 @@ export const ContattiProprietarioModal = () => {
|
||||||
className="w-full md:w-fit"
|
className="w-full md:w-fit"
|
||||||
variant="warning"
|
variant="warning"
|
||||||
>
|
>
|
||||||
<CircleUser className="size-5" />
|
<CircleUser />
|
||||||
Ottieni i contatti
|
Ottieni i contatti
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
@ -340,7 +341,7 @@ const PostUnlock = () => {
|
||||||
</p>
|
</p>
|
||||||
{navigationUrl && (
|
{navigationUrl && (
|
||||||
<a
|
<a
|
||||||
className="inline-flex items-center gap-2 rounded-md border border-border px-3 py-2 hover:bg-accent"
|
className={cn(buttonVariants({ variant: "info" }))}
|
||||||
href={navigationUrl}
|
href={navigationUrl}
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
|
|
||||||
|
|
@ -182,19 +182,20 @@ const ServizioBasicActions = ({ className }: { className?: string }) => {
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ServizioPacksInfos = ({
|
export const ServizioPacksInfos = () => {
|
||||||
title = "Prezzi:",
|
|
||||||
}: {
|
|
||||||
title?: string;
|
|
||||||
}) => {
|
|
||||||
const { servizio } = useServizio();
|
const { servizio } = useServizio();
|
||||||
const { data: packs } = api.servizio.getPacksSolution.useQuery({
|
const { data: packs } = api.servizio.getPacksSolution.useQuery({
|
||||||
servizioId: servizio.servizio_id,
|
servizioId: servizio.servizio_id,
|
||||||
});
|
});
|
||||||
|
const title = "Prezzi:";
|
||||||
|
const sub = "(basati sui parametri di ricerca)";
|
||||||
if (!packs) return null;
|
if (!packs) return null;
|
||||||
return (
|
return (
|
||||||
<div className="w-full space-y-2">
|
<div className="w-full space-y-2">
|
||||||
<h3 className="font-semibold text-lg">{title}</h3>
|
<div className="flex flex-wrap items-center gap-2">
|
||||||
|
<h3 className="font-semibold text-lg">{title}</h3>
|
||||||
|
<span className="text-muted-foreground text-sm">{sub}</span>
|
||||||
|
</div>
|
||||||
<div className="flex w-full flex-col gap-4 md:flex-row">
|
<div className="flex w-full flex-col gap-4 md:flex-row">
|
||||||
<div className="flex flex-1 flex-col gap-2 rounded-md bg-secondary/50 p-2">
|
<div className="flex flex-1 flex-col gap-2 rounded-md bg-secondary/50 p-2">
|
||||||
{packs.acconto.success ? (
|
{packs.acconto.success ? (
|
||||||
|
|
|
||||||
|
|
@ -31,38 +31,32 @@ export const AnnunciRichiesti = ({ userId }: { userId: UsersId }) => {
|
||||||
<Accordion collapsible type="single">
|
<Accordion collapsible type="single">
|
||||||
<AccordionItem className="space-y-4" value="compatibili">
|
<AccordionItem className="space-y-4" value="compatibili">
|
||||||
<AccordionTrigger className="cursor-pointer rounded-md border-2 border-pink-500 bg-muted p-2">
|
<AccordionTrigger className="cursor-pointer rounded-md border-2 border-pink-500 bg-muted p-2">
|
||||||
Annunci Richiesti:
|
Annunci Richiesti dall'Utente ({data.length}):
|
||||||
</AccordionTrigger>
|
</AccordionTrigger>
|
||||||
<AccordionContent>
|
<AccordionContent>
|
||||||
<div className="flex flex-col flex-wrap gap-5">
|
<div className="grid grid-cols-1 gap-3 lg:grid-cols-2">
|
||||||
{!data || data.length === 0 ? (
|
{data.map((a) => {
|
||||||
<div className="flex items-center justify-center gap-1 rounded-md bg-muted p-4 sm:flex">
|
return (
|
||||||
<span>
|
<BasicAnnuncioCard
|
||||||
Nessun annuncio compatibile trovato. Amplia la ricerca per
|
className="w-full border-2 border-pink-500"
|
||||||
trovare annunci compatibili.
|
data={a}
|
||||||
</span>
|
interactions={
|
||||||
</div>
|
<Button
|
||||||
) : (
|
onClick={() => {
|
||||||
data.map((a) => {
|
deleteAnnuncio({ annuncioId: a.id, userId });
|
||||||
return (
|
}}
|
||||||
<BasicAnnuncioCard
|
variant="destructive"
|
||||||
className="w-full border-2 border-pink-500"
|
>
|
||||||
data={a}
|
Rimuovi
|
||||||
interactions={
|
<Trash2 className="size-4" />
|
||||||
<Button
|
</Button>
|
||||||
onClick={() => {
|
}
|
||||||
deleteAnnuncio({ annuncioId: a.id, userId });
|
key={a.id}
|
||||||
}}
|
/>
|
||||||
variant="destructive"
|
);
|
||||||
>
|
})}
|
||||||
Rimuovi
|
{data.length % 2 === 1 && (
|
||||||
<Trash2 className="size-4" />
|
<div className="size-full rounded-md border border-(--pattern-fg) bg-[repeating-linear-gradient(45deg,var(--pattern-fg)_0,var(--pattern-fg)_1px,transparent_0,transparent_50%)] bg-size-[10px_10px] bg-fixed opacity-10 [--pattern-fg:#696969] dark:[--pattern-fg:#e1e1e1]" />
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
key={a.id}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</AccordionContent>
|
</AccordionContent>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import type * as React from "react";
|
||||||
import { cn } from "~/lib/utils";
|
import { cn } from "~/lib/utils";
|
||||||
|
|
||||||
const buttonVariants = cva(
|
const buttonVariants = cva(
|
||||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all cursor-pointer disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-hidden focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all cursor-pointer disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-5 shrink-0 [&_svg]:shrink-0 outline-hidden focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||||
{
|
{
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
size: "default",
|
size: "default",
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,7 @@ export const FormEditServizio = ({
|
||||||
type="button"
|
type="button"
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
>
|
>
|
||||||
<X className="size-5" />
|
<X />
|
||||||
Reset Decorrenza
|
Reset Decorrenza
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -488,7 +488,7 @@ export const FormNewServizio = ({
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Button
|
<Button
|
||||||
className={cn(
|
className={cn(
|
||||||
"h-[42px] w-full pl-3 text-left font-medium",
|
"h-10.5 w-full pl-3 text-left font-medium",
|
||||||
!field.value && "text-muted-foreground",
|
!field.value && "text-muted-foreground",
|
||||||
"rounded-lg border border-neutral-300 shadow-xs outline-hidden file:border-0 file:bg-transparent file:font-medium file:text-sm disabled:cursor-not-allowed disabled:opacity-50 dark:focus:border-transparent",
|
"rounded-lg border border-neutral-300 shadow-xs outline-hidden file:border-0 file:bg-transparent file:font-medium file:text-sm disabled:cursor-not-allowed disabled:opacity-50 dark:focus:border-transparent",
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -59,10 +59,13 @@ import { cn } from "~/lib/utils";
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import { useCatasto } from "~/providers/CatastoProvider";
|
import { useCatasto } from "~/providers/CatastoProvider";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
import type { Servizio } from "~/schemas/public/Servizio";
|
import type { Servizio, ServizioUpdate } from "~/schemas/public/Servizio";
|
||||||
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
|
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
|
||||||
import type { Users, UsersId } from "~/schemas/public/Users";
|
import type { Users, UsersId } from "~/schemas/public/Users";
|
||||||
import type { UsersAnagrafica } from "~/schemas/public/UsersAnagrafica";
|
import type {
|
||||||
|
UsersAnagrafica,
|
||||||
|
UsersAnagraficaUpdate,
|
||||||
|
} from "~/schemas/public/UsersAnagrafica";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
|
|
||||||
type InitialData = {
|
type InitialData = {
|
||||||
|
|
@ -400,56 +403,63 @@ export const FormNewServizioAcquisto = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
function onSubmit(fields: FormNewServizioValues) {
|
function onSubmit(fields: FormNewServizioValues) {
|
||||||
|
const a: UsersAnagraficaUpdate = {
|
||||||
|
azienda: fields.azienda,
|
||||||
|
cap_residenza: fields.cap_recapiti,
|
||||||
|
civico_residenza: fields.civico_recapiti,
|
||||||
|
codice_destinatario: fields.codice_destinatario,
|
||||||
|
codice_fiscale: fields.codice_fiscale,
|
||||||
|
comune_residenza: fields.citta_recapiti,
|
||||||
|
data_nascita: fields.data_nascita,
|
||||||
|
fatturazione_aziendale: fields.fatturazione_aziendale,
|
||||||
|
idanagrafica: initialData.anagrafica?.idanagrafica,
|
||||||
|
legale_rappresentante: fields.legale_rappresentante,
|
||||||
|
luogo_nascita: fields.luogo_nascita,
|
||||||
|
nazione_nascita: fields.nazione_nascita,
|
||||||
|
nazione_residenza: fields.nazione_recapiti,
|
||||||
|
p_iva: fields.p_iva,
|
||||||
|
provincia_residenza: fields.provincia_recapiti,
|
||||||
|
ragione_sociale: fields.ragione_sociale,
|
||||||
|
sede_legale: fields.sede_legale,
|
||||||
|
sesso: fields.sesso,
|
||||||
|
userid: userId,
|
||||||
|
via_residenza: fields.indirizzo_recapiti,
|
||||||
|
};
|
||||||
|
const s: ServizioUpdate = {
|
||||||
|
animali: fields.animali,
|
||||||
|
arredato: fields.arredato,
|
||||||
|
ascensore: fields.ascensore,
|
||||||
|
budget: fields.budget,
|
||||||
|
entromese: fields.entromese,
|
||||||
|
fumatori: fields.fumatori,
|
||||||
|
giardino: fields.giardino,
|
||||||
|
motivazione_transitorio: fields.motivazione_transitorio,
|
||||||
|
n_adulti: fields.n_adulti,
|
||||||
|
n_minori: fields.n_minori,
|
||||||
|
parcheggio: fields.parcheggio,
|
||||||
|
permanenza: fields.permanenza,
|
||||||
|
pianoterra: fields.pianoterra,
|
||||||
|
reddito: fields.reddito,
|
||||||
|
terrazzo: fields.terrazzo,
|
||||||
|
tipologia: fields.tipologia,
|
||||||
|
skipPayment: fields.skipPayment,
|
||||||
|
scadenza_motivazione_transitoria: fields.scadenza_motivazione_transitoria,
|
||||||
|
};
|
||||||
|
const u: Pick<
|
||||||
|
Users,
|
||||||
|
"nome" | "cognome" | "email" | "telefono" | "username"
|
||||||
|
> = {
|
||||||
|
cognome: fields.cognome,
|
||||||
|
email: fields.email,
|
||||||
|
nome: fields.nome,
|
||||||
|
telefono: fields.telefono.replace(/\s/g, ""),
|
||||||
|
username: `${fields.nome.trim()} ${fields.cognome.trim()}`,
|
||||||
|
};
|
||||||
mutate({
|
mutate({
|
||||||
anagrafica: {
|
anagrafica: a,
|
||||||
azienda: fields.azienda,
|
servizio: s,
|
||||||
cap_residenza: fields.cap_recapiti,
|
|
||||||
civico_residenza: fields.civico_recapiti,
|
|
||||||
codice_destinatario: fields.codice_destinatario,
|
|
||||||
codice_fiscale: fields.codice_fiscale,
|
|
||||||
comune_residenza: fields.citta_recapiti,
|
|
||||||
data_nascita: fields.data_nascita,
|
|
||||||
fatturazione_aziendale: fields.fatturazione_aziendale,
|
|
||||||
idanagrafica: initialData.anagrafica?.idanagrafica,
|
|
||||||
legale_rappresentante: fields.legale_rappresentante,
|
|
||||||
luogo_nascita: fields.luogo_nascita,
|
|
||||||
nazione_nascita: fields.nazione_nascita,
|
|
||||||
nazione_residenza: fields.nazione_recapiti,
|
|
||||||
p_iva: fields.p_iva,
|
|
||||||
provincia_residenza: fields.provincia_recapiti,
|
|
||||||
ragione_sociale: fields.ragione_sociale,
|
|
||||||
sede_legale: fields.sede_legale,
|
|
||||||
sesso: fields.sesso,
|
|
||||||
userid: userId,
|
|
||||||
via_residenza: fields.indirizzo_recapiti,
|
|
||||||
},
|
|
||||||
servizio: {
|
|
||||||
animali: fields.animali,
|
|
||||||
arredato: fields.arredato,
|
|
||||||
ascensore: fields.ascensore,
|
|
||||||
budget: fields.budget,
|
|
||||||
entromese: fields.entromese,
|
|
||||||
fumatori: fields.fumatori,
|
|
||||||
giardino: fields.giardino,
|
|
||||||
motivazione_transitorio: fields.motivazione_transitorio,
|
|
||||||
n_adulti: fields.n_adulti,
|
|
||||||
n_minori: fields.n_minori,
|
|
||||||
parcheggio: fields.parcheggio,
|
|
||||||
permanenza: fields.permanenza,
|
|
||||||
pianoterra: fields.pianoterra,
|
|
||||||
reddito: fields.reddito,
|
|
||||||
terrazzo: fields.terrazzo,
|
|
||||||
tipologia: fields.tipologia,
|
|
||||||
skipPayment: fields.skipPayment,
|
|
||||||
},
|
|
||||||
servizioId: initialData.servizio.servizio_id,
|
servizioId: initialData.servizio.servizio_id,
|
||||||
user: {
|
user: u,
|
||||||
cognome: fields.cognome,
|
|
||||||
email: fields.email,
|
|
||||||
nome: fields.nome,
|
|
||||||
telefono: fields.telefono.replace(/\s/g, ""),
|
|
||||||
username: `${fields.nome.trim()} ${fields.cognome.trim()}`,
|
|
||||||
},
|
|
||||||
userId,
|
userId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ const Filters = () => {
|
||||||
onClick={ResetParams}
|
onClick={ResetParams}
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
>
|
>
|
||||||
<FilterX className="size-5" /> {t.annunci.filtri_reset}
|
<FilterX /> {t.annunci.filtri_reset}
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
@ -213,7 +213,7 @@ const DrowdownFilters = () => {
|
||||||
<Badge className="w-fit rounded-md bg-secondary px-1.5 py-0.5 text-secondary-foreground dark:group-hover:bg-transparent">
|
<Badge className="w-fit rounded-md bg-secondary px-1.5 py-0.5 text-secondary-foreground dark:group-hover:bg-transparent">
|
||||||
{nFiltri}
|
{nFiltri}
|
||||||
</Badge>
|
</Badge>
|
||||||
<Filter className="size-5" />{" "}
|
<Filter />{" "}
|
||||||
{nFiltri === 1 ? t.annunci.filtro_attivo : t.annunci.filtri_attivi}
|
{nFiltri === 1 ? t.annunci.filtro_attivo : t.annunci.filtri_attivi}
|
||||||
<ChevronDown />
|
<ChevronDown />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -246,12 +246,11 @@ const RicercaHeader = () => {
|
||||||
>
|
>
|
||||||
{!map ? (
|
{!map ? (
|
||||||
<>
|
<>
|
||||||
<MapIcon className="size-5" />{" "}
|
<MapIcon /> <span className="hidden sm:block">Mappa</span>
|
||||||
<span className="hidden sm:block">Mappa</span>
|
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Table className="size-5" />
|
<Table />
|
||||||
<span className="hidden sm:block">Lista</span>
|
<span className="hidden sm:block">Lista</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -611,7 +611,7 @@ const ShareComponent = () => {
|
||||||
<Dialog>
|
<Dialog>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button>
|
<Button>
|
||||||
<Share2 className="size-5" />
|
<Share2 />
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className="sm:max-w-md">
|
<DialogContent className="sm:max-w-md">
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import { LoadingPage } from "~/components/loading";
|
||||||
import { Status500 } from "~/components/status-page";
|
import { Status500 } from "~/components/status-page";
|
||||||
import { env } from "~/env";
|
import { env } from "~/env";
|
||||||
import type { NextPageWithLayout } from "~/pages/_app";
|
import type { NextPageWithLayout } from "~/pages/_app";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
|
||||||
import type { OrdiniOrdineId } from "~/schemas/public/Ordini";
|
import type { OrdiniOrdineId } from "~/schemas/public/Ordini";
|
||||||
import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper";
|
import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper";
|
||||||
import { zOrdineId } from "~/server/utils/zod_types";
|
import { zOrdineId } from "~/server/utils/zod_types";
|
||||||
|
|
@ -22,7 +21,7 @@ const ServicePurchasePage: NextPageWithLayout<ServizioPurchaseProps> = ({
|
||||||
const { data, isLoading } = api.servizio.getServizioPaymentData.useQuery({
|
const { data, isLoading } = api.servizio.getServizioPaymentData.useQuery({
|
||||||
ordineId,
|
ordineId,
|
||||||
});
|
});
|
||||||
const { t } = useTranslation();
|
|
||||||
const stripePromise = loadStripe(env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY);
|
const stripePromise = loadStripe(env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY);
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ const RiapriConferma: NextPageWithLayout<RiapriConfermaProps> = ({
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
>
|
>
|
||||||
<ArrowLeft className="size-5" />
|
<ArrowLeft />
|
||||||
{t.indietro}
|
{t.indietro}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -243,11 +243,12 @@ export const postAcquistoDataHandler = async ({
|
||||||
}: {
|
}: {
|
||||||
servizioId: ServizioServizioId;
|
servizioId: ServizioServizioId;
|
||||||
userId: UsersId;
|
userId: UsersId;
|
||||||
user: Pick<Users, "nome" | "cognome" | "email" | "telefono">;
|
user: Pick<Users, "nome" | "cognome" | "email" | "telefono" | "username">;
|
||||||
anagrafica: UsersAnagraficaUpdate;
|
anagrafica: UsersAnagraficaUpdate;
|
||||||
servizio: ServizioUpdate;
|
servizio: ServizioUpdate;
|
||||||
}): Promise<{ ordineIdForPayment: OrdiniOrdineId | null }> => {
|
}): Promise<{ ordineIdForPayment: OrdiniOrdineId | null }> => {
|
||||||
try {
|
try {
|
||||||
|
console.log("servizio", servizio);
|
||||||
const servizioData = await db.transaction().execute(async (tx) => {
|
const servizioData = await db.transaction().execute(async (tx) => {
|
||||||
// Update user and anagrafica data
|
// Update user and anagrafica data
|
||||||
await tx
|
await tx
|
||||||
|
|
@ -810,7 +811,7 @@ export const getAllServizioAnnunci = async (userId: UsersId) => {
|
||||||
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().nullsLast(),
|
||||||
)
|
)
|
||||||
.orderBy("servizio_annunci.created_at", "asc")
|
.orderBy("servizio_annunci.created_at", "asc")
|
||||||
.whereRef(
|
.whereRef(
|
||||||
|
|
@ -1321,12 +1322,12 @@ export const userSendConfermaIntent = async ({
|
||||||
mailType: "generic",
|
mailType: "generic",
|
||||||
props: {
|
props: {
|
||||||
noreply: true,
|
noreply: true,
|
||||||
testo: `La tua conferma per l'immobile con codice ${annuncio_codice.codice} è stata ricevuta. Il nostro team la esaminerà a breve. Riceverai una notifica via email per procedere.`,
|
testo: `La tua conferma per l'immobile con codice ${annuncio_codice.codice} è stata inviata con successo. Il nostro team la esaminerà a breve. Riceverai una notifica via email per procedere.`,
|
||||||
title: `Conferma immobile ${annuncio_codice.codice} ricevuta`,
|
title: `Conferma immobile ${annuncio_codice.codice} inviata con successo`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mail: {
|
mail: {
|
||||||
subject: `Conferma immobile ${annuncio_codice.codice} ricevuta`,
|
subject: `Conferma immobile ${annuncio_codice.codice} inviata con successo`,
|
||||||
to: utente.email,
|
to: utente.email,
|
||||||
},
|
},
|
||||||
userId: utente.id,
|
userId: utente.id,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue