initial commit

This commit is contained in:
Josh Myers
2026-04-09 20:36:10 -07:00
commit 4681b1a3c8
248 changed files with 97032 additions and 0 deletions

View File

@@ -0,0 +1,853 @@
'use client';
import { useState, useEffect } from 'react';
import { formatCurrency, formatCompactCurrency } from '@/lib/utils';
import {
TrendingUp,
DollarSign,
Percent,
Calendar,
Plus,
Loader2,
AlertCircle,
CheckCircle,
Zap,
ChevronDown,
ChevronUp,
} from 'lucide-react';
interface DebtFacility {
id: string;
name: string;
lender: string;
type: 'Revolving Credit' | 'Term Loan' | 'Line of Credit' | 'Equipment Financing' | 'Other';
commitmentAmount: number;
drawnAmount: number;
availableAmount: number;
interestRate: string;
maturityDate: string;
status: 'Active' | 'Inactive' | 'Closed';
draws: DebtDraw[];
}
interface DebtDraw {
id: string;
facilityId: string;
drawDate: string;
amount: number;
repaymentDate: string | null;
status: 'Active' | 'Repaid' | 'Partial';
interestRate: string;
}
interface Covenant {
id: string;
name: string;
type: string;
metric: string;
threshold: string | number;
currentValue: string | number;
status: 'Compliant' | 'Warning' | 'Breach';
lastChecked: string;
headroom: string;
}
interface NewFacilityForm {
name: string;
lender: string;
type: 'Revolving Credit' | 'Term Loan' | 'Line of Credit' | 'Equipment Financing' | 'Other';
commitmentAmount: string;
interestRate: string;
maturityDate: string;
}
interface NewDrawForm {
facilityId: string;
amount: string;
date: string;
interestRate: string;
}
interface Toast {
id: string;
message: string;
type: 'success' | 'error' | 'info';
}
export default function CapitalMarketsPage() {
const [loading, setLoading] = useState(true);
const [activeTab, setActiveTab] = useState('facilities');
const [showNewFacility, setShowNewFacility] = useState(false);
const [showRecordDraw, setShowRecordDraw] = useState(false);
const [expandedFacilityId, setExpandedFacilityId] = useState<string | null>(null);
const [toasts, setToasts] = useState<Toast[]>([]);
const [facilities, setFacilities] = useState<DebtFacility[]>([]);
const [draws, setDraws] = useState<DebtDraw[]>([]);
const [covenants, setCovenants] = useState<Covenant[]>([]);
const [newFacilityForm, setNewFacilityForm] = useState<NewFacilityForm>({
name: '',
lender: '',
type: 'Revolving Credit',
commitmentAmount: '',
interestRate: '',
maturityDate: '',
});
const [newDrawForm, setNewDrawForm] = useState<NewDrawForm>({
facilityId: '',
amount: '',
date: new Date().toISOString().split('T')[0],
interestRate: '',
});
const [summary, setSummary] = useState({
totalDebtOutstanding: 0,
totalAvailable: 0,
weightedAvgRate: 0,
nextMaturityDate: null as string | null,
covenantStatus: 'All Clear',
});
// Toast helper
const addToast = (message: string, type: 'success' | 'error' | 'info' = 'info') => {
const id = Math.random().toString(36).substring(7);
setToasts((prev) => [...prev, { id, message, type }]);
setTimeout(() => {
setToasts((prev) => prev.filter((t) => t.id !== id));
}, 4000);
};
// Fetch data from API
useEffect(() => {
const fetchData = async () => {
try {
setLoading(true);
const res = await fetch('/api/capital-markets');
if (!res.ok) throw new Error('Failed to fetch capital markets data');
const data = await res.json();
setFacilities(data.facilities);
setDraws(data.draws);
setCovenants(data.covenants);
setSummary({
totalDebtOutstanding: data.summary?.totalOutstanding ?? 0,
totalAvailable: data.summary?.totalAvailable ?? 0,
weightedAvgRate: data.summary?.weightedAvgRate ?? 0,
nextMaturityDate: data.summary?.nextMaturityDate ?? '',
covenantStatus: data.summary?.covenantStatus ?? 'Unknown',
});
} catch (err) {
console.error('Error fetching capital markets data:', err);
addToast('Failed to fetch capital markets data', 'error');
} finally {
setLoading(false);
}
};
fetchData();
}, []);
const handleAddFacility = async () => {
if (!newFacilityForm.name || !newFacilityForm.lender || !newFacilityForm.commitmentAmount || !newFacilityForm.interestRate || !newFacilityForm.maturityDate) {
addToast('Please fill in all required fields', 'error');
return;
}
try {
setLoading(true);
const res = await fetch('/api/capital-markets', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
action: 'create-facility',
facility: newFacilityForm,
}),
});
if (!res.ok) {
const error = await res.json();
throw new Error(error.error || 'Failed to create facility');
}
// Reset form and close modal
setNewFacilityForm({
name: '',
lender: '',
type: 'Revolving Credit',
commitmentAmount: '',
interestRate: '',
maturityDate: '',
});
setShowNewFacility(false);
addToast('Facility created successfully', 'success');
// Refetch data to keep in sync
const refreshRes = await fetch('/api/capital-markets');
if (refreshRes.ok) {
const refreshData = await refreshRes.json();
setFacilities(refreshData.facilities);
setDraws(refreshData.draws);
setCovenants(refreshData.covenants);
setSummary({
totalDebtOutstanding: refreshData.summary.totalOutstanding,
totalAvailable: refreshData.summary.totalAvailable,
weightedAvgRate: refreshData.summary.weightedAvgRate,
nextMaturityDate: refreshData.summary.nextMaturityDate,
covenantStatus: refreshData.summary.covenantStatus,
});
}
} catch (err) {
console.error('Error adding facility:', err);
addToast(err instanceof Error ? err.message : 'Failed to create facility', 'error');
} finally {
setLoading(false);
}
};
const handleRecordDraw = async () => {
if (!newDrawForm.facilityId || !newDrawForm.amount) {
addToast('Please select a facility and enter an amount', 'error');
return;
}
try {
setLoading(true);
const res = await fetch('/api/capital-markets', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
action: 'record-draw',
draw: newDrawForm,
}),
});
if (!res.ok) {
const error = await res.json();
throw new Error(error.error || 'Failed to record draw');
}
setNewDrawForm({
facilityId: '',
amount: '',
date: new Date().toISOString().split('T')[0],
interestRate: '',
});
setShowRecordDraw(false);
addToast('Draw recorded successfully', 'success');
// Refetch data to keep in sync
const refreshRes = await fetch('/api/capital-markets');
if (refreshRes.ok) {
const refreshData = await refreshRes.json();
setFacilities(refreshData.facilities);
setDraws(refreshData.draws);
setCovenants(refreshData.covenants);
setSummary({
totalDebtOutstanding: refreshData.summary.totalOutstanding,
totalAvailable: refreshData.summary.totalAvailable,
weightedAvgRate: refreshData.summary.weightedAvgRate,
nextMaturityDate: refreshData.summary.nextMaturityDate,
covenantStatus: refreshData.summary.covenantStatus,
});
}
} catch (err) {
console.error('Error recording draw:', err);
addToast(err instanceof Error ? err.message : 'Failed to record draw', 'error');
} finally {
setLoading(false);
}
};
function formatDate(dateStr: string) {
return new Date(dateStr).toLocaleDateString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric',
});
}
const getCovenanStatusColor = (status: string) => {
switch (status) {
case 'Compliant':
return 'bg-green-900/25 text-green-800 border-green-200';
case 'Warning':
return 'bg-yellow-900/25 text-yellow-400 border-yellow-500/25';
case 'Breach':
return 'bg-red-900/25 text-red-800 border-red-200';
default:
return 'bg-[#1A1A1F] text-[#F0F0F3] border-[#2A2A32]';
}
};
const getCovenanStatusIcon = (status: string) => {
switch (status) {
case 'Compliant':
return <CheckCircle size={16} />;
case 'Warning':
return <AlertCircle size={16} />;
case 'Breach':
return <AlertCircle size={16} />;
default:
return null;
}
};
const getCovenantSummaryBadge = () => {
const status = summary.covenantStatus;
if (status === 'In Breach') {
return <span className="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-red-900/25 text-red-800 border border-red-200">In Breach</span>;
} else if (status === 'At Risk') {
return <span className="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-yellow-900/25 text-yellow-400 border border-yellow-500/25">At Risk</span>;
} else {
return <span className="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-green-900/25 text-green-800 border border-green-200">All Clear</span>;
}
};
if (loading && facilities.length === 0) {
return (
<div className="flex items-center justify-center min-h-screen">
<Loader2 className="animate-spin" size={32} />
</div>
);
}
return (
<div className="min-h-screen bg-[#111114] p-8">
{/* Toast Notifications */}
<div className="fixed top-4 right-4 z-50 space-y-2">
{toasts.map((toast) => (
<div
key={toast.id}
className={`px-4 py-3 rounded-lg text-sm font-medium shadow-lg ${
toast.type === 'success'
? 'bg-green-500 text-white'
: toast.type === 'error'
? 'bg-red-500 text-white'
: 'bg-blue-500 text-white'
}`}
>
{toast.message}
</div>
))}
</div>
<div className="max-w-7xl mx-auto">
{/* Header */}
<div className="flex justify-between items-start mb-8">
<div>
<h1 className="text-4xl font-bold text-[#F0F0F3] mb-2">Capital Markets</h1>
<p className="text-lg text-[#8B8B9E]">Debt Management, Credit Facilities & Covenant Compliance</p>
</div>
<div className="flex gap-4">
<button
onClick={() => setShowNewFacility(true)}
className="flex items-center gap-2 bg-blue-600 text-white px-6 py-2.5 rounded-lg hover:bg-blue-700 transition-colors font-medium"
>
<Plus size={18} />
New Facility
</button>
<button
onClick={() => setShowRecordDraw(true)}
className="flex items-center gap-2 bg-green-600 text-white px-6 py-2.5 rounded-lg hover:bg-green-700 transition-colors font-medium"
>
<DollarSign size={18} />
Record Draw
</button>
</div>
</div>
{/* Summary Cards */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-6 mb-8">
<div className="bg-[#1A1A1F] rounded-lg border border-[#2A2A32] p-6" title={formatCurrency(summary.totalDebtOutstanding)}>
<div className="flex items-center justify-between mb-4">
<div className="bg-blue-900/25 p-3 rounded-lg">
<TrendingUp className="w-6 h-6 text-blue-600" />
</div>
</div>
<p className="text-sm font-medium text-[#8B8B9E]">Total Debt Outstanding</p>
<p className="text-2xl font-bold text-[#F0F0F3] mt-2">{formatCompactCurrency(summary.totalDebtOutstanding)}</p>
<p className="text-xs text-[#8B8B9E] mt-1">Across {facilities.length} facilities</p>
</div>
<div className="bg-[#1A1A1F] rounded-lg border border-[#2A2A32] p-6" title={formatCurrency(summary.totalAvailable)}>
<div className="flex items-center justify-between mb-4">
<div className="bg-green-900/25 p-3 rounded-lg">
<DollarSign className="w-6 h-6 text-green-600" />
</div>
</div>
<p className="text-sm font-medium text-[#8B8B9E]">Available Credit</p>
<p className="text-2xl font-bold text-[#F0F0F3] mt-2">{formatCompactCurrency(summary.totalAvailable)}</p>
<p className="text-xs text-[#8B8B9E] mt-1">Ready to draw</p>
</div>
<div className="bg-[#1A1A1F] rounded-lg border border-[#2A2A32] p-6">
<div className="flex items-center justify-between mb-4">
<div className="bg-orange-900/25 p-3 rounded-lg">
<Percent className="w-6 h-6 text-orange-600" />
</div>
</div>
<p className="text-sm font-medium text-[#8B8B9E]">Weighted Avg Rate</p>
<p className="text-2xl font-bold text-[#F0F0F3] mt-2">{summary.weightedAvgRate.toFixed(2)}%</p>
<p className="text-xs text-[#8B8B9E] mt-1">All active facilities</p>
</div>
<div className="bg-[#1A1A1F] rounded-lg border border-[#2A2A32] p-6">
<div className="flex items-center justify-between mb-4">
<div className="bg-purple-900/25 p-3 rounded-lg">
<Calendar className="w-6 h-6 text-purple-600" />
</div>
</div>
<p className="text-sm font-medium text-[#8B8B9E]">Next Maturity</p>
<p className="text-2xl font-bold text-[#F0F0F3] mt-2">
{summary.nextMaturityDate ? formatDate(summary.nextMaturityDate) : 'N/A'}
</p>
<p className="text-xs text-[#8B8B9E] mt-1">Upcoming refinancing</p>
</div>
<div className="bg-[#1A1A1F] rounded-lg border border-[#2A2A32] p-6">
<div className="flex items-center justify-between mb-4">
<div className="bg-indigo-900/15 p-3 rounded-lg">
<Zap className="w-6 h-6 text-indigo-600" />
</div>
</div>
<p className="text-sm font-medium text-[#8B8B9E]">Covenant Status</p>
<div className="mt-2">
{getCovenantSummaryBadge()}
</div>
</div>
</div>
{/* New Facility Form */}
{showNewFacility && (
<div className="bg-[#1A1A1F] rounded-lg border border-[#2A2A32] p-6 mb-8">
<div className="flex items-center justify-between mb-6">
<h3 className="text-lg font-semibold text-[#F0F0F3]">New Debt Facility</h3>
<button
onClick={() => setShowNewFacility(false)}
className="text-[#5A5A6E] hover:text-[#8B8B9E] text-2xl font-light"
>
×
</button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
<div>
<label className="block text-sm font-medium text-[#8B8B9E] mb-1">Facility Name *</label>
<input
type="text"
value={newFacilityForm.name}
onChange={(e) => setNewFacilityForm({ ...newFacilityForm, name: e.target.value })}
className="w-full px-3 py-2 border border-[#3A3A45] rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="e.g., Tech Bank Credit Line"
/>
</div>
<div>
<label className="block text-sm font-medium text-[#8B8B9E] mb-1">Lender *</label>
<input
type="text"
value={newFacilityForm.lender}
onChange={(e) => setNewFacilityForm({ ...newFacilityForm, lender: e.target.value })}
className="w-full px-3 py-2 border border-[#3A3A45] rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="e.g., JP Morgan Chase"
/>
</div>
<div>
<label className="block text-sm font-medium text-[#8B8B9E] mb-1">Type *</label>
<select
value={newFacilityForm.type}
onChange={(e) => setNewFacilityForm({ ...newFacilityForm, type: e.target.value as any })}
className="w-full px-3 py-2 border border-[#3A3A45] rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="Revolving Credit">Revolving Credit</option>
<option value="Term Loan">Term Loan</option>
<option value="Equipment Financing">Equipment Financing</option>
<option value="Line of Credit">Line of Credit</option>
<option value="Other">Other</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-[#8B8B9E] mb-1">Commitment Amount ($) *</label>
<input
type="number"
value={newFacilityForm.commitmentAmount}
onChange={(e) => setNewFacilityForm({ ...newFacilityForm, commitmentAmount: e.target.value })}
className="w-full px-3 py-2 border border-[#3A3A45] rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="0"
/>
</div>
<div>
<label className="block text-sm font-medium text-[#8B8B9E] mb-1">Interest Rate *</label>
<input
type="text"
value={newFacilityForm.interestRate}
onChange={(e) => setNewFacilityForm({ ...newFacilityForm, interestRate: e.target.value })}
className="w-full px-3 py-2 border border-[#3A3A45] rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="e.g., 5.5% or SOFR+200bps"
/>
</div>
<div>
<label className="block text-sm font-medium text-[#8B8B9E] mb-1">Maturity Date *</label>
<input
type="date"
value={newFacilityForm.maturityDate}
onChange={(e) => setNewFacilityForm({ ...newFacilityForm, maturityDate: e.target.value })}
className="w-full px-3 py-2 border border-[#3A3A45] rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
</div>
</div>
<div className="flex gap-3 justify-end">
<button
onClick={() => setShowNewFacility(false)}
className="px-4 py-2 text-[#8B8B9E] border border-[#3A3A45] rounded-lg hover:bg-[#111114] transition-colors font-medium"
>
Cancel
</button>
<button
onClick={handleAddFacility}
disabled={loading}
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-medium disabled:opacity-50 disabled:cursor-not-allowed"
>
{loading ? 'Saving...' : 'Save Facility'}
</button>
</div>
</div>
)}
{/* Record Draw Form */}
{showRecordDraw && (
<div className="bg-[#1A1A1F] rounded-lg border border-[#2A2A32] p-6 mb-8">
<div className="flex items-center justify-between mb-6">
<h3 className="text-lg font-semibold text-[#F0F0F3]">Record Draw</h3>
<button
onClick={() => setShowRecordDraw(false)}
className="text-[#5A5A6E] hover:text-[#8B8B9E] text-2xl font-light"
>
×
</button>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
<div>
<label className="block text-sm font-medium text-[#8B8B9E] mb-1">Facility *</label>
<select
value={newDrawForm.facilityId}
onChange={(e) => {
const facilityId = e.target.value;
const facility = facilities.find((f) => f.id === facilityId);
setNewDrawForm({
...newDrawForm,
facilityId,
interestRate: facility?.interestRate || '',
});
}}
className="w-full px-3 py-2 border border-[#3A3A45] rounded-lg focus:outline-none focus:ring-2 focus:ring-green-500"
>
<option value="">Select a facility...</option>
{facilities.map((f) => (
<option key={f.id} value={f.id}>
{f.name} - Available: {formatCurrency(f.availableAmount)}
</option>
))}
</select>
</div>
<div>
<label className="block text-sm font-medium text-[#8B8B9E] mb-1">Draw Amount ($) *</label>
<input
type="number"
value={newDrawForm.amount}
onChange={(e) => setNewDrawForm({ ...newDrawForm, amount: e.target.value })}
className="w-full px-3 py-2 border border-[#3A3A45] rounded-lg focus:outline-none focus:ring-2 focus:ring-green-500"
placeholder="0"
/>
</div>
<div>
<label className="block text-sm font-medium text-[#8B8B9E] mb-1">Draw Date *</label>
<input
type="date"
value={newDrawForm.date}
onChange={(e) => setNewDrawForm({ ...newDrawForm, date: e.target.value })}
className="w-full px-3 py-2 border border-[#3A3A45] rounded-lg focus:outline-none focus:ring-2 focus:ring-green-500"
/>
</div>
</div>
<div className="flex gap-3 justify-end">
<button
onClick={() => setShowRecordDraw(false)}
className="px-4 py-2 text-[#8B8B9E] border border-[#3A3A45] rounded-lg hover:bg-[#111114] transition-colors font-medium"
>
Cancel
</button>
<button
onClick={handleRecordDraw}
disabled={loading}
className="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors font-medium disabled:opacity-50 disabled:cursor-not-allowed"
>
{loading ? 'Recording...' : 'Record Draw'}
</button>
</div>
</div>
)}
{/* Tabs */}
<div className="bg-[#1A1A1F] rounded-lg border border-[#2A2A32] overflow-hidden">
<div className="border-b border-[#2A2A32]">
<div className="flex">
{[
{ id: 'facilities', label: 'Debt Facilities' },
{ id: 'draws', label: 'Active Draws' },
{ id: 'covenants', label: 'Covenant Compliance' },
].map((tab) => (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
className={`px-6 py-4 font-medium whitespace-nowrap transition-colors ${
activeTab === tab.id
? 'text-blue-600 border-b-2 border-blue-600'
: 'text-[#8B8B9E] hover:text-[#F0F0F3]'
}`}
>
{tab.label}
</button>
))}
</div>
</div>
{/* Tab Content */}
<div className="p-8">
{/* Facilities Tab */}
{activeTab === 'facilities' && (
<div>
<h2 className="text-2xl font-bold text-[#F0F0F3] mb-6">Debt Facilities</h2>
<div className="space-y-4">
{facilities.map((facility) => (
<div
key={facility.id}
className="border border-[#2A2A32] rounded-lg overflow-hidden hover:shadow-md transition-shadow"
>
<div
className="bg-[#111114] p-4 cursor-pointer hover:bg-[#1A1A1F] transition-colors"
onClick={() =>
setExpandedFacilityId(
expandedFacilityId === facility.id ? null : facility.id
)
}
>
<div className="flex items-center justify-between">
<div className="flex items-center gap-4 flex-1">
{expandedFacilityId === facility.id ? (
<ChevronUp size={20} className="text-[#5A5A6E]" />
) : (
<ChevronDown size={20} className="text-[#5A5A6E]" />
)}
<div className="flex-1">
<h3 className="text-lg font-semibold text-[#F0F0F3]">{facility.name}</h3>
<p className="text-sm text-[#8B8B9E]">{facility.lender} {facility.type}</p>
</div>
</div>
<div className="flex gap-8 text-right">
<div>
<p className="text-xs text-[#8B8B9E]">Drawn Amount</p>
<p className="text-lg font-bold text-[#F0F0F3]">
{formatCurrency(facility.drawnAmount)}
</p>
</div>
<div>
<p className="text-xs text-[#8B8B9E]">Available</p>
<p className="text-lg font-bold text-green-600">
{formatCurrency(facility.availableAmount)}
</p>
</div>
<div>
<p className="text-xs text-[#8B8B9E]">Rate</p>
<p className="text-lg font-bold text-[#F0F0F3]">{facility.interestRate}</p>
</div>
<div>
<p className="text-xs text-[#8B8B9E]">Maturity</p>
<p className="text-lg font-bold text-[#F0F0F3]">{formatDate(facility.maturityDate)}</p>
</div>
<div>
<span className="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-green-900/25 text-green-800">
{facility.status}
</span>
</div>
</div>
</div>
</div>
{/* Expanded Details */}
{expandedFacilityId === facility.id && (
<div className="border-t border-[#2A2A32] p-4 bg-[#1A1A1F]">
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
<div>
<p className="text-sm font-medium text-[#8B8B9E]">Commitment Amount</p>
<p className="text-2xl font-bold text-[#F0F0F3] mt-1">
{formatCurrency(facility.commitmentAmount)}
</p>
</div>
<div>
<p className="text-sm font-medium text-[#8B8B9E]">Drawn</p>
<p className="text-2xl font-bold text-[#F0F0F3] mt-1">
{((facility.drawnAmount / facility.commitmentAmount) * 100).toFixed(1)}%
</p>
</div>
<div>
<p className="text-sm font-medium text-[#8B8B9E]">Available Capacity</p>
<p className="text-2xl font-bold text-green-600 mt-1">
{((facility.availableAmount / facility.commitmentAmount) * 100).toFixed(1)}%
</p>
</div>
</div>
{facility.draws.length > 0 && (
<div>
<h4 className="text-sm font-semibold text-[#F0F0F3] mb-3">Draws on This Facility</h4>
<div className="space-y-2">
{facility.draws.map((draw) => (
<div
key={draw.id}
className="flex items-center justify-between p-3 bg-[#111114] rounded border border-[#2A2A32]"
>
<div>
<p className="text-sm font-medium text-[#F0F0F3]">{formatDate(draw.drawDate)}</p>
<p className="text-xs text-[#8B8B9E]">{draw.interestRate}</p>
</div>
<div className="text-right">
<p className="text-sm font-bold text-[#F0F0F3]">{formatCurrency(draw.amount)}</p>
<span
className={`inline-block text-xs font-semibold px-2 py-1 rounded mt-1 ${
draw.status === 'Active'
? 'bg-blue-900/25 text-blue-800'
: draw.status === 'Repaid'
? 'bg-green-900/25 text-green-800'
: 'bg-orange-900/25 text-orange-800'
}`}
>
{draw.status}
</span>
</div>
</div>
))}
</div>
</div>
)}
</div>
)}
</div>
))}
</div>
</div>
)}
{/* Draws Tab */}
{activeTab === 'draws' && (
<div>
<h2 className="text-2xl font-bold text-[#F0F0F3] mb-6">Active Draws</h2>
{draws.length === 0 ? (
<div className="text-center py-12">
<p className="text-[#8B8B9E]">No active draws. Record your first draw using the button at the top.</p>
</div>
) : (
<div className="overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="border-b border-[#3A3A45] bg-[#111114]">
<th className="px-4 py-3 text-left font-semibold text-[#8B8B9E]">Facility</th>
<th className="px-4 py-3 text-left font-semibold text-[#8B8B9E]">Draw Date</th>
<th className="px-4 py-3 text-right font-semibold text-[#8B8B9E]">Amount</th>
<th className="px-4 py-3 text-left font-semibold text-[#8B8B9E]">Interest Rate</th>
<th className="px-4 py-3 text-left font-semibold text-[#8B8B9E]">Status</th>
</tr>
</thead>
<tbody className="divide-y divide-[#2A2A32]">
{draws.map((draw) => {
const facility = facilities.find((f) => f.id === draw.facilityId);
return (
<tr key={draw.id} className="hover:bg-[#111114] transition-colors">
<td className="px-4 py-3 font-medium text-[#F0F0F3]">{facility?.name}</td>
<td className="px-4 py-3 text-[#8B8B9E]">{formatDate(draw.drawDate)}</td>
<td className="px-4 py-3 text-right font-medium">{formatCurrency(draw.amount)}</td>
<td className="px-4 py-3 text-[#8B8B9E]">{draw.interestRate}</td>
<td className="px-4 py-3">
<span
className={`inline-block px-3 py-1 rounded text-xs font-semibold ${
draw.status === 'Active'
? 'bg-blue-900/25 text-blue-800'
: draw.status === 'Repaid'
? 'bg-green-900/25 text-green-800'
: 'bg-orange-900/25 text-orange-800'
}`}
>
{draw.status}
</span>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
)}
</div>
)}
{/* Covenants Tab */}
{activeTab === 'covenants' && (
<div>
<h2 className="text-2xl font-bold text-[#F0F0F3] mb-6">Covenant Compliance Dashboard</h2>
<div className="space-y-4">
{covenants.map((covenant) => (
<div
key={covenant.id}
className={`border rounded-lg p-4 hover:shadow-md transition-shadow ${getCovenanStatusColor(
covenant.status
)}`}
>
<div className="flex items-start justify-between mb-4">
<div>
<div className="flex items-center gap-2 mb-1">
{getCovenanStatusIcon(covenant.status)}
<p className="text-sm font-semibold text-[#F0F0F3]">{covenant.name}</p>
</div>
<p className="text-xs text-[#8B8B9E] mt-1">{covenant.type} Covenant</p>
</div>
<span
className={`px-3 py-1 rounded-full text-xs font-semibold flex items-center gap-1 ${getCovenanStatusColor(
covenant.status
)}`}
>
{covenant.status}
</span>
</div>
<div className="grid grid-cols-4 gap-4 text-sm">
<div>
<p className="text-[#8B8B9E] font-medium">Metric</p>
<p className="font-semibold text-[#F0F0F3] mt-1">{covenant.metric}</p>
</div>
<div>
<p className="text-[#8B8B9E] font-medium">Threshold</p>
<p className="font-semibold text-[#F0F0F3] mt-1">{covenant.threshold}</p>
</div>
<div>
<p className="text-[#8B8B9E] font-medium">Current Value</p>
<p className="font-semibold text-[#F0F0F3] mt-1">{covenant.currentValue}</p>
</div>
<div>
<p className="text-[#8B8B9E] font-medium">Headroom</p>
<p className="font-semibold text-[#F0F0F3] mt-1">{covenant.headroom}</p>
</div>
</div>
<p className="text-xs text-[#8B8B9E] mt-3">
Last checked: {formatDate(covenant.lastChecked)}
</p>
</div>
))}
</div>
</div>
)}
</div>
</div>
</div>
</div>
);
}