Add "go to last page" and page count to notifications and devices lists

The list endpoints now return a total count alongside the page so the
front-end can show how many pages exist and offer a last-page jump.

Backend: add count(is_new) and count_devices(...) (sharing a WHERE-builder
with list_devices so page and count can't drift), wrap both list responses
in {items, total_count} structs, and register them with utoipa.

Front-end: parse the wrapper shape (dropping the fetch-one-extra trick),
add a Last-page button and a responsive "Page X of Y" / "X / Y" label to
the shared PaginationBar, and track the total in both lists. Notifications
re-sync the count on every fetch and decrement it locally on mark-read/
unread removals so the count stays accurate without a re-fetch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
rzuasti
2026-06-05 21:09:25 -04:00
co-authored by Claude Opus 4.8
parent 3cb104e364
commit 844d7d189c
21 changed files with 765 additions and 275 deletions
+3 -4
View File
@@ -5,7 +5,7 @@ extension DeviceApi on BackendAPI {
Future<Device> getDevice(String macAddress) =>
_getModel('/devices/$macAddress', Device.fromJson);
Future<({List<Device> items, bool hasNextPage})> listDevices({
Future<({List<Device> items, int totalCount})> listDevices({
bool? isRegistered,
String? owner,
DeviceType? deviceType,
@@ -28,7 +28,7 @@ extension DeviceApi on BackendAPI {
params['sort_order'] = sortAscending ? 'asc' : 'desc';
}
params['page_offset'] = page * perPage;
params['page_limit'] = perPage + 1;
params['page_limit'] = perPage;
final response = await _dio.get(
'/devices',
@@ -37,9 +37,8 @@ extension DeviceApi on BackendAPI {
);
return _paginate(
response.data as List,
response.data as Map<String, dynamic>,
(item) => Device.fromJson(item as Map<String, dynamic>),
perPage,
);
}
@@ -14,7 +14,7 @@ extension NotificationApi on BackendAPI {
await _dio.post('/notifications/mark_all_as_old');
}
Future<({List<Notification> items, bool hasNextPage})> listNotifications(
Future<({List<Notification> items, int totalCount})> listNotifications(
bool? isNew, {
int page = 0,
int perPage = 5,
@@ -25,15 +25,14 @@ extension NotificationApi on BackendAPI {
queryParameters: {
'is_new': isNew ?? '',
'page_offset': page * perPage,
'page_limit': perPage + 1,
'page_limit': perPage,
},
cancelToken: cancelToken,
);
return _paginate(
response.data as List<dynamic>,
response.data as Map<String, dynamic>,
(item) => Notification.fromJson(item),
perPage,
);
}
}