Every URL in the GSM frontend carries a locale segment —Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ti-infinite/GSMApplication/llms.txt
Use this file to discover all available pages before exploring further.
/en/ or /es/ — immediately after the origin. This design lets the application switch between English and Spanish without a page reload while keeping deep links shareable and bookmarkable. React Router v7 handles the route tree and i18next provides the translation layer.
Route Tree
The full route structure is defined insrc/App.tsx. Routes are nested so that locale context, authentication, and the dashboard shell each add their own layer without repeating concerns.
Route Summary
| Path | Component | Guard |
|---|---|---|
/ | Redirect → /:locale/login | None |
/:locale/login | LoginPage | None |
/:locale/dashboard | DashboardPage (inside DashboardLayout) | AuthGuard |
/:locale/dashboard/* | ModulePage (inside DashboardLayout) | AuthGuard |
/:locale/* | NotFound | AuthGuard |
/* | Redirect → dashboard or login | None |
Locale Prefix
The supported locale values areen (English) and es (Spanish). The active locale is determined in order:
getSavedLocale()reads fromlocalStorageunder the keygsm_locale.- If nothing is stored, it falls back to
en.
LocaleLayout reads the :locale param from the URL and calls i18n.changeLanguage() so all translation hooks in child components immediately use the correct language. The language switcher on the login page and in the navigation header calls switchLocale(next, path) which updates localStorage and navigates to the equivalent path under the new locale prefix.
AuthGuard
AuthGuard sits between the /:locale layout and every protected route. It renders nothing (and redirects to login) if there is no active session, and redirects to the password-change flow if a forced password reset is pending.
isSessionActive()
Session validity is checked by reading the gsm_exp cookie, which holds the JWT expiry timestamp as a Unix integer. The check is purely client-side and never makes a network request.
The actual JWT token (
gsm_token) is stored as an HttpOnly cookie by the backend and is never readable by JavaScript. gsm_exp is a separate non-HttpOnly cookie that carries only the expiry timestamp, allowing the frontend to gate navigation without touching the token itself.i18next Setup
Translation files live inmessages/ at the project root:
src/app/providers/ before the React tree mounts. Namespaces are flat — all keys live in the default namespace. Nested keys use dot notation, for example login.title or productivity.toast.assignmentCreated.
Translation Key Structure
useTranslation() call inside a component automatically switches output when i18n.changeLanguage() is called — no unmounting or re-fetching required.
Language Switcher
The language switcher rendersEN and ES toggle buttons on both the login page (top-right panel) and the dashboard header. Clicking a locale button calls switchLocale and navigates to the current equivalent path under the new locale prefix.
ModulePage: Menu-Driven Navigation
ModulePage renders at /:locale/dashboard/*, meaning the wildcard * segment captures any sub-path under dashboard. It uses that captured slug to look up the matching menu option from the menu tree returned by the application API (GET /api/application/v1/application/getMenu).
| Slug | Component |
|---|---|
productivity | features/productivity/ProductivityPage |
operations/products | features/products/ProductsPage |
resources | features/resources/ResourcesPage |
sop | features/sop/SopPage |
settings | features/settings/SettingsPage |
ExternalRoute value bypass the component registry entirely and are handed off to ExternalPage, which delegates to IframeRenderer, NhBiRenderer, or NewTabRenderer based on the ActiveType field.
Sidebar & Menu API
TheSidebar component in src/layouts/shell/Sidebar.tsx is populated by the useMenu() hook, which calls GET /api/application/v1/application/getMenu via the Orval-generated useGetMenu hook. The response is a JSON-encoded menu string that useMenu parses into a normalised MenuOption[] tree and then applies i18n translations to each item’s description.
staleTime and a select transform that parses the raw JSON string into the MenuOption[] tree:
IsShortcut: true are surfaced as quick-access cards on the Dashboard home screen. Items with Section: 'others' are rendered in the lower “Others” group in the sidebar rather than the main navigation group.