Polish /water/admin: dark zinc palette, Spanish-first, faster load
Deploy to route.crispygoat.com / deploy (push) Successful in 4m8s

Display & aesthetic
- Switch stone-* palette to zinc-950/900/800 to match headgate edit page
- Cards: rounded-2xl p-5 ring-1 ring-zinc-800 (was rounded-xl p-4 ring-stone-200)
- Sticky header: bg-zinc-950/80 backdrop-blur with EN/ES toggle
- Section labels: uppercase tracking-wider text-zinc-500
- Stat numbers: text-3xl font-bold tabular-nums
- Status pills: subdued dark variants (bg-green-900/30 text-green-400, etc.)
- Replace hardcoded "Salir" with localized t.logout
- Default language to ES; auto-detect via navigator.language
- Add missing labels (alerts, no_users, no_alerts, save, filter_all, …)

Performance
- Bootstrap 4 datasets in RSC (page.tsx) so first paint has data, not a spinner
- Drop entries fetch from 500 to 50; add "Load more" paginated button
- Display-summary polling keeps previous data visible during refresh
- Use ref for countdown so the 30s interval isn't recreated each tick

No DB or server-action changes.
This commit is contained in:
Tyler
2026-07-01 14:28:57 -06:00
parent 4d323af51b
commit 602adb4588
2 changed files with 849 additions and 572 deletions
+26 -1
View File
@@ -1,7 +1,15 @@
import { redirect } from "next/navigation";
import { cookies } from "next/headers";
import {
getWaterDisplaySummary,
getWaterHeadgatesAdmin,
getWaterIrrigators,
getWaterAlertLog,
} from "@/actions/water-log/admin";
import WaterAdminClient from "@/components/water/WaterAdminClient";
const TUXEDO_BRAND_ID = "64294306-5f42-463d-a5e8-2ad6c81a96de";
export const dynamic = "force-dynamic";
export default async function WaterAdminPage() {
@@ -11,5 +19,22 @@ export default async function WaterAdminPage() {
redirect("/water/admin/login");
}
return <WaterAdminClient />;
// Bootstrap the 4 datasets in parallel on the server so the first paint
// already has real data — no "Loading…" skeleton flash. The client's
// 30s polling keeps the display-summary card fresh from here.
const [summary, headgates, users, alertLog] = await Promise.all([
getWaterDisplaySummary(TUXEDO_BRAND_ID),
getWaterHeadgatesAdmin(TUXEDO_BRAND_ID),
getWaterIrrigators(TUXEDO_BRAND_ID),
getWaterAlertLog(TUXEDO_BRAND_ID, 50),
]);
return (
<WaterAdminClient
initialSummary={summary}
initialHeadgates={headgates}
initialUsers={users}
initialAlertLog={alertLog}
/>
);
}
File diff suppressed because it is too large Load Diff