2.9 KiB
Navigation
The sidebar (components/ui/app-sidebar.tsx) is the primary navigation. It is a shadcn Sidebar with a header (brand) and two collapsible category groups. Menu items are data-driven from a categories array and filtered by the user's permissions / admin flag.
Sidebar header
Brand block at the top: a bordered, centered, uppercase title with title-bg background (the "SAR LINK" branding).
Menu tree
Group: MENU (all users)
| Label | Route | Icon (lucide) | Permission (perm_identifier) |
|---|---|---|---|
| Devices | /devices?page=1 |
Smartphone |
device |
| Parental Control | /parental-control?page=1 |
CreditCard |
device |
| Subscriptions | /payments?page=1 |
CreditCard |
payment |
| Top Ups | /top-ups?page=1 |
BadgePlus |
topup |
| Transaction History | /wallet |
Wallet2Icon |
wallet transaction |
| Agreements | /agreements |
Handshake |
device |
Group: ADMIN CONTROL (admin only)
| Label | Route | Icon (lucide) | Permission (perm_identifier) |
|---|---|---|---|
| Users | /users |
UsersRound |
device |
| User Devices | /user-devices |
MonitorSpeaker |
device |
| User Payments | /user-payments |
Coins |
payment |
| User Topups | /user-topups |
Coins |
topup |
| Price Calculator | /price-calculator |
Calculator |
device |
Note: the
Price Calculatorsits underADMIN CONTROLin the source array, so it is only shown to admins even though the page itself is generic.
Visibility logic
Computed in app-sidebar.tsx from the current user (now read from userAtom; previously getServerSession):
- If
user.is_admin→ show all categories and items. - Else →
- Drop the entire
ADMIN CONTROLcategory. - For remaining items, keep an item only if the user has a matching permission: the item's
perm_identifieris compared against the model name parsed from eachuser.user_permissions[].name(permission name split on spaces, model = parts from index 2 onward). - Drop any category left with zero visible children.
- Drop the entire
So a non-admin sees a subset of the MENU group based on granted permissions; the whole admin group is hidden.
Other navigation entry points
- Header account popover (
account-popver.tsx): links to View Profile (/profile) and Logout. - Header wallet button (
wallet.tsx): opens the top-up drawer (not a route). - Device cart (
device-cart.tsx): "Pay" routes to/devices-to-pay. - Root
/: redirects to/devices(authed) or/auth/signin(not authed). - Admin list rows: "Details" buttons link into
/users/[userId]/details,/devices/[deviceId],/payments/[paymentId],/top-ups/[topupId]. - Table pagination & filters: mutate URL query params (
?page=,?query=,?status=,?sortBy=…) vianuqs.
See routes.md for the full route list and [navigation gating] mirrors the admin route guards documented there.