diff --git a/app/core/plugins.py b/app/core/plugins.py index c48dec6..143b5ca 100644 --- a/app/core/plugins.py +++ b/app/core/plugins.py @@ -1,16 +1,29 @@ import logging -from flask import Blueprint, g, abort, redirect, url_for, flash +from flask import Blueprint, g, abort, redirect, url_for, flash, current_app from functools import wraps from app.models.feature_system import is_feature_enabled logger = logging.getLogger(__name__) +class MenuItem: + def __init__(self, label, endpoint, icon, order=100, group=None, required_role=None, feature_name=None, badge_count_key=None, label_is_key=False): + self.label = label + self.endpoint = endpoint + self.icon = icon + self.order = order + self.group = group + self.required_role = required_role + self.feature_name = feature_name + self.badge_count_key = badge_count_key + self.label_is_key = label_is_key # If True, label is a key in app_labels + class Plugin: - def __init__(self, name, blueprint, feature_name=None, url_prefix=None): + def __init__(self, name, blueprint, feature_name=None, url_prefix=None, menu_items=None): self.name = name self.blueprint = blueprint self.feature_name = feature_name or name self.url_prefix = url_prefix + self.menu_items = menu_items or [] def plugin_required(feature_name): """Decorator to check if a feature is enabled for the current department""" @@ -27,6 +40,7 @@ def decorated_function(*args, **kwargs): class PluginManager: _plugins = {} + _core_menu_items = [] @classmethod def register(cls, plugin): @@ -40,6 +54,37 @@ def check_enabled(): # Redirect or 404 return redirect(url_for('dashboard.index')) + @classmethod + def register_menu_item(cls, menu_item): + cls._core_menu_items.append(menu_item) + + @classmethod + def get_menu_items(cls): + all_items = list(cls._core_menu_items) + for plugin in cls._plugins.values(): + all_items.extend(plugin.menu_items) + + # Sort by order + all_items.sort(key=lambda x: (x.order, x.label)) + return all_items + + @classmethod + def get_grouped_menu_items(cls): + items = cls.get_menu_items() + groups = {} + for item in items: + group = item.group or 'Sonstiges' + if group not in groups: + groups[group] = [] + groups[group].append(item) + + # Define group order + group_order = ['Übersicht', 'Inventar', 'Personal', 'Service', 'Allgemein', 'Sonstiges'] + + # Sort groups based on group_order, then alphabetically for unknown groups + sorted_groups = sorted(groups.items(), key=lambda x: (group_order.index(x[0]) if x[0] in group_order else 999, x[0])) + return sorted_groups + @classmethod def init_app(cls, app): for plugin in cls._plugins.values(): diff --git a/app/plugins/canteen/__init__.py b/app/plugins/canteen/__init__.py index 0d6cfdf..0eb5e2d 100644 --- a/app/plugins/canteen/__init__.py +++ b/app/plugins/canteen/__init__.py @@ -1,4 +1,6 @@ from .routes import bp -from app.core.plugins import Plugin, plugin_manager +from app.core.plugins import Plugin, plugin_manager, MenuItem -plugin_manager.register(Plugin('canteen', bp, 'canteen_plan')) +plugin_manager.register(Plugin('canteen', bp, 'canteen_plan', url_prefix='/canteen', menu_items=[ + MenuItem('Kantinenplan', 'canteen.index', 'fas fa-utensils', order=80, group='Allgemein', feature_name='canteen_plan') +])) diff --git a/app/plugins/consumables/__init__.py b/app/plugins/consumables/__init__.py index 532274d..7e52276 100644 --- a/app/plugins/consumables/__init__.py +++ b/app/plugins/consumables/__init__.py @@ -1,4 +1,6 @@ from .routes import bp -from app.core.plugins import Plugin, plugin_manager +from app.core.plugins import Plugin, plugin_manager, MenuItem -plugin_manager.register(Plugin('consumables', bp, 'consumables', url_prefix='/consumables')) +plugin_manager.register(Plugin('consumables', bp, 'consumables', url_prefix='/consumables', menu_items=[ + MenuItem('consumables', 'consumables.index', 'fas fa-box-open', order=30, group='Inventar', feature_name='consumables', label_is_key=True) +])) diff --git a/app/plugins/jobs/__init__.py b/app/plugins/jobs/__init__.py index bba2f04..a566161 100644 --- a/app/plugins/jobs/__init__.py +++ b/app/plugins/jobs/__init__.py @@ -1,4 +1,6 @@ from .routes import bp -from app.core.plugins import Plugin, plugin_manager +from app.core.plugins import Plugin, plugin_manager, MenuItem -plugin_manager.register(Plugin('jobs', bp, 'job_board', url_prefix='/jobs')) +plugin_manager.register(Plugin('jobs', bp, 'job_board', url_prefix='/jobs', menu_items=[ + MenuItem('Jobbörse', 'jobs.job_list', 'fas fa-briefcase', order=70, group='Allgemein', feature_name='job_board') +])) diff --git a/app/plugins/tickets/__init__.py b/app/plugins/tickets/__init__.py index 9594072..ebb380b 100644 --- a/app/plugins/tickets/__init__.py +++ b/app/plugins/tickets/__init__.py @@ -1,6 +1,10 @@ from .routes import bp -from app.core.plugins import Plugin, plugin_manager +from app.core.plugins import Plugin, plugin_manager, MenuItem + +plugin_manager.register(Plugin('tickets', bp, 'ticket_system', url_prefix='/tickets', menu_items=[ + MenuItem('tickets', 'tickets.create', 'fas fa-ticket-alt', order=50, group='Service', feature_name='ticket_system', label_is_key=True, badge_count_key='unread_tickets_count'), + MenuItem('Auftragserstellung', 'tickets.public_create_order', 'fas fa-file-alt', order=60, group='Service', feature_name='ticket_system') +])) -plugin_manager.register(Plugin('tickets', bp, 'ticket_system', url_prefix='/tickets')) from .history_routes import bp as history_bp plugin_manager.register(Plugin('ticket_history', history_bp, 'ticket_system', url_prefix='/api/tickets')) diff --git a/app/plugins/tools/__init__.py b/app/plugins/tools/__init__.py index 17b95b2..f9a20f6 100644 --- a/app/plugins/tools/__init__.py +++ b/app/plugins/tools/__init__.py @@ -1,4 +1,6 @@ from .routes import bp -from app.core.plugins import Plugin, plugin_manager +from app.core.plugins import Plugin, plugin_manager, MenuItem -plugin_manager.register(Plugin('tools', bp, 'tools', url_prefix='/tools')) +plugin_manager.register(Plugin('tools', bp, 'tools', url_prefix='/tools', menu_items=[ + MenuItem('tools', 'tools.index', 'fas fa-tools', order=20, group='Inventar', feature_name='tools', label_is_key=True) +])) diff --git a/app/plugins/workers/__init__.py b/app/plugins/workers/__init__.py index 16d730b..ef65744 100644 --- a/app/plugins/workers/__init__.py +++ b/app/plugins/workers/__init__.py @@ -1,4 +1,7 @@ from .routes import bp -from app.core.plugins import Plugin, plugin_manager +from app.core.plugins import Plugin, plugin_manager, MenuItem -plugin_manager.register(Plugin('workers', bp, 'workers', url_prefix='/workers')) +plugin_manager.register(Plugin('workers', bp, 'workers', url_prefix='/workers', menu_items=[ + MenuItem('Mitarbeiter', 'workers.index', 'fas fa-users', order=40, group='Personal', feature_name='workers'), + MenuItem('Wochenberichte', 'workers.timesheet_list', 'fas fa-clock', order=45, group='Personal', feature_name='weekly_reports', badge_count_key='unfilled_timesheet_days') +])) diff --git a/app/routes/__init__.py b/app/routes/__init__.py index 29d49a5..6ede288 100755 --- a/app/routes/__init__.py +++ b/app/routes/__init__.py @@ -6,7 +6,7 @@ from app.routes.main import bp as main_bp from app.routes.dashboard import bp as dashboard_bp from app.routes.setup import bp as setup_bp -from app.core.plugins import plugin_manager +from app.core.plugins import plugin_manager, MenuItem # Import plugins to register them import app.plugins.tools @@ -33,6 +33,10 @@ def init_app(app): app.register_blueprint(api_bp) app.register_blueprint(setup_bp) + # Register Core Menu Items + plugin_manager.register_menu_item(MenuItem('Dashboard', 'dashboard.index', 'fas fa-th-large', order=10, group='Übersicht')) + plugin_manager.register_menu_item(MenuItem('Über Scandy', 'main.about', 'fas fa-info-circle', order=100, group='Allgemein')) + # Register Plugins plugin_manager.init_app(app) diff --git a/app/static/css/main.css b/app/static/css/main.css index b653e45..56d2c6b 100755 --- a/app/static/css/main.css +++ b/app/static/css/main.css @@ -1,3 +1,41 @@ +/* ======================================== + BTZ-KÖLN CORPORATE DESIGN SYSTEM + ======================================== */ + +:root { + /* BTZ-Köln Farbpalette - Mapped to Theme Variables */ + --btz-primary: oklch(var(--p)); + --btz-primary-light: oklch(var(--p) / 0.8); + --btz-primary-dark: oklch(var(--p) / 1.1); + --btz-primary-hover: oklch(var(--p) / 0.9); + --btz-secondary: oklch(var(--b2)); + --btz-secondary-dark: oklch(var(--b3)); + --btz-accent: oklch(var(--a)); + --btz-accent-dark: oklch(var(--a) / 0.8); + --btz-text: oklch(var(--bc)); + --btz-text-light: oklch(var(--bc) / 0.7); + --btz-text-muted: oklch(var(--bc) / 0.5); + --btz-success: oklch(var(--su)); + --btz-warning: oklch(var(--wa)); + --btz-danger: oklch(var(--er)); + --btz-info: oklch(var(--in)); + + /* Schatten und Effekte */ + --btz-shadow-sm: 0 1px 2px 0 rgba(0, 102, 204, 0.05); + --btz-shadow: 0 1px 3px 0 rgba(0, 102, 204, 0.1), 0 1px 2px 0 rgba(0, 102, 204, 0.06); + --btz-shadow-lg: 0 10px 15px -3px rgba(0, 102, 204, 0.1), 0 4px 6px -2px rgba(0, 102, 204, 0.05); + --btz-shadow-xl: 0 20px 25px -5px rgba(0, 102, 204, 0.1), 0 10px 10px -5px rgba(0, 102, 204, 0.04); + + /* Abstände */ + --btz-radius-sm: 0.25rem; + --btz-radius: 0.375rem; + --btz-radius-lg: 0.5rem; + --btz-radius-xl: 0.75rem; + + /* Übergänge */ + --btz-transition: all 0.2s ease-in-out; +} + *, ::before, ::after { --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; @@ -22,7 +60,7 @@ --tw-numeric-fraction: ; --tw-ring-inset: ; --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; + --tw-ring-offset-color: oklch(var(--b1)); --tw-ring-color: rgb(59 130 246 / 0.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; @@ -76,7 +114,7 @@ --tw-numeric-fraction: ; --tw-ring-inset: ; --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; + --tw-ring-offset-color: oklch(var(--b1)); --tw-ring-color: rgb(59 130 246 / 0.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; @@ -106,6 +144,567 @@ --tw-contain-style: ; } +/* ======================================== + BTZ-KÖLN COMPONENT STYLES + ======================================== */ + +/* Body Background - Sicherstellen, dass er hell ist */ +body { + + +} + +/* Hauptinhaltsbereich */ +.main-content-with-sidebar { + +} + +/* ======================================== + BTZ-KÖLN COMPONENT STYLES + ======================================== */ + +/* Button Styles */ +.btn-primary { + background-color: var(--btz-primary) ; + border-color: var(--btz-primary) ; + color: white ; + transition: var(--btz-transition) !important; + box-shadow: var(--btz-shadow-sm) !important; +} + +.btn-primary:hover { + background-color: var(--btz-primary-hover) ; + border-color: var(--btz-primary-hover) ; + box-shadow: var(--btz-shadow) !important; + transform: translateY(-1px) !important; +} + +.btn-secondary { + background-color: var(--btz-secondary) ; + border-color: var(--btz-secondary-dark) ; + color: var(--btz-text) ; + transition: var(--btz-transition) !important; + box-shadow: var(--btz-shadow-sm) !important; +} + +.btn-secondary:hover { + background-color: var(--btz-secondary-dark) ; + border-color: var(--btz-secondary-dark) ; + box-shadow: var(--btz-shadow) !important; + transform: translateY(-1px) !important; +} + +.btn-success { + background-color: var(--btz-success) ; + border-color: var(--btz-success) ; + color: white ; + transition: var(--btz-transition) !important; + box-shadow: var(--btz-shadow-sm) !important; +} + +.btn-success:hover { + background-color: oklch(var(--su)) ; + border-color: oklch(var(--su)) ; + box-shadow: var(--btz-shadow) !important; + transform: translateY(-1px) !important; +} + +.btn-danger { + background-color: var(--btz-danger) ; + border-color: var(--btz-danger) ; + color: white ; + transition: var(--btz-transition) !important; + box-shadow: var(--btz-shadow-sm) !important; +} + +.btn-danger:hover { + background-color: oklch(var(--er)) ; + border-color: oklch(var(--er)) ; + box-shadow: var(--btz-shadow) !important; + transform: translateY(-1px) !important; +} + +.btn-warning { + background-color: var(--btz-warning) ; + border-color: var(--btz-warning) ; + color: var(--btz-text) ; + transition: var(--btz-transition) !important; + box-shadow: var(--btz-shadow-sm) !important; +} + +.btn-warning:hover { + background-color: oklch(var(--wa)) ; + border-color: oklch(var(--wa)) ; + box-shadow: var(--btz-shadow) !important; + transform: translateY(-1px) !important; +} + +.btn-info { + background-color: var(--btz-info) ; + border-color: var(--btz-info) ; + color: white ; + transition: var(--btz-transition) !important; + box-shadow: var(--btz-shadow-sm) !important; +} + +.btn-info:hover { + background-color: oklch(var(--in)) ; + border-color: oklch(var(--in)) ; + box-shadow: var(--btz-shadow) !important; + transform: translateY(-1px) !important; +} + +/* Card Styles */ +.card { + border: none ; + border-radius: var(--btz-radius-lg) !important; + box-shadow: var(--btz-shadow) !important; + transition: var(--btz-transition) !important; + background-color: oklch(var(--b1)) ; +} + +.card:hover { + box-shadow: var(--btz-shadow-lg) !important; + transform: translateY(-2px) !important; +} + +.card-header { + background: oklch(var(--p) / 0.1) ; + color: oklch(var(--p)) ; + border-radius: 0.5rem 0.5rem 0 0 !important; + border-bottom: 2px solid oklch(var(--p)) !important; + padding: 1.25rem 1.5rem !important; +} + +.card-title { + margin: 0 !important; + font-weight: 600 !important; + font-size: 1.125rem !important; + letter-spacing: -0.01em !important; + color: oklch(var(--p)) ; +} + +.card-body { + padding: 1.5rem !important; + background-color: transparent ; +} + +/* Form Styles */ +.form-control { + border: 2px solid #e1e5e9 ; + border-radius: var(--btz-radius) !important; + padding: 0.75rem 1rem !important; + transition: var(--btz-transition) !important; + background-color: oklch(var(--b1)) ; + font-size: 0.875rem !important; +} + +.form-control:focus { + border-color: var(--btz-primary) ; + box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1) !important; + outline: none !important; +} + +.form-control:hover { + border-color: var(--btz-primary-light) ; +} + +.form-label { + font-weight: 600 !important; + color: var(--btz-text) ; + margin-bottom: 0.5rem !important; + font-size: 0.875rem !important; +} + +/* Table Styles - HELLE, LESBARE VERSION */ +.table { + border-radius: 0.5rem !important; + overflow: hidden !important; + box-shadow: 0 2px 8px rgba(0, 102, 204, 0.08) !important; + background-color: oklch(var(--b1)) ; + border: 1px solid #e3f2fd ; +} + +.table thead th { + background: oklch(var(--p) / 0.1) ; + border: none ; + color: oklch(var(--p)) ; + font-weight: 600 !important; + padding: 1rem !important; + font-size: 0.875rem !important; + text-transform: uppercase !important; + letter-spacing: 0.05em !important; + border-bottom: 2px solid oklch(var(--p)) !important; +} + +.table tbody tr { + transition: all 0.2s ease-in-out !important; + border-bottom: 1px solid #f1f3f4 !important; + background-color: oklch(var(--b1)) ; +} + +.table tbody tr:hover { + background-color: oklch(var(--b2)) ; + box-shadow: 0 1px 3px rgba(0, 102, 204, 0.05) !important; +} + +.table tbody td { + padding: 1rem !important; + border: none ; + vertical-align: middle !important; + + background: transparent ; +} + +/* Navigation Styles - HELLE, LESBARE VERSION */ +.navbar { + background: linear-gradient(135deg, oklch(var(--b1)) 0%, oklch(var(--b2)) 100%) ; + border: none ; + border-bottom: 2px solid #e3f2fd !important; + box-shadow: 0 2px 10px rgba(0, 102, 204, 0.08) !important; + padding: 0 !important; +} + +.navbar-brand { + color: oklch(var(--p)) ; + font-weight: 700 !important; + font-size: 1.25rem !important; + letter-spacing: -0.02em !important; + text-shadow: none !important; +} + +.navbar-brand:hover { + color: oklch(var(--p) / 0.9) ; + text-decoration: none !important; +} + +/* Alert Styles */ +.alert { + border: none ; + border-radius: var(--btz-radius) !important; + box-shadow: var(--btz-shadow-sm) !important; +} + +.alert-success { + background-color: rgba(40, 167, 69, 0.1) ; + color: var(--btz-success) ; + border-left: 4px solid var(--btz-success) !important; +} + +.alert-danger { + background-color: rgba(220, 53, 69, 0.1) ; + color: var(--btz-danger) ; + border-left: 4px solid var(--btz-danger) !important; +} + +.alert-warning { + background-color: rgba(255, 193, 7, 0.1) ; + color: #856404 ; + border-left: 4px solid var(--btz-warning) !important; +} + +.alert-info { + background-color: rgba(23, 162, 184, 0.1) ; + color: var(--btz-info) ; + border-left: 4px solid var(--btz-info) !important; +} + +/* Badge Styles */ +.badge { + border-radius: var(--btz-radius-sm) !important; + font-weight: 600 !important; + padding: 0.25rem 0.75rem !important; + font-size: 0.75rem !important; +} + +.badge-primary { + background-color: var(--btz-primary) ; + color: white ; +} + +.badge-success { + background-color: var(--btz-success) ; + color: white ; +} + +.badge-danger { + background-color: var(--btz-danger) ; + color: white ; +} + +.badge-danger.badge-sm { + background-color: var(--btz-danger) ; + color: white ; + border-radius: var(--btz-radius-sm) !important; + font-weight: 600 !important; + box-shadow: 0 2px 4px rgba(220, 53, 69, 0.3) !important; +} + +.badge-warning { + background-color: var(--btz-warning) ; + +} + +.badge-error { + background-color: var(--btz-danger) ; + color: white ; +} + +.badge-error.badge-sm { + background-color: var(--btz-danger) ; + color: white ; + border-radius: 50% !important; + min-width: 1.25rem !important; + height: 1.25rem !important; + padding: 0.125rem 0.375rem !important; + font-size: 0.75rem !important; + font-weight: 700 !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + box-shadow: 0 2px 4px rgba(220, 53, 69, 0.3) !important; +} + +/* Sidebar Styles - HELLE, LESBARE VERSION */ +.sidebar { + background-color: oklch(var(--b1)) ; + border-right: 2px solid #e3f2fd !important; + box-shadow: 0 0 10px rgba(0, 102, 204, 0.05) !important; +} + +.sidebar .nav-link { + + border-radius: 0.5rem !important; + margin: 0.25rem 0.5rem !important; + padding: 0.75rem 1rem !important; + transition: all 0.2s ease-in-out !important; + font-weight: 500 !important; + background: transparent ; + border: none ; +} + +.sidebar .nav-link:hover { + background-color: #e3f2fd ; + color: oklch(var(--p)) ; + transform: translateX(4px) !important; + box-shadow: 0 2px 8px rgba(0, 102, 204, 0.1) !important; +} + +.sidebar .nav-link.active { + background: oklch(var(--p) / 0.1) ; + color: oklch(var(--p)) ; + box-shadow: 0 2px 8px rgba(0, 102, 204, 0.15) !important; + font-weight: 600 !important; +} + +/* Modal Styles */ +.modal-content { + border: none ; + border-radius: var(--btz-radius-lg) !important; + box-shadow: var(--btz-shadow-xl) !important; +} + +.modal-header { + background: var(--btz-accent) ; + border-bottom: 2px solid var(--btz-primary-light) !important; + border-radius: var(--btz-radius-lg) var(--btz-radius-lg) 0 0 !important; +} + +.modal-title { + color: var(--btz-text) ; + font-weight: 600 !important; +} + +/* Loading States */ +.loading { + position: relative !important; +} + +.loading::after { + content: "" !important; + position: absolute !important; + top: 50% !important; + left: 50% !important; + width: 20px !important; + height: 20px !important; + margin: -10px 0 0 -10px !important; + border: 2px solid var(--btz-primary-light) ; + border-top: 2px solid var(--btz-primary) !important; + border-radius: 50% !important; + animation: spin 1s linear infinite !important; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* ======================================== + BTZ-KÖLN FORM ELEMENTS - IMPROVED + ======================================== */ + +/* Checkbox Styles - Verbesserte Sichtbarkeit */ +input[type="checkbox"] { + appearance: none !important; + -webkit-appearance: none !important; + -moz-appearance: none !important; + width: 1.25rem !important; + height: 1.25rem !important; + border: 2px solid #6c757d ; + background-color: oklch(var(--b1)) ; + border-radius: 0.25rem !important; + position: relative !important; + cursor: pointer !important; + transition: all 0.2s ease-in-out !important; +} + +input[type="checkbox"]:hover { + border-color: oklch(var(--p)) ; + box-shadow: 0 0 0 2px rgba(0, 102, 204, 0.1) !important; +} + +input[type="checkbox"]:checked { + background: oklch(var(--p)) ; + border-color: oklch(var(--p)) ; + box-shadow: 0 0 0 2px rgba(0, 102, 204, 0.2) !important; +} + +input[type="checkbox"]:checked::after { + content: "✓" !important; + color: white ; + font-size: 0.75rem !important; + font-weight: bold !important; + position: absolute !important; + top: 50% !important; + left: 50% !important; + transform: translate(-50%, -50%) !important; +} + +/* Radio Button Styles */ +input[type="radio"] { + appearance: none !important; + -webkit-appearance: none !important; + -moz-appearance: none !important; + width: 1.25rem !important; + height: 1.25rem !important; + border: 2px solid #6c757d ; + background-color: oklch(var(--b1)) ; + border-radius: 50% !important; + position: relative !important; + cursor: pointer !important; + transition: all 0.2s ease-in-out !important; +} + +input[type="radio"]:hover { + border-color: oklch(var(--p)) ; + box-shadow: 0 0 0 2px rgba(0, 102, 204, 0.1) !important; +} + +input[type="radio"]:checked { + border-color: oklch(var(--p)) ; + box-shadow: 0 0 0 2px rgba(0, 102, 204, 0.2) !important; +} + +input[type="radio"]:checked::after { + content: "" !important; + position: absolute !important; + top: 50% !important; + left: 50% !important; + transform: translate(-50%, -50%) !important; + width: 0.5rem !important; + height: 0.5rem !important; + background: oklch(var(--p)) ; + border-radius: 50% !important; +} + +/* Checkbox Styles - Verbesserte Sichtbarkeit (DaisyUI) */ +.checkbox { + border: 2px solid #6c757d ; + background-color: oklch(var(--b1)) ; + transition: all 0.2s ease-in-out !important; + width: 1.25rem !important; + height: 1.25rem !important; + border-radius: 0.25rem !important; +} + +.checkbox:hover { + border-color: oklch(var(--p)) ; + box-shadow: 0 0 0 2px rgba(0, 102, 204, 0.1) !important; +} + +.checkbox:checked { + background: oklch(var(--p)) ; + border-color: oklch(var(--p)) ; + box-shadow: 0 0 0 2px rgba(0, 102, 204, 0.2) !important; +} + +.checkbox:checked::after { + content: "✓" !important; + color: white ; + font-size: 0.75rem !important; + font-weight: bold !important; + position: absolute !important; + top: 50% !important; + left: 50% !important; + transform: translate(-50%, -50%) !important; +} + +/* Dropdown Menu Styles - Weißer Hintergrund für Admin-Menü */ +.dropdown-content { + background-color: oklch(var(--b1)) ; + border: 1px solid #e3f2fd ; + border-radius: 0.5rem !important; + box-shadow: 0 10px 25px rgba(0, 102, 204, 0.1) !important; + +} + +.dropdown-content .menu li a { + + transition: all 0.2s ease-in-out !important; + padding: 0.5rem 0.75rem !important; + border-radius: 0.25rem !important; +} + +.dropdown-content .menu li a:hover { + background: #e3f2fd ; + color: oklch(var(--p)) ; +} + +.dropdown-content .menu li a.active { + background: #bbdefb ; + color: oklch(var(--p)) ; + font-weight: 600 !important; +} + +.dropdown-content .divider { + border-color: #e3f2fd ; +} + +/* Menu Styles für bessere Konsistenz */ +.menu { + background-color: oklch(var(--b1)) ; +} + +.menu li a { + +} + +.menu li a:hover { + background: #e3f2fd ; + color: oklch(var(--p)) ; +} + +/* Modal/Dialog Hintergrund - Sicherstellen, dass er nicht transparent ist */ +.modal { + background: rgba(0, 0, 0, 0.5) ; +} + +.modal-box { + background-color: oklch(var(--b1)) ; + border: 1px solid #e3f2fd ; + box-shadow: 0 20px 25px rgba(0, 102, 204, 0.1) !important; +} + /* ! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com */ @@ -566,12 +1165,12 @@ video { --fallback-p: #491eff; --fallback-pc: #d4dbff; --fallback-s: #ff41c7; - --fallback-sc: #fff9fc; + --fallback-sc: oklch(var(--b1)); --fallback-a: #00cfbd; --fallback-ac: #00100d; --fallback-n: #2b3440; --fallback-nc: #d7dde4; - --fallback-b1: #ffffff; + --fallback-b1: oklch(var(--b1)); --fallback-b2: #e5e6e6; --fallback-b3: #e5e6e6; --fallback-bc: #1f2937; @@ -842,7 +1441,7 @@ body { .\!table tr.hover:hover, .\!table tr.hover:nth-child(even):hover { --tw-bg-opacity: 1 !important; - background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))) ; } .table tr.hover:hover, @@ -854,7 +1453,7 @@ body { .\!table tr.hover:hover, .\!table tr.hover:nth-child(even):hover { --tw-bg-opacity: 1 !important; - background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))) ; } .table-zebra tr.hover:hover, @@ -877,8 +1476,8 @@ body { align-items: center !important; justify-content: center !important; border-radius: var(--rounded-btn, 0.5rem) !important; - border-color: transparent !important; - border-color: oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity)) !important; + border-color: transparent ; + border-color: oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity)) ; padding-left: 1rem !important; padding-right: 1rem !important; text-align: center !important; @@ -892,12 +1491,12 @@ body { border-width: var(--border-btn, 1px) !important; transition-property: color, background-color, border-color, opacity, box-shadow, transform !important; --tw-text-opacity: 1 !important; - color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))) !important; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))) ; --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05) !important; --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color) !important; box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow) !important; - outline-color: var(--fallback-bc,oklch(var(--bc)/1)) !important; - background-color: oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity)) !important; + outline-color: var(--fallback-bc,oklch(var(--bc)/1)) ; + background-color: oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity)) ; --tw-bg-opacity: 1 !important; --tw-border-opacity: 1 !important; } @@ -1392,9 +1991,9 @@ body { .\!btn:hover { --tw-border-opacity: 1 !important; - border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity))) !important; + border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity))) ; --tw-bg-opacity: 1 !important; - background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))) ; } @supports (color: color-mix(in oklab, black, black)) { @@ -1403,19 +2002,19 @@ body { in oklab, oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity, 1)) 90%, black - ) !important; + ) ; border-color: color-mix( in oklab, oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity, 1)) 90%, black - ) !important; + ) ; } } @supports not (color: oklch(0% 0 0)) { .\!btn:hover { - background-color: var(--btn-color, var(--fallback-b2)) !important; - border-color: var(--btn-color, var(--fallback-b2)) !important; + background-color: var(--btn-color, var(--fallback-b2)) ; + border-color: var(--btn-color, var(--fallback-b2)) ; } } @@ -1450,9 +2049,9 @@ body { .\!btn:hover { --tw-border-opacity: 1 !important; - border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity))) !important; + border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity))) ; --tw-bg-opacity: 1 !important; - background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))) ; } @supports (color: color-mix(in oklab, black, black)) { @@ -1461,27 +2060,27 @@ body { in oklab, oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity, 1)) 90%, black - ) !important; + ) ; border-color: color-mix( in oklab, oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity, 1)) 90%, black - ) !important; + ) ; } } @supports not (color: oklch(0% 0 0)) { .\!btn:hover { - background-color: var(--btn-color, var(--fallback-b2)) !important; - border-color: var(--btn-color, var(--fallback-b2)) !important; + background-color: var(--btn-color, var(--fallback-b2)) ; + border-color: var(--btn-color, var(--fallback-b2)) ; } } .\!btn:hover { --tw-border-opacity: 1 !important; - border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity))) !important; + border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity))) ; --tw-bg-opacity: 1 !important; - background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))) ; } @supports (color: color-mix(in oklab, black, black)) { @@ -1490,19 +2089,19 @@ body { in oklab, oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity, 1)) 90%, black - ) !important; + ) ; border-color: color-mix( in oklab, oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity, 1)) 90%, black - ) !important; + ) ; } } @supports not (color: oklch(0% 0 0)) { .\!btn:hover { - background-color: var(--btn-color, var(--fallback-b2)) !important; - border-color: var(--btn-color, var(--fallback-b2)) !important; + background-color: var(--btn-color, var(--fallback-b2)) ; + border-color: var(--btn-color, var(--fallback-b2)) ; } } @@ -1633,16 +2232,16 @@ body { .\!btn[disabled]:hover, .\!btn:disabled:hover { --tw-border-opacity: 0 !important; - background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))) ; --tw-bg-opacity: 0.2 !important; - color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))) !important; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))) ; --tw-text-opacity: 0.2 !important; } @supports (color: color-mix(in oklab, black, black)) { .\!btn:is(input[type="checkbox"]:checked):hover, .\!btn:is(input[type="radio"]:checked):hover { - background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black) !important; - border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black) !important; + background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black) ; + border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black) ; } .btn:is(input[type="checkbox"]:checked):hover, .btn:is(input[type="radio"]:checked):hover { @@ -1651,8 +2250,8 @@ body { } .\!btn:is(input[type="checkbox"]:checked):hover, .\!btn:is(input[type="radio"]:checked):hover { - background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black) !important; - border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black) !important; + background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black) ; + border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black) ; } } @@ -1820,9 +2419,9 @@ body { line-height: 1.5rem !important; border-radius: var(--rounded-btn, 0.5rem) !important; border-width: 1px !important; - border-color: transparent !important; + border-color: transparent ; --tw-bg-opacity: 1 !important; - background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))) ; } .input { @@ -2017,8 +2616,8 @@ body { opacity: 0 !important; overscroll-behavior: contain !important; z-index: 999 !important; - background-color: transparent !important; - color: inherit !important; + + color: inherit ; transition-duration: 200ms !important; transition-timing-function: cubic-bezier(0, 0, 0.2, 1) !important; transition-property: transform, opacity, visibility !important; @@ -2488,7 +3087,7 @@ input.tab:checked + .tab-content, top: 0px !important; z-index: 1 !important; --tw-bg-opacity: 1 !important; - background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))) ; } .table :where(.table-pin-rows thead tr) { @@ -2504,7 +3103,7 @@ input.tab:checked + .tab-content, bottom: 0px !important; z-index: 1 !important; --tw-bg-opacity: 1 !important; - background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))) ; } .table :where(.table-pin-rows tfoot tr) { @@ -2520,7 +3119,7 @@ input.tab:checked + .tab-content, left: 0px !important; right: 0px !important; --tw-bg-opacity: 1 !important; - background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))) ; } .table :where(.table-pin-cols tr th) { @@ -2689,11 +3288,11 @@ input.tab:checked + .tab-content, } .badge-error { - border-color: transparent; + border-color: transparent ; --tw-bg-opacity: 1; - background-color: var(--fallback-er,oklch(var(--er)/var(--tw-bg-opacity))); + background-color: var(--btz-danger) ; --tw-text-opacity: 1; - color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity))); + color: white ; } .badge-ghost { @@ -2749,7 +3348,12 @@ input.tab:checked + .tab-content, .badge-outline.badge-error { --tw-text-opacity: 1; - color: var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity))); + color: var(--btz-danger) ; +} + +.badge-outline.badge-danger { + --tw-text-opacity: 1; + color: var(--btz-danger) ; } .btm-nav > *:where(.active) { @@ -2803,8 +3407,8 @@ input.tab:checked + .tab-content, @supports not (color: oklch(0% 0 0)) { .\!btn { - background-color: var(--btn-color, var(--fallback-b2)) !important; - border-color: var(--btn-color, var(--fallback-b2)) !important; + background-color: var(--btn-color, var(--fallback-b2)) ; + border-color: var(--btn-color, var(--fallback-b2)) ; } .btn { @@ -2983,7 +3587,7 @@ input.tab:checked + .tab-content, --tw-shadow: 0 0 #0000 !important; --tw-shadow-colored: 0 0 #0000 !important; box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow) !important; - outline-color: currentColor !important; + outline-color: currentColor ; } .btn.glass { @@ -3118,9 +3722,9 @@ input.tab:checked + .tab-content, .\!btn[disabled], .\!btn:disabled { --tw-border-opacity: 0 !important; - background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))) ; --tw-bg-opacity: 0.2 !important; - color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))) !important; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))) ; --tw-text-opacity: 0.2 !important; } @@ -3138,20 +3742,20 @@ input.tab:checked + .tab-content, .\!btn[disabled], .\!btn:disabled { --tw-border-opacity: 0 !important; - background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))) ; --tw-bg-opacity: 0.2 !important; - color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))) !important; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))) ; --tw-text-opacity: 0.2 !important; } .\!btn:is(input[type="checkbox"]:checked), .\!btn:is(input[type="radio"]:checked) { --tw-border-opacity: 1 !important; - border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))) !important; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))) ; --tw-bg-opacity: 1 !important; - background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))) ; --tw-text-opacity: 1 !important; - color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))) !important; + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))) ; } .btn:is(input[type="checkbox"]:checked), @@ -3167,15 +3771,15 @@ input.tab:checked + .tab-content, .\!btn:is(input[type="checkbox"]:checked), .\!btn:is(input[type="radio"]:checked) { --tw-border-opacity: 1 !important; - border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))) !important; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))) ; --tw-bg-opacity: 1 !important; - background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))) ; --tw-text-opacity: 1 !important; - color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))) !important; + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))) ; } .\!btn:is(input[type="checkbox"]:checked):focus-visible, .\!btn:is(input[type="radio"]:checked):focus-visible { - outline-color: var(--fallback-p,oklch(var(--p)/1)) !important; + outline-color: var(--fallback-p,oklch(var(--p)/1)) ; } .btn:is(input[type="checkbox"]:checked):focus-visible, .btn:is(input[type="radio"]:checked):focus-visible { @@ -3183,7 +3787,7 @@ input.tab:checked + .tab-content, } .\!btn:is(input[type="checkbox"]:checked):focus-visible, .\!btn:is(input[type="radio"]:checked):focus-visible { - outline-color: var(--fallback-p,oklch(var(--p)/1)) !important; + outline-color: var(--fallback-p,oklch(var(--p)/1)) ; } @keyframes button-pop { @@ -3537,8 +4141,8 @@ details.collapse summary::-webkit-details-marker { .\!input input { --tw-bg-opacity: 1 !important; - background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))) !important; - background-color: transparent !important; + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))) ; + } .input input { @@ -3572,11 +4176,11 @@ details.collapse summary::-webkit-details-marker { .\!input:focus, .\!input:focus-within { box-shadow: none !important; - border-color: var(--fallback-bc,oklch(var(--bc)/0.2)) !important; + border-color: var(--fallback-bc,oklch(var(--bc)/0.2)) ; outline-style: solid !important; outline-width: 2px !important; outline-offset: 2px !important; - outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)) !important; + outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)) ; } .input:focus, @@ -3592,11 +4196,11 @@ details.collapse summary::-webkit-details-marker { .\!input:focus, .\!input:focus-within { box-shadow: none !important; - border-color: var(--fallback-bc,oklch(var(--bc)/0.2)) !important; + border-color: var(--fallback-bc,oklch(var(--bc)/0.2)) ; outline-style: solid !important; outline-width: 2px !important; outline-offset: 2px !important; - outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)) !important; + outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)) ; } .input-error { @@ -3616,10 +4220,10 @@ details.collapse summary::-webkit-details-marker { .\!input[disabled] { cursor: not-allowed !important; --tw-border-opacity: 1 !important; - border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))) !important; + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))) ; --tw-bg-opacity: 1 !important; - background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))) !important; - color: var(--fallback-bc,oklch(var(--bc)/0.4)) !important; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))) ; + color: var(--fallback-bc,oklch(var(--bc)/0.4)) ; } .input:has(> input[disabled]), @@ -3639,21 +4243,21 @@ details.collapse summary::-webkit-details-marker { .\!input[disabled] { cursor: not-allowed !important; --tw-border-opacity: 1 !important; - border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))) !important; + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))) ; --tw-bg-opacity: 1 !important; - background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))) !important; - color: var(--fallback-bc,oklch(var(--bc)/0.4)) !important; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))) ; + color: var(--fallback-bc,oklch(var(--bc)/0.4)) ; } .\!input:has(> input[disabled])::-moz-placeholder, .\!input:disabled::-moz-placeholder, .\!input[disabled]::-moz-placeholder { - color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))) !important; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))) ; --tw-placeholder-opacity: 0.2 !important; } .\!input:has(> input[disabled])::placeholder, .\!input:disabled::placeholder, .\!input[disabled]::placeholder { - color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))) !important; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))) ; --tw-placeholder-opacity: 0.2 !important; } @@ -3671,14 +4275,14 @@ details.collapse summary::-webkit-details-marker { } .\!input:has(> input[disabled])::-moz-placeholder, .\!input:disabled::-moz-placeholder, .\!input[disabled]::-moz-placeholder { - color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))) !important; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))) ; --tw-placeholder-opacity: 0.2 !important; } .\!input:has(> input[disabled])::placeholder, .\!input:disabled::placeholder, .\!input[disabled]::placeholder { - color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))) !important; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))) ; --tw-placeholder-opacity: 0.2 !important; } @@ -3907,7 +4511,7 @@ details.collapse summary::-webkit-details-marker { text-overflow: ellipsis !important; white-space: nowrap !important; --tw-bg-opacity: 1 !important; - background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))) ; padding-left: 2rem !important; direction: ltr !important; } @@ -3939,7 +4543,7 @@ details.collapse summary::-webkit-details-marker { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) !important; border-radius: 9999px !important; border-width: 2px !important; - border-color: currentColor !important; + border-color: currentColor ; opacity: 0.6 !important; } @@ -3969,7 +4573,7 @@ details.collapse summary::-webkit-details-marker { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) !important; border-radius: 9999px !important; border-width: 1px !important; - border-color: currentColor !important; + border-color: currentColor ; opacity: 0.6 !important; } @@ -3990,7 +4594,7 @@ details.collapse summary::-webkit-details-marker { .\!modal:not(dialog:not(.modal-open)), .\!modal::backdrop { - background-color: #0006 !important; + background-color: #0006 ; animation: modal-pop 0.2s ease-out !important; } @@ -4002,7 +4606,7 @@ details.collapse summary::-webkit-details-marker { .\!modal:not(dialog:not(.modal-open)), .\!modal::backdrop { - background-color: #0006 !important; + background-color: #0006 ; animation: modal-pop 0.2s ease-out !important; } @@ -4591,7 +5195,7 @@ details.collapse summary::-webkit-details-marker { .\!table tr.active, .\!table tr.active:nth-child(even) { --tw-bg-opacity: 1 !important; - background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))) ; } .table tr.active, @@ -4604,7 +5208,7 @@ details.collapse summary::-webkit-details-marker { .\!table tr.active, .\!table tr.active:nth-child(even) { --tw-bg-opacity: 1 !important; - background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))) !important; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))) ; } .table-zebra tr.active, @@ -4617,7 +5221,7 @@ details.collapse summary::-webkit-details-marker { .\!table :where(thead tr, tbody tr:not(:last-child), tbody tr:first-child:last-child) { border-bottom-width: 1px !important; --tw-border-opacity: 1 !important; - border-bottom-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))) !important; + border-bottom-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))) ; } .table :where(thead tr, tbody tr:not(:last-child), tbody tr:first-child:last-child) { @@ -4631,7 +5235,7 @@ details.collapse summary::-webkit-details-marker { font-size: 0.75rem !important; line-height: 1rem !important; font-weight: 700 !important; - color: var(--fallback-bc,oklch(var(--bc)/0.6)) !important; + color: var(--fallback-bc,oklch(var(--bc)/0.6)) ; } .table :where(thead, tfoot) { @@ -4645,7 +5249,7 @@ details.collapse summary::-webkit-details-marker { .\!table :where(tfoot) { border-top-width: 1px !important; --tw-border-opacity: 1 !important; - border-top-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))) !important; + border-top-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))) ; } .table :where(tfoot) { @@ -4860,6 +5464,20 @@ details.collapse summary::-webkit-details-marker { padding-right: 0.438rem; } +.badge-error.badge-sm { + height: 1.25rem !important; + min-width: 1.25rem !important; + font-size: 0.75rem !important; + line-height: 1.25rem !important; + padding-left: 0.375rem !important; + padding-right: 0.375rem !important; + border-radius: 50% !important; + background-color: var(--btz-danger) ; + color: white ; + font-weight: 700 !important; + box-shadow: 0 2px 4px rgba(220, 53, 69, 0.3) !important; +} + .badge-lg { height: 1.5rem; font-size: 1rem; diff --git a/app/static/css/quickscan.css b/app/static/css/quickscan.css index d49362a..aa12ea2 100755 --- a/app/static/css/quickscan.css +++ b/app/static/css/quickscan.css @@ -1,340 +1,340 @@ -/* iOS Viewport-Fallbacks für Kamera-Container */ -.camera-container { - height: 45dvh; - min-height: 200px; - display: block; - visibility: visible; -} -@supports not (height: 1dvh) { - .camera-container { height: calc(45vh - env(safe-area-inset-top) - env(safe-area-inset-bottom)); } -} -@supports (height: 1svh) { - .camera-container { height: 45svh; } -} -/* QuickScan Styles */ - -/* Card States - Spezifischere Selektoren */ -#itemCard.selected, -#workerCard.selected { - border-color: #fbbf24 !important; - background-color: rgba(251, 191, 36, 0.1) !important; - box-shadow: 0 0 20px rgba(251, 191, 36, 0.3) !important; -} - -#itemCard.success, -#workerCard.success { - border-color: #10b981 !important; - background-color: rgba(16, 185, 129, 0.1) !important; - box-shadow: 0 0 20px rgba(16, 185, 129, 0.3) !important; -} - -.scan-area { - position: relative; - min-height: 60px; - border-radius: 0.5rem; - overflow: hidden; - background: rgba(var(--b1) / 0.1); - backdrop-filter: blur(8px); -} - -.scan-animation { - position: relative; - min-height: 3rem; -} - -.scan-line { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 2px; - background: linear-gradient(90deg, - transparent 0%, - hsl(var(--p) / 0.3) 20%, - hsl(var(--p)) 50%, - hsl(var(--p) / 0.3) 80%, - transparent 100% - ); - box-shadow: 0 0 8px hsl(var(--p) / 0.5); - animation: scanning 1.5s ease-in-out infinite; - z-index: 10; -} - -.scan-overlay { - position: absolute; - inset: 0; - border: 2px solid hsl(var(--p)); - border-radius: 0.5rem; -} - -@keyframes scanning { - 0% { - top: 0; - opacity: 0.8; - } - 50% { - top: calc(100% - 2px); - opacity: 1; - } - 100% { - top: 0; - opacity: 0.8; - } -} - -/* Step Styles */ -.step.step-primary .collapse-title { - background-color: hsl(var(--p)); - color: hsl(var(--pc)); -} - -.step:not(.step-primary) .collapse-content { - opacity: 0.5; -} - -/* Webcam Container */ -#webcamMode { - aspect-ratio: 16/9; - max-height: 200px; - overflow: hidden; - border-radius: 0.5rem; -} - -#video { - width: 100%; - height: 100%; - object-fit: cover; -} - -/* Anpassungen für horizontale Steps */ -.modal-box { - max-height: min(600px, 80vh); - width: min(450px, 95vw); -} - -.steps-horizontal { - margin-bottom: 1rem; -} - -.step { - opacity: 0.7; - transition: all 0.3s ease; -} - -.step.active { - opacity: 1; -} - -/* Steps */ -.steps { - --connector-size: 2px; - --step-padding: 1rem; -} - -.steps .step { - --size: 2rem; -} - -.steps .step:before { - height: var(--connector-size); - background-color: hsl(var(--b3)); -} - -.steps .step.step-primary:before { - background-color: hsl(var(--p)); -} - -.steps .step:after { - width: var(--size); - height: var(--size); - background-color: hsl(var(--b3)); - border: var(--connector-size) solid hsl(var(--b2)); - font-size: 0.8rem; -} - -.steps .step.step-primary:after { - background-color: hsl(var(--p)); - border-color: hsl(var(--p)); - color: hsl(var(--pc)); -} - -/* Content Area */ -#stepContent { - transition: all 0.3s ease-in-out; -} - -/* Transitions */ -.transition-all { - transition-property: all; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -/* Alert Customization */ -.alert { - --padding-y: 0.5rem; - --padding-x: 0.75rem; -} - -/* Input Customization */ -.input-sm { - height: 2rem; - font-size: 0.875rem; -} - -/* Button Customization */ -.btn-sm { - height: 2rem; - min-height: 2rem; - padding-left: 0.75rem; - padding-right: 0.75rem; -} - -/* Content Area */ -.bg-base-200 { - --tw-bg-opacity: 0.5; -} - -/* Progress Steps Container */ -.w-full.px-4.py-2.bg-base-200 { - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} - -/* Content Area Padding anpassen */ -.p-4 { - padding: 0.75rem; -} - -/* Alert Größe optimieren */ -.alert.shadow-sm { - padding: 0.5rem; - min-height: unset; -} - -/* Toast Container */ -#toast-container { - position: fixed; - bottom: 1rem; - right: 1rem; - z-index: 9999; /* Höher als Modal (normalerweise 999) */ - pointer-events: none; /* Erlaubt Klicks durch den Container */ - display: flex; - flex-direction: column; - gap: 0.5rem; -} - -/* Individual Toast */ -#toast-container .alert { - pointer-events: auto; /* Macht den Toast selbst klickbar */ - min-width: 250px; - max-width: 90vw; - backdrop-filter: blur(8px); - border: 1px solid rgba(0,0,0,0.1); - box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), - 0 2px 4px -1px rgba(0, 0, 0, 0.06); -} - -/* Toast Animation */ -#toast-container .alert { - transition: all 0.3s ease; -} - -/* Toast Varianten */ -#toast-container .alert-error { - background-color: hsl(var(--er)); - color: hsl(var(--erc)); -} - -#toast-container .alert-success { - background-color: hsl(var(--su)); - color: hsl(var(--suc)); -} - -#toast-container .alert-info { - background-color: hsl(var(--in)); - color: hsl(var(--inc)); -} - -#toast-container .alert-warning { - background-color: hsl(var(--wa)); - color: hsl(var(--wac)); -} - -/* Scanning Animation */ -.scan-step { - transition: all 0.3s ease-in-out; - opacity: 1; - transform: translateY(0); -} - -.scan-step.hidden { - opacity: 0; - transform: translateY(20px); - pointer-events: none; -} - -/* Confirmation Barcodes */ -canvas { - max-width: 100%; - height: auto; - margin: 0 auto; -} - -/* Success Animation */ -@keyframes success-pulse { - 0% { - transform: scale(0.8); - opacity: 0; - } - 50% { - transform: scale(1.1); - opacity: 0.8; - } - 100% { - transform: scale(1); - opacity: 1; - } -} - -.success-icon { - animation: success-pulse 0.5s ease-out forwards; -} - -/* Mobile Optimierungen */ -@media (max-width: 768px) { - .modal-box { - width: 100%; - height: 100%; - max-height: 100vh; - margin: 0; - border-radius: 0; - } - - .scan-area { - min-height: 80px; - } - - #webcamMode { - max-height: 300px; - } - - .steps-horizontal { - flex-wrap: wrap; - } - - .step { - min-width: 50%; - } -} - -/* Touch-Optimierungen */ -@media (hover: none) { - .btn { - min-height: 44px; /* Bessere Touch-Targets */ - } - - .scan-area { - min-height: 100px; - } -} \ No newline at end of file +/* iOS Viewport-Fallbacks für Kamera-Container */ +.camera-container { + height: 45dvh; + min-height: 200px; + display: block; + visibility: visible; +} +@supports not (height: 1dvh) { + .camera-container { height: calc(45vh - env(safe-area-inset-top) - env(safe-area-inset-bottom)); } +} +@supports (height: 1svh) { + .camera-container { height: 45svh; } +} +/* QuickScan Styles */ + +/* Card States - Spezifischere Selektoren */ +#itemCard.selected, +#workerCard.selected { + border-color: oklch(var(--wa)) !important; + background-color: oklch(var(--wa) / 0.1) !important; + box-shadow: 0 0 20px oklch(var(--wa) / 0.3) !important; +} + +#itemCard.success, +#workerCard.success { + border-color: oklch(var(--su)) !important; + background-color: oklch(var(--su) / 0.1) !important; + box-shadow: 0 0 20px oklch(var(--su) / 0.3) !important; +} + +.scan-area { + position: relative; + min-height: 60px; + border-radius: 0.5rem; + overflow: hidden; + background: rgba(var(--b1) / 0.1); + backdrop-filter: blur(8px); +} + +.scan-animation { + position: relative; + min-height: 3rem; +} + +.scan-line { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 2px; + background: linear-gradient(90deg, + transparent 0%, + oklch(var(--p) / 0.3) 20%, + oklch(var(--p)) 50%, + oklch(var(--p) / 0.3) 80%, + transparent 100% + ); + box-shadow: 0 0 8px oklch(var(--p) / 0.5); + animation: scanning 1.5s ease-in-out infinite; + z-index: 10; +} + +.scan-overlay { + position: absolute; + inset: 0; + border: 2px solid oklch(var(--p)); + border-radius: 0.5rem; +} + +@keyframes scanning { + 0% { + top: 0; + opacity: 0.8; + } + 50% { + top: calc(100% - 2px); + opacity: 1; + } + 100% { + top: 0; + opacity: 0.8; + } +} + +/* Step Styles */ +.step.step-primary .collapse-title { + background-color: oklch(var(--p)); + color: oklch(var(--pc)); +} + +.step:not(.step-primary) .collapse-content { + opacity: 0.5; +} + +/* Webcam Container */ +#webcamMode { + aspect-ratio: 16/9; + max-height: 200px; + overflow: hidden; + border-radius: 0.5rem; +} + +#video { + width: 100%; + height: 100%; + object-fit: cover; +} + +/* Anpassungen für horizontale Steps */ +.modal-box { + max-height: min(600px, 80vh); + width: min(450px, 95vw); +} + +.steps-horizontal { + margin-bottom: 1rem; +} + +.step { + opacity: 0.7; + transition: all 0.3s ease; +} + +.step.active { + opacity: 1; +} + +/* Steps */ +.steps { + --connector-size: 2px; + --step-padding: 1rem; +} + +.steps .step { + --size: 2rem; +} + +.steps .step:before { + height: var(--connector-size); + background-color: oklch(var(--b3)); +} + +.steps .step.step-primary:before { + background-color: oklch(var(--p)); +} + +.steps .step:after { + width: var(--size); + height: var(--size); + background-color: oklch(var(--b3)); + border: var(--connector-size) solid oklch(var(--b2)); + font-size: 0.8rem; +} + +.steps .step.step-primary:after { + background-color: oklch(var(--p)); + border-color: oklch(var(--p)); + color: oklch(var(--pc)); +} + +/* Content Area */ +#stepContent { + transition: all 0.3s ease-in-out; +} + +/* Transitions */ +.transition-all { + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +/* Alert Customization */ +.alert { + --padding-y: 0.5rem; + --padding-x: 0.75rem; +} + +/* Input Customization */ +.input-sm { + height: 2rem; + font-size: 0.875rem; +} + +/* Button Customization */ +.btn-sm { + height: 2rem; + min-height: 2rem; + padding-left: 0.75rem; + padding-right: 0.75rem; +} + +/* Content Area */ +.bg-base-200 { + --tw-bg-opacity: 0.5; +} + +/* Progress Steps Container */ +.w-full.px-4.py-2.bg-base-200 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +/* Content Area Padding anpassen */ +.p-4 { + padding: 0.75rem; +} + +/* Alert Größe optimieren */ +.alert.shadow-sm { + padding: 0.5rem; + min-height: unset; +} + +/* Toast Container */ +#toast-container { + position: fixed; + bottom: 1rem; + right: 1rem; + z-index: 9999; /* Höher als Modal (normalerweise 999) */ + pointer-events: none; /* Erlaubt Klicks durch den Container */ + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +/* Individual Toast */ +#toast-container .alert { + pointer-events: auto; /* Macht den Toast selbst klickbar */ + min-width: 250px; + max-width: 90vw; + backdrop-filter: blur(8px); + border: 1px solid rgba(0,0,0,0.1); + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -1px rgba(0, 0, 0, 0.06); +} + +/* Toast Animation */ +#toast-container .alert { + transition: all 0.3s ease; +} + +/* Toast Varianten */ +#toast-container .alert-error { + background-color: oklch(var(--er)); + color: oklch(var(--erc)); +} + +#toast-container .alert-success { + background-color: oklch(var(--su)); + color: oklch(var(--suc)); +} + +#toast-container .alert-info { + background-color: oklch(var(--in)); + color: oklch(var(--inc)); +} + +#toast-container .alert-warning { + background-color: oklch(var(--wa)); + color: oklch(var(--wac)); +} + +/* Scanning Animation */ +.scan-step { + transition: all 0.3s ease-in-out; + opacity: 1; + transform: translateY(0); +} + +.scan-step.hidden { + opacity: 0; + transform: translateY(20px); + pointer-events: none; +} + +/* Confirmation Barcodes */ +canvas { + max-width: 100%; + height: auto; + margin: 0 auto; +} + +/* Success Animation */ +@keyframes success-pulse { + 0% { + transform: scale(0.8); + opacity: 0; + } + 50% { + transform: scale(1.1); + opacity: 0.8; + } + 100% { + transform: scale(1); + opacity: 1; + } +} + +.success-icon { + animation: success-pulse 0.5s ease-out forwards; +} + +/* Mobile Optimierungen */ +@media (max-width: 768px) { + .modal-box { + width: 100%; + height: 100%; + max-height: 100vh; + margin: 0; + border-radius: 0; + } + + .scan-area { + min-height: 80px; + } + + #webcamMode { + max-height: 300px; + } + + .steps-horizontal { + flex-wrap: wrap; + } + + .step { + min-width: 50%; + } +} + +/* Touch-Optimierungen */ +@media (hover: none) { + .btn { + min-height: 44px; /* Bessere Touch-Targets */ + } + + .scan-area { + min-height: 100px; + } +} diff --git a/app/templates/about.html b/app/templates/about.html index 20f7b23..88b7c0f 100755 --- a/app/templates/about.html +++ b/app/templates/about.html @@ -3,13 +3,13 @@ {% block title %}Über Scandy - Funktionsübersicht & Anleitung{% endblock %} {% block content %} -
+
-
-

