Skip to content

Site Filtering

The topbar is the single source of truth for site selection across the entire application. The URL path includes the site code, and all pages react to site changes via a shared event system.

All pages follow the pattern /central/{site_code}/{page}. The site code in the URL is the primary source of truth:

https://fjzippin.com/central/elior-stmicrocrolles/home
https://fjzippin.com/central/elior-stmicrocrolles/operations
Variable / KeyDescription
window.FJ.sitesArray of all site objects fetched from /api/sites on page load
window.FJ.selectedSiteCurrent site code (e.g. “elior-stmicrocrolles”), updated on every site change
localStorage[“fj-topbar-site”]Persisted selected site code (survives page reloads)
Cookie fj-siteHTTP cookie with 1-year expiry (SameSite=Lax), used for server-side awareness

The site is resolved in this priority order:

  1. URL path — extract site code from /central/{site_code}/{page}
  2. localStorage — fallback to fj-topbar-site
  3. First available site — default if nothing is set

If the URL site code is invalid, the user is redirected to /central/select-site.

When the site is resolved (or changed), a fj:site-change CustomEvent is dispatched on document:

All sidebar links use the pageUrl() helper to preserve site context:

export function pageUrl(page) {
const site = window.FJ.selectedSite || _urlSite || 'default';
return `/central/${site}/${page}`;
}

Pages filter content by matching the selected site’s rpi_ids array against device data:

function filterRpisBySite(rpis) {
const site = window.FJ?.selectedSite;
if (!site || site === 'all') return rpis;
const siteObj = window.FJ?.sites?.find(s => s.site_code === site);
if (!siteObj?.rpi_ids) return rpis;
const rpiIds = new Set(
Array.isArray(siteObj.rpi_ids) ? siteObj.rpi_ids : JSON.parse(siteObj.rpi_ids || '[]')
);
return rpis.filter(rpi => rpiIds.has(rpi.rpi_id));
}