import React, { useState, useEffect } from 'react';
import Toast from '../Components/Toast';
import {
ChevronLeft,
Edit2,
TrendingUp,
Calendar,
MapPin,
Building,
Wallet,
FileText,
Users,
Eye,
Percent,
Clock,
Shield,
CheckCircle2,
AlertCircle,
X,
ArrowRight,
Download
} from 'lucide-react';
export default function InvestorView({ id }) {
const isReceptionist = window.__APP_DATA__?.role === 'receptionist';
const basePath = isReceptionist ? '/receptionist/investors' : '/owner/investors';
const [investor, setInvestor] = useState(null);
const [payouts, setPayouts] = useState([]);
const [roiStatus, setRoiStatus] = useState([]);
const [loading, setLoading] = useState(true);
const [toast, setToast] = useState(null);
const [activeTab, setActiveTab] = useState('Overview');
const [isPreviewOpen, setIsPreviewOpen] = useState(false);
const [settleModal, setSettleModal] = useState({
isOpen: false,
month: '',
amount: '',
originalAmount: '',
baseAmount: 0,
carryOver: 0,
date: new Date().toISOString().split('T')[0],
method: 'Bank Transfer',
remarks: ''
});
useEffect(() => {
fetchInvestor();
fetchPayouts();
fetchROIStatus();
}, [id]);
const fetchPayouts = async () => {
try {
const response = await fetch(`/api/investors/${id}/payouts`);
const data = await response.json();
setPayouts(data);
} catch (error) {
console.error('Error fetching payouts:', error);
}
};
const fetchROIStatus = async () => {
try {
const response = await fetch(`/api/investors/${id}/roi-status`);
const data = await response.json();
setRoiStatus(data);
} catch (error) {
console.error('Error fetching ROI status:', error);
}
};
const fetchInvestor = async () => {
try {
const response = await fetch(`/api/investors/${id}`);
const data = await response.json();
setInvestor(data);
} catch (error) {
console.error('Error fetching investor:', error);
setToast({ message: 'Failed to load investor details.', type: 'error' });
} finally {
setLoading(false);
}
};
const handleSettleROI = async (e) => {
e.preventDefault();
// Validation: Remarks mandatory if amount is adjusted
if (parseFloat(settleModal.amount) !== parseFloat(settleModal.originalAmount) && !settleModal.remarks?.trim()) {
setToast({ message: 'Remarks field is mandatory when adjusting the payment amount.', type: 'error' });
return;
}
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
try {
const response = await fetch(`/api/investors/${id}/settle-roi`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken
},
body: JSON.stringify({
payout_month: settleModal.month,
amount: settleModal.amount,
payout_date: settleModal.date,
payment_method: settleModal.method,
remarks: settleModal.remarks
})
});
if (response.ok) {
setToast({ message: 'ROI settled successfully!', type: 'success' });
setSettleModal({
isOpen: false,
month: '',
amount: '',
originalAmount: '',
date: new Date().toISOString().split('T')[0],
method: 'Bank Transfer',
remarks: ''
});
fetchPayouts();
fetchROIStatus();
} else {
setToast({ message: 'Settlement failed.', type: 'error' });
}
} catch (error) {
setToast({ message: 'Error during settlement.', type: 'error' });
}
};
if (loading) return (
);
if (!investor) return (
Investor Not Found
);
const initials = investor.name?.split(' ').map(n => n[0]).join('').toUpperCase() || 'INV';
const totalPayouts = payouts.reduce((acc, p) => acc + parseFloat(p.amount || 0), 0);
return (
<>
{toast && setToast(null)} />}
{/* Navigation & Actions */}
{/* Profile Identity Card */}
{initials}
{investor.name}
Active Investor
{investor.applicable_to_all_branches ? "Global Portfolio" : `${investor.branches?.length || 0} Branches`}
Since {new Date(investor.investment_date).toLocaleDateString()}
Total Capital
{parseFloat(investor.investment_amount).toLocaleString()} AED
ROI Yielded
{totalPayouts.toLocaleString()} AED
{/* Tabs & Content */}
{['Overview', 'ROI Payouts', 'Monthly Status'].map(tab => (
))}
{activeTab === 'Overview' && (
{investor.roi_type === 'Percentage' ? 'ROI Interest' : 'Fixed ROI'}
{investor.roi_value}
{investor.roi_type === 'Percentage' ? '%' : ' AED'}
PER {investor.roi_period || 'MONTH'}
Strategic Allocation
{investor.applicable_to_all_branches ? (
Organization Wide Equity
) : (
investor.branches?.map(branch => (
{branch.name}
))
)}
{investor.security_proof_document ? (
setIsPreviewOpen(true)}>
Security Proof
Click to View
) : (
)}
)}
{activeTab === 'ROI Payouts' && (
Distribution History
Total ROI Settled: {totalPayouts.toLocaleString()} AED
| Period |
Amount (AED) |
Payment Date |
Method |
Status |
{payouts.length > 0 ? (
payouts.map(p => (
| {p.payout_month} |
{(parseFloat(p.amount) || 0).toLocaleString()} AED |
{new Date(p.payout_date).toLocaleDateString(undefined, { day: '2-digit', month: 'short', year: 'numeric' })} |
{p.payment_method} |
{p.status || 'Paid'}
|
))
) : (
No ROI distributions recorded
|
)}
)}
{activeTab === 'Monthly Status' && (
Settlement Tracking
Unpaid ROI Periods since Investment
| ROI Period |
Breakdown |
Net Due |
Status |
Action |
{roiStatus.filter(s => s.status === 'Pending' || s.status === 'Partial').length > 0 ? (
roiStatus.filter(s => s.status === 'Pending' || s.status === 'Partial').map((s, idx) => (
| {s.month} |
Base ROI: {(parseFloat(s.base_amount) || 0).toLocaleString()} AED
{parseFloat(s.carry_from_previous) !== 0 && (
0 ? 'text-amber-500' : 'text-emerald-500'}`}>
Carry Over: {parseFloat(s.carry_from_previous) > 0 ? '+' : ''}{parseFloat(s.carry_from_previous).toLocaleString()} AED
)}
{s.paid > 0 && (
Allocated: -{(parseFloat(s.paid) || 0).toLocaleString()} AED
)}
|
{(parseFloat(s.amount) || 0).toLocaleString()} AED |
{s.status === 'Pending' ? (
Pending
) : (
Partially Paid
)}
|
{s.can_settle ? (
) : (
)}
|
))
) : (
All ROI Distributions Up to Date
|
)}
)}
{/* Document Preview Modal */}
{isPreviewOpen && (
{investor.security_proof_document.toLowerCase().endsWith('.pdf') ? (
) : (

)}
)}
{/* Settle ROI Modal */}
{settleModal.isOpen && (
ROI Settlement
Distributing ROI for {settleModal.month}
)}
>
);
}