Introduce initial version of the Lonc app with core features, styling, and configurations.
- 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.
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
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,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user