'use client'; import { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; import AdminLayout from '../../components/AdminLayout'; import { getUsers } from '../../lib/api'; export default function UsersPage() { const router = useRouter(); const [users, setUsers] = useState([]); const [search, setSearch] = useState(''); const [filter, setFilter] = useState('all'); const [loading, setLoading] = useState(true); const [expandedUser, setExpandedUser] = useState(null); useEffect(() => { loadUsers(); }, []); const loadUsers = async () => { try { const data = await getUsers(); setUsers(data.users || []); } catch (err) { console.error('Failed to load users:', err); } finally { setLoading(false); } }; const filteredUsers = users.filter((user) => { // Search filter if (search) { const s = search.toLowerCase(); const matchesSearch = user.email?.toLowerCase().includes(s) || user.first_name?.toLowerCase().includes(s) || user.last_name?.toLowerCase().includes(s); if (!matchesSearch) return false; } // Type filter if (filter === 'beneficiaries') return user.is_beneficiary; if (filter === 'caretakers') return user.is_caretaker; if (filter === 'admins') return user.role === 'admin'; return true; }); const stats = { total: users.length, beneficiaries: users.filter(u => u.is_beneficiary).length, caretakers: users.filter(u => u.is_caretaker).length, admins: users.filter(u => u.role === 'admin').length, }; return (

Users

setSearch(e.target.value)} style={styles.search} />
{/* Stats */}
{loading ? (

Loading...

) : filteredUsers.length === 0 ? (

No users found

) : (
{filteredUsers.map((user) => ( setExpandedUser(expandedUser === user.id ? null : user.id)} onView={() => router.push(`/users/${user.id}`)} /> ))}
)}
); } function StatCard({ label, value, icon, color = '#3B82F6' }) { return (
{icon}
{value}
{label}
); } function UserCard({ user, expanded, onToggle, onView }) { const userName = user.first_name || user.last_name ? `${user.first_name || ''} ${user.last_name || ''}`.trim() : 'Unnamed User'; const hasRelationships = (user.watches?.length > 0) || (user.watched_by?.length > 0); return (
{userName}
{user.email}
{user.phone &&
{user.phone}
}
{user.role === 'admin' && } {user.is_beneficiary && } {user.is_caretaker && }
Joined {new Date(user.created_at).toLocaleDateString()} {hasRelationships && ( {expanded ? '▼' : '▶'} )}
{expanded && hasRelationships && (
{user.watched_by?.length > 0 && (
👀 Watched by:
{user.watched_by.map((rel, idx) => (
{rel.accessor_email}
))}
)} {user.watches?.length > 0 && (
🔍 Watches:
{user.watches.map((rel, idx) => (
{rel.beneficiary_email}
))}
)}
)}
); } function Badge({ text, color }) { return ( {text} ); } function RoleBadge({ role }) { const colors = { owner: '#EF4444', caretaker: '#6366F1', installer: '#8B5CF6', }; const color = colors[role] || '#6B7280'; return ( {role} ); } const styles = { header: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '24px', flexWrap: 'wrap', gap: '16px', }, title: { fontSize: '24px', fontWeight: '600', }, controls: { display: 'flex', gap: '12px', alignItems: 'center', }, filterSelect: { padding: '10px 16px', fontSize: '14px', border: '1px solid var(--border)', borderRadius: '8px', background: 'white', cursor: 'pointer', outline: 'none', }, search: { padding: '10px 16px', fontSize: '14px', border: '1px solid var(--border)', borderRadius: '8px', width: '240px', outline: 'none', }, statsGrid: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: '16px', marginBottom: '24px', }, statCard: { background: 'white', borderRadius: '12px', padding: '20px', display: 'flex', alignItems: 'center', gap: '16px', }, statIcon: { fontSize: '28px', }, statInfo: { flex: 1, }, statValue: { fontSize: '28px', fontWeight: '700', }, statLabel: { fontSize: '13px', color: 'var(--text-muted)', }, loading: { color: 'var(--text-muted)', textAlign: 'center', padding: '48px', }, empty: { background: 'white', borderRadius: '12px', padding: '48px', textAlign: 'center', color: 'var(--text-muted)', }, userList: { display: 'flex', flexDirection: 'column', gap: '12px', }, userCard: { background: 'white', borderRadius: '12px', overflow: 'hidden', }, userMain: { display: 'grid', gridTemplateColumns: '1fr auto auto', gap: '20px', padding: '20px', alignItems: 'center', cursor: 'pointer', }, userInfo: { minWidth: 0, }, userName: { fontSize: '15px', fontWeight: '600', marginBottom: '4px', }, userEmail: { fontSize: '14px', color: 'var(--text-secondary)', }, userPhone: { fontSize: '13px', color: 'var(--text-muted)', marginTop: '2px', }, badges: { display: 'flex', gap: '8px', flexWrap: 'wrap', }, userMeta: { display: 'flex', alignItems: 'center', gap: '12px', color: 'var(--text-muted)', }, date: { fontSize: '13px', }, expandIcon: { fontSize: '12px', color: 'var(--text-muted)', cursor: 'pointer', }, viewBtn: { padding: '6px 12px', background: 'var(--primary)', color: 'white', border: 'none', borderRadius: '6px', fontSize: '12px', cursor: 'pointer', }, relationships: { background: 'var(--surface)', padding: '16px 20px', borderTop: '1px solid var(--border)', }, relationSection: { marginBottom: '12px', }, relationTitle: { fontSize: '12px', fontWeight: '600', color: 'var(--text-muted)', marginBottom: '8px', }, relationList: { display: 'flex', flexDirection: 'column', gap: '6px', }, relationItem: { display: 'flex', alignItems: 'center', gap: '10px', fontSize: '13px', }, relationEmail: { color: 'var(--text-secondary)', }, };