33 lines
3.3 KiB
React
33 lines
3.3 KiB
React
import React,{useEffect,useRef} from 'react';
|
|
|
|
const sections = {
|
|
human_resources:['human_resources'],
|
|
commercial:['services','billing','billing_support'], purchasing:['purchasing'], stock:['stock'],
|
|
workshop:['workshop'], finance:['treasury','receivables','costs'], accounting:['accounting'],
|
|
};
|
|
export function moduleGroups(groups, module) {
|
|
if(!sections[module])return [];
|
|
const own=groups.filter(g => sections[module].includes(g.id));
|
|
if(['commercial','human_resources'].includes(module))return own;
|
|
const shared=groups.flatMap(g=>g.items).filter(i=>['clients','services','service_drafts','billing_drafts'].includes(i.id));
|
|
return shared.length?[...own,{id:'shared_records',label:'Cadastros e rascunhos do módulo',items:shared}]:own;
|
|
}
|
|
export function moduleFunctionAllowed(context,groups,module,id){return Boolean(context?.modules?.some(m=>m.id===module)&&(id==='home'||moduleGroups(groups,module).some(g=>g.items.some(i=>i.id===id))));}
|
|
|
|
export default function ModuleNavigation({groups, context, page, navigate, openPage, user, busy, logout}) {
|
|
const active=context?.modules?.find(m=>m.id===context.module_id);
|
|
const menu=useRef(null);
|
|
useEffect(()=>{const close=e=>{if(!menu.current?.contains(e.target))for(const d of menu.current?.querySelectorAll('details[open]')??[])d.open=false;};window.addEventListener('pointerdown',close);return()=>window.removeEventListener('pointerdown',close);},[]);
|
|
const choose=(event,module,id)=>{event.currentTarget.closest('details').open=false;openPage(module,id);};
|
|
return <div className="module-navigation">
|
|
<div className="module-topbar"><button className="topbar-brand" onClick={()=>navigate('home')}>TEMPO <span>SGF</span></button>
|
|
<nav aria-label="Opções gerais"><button aria-current={page==='home'?'page':undefined} onClick={()=>navigate('home')}>Início</button>{groups.find(g=>g.id==='admin')?.items.map(i=><button key={i.id} aria-current={page===i.id?'page':undefined} onClick={()=>navigate(i.id)}>{i.label}</button>)}</nav>
|
|
<div className="topbar-account"><strong>{user.name}</strong>{context.single_installation&&<a href="/sgf">Trocar função QA</a>}<button disabled={busy} onClick={logout}>Sair</button></div>
|
|
</div>
|
|
<nav ref={menu} className="module-menu module-dropdowns" aria-label="Módulos e funções" onKeyDown={event=>{if(event.key==='Escape'){const d=event.target.closest('details');if(d){d.open=false;d.querySelector('summary')?.focus();}}}}>
|
|
{context?.modules?.map(module=><details key={module.id} name="sgf-modules" className={active?.id===module.id?'active-module':''}><summary aria-current={active?.id===module.id?'true':undefined}>{module.label}<span aria-hidden="true">▾</span></summary><div aria-label={`Funções de ${module.label}`}><p className="module-dropdown-title">{module.label}</p>{moduleGroups(groups,module.id).map(group=><section key={group.id}><h2>{group.label}</h2>{group.items.map(item=><button key={item.id} disabled={busy} aria-current={active?.id===module.id&&page===item.id?'page':undefined} onClick={event=>choose(event,module.id,item.id)}>{item.label}</button>)}</section>)}</div></details>)}
|
|
{!context?.modules?.length&&<span>Sem módulos autorizados neste contexto.</span>}
|
|
</nav>
|
|
</div>;
|
|
}
|