Files
route-commerce/src/app/admin/water-log/page.tsx
T
tyler b845d69aba feat: comprehensive frontend polish - UI/UX improvements across all pages
Public Pages:
- Landing page with server/client split and metadata export
- Cart page with ARIA accessibility and loading states
- Checkout page with form accessibility and proper design system
- Contact page with SEO metadata and improved accessibility
- Pricing page with enhanced FAQ accessibility
- Login page with Suspense boundaries and secure patterns

Brand Storefronts:
- Premium loading skeletons for Tuxedo and Indian River Direct
- Branded error boundaries with animations
- Loading.tsx for about, contact, FAQ, stops pages
- Error.tsx for all storefront subpages

Admin Dashboard:
- AdminSidebar: ARIA labels, keyboard navigation, mobile improvements
- DashboardClient: Stats cards, quick actions, usage progress
- Admin layout: Toast provider integration

Admin Orders/Products/Stops:
- Toast notification system with auto-dismiss
- Skeleton loading components (Table, Card, Stats, Form)
- Bulk actions (mark picked up, publish stops)
- Form validation with error styling

Admin Communications:
- AnalyticsDashboard: sparklines, stat cards, engagement badges
- CampaignComposerPage: step wizard, template selection, email preview
- SegmentBuilderPage: empty state, active segment handling
- ContactListPanel: loading skeletons, professional empty states
- MessageLogPanel: stats cards, engagement indicators
- HarvestReachNav: branded tab navigation
- All pages: metadata exports and loading.tsx

Admin Settings:
- SquareSyncSettingsClient: design system colors, save/cancel UX
- ShippingSettingsForm: validation, dirty state tracking
- Integrations page: proper layout with AI and communications sections
- Billing: improved plan comparison, add-on cards
- PaymentSettings: toggle components, validation

Wholesale Portal:
- Portal: loading skeletons, quantity stepper, search/filter
- Login/Register: FormField validation, success states
- Success/Cancel pages: animated checkmarks
- Employee portal: skeletons, empty states, mobile responsive

Water Log:
- FieldClient: loading step, progress indicator, spinner
- AdminClient: loading skeletons
- Admin pages: loading.tsx files

New Components:
- Toast.tsx/ToastContainer.tsx: comprehensive notification system
- Skeleton.tsx: shimmer loading components
- AdminToggle.tsx: consistent toggle/switch
- CommunicationsLoading.tsx: loading skeleton for comms
- ToastExport.ts: exports

CSS Improvements:
- Shimmer animation keyframes
- Toast slide-in animation

Accessibility:
- ARIA labels throughout
- Keyboard navigation
- Focus states
- Semantic HTML
- Screen reader support
2026-06-02 05:19:34 +00:00

95 lines
3.3 KiB
TypeScript

import WaterLogAdminPanel from "@/components/admin/WaterLogAdminPanel";
import { getAdminUser } from "@/lib/admin-permissions";
import { getWaterIrrigators, getWaterHeadgatesAdmin, getWaterEntries } from "@/actions/water-log/admin";
import { redirect } from "next/navigation";
import { PageHeader } from "@/components/admin/design-system";
const TUXEDO_BRAND_ID = "64294306-5f42-463d-a5e8-2ad6c81a96de";
export const dynamic = "force-dynamic";
// ── Skeleton Loading ──────────────────────────────────────────────────────────
function WaterLogLoadingSkeleton() {
return (
<div className="space-y-6 px-6 pb-8">
{/* Navigation skeleton */}
<div className="flex gap-2">
{[1, 2, 3].map(i => (
<div key={i} className="h-10 w-28 rounded-xl bg-slate-200 animate-pulse" />
))}
</div>
{/* Summary skeleton */}
<div className="rounded-xl border border-slate-200 bg-white p-5 animate-pulse">
<div className="flex items-start justify-between mb-4">
<div className="h-5 w-32 bg-slate-200 rounded" />
<div className="h-8 w-48 bg-slate-100 rounded" />
</div>
<div className="grid grid-cols-3 gap-4">
{[1, 2, 3].map(i => (
<div key={i} className="space-y-1">
<div className="h-3 w-20 bg-slate-100 rounded" />
<div className="h-6 w-16 bg-slate-200 rounded" />
</div>
))}
</div>
</div>
{/* Table skeletons */}
<div className="rounded-xl border border-slate-200 bg-white p-4 animate-pulse">
<div className="h-5 w-28 bg-slate-200 rounded mb-4" />
<div className="space-y-2">
{[1, 2, 3].map(i => (
<div key={i} className="flex items-center gap-4 py-3 border-b border-slate-50 last:border-0">
<div className="h-4 w-20 bg-slate-100 rounded" />
<div className="h-4 w-16 bg-slate-100 rounded" />
<div className="h-4 w-14 bg-slate-100 rounded ml-auto" />
<div className="h-4 w-12 bg-slate-100 rounded" />
</div>
))}
</div>
</div>
</div>
);
}
export default async function AdminWaterLogPage() {
const adminUser = await getAdminUser();
const isAuthorized =
adminUser?.role === "platform_admin" ||
(adminUser?.role === "brand_admin" &&
adminUser?.brand_id === TUXEDO_BRAND_ID &&
adminUser?.can_manage_water_log);
if (!isAuthorized) {
redirect("/admin/pickup");
}
const brandId = TUXEDO_BRAND_ID;
const [users, headgates, entries] = await Promise.all([
getWaterIrrigators(brandId),
getWaterHeadgatesAdmin(brandId),
getWaterEntries(brandId, 50),
]);
return (
<div className="min-h-screen bg-[var(--admin-bg)]">
<PageHeader
title="Water Log"
subtitle="PIN-based access · Tuxedo only · separate from site admin"
className="px-6 pt-6"
/>
<div className="px-6 pb-8">
<WaterLogAdminPanel
initialUsers={users}
initialHeadgates={headgates}
initialEntries={entries}
brandId={brandId}
canManage={isAuthorized}
/>
</div>
</div>
);
}