Local Build and Deploy / deploy (push) Successful in 1m9s
Co-authored-by: Cursor <[email protected]>
118 lines
2.6 KiB
TypeScript
118 lines
2.6 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { useTranslations } from "next-intl";
|
|
import { DataTable } from "@/components/admin/data-table";
|
|
import { Badge } from "@/components/ui/badge";
|
|
import type { DataTableColumn, PaginatedResult } from "@/types";
|
|
|
|
export interface CfhRow {
|
|
id: number;
|
|
issue: string;
|
|
roomId: number;
|
|
when: string;
|
|
sender: string;
|
|
senderId: number;
|
|
reported: string;
|
|
reportedId: number;
|
|
mod: string;
|
|
state: number;
|
|
stateLabel: string;
|
|
}
|
|
|
|
export function CfhTable({ data }: { data: PaginatedResult<CfhRow> }) {
|
|
const t = useTranslations("pages.admin.cfh");
|
|
|
|
const columns: DataTableColumn<CfhRow>[] = [
|
|
{ key: "id", label: t("colId"), sortable: true },
|
|
{
|
|
key: "issue",
|
|
label: t("colIssue"),
|
|
sortable: true,
|
|
render: (_value, row) => (
|
|
<div className="min-w-0">
|
|
<Link
|
|
href={`/admin/moderation/cfh/${row.id}`}
|
|
className="text-sm font-medium truncate block hover:underline"
|
|
>
|
|
{row.issue || t("noDescription")}
|
|
</Link>
|
|
<p className="text-[10px] text-muted-foreground">
|
|
{t("roomMeta", { room: row.roomId, when: row.when })}
|
|
</p>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
key: "sender",
|
|
label: t("colSender"),
|
|
sortable: true,
|
|
render: (_value, row) =>
|
|
row.senderId ? (
|
|
<Link
|
|
href={`/admin/users/${row.senderId}`}
|
|
className="hover:underline"
|
|
>
|
|
{row.sender}
|
|
</Link>
|
|
) : (
|
|
"—"
|
|
),
|
|
},
|
|
{
|
|
key: "reported",
|
|
label: t("colReported"),
|
|
sortable: true,
|
|
render: (_value, row) =>
|
|
row.reportedId ? (
|
|
<Link
|
|
href={`/admin/users/${row.reportedId}`}
|
|
className="font-medium hover:underline"
|
|
>
|
|
{row.reported}
|
|
</Link>
|
|
) : (
|
|
"—"
|
|
),
|
|
},
|
|
{ key: "mod", label: t("colMod"), sortable: true },
|
|
{
|
|
key: "state",
|
|
label: t("colStatus"),
|
|
sortable: true,
|
|
filterKey: "filter_state",
|
|
filterOptions: [
|
|
{ label: t("stateOpen"), value: "0" },
|
|
{ label: t("statePicked"), value: "1" },
|
|
{ label: t("stateClosed"), value: "2" },
|
|
],
|
|
render: (_value, row) => {
|
|
const variant =
|
|
row.state === 0
|
|
? "destructive"
|
|
: row.state === 1
|
|
? "default"
|
|
: "secondary";
|
|
return (
|
|
<Badge variant={variant} className="text-[0.7rem]">
|
|
{row.stateLabel}
|
|
</Badge>
|
|
);
|
|
},
|
|
},
|
|
];
|
|
|
|
return (
|
|
<DataTable
|
|
data={data}
|
|
columns={columns}
|
|
searchPlaceholder={t("searchPlaceholder")}
|
|
presets={[
|
|
{ label: t("stateOpen"), params: { filter_state: "0" } },
|
|
{ label: t("statePicked"), params: { filter_state: "1" } },
|
|
{ label: t("stateClosed"), params: { filter_state: "2" } },
|
|
]}
|
|
/>
|
|
);
|
|
}
|