infoalloggi-monorepo/apps/infoalloggi/src/components/tables/orders-table.tsx

292 lines
6.7 KiB
TypeScript
Raw Normal View History

2025-08-28 18:27:07 +02:00
import type { ColumnDef } from "@tanstack/react-table";
import { Circle, CircleCheck, ExternalLink } from "lucide-react";
2025-08-28 18:27:07 +02:00
import Link from "next/link";
import { useState } from "react";
import {
AdminWrapperOrdiniModal,
UserOrdiniModal,
} from "~/components/area-riservata/ordini";
2025-08-04 17:45:44 +02:00
import { DataTable } from "~/components/custom_ui/data-table";
2025-08-28 18:27:07 +02:00
import { DataTableColumnHeader } from "~/components/custom_ui/dataTable-header";
2025-08-04 17:45:44 +02:00
import type {
2025-08-28 18:27:07 +02:00
PinnedFiltro,
SearchFiltro,
2025-08-04 17:45:44 +02:00
} from "~/components/custom_ui/dataTable-toolbar";
import { Button } from "~/components/ui/button";
import { formatCurrency } from "~/lib/utils";
2025-08-04 17:45:44 +02:00
import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
import type { OrdiniOrdineId } from "~/schemas/public/Ordini";
2025-08-28 18:27:07 +02:00
import PaymentStatusEnum from "~/schemas/public/PaymentStatusEnum";
import type { UsersId } from "~/schemas/public/Users";
import type { Ordini_w_Utente } from "~/server/controllers/ordini.controller";
2025-08-04 17:45:44 +02:00
type PaymentsTableProps = {
data: Ordini_w_Utente[];
2025-08-28 18:27:07 +02:00
isAdmin: boolean;
userId?: UsersId;
filter: OrdiniOrdineId | null;
2025-08-04 17:45:44 +02:00
};
const StatusMapping = (status: PaymentStatusEnum | null) => {
switch (status) {
case PaymentStatusEnum.success:
return "Successo";
case PaymentStatusEnum.processing:
return "In lavorazione";
case PaymentStatusEnum.failed:
return "Errore";
default:
return "Non completato";
}
};
export const OrdiniTable = ({
data,
isAdmin,
userId,
filter,
}: PaymentsTableProps) => {
2025-08-28 18:27:07 +02:00
const tabledata = data.map((row) => {
return {
2025-08-29 16:18:32 +02:00
actions: "Azioni",
created_at: row.created_at,
2025-08-28 18:27:07 +02:00
id: row.ordine_id,
status: row.isActive,
payment_status: row.paymentstatus,
importo: row.amount_cent,
2025-08-29 16:18:32 +02:00
packid: row.packid,
tipo: row.type,
userId: row.userid,
username: row.username,
2025-08-28 18:27:07 +02:00
};
});
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
const columns_titles = {
id: "ID Ordine",
2025-08-29 16:18:32 +02:00
actions: "Azioni",
2025-08-28 18:27:07 +02:00
created_at: "Creato il",
importo: "Importo",
status: "Status",
payment_status: "Pagamento",
2025-08-29 16:18:32 +02:00
packid: "ID Pacchetto",
tipo: "Tipo",
username: "Utente",
2025-08-28 18:27:07 +02:00
};
const statusOptions = [
{ label: "Attivo", value: "true" },
{ label: "Non attivo", value: "false" },
2025-08-28 18:27:07 +02:00
];
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
const type_options = [
2025-08-29 16:18:32 +02:00
{ label: "Acconto", value: OrderTypeEnum.Acconto },
{ label: "Saldo", value: OrderTypeEnum.Saldo },
{ label: "Consulenza", value: OrderTypeEnum.Consulenza },
{ label: "Altro", value: OrderTypeEnum.Altro },
2025-08-28 18:27:07 +02:00
];
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
const [selectedOrdine, setSelectedOrdine] = useState<OrdiniOrdineId | null>(
null,
);
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
type Column = (typeof tabledata)[number];
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
const columns: ColumnDef<Column>[] = [
{
accessorKey: "id",
cell: () => null,
enableHiding: false,
header: () => null,
},
2025-08-28 18:27:07 +02:00
{
accessorKey: "username",
cell: ({ row }) => {
if (isAdmin) {
return (
<Link
aria-label="Visualizza Utente"
href={`/area-riservata/admin/user-view/ricerca/${row.original.userId}`}
>
<Button size="sm">{row.original.username}</Button>
</Link>
);
}
return <span>{row.original.username}</span>;
},
2025-08-29 16:18:32 +02:00
enableHiding: false,
2025-08-28 18:27:07 +02:00
header: ({ column }) => (
<DataTableColumnHeader
column={column}
2025-08-29 16:18:32 +02:00
title={columns_titles.username}
2025-08-28 18:27:07 +02:00
/>
),
2025-08-29 16:18:32 +02:00
},
{
2025-08-28 18:27:07 +02:00
accessorKey: "created_at",
cell: ({ row }) => {
const date = row.getValue("created_at");
return new Date(date as Date).toLocaleDateString();
},
enableHiding: false,
header: ({ column }) => (
2025-08-29 16:18:32 +02:00
<DataTableColumnHeader
column={column}
title={columns_titles.created_at}
/>
2025-08-28 18:27:07 +02:00
),
2025-08-29 16:18:32 +02:00
sortingFn: "datetime",
},
{
2025-08-28 18:27:07 +02:00
accessorKey: "tipo",
cell: ({ row }) => {
return row.original.tipo.toString();
},
filterFn: (row, id, value) => {
return value.includes(row.getValue(id));
},
2025-08-29 16:18:32 +02:00
header: ({ column }) => (
<DataTableColumnHeader column={column} title={columns_titles.tipo} />
),
2025-08-28 18:27:07 +02:00
},
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
{
2025-08-29 16:18:32 +02:00
accessorKey: "packid",
2025-08-28 18:27:07 +02:00
header: ({ column }) => (
<DataTableColumnHeader column={column} title={columns_titles.packid} />
),
},
{
accessorKey: "importo",
2025-08-28 18:27:07 +02:00
cell: ({ row }) => {
return <span>{formatCurrency(row.original.importo / 100)}</span>;
},
header: ({ column }) => (
<DataTableColumnHeader column={column} title={columns_titles.importo} />
),
enableHiding: false,
sortingFn: (a, b, id) => {
const aValue = a.getValue(id) as number;
const bValue = b.getValue(id) as number;
return aValue - bValue;
},
},
{
accessorKey: "status",
cell: ({ row }) => {
if (!row.original.status) {
2025-08-28 18:27:07 +02:00
return (
<span className="inline-flex items-center gap-1">
<Circle className="size-5" />
Non attivo
2025-08-28 18:27:07 +02:00
</span>
);
}
return (
<span className="inline-flex items-center gap-1 text-green-500">
<CircleCheck className="size-5" />
Attivo
</span>
);
2025-08-28 18:27:07 +02:00
},
2025-08-29 16:18:32 +02:00
filterFn: (row, id, value) => {
return value.includes(row.getValue(id));
},
header: ({ column }) => (
<DataTableColumnHeader column={column} title={columns_titles.status} />
2025-08-29 16:18:32 +02:00
),
2025-08-28 18:27:07 +02:00
},
{
accessorKey: "payment_status",
cell: ({ row }) => {
return <span>{StatusMapping(row.original.payment_status)}</span>;
},
2025-08-04 17:45:44 +02:00
filterFn: (row, id, value) => {
return value.includes(row.getValue(id));
},
header: ({ column }) => (
<DataTableColumnHeader
column={column}
title={columns_titles.payment_status}
/>
),
},
2025-08-28 18:27:07 +02:00
{
cell: ({ row }) => {
return (
<Button
aria-label="Apri Dettagli Ordine"
onClick={() => {
setSelectedOrdine(row.original.id);
}}
2025-08-29 16:18:32 +02:00
size="sm"
variant="outline"
2025-08-28 18:27:07 +02:00
>
<ExternalLink className="size-5" />
2025-08-28 18:27:07 +02:00
</Button>
);
},
2025-08-29 16:18:32 +02:00
enableHiding: false,
id: "actions",
2025-08-28 18:27:07 +02:00
},
];
2025-08-04 17:45:44 +02:00
const searchFiltro: SearchFiltro = {
columnName: "id",
placeholder: "Cerca ordine...",
};
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
const pinnedFiltri: PinnedFiltro[] = [
{
columnName: "status",
2025-08-04 17:45:44 +02:00
options: statusOptions,
title: "Stato Ordine",
2025-08-28 18:27:07 +02:00
},
{
columnName: "tipo",
options: type_options,
2025-08-29 16:18:32 +02:00
title: "Tipo Ordine",
2025-08-28 18:27:07 +02:00
},
];
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
return (
<div className="mx-auto w-full">
2025-08-28 18:27:07 +02:00
<DataTable
columns={columns}
columns_titles={columns_titles}
2025-08-29 16:18:32 +02:00
data={tabledata}
2025-08-28 18:27:07 +02:00
defaultColumnVisibility={{
2025-08-29 16:18:32 +02:00
actions: true,
2025-08-28 18:27:07 +02:00
amount: true,
2025-08-29 16:18:32 +02:00
packid: true,
2025-08-28 18:27:07 +02:00
paid_at: true,
2025-08-29 16:18:32 +02:00
status: true,
tipo: true,
username: isAdmin && !userId,
2025-08-28 18:27:07 +02:00
}}
defaultFilterState={
filter ? [{ id: "id", value: filter.toString() }] : []
}
2025-08-29 16:18:32 +02:00
defaultSort={[{ desc: true, id: "created_at" }]}
pinnedFiltri={pinnedFiltri}
searchColumn={searchFiltro}
2025-08-28 18:27:07 +02:00
/>
{isAdmin ? (
<AdminWrapperOrdiniModal
2025-08-29 16:18:32 +02:00
ordineId={selectedOrdine}
setSelected={setSelectedOrdine}
2025-08-28 18:27:07 +02:00
/>
) : (
selectedOrdine && (
<UserOrdiniModal
ordineId={selectedOrdine}
setSelected={setSelectedOrdine}
/>
)
2025-08-28 18:27:07 +02:00
)}
</div>
);
2025-08-04 17:45:44 +02:00
};