import * as React from "react" import { type Table } from "@tanstack/react-table" import { Plus, Send, Users, Download, RefreshCw, FileText, MessageSquare, CheckCircle2 } from "lucide-react" import { toast } from "sonner" import { useRouter } from "next/navigation" import { Button } from "@/components/ui/button" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { RequestDocumentsDialog, RequestEvaluationDialog, } from "./periodic-evaluation-action-dialogs" import { PeriodicEvaluationView } from "@/db/schema" import { exportTableToExcel } from "@/lib/export" import { FinalizeEvaluationDialog } from "./periodic-evaluation-finalize-dialogs" import { useAuthRole } from "@/hooks/use-auth-role" interface PeriodicEvaluationsTableToolbarActionsProps { table: Table onRefresh?: () => void } export function PeriodicEvaluationsTableToolbarActions({ table, onRefresh }: PeriodicEvaluationsTableToolbarActionsProps) { const [isLoading, setIsLoading] = React.useState(false) const [createEvaluationDialogOpen, setCreateEvaluationDialogOpen] = React.useState(false) const [requestDocumentsDialogOpen, setRequestDocumentsDialogOpen] = React.useState(false) const [requestEvaluationDialogOpen, setRequestEvaluationDialogOpen] = React.useState(false) const [finalizeEvaluationDialogOpen, setFinalizeEvaluationDialogOpen] = React.useState(false) const router = useRouter() // 권한 체크 (방법 1 또는 방법 2 중 선택) const { hasRole, isLoading: roleLoading } = useAuthRole() const canManageEvaluations = hasRole('정기평가') || hasRole('admin') // 선택된 행들 const selectedRows = table.getFilteredSelectedRowModel().rows const hasSelection = selectedRows.length > 0 // ✅ selectedEvaluations를 useMemo로 안정화 const selectedEvaluations = React.useMemo(() => { return selectedRows.map(row => row.original) }, [selectedRows]) // ✅ 각 상태별 평가들을 개별적으로 메모이제이션 const pendingSubmissionEvaluations = React.useMemo(() => { return table .getFilteredSelectedRowModel() .rows .map(row => row.original) .filter(e => e.status === "PENDING_SUBMISSION"||e.status === "PENDING"); }, [table.getFilteredSelectedRowModel().rows]); const submittedEvaluations = React.useMemo(() => { return table .getFilteredSelectedRowModel() .rows .map(row => row.original) .filter(e => e.status === "SUBMITTED" || e.status === "PENDING_SUBMISSION"); }, [table.getFilteredSelectedRowModel().rows]); const inReviewEvaluations = React.useMemo(() => { return table .getFilteredSelectedRowModel() .rows .map(row => row.original) .filter(e => e.status === "IN_REVIEW"); }, [table.getFilteredSelectedRowModel().rows]); const reviewCompletedEvaluations = React.useMemo(() => { return table .getFilteredSelectedRowModel() .rows .map(row => row.original) .filter(e => e.status === "REVIEW_COMPLETED"); }, [table.getFilteredSelectedRowModel().rows]); const finalizedEvaluations = React.useMemo(() => { return table .getFilteredSelectedRowModel() .rows .map(row => row.original) .filter(e => e.status === "FINALIZED"); }, [table.getFilteredSelectedRowModel().rows]); // ✅ 선택된 항목들의 상태 분석 - 안정화된 개별 배열들 사용 const selectedStats = React.useMemo(() => { const pendingSubmission = pendingSubmissionEvaluations.length const submitted = submittedEvaluations.length const inReview = inReviewEvaluations.length const reviewCompleted = reviewCompletedEvaluations.length const finalized = finalizedEvaluations.length // 협력업체에게 자료 요청 가능: PENDING_SUBMISSION 상태 const canRequestDocuments = pendingSubmission > 0 // 평가자에게 평가 요청 가능: SUBMITTED 상태 (제출됐지만 아직 평가 시작 안됨) const canRequestEvaluation = submitted > 0 // 평가 확정 가능: REVIEW_COMPLETED 상태 const canFinalizeEvaluation = reviewCompleted > 0 return { pendingSubmission, submitted, inReview, reviewCompleted, finalized, canRequestDocuments, canRequestEvaluation, canFinalizeEvaluation, total: selectedEvaluations.length } }, [ pendingSubmissionEvaluations.length, submittedEvaluations.length, inReviewEvaluations.length, reviewCompletedEvaluations.length, finalizedEvaluations.length, selectedEvaluations.length ]) // ---------------------------------------------------------------- // 다이얼로그 성공 핸들러 // ---------------------------------------------------------------- const handleActionSuccess = React.useCallback(() => { table.resetRowSelection() onRefresh?.() router.refresh() }, [table, onRefresh, router]) // ---------------------------------------------------------------- // 내보내기 핸들러 // ---------------------------------------------------------------- const handleExport = React.useCallback(() => { exportTableToExcel(table, { filename: "periodic-evaluations", excludeColumns: ["select", "actions"], }) }, [table]) // 권한이 없거나 로딩 중인 경우 내보내기 버튼만 표시 if (roleLoading) { return (
) } return ( <>
{/* 유틸리티 버튼들 */}
{/* 선택된 항목 액션 버튼들 - 정기평가 권한이 있는 경우만 표시 */} {canManageEvaluations && hasSelection && (
{/* 협력업체 자료 요청 버튼 */} {selectedStats.canRequestDocuments && ( )} {/* 평가자 평가 요청 버튼 */} {selectedStats.canRequestEvaluation && ( )} {/* 평가 확정 버튼 */} {selectedStats.canFinalizeEvaluation && ( )}
)} {/* 권한이 없는 경우 안내 메시지 (선택사항) */} {!canManageEvaluations && hasSelection && (
평가 관리 권한이 필요합니다
)}
{/* 다이얼로그들 - 권한이 있는 경우만 렌더링 */} {canManageEvaluations && ( <> {/* 협력업체 자료 요청 다이얼로그 */} {/* 평가자 평가 요청 다이얼로그 */} {/* 평가 확정 다이얼로그 */} )} ) }