1import {href,demo,offline,environment} from './api.js'; 2import {brand,icon,e,demoBanner,safeURL} from './ui.js'; 3import {environmentLabel,productionNotice} from './environment.js'; 4import {pageNames} from './routes.js'; 5import {isSport,clubWords} from './organization.js'; 6 7export const pageSkeleton=()=>`<div class="loading page-skeleton"><p class="loading-label">Jullie gegevens ophalenâ¦</p><div class="skeleton skeleton-title" aria-hidden="true"></div><div class="metrics company-metrics" aria-hidden="true"><div class="skeleton"></div><div class="skeleton"></div><div class="skeleton"></div><div class="skeleton"></div></div><div class="skeleton big" aria-hidden="true"></div></div>`; 8function navigation(company){ 9 const w=clubWords(company),groups=[['Jullie resultaat',[['overzicht','Overzicht','grid'],['resultaten','Resultaten','chart'],['challenges','Challenges','flag'],['gouden-uiltjes','Gouden Uiltjes','trophy']]],['Jullie organisatie',[['deelnemers','Deelnemers','users'],['teams','Teams & locaties','team'],['bedrijf',w.profile,'building']]]]; 10 return groups.map(([title,items])=>`<p class="nav-group">${title}</p><nav class="nav-links" aria-label="${title}">${items.filter(([path])=>path!=='gouden-uiltjes'||!isSport(company)).map(([path,label,name])=>`<a data-nav data-page="/${path}" href="${href('/'+path)}">${icon(name)}${label}</a>`).join('')}</nav>`).join(''); 11} 12export function shellMarkup(){ 13 return `<aside class="sidebar" id="sidebar" aria-label="Clubdashboard"><a class="brand-link" data-nav href="${href('/overzicht')}">${brand()}</a><div class="company-switch" aria-busy="true"><div class="company-avatar identity-placeholder" aria-hidden="true"></div><div class="company-identity"><strong class="identity-placeholder" data-company-name><span class="sr-only">Clubgegevens laden</span></strong><small>Clubbeheerder</small></div></div><div id="sidebar-navigation"><div class="nav-placeholder" aria-hidden="true"></div></div><div class="sidebar-bottom"><a data-nav class="button quiet" href="${href('/uitleg')}">${icon('info')} Uitleg & hulp</a><button class="button quiet" data-action="logout">${icon('logout')} ${demo?'Naar inloggen':'Uitloggen'}</button><p class="sidebar-note" data-sidebar-note>ReisWijs<br>${demo?'Ontwerpcontrole met voorbeeldgegevens':environmentLabel(environment)}</p></div></aside><button class="menu-shade" data-action="close-menu" aria-label="Menu sluiten" hidden></button><header class="topbar"><button class="icon-button mobile-only" data-action="menu" aria-label="Navigatie openen" aria-expanded="false" aria-controls="sidebar">${icon('menu')}</button><div class="breadcrumb"><span data-dashboard-name>Clubdashboard</span><span class="slash">/</span><strong data-page-title></strong></div><div class="topbar-actions">${demo||environmentLabel(environment)?`<span class="environment">${demo?'Voorbeeldmodus':environmentLabel(environment)}</span>`:''}<a data-nav data-invite class="button secondary" href="${href('/uitnodigen')}" hidden>${icon('plus')}<span>Uitnodigen</span></a></div></header><main class="page" id="main" tabindex="-1"><div class="page-inner">${demoBanner({demo,offline,loginHref:href('/login')})}${productionNotice(environment,demo)}<p id="page-status" class="page-status" role="status" aria-live="polite"></p><div id="page-refresh-error" role="alert" hidden></div><div id="page-content"></div></div></main>`; 14} 15 16// Update the existing shell in place. Profile, navigation, mobile menu and 17// keyboard focus are never reset just because page content is loading. 18export function updateShell(app,path,profile){ 19 const c=profile?.company,w=c?clubWords(c):{dashboard:'Clubdashboard',profile:'Clubprofiel',invite:'Uitnodigen'}; 20 const title=path==='/bedrijf'?w.profile:path==='/uitnodigen'?w.invite:pageNames[path.split('/')[1]]||w.dashboard; 21 app.querySelector('[data-dashboard-name]').textContent=w.dashboard; 22 app.querySelector('[data-page-title]').textContent=title; 23 const invite=app.querySelector('[data-invite]');invite.hidden=!c||['/instellen','/uitnodigen','/overzicht'].includes(path);invite.querySelector('span').textContent=w.invite; 24 if(c){ 25 const name=app.querySelector('[data-company-name]');name.classList.remove('identity-placeholder');name.textContent=c.name||'Jullie club';name.title=c.name||'Jullie club'; 26 const avatar=app.querySelector('.company-avatar'),url=safeURL(c.logoImageUrl),identity=url||c.name||''; 27 if(avatar.dataset.identity!==identity){avatar.innerHTML=url?`<img src="${e(url)}" alt="" width="40" height="40">`:e((c.name||'C').slice(0,1).toUpperCase());avatar.dataset.identity=identity;avatar.classList.remove('identity-placeholder');} 28 app.querySelector('.company-switch').setAttribute('aria-busy','false'); 29 app.querySelector('#sidebar').setAttribute('aria-label',w.dashboard); 30 app.querySelector('[data-sidebar-note]').innerHTML=`ReisWijs · voor ${w.sport?'sportclubs':'bedrijven'}<br>${demo?'Ontwerpcontrole met voorbeeldgegevens':environmentLabel(environment)}`; 31 const nav=app.querySelector('#sidebar-navigation'),kind=path==='/instellen'?'setup':w.sport?'sport':'company'; 32 if(nav.dataset.kind!==kind){nav.innerHTML=kind==='setup'?'<p class="sidebar-note">Eerst jullie indeling en uitstraling. Daarna kunnen jullie samen op weg.</p>':navigation(c);nav.dataset.kind=kind;} 33 } 34 app.querySelectorAll('[data-page]').forEach(link=>
34{const active=path===link.dataset.page||path.startsWith(link.dataset.page+'/');active?link.setAttribute('aria-current','page'):link.removeAttribute('aria-current');}); 35 document.title=title+' · ReisWijs'; 36}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.