first commit

This commit is contained in:
2026-09-25 16:31:10 +05:30
parent e43cebb43e
commit 88f658fba9
378 changed files with 33242 additions and 115 deletions

View File

@@ -0,0 +1,50 @@
'use client';
import {VStack} from '@astryxdesign/core/Layout';
import {PageHeader} from '@/shared/components/primitives/PageHeader';
import {AsyncBoundary} from '@/shared/components/data/AsyncBoundary';
import {SkeletonCardGrid} from '@/shared/components/patterns/LoadingState';
import {EmptyPanel} from '@/shared/components/patterns/EmptyPanel';
import {useSites} from '@/features/stores/hooks/useSites';
import {ShopSection} from '@/features/stores/components/ShopSection';
/**
* The estate, from GET /api/sites.
*
* Health fields are nullable and rendered as "—" when the platform does not
* report them. A deployment that sends no camera health is not a deployment
* with zero cameras up, and printing "0/0" for "not reported" makes a working
* estate look broken.
*/
export default function StoresPage() {
const sites = useSites();
return (
<VStack gap={5}>
<PageHeader
title="Store"
description="Every shop, its cameras, and the shop PC that watches them."
/>
<AsyncBoundary
resource={sites}
loading={<SkeletonCardGrid count={4} height={170} />}
empty={
<EmptyPanel
icon="stores"
title="No stores yet"
description="Shops appear here once they are registered on the platform."
/>
}
>
{(rows) => (
<VStack gap={6}>
{rows.map((site) => (
<ShopSection key={site.id} site={site} />
))}
</VStack>
)}
</AsyncBoundary>
</VStack>
);
}