87 lines
2.2 KiB
TypeScript
87 lines
2.2 KiB
TypeScript
import { type ReactNode } from "react";
|
|
|
|
import type { DefaultModel } from "@/back/types/global";
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from "@/components/ui/table";
|
|
import useTrans from "@/hooks/use-translations";
|
|
|
|
interface DetailsTableProps {
|
|
columns: {
|
|
accessorKey: keyof DefaultModel;
|
|
header: string;
|
|
|
|
cell?: (params: { value: unknown }) => ReactNode;
|
|
}[];
|
|
model: DefaultModel;
|
|
forceRenderValue?: boolean;
|
|
}
|
|
|
|
export default function DetailsTable({
|
|
columns,
|
|
model,
|
|
forceRenderValue = false,
|
|
}: DetailsTableProps) {
|
|
const tableNotKnownTrans = useTrans("uwil-backend::back.table_not_known");
|
|
return (
|
|
<div className="rounded-md border">
|
|
<Table>
|
|
<TableHeader>
|
|
<TableRow>
|
|
<TableHead>{useTrans("uwil-backend::back.table_field")}</TableHead>
|
|
<TableHead>{useTrans("uwil-backend::back.table_value")}</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{columns.map(({ accessorKey, header, cell }) => {
|
|
const rawValue = model[accessorKey];
|
|
|
|
const renderValue = (): ReactNode => {
|
|
if (rawValue === null) {
|
|
return (
|
|
<span className="text-sm italic text-muted-foreground">
|
|
{tableNotKnownTrans}
|
|
</span>
|
|
);
|
|
}
|
|
|
|
if (forceRenderValue && cell) {
|
|
return cell({ value: rawValue });
|
|
}
|
|
|
|
if (cell) {
|
|
return cell({ value: rawValue });
|
|
}
|
|
|
|
if (
|
|
typeof rawValue === "string" ||
|
|
typeof rawValue === "number" ||
|
|
typeof rawValue === "boolean"
|
|
) {
|
|
return String(rawValue);
|
|
}
|
|
|
|
if (rawValue instanceof Date) {
|
|
return rawValue.toLocaleString();
|
|
}
|
|
|
|
return JSON.stringify(rawValue);
|
|
};
|
|
|
|
return (
|
|
<TableRow key={accessorKey}>
|
|
<TableCell>{header}</TableCell>
|
|
<TableCell>{renderValue()}</TableCell>
|
|
</TableRow>
|
|
);
|
|
})}
|
|
</TableBody>
|
|
</Table>
|
|
</div>
|
|
);
|
|
}
|