import React, { useState, useEffect } from 'react'; import Toast from '../Components/Toast'; import { ChevronLeft, Edit2, Mail, Phone, Shield, Calendar, MapPin, Building, Plus, Minus, Wallet, FileText, Users, Bell, Eye, Save, X, Clock, Heart } from 'lucide-react'; export default function StaffView({ id }) { const isReceptionist = window.__APP_DATA__?.role === 'receptionist'; const basePath = isReceptionist ? '/receptionist' : '/owner'; const [staff, setStaff] = useState(null); const [payments, setPayments] = useState([]); const [loading, setLoading] = useState(true); const [history, setHistory] = useState([]); const [showHistory, setShowHistory] = useState(false); const [loadingHistory, setLoadingHistory] = useState(false); const [toast, setToast] = useState(null); const [isPaymentModalOpen, setIsPaymentModalOpen] = useState(false); const [newPayment, setNewPayment] = useState({ amount: '', payment_date: new Date().toISOString().split('T')[0], payment_type: 'Salary', status: 'Paid', remarks: '' }); const [personCount, setPersonCount] = useState(1); // For commission mockup const [isSettleModalOpen, setIsSettleModalOpen] = useState(false); const [settlementData, setSettlementData] = useState(null); const [settling, setSettling] = useState(false); const [payrollStatus, setPayrollStatus] = useState([]); const [loadingPayroll, setLoadingPayroll] = useState(false); const [advanceHistory, setAdvanceHistory] = useState([]); const [loadingAdvanceHistory, setLoadingAdvanceHistory] = useState(false); const [isAdvanceHistoryModalOpen, setIsAdvanceHistoryModalOpen] = useState(false); const [isPaymentHistoryModalOpen, setIsPaymentHistoryModalOpen] = useState(false); useEffect(() => { fetchStaff(); fetchPayments(); fetchPayrollStatus(); fetchAdvanceHistory(); }, [id]); const fetchPayments = async () => { try { const response = await fetch(`/api/staff/${id}/payments`); const data = await response.json(); setPayments(data); } catch (error) { console.error('Error fetching payments:', error); } }; const handleAddPayment = async (e) => { e.preventDefault(); const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'); try { const response = await fetch(`/api/staff/${id}/payments`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken }, body: JSON.stringify(newPayment) }); if (response.ok) { setToast({ message: 'Payment recorded successfully!', type: 'success' }); setIsPaymentModalOpen(false); fetchPayments(); setNewPayment({ amount: '', payment_date: new Date().toISOString().split('T')[0], payment_type: 'Salary', status: 'Paid', remarks: '' }); } } catch (error) { setToast({ message: 'Failed to record payment.', type: 'error' }); } }; const fetchStaff = async () => { try { const response = await fetch(`/api/staff/${id}`); const data = await response.json(); setStaff(data); } catch (error) { console.error('Error fetching staff:', error); setToast({ message: 'Failed to load staff details.', type: 'error' }); } finally { setLoading(false); } }; const handleToggleStatus = async () => { const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'); const newStatus = staff.status === 'Active' ? 'Inactive' : 'Active'; try { const response = await fetch(`/api/staff/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken }, body: JSON.stringify({ ...staff, status: newStatus }) }); if (response.ok) { setStaff({ ...staff, status: newStatus }); setToast({ message: `Staff marked as ${newStatus}`, type: 'success' }); } } catch (error) { setToast({ message: 'Failed to update status.', type: 'error' }); } }; const fetchHistory = async () => { setLoadingHistory(true); setShowHistory(true); try { const res = await fetch(`/api/staff/${id}/commission-history`); const data = await res.json(); setHistory(data); } catch (error) { console.error('Error fetching history:', error); } finally { setLoadingHistory(false); } }; const fetchPayrollStatus = async () => { setLoadingPayroll(true); try { const res = await fetch(`/api/staff/${id}/payroll-status`); const data = await res.json(); setPayrollStatus(data); } catch (error) { console.error('Error fetching payroll status:', error); } finally { setLoadingPayroll(false); } }; const fetchAdvanceHistory = async () => { setLoadingAdvanceHistory(true); try { const res = await fetch(`/api/staff/${id}/advance-history`); const data = await res.json(); setAdvanceHistory(data); } catch (error) { console.error('Error fetching advance history:', error); } finally { setLoadingAdvanceHistory(false); } }; const fetchSettlement = async (monthKey = null) => { try { const url = monthKey ? `/api/staff/${id}/settlement?month=${monthKey}` : `/api/staff/${id}/settlement`; const res = await fetch(url); const data = await res.json(); if (data.can_settle === false) { setToast({ message: data.message, type: 'info' }); return; } setSettlementData(data); setIsSettleModalOpen(true); } catch (error) { setToast({ message: 'Failed to fetch settlement details.', type: 'error' }); } }; const handleSettle = async () => { setSettling(true); const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'); try { const res = await fetch(`/api/staff/${id}/settle`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken }, body: JSON.stringify({ settlement_month: settlementData.settlement_month }) }); if (res.ok) { setToast({ message: 'Salary settled successfully!', type: 'success' }); setIsSettleModalOpen(false); fetchStaff(); fetchPayments(); fetchPayrollStatus(); } else { const err = await res.json(); setToast({ message: err.message || 'Failed to settle salary.', type: 'error' }); } } catch (error) { setToast({ message: 'Failed to settle salary.', type: 'error' }); } finally { setSettling(false); } }; const handleGetAdvance = async () => { // Redirect to edit with advance enabled or just update here window.location.href = `${basePath}/staff/edit/${id}?get_advance=true`; }; if (loading) return
Loading profile...
; if (!staff) return
Staff Member Not Found!
; const initials = staff.full_name?.split(' ').map(n => n[0]).join('').toUpperCase() || 'ST'; return ( <> {toast && setToast(null)} />}
{/* Back Link */} {/* Profile Header Card */}
{initials}

{staff.full_name}

{staff.status}
{staff.email}
{staff.phone || 'N/A'}
{staff.role || staff.designation || 'N/A'}
{/* Basic Details Card */}

Basic Details

Staff ID

{staff.staff_id_code || 'N/A'}

Name

{staff.full_name}

Contact Number

{staff.phone || 'N/A'}

Email

{staff.email}

Branch

{staff.branch?.name || 'UNDEF'}

Designation

{staff.role || staff.designation || 'N/A'}

Joining Date

{staff.joining_date || 'N/A'}

Status

{staff.status}
{/* Salary Details Section */}

Salary Details

{/* Current Salary Box */}

Current Salary

{(staff.salary_amount || 0).toLocaleString()} AED
Type: {staff.salary_type || 'Monthly'}
Cycle: {staff.salary_cycle || 'Monthly'}
{/* Advance Card */}

Salary Advance

{!staff.advance_enabled && ( )}
{(() => { const activeAdvance = advanceHistory.find(h => h.status === 'Pending'); if (activeAdvance) { return ( <>
{(parseFloat(activeAdvance.advance_amount) || 0).toLocaleString()} AED
Mode
{staff.advance_repayment_mode}
); } else { return (

No active advance

); } })()} {advanceHistory.length > 0 && (

Total Balance Due

{advanceHistory .filter(h => h.status === 'Pending') .reduce((sum, h) => sum + (parseFloat(h.advance_amount) - parseFloat(h.paid_amount || 0)), 0) .toLocaleString()} AED

Total Paid

{advanceHistory.reduce((sum, h) => sum + (parseFloat(h.paid_amount || 0)), 0).toLocaleString()} AED

)} {advanceHistory.length > 0 && (

Monthly Repayment Schedule

{advanceHistory.flatMap(h => h.installment_schedule || []).length > 3 && ( )}
{advanceHistory.flatMap(h => h.installment_schedule || []) .slice(0, 3) .map((item, idx) => (

{item.month}

AED {item.amount.toLocaleString()}

{item.status}
))}
)}
{/* Monthly Payroll Status Table */}

Monthly Payroll Status

Paid
Unpaid
{payrollStatus.length > 0 ? ( payrollStatus.map((p) => ( )) ) : ( )}
Month Status Net Amount Action
{p.month} {p.status} {p.amount ? `${parseFloat(p.amount).toLocaleString()} AED` : '-'} {p.can_settle ? ( ) : ( COMPLETED )}
No months yet to settle. Next settlement will be available after 1st of next month.
{/* Transaction History Table */}

Transaction History

{payments.length > 3 && ( )}
{payments.length > 0 ? ( payments.slice(0, 3).map((p) => ( )) ) : ( )}
Date Type Amount Status
{p.payment_date} {p.payment_type} {p.payment_type === 'Salary Settlement' && p.settlement_month && ( ({p.settlement_month}) )} {(parseFloat(p.amount) || 0).toLocaleString()} AED {p.status}
No transactions recorded yet.
{/* Member Commission Section */}

Member Commission

Amount Per Person

{staff.commission_amount || 0} AED

Total Monthly Estimate

{(staff.commission_amount * (staff.commission_member_count || 0)).toLocaleString()} AED

Active Member Count

{staff.commission_member_count || 0}

Updated Monthly

{/* Bottom Row: Docs, Family, Notifications */}
{/* Documentation Card */}

Documentation

VERIFIED
{staff.documents && staff.documents.length > 0 ? ( staff.documents.map((doc, index) => (

{doc.name}

{doc.document_number || 'No Number'}

Expiry: {doc.expiry_date || 'N/A'}

{doc.path && ( )}
)) ) : (

No documents

)}
{/* Family Members Card */}

Family Details

{staff.family_members && staff.family_members.length > 0 ? ( staff.family_members.map((member, index) => (

Family Member {index + 1}

{member.name}

{member.relation}
{member.contact}
)) ) : staff.family_member_name ? (

Emergency Contact

{staff.family_member_name}

{staff.family_member_relation}
{staff.family_member_contact}
) : (

Not Provided

)}
{/* Payment Modal */} {isPaymentModalOpen && (

Record Payment

Staff Transaction

setNewPayment({...newPayment, amount: e.target.value})} />
setNewPayment({...newPayment, payment_date: e.target.value})} />