import type { ColumnDef, Table } from "@tanstack/react-table";
import {
add,
format,
formatDuration,
intervalToDuration,
isBefore,
} from "date-fns";
import { it } from "date-fns/locale";
import {
CircleCheck,
CircleCheckBig,
ClockFading,
ExternalLink,
Logs,
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 { OrdersModal } from "~/components/servizio/servizio_actions";
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 {
PinnedFiltro,
SearchFiltro,
} from "~/components/ui/dataTable-toolbar";
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "~/components/ui/sheet";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "~/components/ui/tooltip";
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[];
};
export const RichiesteTable = ({ data }: RichiesteTableProps) => {
const tabledata = data;
const columns_titles = {
id: "ID Ordine",
username: "Utente",
note: "Note",
decorrenza: "Decorrenza",
status: "Status",
tipologia: "Tipo",
annunci: "Annunci",
ordini: "Ordini",
interruzione_expires_at: "Scad. interr.",
actions: "Azioni",
};
const statusOptions = [
{ label: "Attesa di attivazione", value: "attesa_attivazione" },
{ label: "Acconto pagato", value: "acconto_pagato" },
{ label: "Saldo pagato", value: "saldo_pagato" },
{ label: "Conferma in corso", value: "conferma" },
];
const type_options = [
{ label: "Transitorio", value: TipologiaPosizioneEnum.Transitorio },
{ label: "Stabile", value: TipologiaPosizioneEnum.Stabile },
];
type Column = (typeof tabledata)[number];
const tableRef = useRef
| null>(null);
const utils = api.useUtils();
const { onMutate, onSettled } = MutationPageRestore(tableRef);
const { mutate, isPending } = api.users.editUser.useMutation({
onMutate,
onSettled,
onSuccess: async () => {
toast.success("Note aggiornate con successo");
await utils.users.invalidate();
await utils.servizio.invalidate();
},
onError: (error) => {
toast.error(error.message);
},
});
const searchFiltro: SearchFiltro = {
columnName: "username",
placeholder: "Cerca...",
};
const columns: ColumnDef[] = [
{
accessorKey: "id",
cell: () => null,
enableHiding: false,
header: () => null,
},
{
accessorKey: "username",
cell: ({ row }) => {
const data = row.original;
return (
{data.username}
{data.username}
Profilo
WhatsApp
);
},
enableHiding: false,
header: ({ column }) => (
),
},
{
accessorKey: "note",
cell: ({ row }) => {
const note = row.original.note;
return (
);
},
header: ({ column }) => (
),
enableSorting: false,
},
{
accessorKey: "decorrenza",
cell: ({ row }) => {
let decorrenzaColor = "";
let decorrenzaTooltip = "";
if (!row.original.isOkAcconto || !row.original.decorrenza) {
decorrenzaColor = "text-muted-foreground";
decorrenzaTooltip = "Attesa di attivazione";
} else if (row.original.isInterrotto) {
decorrenzaColor = "text-destructive";
decorrenzaTooltip = "Servizio interrotto";
} else if (row.original.isOkAcconto && !row.original.isOkSaldo) {
decorrenzaColor = "text-warning";
decorrenzaTooltip = "Attesa di saldo";
}
return (
{row.original.decorrenza
? format(row.original.decorrenza, "dd/MM")
: "---"}
{decorrenzaTooltip}
);
},
enableHiding: false,
header: ({ column }) => (
),
sortingFn: "datetime",
},
{
accessorKey: "tipologia",
cell: ({ row }) => {
const { tipologia } = row.original;
return (
{tipologia.toString()}
);
},
filterFn: (row, id, value) => {
return value.includes(row.getValue(id));
},
header: ({ column }) => (
),
},
{
accessorKey: "status",
cell: ({ row }) => {
let badgeClass = "";
let contents: React.ReactNode;
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 pag. 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,
);
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,
);
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,
);
if (annuncioAttesaConferma.length > 0) {
badgeClass = "border-blue-500 bg-blue-500/10 text-blue-500";
contents = (
<>
Attesa accett. conferma
>
);
return;
}
badgeClass = "border-green-500 bg-green-500/10 text-green-500";
contents = (
<>
Attivo
>
);
};
resolveStatus();
return (
svg]:size-4",
badgeClass,
)}
variant="outline"
>
{contents}
);
},
filterFn: (row, id, value) => {
return value.includes(row.getValue(id));
},
header: ({ column }) => (
),
},
{
accessorKey: "interruzione_expires_at",
cell: ({ row }) => {
if (row.original.isInterrotto) return "---";
if (!row.original.decorrenza) return "---";
const expiresAt = add(row.original.decorrenza, {
days: row.original.interruzioneDays,
});
const timeLeft = intervalToDuration({
start: new Date(),
end: expiresAt,
});
const daysLeft = timeLeft.days || 0;
let badgeColor = "";
if (daysLeft > 5) {
badgeColor = "border-green-500 bg-green-500/10 text-green-500";
} else if (daysLeft > 0) {
badgeColor = "border-yellow-500 bg-yellow-500/10 text-yellow-500";
} else {
badgeColor = "border-red-500 bg-red-500/10 text-red-500";
}
return (
{format(expiresAt, "dd/MM")}
{daysLeft > 0 ? (
{formatDuration(timeLeft, { locale: it, format: ["days"] })}{" "}
rimanenti
) : (
Interruzione scaduta
)}
);
},
enableSorting: false,
header: ({ column }) => (
),
},
{
accessorKey: "annunci_servizio",
cell: ({ row }) => {
const annunci = row.original.annunci_servizio;
return (
Annunci Inseriti
Desc
{annunci.map((a) => (
))}
);
},
header: ({ column }) => (
),
enableSorting: false,
},
{
accessorKey: "ordini",
cell: ({ row }) => {
return (
);
},
header: ({ column }) => (
),
enableSorting: false,
},
{
cell: ({ row }) => {
return (
);
},
enableHiding: false,
id: "actions",
},
];
const pinnedFiltri: PinnedFiltro[] = [
{
columnName: "status",
options: statusOptions,
title: "Stato Ordine",
},
{
columnName: "tipologia",
options: type_options,
title: "Tipo Ordine",
},
];
return (
(tableRef.current = t)}
pinnedFiltri={pinnedFiltri}
searchColumn={searchFiltro}
/>
);
};