import { createFileRoute, useNavigate } from '@tanstack/react-router'; import * as React from 'react'; import { Search, Plus, Users as TeamIcon, Pencil, X } from 'lucide-react'; import ModalTeamDetail from './_components/hackathon-teams/modal-team-detail-new'; import { BackofficeWrapper, DataTable, } from '@imphnen-frontend-service/ui/organisms'; import { ColumnDef } from '@tanstack/react-table'; import { Avatar, AvatarFallback, AvatarImage, Badge, Button, Card, CardContent, CardHeader, Input, } from '@imphnen-frontend-service/ui/atoms'; import { useQuery } from '@tanstack/react-query'; import { getAdminTeams, TAdminTeamItem, } from '@imphnen-frontend-service/service'; type TeamType = TAdminTeamItem; export const Route = createFileRoute('/_authenticated/hackathon-teams')({ component: HackathonTeamsPage, validateSearch: (search: Record) => ({ page: Number(search.page) || 1, search: (search.search as string) || '', per_page: Number(search.per_page) || 10, }), }); function HackathonTeamsPage() { const searchParams = Route.useSearch(); const navigate = useNavigate(); const currentPage = Math.max(1, searchParams.page); const searchQuery = searchParams.search || ''; const perPage = searchParams.per_page || 10; const [showDetailModal, setShowDetailModal] = React.useState(false); const [showNewTeamModal, setShowNewTeamModal] = React.useState(false); const [selectedTeam, setSelectedTeam] = React.useState(null); const [globalFilter, setGlobalFilter] = React.useState(searchQuery); const [visibilityFilter, setVisibilityFilter] = React.useState('all'); const [cityFilter, setCityFilter] = React.useState('all'); const { data: teamsResponse, isLoading, isFetching, } = useQuery({ queryKey: [ 'admin-teams', currentPage, perPage, cityFilter, visibilityFilter, searchQuery, ], queryFn: () => getAdminTeams({ page: currentPage, per_page: perPage, search: searchQuery || undefined, }), staleTime: 30000, gcTime: 5 * 60 * 1000, }); const totalData = teamsResponse?.meta?.total_data || 0; const totalPages = teamsResponse?.meta?.total_page || 1; const handlePageChange = React.useCallback( (newPage: number) => { navigate({ search: { page: newPage, per_page: perPage !== 10 ? perPage : undefined, search: searchQuery || undefined, } as any, }); window.scrollTo({ top: 0, behavior: 'smooth' }); }, [navigate, perPage, searchQuery] ); React.useEffect(() => { if (!isLoading && totalPages > 0 && currentPage > totalPages) { navigate({ search: { page: totalPages } as any }); } }, [currentPage, totalPages, navigate, isLoading]); React.useEffect(() => { setGlobalFilter(searchQuery); }, [searchQuery]); const handleSearch = React.useCallback(() => { navigate({ search: { page: 1, per_page: perPage !== 10 ? perPage : undefined, search: globalFilter.trim() || undefined, } as any, }); }, [globalFilter, navigate, perPage]); const filteredData = React.useMemo(() => { return ( ((teamsResponse?.data as any)?.data as TeamType[]) ?? (teamsResponse?.data as TeamType[]) ?? [] ); }, [teamsResponse]); const handleShowDetailModal = React.useCallback((team: TeamType) => { setSelectedTeam(team); setShowDetailModal(true); }, []); const columns: ColumnDef[] = React.useMemo( () => [ { accessorKey: 'name', header: 'Team', cell: ({ row }) => (

{row.original.name}

), enableSorting: true, }, { accessorKey: 'city', header: 'City', cell: ({ row }) => ( {row.original.city} ), enableSorting: true, }, { accessorKey: 'visibility', header: 'Visibility', cell: ({ row }) => ( {row.original.visibility === 'public' ? 'Public' : 'Private'} ), enableSorting: true, }, { id: 'leader', header: 'Leader ID', cell: ({ row }) => (
{row.original.leader_id}
), enableSorting: false, }, { accessorKey: 'created_at', header: 'Created', cell: ({ row }) => ( {new Date(row.original.created_at).toLocaleDateString('en-UK', { year: 'numeric', month: 'short', day: 'numeric', })} ), enableSorting: true, sortingFn: 'datetime', }, { id: 'actions', header: 'Actions', cell: ({ row }) => ( ), enableSorting: false, }, ], [handleShowDetailModal] ); const hasActiveFilters = visibilityFilter !== 'all' || cityFilter !== 'all'; return (
setGlobalFilter(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSearch()} />
{hasActiveFilters && (
Active filters: {visibilityFilter !== 'all' && ( Visibility: {visibilityFilter} )} {cityFilter !== 'all' && ( City: {cityFilter} )}
)} {isLoading ? (
Memuat data teams…
) : filteredData.length > 0 ? ( <>
Menampilkan {filteredData.length} dari {totalData} teams (page{' '} {currentPage} / {totalPages}) {isFetching && ( Updating… )}
) : (
Tidak ada team. Coba ubah filter pencarian.
)}
{ setShowDetailModal(false); setSelectedTeam(null); }} team={selectedTeam} /> setShowNewTeamModal(false)} team={null} />
); }