TTMT.ManageWebGUI/src/template/table-manager-template.tsx

151 lines
4.5 KiB
TypeScript

import { RequestUpdateMenu } from "@/components/menu/request-update-menu";
import { SelectDialog } from "@/components/dialogs/select-dialog";
import { DeviceSearchDialog } from "@/components/bars/device-searchbar";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { FormDialog } from "@/components/dialogs/form-dialog";
import { VersionTable } from "@/components/tables/version-table";
import type { ColumnDef } from "@tanstack/react-table";
import { FileText, Building2 } from "lucide-react";
import { useState } from "react";
import { BlacklistForm } from "@/components/forms/black-list-form";
import type { BlacklistFormData } from "@/types/black-list";
import type { Room } from "@/types/room";
import { mapRoomsToSelectItems } from "@/helpers/mapRoomToSelectItems";
import { fetchDevicesFromRoom } from "@/services/device.service";
interface BlackListManagerTemplateProps<TData> {
title: string;
description: string;
data: TData[];
isLoading: boolean;
columns: ColumnDef<TData, any>[];
onAdd: (data: BlacklistFormData) => Promise<void>;
onDelete?: (id: number) => Promise<void>;
onUpdate?: (target: string | string[]) => void | Promise<void>;
updateLoading?: boolean;
onTableInit?: (table: any) => void;
rooms: Room[];
}
export function BlackListManagerTemplate<TData>({
title,
description,
data,
isLoading,
columns,
onAdd,
onUpdate,
updateLoading,
onTableInit,
rooms = [],
}: BlackListManagerTemplateProps<TData>) {
const [dialogOpen, setDialogOpen] = useState(false);
const [dialogType, setDialogType] = useState<"room" | "device" | null>(null);
const handleUpdateAll = async () => {
if (onUpdate) await onUpdate("All");
};
const openRoomDialog = () => {
if (rooms.length > 0 && onUpdate) {
setDialogType("room");
setDialogOpen(true);
}
};
const openDeviceDialog = () => {
if (onUpdate) {
setDialogType("device");
setDialogOpen(true);
}
};
return (
<div className="w-full px-6 space-y-4">
{/* Header */}
<div className="flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold">{title}</h1>
<p className="text-muted-foreground mt-2">{description}</p>
</div>
<FormDialog
triggerLabel="Thêm phần mềm bị chặn"
title="Thêm phần mềm bị chặn"
>
{(closeDialog) => (
<BlacklistForm onSubmit={onAdd} closeDialog={closeDialog} />
)}
</FormDialog>
</div>
{/* Table */}
<Card className="w-full">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<FileText className="h-5 w-5" /> Danh sách phần mềm bị chặn
</CardTitle>
<CardDescription>
Các phần mềm không đưc cho phép trong hệ thống
</CardDescription>
</CardHeader>
<CardContent>
<VersionTable
data={data}
isLoading={isLoading}
columns={columns}
onTableInit={onTableInit}
/>
</CardContent>
{/* Footer */}
{onUpdate && (
<CardFooter className="flex flex-col sm:flex-row gap-2">
<RequestUpdateMenu
onUpdateDevice={openDeviceDialog}
onUpdateRoom={openRoomDialog}
onUpdateAll={handleUpdateAll}
loading={updateLoading}
/>
</CardFooter>
)}
</Card>
{/* Dialog chọn phòng */}
{dialogType === "room" && (
<SelectDialog
open={dialogOpen}
onClose={() => setDialogOpen(false)}
title="Chọn phòng"
description="Chọn các phòng cần cập nhật danh sách đen"
icon={<Building2 className="w-6 h-6 text-primary" />}
items={mapRoomsToSelectItems(rooms)}
onConfirm={async (selectedRooms) => {
if (!onUpdate) return;
await onUpdate(selectedRooms);
setDialogOpen(false);
}}
/>
)}
{/* Dialog tìm thiết bị */}
{dialogType === "device" && (
<DeviceSearchDialog
open={dialogOpen && dialogType === "device"}
onClose={() => setDialogOpen(false)}
rooms={rooms}
fetchDevices={fetchDevicesFromRoom} // thêm vào đây
onSelect={(deviceIds) => onUpdate && onUpdate(deviceIds)}
/>
)}
</div>
);
}