Various CSS work

This commit is contained in:
Janus C. H. Knudsen 2026-01-12 22:10:57 +01:00
parent ef174af0e1
commit 15579acba8
52 changed files with 8001 additions and 944 deletions

View file

@ -10,6 +10,7 @@ import { ThemeController } from './modules/theme';
import { SearchController } from './modules/search';
import { LockScreenController } from './modules/lockscreen';
import { CashController } from './modules/cash';
import { EmployeesController } from './modules/employees';
/**
* Main application class
@ -21,6 +22,7 @@ export class App {
readonly search: SearchController;
readonly lockScreen: LockScreenController;
readonly cash: CashController;
readonly employees: EmployeesController;
constructor() {
// Initialize controllers
@ -30,6 +32,7 @@ export class App {
this.search = new SearchController();
this.lockScreen = new LockScreenController(this.drawers);
this.cash = new CashController();
this.employees = new EmployeesController();
}
}

View file

@ -0,0 +1,191 @@
/**
* Employees Controller
*
* Handles content swap between list view and detail view,
* plus tab switching within each view.
* Uses History API for browser back/forward navigation.
*/
export class EmployeesController {
private listView: HTMLElement | null = null;
private detailView: HTMLElement | null = null;
constructor() {
this.listView = document.getElementById('employees-list-view');
this.detailView = document.getElementById('employee-detail-view');
// Only initialize if we're on the employees page
if (!this.listView) return;
this.setupListTabs();
this.setupDetailTabs();
this.setupChevronNavigation();
this.setupBackNavigation();
this.setupHistoryNavigation();
this.restoreStateFromUrl();
}
/**
* Setup popstate listener for browser back/forward
*/
private setupHistoryNavigation(): void {
window.addEventListener('popstate', (e: PopStateEvent) => {
if (e.state?.employeeKey) {
this.showDetailViewInternal(e.state.employeeKey);
} else {
this.showListViewInternal();
}
});
}
/**
* Restore view state from URL on page load
*/
private restoreStateFromUrl(): void {
const hash = window.location.hash;
if (hash.startsWith('#employee-')) {
const employeeKey = hash.substring(1); // Remove #
this.showDetailViewInternal(employeeKey);
}
}
/**
* Setup tab switching for the list view
*/
private setupListTabs(): void {
if (!this.listView) return;
const tabs = this.listView.querySelectorAll<HTMLElement>('swp-tab-bar > swp-tab[data-tab]');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
const targetTab = tab.dataset.tab;
if (targetTab) {
this.switchTab(this.listView!, targetTab);
}
});
});
}
/**
* Setup tab switching for the detail view
*/
private setupDetailTabs(): void {
if (!this.detailView) return;
const tabs = this.detailView.querySelectorAll<HTMLElement>('swp-tab-bar > swp-tab[data-tab]');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
const targetTab = tab.dataset.tab;
if (targetTab) {
this.switchTab(this.detailView!, targetTab);
}
});
});
}
/**
* Switch to a specific tab within a container
*/
private switchTab(container: HTMLElement, targetTab: string): void {
const tabs = container.querySelectorAll<HTMLElement>('swp-tab-bar > swp-tab[data-tab]');
const contents = container.querySelectorAll<HTMLElement>('swp-tab-content[data-tab]');
tabs.forEach(t => {
t.classList.toggle('active', t.dataset.tab === targetTab);
});
contents.forEach(content => {
content.classList.toggle('active', content.dataset.tab === targetTab);
});
}
/**
* Setup row click to show detail view
* Ignores clicks on action buttons
*/
private setupChevronNavigation(): void {
document.addEventListener('click', (e: Event) => {
const target = e.target as HTMLElement;
// Ignore clicks on action buttons
if (target.closest('swp-icon-btn') || target.closest('swp-table-actions')) {
return;
}
const row = target.closest<HTMLElement>('swp-employee-row[data-employee-detail]');
if (row) {
const employeeKey = row.dataset.employeeDetail;
if (employeeKey) {
this.showDetailView(employeeKey);
}
}
});
}
/**
* Setup back button to return to list view
*/
private setupBackNavigation(): void {
document.addEventListener('click', (e: Event) => {
const target = e.target as HTMLElement;
const backLink = target.closest<HTMLElement>('[data-employee-back]');
if (backLink) {
this.showListView();
}
});
}
/**
* Show the detail view and hide list view (with history push)
*/
private showDetailView(employeeKey: string): void {
// Push state to history
history.pushState(
{ employeeKey },
'',
`#${employeeKey}`
);
this.showDetailViewInternal(employeeKey);
}
/**
* Show detail view without modifying history (for popstate)
*/
private showDetailViewInternal(employeeKey: string): void {
if (this.listView && this.detailView) {
this.listView.style.display = 'none';
this.detailView.style.display = 'block';
this.detailView.dataset.employee = employeeKey;
// Reset to first tab
this.switchTab(this.detailView, 'general');
}
}
/**
* Show the list view and hide detail view (with history push)
*/
private showListView(): void {
// Push state to history (clear hash)
history.pushState(
{},
'',
window.location.pathname
);
this.showListViewInternal();
}
/**
* Show list view without modifying history (for popstate)
*/
private showListViewInternal(): void {
if (this.listView && this.detailView) {
this.detailView.style.display = 'none';
this.listView.style.display = 'block';
}
}
}