Stores, Team and Account run against the platform, not a mock
Stores: each shop's health in one line (offline, losing visits, camera trouble, faces too poor - in severity order, one verdict), its cameras as pictures with connection and 'proven to recognise a face' as two different claims, add/edit/remove camera with the make picker, test connection and placement checks claimed by the shop PC, and the enrolment code a new shop PC types. Team: create an account (password shown once), invite (code shown once), change role, remove access, reset password, revoke pending invitations - with the rank rules the server enforces mirrored in what the form offers. Account: who you are and every device signed in, with 'sign out' per device and everywhere else. Gone: StoreManagement, SecurityManager and ProfileForm that rendered hard-coded arrays, the Business form with no backend, the /api/stores route nothing served, and the cascading account menu's dead links. Two things found by using the camera form, not by tests: Chrome filled the operator's own email into 'camera username', and the first camera saved with a password and no username because autofill wrote to the input without React seeing it. The dialog sets autocomplete on the real inputs and reads the credential fields from the DOM at submit. Every route was exercised against production before this commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KGcjxF1cNLcuwc3DAPcnfj
This commit is contained in:
@@ -59,11 +59,12 @@ export function isBranch(row: AccountRowSpec): row is AccountBranch {
|
||||
* it is grouped by what it is rather than stacked by what fit.
|
||||
*/
|
||||
export const ACCOUNT_ROOT_GROUPS: AccountRowSpec[][] = [
|
||||
// Flat: every row is a destination that exists. The cascading panels below
|
||||
// are unreachable from here and kept only until the menu is simplified.
|
||||
[
|
||||
{label: 'Settings', icon: ICONS.settings, panel: 'settings'},
|
||||
{label: 'Profile', icon: ICONS.profile, panel: 'profile'},
|
||||
{label: 'Language', icon: ICONS.language, panel: 'language'},
|
||||
{label: 'Help', icon: ICONS.help, panel: 'help'},
|
||||
{label: 'Account & devices', icon: ICONS.profile, href: '/settings'},
|
||||
{label: 'Team', icon: ICONS.staff, href: '/settings/team'},
|
||||
{label: 'Keyboard shortcuts', icon: ICONS.keyboard, action: 'shortcuts'},
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -121,14 +122,7 @@ export const ACCOUNT_PANELS: Record<AccountPanelId, AccountPanel> = {
|
||||
profile: {
|
||||
title: 'Profile',
|
||||
rows: [
|
||||
{label: 'Business Details', icon: ICONS.business, href: '/settings'},
|
||||
{label: 'Subscription', icon: ICONS.billing, href: '/settings/billing'},
|
||||
{label: 'Activity', icon: ICONS.analytics, href: '/activity'},
|
||||
// Devices and Sessions are two views of the same Security screen today.
|
||||
// They stay two rows because they are two questions a merchant asks;
|
||||
// when Security splits into tabs, only the href moves.
|
||||
{label: 'Devices', icon: ICONS.security, href: '/settings/security'},
|
||||
{label: 'Sessions', icon: ICONS.sessions, href: '/settings/security'},
|
||||
{label: 'Account & devices', icon: ICONS.profile, href: '/settings'},
|
||||
],
|
||||
},
|
||||
language: {
|
||||
@@ -137,7 +131,7 @@ export const ACCOUNT_PANELS: Record<AccountPanelId, AccountPanel> = {
|
||||
{
|
||||
label: 'Language settings',
|
||||
icon: ICONS.preferences,
|
||||
href: '/settings/preferences',
|
||||
href: '/settings',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user