import { router } from 'expo-router'; import { Pressable, Text, View } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import type { ObjectCategory, PermissionRight } from '@siop/shared'; import { useMe } from '@/auth/session'; import { estRoleTerrain } from '@/auth/roles'; import { usePermissions } from '@/auth/use-permissions'; import { EnteteTabs } from '@/composants/ui'; import { useTokens, type Tokens } from '@/theme/tokens'; /** Menu — maquette « mobile ouvert à tous les rôles », écran 3 : reprend à * l'identique les 4 groupes et l'ordre de la sidebar web (Exploitation / * Parc / Ressources / Pilotage, coquille.tsx), filtrés par LA MÊME matrice * (D2 — aucune règle de droit nouvelle). Un groupe sans aucun lien visible * est masqué en entier (D3) : l'écran est petit, un intitulé vide n'aide * personne. Ce que « Ma journée »/« Préventif » couvrent déjà pour le * Technicien n'est pas dupliqué ici. */ interface LienMenu { libelle: string; permission: [ObjectCategory, PermissionRight]; ico: string; cacheEnTerrain?: boolean; // déjà couvert par un onglet terrain dédié route?: string; aVenir?: string; // detail affiché sur l'écran « à venir » } const GROUPES: { titre: string; liens: LienMenu[] }[] = [ { titre: 'Exploitation', liens: [ { libelle: 'Ordres de travail', ico: '☰', permission: ['WORK_ORDERS', 'view'], cacheEnTerrain: true, route: '/(tabs)/ot' }, { libelle: 'Demandes', ico: '✎', permission: ['REQUESTS', 'view'], route: '/demandes' }, { libelle: 'Préventif', ico: '✓', permission: ['WORK_ORDERS', 'view'], cacheEnTerrain: true, aVenir: 'Les grilles préventives pour les rôles de gestion arrivent dans une prochaine étape — le Technicien les a déjà dans son onglet dédié.' }, ], }, { titre: 'Parc', liens: [ { libelle: 'Ascenseurs', ico: '▣', permission: ['ASSETS', 'view'], aVenir: 'La liste du parc en mobilité arrive dans une prochaine étape — en attendant, le Scanner et les fiches OT y mènent déjà.' }, { libelle: 'Sites', ico: '◫', permission: ['LOCATIONS', 'view'], aVenir: 'La liste des sites en mobilité arrive dans une prochaine étape.' }, { libelle: 'Catégories', ico: '▤', permission: ['SETTINGS', 'view'], aVenir: 'L’administration des catégories reste sur le grand écran pour l’instant.' }, ], }, { titre: 'Ressources', liens: [ { libelle: 'Stock & achats', ico: '◔', permission: ['PARTS', 'view'], aVenir: 'Le stock et les bons de commande en mobilité arrivent dans une prochaine étape.' }, { libelle: 'Tiers', ico: '⇄', permission: ['PURCHASE_ORDERS', 'view'], aVenir: 'Fournisseurs et clients restent sur le grand écran pour l’instant.' }, { libelle: 'Fichiers', ico: '▧', permission: ['ASSETS', 'view'], aVenir: 'La bibliothèque documentaire reste sur le grand écran pour l’instant.' }, ], }, { titre: 'Pilotage', liens: [ { libelle: 'Statistiques', ico: '◈', permission: ['ANALYTICS', 'view'], aVenir: 'Les statistiques en mobilité arrivent dans une prochaine étape.' }, { libelle: 'Assistant', ico: '✦', permission: ['WORK_ORDERS', 'view'], aVenir: 'L’assistant IA reste sur le grand écran et la clôture mobile pour l’instant.' }, { libelle: 'Personnes & équipes', ico: '◎', permission: ['PEOPLE_TEAMS', 'view'], aVenir: 'La gestion des personnes et équipes en mobilité arrive dans une prochaine étape.' }, ], }, ]; export default function PageMenu() { const t = useTokens(); const { data: me } = useMe(); const { can } = usePermissions(); const terrain = estRoleTerrain(me?.role.name); const groupesVisibles = GROUPES.map((g) => ({ ...g, liens: g.liens.filter( ({ permission, cacheEnTerrain }) => can(...permission) && !(cacheEnTerrain && terrain), ), })).filter((g) => g.liens.length > 0); return ( Menu {groupesVisibles.length === 0 ? ( Rien d'autre accessible à votre rôle ici. ) : null} {groupesVisibles.map((g) => ( {g.titre} {g.liens.map((lien) => ( ))} ))} ); } function LigneMenu({ lien, t }: { lien: LienMenu; t: Tokens }) { const aller = () => { if (lien.route) { router.push(lien.route as never); } else { router.push({ pathname: '/a-venir', params: { titre: lien.libelle, detail: lien.aVenir ?? '' } }); } }; return ( {lien.ico} {lien.libelle} ); }