Compare commits

..

1 Commits

Author SHA1 Message Date
Stockboy Steve c7b96eebc4 feat(GRO-2513): gate Settings nav+route to manager/super-user, eliminate groomer 403
CI / Test (pull_request) Successful in 22s
CI / Lint & Typecheck (pull_request) Successful in 30s
CI / Build & Push Docker Image (pull_request) Successful in 46s
- App.tsx AdminLayout: fetch /api/staff/me on mount, filter NAV_LINKS so
  Settings only appears for role=manager or isSuperUser (fail-closed while
  loading). Guard /admin/settings route to redirect non-managers to /admin.
- Settings.tsx: replace parallel-fire useEffects with a single sequential
  flow — fetch /api/staff/me first, then only call /api/admin/settings for
  managers/super-users and /api/admin/auth-provider for super-users only.
  Groomers/receptionists never trigger the 403.
- UAT_PLAYBOOK.md §5.14: updated with role-gated test cases (TC-WEB-5.14.1–8)
  covering manager-sees-tab, groomer-no-tab, direct-URL redirect, zero-403,
  and shared-endpoint regression.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-25 01:56:23 +00:00
5 changed files with 4 additions and 32 deletions
+1 -11
View File
@@ -5,14 +5,4 @@ node_modules/
dist/
playwright-report/
test-results/
*.log
# Agent runtime artifacts — never commit
.gh-token
*.gh-token
**/.gh-token
.config/gh/
**/.config/gh/
**/AGENT_HOME/**
$AGENT_HOME/**
.claude/
.codex/
*.log
-9
View File
@@ -320,15 +320,6 @@ the seeded UAT customer (`uat-customer@groombook.dev`), not just unit-rendered.
| TC-WEB-5.16.2 | PWA install prompt | Load app on supported browser | Install prompt appears when criteria met |
| TC-WEB-5.16.3 | Touch interactions | Use touch gestures on mobile | All interactions work with touch input |
#### 5.16a Portal Tab Rows — Mobile Overflow (GRO-730 / GRO-1026)
| # | Scenario | Steps | Expected |
|---|----------|-------|----------|
| TC-WEB-5.16.4 | My Pets tab row — horizontal scroll, no visible scrollbar | Sign in as customer → My Pets. Set viewport to 390px. If 3+ pets are seeded, the pet-selector row overflows. | Pet selector row scrolls horizontally; native scrollbar is **not** visible (`scrollbar-width: none` / `scrollbar-hide` applied). |
| TC-WEB-5.16.5 | My Pets section tab row — no visible scrollbar | On the same My Pets view, observe the tabs row (Basic Info / Medical / Grooming / History). | Tabs row scrolls horizontally when needed; native scrollbar is not visible. |
| TC-WEB-5.16.6 | Billing/Payments tab row — no wrap, no visible scrollbar | Sign in as customer → Billing/Payments at 390px. | Tab row (Invoices / Payment Methods / Packages) does **not** wrap to a second line; scrolls horizontally if needed; native scrollbar not visible. |
| TC-WEB-5.16.7 | Desktop — no visual regression | Open My Pets and Billing/Payments at ≥1024px. | No layout change; tab rows display identically to before the fix. |
### 5.17 Error & Empty States
| # | Scenario | Steps | Expected |
-9
View File
@@ -78,15 +78,6 @@ input:focus, select:focus, textarea:focus {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
}
/* ─── Scrollbar hide utility ─── */
.scrollbar-hide {
scrollbar-width: none;
-ms-overflow-style: none;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
/* ─── Scrollbar polish ─── */
::-webkit-scrollbar {
width: 6px;
+1 -1
View File
@@ -130,7 +130,7 @@ function BillingPaymentsInner({ sessionId, readOnly }: BillingPaymentsProps) {
</div>
)}
<div className="flex gap-2 overflow-x-auto scrollbar-hide">
<div className="flex gap-2 flex-wrap">
{([
{ id: "invoices" as const, label: "Invoices", icon: DollarSign },
{ id: "payment" as const, label: "Payment Methods", icon: CreditCard },
+2 -2
View File
@@ -145,7 +145,7 @@ export function PetProfiles({ sessionId, readOnly }: Props) {
return (
<div className="space-y-6">
{/* Pet Selector */}
<div className="flex gap-3 overflow-x-auto pb-1 scrollbar-hide">
<div className="flex gap-3 overflow-x-auto pb-1">
{pets.map(p => (
<button
key={p.id}
@@ -191,7 +191,7 @@ export function PetProfiles({ sessionId, readOnly }: Props) {
)}
{/* Tabs */}
<div className="flex gap-1 bg-white rounded-xl border border-stone-200 p-1 overflow-x-auto scrollbar-hide">
<div className="flex gap-1 bg-white rounded-xl border border-stone-200 p-1 overflow-x-auto">
{([
{ id: "info", label: "Basic Info", icon: PawPrint },
{ id: "medical", label: "Medical", icon: Heart },