update api and login

This commit is contained in:
2026-09-29 00:44:48 +05:30
parent b36a30385c
commit 2d8739e9a4
50 changed files with 2044 additions and 986 deletions

View File

@@ -4,16 +4,13 @@ import {proportional} from '@astryxdesign/core/Table';
import type {TableColumn} from '@astryxdesign/core/Table';
import {HStack} from '@astryxdesign/core/Layout';
import {Text} from '@astryxdesign/core/Text';
import {Link} from '@astryxdesign/core/Link';
import {StatusDot} from '@astryxdesign/core/StatusDot';
import {ResponsiveTable} from '@/shared/components/patterns/ResponsiveTable';
import type {
AdminAlert,
AdminCamera,
AdminCameraStatus,
AdminEvent,
AdminSeverity,
AdminStore,
} from '@/features/admin/types/monitoring';
/**
@@ -35,79 +32,14 @@ export const adminHref = {
merchants: '/admin/merchants',
company: (companyId: string) =>
`/admin/merchants/${encodeURIComponent(companyId)}`,
/** The merchant page, opened on its Shops tab — where "back" from a shop goes. */
shops: (companyId: string) => `${adminHref.company(companyId)}?tab=shops`,
store: (companyId: string, storeId: string) =>
`${adminHref.company(companyId)}/shops/${encodeURIComponent(storeId)}`,
camera: (companyId: string, storeId: string, cameraId: string) =>
`${adminHref.store(companyId, storeId)}/cameras/${encodeURIComponent(cameraId)}`,
};
/* ── Stores ──────────────────────────────────────────────────────────── */
type StoreRow = Record<string, unknown> & {
id: string;
name: string;
slug: string;
isOnline?: boolean;
timezone: string;
cameras: string;
online: string;
};
export function StoreTable({
companyId,
stores,
}: {
companyId: string;
stores: AdminStore[];
}) {
const columns: TableColumn<StoreRow>[] = [
{
key: 'name',
header: 'Shop',
width: proportional(3),
renderCell: (row) => (
<Link href={adminHref.store(companyId, row.id)}>
<Text size="sm" weight="medium">
{row.name}
</Text>
</Link>
),
},
{
key: 'isOnline',
header: 'Status',
width: proportional(1),
renderCell: (row) =>
row.isOnline === undefined ? (
<Text size="sm">{DASH}</Text>
) : (
<CameraStatus status={row.isOnline ? 'online' : 'offline'} />
),
},
{key: 'timezone', header: 'Timezone', width: proportional(2)},
{key: 'cameras', header: 'Cameras', width: proportional(1), align: 'end'},
{key: 'online', header: 'Online', width: proportional(1), align: 'end'},
];
const rows: StoreRow[] = stores.map((s) => ({
id: s.id,
name: s.name || s.slug,
slug: s.slug,
isOnline: s.isOnline,
timezone: s.timezone ?? DASH,
cameras: s.cameras === undefined ? DASH : String(s.cameras),
online: s.camerasOnline === undefined ? DASH : String(s.camerasOnline),
}));
return (
<ResponsiveTable
data={rows}
columns={columns}
idKey="id"
primaryKey="name"
density="balanced"
/>
);
}
/* ── Cameras ─────────────────────────────────────────────────────────── */
const CAMERA_STATUS: Record<
@@ -131,66 +63,6 @@ export function CameraStatus({status}: {status: AdminCameraStatus}) {
);
}
type CameraRow = Record<string, unknown> & {
id: string;
name: string;
zone: string;
status: AdminCameraStatus;
lastSeen: string;
};
export function CameraTable({
companyId,
storeId,
cameras,
}: {
companyId: string;
storeId: string;
cameras: AdminCamera[];
}) {
const columns: TableColumn<CameraRow>[] = [
{
key: 'name',
header: 'Camera',
width: proportional(3),
renderCell: (row) => (
<Link href={adminHref.camera(companyId, storeId, row.id)}>
<Text size="sm" weight="medium">
{row.name}
</Text>
</Link>
),
},
{key: 'zone', header: 'Location', width: proportional(2)},
{
key: 'status',
header: 'Status',
width: proportional(1),
renderCell: (row) => <CameraStatus status={row.status} />,
},
{key: 'lastSeen', header: 'Last seen', width: proportional(2), align: 'end'},
];
const rows: CameraRow[] = cameras.map((c) => ({
id: c.id,
name: c.name,
zone: c.zone ?? DASH,
status: c.status,
lastSeen: when(c.lastSeenAt),
}));
return (
<ResponsiveTable
data={rows}
columns={columns}
idKey="id"
primaryKey="name"
summaryKeys={['status', 'lastSeen']}
density="balanced"
/>
);
}
/* ── Events and alerts ───────────────────────────────────────────────── */
const SEVERITY: Record<
AdminSeverity,
{label: string; dot: 'error' | 'warning' | 'neutral'}