Re_Figma_Code/src/pages/RequestDetail/components/tabs/SummaryTab.tsx

204 lines
8.6 KiB
TypeScript

import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { FileText, CheckCircle, XCircle, Clock, Loader2, Share2 } from 'lucide-react';
import { format } from 'date-fns';
import type { SummaryDetails } from '@/services/summaryApi';
interface SummaryTabProps {
summary: SummaryDetails | null;
loading: boolean;
onShare?: () => void;
isInitiator?: boolean;
}
export function SummaryTab({ summary, loading, onShare, isInitiator }: SummaryTabProps) {
const getStatusIcon = (status: string) => {
const statusLower = status.toLowerCase();
if (statusLower === 'approved') return <CheckCircle className="h-4 w-4 text-green-600" />;
if (statusLower === 'rejected') return <XCircle className="h-4 w-4 text-red-600" />;
if (statusLower === 'pending' || statusLower === 'in progress') return <Clock className="h-4 w-4 text-orange-600" />;
return <FileText className="h-4 w-4 text-gray-600" />;
};
const getStatusColor = (status: string) => {
const statusLower = status.toLowerCase();
if (statusLower === 'approved') return 'bg-green-100 text-green-700 border-green-300';
if (statusLower === 'rejected') return 'bg-red-100 text-red-700 border-red-300';
if (statusLower === 'pending' || statusLower === 'in progress') return 'bg-orange-100 text-orange-700 border-orange-300';
return 'bg-gray-100 text-gray-700 border-gray-300';
};
// Helper function to get designation or department (fallback to department if designation is N/A or empty)
const getDesignationOrDepartment = (designation?: string | null, department?: string | null) => {
if (designation && designation.trim() && designation.trim().toUpperCase() !== 'N/A') {
return designation;
}
if (department && department.trim() && department.trim().toUpperCase() !== 'N/A') {
return department;
}
return 'N/A';
};
if (loading) {
return (
<div className="flex items-center justify-center py-12">
<div className="text-center">
<Loader2 className="h-12 w-12 animate-spin text-blue-600 mx-auto mb-4" />
<p className="text-gray-600">Loading summary...</p>
</div>
</div>
);
}
if (!summary) {
return (
<div className="flex items-center justify-center py-12">
<div className="text-center">
<FileText className="h-12 w-12 text-gray-400 mx-auto mb-4" />
<h2 className="text-xl font-bold text-gray-900 mb-2">Summary Not Available</h2>
<p className="text-gray-600">Summary has not been generated for this request yet.</p>
</div>
</div>
);
}
return (
<div className="space-y-6">
{/* Summary Card */}
<div className="bg-white rounded-lg shadow-sm border border-gray-200">
<div className="p-6 border-b border-gray-200">
<div className="flex items-start justify-between gap-4 mb-4">
<div>
<h2 className="text-xl font-semibold text-gray-900 mb-2">{summary.title}</h2>
<p className="text-sm text-gray-600">Request #{summary.requestNumber}</p>
</div>
{isInitiator && onShare ? (
<Button
variant="outline"
size="sm"
onClick={onShare}
className="flex items-center gap-2"
>
<Share2 className="w-4 h-4" />
<span>Share</span>
</Button>
) : (
<Badge className={getStatusColor(summary.workflow.status)}>
{getStatusIcon(summary.workflow.status)}
<span className="ml-1 capitalize">{summary.workflow.status}</span>
</Badge>
)}
</div>
{summary.description && (
<p className="text-gray-700 mb-4">{summary.description}</p>
)}
</div>
{/* Initiator Section */}
<div className="p-6 border-b border-gray-200">
<h3 className="text-lg font-semibold text-gray-900 mb-4">Initiator</h3>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<div>
<p className="text-xs text-gray-500 mb-1">Name</p>
<p className="text-sm font-medium text-gray-900">{summary.initiator.name}</p>
</div>
<div>
<p className="text-xs text-gray-500 mb-1">Designation</p>
<p className="text-sm font-medium text-gray-900">
{getDesignationOrDepartment(summary.initiator.designation, summary.initiator.department)}
</p>
</div>
<div>
<p className="text-xs text-gray-500 mb-1">Status</p>
<p className="text-sm font-medium text-gray-900">{summary.initiator.status}</p>
</div>
<div>
<p className="text-xs text-gray-500 mb-1">Time Stamp</p>
<p className="text-sm font-medium text-gray-900">
{format(new Date(summary.initiator.timestamp), 'MMM dd, yy, HH:mm')}
</p>
</div>
</div>
</div>
{/* Approvers Section */}
{summary.approvers && summary.approvers.length > 0 && (
<div className="p-6 border-b border-gray-200">
<h3 className="text-lg font-semibold text-gray-900 mb-4">Workflow</h3>
{summary.approvers.map((approver, index) => (
<div key={index} className="mb-6 last:mb-0">
<h4 className="text-md font-semibold text-gray-800 mb-3">
{approver.levelName || `Approver ${approver.levelNumber}`}
</h4>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-3">
<div>
<p className="text-xs text-gray-500 mb-1">Name</p>
<p className="text-sm font-medium text-gray-900">{approver.name}</p>
</div>
<div>
<p className="text-xs text-gray-500 mb-1">Designation</p>
<p className="text-sm font-medium text-gray-900">
{getDesignationOrDepartment(approver.designation, approver.department)}
</p>
</div>
<div>
<p className="text-xs text-gray-500 mb-1">Status</p>
<div className="flex items-center gap-1">
{getStatusIcon(approver.status)}
<p className="text-sm font-medium text-gray-900">{approver.status}</p>
</div>
</div>
<div>
<p className="text-xs text-gray-500 mb-1">Time Stamp</p>
<p className="text-sm font-medium text-gray-900">
{format(new Date(approver.timestamp), 'MMM dd, yy, HH:mm')}
</p>
</div>
</div>
<div>
<p className="text-xs text-gray-500 mb-1">Remarks</p>
<p className="text-sm text-gray-700">{approver.remarks || '—'}</p>
</div>
</div>
))}
</div>
)}
{/* Closing Remarks Section */}
<div className="p-6">
<h3 className="text-lg font-semibold text-gray-900 mb-4">Closing Remarks (Conclusion)</h3>
<div className="bg-gray-50 rounded-lg p-4">
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-4">
<div>
<p className="text-xs text-gray-500 mb-1">Name</p>
<p className="text-sm font-medium text-gray-900">{summary.initiator.name}</p>
</div>
<div>
<p className="text-xs text-gray-500 mb-1">Designation</p>
<p className="text-sm font-medium text-gray-900">
{getDesignationOrDepartment(summary.initiator.designation, summary.initiator.department)}
</p>
</div>
<div>
<p className="text-xs text-gray-500 mb-1">Status</p>
<p className="text-sm font-medium text-gray-900">Concluded</p>
</div>
{summary.isAiGenerated && (
<div>
<p className="text-xs text-gray-500 mb-1">Source</p>
<Badge variant="outline" className="text-xs">AI Generated</Badge>
</div>
)}
</div>
<div>
<p className="text-xs text-gray-500 mb-1">Remarks</p>
<p className="text-sm text-gray-700 whitespace-pre-wrap">{summary.closingRemarks || '—'}</p>
</div>
</div>
</div>
</div>
</div>
);
}