import { apiFetch } from '../api'; import { useState, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { UserPlus, Search, Trash2, Shield, Mail, Lock, Check, X, LayoutGrid, Receipt, Users, ShoppingBag, ShoppingCart, Wallet, BarChart3, Table2, CreditCard, Megaphone, MessageSquare, Store } from 'lucide-react'; interface Manager { id: string; name: string; email: string; role: string; sections: string[]; status: 'active' | 'inactive'; } const ALL_SECTIONS = [ { id: 'dashboard', label: 'Dashboard', icon: LayoutGrid }, { id: 'sale', label: 'Sale', icon: Receipt }, { id: 'customers', label: 'Customers', icon: Users }, { id: 'purchases', label: 'Purchases', icon: ShoppingBag }, { id: 'inventory', label: 'Inventory', icon: ShoppingCart }, { id: 'expense', label: 'Expense', icon: Wallet }, { id: 'reports', label: 'Reports', icon: BarChart3 }, { id: 'table', label: 'Table Management', icon: Table2 }, { id: 'wallet', label: 'Wallet', icon: CreditCard }, { id: 'promotions', label: 'Promotions', icon: Megaphone }, { id: 'feedback', label: 'Feedback', icon: MessageSquare }, { id: 'stores', label: 'Stores', icon: Store } ]; const Managers = () => { const [managers, setManagers] = useState([]); const [isModalOpen, setIsModalOpen] = useState(false); const [searchQuery, setSearchQuery] = useState(''); const [loading, setLoading] = useState(true); // Form State const [formData, setFormData] = useState({ name: '', email: '', password: '', viewOnly: false, selectedSections: [] as string[] }); // Fetch from Backend const fetchManagers = async () => { setLoading(true); try { const res = await apiFetch('/api/system/managers'); if (res.ok) { const data = await res.json(); // Backend uses 'permissions' field, map it to 'sections' for the component if needed const mappedData = data.map((m: any) => ({ ...m, sections: m.permissions || [] })); setManagers(mappedData); } } catch (err) { console.error('Error fetching managers:', err); } finally { setLoading(false); } }; useEffect(() => { fetchManagers(); }, []); const toggleSection = (sectionId: string) => { setFormData(prev => ({ ...prev, selectedSections: prev.selectedSections.includes(sectionId) ? prev.selectedSections.filter(id => id !== sectionId) : [...prev.selectedSections, sectionId] })); }; const handleCreateAccount = async (e: React.FormEvent) => { e.preventDefault(); try { const response = await apiFetch('/api/system/managers', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: formData.name, email: formData.email, password: formData.password, viewOnly: formData.viewOnly, permissions: formData.selectedSections }) }); if (response.ok) { fetchManagers(); setIsModalOpen(false); setFormData({ name: '', email: '', password: '', viewOnly: false, selectedSections: [] }); } else { alert('Failed to create manager'); } } catch (err) { console.error('Create manager error:', err); alert('Network error - make sure backend is running'); } }; const dismissManager = async (id: string) => { if (window.confirm('Are you sure you want to dismiss this manager?')) { try { const response = await apiFetch(`/api/system/managers/${id}`, { method: 'DELETE' }); if (response.ok) { fetchManagers(); } } catch (err) { console.error('Delete error:', err); } } }; return (

Managers

Manage portal access and role assignments

{/* Search & Stats */}
setSearchQuery(e.target.value)} className="w-full h-14 bg-white border border-[#e2e8f0] rounded-2xl pl-14 pr-4 text-sm font-semibold outline-none transition-all focus:border-[#001828]/30 focus:shadow-md shadow-sm text-[#1e293b] placeholder:text-[#94a3b8]" />

Active Managers

{managers.length}

{/* Managers List */}
{managers.filter(m => { const query = (searchQuery || '').toLowerCase(); return (m.name || '').toLowerCase().includes(query) || (m.email || '').toLowerCase().includes(query); }).map((manager) => ( ))}
Manager Role Permissions Status
{manager.name.charAt(0)}

{manager.name}

{manager.email}

{manager.role}
{manager.sections.map(s => ( {s} ))}
Active
{/* Create Account Modal */} {isModalOpen && (
setIsModalOpen(false)} className="absolute inset-0 bg-[#1e293b]/60 backdrop-blur-sm" />

Create manager account for Tillo Canteen

setFormData({...formData, name: e.target.value})} placeholder="e.g. Main Desk" className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#001828] rounded-2xl py-3 pl-4 pr-4 text-sm font-semibold outline-none transition-all" />
setFormData({...formData, email: e.target.value})} placeholder="manager@tillo.com" className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#001828] rounded-2xl py-3 pl-11 pr-4 text-sm font-semibold outline-none transition-all" />
setFormData({...formData, password: e.target.value})} placeholder="••••••••" className="w-full bg-white border-2 border-[#e2e8f0] focus:border-[#001828] rounded-2xl py-3 pl-11 pr-4 text-sm font-semibold outline-none transition-all" />
setFormData({...formData, viewOnly: !formData.viewOnly})} className={cn( "w-5 h-5 rounded border-2 flex items-center justify-center cursor-pointer transition-all", formData.viewOnly ? "bg-[#001828] border-[#001828]" : "border-[#e2e8f0]" )} > {formData.viewOnly && }
View only access
{/* Sections Selection */}
{ALL_SECTIONS.map((section) => (
toggleSection(section.id)} className={cn( "flex flex-col items-center justify-center p-4 rounded-2xl border-2 cursor-pointer transition-all gap-2", formData.selectedSections.includes(section.id) ? "bg-[#001828]/5 border-[#001828] text-[#001828]" : "bg-white border-[#e2e8f0] text-[#94a3b8] hover:border-[#001828]/30" )} > {section.label}
))}
)}
); }; // Helper for class names function cn(...inputs: any[]) { return inputs.filter(Boolean).join(' '); } export default Managers;