diff --git a/backend/users/models.py b/backend/users/models.py index 6128002..2834285 100644 --- a/backend/users/models.py +++ b/backend/users/models.py @@ -102,7 +102,7 @@ class Users(SQLModel, table=True): select(cls) .options(selectinload(cls.role)) .where(cls.is_deleted == False) - .order_by(cls.created_at.desc()) + .order_by(cls.created_at.desc(),cls.id.desc()) ) if search: statement = statement.where(cls._search_filter(search)) diff --git a/frontend/src/screens/Candidates.jsx b/frontend/src/screens/Candidates.jsx index 3e43eda..20557e1 100644 --- a/frontend/src/screens/Candidates.jsx +++ b/frontend/src/screens/Candidates.jsx @@ -14,7 +14,7 @@ import { useLocation, useNavigate } from 'react-router-dom' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import Modal from '../ui/Modal' -import { DataTableHead, DEFAULT_PAGE_SIZE, Pagination, pageAfterSizeChange, pageWindow, useDataTable } from '../ui/DataTable' +import { DataTableHead, DEFAULT_PAGE_SIZE, Pagination, pageWindow, useDataTable } from '../ui/DataTable' import PageHeader from '../ui/PageHeader' import { Avatar, Badge, EmptyState, FieldError, Icon, SkeletonRows } from '../ui/primitives' import { useToast } from '../ui/Toast' @@ -117,13 +117,12 @@ export default function Candidates() { const [filters, setFilters] = useState(EMPTY_FILTERS) const [showFilters, setShowFilters] = useState(false) const [sortMode, setSortMode] = useState('recent') - const [page, setPage] = useState(1) + const [skip, setSkip] = useState(0) const [pageSize, setPageSize] = useState(DEFAULT_PAGE_SIZE) const [profileFor, setProfileFor] = useState(null) const [atsFor, setAtsFor] = useState(null) const [adding, setAdding] = useState(false) - const skip = (page - 1) * pageSize const countQuery = useQuery({ queryKey: qk.candidates.count({ roleId: CANDIDATE_ROLE_ID }), queryFn: async () => { @@ -216,8 +215,7 @@ export default function Candidates() { return true }) - if (sortMode === 'recent') list = [...list].sort((a, b) => (b.applied ?? 0) - (a.applied ?? 0)) - else if (sortMode === 'name') list = [...list].sort((a, b) => a.name.localeCompare(b.name)) + if (sortMode === 'name') list = [...list].sort((a, b) => a.name.localeCompare(b.name)) return list }, [candidates, filters, q, sortMode]) @@ -238,11 +236,14 @@ export default function Candidates() { const t = useDataTable({ columns, rows, pageSize: Math.max(rows.length, 1) }) const total = countQuery.data ?? 0 const pages = Math.max(1, Math.ceil(total / pageSize)) - const currentPage = Math.min(page, pages) + const from = total ? skip + 1 : 0 + const to = total ? skip + rows.length : 0 + const currentPage = Math.min(Math.floor(skip / pageSize) + 1, pages) useEffect(() => { - if (page > pages) setPage(pages) - }, [page, pages]) + if (total <= 0 || skip < total) return + setSkip(Math.max(0, Math.floor((total - 1) / pageSize) * pageSize)) + }, [total, pageSize, skip]) const recentChips = recentlyViewed .slice(0, 6) @@ -426,15 +427,15 @@ export default function Candidates() { setSkip((p - 1) * pageSize)} pageButtons={pageWindow(currentPage, pages)} pageSize={pageSize} - onPageSizeChange={(n) => { setPageSize(n); setPage((p) => pageAfterSizeChange(p, total, n)) }} + onPageSizeChange={(n) => setPageSize(n)} pageSizeMax={500} /> diff --git a/frontend/src/screens/Matching.jsx b/frontend/src/screens/Matching.jsx index 84ac818..d311d84 100644 --- a/frontend/src/screens/Matching.jsx +++ b/frontend/src/screens/Matching.jsx @@ -14,7 +14,7 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import OpenResumeButton from '../ui/OpenResumeButton' import PageHeader from '../ui/PageHeader' import { Tabs } from '../ui/Tabs' -import { DEFAULT_PAGE_SIZE, Pagination, pageAfterSizeChange, pageWindow } from '../ui/DataTable' +import { DEFAULT_PAGE_SIZE, Pagination, pageWindow } from '../ui/DataTable' import { Avatar, Badge, EmptyState, Icon } from '../ui/primitives' import { JobCard, PickRoleModal } from '../ui/SuggestedRoles' import { useToast } from '../ui/Toast' @@ -109,7 +109,7 @@ export default function Matching() { const deepLink = searchParams.get('record') const [tab, setTab] = useState('needs') - const [page, setPage] = useState(1) + const [skip, setSkip] = useState(0) const [pageSize, setPageSize] = useState(DEFAULT_PAGE_SIZE) const [selectedId, setSelectedId] = useState(deepLink || null) const [q, setQ] = useState('') @@ -121,9 +121,9 @@ export default function Matching() { const listParams = useMemo(() => ({ ...tabFilter, top: pageSize, - skip: (page - 1) * pageSize, + skip, ...(q.trim() ? { search: q.trim() } : {}), - }), [tabFilter, page, pageSize, q]) + }), [tabFilter, skip, pageSize, q]) const listQuery = useQuery({ queryKey: qk.candidates.matching({ ...listParams, tab }), @@ -147,11 +147,14 @@ export default function Matching() { const filtered = rows const total = listQuery.data?.total ?? 0 const pages = Math.max(1, Math.ceil(total / pageSize)) - const currentPage = Math.min(page, pages) + const from = total ? skip + 1 : 0 + const to = Math.min(skip + pageSize, total) + const currentPage = Math.min(Math.floor(skip / pageSize) + 1, pages) useEffect(() => { - if (listQuery.isSuccess && page > pages) setPage(pages) - }, [listQuery.isSuccess, page, pages]) + if (!listQuery.isSuccess || total <= 0 || skip < total) return + setSkip(Math.max(0, Math.floor((total - 1) / pageSize) * pageSize)) + }, [listQuery.isSuccess, total, pageSize, skip]) useEffect(() => { if (!deepLink) return undefined @@ -284,7 +287,7 @@ export default function Matching() {
{ setTab(t); setPage(1); setSelectedId(null) }} + onChange={(t) => { setTab(t); setSkip(0); setSelectedId(null) }} className="tabs tabs-wrap" tabs={TABS.map((t) => ({ key: t.key, @@ -301,7 +304,7 @@ export default function Matching() { { setQ(e.target.value); setPage(1) }} + onChange={(e) => { setQ(e.target.value); setSkip(0) }} placeholder="Search…" />
@@ -342,18 +345,17 @@ export default function Matching() { {listQuery.isSuccess && total > 0 && ( { setPage(p); setSelectedId(null) }} + setPage={(p) => { setSkip((p - 1) * pageSize); setSelectedId(null) }} pageButtons={pageWindow(currentPage, pages)} pageSize={pageSize} pageSizeMax={PAGE_SIZE_MAX} onPageSizeChange={(n) => { setPageSize(n) - setPage((p) => pageAfterSizeChange(p, total, n)) setSelectedId(null) }} />