"use client"; import { FormEvent, useEffect, useMemo, useState } from "react"; import { approveWorkflowRequest, getWorkflowRequests, rejectWorkflowRequest, WorkflowFilters } from "@/services/workflow"; import { useApiStore } from "@/store/uiStore"; import { useLocaleStore } from "@/store/uiStore"; import { t } from "@/lib/locale"; import DataTable from "@/components/ui/Table"; import StatusBadge from "@/components/workflow/StatusBadge"; import ApprovalActionModal from "@/components/workflow/ApprovalActionModal"; import PageHeader from "@/components/ui/PageHeader"; import EmptyState from "@/components/ui/EmptyState"; import { WorkflowRequestItem, WorkflowStatus } from "@/types/api"; const DEFAULT_FILTERS: WorkflowFilters = { status: "", resourceType: "", makerUsername: "", limit: 50 }; export default function WorkflowPage() { const [filters, setFilters] = useState(DEFAULT_FILTERS); const [requests, setRequests] = useState([]); const [loading, setLoading] = useState(false); const [approvalRequest, setApprovalRequest] = useState(null); const [actionType, setActionType] = useState<"approve" | "reject">("approve"); const [isOpen, setIsOpen] = useState(false); const addToast = useApiStore((s) => s.addToast); const locale = useLocaleStore((s) => s.locale); const filtered = useMemo( () => requests.filter((item) => { const matchesStatus = !filters.status || item.status === filters.status; const matchesType = !filters.resourceType || item.resourceType === filters.resourceType; const matchesMaker = !filters.makerUsername || item.makerUsername.includes(filters.makerUsername); return matchesStatus && matchesType && matchesMaker; }), [filters, requests] ); const load = async () => { setLoading(true); try { const response = await getWorkflowRequests(filters); setRequests(response); } catch (error) { addToast((error as { message?: string })?.message || t("loadFailed", locale), "error"); } finally { setLoading(false); } }; useEffect(() => { load(); }, [filters]); const onSubmitAction = async (notes?: string, checkerRole?: string) => { if (!approvalRequest) return; try { if (actionType === "approve") { await approveWorkflowRequest(approvalRequest.id, { notes, checkerRole }); addToast(t("requestApproved", locale), "success"); } else { await rejectWorkflowRequest(approvalRequest.id, { notes, checkerRole }); addToast(t("requestRejected", locale), "success"); } setIsOpen(false); load(); } catch (error) { addToast((error as { message?: string })?.message || t("actionFailed", locale), "error"); } }; const submitFilters = (e: FormEvent) => { e.preventDefault(); load(); }; return (
setFilters((prev) => ({ ...prev, resourceType: e.target.value }))} /> setFilters((prev) => ({ ...prev, makerUsername: e.target.value }))} /> setFilters((prev) => ({ ...prev, limit: Number(e.target.value) }))} />
{filtered.length === 0 && !loading && ( )} }, { key: "currentStep", header: "Current Step" }, { key: "requiredSteps", header: "Required Steps" }, { key: "updatedAt", header: "Updated At" }, { key: "actions", header: "Actions", render: (row) => (
) } ]} data={filtered} />
setIsOpen(false)} title={actionType === "approve" ? t("approveRequest", locale) : t("rejectRequest", locale)} />
); }