fix
This commit is contained in:
@@ -14,14 +14,8 @@ component and look identical on screen, down to the heading. The only difference
|
||||
is the pathname, which is precisely the input this map takes.
|
||||
*/
|
||||
|
||||
/** The routes that must be able to answer, per workspace. */
|
||||
const MUST_HAVE_AN_AGENT = [
|
||||
'/admin/console',
|
||||
'/admin/sales',
|
||||
'/admin/inventory',
|
||||
'/store/console',
|
||||
'/store/sales',
|
||||
];
|
||||
/** Every platform page must be able to answer. */
|
||||
const MUST_HAVE_AN_AGENT = ['/nearle/stores', '/nearle/onboard/tenant', '/nearle/catalogue'];
|
||||
|
||||
test('every workspace that can answer, does', () => {
|
||||
for (const pathname of MUST_HAVE_AN_AGENT) {
|
||||
@@ -33,15 +27,31 @@ test('every workspace that can answer, does', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('the two console pages answer with the same agent', () => {
|
||||
// `/admin/console` and `/store/console` are the same page at two scopes. One
|
||||
// of them carrying an agent and the other not is the exact shape of the bug,
|
||||
// and it is invisible in the rendered output.
|
||||
const merchant = matchAssistantRoute('/admin/console').context;
|
||||
const branch = matchAssistantRoute('/store/console').context;
|
||||
test('every platform page answers with the platform agent', () => {
|
||||
// One agent here, not three. A platform account carries no tenant, so the
|
||||
// eight tools that read a shop's data refuse it — `platform` holds `help`
|
||||
// and nothing else. A page pointed at `console` or `orders` would accept a
|
||||
// question and answer "pick a shop first" to it.
|
||||
for (const pathname of MUST_HAVE_AN_AGENT) {
|
||||
assert.equal(
|
||||
matchAssistantRoute(pathname).context.agent,
|
||||
'platform',
|
||||
`${pathname} names an agent this console cannot use`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(branch.agent, merchant.agent);
|
||||
assert.equal(matchAssistantRoute('/store/sales').context.agent, 'orders');
|
||||
test('the merchant workspaces are not routes here', () => {
|
||||
// They moved out with the split. An entry left behind could never match —
|
||||
// these are not paths in this application — and would only ship merchant
|
||||
// copy to Nearle staff.
|
||||
for (const pathname of ['/admin/console', '/admin/sales', '/store/console', '/store/sales']) {
|
||||
assert.equal(
|
||||
matchAssistantRoute(pathname).key,
|
||||
undefined,
|
||||
`${pathname} is still in this console's route map`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('a page falls through to the fallback rather than to nothing', () => {
|
||||
@@ -55,10 +65,10 @@ test('a page falls through to the fallback rather than to nothing', () => {
|
||||
});
|
||||
|
||||
test('a deeper path still finds its page', () => {
|
||||
// `/admin/sales/4412` is still the Sales panel. Exact matching would drop the
|
||||
// agent the moment anybody opened a row.
|
||||
assert.equal(matchAssistantRoute('/admin/sales/4412').context.agent, 'orders');
|
||||
assert.equal(matchAssistantRoute('/store/console?branch=3').context.agent, 'console');
|
||||
// `/nearle/stores/1147` is still the Stores panel. Exact matching would drop
|
||||
// the agent the moment anybody opened a tenant.
|
||||
assert.equal(matchAssistantRoute('/nearle/stores/1147').context.agent, 'platform');
|
||||
assert.equal(matchAssistantRoute('/nearle/catalogue?brand=x').context.agent, 'platform');
|
||||
});
|
||||
|
||||
test('no key shadows another', () => {
|
||||
|
||||
@@ -95,158 +95,12 @@ export const CONTEXT: Record<
|
||||
],
|
||||
},
|
||||
|
||||
/* ── Store Admin ──────────────────────────────────────────────────────── */
|
||||
/* The merchant workspaces were here — `/admin/*` and `/store/*`, with the
|
||||
console, orders and inventory agents. They moved out with the split: those
|
||||
paths are not routes in this application, so the entries could never match
|
||||
and only shipped merchant copy to Nearle staff. They live in
|
||||
`nearle-console`. */
|
||||
|
||||
'/admin/console': {
|
||||
agent: 'console',
|
||||
page: 'Console',
|
||||
title: 'Across your branches',
|
||||
greeting: 'App sales, counter sales and imported bills are counted separately — they live in different ledgers.',
|
||||
reading: 'Would cover every branch — revenue by channel, stock health, till status and what is waiting on you.',
|
||||
prompts: [
|
||||
'Which branch is underperforming?',
|
||||
'Any tills not syncing?',
|
||||
'What needs my approval?',
|
||||
'Where is stock running out?',
|
||||
],
|
||||
},
|
||||
'/admin/sales': {
|
||||
agent: 'orders',
|
||||
page: 'Sales',
|
||||
title: 'Orders and deliveries',
|
||||
greeting: 'An app order and a counter bill are both sales, but only one of them has a delivery.',
|
||||
reading: 'Would cover orders, counter bills and delivery progress across your branches.',
|
||||
prompts: [
|
||||
'Why is the cancel rate high?',
|
||||
'Which orders are stuck?',
|
||||
'Compare online and counter sales',
|
||||
'What is out for delivery?',
|
||||
],
|
||||
},
|
||||
'/admin/inventory': {
|
||||
agent: 'inventory',
|
||||
page: 'Inventory',
|
||||
title: 'Catalogue and stock',
|
||||
greeting: 'A product in the store catalogue does not mean stock on the shelf — that takes an approved request.',
|
||||
reading: 'Would cover your catalogue, per-branch stock levels and the stock requests waiting on you.',
|
||||
prompts: [
|
||||
'What is waiting for approval?',
|
||||
'What is low or out of stock?',
|
||||
'What has run out completely?',
|
||||
'Which branch is waiting on most stock?',
|
||||
],
|
||||
},
|
||||
'/admin/users': {
|
||||
page: 'Users & access',
|
||||
title: 'Who can sign in',
|
||||
greeting: 'A till account and a console login are two different things — a cashier has no console access at all.',
|
||||
reading: 'Would cover your back-office directory and the till accounts at each branch.',
|
||||
prompts: [
|
||||
'What is the difference between the two?',
|
||||
'How do I add a cashier?',
|
||||
'Why can I not delete someone?',
|
||||
'Who is inactive?',
|
||||
],
|
||||
},
|
||||
'/admin/reports': {
|
||||
page: 'Reports',
|
||||
title: 'Revenue, sales and stock',
|
||||
greeting: 'Fast and slow movers are the two lists that change what you order next.',
|
||||
reading: 'Would cover revenue by channel and branch, product performance and stock movement.',
|
||||
prompts: [
|
||||
'Which products are slow moving?',
|
||||
'Compare my branches',
|
||||
'Online versus counter revenue',
|
||||
'What is my inventory worth?',
|
||||
],
|
||||
},
|
||||
|
||||
/* ── Store user ───────────────────────────────────────────────────────────
|
||||
*
|
||||
* One branch, fixed. The pages are largely the SAME components the merchant
|
||||
* sees — `/store/console` and `/admin/console` are both `ConsolePage` — so
|
||||
* the absence of these entries was invisible in the code and total in the
|
||||
* product: a store-manager got the fallback on every route, and the fallback
|
||||
* has no agent, so the composer was dead for that whole role no matter what
|
||||
* the deployment had configured.
|
||||
*
|
||||
* It stayed hidden because every test signed in as one of the other two
|
||||
* roles, and because `/admin/console` and `/store/console` look identical on
|
||||
* screen down to the heading.
|
||||
*
|
||||
* The wording differs from the merchant's on purpose. "Which branch is
|
||||
* underperforming?" is not a question a branch user can act on, and the
|
||||
* answers are scoped to their one branch by the session regardless — so the
|
||||
* chips say what that scope actually is rather than implying a choice.
|
||||
*/
|
||||
|
||||
'/store/console': {
|
||||
agent: 'console',
|
||||
page: 'Console',
|
||||
title: 'Your branch today',
|
||||
greeting: 'App sales, counter sales and imported bills are counted separately — they live in different ledgers.',
|
||||
reading: 'Would cover this branch — sales by channel, stock health, till status and what is waiting.',
|
||||
prompts: [
|
||||
'Any tills not syncing?',
|
||||
'Where is stock running out?',
|
||||
'What needs attention?',
|
||||
'How is today going?',
|
||||
],
|
||||
},
|
||||
'/store/sales': {
|
||||
agent: 'orders',
|
||||
page: 'Sales',
|
||||
title: 'Orders and deliveries',
|
||||
greeting: 'An app order and a counter bill are both sales, but only one of them has a delivery.',
|
||||
reading: 'Would cover this branch — orders, counter bills and delivery progress.',
|
||||
prompts: [
|
||||
'Which orders are stuck?',
|
||||
'What is out for delivery?',
|
||||
'Compare online and counter sales',
|
||||
'Why is the cancel rate high?',
|
||||
],
|
||||
},
|
||||
'/store/products': {
|
||||
// No agent, and not an oversight. The `inventory` agent carries
|
||||
// `approve_stock_request`, and whether a branch user may approve the stock
|
||||
// their own branch asked for is a question about who is allowed to spend,
|
||||
// not about which page this is. Until that is settled the page keeps the
|
||||
// prompts and loses the composer, which is the honest of the two.
|
||||
page: 'Products',
|
||||
title: 'Catalogue and stock',
|
||||
greeting: 'A product in the catalogue does not mean stock on the shelf — that takes an approved request.',
|
||||
reading: 'Would cover this branch — what is on the shelf and what has been asked for.',
|
||||
prompts: [
|
||||
'What is low or out of stock?',
|
||||
'What has run out completely?',
|
||||
'How do I request stock?',
|
||||
'Why is my request still pending?',
|
||||
],
|
||||
},
|
||||
'/store/reports': {
|
||||
page: 'Reports',
|
||||
title: 'Revenue, sales and stock',
|
||||
greeting: 'Fast and slow movers are the two lists that change what you order next.',
|
||||
reading: 'Would cover this branch — revenue by channel, product performance and stock movement.',
|
||||
prompts: [
|
||||
'Which products are slow moving?',
|
||||
'Online versus counter revenue',
|
||||
'What sold best this week?',
|
||||
'What is my stock worth?',
|
||||
],
|
||||
},
|
||||
'/store/staff': {
|
||||
page: 'Staff',
|
||||
title: 'Who can sign in',
|
||||
greeting: 'A till account and a console login are two different things — a cashier has no console access at all.',
|
||||
reading: 'Would cover the people at this branch and the till accounts they sign in with.',
|
||||
prompts: [
|
||||
'What is the difference between the two?',
|
||||
'How do I add a cashier?',
|
||||
'Why can I not delete someone?',
|
||||
'Who is inactive?',
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const FALLBACK: (typeof CONTEXT)[string] = {
|
||||
|
||||
Reference in New Issue
Block a user