Über Scandy

-

Universelles Verwaltungssystem für Inventar, Personal und Aufgaben

-
-
+
+

Über Scandy

+

Universelles Verwaltungssystem für Inventar, Personal und Aufgaben

+
+
@@ -37,10 +37,10 @@

Über Scandy

-
-
-

Benutzerhandbuch – Inhaltsverzeichnis

-
+
+
+

Benutzerhandbuch

+ -
+
-
- 1. Rollen & Berechtigungen +
+ 1. Rollen & Berechtigungen
-
-
+
+
  • Admin: System verwalten (Benutzer, Abteilungen, Feature‑Schalter, Backups). Sieht/bearbeitet alle Abteilungen.
  • Mitarbeiter: In der eigenen Abteilung arbeiten ({{ app_labels.tools.name }}, {{ app_labels.consumables.name }}, Tickets, Ausleihen/Rückgaben).
  • diff --git a/app/templates/admin/auto_backup.html b/app/templates/admin/auto_backup.html index aad70e8..d42df1c 100755 --- a/app/templates/admin/auto_backup.html +++ b/app/templates/admin/auto_backup.html @@ -4,50 +4,50 @@ {% block content %}
    -
    +
    -

    +

    Automatisches Backup-System

    -
    +
    -

    System-Status

    +

    System-Status

    - Status: + Status: Lade...
    - Nächste Backups: - Lade... + Nächste Backups: + Lade...
    - Backup-Zeiten: - Lade... + Backup-Zeiten: + Lade...
    - Nächstes wöchentliches Backup: - Lade... + Nächstes wöchentliches Backup: + Lade...
    - Letztes wöchentliches Backup: - Lade... + Letztes wöchentliches Backup: + Lade...
    - Wöchentliche Backup-E-Mail: - Lade... + Wöchentliche Backup-E-Mail: + Lade...
    -
    +
    -

    Steuerung

    +

    Steuerung

    -
    +
    -

    Konfiguration

    +

    Konfiguration

    @@ -81,9 +81,9 @@

    Konfiguration

    -
    +
    Geben Sie die gewünschten Backup-Zeiten im Format HH:MM ein, getrennt durch Kommas (z.B. 06:00,18:00)
    Konfiguration
    -
    +
    Geben Sie die gewünschte Zeit für das wöchentliche Backup-Archiv im Format HH:MM ein
    Konfiguration
    -
    +
    Geben Sie die E-Mail-Adresse ein, an die das wöchentliche Backup-Archiv gesendet werden soll
    Konfiguration
    -
    +

    • Werkzeuge, Verbrauchsmaterialien, Mitarbeiter

    • Ausleihen, Tickets, Einstellungen

    • Alle Datenbank-Collections

    @@ -159,18 +159,18 @@

    Konfiguration

    -
    +

    • Letzte 10 Backups werden behalten

    • Alte Backups werden automatisch gelöscht

    -
    +

    • Jeden Freitag wird ein ZIP-Archiv aller aktuellen Backups erstellt

    • Das Archiv wird automatisch per E-Mail versendet

    • Maximale E-Mail-Größe: 25MB

    @@ -182,12 +182,12 @@

    Konfiguration

    -
    +
    -

    Backup-Logs

    -
    -
    -

    Lade Logs...

    +

    Backup-Logs

    +
    +
    +

    Lade Logs...

    @@ -352,7 +352,7 @@

    Backup-Logs

    ).join(''); logsContainer.scrollTop = logsContainer.scrollHeight; } else { - logsContainer.innerHTML = '

    Keine Logs verfügbar

    '; + logsContainer.innerHTML = '

    Keine Logs verfügbar

    '; } } else { showToast('error', 'Fehler beim Laden der Logs'); diff --git a/app/templates/admin/cleanup_status.html b/app/templates/admin/cleanup_status.html index bc113d4..c515581 100755 --- a/app/templates/admin/cleanup_status.html +++ b/app/templates/admin/cleanup_status.html @@ -149,7 +149,7 @@

    Keine Benutzer zur Löschung vorgesehen

    -

    Alle Benutzer sind aktuell aktiv und nicht zur Löschung geplant.

    +

    Alle Benutzer sind aktuell aktiv und nicht zur Löschung geplant.

    {% endif %}

    diff --git a/app/templates/admin/manual_lending.html b/app/templates/admin/manual_lending.html index 7bb338f..a2e62d4 100755 --- a/app/templates/admin/manual_lending.html +++ b/app/templates/admin/manual_lending.html @@ -49,17 +49,17 @@

    class="input input-bordered mb-4"> -
    -
    -

    {{ app_labels.tools.name }}

    +
    +
    +

    {{ app_labels.tools.name }}

    + class="w-full h-[calc(100%-4rem)] overflow-y-auto p-2 bg-base-100 text-base-content border-0 focus:outline-none focus:ring-2 focus:ring-blue-500"> {% for item in consumables %} {% endfor %} @@ -123,17 +123,17 @@

    class="input input-bordered mb-4"> -
    -
    -

    Mitarbeiter

    +
    +
    +

    Mitarbeiter

    Zusammenfassung
    -

    Mitarbeiter

    +

    Mitarbeiter

    Kein Mitarbeiter ausgewählt
    @@ -215,7 +215,7 @@

    Aktuelle Ausleihen

    {% if current_lendings %}
    - +
    Artikel @@ -274,7 +274,7 @@

    Aktuelle Ausleihen

    {% else %} -

    Keine aktiven Ausleihen vorhanden.

    +

    Keine aktiven Ausleihen vorhanden.

    {% endif %}
    diff --git a/app/templates/admin/trash.html b/app/templates/admin/trash.html index 796c510..5ba0a3a 100755 --- a/app/templates/admin/trash.html +++ b/app/templates/admin/trash.html @@ -10,7 +10,7 @@

    Papierkorb

    -
    +

    Anzahl gelöschter {{ app_labels.tools.name }}: {{ tools|length }}

    Anzahl gelöschter {{ app_labels.consumables.name }}: {{ consumables|length }}

    Anzahl gelöschter Mitarbeiter: {{ workers|length }}

    diff --git a/app/templates/admin/version_check.html b/app/templates/admin/version_check.html index 24309d3..ee711ab 100755 --- a/app/templates/admin/version_check.html +++ b/app/templates/admin/version_check.html @@ -7,11 +7,11 @@
    -

    +

    Versionscheck

    -

    +

    Prüft ob Updates für {{ app_labels.system_name }} verfügbar sind

    diff --git a/app/templates/auth/login.html b/app/templates/auth/login.html index c00195f..0dee274 100755 --- a/app/templates/auth/login.html +++ b/app/templates/auth/login.html @@ -3,17 +3,17 @@ {% block title %}Anmeldung - {{ config.SYSTEM_NAME }}{% endblock %} {% block content %} -
    -
    +
    +
    -
    -
    - +
    +
    +
    -

    +

    Anmeldung

    -

    {{ config.SYSTEM_NAME }}

    +

    {{ config.SYSTEM_NAME }}

    {% if error %} diff --git a/app/templates/auth/session_error.html b/app/templates/auth/session_error.html index c40fcbc..2333170 100644 --- a/app/templates/auth/session_error.html +++ b/app/templates/auth/session_error.html @@ -11,7 +11,7 @@

    Session-Fehler

    -

    {{ config.SYSTEM_NAME }}

    +

    {{ config.SYSTEM_NAME }}

    @@ -19,7 +19,7 @@

    Nach dem Update ist ein Session-Fehler aufgetreten. Bitte melden Sie sich erneut an.

    -
    +

    Dies kann passieren nach:

    • System-Updates
    • diff --git a/app/templates/base.html b/app/templates/base.html index b954995..7d9decc 100755 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -3,7 +3,6 @@ - {# CSRF deaktiviert - Token nicht verfügbar #} {% block title %}Scandy{% endblock %} @@ -17,7 +16,7 @@ - + @@ -26,10 +25,9 @@ - - - - + + + @@ -37,579 +35,346 @@ - - - - Zum Hauptinhalt springen -
      - -