Skip to main content
The Factus Challenge frontend lives in the fr-v1/ directory and is a fully static HTML application built with ES modules. There is no build step, no bundler, and no framework — you can open index.html directly in a browser or serve the folder from any static host. All JavaScript is loaded as native ES modules via <script type="module">, and each page controller is a class of pure static methods.

Technology Stack

HTML5 + Bootstrap 5.3.3

Uses the Bootstrap 5.3.3 Vapor dark theme, loaded from resources/utils/bootstrap-5.3.3/. The entire layout relies on Bootstrap utility classes — no custom CSS grid.

Vanilla JS ES Modules

All logic lives in .mjs files under resources/js/. Each view is an exported default class with only static methods; the classes throw on construction.

Tabulator 6.3

Tabulator 6.3 powers every data table. Progressive-scroll loading, column tooltips, custom cell formatters, and footer action buttons are used throughout.

Luxon 3

Luxon 3 handles all date parsing and formatting. Dates from the API arrive as dd-MM-yyyy hh:mm:ss a and are displayed in a long Spanish locale format.
Additional bundled libraries:
  • Bootstrap Popper (resources/utils/popper/) — powers dropdowns and tooltips
  • Custom utilities in resources/utils/own/:
    • helpers.js — Helpers class
    • toast.js — Toast class
    • popup.js — Popup / Modal class
    • icons.js — icons object of SVG strings
    • dialog.js — base Dialog class extended by Popup

Directory Structure


Configuration

The only thing you need to change to point the frontend at a different backend is the single-field config.json file. On startup, index.mjs fetches this file and writes the URL to window.urlAPI, which every module then reads as a global.
resources/assets/config.json
Change url to the address of your deployed backend (e.g. https://api.myserver.com) and the entire frontend will switch targets without any other modification.

How the Router Works

index.mjs defines a single App class. When the page loads, App.main():
1

Fetch config

Reads config.json and stores config.url in window.urlAPI. Also registers shared globals (window.Tabulator, window.Toast, window.Modal, window.Helpers, window.icons, window.DateTime, etc.).
2

Verify backend connection

Calls GET ${urlAPI}/. If the response status is 200 the router continues; otherwise a danger Toast is shown.
3

Read current page

Extracts the trailing filename from window.location.href using the regex /[^/]+\.html$/ — e.g. factus.html.
4

Dynamic import

Passes the filename to App.#mainMenu(option), which uses a switch statement to dynamically import() the matching .mjs module and calls its .init() static method.
resources/js/index.mjs (router excerpt)

Custom Utility Classes

All utility classes are exposed as window globals by index.mjs so every lazily-loaded module can use them without additional imports.
Defined in resources/utils/own/helpers.js. Exposes common operations needed by all page controllers.
Defined in resources/utils/own/toast.js. Displays a slide-in notification anchored to a <dialog> element appended to <body>.
Each mode maps to a Bootstrap icon: checkCircleFill (success), infoCircleFill (info), exclamationCircleFill2 (warning), xCircleFill (danger).
Defined in resources/js/customs.mjs. Exported as named exports, re-exposed globally as window.Customs.
Defined in resources/utils/own/icons.js. A plain export default object where each key is a descriptive name and each value is an SVG string. Used inline in button HTML. Exposed as window.icons.Key icons used by the UI: icons.plusSquare (add row), icons.edit (edit row), icons.delete (delete row), icons.deleteWhite / icons.editWhite (modal submit buttons), icons.xLg (cancel), icons.pdf_icon1 (PDF download).