929ee6557a
- Add base app structure, including Bootstrap setup and Alpine.js integration. - Implement authentication flow with session handling. - Integrate stock management and label creation functionalities. - Include responsive styling and theme using CSS variables and custom components. - Add API clients for Tryton-based backend. - Set up kitchen and dashboard navigation workflows. - Configure service worker for PWA support.
96 lines
2.8 KiB
JavaScript
96 lines
2.8 KiB
JavaScript
import { ROUTES } from './config.js';
|
|
import { renderDashboardPage } from '../features/dashboard/dashboard-page.js';
|
|
import { renderKitchenSelector } from '../features/kitchens/kitchen-selector.js';
|
|
import { renderLoginPage } from '../features/auth/login-page.js';
|
|
import { renderLabelCreatePage } from '../features/labels/label-create-page.js';
|
|
import { renderSettingsPage } from '../features/auth/settings-page.js';
|
|
import { renderStockDetailPage } from '../features/stock/stock-detail-page.js';
|
|
import { renderStockListPage } from '../features/stock/stock-list-page.js';
|
|
|
|
const routeDefinitions = [
|
|
{ path: ROUTES.login, render: renderLoginPage, protected: false },
|
|
{ path: ROUTES.home, render: renderDashboardPage, protected: true },
|
|
{ path: ROUTES.stock, render: renderStockListPage, protected: true },
|
|
{ path: ROUTES.stockNew, render: renderLabelCreatePage, protected: true },
|
|
{ path: ROUTES.stockDetail, render: renderStockDetailPage, protected: true },
|
|
{ path: ROUTES.labelsNew, render: renderLabelCreatePage, protected: true },
|
|
{ path: ROUTES.settings, render: renderSettingsPage, protected: false },
|
|
];
|
|
|
|
function normalizeHashRoute() {
|
|
const route = window.location.hash.replace(/^#/, '') || ROUTES.home;
|
|
return route.startsWith('/') ? route : `/${route}`;
|
|
}
|
|
|
|
function matchRoute(pathname) {
|
|
for (const definition of routeDefinitions) {
|
|
const keys = [];
|
|
const pattern = definition.path.replace(/:([^/]+)/g, (_, key) => {
|
|
keys.push(key);
|
|
return '([^/]+)';
|
|
});
|
|
|
|
const regex = new RegExp(`^${pattern}$`);
|
|
const match = pathname.match(regex);
|
|
if (!match) {
|
|
continue;
|
|
}
|
|
|
|
const params = keys.reduce((accumulator, key, index) => {
|
|
accumulator[key] = decodeURIComponent(match[index + 1]);
|
|
return accumulator;
|
|
}, {});
|
|
|
|
return { ...definition, params };
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
export function navigate(path) {
|
|
window.location.hash = path;
|
|
}
|
|
|
|
export function getRouteContext() {
|
|
return window.__loncRouteContext || { path: ROUTES.home, params: {} };
|
|
}
|
|
|
|
export function createRouter({ Alpine, store, outlet }) {
|
|
const render = async () => {
|
|
const pathname = normalizeHashRoute();
|
|
const match = matchRoute(pathname);
|
|
|
|
if (!match) {
|
|
navigate(ROUTES.home);
|
|
return;
|
|
}
|
|
|
|
if (match.protected && !store.isConnected) {
|
|
navigate(ROUTES.login);
|
|
return;
|
|
}
|
|
|
|
if (
|
|
store.isConnected &&
|
|
!store.activeKitchen &&
|
|
pathname !== ROUTES.login &&
|
|
pathname !== ROUTES.settings
|
|
) {
|
|
outlet.innerHTML = renderKitchenSelector();
|
|
Alpine.initTree(outlet);
|
|
return;
|
|
}
|
|
|
|
window.__loncRouteContext = { path: pathname, params: match.params };
|
|
outlet.innerHTML = match.render();
|
|
Alpine.initTree(outlet);
|
|
};
|
|
|
|
window.addEventListener('hashchange', render);
|
|
|
|
return {
|
|
start: render,
|
|
render,
|
|
};
|
|
}
|