Add pagination to admin user, vendor, and ban lists

Introduces pagination controls and server-side paginated fetching for blocked users, users, and vendors in the admin dashboard. Improves error handling in server API responses and validates order ID in OrderDetailsModal. Updates git-info.json with latest commit metadata.
This commit is contained in:
g
2025-12-31 05:46:24 +00:00
parent 0062aa2dfe
commit 5f1e294091
6 changed files with 194 additions and 20 deletions

View File

@@ -25,6 +25,19 @@ interface TelegramUser {
createdAt?: string;
}
interface PaginationResponse {
success: boolean;
users: TelegramUser[];
pagination: {
page: number;
limit: number;
total: number;
totalPages: number;
hasNextPage: boolean;
hasPrevPage: boolean;
};
}
function formatCurrency(amount: number): string {
return new Intl.NumberFormat('en-GB', {
style: 'currency',
@@ -37,16 +50,19 @@ export default function AdminUsersPage() {
const [loading, setLoading] = useState(true);
const [users, setUsers] = useState<TelegramUser[]>([]);
const [searchQuery, setSearchQuery] = useState("");
const [page, setPage] = useState(1);
const [pagination, setPagination] = useState<PaginationResponse['pagination'] | null>(null);
useEffect(() => {
fetchUsers();
}, []);
}, [page]);
const fetchUsers = async () => {
try {
setLoading(true);
const data = await fetchClient<TelegramUser[]>("/admin/users");
setUsers(data);
const data = await fetchClient<PaginationResponse>(`/admin/users?page=${page}&limit=25`);
setUsers(data.users);
setPagination(data.pagination);
} catch (error: any) {
console.error("Failed to fetch users:", error);
toast({
@@ -300,6 +316,31 @@ export default function AdminUsersPage() {
</TableBody>
</Table>
)}
{pagination && pagination.totalPages > 1 && (
<div className="mt-4 flex items-center justify-between">
<div className="text-sm text-muted-foreground">
Showing page {pagination.page} of {pagination.totalPages} ({pagination.total} total users)
</div>
<div className="flex gap-2">
<Button
variant="outline"
size="sm"
onClick={() => setPage(p => Math.max(1, p - 1))}
disabled={!pagination.hasPrevPage}
>
Previous
</Button>
<Button
variant="outline"
size="sm"
onClick={() => setPage(p => p + 1)}
disabled={!pagination.hasNextPage}
>
Next
</Button>
</div>
</div>
)}
</CardContent>
</Card>
</div>