Redesign Home screen with device summary and scanner status

Adds a responsive Home screen combining the notification list with a
device summary panel and ARP scanner status, visible side-by-side on
wide screens and stacked on narrow ones.

Backend:
- New GET /api/devices/summary endpoint returning registered device
  counts and "seen in last 24h / 7 days" breakdowns by registration
  status
- Migration 07 adds indexes on (is_registered) and (last_seen,
  is_registered) so summary queries use index range scans instead of
  full table scans

Frontend:
- HomeScreen replaces NotificationList, embedding notifications,
  device summary card, and ArpScannerCard in a LayoutBuilder-driven
  two-column (≥700 px) or single-column layout
- ArpScannerCard extracted to a shared public widget reused by both
  HomeScreen and StatusScreen
- Nav rail entry renamed to "Home" with home icon

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
rzuasti
2026-05-28 19:10:08 -04:00
co-authored by Claude Sonnet 4.6
parent dc8f47e66d
commit 251d8a479e
13 changed files with 802 additions and 367 deletions
+4 -1
View File
@@ -1,7 +1,7 @@
use std::error::Error;
use crate::model::device_events::{DeviceEvent, DeviceEventType};
use crate::model::devices::Device;
use crate::model::devices::{Device, DeviceSummary};
use crate::model::notifications::{Notification, NotificationType};
use crate::settings::get_settings;
use crate::web_server::arp_scanner::ArpScannerStatusResponse;
@@ -38,6 +38,7 @@ pub mod utils;
paths(
test_api,
devices::list,
devices::summary,
devices::read,
devices::register,
devices::unregister,
@@ -51,6 +52,7 @@ pub mod utils;
),
components(schemas(
Device,
DeviceSummary,
Notification,
NotificationType,
RegisterDevicePayload,
@@ -103,6 +105,7 @@ pub async fn serve() -> Result<(), Box<dyn Error>> {
.route("/api/test", get(test_api))
.route("/api/devices", get(devices::list))
.route("/api/devices", put(devices::register))
.route("/api/devices/summary", get(devices::summary))
.route("/api/devices/{mac_address}", delete(devices::unregister))
.route("/api/devices/{mac_address}", get(devices::read))
.route("/api/devices/{mac_address}/events", get(device_events::list))