feat(improvement): add pagination to endpoints and pages + sync navbar when data changes

This commit is contained in:
2026-03-13 10:30:27 +08:00
parent a9ebbf6a4a
commit 56404792c6
14 changed files with 543 additions and 210 deletions

View File

@@ -10,12 +10,18 @@ import DeleteClientModal from "../components/DeleteClientModal"
import FilterBar from "../components/FilterBar"
import { Button } from "../components/ui/button"
import { Card } from "../components/ui/card"
import { Pagination } from "../components/Pagination"
export default function Clients() {
const { activeWorkspace } = useWorkspace()
const [clients, setClients] = useState<Client[]>([])
const [isLoading, setIsLoading] = useState(true)
// Pagination States
const [currentPage, setCurrentPage] = useState(1)
const [totalItems, setTotalItems] = useState(0)
const [limit, setLimit] = useState(10)
// Filter States
const [searchQuery, setSearchQuery] = useState("")
const [debouncedSearch, setDebouncedSearch] = useState("")
@@ -37,6 +43,11 @@ export default function Clients() {
{ value: "-updated_at", label: isFa ? "اخیراً بروزرسانی شده" : "Recently Updated" },
]
// بازگشت به صفحه اول در صورت تغییر فیلتر یا جستجو
useEffect(() => {
setCurrentPage(1)
}, [debouncedSearch, ordering])
// Debounce search input to avoid spamming the API
useEffect(() => {
const handler = setTimeout(() => {
@@ -53,8 +64,14 @@ export default function Clients() {
setIsLoading(true)
try {
const data: any = await getClients(activeWorkspace.id, debouncedSearch, ordering)
setClients(data?.results || (Array.isArray(data) ? data : []))
const offset = (currentPage - 1) * limit
const data: any = await getClients(activeWorkspace.id, debouncedSearch, ordering, limit, offset)
const items = data?.results || (Array.isArray(data) ? data : [])
const count = data?.count !== undefined ? data.count : items.length
setClients(items)
setTotalItems(count)
} catch (error) {
console.error(t.clients.errors.fetchFailed, error)
setClients([])
@@ -76,10 +93,9 @@ export default function Clients() {
}
}
// Refetch when workspace, debounced search, or ordering changes
useEffect(() => {
fetchClientsList()
}, [activeWorkspace?.id, debouncedSearch, ordering])
}, [activeWorkspace?.id, debouncedSearch, ordering, currentPage, limit])
if (!activeWorkspace) {
return (
@@ -90,7 +106,7 @@ export default function Clients() {
}
return (
<div className="p-6 max-w-6xl mx-auto min-h-[calc(100vh-73px)]">
<div className="flex flex-col p-6 max-w-6xl mx-auto min-h-[calc(100vh-73px)]">
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-8">
<div>
<h1 className="text-2xl font-bold text-slate-900 dark:text-white">{t.clients.title}</h1>
@@ -114,7 +130,7 @@ export default function Clients() {
searchPlaceholder={t.clients.searchPlaceholder}
/>
<Card className="overflow-hidden dark:bg-slate-900 dark:border-slate-800">
<Card className="overflow-hidden dark:bg-slate-900 dark:border-slate-800 mb-6">
<div className="p-0">
{isLoading ? (
<div className="flex justify-center items-center p-12 text-slate-500">
@@ -169,6 +185,16 @@ export default function Clients() {
</div>
</Card>
{!isLoading && clients.length > 0 && (
<Pagination
currentPage={currentPage}
totalCount={totalItems}
limit={limit}
onPageChange={setCurrentPage}
onLimitChange={setLimit}
/>
)}
<CreateClientModal
isOpen={isCreateModalOpen}
onClose={() => setIsCreateModalOpen(false)}