fix(nav): header "Turni"→"Turnet" (plural); remove duplicate Setup shifts tab
The header shift link used nav.shift (singular: Turni/Shift) but points at the /shift HISTORY hub, so it now uses nav.shifts (plural: Turnet/Shifts). The Setup "Turnet" tab was a duplicate — /setup/shifts and the standalone /shift both rendered ShiftsHistory. Removed the Setup tab + its child route; /setup/shifts redirects to /shift for old bookmarks, and the operator-landing fallback (a shift:read user opening /setup) now points at /shift. The orphaned nav.shift key is left in both catalogs (harmless). Verified at runtime (Playwright): header reads Kabina·Turnet·Abonimet·Konfigurimi, Setup no longer lists Turnet, /setup/shifts redirects to /shift. build+lint 14/14. Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
+7
-16
@@ -85,7 +85,6 @@ function SetupLayout() {
|
|||||||
{show("site:read") && <SetupTab to="/setup/site" label={t("nav.site")} />}
|
{show("site:read") && <SetupTab to="/setup/site" label={t("nav.site")} />}
|
||||||
{show("user:read") && <SetupTab to="/setup/users" label={t("nav.users")} />}
|
{show("user:read") && <SetupTab to="/setup/users" label={t("nav.users")} />}
|
||||||
{show("role:read") && <SetupTab to="/setup/roles" label={t("nav.roles")} />}
|
{show("role:read") && <SetupTab to="/setup/roles" label={t("nav.roles")} />}
|
||||||
{show("shift:read") && <SetupTab to="/setup/shifts" label={t("nav.shifts")} />}
|
|
||||||
{show("log:read") && <SetupTab to="/setup/logs" label={t("nav.logs")} />}
|
{show("log:read") && <SetupTab to="/setup/logs" label={t("nav.logs")} />}
|
||||||
</nav>
|
</nav>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
@@ -369,7 +368,7 @@ function RootLayout() {
|
|||||||
<span className="text-sm font-bold uppercase tracking-widest text-term-amber">▮ Parking</span>
|
<span className="text-sm font-bold uppercase tracking-widest text-term-amber">▮ Parking</span>
|
||||||
<nav className="flex items-center gap-1">
|
<nav className="flex items-center gap-1">
|
||||||
<NavLink to="/booth" label={t("nav.booth")} />
|
<NavLink to="/booth" label={t("nav.booth")} />
|
||||||
<NavLink to="/shift" label={t("nav.shift")} />
|
<NavLink to="/shift" label={t("nav.shifts")} />
|
||||||
{/* Subscriptions — a standalone section (Abonimet / Planet / Lab tarife).
|
{/* Subscriptions — a standalone section (Abonimet / Planet / Lab tarife).
|
||||||
Shown if the user can reach ANY of its tabs. */}
|
Shown if the user can reach ANY of its tabs. */}
|
||||||
{(show("subscription:read") || show("subscription:plan") || show("tariff:read")) && (
|
{(show("subscription:read") || show("subscription:plan") || show("tariff:read")) && (
|
||||||
@@ -441,6 +440,7 @@ const legacyRedirects = (
|
|||||||
["/setup/subscriptions", "/subscriptions"],
|
["/setup/subscriptions", "/subscriptions"],
|
||||||
["/setup/plans", "/subscriptions/plans"],
|
["/setup/plans", "/subscriptions/plans"],
|
||||||
["/setup/tariff-lab", "/subscriptions/tariff-lab"],
|
["/setup/tariff-lab", "/subscriptions/tariff-lab"],
|
||||||
|
["/setup/shifts", "/shift"],
|
||||||
] as const
|
] as const
|
||||||
).map(([from, to]) =>
|
).map(([from, to]) =>
|
||||||
createRoute({
|
createRoute({
|
||||||
@@ -482,14 +482,15 @@ function requirePerm(perm: Permission) {
|
|||||||
|
|
||||||
// The Setup tabs in display order, each with the permission its screen needs. Used
|
// The Setup tabs in display order, each with the permission its screen needs. Used
|
||||||
// to land a user on the FIRST tab they may see when they open /setup without
|
// to land a user on the FIRST tab they may see when they open /setup without
|
||||||
// `site:update` (e.g. an operator who only has shift:read → goes to /setup/shifts).
|
// `site:update` (e.g. an operator who only has shift:read → goes to the standalone
|
||||||
|
// /shift hub, which is no longer a Setup tab).
|
||||||
const SETUP_TABS: { to: string; perm: Permission }[] = [
|
const SETUP_TABS: { to: string; perm: Permission }[] = [
|
||||||
{ to: "/setup", perm: "site:update" },
|
{ to: "/setup", perm: "site:update" },
|
||||||
{ to: "/setup/tariff", perm: "tariff:read" },
|
{ to: "/setup/tariff", perm: "tariff:read" },
|
||||||
{ to: "/setup/site", perm: "site:read" },
|
{ to: "/setup/site", perm: "site:read" },
|
||||||
{ to: "/setup/users", perm: "user:read" },
|
{ to: "/setup/users", perm: "user:read" },
|
||||||
{ to: "/setup/roles", perm: "role:read" },
|
{ to: "/setup/roles", perm: "role:read" },
|
||||||
{ to: "/setup/shifts", perm: "shift:read" },
|
{ to: "/shift", perm: "shift:read" },
|
||||||
{ to: "/setup/logs", perm: "log:read" },
|
{ to: "/setup/logs", perm: "log:read" },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -583,17 +584,8 @@ const rolesRoute = createRoute({
|
|||||||
return <RolesManager user={user} />;
|
return <RolesManager user={user} />;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// Shift history. Gated by shift:read (operators have it) — the SERVER scopes the
|
// (Shift history lives at the standalone /shift route — see shiftRoute. It was
|
||||||
// data: operators see only their own; shift:cash holders see all + can filter.
|
// removed as a Setup tab; /setup/shifts redirects there for old bookmarks.)
|
||||||
const shiftsHistoryRoute = createRoute({
|
|
||||||
getParentRoute: () => setupRoute,
|
|
||||||
path: "shifts",
|
|
||||||
beforeLoad: ({ context }) => requirePerm("shift:read")(context),
|
|
||||||
component: function ShiftsHistoryRoute() {
|
|
||||||
const { user } = rootRoute.useRouteContext();
|
|
||||||
return <ShiftsHistory user={user} />;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Diagnostic logs. Gated by log:read (an admin/diagnostic permission).
|
// Diagnostic logs. Gated by log:read (an admin/diagnostic permission).
|
||||||
const logsRoute = createRoute({
|
const logsRoute = createRoute({
|
||||||
@@ -619,7 +611,6 @@ const routeTree = rootRoute.addChildren([
|
|||||||
siteRoute,
|
siteRoute,
|
||||||
usersRoute,
|
usersRoute,
|
||||||
rolesRoute,
|
rolesRoute,
|
||||||
shiftsHistoryRoute,
|
|
||||||
logsRoute,
|
logsRoute,
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -1280,3 +1280,10 @@ Legacy /setup/subscriptions, /setup/plans, /setup/tariff-lab redirect to the new
|
|||||||
/subscriptions→/setup redirect was removed (it's a real route now). Verified at runtime via Playwright
|
/subscriptions→/setup redirect was removed (it's a real route now). Verified at runtime via Playwright
|
||||||
(header order, the 3 sub-tabs, Setup no longer shows them, /setup/subscriptions redirects). The Tariff
|
(header order, the 3 sub-tabs, Setup no longer shows them, /setup/subscriptions redirects). The Tariff
|
||||||
COMPOSER stays in Setup; only the Tariff LAB simulator moved. build+lint 14/14.
|
COMPOSER stays in Setup; only the Tariff LAB simulator moved. build+lint 14/14.
|
||||||
|
|
||||||
|
## [2026-06-21] fix | Header "Turni"→"Turnet" (plural); drop the duplicate Setup shifts tab
|
||||||
|
The header shift link was nav.shift (singular: Turni/Shift) but points at the /shift HISTORY hub →
|
||||||
|
relabelled to nav.shifts (plural: Turnet/Shifts). Removed the duplicate "Turnet" tab from Setup (the
|
||||||
|
/setup/shifts route + tab rendered the SAME ShiftsHistory as the standalone /shift). /setup/shifts now
|
||||||
|
redirects to /shift; the operator-landing fallback (shift:read user opening /setup) points at /shift.
|
||||||
|
nav.shift key left in the catalogs (now orphaned, harmless). Verified at runtime. build+lint 14/14.
|
||||||
|
|||||||
Reference in New Issue
Block a user