chore(core): install primeng and tailwind

This commit is contained in:
2025-08-20 18:20:02 +02:00
parent cc7eb48fe1
commit 613263731d
14 changed files with 1628 additions and 482 deletions

View File

@@ -0,0 +1,123 @@
import { Translation } from 'primeng/api';
export const germanTranslation: Translation = {
startsWith: 'Beginnt mit',
contains: 'Enthält',
notContains: 'Enthält nicht',
endsWith: 'Endet mit',
equals: 'Gleich',
notEquals: 'Ungleich',
noFilter: 'Kein Filter',
lt: 'Kleiner als',
lte: 'Kleiner oder gleich',
gt: 'Größer als',
gte: 'Größer oder gleich',
dateIs: 'Datum ist',
dateIsNot: 'Datum ist nicht',
dateBefore: 'Datum ist vor',
dateAfter: 'Datum ist nach',
clear: 'Zurücksetzen',
apply: 'Übernehmen',
matchAll: 'Alle Bedingungen',
matchAny: 'Mindestens eine Bedingung',
addRule: 'Regel hinzufügen',
removeRule: 'Regel entfernen',
accept: 'Ja',
reject: 'Nein',
choose: 'Auswählen',
upload: 'Hochladen',
cancel: 'Abbrechen',
completed: 'Abgeschlossen',
pending: 'Ausstehend',
fileSizeTypes: ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
dayNames: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
dayNamesShort: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
dayNamesMin: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
monthNames: [
'Januar','Februar','März','April','Mai','Juni',
'Juli','August','September','Oktober','November','Dezember'
],
monthNamesShort: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
chooseYear: 'Jahr wählen',
chooseMonth: 'Monat wählen',
chooseDate: 'Datum wählen',
prevDecade: 'Vorheriges Jahrzehnt',
nextDecade: 'Nächstes Jahrzehnt',
prevYear: 'Vorheriges Jahr',
nextYear: 'Nächstes Jahr',
prevMonth: 'Vorheriger Monat',
nextMonth: 'Nächster Monat',
prevHour: 'Vorherige Stunde',
nextHour: 'Nächste Stunde',
prevMinute: 'Vorherige Minute',
nextMinute: 'Nächste Minute',
prevSecond: 'Vorherige Sekunde',
nextSecond: 'Nächste Sekunde',
am: 'vorm.',
pm: 'nachm.',
today: 'Heute',
weekHeader: 'KW',
firstDayOfWeek: 1,
dateFormat: 'dd.mm.yy',
weak: 'Schwach',
medium: 'Mittel',
strong: 'Stark',
passwordPrompt: 'Passwort eingeben',
emptyFilterMessage: 'Keine Ergebnisse gefunden',
searchMessage: '{0} Ergebnisse verfügbar',
selectionMessage: '{0} Elemente ausgewählt',
emptySelectionMessage: 'Kein Element ausgewählt',
emptySearchMessage: 'Keine Ergebnisse gefunden',
emptyMessage: 'Keine Optionen verfügbar',
aria: {
trueLabel: 'Wahr',
falseLabel: 'Falsch',
nullLabel: 'Nicht ausgewählt',
star: '1 Stern',
stars: '{star} Sterne',
selectAll: 'Alle Elemente ausgewählt',
unselectAll: 'Alle Elemente abgewählt',
close: 'Schließen',
previous: 'Zurück',
next: 'Weiter',
navigation: 'Navigation',
scrollTop: 'Nach oben scrollen',
moveTop: 'Nach ganz oben',
moveUp: 'Nach oben',
moveDown: 'Nach unten',
moveBottom: 'Nach ganz unten',
moveToTarget: 'Zum Ziel verschieben',
moveToSource: 'Zur Quelle verschieben',
moveAllToTarget: 'Alle zum Ziel verschieben',
moveAllToSource: 'Alle zur Quelle verschieben',
pageLabel: '{page}',
firstPageLabel: 'Erste Seite',
lastPageLabel: 'Letzte Seite',
nextPageLabel: 'Nächste Seite',
prevPageLabel: 'Vorherige Seite',
rowsPerPageLabel: 'Zeilen pro Seite',
jumpToPageDropdownLabel: 'Seite auswählen',
jumpToPageInputLabel: 'Seite eingeben',
selectRow: 'Zeile ausgewählt',
unselectRow: 'Zeile abgewählt',
expandRow: 'Zeile erweitert',
collapseRow: 'Zeile eingeklappt',
showFilterMenu: 'Filtermenü anzeigen',
hideFilterMenu: 'Filtermenü ausblenden',
filterOperator: 'Filter-Operator',
filterConstraint: 'Filter-Bedingung',
editRow: 'Zeile bearbeiten',
saveEdit: 'Bearbeitung speichern',
cancelEdit: 'Bearbeitung abbrechen',
listView: 'Listenansicht',
gridView: 'Rasteransicht',
slide: 'Folie',
slideNumber: '{slideNumber}',
zoomImage: 'Bild zoomen',
zoomIn: 'Vergrößern',
zoomOut: 'Verkleinern',
rotateRight: 'Nach rechts drehen',
rotateLeft: 'Nach links drehen'
}
};

View File

@@ -0,0 +1,21 @@
export class Theme {
code: string;
name: string;
constructor(code: string, name: string) {
this.code = code;
this.name = name;
}
static findByCode(code: string): Theme {
return Theme.THEMES.find(theme => theme.code === code) || Theme.DEFAULT_THEME;
}
static readonly THEMES: Theme[] = [
new Theme('light', 'Hell'),
new Theme('dark', 'Dunkel'),
new Theme('system', 'System'),
];
static readonly DEFAULT_THEME = Theme.THEMES[2];
}

View File

@@ -0,0 +1,56 @@
import {effect, Injectable, signal, WritableSignal} from '@angular/core';
import {Theme} from "../models/theme";
@Injectable({
providedIn: 'root'
})
export class ThemeSwitchService {
private readonly THEME_KEY = 'app-theme-mode';
public theme: WritableSignal<Theme> = signal(Theme.DEFAULT_THEME);
constructor() {
effect(() => {
const currentTheme = this.theme();
localStorage.setItem(this.THEME_KEY, currentTheme.code);
const html = document.querySelector('html')!;
const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const isDark = currentTheme.code === 'dark' || (currentTheme.code === 'system' && systemPrefersDark);
html.classList.toggle('dark', isDark);
});
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
if (this.theme().code === 'system') {
this.theme.update(t => t);
}
});
}
initialize() {
console.info('initializing dark mode service');
const stored = Theme.THEMES.find(theme => theme.code === localStorage.getItem(this.THEME_KEY));
if (stored === undefined) {
this.theme.set(Theme.DEFAULT_THEME);
return;
}
if (stored.code === 'dark' || stored.code === 'light' || stored.code === 'system') {
this.theme.set(stored);
} else {
this.theme.set(Theme.DEFAULT_THEME);
}
}
switchToTheme(theme: Theme) {
console.info(`switching to theme: ${theme.name}`);
this.theme.set(theme);
}
isDarkMode(): boolean {
return this.theme().code === 'dark' || (this.theme().code === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches);
}
}