From bb8c796fa8cc4a6b6475bf63cfcdca14b09f4e36 Mon Sep 17 00:00:00 2001 From: Marco Pedone Date: Mon, 30 Mar 2026 16:26:03 +0200 Subject: [PATCH] feat: enhance RichiesteTable with context menu for user actions and improve status resolution logic --- .../src/components/servizio/servizio.tsx | 36 ++- .../src/components/tables/richieste-table.tsx | 299 +++++++++++++----- .../server/controllers/servizio.controller.ts | 4 +- 3 files changed, 245 insertions(+), 94 deletions(-) diff --git a/apps/infoalloggi/src/components/servizio/servizio.tsx b/apps/infoalloggi/src/components/servizio/servizio.tsx index e4c521e..376644d 100644 --- a/apps/infoalloggi/src/components/servizio/servizio.tsx +++ b/apps/infoalloggi/src/components/servizio/servizio.tsx @@ -328,8 +328,8 @@ const Content = () => { - @@ -552,10 +552,10 @@ const Main = () => { } //servizio scaduto se decorrenza + 60 giorni è passato e non è ok saldo if ( - new Date() > - add(servizio.decorrenza, { - days: DEFAULT_SERVIZIO_DURATION_DAYS, - }) && + isBefore( + add(servizio.decorrenza, { days: DEFAULT_SERVIZIO_DURATION_DAYS }), + new Date(), + ) && !servizio.isOkSaldo ) { //todo capire come fare con saldo quando scade @@ -586,6 +586,30 @@ const Main = () => { ); })} + {isAdmin && ( +
+

Altri annunci:

+
+ {servizio.annunci + .filter((a) => !a.accettato_conferma_at) + .map((data) => { + return ( + + + + ); + })} + {servizio.annunci.length > 1 && + servizio.annunci.length % 2 === 1 && ( +
+ )} +
+
+ )} ); } diff --git a/apps/infoalloggi/src/components/tables/richieste-table.tsx b/apps/infoalloggi/src/components/tables/richieste-table.tsx index e52db89..79136a5 100644 --- a/apps/infoalloggi/src/components/tables/richieste-table.tsx +++ b/apps/infoalloggi/src/components/tables/richieste-table.tsx @@ -1,22 +1,36 @@ import type { ColumnDef, Table } from "@tanstack/react-table"; -import { add, format, formatDuration, intervalToDuration } from "date-fns"; +import { + add, + format, + formatDuration, + intervalToDuration, + isBefore, +} from "date-fns"; import { it } from "date-fns/locale"; import { CircleCheck, CircleCheckBig, - CircleEllipsis, ClockFading, ExternalLink, SearchX, + UserCog, } from "lucide-react"; import Link from "next/link"; import { useRef } from "react"; import toast from "react-hot-toast"; import { NotePopover } from "~/components/notePopover"; import { AnnuncioCardRichieste } from "~/components/servizio/annuncio_card"; +import { WhatsAppIcon2 } from "~/components/svgs"; import { Badge } from "~/components/ui/badge"; import { Button } from "~/components/ui/button"; +import { + ContextMenu, + ContextMenuContent, + ContextMenuItem, + ContextMenuLabel, + ContextMenuTrigger, +} from "~/components/ui/context-menu"; import { DataTable } from "~/components/ui/data-table"; import { DataTableColumnHeader } from "~/components/ui/dataTable-header"; import type { @@ -39,9 +53,11 @@ import { import { UserAvatar } from "~/components/user_avatar"; import { MutationPageRestore } from "~/lib/tableUtils"; import { cn } from "~/lib/utils"; +import OrderTypeEnum from "~/schemas/public/OrderTypeEnum"; import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum"; import type { RichiesteData } from "~/server/controllers/servizio.controller"; import { api } from "~/utils/api"; +import { DEFAULT_SERVIZIO_DURATION_DAYS } from "~/utils/config"; type RichiesteTableProps = { data: RichiesteData[]; @@ -101,20 +117,55 @@ export const RichiesteTable = ({ data }: RichiesteTableProps) => { { accessorKey: "username", cell: ({ row }) => { + const data = row.original; return ( - - - - {row.original.username} - - + + + + + {data.username} + + + + + + {data.username} + + + + + Profilo + + + + + + + WhatsApp + + + + ); }, enableHiding: false, @@ -215,44 +266,154 @@ export const RichiesteTable = ({ data }: RichiesteTableProps) => { cell: ({ row }) => { let badgeClass = ""; let contents: React.ReactNode; - const annunci = row.original.annunci_servizio; - const awaitingConferma = annunci.some( - (a) => a.user_confirmed_at !== null && !a.hasConfermaAdmin, - ); - const hasConfermaAdmin = annunci.some((a) => a.hasConfermaAdmin); - if (row.original.isInterrotto) { - badgeClass = "border-destructive bg-destructive/10 text-destructive"; - contents = ( - <> - - Interrotto - + + const resolveStatus = () => { + if (row.original.isInterrotto) { + badgeClass = + "border-destructive bg-destructive/10 text-destructive"; + contents = ( + <> + + Interrotto + + ); + return; + } + if (!row.original.onboardOk) { + badgeClass = "border-pink-500 bg-pink-500/10 text-pink-600"; + contents = ( + <> + + Onboarding + + ); + return; + } + if (!row.original.isOkAcconto || !row.original.decorrenza) { + const acconti = row.original.ordini_servizio.filter( + (o) => o.type === OrderTypeEnum.Acconto, + ); + + const activeAcconto = acconti.find((a) => a.isActive); + + if (activeAcconto) { + badgeClass = "border-yellow-500 bg-yellow-500/10 text-yellow-600"; + contents = ( + <> + + Attesa attivazione + + ); + } else { + badgeClass = "border-yellow-500 bg-yellow-500/10 text-yellow-600"; + contents = ( + <> + + Attesa pagamento acconto + + ); + } + return; + } + if ( + isBefore( + add(row.original.decorrenza, { + days: DEFAULT_SERVIZIO_DURATION_DAYS, + }), + new Date(), + ) && + !row.original.isOkSaldo + ) { + badgeClass = "border-red-500 bg-red-500/10 text-red-500"; + contents = ( + <> + + Scaduto + + ); + return; + } + + const contrattoInserito = row.original.annunci_servizio.filter( + (a) => a.doc_contratto_added, ); - } else if (!row.original.onboardOk) { - badgeClass = "border-yellow-500 bg-yellow-500/10 text-yellow-600"; - contents = ( - <> - - Attesa attivazione - + if (contrattoInserito.length > 0) { + if (row.original.isOkSaldo) { + if (row.original.isOkConsulenza) { + badgeClass = "border-blue-500 bg-blue-500/10 text-blue-500"; + contents = ( + <> + + Confermato + + ); + return; + } + if ( + row.original.ordini_servizio.some( + (o) => o.type === OrderTypeEnum.Consulenza && !o.isActive, + ) + ) { + badgeClass = + "border-yellow-500 bg-yellow-500/10 text-yellow-600"; + contents = ( + <> + + Consulenza da pagare + + ); + return; + } + badgeClass = "border-yellow-500 bg-yellow-500/10 text-yellow-600"; + contents = ( + <> + + Consulenza da inserire + + ); + return; + } + } + + const annuncioConfermato = row.original.annunci_servizio.filter( + (a) => a.accettato_conferma_at !== null, ); - } else if (awaitingConferma) { - badgeClass = "border-sky-500 bg-sky-500/10 text-sky-500"; - contents = ( - <> - - In Conferma - + if (annuncioConfermato.length > 0) { + if (row.original.isOkSaldo) { + badgeClass = "border-blue-500 bg-blue-500/10 text-blue-500"; + contents = ( + <> + + Confermato + + ); + } else { + badgeClass = "border-yellow-500 bg-yellow-500/10 text-yellow-600"; + contents = ( + <> + + Attesa saldo + + ); + } + + return; + } + + const annuncioAttesaConferma = row.original.annunci_servizio.filter( + (a) => a.accettato_conferma_at == null && a.doc_conferma_added, ); - } else if (row.original.isOkSaldo && hasConfermaAdmin) { - badgeClass = "border-blue-500 bg-blue-500/10 text-blue-500"; - contents = ( - <> - - Saldo pagato - - ); - } else if (row.original.isOkAcconto) { + if (annuncioAttesaConferma.length > 0) { + badgeClass = "border-blue-500 bg-blue-500/10 text-blue-500"; + contents = ( + <> + + Attesa accettazione conferma + + ); + return; + } + badgeClass = "border-green-500 bg-green-500/10 text-green-500"; contents = ( <> @@ -260,7 +421,8 @@ export const RichiesteTable = ({ data }: RichiesteTableProps) => { Attivo ); - } + }; + resolveStatus(); return ( { cell: ({ row }) => { const annunci = row.original.annunci_servizio; return ( - // - // - // - // - // - // - // Annunci Inseriti - // - // Desc - // - // - //
- // {annunci.map((a) => ( - // - // ))} - //
- //
- //