feat: fix project status counts, add top pagination and sortable columns
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m39s
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m39s
- Status counts now show each project's latest round state only (no more inflated counts from projects passing multiple rounds) - Add pagination controls at top of projects, members, and observer lists - Add sortable column headers to admin projects table (title, category, program, assignments, status) and members table (name, role, status, last login) - Backend: add sortBy/sortDir params to project.list and user.list Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -94,6 +94,7 @@ import { ProjectLogo } from '@/components/shared/project-logo'
|
||||
import { BulkNotificationDialog } from '@/components/admin/projects/bulk-notification-dialog'
|
||||
|
||||
import { Pagination } from '@/components/shared/pagination'
|
||||
import { SortableHeader } from '@/components/shared/sortable-header'
|
||||
import { getCountryName, getCountryFlag, normalizeCountryToCode } from '@/lib/countries'
|
||||
import { CountryFlagImg } from '@/components/ui/country-select'
|
||||
import {
|
||||
@@ -215,6 +216,8 @@ export default function ProjectsPage() {
|
||||
const [perPage, setPerPage] = useState(parsed.perPage || 20)
|
||||
const [searchInput, setSearchInput] = useState(parsed.search)
|
||||
const [viewMode, setViewMode] = useState<'table' | 'card'>('table')
|
||||
const [sortBy, setSortBy] = useState<string | undefined>(undefined)
|
||||
const [sortDir, setSortDir] = useState<'asc' | 'desc'>('desc')
|
||||
|
||||
// Fetch display settings
|
||||
const { data: displaySettings } = trpc.settings.getMultiple.useQuery({
|
||||
@@ -260,6 +263,16 @@ export default function ProjectsPage() {
|
||||
setPage(1)
|
||||
}
|
||||
|
||||
const handleSort = (column: string) => {
|
||||
if (sortBy === column) {
|
||||
setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'))
|
||||
} else {
|
||||
setSortBy(column)
|
||||
setSortDir('asc')
|
||||
}
|
||||
setPage(1)
|
||||
}
|
||||
|
||||
// Build tRPC query input
|
||||
const queryInput = {
|
||||
search: filters.search || undefined,
|
||||
@@ -298,6 +311,8 @@ export default function ProjectsPage() {
|
||||
hasAssignments: filters.hasAssignments,
|
||||
page,
|
||||
perPage,
|
||||
sortBy: sortBy as 'title' | 'category' | 'program' | 'assignments' | 'status' | 'createdAt' | undefined,
|
||||
sortDir: sortBy ? sortDir : undefined,
|
||||
}
|
||||
|
||||
const utils = trpc.useUtils()
|
||||
@@ -876,6 +891,17 @@ export default function ProjectsPage() {
|
||||
</Card>
|
||||
) : data ? (
|
||||
<>
|
||||
{/* Top Pagination */}
|
||||
{data.totalPages > 1 && (
|
||||
<Pagination
|
||||
page={data.page}
|
||||
totalPages={data.totalPages}
|
||||
total={data.total}
|
||||
perPage={perPage}
|
||||
onPageChange={setPage}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Table View */}
|
||||
{viewMode === 'table' ? (
|
||||
<>
|
||||
@@ -891,12 +917,12 @@ export default function ProjectsPage() {
|
||||
aria-label="Select all projects"
|
||||
/>
|
||||
</TableHead>
|
||||
<TableHead className="min-w-[280px]">Project</TableHead>
|
||||
<TableHead>Category</TableHead>
|
||||
<TableHead>Program</TableHead>
|
||||
<SortableHeader label="Project" column="title" currentSort={sortBy} currentDir={sortDir} onSort={handleSort} className="min-w-[280px]" />
|
||||
<SortableHeader label="Category" column="category" currentSort={sortBy} currentDir={sortDir} onSort={handleSort} />
|
||||
<SortableHeader label="Program" column="program" currentSort={sortBy} currentDir={sortDir} onSort={handleSort} />
|
||||
<TableHead>Tags</TableHead>
|
||||
<TableHead>Assignments</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
<SortableHeader label="Assignments" column="assignments" currentSort={sortBy} currentDir={sortDir} onSort={handleSort} />
|
||||
<SortableHeader label="Status" column="status" currentSort={sortBy} currentDir={sortDir} onSort={handleSort} />
|
||||
<TableHead className="text-right">Actions</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
||||
Reference in New Issue
Block a user