'use client'; // ADR-021: IntegratedBanner — แสดง metadata เอกสาร + สถานะ Workflow + ปุ่ม Action ในแถวเดียว // ใช้ใน RFA, Correspondence, Transmittal, Circulation detail pages import { useState } from 'react'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Textarea } from '@/components/ui/textarea'; import { Popover, PopoverContent, PopoverTrigger, } from '@/components/ui/popover'; import { Separator } from '@/components/ui/separator'; import { CheckCircle2, XCircle, RotateCcw, MessageSquare, Loader2, AlertTriangle } from 'lucide-react'; import { WorkflowPriority } from '@/types/workflow'; import { useWorkflowAction } from '@/hooks/use-workflow-action'; import { useTranslations } from '@/hooks/use-translations'; // สีของ Priority Badge (label ถูก resolve ผ่าน t() ใน component) const PRIORITY_CONFIG: Record = { URGENT: { labelKey: 'workflow.priority.URGENT', className: 'bg-red-600 text-white animate-pulse' }, HIGH: { labelKey: 'workflow.priority.HIGH', className: 'bg-orange-500 text-white' }, MEDIUM: { labelKey: 'workflow.priority.MEDIUM', className: 'bg-yellow-500 text-white' }, LOW: { labelKey: 'workflow.priority.LOW', className: 'bg-green-600 text-white' }, }; // สีของ Status Badge function getStatusVariant(status: string): 'default' | 'secondary' | 'destructive' | 'outline' { const s = status?.toUpperCase(); if (['APPROVED', 'COMPLETED', 'ISSUED'].includes(s)) return 'default'; if (['REJECTED', 'CANCELLED'].includes(s)) return 'destructive'; if (['DRAFT', 'DFT'].includes(s)) return 'secondary'; return 'outline'; } // แสดงป้ายสีตาม Workflow State function getStateColor(state?: string): string { if (!state) return 'text-muted-foreground'; const s = state.toUpperCase(); if (s.includes('APPROV') || s.includes('COMPLET') || s.includes('ISSUED')) return 'text-green-600'; if (s.includes('REJECT') || s.includes('CANCEL')) return 'text-red-600'; if (s.includes('REVIEW') || s.includes('PENDING') || s.includes('IN_')) return 'text-blue-600'; return 'text-amber-600'; } // Action button config (label ถูก resolve ผ่าน t() ใน component) const ACTION_CONFIG: Record = { APPROVE: { labelKey: 'workflow.action.APPROVE', icon: , variant: 'default', requiresComment: false }, REJECT: { labelKey: 'workflow.action.REJECT', icon: , variant: 'destructive', requiresComment: true }, RETURN: { labelKey: 'workflow.action.RETURN', icon: , variant: 'outline', requiresComment: true }, ACKNOWLEDGE: { labelKey: 'workflow.action.ACKNOWLEDGE', icon: , variant: 'secondary', requiresComment: false }, COMMENT: { labelKey: 'workflow.action.COMMENT', icon: , variant: 'outline', requiresComment: true }, }; export interface IntegratedBannerProps { docNo: string; subject: string; status: string; priority?: WorkflowPriority; workflowState?: string; availableActions?: string[]; /** Legacy prop — ใช้เมื่อไม่มี instanceId (Transmittal, Circulation) */ onAction?: (action: string, comment?: string) => void; isLoading?: boolean; // ADR-021 T029: Workflow action wiring instanceId?: string; /** publicIds ของไฟล์ที่ user อัปโหลดใน WorkflowLifecycle Upload Zone */ pendingAttachmentIds?: string[]; /** เรียกเมื่อ action สำเร็จ (optional — React Query เปิด invalidate อัตโนมัติ) */ onActionSuccess?: () => void; } // Action button พร้อม Popover สำหรับ Comment function ActionButton({ actionKey, onAction, disabled, t, }: { actionKey: string; onAction: (action: string, comment?: string) => void; disabled?: boolean; t: (key: string) => string; }) { const [open, setOpen] = useState(false); const [comment, setComment] = useState(''); const config = ACTION_CONFIG[actionKey] ?? { labelKey: actionKey, icon: null, variant: 'outline' as const, requiresComment: false, }; const handleSubmit = () => { onAction(actionKey, comment || undefined); setComment(''); setOpen(false); }; if (!config.requiresComment) { return ( ); } return (

{t('workflow.action.commentLabel')}