primus-saas-react 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/styles.css +568 -0
  2. package/package.json +15 -9
  3. package/DEMO.md +0 -68
  4. package/INTEGRATION.md +0 -702
  5. package/build_log.txt +0 -0
  6. package/postcss.config.js +0 -6
  7. package/src/components/ai/AICopilot.tsx +0 -88
  8. package/src/components/auth/PrimusLogin.tsx +0 -298
  9. package/src/components/auth/UserProfile.tsx +0 -26
  10. package/src/components/banking/accounts/AccountDashboard.tsx +0 -67
  11. package/src/components/banking/cards/CreditCardVisual.tsx +0 -67
  12. package/src/components/banking/credit/CreditScoreCard.tsx +0 -80
  13. package/src/components/banking/kyc/KYCVerification.tsx +0 -76
  14. package/src/components/banking/loans/LoanCalculator.tsx +0 -106
  15. package/src/components/banking/transactions/TransactionHistory.tsx +0 -74
  16. package/src/components/crud/PrimusDataTable.tsx +0 -220
  17. package/src/components/crud/PrimusModal.tsx +0 -68
  18. package/src/components/dashboard/PrimusDashboard.tsx +0 -145
  19. package/src/components/documents/DocumentViewer.tsx +0 -107
  20. package/src/components/featureflags/FeatureFlagToggle.tsx +0 -64
  21. package/src/components/insurance/agents/AgentDirectory.tsx +0 -72
  22. package/src/components/insurance/claims/ClaimStatusTracker.tsx +0 -78
  23. package/src/components/insurance/fraud/FraudDetectionDashboard.tsx +0 -68
  24. package/src/components/insurance/policies/PolicyCard.tsx +0 -77
  25. package/src/components/insurance/premium/PremiumCalculator.tsx +0 -104
  26. package/src/components/insurance/quotes/QuoteComparison.tsx +0 -75
  27. package/src/components/layout/PrimusHeader.tsx +0 -75
  28. package/src/components/layout/PrimusLayout.tsx +0 -47
  29. package/src/components/layout/PrimusSidebar.tsx +0 -102
  30. package/src/components/logging/LogViewer.tsx +0 -90
  31. package/src/components/notifications/NotificationFeed.tsx +0 -106
  32. package/src/components/notifications/PrimusNotificationCenter.tsx +0 -282
  33. package/src/components/payments/CheckoutForm.tsx +0 -167
  34. package/src/components/security/SecurityDashboard.tsx +0 -83
  35. package/src/components/shared/Button.tsx +0 -36
  36. package/src/components/shared/Input.tsx +0 -36
  37. package/src/components/storage/FileUploader.tsx +0 -79
  38. package/src/context/PrimusProvider.tsx +0 -156
  39. package/src/context/PrimusThemeProvider.tsx +0 -160
  40. package/src/hooks/useNotifications.ts +0 -58
  41. package/src/hooks/usePrimusAuth.ts +0 -3
  42. package/src/hooks/useRealtimeNotifications.ts +0 -114
  43. package/src/index.ts +0 -42
  44. package/tailwind.config.js +0 -18
  45. package/tsconfig.json +0 -28
