import { createFileRoute } from "@tanstack/react-router"; import { AppManagerTemplate } from "@/template/app-manager-template"; import { useGetSoftwareList, useGetRoomList, useUploadSoftware, useDeleteFile, useAddRequiredFile, useDeleteRequiredFile, useInstallMsi, useDownloadFiles, } from "@/hooks/queries"; import { toast } from "sonner"; import type { ColumnDef } from "@tanstack/react-table"; import type { AxiosProgressEvent } from "axios"; import type { Version } from "@/types/file"; import { Check, X } from "lucide-react"; import { useState } from "react"; export const Route = createFileRoute("/_auth/apps/")({ head: () => ({ meta: [{ title: "Quản lý phần mềm" }] }), component: AppsComponent, }); function AppsComponent() { const { data, isLoading } = useGetSoftwareList(); const { data: roomData } = useGetRoomList(); const versionList: Version[] = Array.isArray(data) ? data : data ? [data] : []; const [table, setTable] = useState(); const uploadMutation = useUploadSoftware(); const installMutation = useInstallMsi(); const downloadMutation = useDownloadFiles(); const deleteMutation = useDeleteFile(); const addRequiredFileMutation = useAddRequiredFile(); const deleteRequiredFileMutation = useDeleteRequiredFile(); // Cột bảng const columns: ColumnDef[] = [ { accessorKey: "version", header: "Phiên bản" }, { accessorKey: "fileName", header: "Tên file" }, { accessorKey: "folderPath", header: "Đường dẫn" }, { accessorKey: "updatedAt", header: () =>
Thời gian cập nhật
, cell: ({ getValue }) => getValue() ? new Date(getValue() as string).toLocaleString("vi-VN") : "N/A", }, { accessorKey: "requestUpdateAt", header: () =>
Thời gian yêu cầu cài đặt/tải xuống
, cell: ({ getValue }) => getValue() ? new Date(getValue() as string).toLocaleString("vi-VN") : "N/A", }, { id: "required", header: () =>
Đã thêm vào danh sách
, cell: ({ row }) => { const isRequired = row.original.isRequired; return isRequired ? (
) : (
Không
); }, enableSorting: false, enableHiding: false, }, { id: "select", header: () =>
Chọn
, cell: ({ row }) => ( ), enableSorting: false, enableHiding: false, }, ]; // Upload file MSI const handleUpload = async ( fd: FormData, config?: { onUploadProgress?: (e: AxiosProgressEvent) => void } ) => { try { await uploadMutation.mutateAsync({ formData: fd, onUploadProgress: config?.onUploadProgress, }); toast.success("Upload thành công!"); } catch (error: any) { console.error("Upload error:", error); toast.error("Upload thất bại!"); } }; // Callback khi chọn phòng const handleInstall = async (roomNames: string[]) => { if (!table) { toast.error("Không thể lấy thông tin bảng!"); return; } const selectedRows = table.getSelectedRowModel().rows; if (selectedRows.length === 0) { toast.error("Vui lòng chọn ít nhất một file để cài đặt!"); return; } const MsiFileIds = selectedRows.map((row: any) => row.original.id); try { for (const roomName of roomNames) { await installMutation.mutateAsync({ roomName, data: { MsiFileIds }, }); } toast.success("Đã gửi yêu cầu cài đặt phần mềm cho các phòng đã chọn!"); } catch (e) { toast.error("Có lỗi xảy ra khi cài đặt!"); } }; const handleDonwload = async (roomNames: string[]) => { if (!table) { toast.error("Không thể lấy thông tin bảng!"); return; } const selectedRows = table.getSelectedRowModel().rows; if (selectedRows.length === 0) { toast.error("Vui lòng chọn ít nhất một file để tải!"); return; } const MsiFileIds = selectedRows.map((row: any) => row.original.id); try { for (const roomName of roomNames) { await downloadMutation.mutateAsync({ roomName, data: { MsiFileIds }, }); } toast.success("Đã gửi yêu cầu tải file cho các phòng đã chọn!"); } catch (e) { toast.error("Có lỗi xảy ra khi tải!"); } }; const handleDelete = async () => { if (!table) { toast.error("Không thể lấy thông tin bảng!"); return; } const selectedRows = table.getSelectedRowModel().rows; if (selectedRows.length === 0) { toast.error("Vui lòng chọn ít nhất một file để xóa!"); return; } try { for (const row of selectedRows) { const { id } = row.original; await deleteMutation.mutateAsync(id); } toast.success("Xóa phần mềm thành công!"); } catch (e) { toast.error("Xóa phần mềm thất bại!"); } }; const handleDeleteFromRequiredList = async () => { if (!table) return; const selectedRows = table.getSelectedRowModel().rows; try { for (const row of selectedRows) { const { id } = row.original; await deleteRequiredFileMutation.mutateAsync(id); } toast.success("Xóa file khỏi danh sách thành công!"); if (table) { table.setRowSelection({}); } } catch (e) { console.error("Delete from required list error:", e); toast.error("Có lỗi xảy ra khi xóa!"); } }; const handleDeleteFromServer = async () => { if (!table) return; const selectedRows = table.getSelectedRowModel().rows; try { for (const row of selectedRows) { const { id } = row.original; await deleteMutation.mutateAsync(id); } toast.success("Xóa phần mềm từ server thành công!"); if (table) { table.setRowSelection({}); } } catch (e) { console.error("Delete error:", e); toast.error("Có lỗi xảy ra khi xóa!"); } }; const handleAddToRequired = async () => { if (!table) { toast.error("Không thể lấy thông tin bảng!"); return; } const selectedRows = table.getSelectedRowModel().rows; if (selectedRows.length === 0) { toast.error("Vui lòng chọn ít nhất một file!"); return; } try { for (const row of selectedRows) { const { fileName, version } = row.original; await addRequiredFileMutation.mutateAsync({ fileName, version, }); } toast.success("Thêm file vào danh sách thành công!"); table.setRowSelection({}); } catch (e) { console.error("Add required file error:", e); toast.error("Có lỗi xảy ra!"); } }; return ( <> title="Quản lý phần mềm" uploadFormTitle="Tải lên || Cập nhật file phần mềm" description="Quản lý và gửi yêu cầu cài đặt phần mềm hoặc file cấu hình" data={versionList} isLoading={isLoading} columns={columns} onUpload={handleUpload} onUpdate={handleInstall} onDownload={handleDonwload} onDelete={handleDelete} onDeleteFromServer={handleDeleteFromServer} onDeleteFromRequired={handleDeleteFromRequiredList} onAddToRequired={handleAddToRequired} updateLoading={installMutation.isPending} downloadLoading={downloadMutation.isPending} deleteLoading={deleteMutation.isPending || deleteRequiredFileMutation.isPending} addToRequiredLoading={addRequiredFileMutation.isPending} onTableInit={setTable} rooms={roomData} /> ); }