289 lines
10 KiB
TypeScript
289 lines
10 KiB
TypeScript
'use client'
|
|
|
|
import Link from 'next/link'
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
|
import { Badge } from '@/components/ui/badge'
|
|
import { Button } from '@/components/ui/button'
|
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
|
import {
|
|
ArrowLeft,
|
|
Building2,
|
|
Calendar,
|
|
DollarSign,
|
|
FileText,
|
|
Users,
|
|
CheckSquare,
|
|
Briefcase,
|
|
CreditCard,
|
|
Shield
|
|
} from 'lucide-react'
|
|
import { formatDate } from '@/lib/utils'
|
|
|
|
interface PolicyDetailProps {
|
|
policy: any
|
|
}
|
|
|
|
export function PolicyDetail({ policy }: PolicyDetailProps) {
|
|
const isExpired = new Date(policy.expirationDate) < new Date()
|
|
const daysUntilExpiration = Math.ceil(
|
|
(new Date(policy.expirationDate).getTime() - new Date().getTime()) / (1000 * 60 * 60 * 24)
|
|
)
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* Header */}
|
|
<div className="flex items-start justify-between">
|
|
<div className="space-y-1">
|
|
<div className="flex items-center gap-2">
|
|
<Link href={`/clients/${policy.client.id}`}>
|
|
<Button variant="ghost" size="sm">
|
|
<ArrowLeft className="h-4 w-4 mr-2" />
|
|
Back to {policy.client.name}
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
<h1 className="text-3xl font-bold">{policy.policyType || 'Type LOB'}</h1>
|
|
<p className="text-muted-foreground">
|
|
Policy #{policy.policyNumber || 'N/A'}
|
|
</p>
|
|
</div>
|
|
<div className="text-right">
|
|
<Badge
|
|
variant={isExpired ? 'destructive' : daysUntilExpiration <= 30 ? 'destructive' : daysUntilExpiration <= 90 ? 'secondary' : 'default'}
|
|
className="text-sm"
|
|
>
|
|
{isExpired ? 'Expired' : `Expires in ${daysUntilExpiration} days`}
|
|
</Badge>
|
|
<p className="text-sm text-muted-foreground mt-2">
|
|
<span suppressHydrationWarning>{formatDate(policy.expirationDate)}</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Client Info Card */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<Building2 className="h-5 w-5" />
|
|
Client Information
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">Client Name</p>
|
|
<p className="font-medium">{policy.client.name}</p>
|
|
</div>
|
|
{policy.client.city && (
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">Location</p>
|
|
<p className="font-medium">
|
|
{[policy.client.city, policy.client.state].filter(Boolean).join(', ')}
|
|
</p>
|
|
</div>
|
|
)}
|
|
{policy.client.designation && (
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">Primary Designation</p>
|
|
<Badge variant="outline">{policy.client.designation.name}</Badge>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Policy Details Grid */}
|
|
<div className="grid gap-6 md:grid-cols-2">
|
|
{/* Coverage Information */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<Shield className="h-5 w-5" />
|
|
Coverage Information
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">Type LOB</p>
|
|
<p className="font-medium text-lg">{policy.policyType || 'N/A'}</p>
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">Effective Date</p>
|
|
<p className="font-medium">
|
|
<span suppressHydrationWarning>
|
|
{policy.effectiveDate ? formatDate(policy.effectiveDate) : 'N/A'}
|
|
</span>
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">Expiration Date</p>
|
|
<p className="font-medium">
|
|
<span suppressHydrationWarning>
|
|
{formatDate(policy.expirationDate)}
|
|
</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
{policy.status && (
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">Status</p>
|
|
<Badge>{policy.status}</Badge>
|
|
</div>
|
|
)}
|
|
{policy.businessType && (
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">Business Type</p>
|
|
<p className="font-medium">{policy.businessType}</p>
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Carrier & Financial */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<Briefcase className="h-5 w-5" />
|
|
Carrier & Financial
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
{policy.writingCompanyName && (
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">Writing Company</p>
|
|
<p className="font-medium">{policy.writingCompanyName}</p>
|
|
</div>
|
|
)}
|
|
{policy.carrierName && (
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">Parent Company</p>
|
|
<p className="font-medium">{policy.carrierName}</p>
|
|
</div>
|
|
)}
|
|
{policy.billMethod && (
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">Billing Method</p>
|
|
<p className="font-medium">{policy.billMethod}</p>
|
|
</div>
|
|
)}
|
|
{policy.premiumAmount && (
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">Premium Amount</p>
|
|
<p className="font-medium text-lg">
|
|
${policy.premiumAmount.toLocaleString()}
|
|
</p>
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
{/* Personnel Information */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<Users className="h-5 w-5" />
|
|
Assigned Personnel
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="grid grid-cols-2 md:grid-cols-3 gap-6">
|
|
{policy.department && (
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">Department</p>
|
|
<Badge variant="outline" className="mt-1">{policy.department}</Badge>
|
|
</div>
|
|
)}
|
|
{policy.executiveName && (
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">Executive</p>
|
|
<p className="font-medium">{policy.executiveName}</p>
|
|
</div>
|
|
)}
|
|
{policy.csrName && (
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">CSR</p>
|
|
<p className="font-medium">{policy.csrName}</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Additional Personnel */}
|
|
{(policy.additionalRep1 || policy.additionalRep2 || policy.additionalExec1 || policy.additionalExec2) && (
|
|
<div className="mt-6 pt-6 border-t">
|
|
<p className="text-sm text-muted-foreground mb-3">Additional Personnel</p>
|
|
<div className="flex flex-wrap gap-2">
|
|
{policy.additionalRep1 && (
|
|
<Badge variant="secondary">Rep: {policy.additionalRep1}</Badge>
|
|
)}
|
|
{policy.additionalRep2 && (
|
|
<Badge variant="secondary">Rep: {policy.additionalRep2}</Badge>
|
|
)}
|
|
{policy.additionalExec1 && (
|
|
<Badge variant="secondary">Exec: {policy.additionalExec1}</Badge>
|
|
)}
|
|
{policy.additionalExec2 && (
|
|
<Badge variant="secondary">Exec: {policy.additionalExec2}</Badge>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Tasks Tab */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<CheckSquare className="h-5 w-5" />
|
|
Renewal Tasks ({policy.tasks.length})
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
{policy.tasks.length === 0 ? (
|
|
<p className="text-center text-muted-foreground py-8">
|
|
No tasks assigned to this policy
|
|
</p>
|
|
) : (
|
|
<div className="space-y-3">
|
|
{policy.tasks.map((task: any) => (
|
|
<div key={task.id} className="flex items-start justify-between p-4 border rounded-lg">
|
|
<div className="flex-1">
|
|
<h4 className="font-semibold">{task.title}</h4>
|
|
{task.description && (
|
|
<p className="text-sm text-muted-foreground mt-1">{task.description}</p>
|
|
)}
|
|
{task.assignments.length > 0 && (
|
|
<div className="flex gap-2 mt-2">
|
|
{task.assignments.map((assignment: any) => (
|
|
<Badge key={assignment.id} variant="outline" className="text-xs">
|
|
{assignment.user.displayName}
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
<div className="text-right ml-4">
|
|
<Badge variant={
|
|
task.status === 'COMPLETED' ? 'default' :
|
|
task.status === 'IN_PROGRESS' ? 'secondary' :
|
|
task.status === 'BLOCKED' ? 'destructive' : 'outline'
|
|
}>
|
|
{task.status}
|
|
</Badge>
|
|
{task.dueDate && (
|
|
<p className="text-xs text-muted-foreground mt-1">
|
|
Due: <span suppressHydrationWarning>{formatDate(task.dueDate)}</span>
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
)
|
|
}
|