@@ -1,145 +0,0 @@
1
- import React from 'react';
2
-
3
- export interface StatCardProps {
4
- title: string;
5
- value: string | number;
6
- change?: {
7
- value: number;
8
- type: 'increase' | 'decrease' | 'neutral';
9
- };
10
- icon?: React.ReactNode;
11
- description?: string;
12
- trend?: number[]; // Values for sparkline
13
- }
14
-
15
- export const PrimusStatCard: React.FC<StatCardProps> = ({
16
- title,
17
- value,
18
- change,
19
- icon,
20
- description,
21
- trend = [40, 35, 50, 45, 60, 55, 70] // Default dummy data
22
- }) => {
23
- const changeColors = {
24
- increase: 'text-emerald-400 bg-emerald-400/10',
25
- decrease: 'text-rose-400 bg-rose-400/10',
26
- neutral: 'text-gray-400 bg-gray-400/10',
27
- };
28
-
29
- const changeIcons = {
30
- increase: '↑',
31
- decrease: '↓',
32
- neutral: '→',
33
- };
34
-
35
- // Render Sparkline
36
- const renderSparkline = () => {
37
- // Sparkline implementation simplified for visual effect
38
- // In a real app, 'trend' would be normalized to SVG coordinates
39
- return (
40
- <svg className="w-full h-12 opacity-50 absolute bottom-0 left-0" preserveAspectRatio="none" data-trend={trend.join(',')}>
41
- <path d="M0 40 Q 20 20 40 40 T 80 40 T 120 40 T 160 30 V 50 H 0 Z" fill={`url(#gradient-${title.replace(/\s/g, '')})`} stroke="none" />
42
- <defs>
43
- <linearGradient id={`gradient-${title.replace(/\s/g, '')}`} x1="0" y1="0" x2="0" y2="1">
44
- <stop offset="0%" stopColor="currentColor" stopOpacity="0.2" />
45
- <stop offset="100%" stopColor="currentColor" stopOpacity="0" />
46
- </linearGradient>
47
- </defs>
48
- </svg>
49
- );
50
- };
51
-
52
- return (
53
- <div className="relative overflow-hidden bg-slate-900/40 backdrop-blur-md rounded-2xl border border-white/5 hover:border-white/10 transition-all duration-300 group">
54
- <div className="absolute inset-0 bg-gradient-to-br from-white/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none" />
55
-
56
- <div className="p-6 relative z-10">
57
- <div className="flex items-start justify-between mb-4">
58
- <div className="p-2.5 rounded-lg bg-white/5 text-gray-300 ring-1 ring-white/10 group-hover:bg-purple-500/20 group-hover:text-purple-300 transition-colors">
59
- {icon || <div className="w-5 h-5 bg-current opacity-20" />}
60
- </div>
61
- {change && (
62
- <span className={`px-2 py-0.5 text-xs font-medium rounded-full flex items-center gap-1 ${changeColors[change.type]}`}>
63
- {changeIcons[change.type]} {Math.abs(change.value)}%
64
- </span>
65
- )}
66
- </div>
67
-
68
- <div>
69
- <h3 className="text-sm font-medium text-gray-400 tracking-wide">{title}</h3>
70
- <div className="mt-1 flex items-baseline gap-2">
71
- <span className="text-3xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-white to-gray-400">
72
- {value}
73
- </span>
74
- </div>
75
- {description && (
76
- <p className="text-xs text-gray-500 mt-2 font-medium">{description}</p>
77
- )}
78
- </div>
79
- </div>
80
-
81
- {renderSparkline()}
82
-
83
- {/* Sparkline Decor (abstract) */}
84
- <div className={`absolute -bottom-2 -right-4 w-32 h-32 blur-2xl opacity-20 rounded-full transition-colors duration-500 ${change?.type === 'increase' ? 'bg-emerald-500' :
85
- change?.type === 'decrease' ? 'bg-rose-500' : 'bg-blue-500'
86
- }`} />
87
- </div>
88
- );
89
- };
90
-
91
- export interface PrimusDashboardProps {
92
- children: React.ReactNode;
93
- title?: string;
94
- subtitle?: string;
95
- actions?: React.ReactNode;
96
- }
97
-
98
- export const PrimusDashboard: React.FC<PrimusDashboardProps> = ({
99
- children,
100
- title,
101
- subtitle,
102
- actions,
103
- }) => {
104
- return (
105
- <div className="space-y-8 animate-enter">
106
- {(title || actions) && (
107
- <div className="flex flex-col md:flex-row md:items-end justify-between gap-4 border-b border-white/5 pb-6">
108
- <div>
109
- {title && (
110
- <h1 className="text-3xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-white via-gray-200 to-gray-400 tracking-tight">
111
- {title}
112
- </h1>
113
- )}
114
- {subtitle && <p className="text-gray-400 mt-2 text-lg font-light leading-relaxed">{subtitle}</p>}
115
- </div>
116
- {actions && <div className="flex items-center gap-3">{actions}</div>}
117
- </div>
118
- )}
119
- {children}
120
- </div>
121
- );
122
- };
123
-
124
- export interface DashboardGridProps {
125
- children: React.ReactNode;
126
- columns?: 1 | 2 | 3 | 4;
127
- }
128
-
129
- export const DashboardGrid: React.FC<DashboardGridProps> = ({
130
- children,
131
- columns = 4,
132
- }) => {
133
- const colClasses = {
134
- 1: 'grid-cols-1',
135
- 2: 'grid-cols-1 md:grid-cols-2',
136
- 3: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',
137
- 4: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-4',
138
- };
139
-
140
- return (
141
- <div className={`grid gap-6 ${colClasses[columns]}`}>
142
- {children}
143
- </div>
144
- );
145
- };
@@ -1,107 +0,0 @@
1
- import React from 'react';
2
- import { Button } from '../shared/Button';
3
- import {
4
- DocumentArrowDownIcon,
5
- // EyeIcon,
6
- PrinterIcon,
7
- XMarkIcon
8
- } from '@heroicons/react/24/outline';
9
-
10
- export interface Document {
11
- id: string;
12
- name: string;
13
- type: 'pdf' | 'image' | 'text';
14
- url: string;
15
- size?: string;
16
- date?: string;
17
- }
18
-
19
- export interface DocumentViewerProps {
20
- document: Document;
21
- onClose?: () => void;
22
- onDownload?: () => void;
23
- }
24
-
25
- export const DocumentViewer: React.FC<DocumentViewerProps> = ({
26
- document,
27
- onClose,
28
- onDownload
29
- }) => {
30
- // const [isFullscreen, setIsFullscreen] = useState(false);
31
-
32
- // Mock content display based on type
33
- const renderContent = () => {
34
- switch (document.type) {
35
- case 'image':
36
- return (
37
- <img
38
- src={document.url}
39
- alt={document.name}
40
- className="max-w-full max-h-[80vh] object-contain mx-auto shadow-lg rounded"
41
- />
42
- );
43
- case 'pdf':
44
- return (
45
- <div className="bg-gray-100 p-8 rounded-lg text-center h-[600px] flex items-center justify-center border-2 border-dashed border-gray-300">
46
- <div className="text-gray-500">
47
- <DocumentArrowDownIcon className="h-16 w-16 mx-auto mb-4 text-gray-400" />
48
- <p className="font-medium">PDF Preview</p>
49
- <p className="text-sm mt-2">{document.name}</p>
50
- <Button variant="outline" size="sm" className="mt-4" onClick={onDownload}>
51
- Download to view
52
- </Button>
53
- </div>
54
- </div>
55
- );
56
- default:
57
- return (
58
- <div className="bg-white p-8 rounded shadow border border-gray-200 h-[600px] overflow-auto font-mono text-sm leading-relaxed">
59
- {/* Mock text content */}
60
- <p>Document Content: {document.name}</p>
61
- <p className="mt-4 text-gray-500">
62
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
63
- </p>
64
- </div>
65
- );
66
- }
67
- };
68
-
69
- return (
70
- <div className="flex flex-col h-full bg-gray-50 rounded-lg overflow-hidden border border-gray-200">
71
- {/* Header */}
72
- <div className="bg-white border-b border-gray-200 px-4 py-3 flex items-center justify-between shadow-sm">
73
- <div className="flex items-center gap-3">
74
- <div className="h-8 w-8 bg-primus-100 rounded flex items-center justify-center text-primus-700">
75
- <span className="uppercase text-xs font-bold">{document.type}</span>
76
- </div>
77
- <div>
78
- <h3 className="text-sm font-semibold text-gray-900">{document.name}</h3>
79
- {document.size && <p className="text-xs text-gray-500">{document.size} • {document.date}</p>}
80
- </div>
81
- </div>
82
-
83
- <div className="flex items-center gap-2">
84
- <Button variant="ghost" size="sm" onClick={() => window.print()}>
85
- <PrinterIcon className="h-4 w-4" />
86
- </Button>
87
- <Button variant="ghost" size="sm" onClick={onDownload}>
88
- <DocumentArrowDownIcon className="h-4 w-4" />
89
- </Button>
90
- {onClose && (
91
- <div className="h-6 w-px bg-gray-200 mx-1" />
92
- )}
93
- {onClose && (
94
- <Button variant="ghost" size="sm" onClick={onClose} className="text-gray-400 hover:text-red-500">
95
- <XMarkIcon className="h-5 w-5" />
96
- </Button>
97
- )}
98
- </div>
99
- </div>
100
-
101
- {/* Content Area */}
102
- <div className="flex-1 overflow-auto p-6 flex flex-col items-center justify-center">
103
- {renderContent()}
104
- </div>
105
- </div>
106
- );
107
- };
@@ -1,64 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
-
3
- export interface FeatureFlag {
4
- name: string;
5
- enabled: boolean;
6
- description: string;
7
- rolloutPercentage?: number;
8
- }
9
-
10
- export const FeatureFlagToggle: React.FC<{ apiUrl?: string }> = ({
11
- apiUrl = 'http://localhost:5221'
12
- }) => {
13
- const [flags, setFlags] = useState<FeatureFlag[]>([]);
14
- const [loading, setLoading] = useState(true);
15
-
16
- useEffect(() => {
17
- fetchFlags();
18
- }, []);
19
-
20
- const fetchFlags = async () => {
21
- try {
22
- const response = await fetch(`${apiUrl}/api/featureflags`);
23
- if (response.ok) {
24
- const data = await response.json();
25
- setFlags(data);
26
- }
27
- } catch (error) {
28
- console.error('Failed to fetch feature flags:', error);
29
- } finally {
30
- setLoading(false);
31
- }
32
- };
33
-
34
- if (loading) {
35
- return <div className="p-4">Loading feature flags...</div>;
36
- }
37
-
38
- return (
39
- <div className="bg-white p-6 rounded-lg border border-gray-200 shadow-sm">
40
- <h3 className="text-lg font-medium text-gray-900 mb-4">Feature Flags</h3>
41
- <div className="space-y-4">
42
- {flags.map((flag) => (
43
- <div key={flag.name} className="flex items-center justify-between p-4 bg-gray-50 rounded-lg">
44
- <div className="flex-1">
45
- <h4 className="font-medium text-gray-900">{flag.name}</h4>
46
- <p className="text-sm text-gray-500">{flag.description}</p>
47
- {flag.rolloutPercentage !== undefined && (
48
- <p className="text-xs text-gray-400 mt-1">
49
- Rollout: {flag.rolloutPercentage}%
50
- </p>
51
- )}
52
- </div>
53
- <div className={`px-3 py-1 rounded-full text-sm font-medium ${flag.enabled
54
- ? 'bg-green-100 text-green-800'
55
- : 'bg-gray-100 text-gray-800'
56
- }`}>
57
- {flag.enabled ? 'Enabled' : 'Disabled'}
58
- </div>
59
- </div>
60
- ))}
61
- </div>
62
- </div>
63
- );
64
- };
@@ -1,72 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
-
3
- interface Agent {
4
- id: string;
5
- name: string;
6
- email: string;
7
- phone: string;
8
- specialty: string;
9
- rating: number;
10
- yearsExperience: number;
11
- }
12
-
13
- export const AgentDirectory: React.FC<{ apiUrl?: string }> = ({
14
- apiUrl = 'http://localhost:5221'
15
- }) => {
16
- const [agents, setAgents] = useState<Agent[]>([]);
17
- const [loading, setLoading] = useState(true);
18
-
19
- useEffect(() => {
20
- fetchAgents();
21
- }, []);
22
-
23
- const fetchAgents = async () => {
24
- try {
25
- const response = await fetch(`${apiUrl}/api/insurance/agents`);
26
- if (response.ok) {
27
- const data = await response.json();
28
- setAgents(data);
29
- }
30
- } catch (error) {
31
- console.error('Failed to fetch agents:', error);
32
- } finally {
33
- setLoading(false);
34
- }
35
- };
36
-
37
- if (loading) return <div className="p-4">Loading agents...</div>;
38
-
39
- return (
40
- <div className="bg-white p-6 rounded-lg border border-gray-200 shadow-sm">
41
- <h3 className="text-lg font-medium text-gray-900 mb-4">Insurance Agents</h3>
42
-
43
- <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
44
- {agents.map((agent) => (
45
- <div key={agent.id} className="p-4 border border-gray-200 rounded-lg">
46
- <div className="flex items-start gap-3">
47
- <div className="w-12 h-12 bg-primus-100 rounded-full flex items-center justify-center text-primus-600 font-bold text-lg">
48
- {agent.name.split(' ').map(n => n[0]).join('')}
49
- </div>
50
- <div className="flex-1">
51
- <h4 className="font-medium text-gray-900">{agent.name}</h4>
52
- <p className="text-sm text-gray-600">{agent.specialty}</p>
53
- <div className="flex items-center gap-2 mt-1">
54
- <div className="flex items-center">
55
- {'⭐'.repeat(Math.floor(agent.rating))}
56
- <span className="text-xs text-gray-500 ml-1">{agent.rating}</span>
57
- </div>
58
- <span className="text-xs text-gray-400">•</span>
59
- <span className="text-xs text-gray-500">{agent.yearsExperience} years</span>
60
- </div>
61
- <div className="mt-2 space-y-1">
62
- <p className="text-xs text-gray-600">{agent.email}</p>
63
- <p className="text-xs text-gray-600">{agent.phone}</p>
64
- </div>
65
- </div>
66
- </div>
67
- </div>
68
- ))}
69
- </div>
70
- </div>
71
- );
72
- };
@@ -1,78 +0,0 @@
1
- import React from 'react';
2
- import { clsx } from 'clsx';
3
- import { CheckIcon } from '@heroicons/react/24/solid';
4
-
5
- export interface ClaimStep {
6
- id: string;
7
- label: string;
8
- status: 'completed' | 'current' | 'upcoming';
9
- date?: string;
10
- }
11
-
12
- export interface ClaimStatusTrackerProps {
13
- claimId: string;
14
- steps: ClaimStep[];
15
- }
16
-
17
- export const ClaimStatusTracker: React.FC<ClaimStatusTrackerProps> = ({
18
- claimId,
19
- steps
20
- }) => {
21
- return (
22
- <div className="bg-white rounded-xl border border-gray-200 shadow-sm p-6">
23
- <div className="mb-8">
24
- <h3 className="text-lg font-semibold text-gray-900">Claim Status</h3>
25
- <p className="text-sm text-gray-500">Claim ID: #{claimId}</p>
26
- </div>
27
-
28
- <nav aria-label="Progress">
29
- <ol role="list" className="overflow-hidden">
30
- {steps.map((step, stepIdx) => (
31
- <li key={step.label} className={clsx(
32
- "relative pb-10",
33
- stepIdx === steps.length - 1 ? "pb-0" : ""
34
- )}>
35
- {stepIdx !== steps.length - 1 ? (
36
- <div
37
- className={clsx(
38
- "absolute top-4 left-4 -ml-px h-full w-0.5",
39
- step.status === 'completed' ? "bg-primus-600" : "bg-gray-200"
40
- )}
41
- aria-hidden="true"
42
- />
43
- ) : null}
44
-
45
- <div className="relative flex items-start group">
46
- <span className="h-9 flex items-center">
47
- <span className={clsx(
48
- "relative z-10 w-8 h-8 flex items-center justify-center rounded-full ring-1 ring-white",
49
- step.status === 'completed' ? "bg-primus-600" :
50
- step.status === 'current' ? "bg-white border-2 border-primus-600" :
51
- "bg-white border-2 border-gray-300"
52
- )}>
53
- {step.status === 'completed' ? (
54
- <CheckIcon className="w-5 h-5 text-white" aria-hidden="true" />
55
- ) : step.status === 'current' ? (
56
- <span className="h-2.5 w-2.5 bg-primus-600 rounded-full" />
57
- ) : null}
58
- </span>
59
- </span>
60
- <span className="ml-4 min-w-0 flex flex-col">
61
- <span className={clsx(
62
- "text-sm font-medium",
63
- step.status === 'upcoming' ? "text-gray-500" : "text-gray-900"
64
- )}>
65
- {step.label}
66
- </span>
67
- {step.date && (
68
- <span className="text-xs text-gray-500 mt-1">{step.date}</span>
69
- )}
70
- </span>
71
- </div>
72
- </li>
73
- ))}
74
- </ol>
75
- </nav>
76
- </div>
77
- );
78
- };
@@ -1,68 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
-
3
- export const FraudDetectionDashboard: React.FC<{ apiUrl?: string }> = ({
4
- apiUrl = 'http://localhost:5221'
5
- }) => {
6
- const [alerts, setAlerts] = useState<any[]>([]);
7
- const [loading, setLoading] = useState(true);
8
-
9
- useEffect(() => {
10
- fetchAlerts();
11
- }, []);
12
-
13
- const fetchAlerts = async () => {
14
- try {
15
- const response = await fetch(`${apiUrl}/api/insurance/fraud/alerts`);
16
- if (response.ok) {
17
- const data = await response.json();
18
- setAlerts(data);
19
- }
20
- } catch (error) {
21
- console.error('Failed to fetch fraud alerts:', error);
22
- } finally {
23
- setLoading(false);
24
- }
25
- };
26
-
27
- const getSeverityColor = (severity: string) => {
28
- switch (severity.toLowerCase()) {
29
- case 'high': return 'bg-red-100 text-red-800 border-red-200';
30
- case 'medium': return 'bg-yellow-100 text-yellow-800 border-yellow-200';
31
- case 'low': return 'bg-blue-100 text-blue-800 border-blue-200';
32
- default: return 'bg-gray-100 text-gray-800 border-gray-200';
33
- }
34
- };
35
-
36
- if (loading) return <div className="p-4">Loading fraud alerts...</div>;
37
-
38
- return (
39
- <div className="bg-white p-6 rounded-lg border border-gray-200 shadow-sm">
40
- <div className="flex justify-between items-center mb-4">
41
- <h3 className="text-lg font-medium text-gray-900">Fraud Detection</h3>
42
- <span className="px-3 py-1 bg-red-100 text-red-800 rounded-full text-sm font-medium">
43
- {alerts.length} Active Alerts
44
- </span>
45
- </div>
46
-
47
- <div className="space-y-3">
48
- {alerts.map((alert) => (
49
- <div key={alert.id} className={`p-4 border-2 rounded-lg ${getSeverityColor(alert.severity)}`}>
50
- <div className="flex justify-between items-start mb-2">
51
- <div>
52
- <h4 className="font-medium">{alert.type.replace(/_/g, ' ').toUpperCase()}</h4>
53
- <p className="text-sm mt-1">{alert.description}</p>
54
- </div>
55
- <span className="px-2 py-1 bg-white rounded text-xs font-medium">
56
- {alert.severity}
57
- </span>
58
- </div>
59
- <div className="flex justify-between items-center mt-3 text-xs">
60
- <span>Claim: {alert.claimId}</span>
61
- <span>{new Date(alert.detectedDate).toLocaleString()}</span>
62
- </div>
63
- </div>
64
- ))}
65
- </div>
66
- </div>
67
- );
68
- };
@@ -1,77 +0,0 @@
1
- import React from 'react';
2
- import { Button } from '../../shared/Button';
3
- import { clsx } from "clsx";
4
- import { ShieldCheckIcon, DocumentTextIcon } from '@heroicons/react/24/outline';
5
-
6
- export interface PolicyProps {
7
- policyNumber: string;
8
- type: string;
9
- status: 'active' | 'expired' | 'pending';
10
- coverageAmount: number;
11
- nextPaymentDate: string;
12
- premiumAmount: number;
13
- }
14
-
15
- export const PolicyCard: React.FC<PolicyProps> = ({
16
- policyNumber,
17
- type,
18
- status,
19
- coverageAmount,
20
- nextPaymentDate,
21
- premiumAmount
22
- }) => {
23
- return (
24
- <div className="bg-white rounded-xl border border-gray-200 shadow-sm overflow-hidden hover:shadow-md transition-shadow">
25
- <div className="bg-gray-50 px-6 py-4 border-b border-gray-100 flex justify-between items-center">
26
- <div className="flex items-center gap-2">
27
- <ShieldCheckIcon className="h-5 w-5 text-primus-600" />
28
- <span className="font-semibold text-gray-900">{type} Insurance</span>
29
- </div>
30
- <span className={clsx(
31
- "px-2.5 py-0.5 rounded-full text-xs font-medium uppercase tracking-wide",
32
- status === 'active' ? "bg-green-100 text-green-800" :
33
- status === 'pending' ? "bg-yellow-100 text-yellow-800" :
34
- "bg-gray-100 text-gray-800"
35
- )}>
36
- {status}
37
- </span>
38
- </div>
39
-
40
- <div className="p-6">
41
- <div className="mb-6">
42
- <p className="text-xs text-gray-500 uppercase tracking-wider mb-1">Policy Number</p>
43
- <p className="font-mono text-lg font-medium text-gray-900">{policyNumber}</p>
44
- </div>
45
-
46
- <div className="grid grid-cols-2 gap-6 mb-6">
47
- <div>
48
- <p className="text-xs text-gray-500 uppercase tracking-wider mb-1">Coverage</p>
49
- <p className="text-xl font-bold text-gray-900">
50
- {new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 }).format(coverageAmount)}
51
- </p>
52
- </div>
53
- <div>
54
- <p className="text-xs text-gray-500 uppercase tracking-wider mb-1">Premium</p>
55
- <p className="text-gray-900 font-medium">
56
- {new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(premiumAmount)}
57
- <span className="text-xs text-gray-500 font-normal"> / month</span>
58
- </p>
59
- </div>
60
- </div>
61
-
62
- <div className="bg-blue-50 rounded-lg p-3 flex items-start gap-3 mb-6">
63
- <DocumentTextIcon className="h-5 w-5 text-blue-600 mt-0.5" />
64
- <div>
65
- <p className="text-sm font-medium text-blue-900">Next Payment due</p>
66
- <p className="text-sm text-blue-700">{nextPaymentDate}</p>
67
- </div>
68
- </div>
69
-
70
- <div className="flex gap-3">
71
- <Button variant="outline" className="flex-1">View Details</Button>
72
- <Button className="flex-1">File Claim</Button>
73
- </div>
74
- </div>
75
- </div>
76
- );
77
- };