Add main menu page with role-based modules (#7)

- `/` is now the main menu; orders/receipts page moved to `/receipts`
- Module registry (features/menu/modules.ts) drives both the menu tiles
  and route guards (ModuleRoute); admin sees every module
- Menu: module search with Ctrl+K, profile with logout, responsive grid,
  palette matching the login page
- «← Головне меню» link on receipts and cash registers pages;
  «Каси» moved from the receipts toolbar into the menu

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-25 17:11:57 +03:00
co-authored by Claude Opus 5.5
parent 0ba2ca01c4
commit 8fffdc3ce6
11 changed files with 728 additions and 22 deletions
+8 -13
View File
@@ -5,6 +5,7 @@ import { Link } from 'react-router-dom'
import { deleteOrder } from '@/api/orders'
import { cancelReceipt, createReceipts } from '@/api/receipts'
import '@/pages/DashboardPage.css'
import { ROLE_LABEL } from '@/features/auth/roles'
import { useAuth } from '@/features/auth/useAuth'
import { OrderDetailModal } from '@/features/orders/OrderDetailModal'
import type { Order, OrderTab } from '@/features/orders/types'
@@ -13,12 +14,6 @@ import { defaultPrepayment, prepaymentMatches, toKopecks } from '@/features/rece
import { CANCELLABLE, RECEIPT_STATUS } from '@/features/receipts/types'
import type { ReceiptRequestItem } from '@/features/receipts/types'
const ROLE_LABEL: Record<string, string> = {
admin: 'Адміністратор',
cashier: 'Касир',
viewer: 'Спостерігач',
}
const TABS: { key: OrderTab; label: string }[] = [
{ key: 'no_receipt', label: 'Без чека' },
{ key: 'has_receipt', label: 'Виписані чеки' },
@@ -174,10 +169,15 @@ export function DashboardPage() {
return (
<div className="dashboard-shell">
<header className="dashboard-topbar">
<span className="dashboard-brand">Assistant System</span>
<div className="dashboard-topbar-start">
<Link to="/" className="orders-link-btn">
← Головне меню
</Link>
<span className="dashboard-brand">Assistant System</span>
</div>
<div className="dashboard-user">
<span>{user?.full_name}</span>
<span className="dashboard-role">{user ? (ROLE_LABEL[user.role] ?? user.role) : ''}</span>
<span className="dashboard-role">{user ? ROLE_LABEL[user.role] : ''}</span>
<button type="button" className="dashboard-logout" onClick={() => void logout()}>
Вийти
</button>
@@ -188,11 +188,6 @@ export function DashboardPage() {
<div className="orders-toolbar">
<h2>Замовлення</h2>
<div className="orders-toolbar-actions">
{user?.role === 'admin' && (
<Link to="/cash-registers" className="orders-link-btn">
Каси
</Link>
)}
{tab === 'no_receipt' && canFiscalize && (
<button
type="button"