import { FC, ReactElement, useState, useMemo, useCallback } from 'react'; import ModalUserDetail from './_components/modal-user-detail'; import { BackofficeWrapper, DataTable, } from '@imphnen-frontend-service/ui/organisms'; import { ColumnDef } from '@tanstack/react-table'; import { Button } from '@imphnen-frontend-service/ui/atoms'; import { cn } from '@imphnen-frontend-service/utils'; import { EditOutlined, UserOutlined, SearchOutlined, FilterOutlined, PlusOutlined, } from '@ant-design/icons'; // Removed unused SearchOutlined icon after schema revision // Define interface outside component interface UserType { id: string; // UUID avatar?: string; fullname: string; bio?: string; location: string; is_active: boolean; // admin can deactivate skills: string[]; // Frontend Developer, Backend Developer, etc. created_at: string; updated_at: string; } // Move mock data outside component to prevent recreation const skillsOptions = [ 'Frontend Developer', 'Backend Developer', 'Full Stack Developer', 'DevOps Engineer', 'UI/UX Designer', 'Product Manager', 'Data Scientist', 'Mobile Developer', ]; const locations = ['Jakarta', 'Bandung', 'Surabaya', 'Medan', 'Yogyakarta']; const bios = [ 'Passionate developer with 5+ years experience', 'Tech enthusiast and problem solver', 'Building scalable solutions for modern problems', 'Creative designer with technical background', 'Data-driven decision maker', ]; const mockData: UserType[] = Array.from({ length: 50 }, (_, i) => { const randomSkillsCount = Math.floor(Math.random() * 3) + 1; // 1-3 skills const randomSkills = skillsOptions .sort(() => 0.5 - Math.random()) .slice(0, randomSkillsCount); return { id: `24db9e4d-ca4c-46aa-ac36-8ef04bbe01${String(i).padStart(2, '0')}`, avatar: i % 4 === 0 ? `https://ui-avatars.com/api/?name=${encodeURIComponent( i % 3 === 0 ? 'Ahmad Wijuana' : 'Sofia Wijuana' )}&background=random` : undefined, fullname: i % 3 === 0 ? 'Ahmad Wijuana' : i % 3 === 1 ? 'Sofia Wijuana' : 'Budi Santoso', bio: i % 4 === 0 ? bios[i % bios.length] : undefined, location: locations[i % locations.length], is_active: i % 7 !== 0, // More realistic distribution skills: randomSkills, created_at: new Date( Date.now() - i * 86400000 * (Math.random() * 30 + 1) ).toISOString(), // Random within last 30-60 days updated_at: new Date().toISOString(), }; }); export const HackathonUsersPage: FC = (): ReactElement => { const [showDetailModal, setShowDetailModal] = useState(false); const [showNewUserModal, setShowNewUserModal] = useState(false); const [selectedUser, setSelectedUser] = useState(null); const [globalFilter, setGlobalFilter] = useState(''); // Advanced filtering states const [statusFilter, setStatusFilter] = useState('all'); const [locationFilter, setLocationFilter] = useState('all'); const [skillsFilter, setSkillsFilter] = useState([]); // Constants const pageSize = 10; // Memoize the callback to prevent recreation const handleShowDetailModal = useCallback((user: UserType) => { setSelectedUser(user); setShowDetailModal(true); }, []); const handleCloseDetailModal = useCallback(() => { setShowDetailModal(false); setSelectedUser(null); }, []); const handleShowNewUserModal = useCallback(() => { setShowNewUserModal(true); }, []); const handleCloseNewUserModal = useCallback(() => { setShowNewUserModal(false); }, []); // Filter data based on current filter states const filteredData = useMemo(() => { return mockData.filter((user) => { // Status filter if (statusFilter !== 'all') { const isActive = statusFilter === 'active'; if (user.is_active !== isActive) return false; } // Location filter if (locationFilter !== 'all' && user.location !== locationFilter) { return false; } // Skills filter if (skillsFilter.length > 0) { const hasMatchingSkill = skillsFilter.some((skill) => user.skills.includes(skill) ); if (!hasMatchingSkill) return false; } return true; }); }, [statusFilter, locationFilter, skillsFilter]); // Memoize columns to prevent recreation on every render const columns: ColumnDef[] = useMemo( () => [ { accessorKey: 'fullname', header: 'User', cell: ({ row }) => (
{/* Avatar */}
{row.original.avatar ? ( {row.original.fullname} ) : ( )}
{/* Name only */}

{row.original.fullname}

), enableSorting: true, }, { accessorKey: 'skills', header: 'Skills', cell: ({ row }) => (
{row.original.skills.slice(0, 2).map((skill, index) => ( {skill.replace(' Developer', '').replace(' Engineer', '')} ))} {row.original.skills.length > 2 && ( +{row.original.skills.length - 2} )}
), enableSorting: false, }, { accessorKey: 'location', header: 'Location', cell: ({ row }) => ( {row.original.location} ), enableSorting: true, }, { accessorKey: 'is_active', header: 'Status', cell: ({ row }) => (
{row.original.is_active ? 'Active' : 'Inactive'}
), enableSorting: true, sortingFn: (rowA, rowB) => { const aActive = rowA.original.is_active; const bActive = rowB.original.is_active; if (aActive && !bActive) return -1; if (!aActive && bActive) return 1; return 0; }, }, { accessorKey: 'created_at', header: 'Joined', cell: ({ row }) => ( {new Date(row.original.created_at).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric', })} ), enableSorting: true, sortingFn: 'datetime', }, { id: 'actions', header: 'Actions', meta: { cellClassName: cn('w-48') }, cell: ({ row }) => (
), enableSorting: false, }, ], [handleShowDetailModal] ); return (

User Management

{/* Filters and actions */}
{/* Left side - Search & filters */}
{/* Search bar */}
setGlobalFilter(e.target.value)} />
{/* Status Filter */}
{/* Location Filter */}
{/* Skills Filter with Icon */}
{/* Right side - Add User Button */}
{/* Active filters display */} {(skillsFilter.length > 0 || statusFilter !== 'all' || locationFilter !== 'all') && (
Active filters: {/* Status filter badge */} {statusFilter !== 'all' && ( Status: {statusFilter} )} {/* Location filter badge */} {locationFilter !== 'all' && ( Location: {locationFilter} )} {/* Skills filter badges */} {skillsFilter.map((skill) => ( {skill.replace(' Developer', '').replace(' Engineer', '')} ))} {/* Clear all filters */}
)} {/* Pagination-aware results display */} {filteredData.length > 0 && (
Showing {Math.min(pageSize, filteredData.length)} of{' '} {filteredData.length} users {filteredData.length > pageSize}
)} {/* Table */}
{/* Modals component */} {/* New User Modal */}
); }; export default HackathonUsersPage;