"use client"; import React, { useState, useEffect, useCallback } from "react"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Loader2, CheckCircle2, XCircle, Clock, FileCheck2 } from "lucide-react"; import { getApprovalRequests, getApprovalRequest, getMyPendingApprovals, processApprovalLine, cancelApprovalRequest, type ApprovalRequest, type ApprovalLine, } from "@/lib/api/approval"; // 상태 배지 색상 const statusConfig: Record = { requested: { label: "요청됨", variant: "secondary" }, in_progress: { label: "진행 중", variant: "default" }, approved: { label: "승인됨", variant: "outline" }, rejected: { label: "반려됨", variant: "destructive" }, cancelled: { label: "취소됨", variant: "secondary" }, }; const lineStatusConfig: Record = { waiting: { label: "대기", icon: }, pending: { label: "진행 중", icon: }, approved: { label: "승인", icon: }, rejected: { label: "반려", icon: }, skipped: { label: "건너뜀", icon: }, }; // 결재 상세 모달 interface ApprovalDetailModalProps { request: ApprovalRequest | null; open: boolean; onClose: () => void; onRefresh: () => void; pendingLineId?: number; // 내가 처리해야 할 결재 라인 ID } function ApprovalDetailModal({ request, open, onClose, onRefresh, pendingLineId }: ApprovalDetailModalProps) { const [comment, setComment] = useState(""); const [isProcessing, setIsProcessing] = useState(false); const [isCancelling, setIsCancelling] = useState(false); useEffect(() => { if (!open) setComment(""); }, [open]); const handleProcess = async (action: "approved" | "rejected") => { if (!pendingLineId) return; setIsProcessing(true); const res = await processApprovalLine(pendingLineId, { action, comment: comment.trim() || undefined }); setIsProcessing(false); if (res.success) { onRefresh(); onClose(); } }; const handleCancel = async () => { if (!request) return; setIsCancelling(true); const res = await cancelApprovalRequest(request.request_id); setIsCancelling(false); if (res.success) { onRefresh(); onClose(); } }; if (!request) return null; const statusInfo = statusConfig[request.status] || { label: request.status, variant: "secondary" as const }; return ( {request.title} {statusInfo.label} 요청자: {request.requester_name || request.requester_id} {request.requester_dept ? ` (${request.requester_dept})` : ""}
{/* 결재 사유 */} {request.description && (

결재 사유

{request.description}

)} {/* 결재선 */}

결재선

{(request.lines || []).map((line) => { const lineStatus = lineStatusConfig[line.status] || { label: line.status, icon: null }; return (
{lineStatus.icon}

{line.approver_label || `${line.step_order}차 결재`} — {line.approver_name || line.approver_id}

{line.approver_position && (

{line.approver_position}

)} {line.comment && (

의견: {line.comment}

)}
{lineStatus.label}
); })}
{/* 승인/반려 입력 (대기 상태일 때만) */} {pendingLineId && (

결재 의견 (선택사항)