# Simple pagination

> In a time where we delegate repetitive tasks to AI, writing simple code like this manually every now and then keeps us sharp. This challenge is a plain fetch with pagination and manual loading and error handling — exactly what so many job interviews ask for, and the kind of thing we forget if we don't practice it once in a while.

- Difficulty: intermediate
- Tags: useState, useEffect, fetching
- Estimated time: 45 minutes
- Tests: 15
- Requires subscription: yes

## Overview

In a time where we delegate repetitive tasks to AI, writing simple code like this manually every now and then keeps us sharp. This challenge is a plain fetch with pagination and manual loading and error handling — exactly what so many job interviews ask for, and the kind of thing we forget if we don't practice it once in a while.


## Requirements

- Fetch users from `https://example/users?page={page}` and display the response in a table with columns: ID, Name, and Last name. The API returns up to 10 users per page.
- Show `TableSkeleton` while fetching.
- Display a page info text: `Page {page} of {totalPages} ({count} users)`.
- Pagination buttons:
  - **First**: goes to page 0. Disabled when on page 0.
  - **Previous**: goes to the previous page. Disabled when on page 0.
  - **Next**: goes to the next page. Disabled when on the last page.
  - **Last**: goes to the last page. Disabled when on the last page.
- All buttons must be disabled when the response has `count: 0` (no users) or loading
- Display an error message when the request fails. Use `data-testid="error-message"` on the error element.


## Notes

- The API response shape is

```typescript
{
  count: number;
  users: {
    id: number;
    name: string;
    lastName: string;
  }
  [];
}
```

- `count` is the total number of users, not the page size.
- Pages are 0-based: `?page=0` returns the first 10 users.
- The mock API randomly fails ~20% of requests (1 in 5) and a delay of 500ms to simulate real-world server errors.
- The `data-testid` attributes on buttons and the page info are used by the tests — keep them.
- Clear the error state when starting a new fetch so it doesn't stick around after a successful retry.


## Tests

01. renders the app title
02. shows skeleton rows while loading
03. renders first page of users after loading
04. disables First and Previous on first page, enables Next and Last
05. navigates to next page
06. navigates back with Previous
07. navigates to last page
08. navigates to first page from another page
09. disables Next and Last on the last page
10. cannot navigate before page 0
11. cannot navigate past the last page
12. disables all buttons when there are no users
13. shows last 4 users on the last page
14. shows error message when fetch fails
15. recovers from error on retry


