Menüübersicht
This commit is contained in:
+90
-48
@@ -232,70 +232,111 @@ $themeCss = app_tenant_theme_root_css($tenantSettings);
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Die Kaffeeliste</title>
|
||||
<style>
|
||||
:root{<?= $themeCss ?>--line:rgba(37,24,15,.14);--radius:18px;--shadow:0 16px 36px rgba(37,24,15,.08)}
|
||||
*{box-sizing:border-box}body{margin:0;font-family:"Aptos","Segoe UI",sans-serif;color:var(--ink);background:linear-gradient(180deg,#f9f6ef 0%,var(--bg) 100%)}a{color:inherit}.shell{width:min(1180px,calc(100vw - 32px));margin:20px auto 40px}.bar,.hero,.card,.alert{border:1px solid var(--line);border-radius:var(--radius);background:var(--card);box-shadow:var(--shadow)}.bar,.actions,.context{display:flex;flex-wrap:wrap;gap:10px}.bar{justify-content:space-between;align-items:center;padding:18px 22px;margin-bottom:14px}.brand strong,h1,h2,h3{font-family:Georgia,serif}.brand strong{font-size:1.18rem}.brand span,p,.muted{color:var(--muted)}.hero,.card{padding:24px}.hero{margin-bottom:18px;background:linear-gradient(180deg,#fffdf8 0%,#f9f4ea 100%)}.grid{display:grid;gap:18px}.grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-4{grid-template-columns:repeat(4,minmax(0,1fr))}.tenant-nav-wrap{margin-bottom:18px}.tenant-nav{display:grid;gap:12px;padding:14px 16px;border:1px solid var(--line);border-radius:20px;background:rgba(255,251,244,.92);box-shadow:var(--shadow)}.tenant-nav__desktop{display:flex;align-items:center;gap:14px;justify-content:space-between}.tenant-nav__links{display:flex;gap:10px;flex:1 1 auto;overflow-x:auto;scrollbar-width:none}.tenant-nav__links::-webkit-scrollbar{display:none}.tenant-nav__link,.button,button{display:inline-flex;align-items:center;justify-content:center;padding:10px 14px;border-radius:999px;text-decoration:none;font-weight:700;border:1px solid transparent;cursor:pointer}.tenant-nav__link{background:#fff;color:var(--brand);border-color:rgba(var(--brand-rgb),.12);white-space:nowrap}.tenant-nav__link.active{background:var(--brand);color:#fff}.tenant-nav__mobile{display:none;position:relative}.tenant-nav__mobile[open]{z-index:20}.tenant-nav__toggle{display:inline-flex;align-items:center;justify-content:center;gap:10px;padding:10px 14px;border-radius:999px;text-decoration:none;font-weight:700;border:1px solid rgba(var(--brand-rgb),.12);cursor:pointer;list-style:none;background:#fff;color:var(--brand)}.tenant-nav__toggle::-webkit-details-marker{display:none}.tenant-nav__toggle::before{content:"";width:18px;height:12px;border-top:2px solid currentColor;border-bottom:2px solid currentColor;box-shadow:inset 0 -4px 0 0 currentColor}.tenant-nav__panel{margin-top:12px;padding:14px;border-radius:18px;border:1px solid var(--line);background:#fffdf9;box-shadow:var(--shadow)}.tenant-nav__stack{display:grid;gap:10px}.tenant-nav__logout{display:flex;justify-content:flex-end}.button,button{background:var(--brand);color:#fff}.button.secondary{background:#fff;color:var(--brand);border-color:rgba(var(--brand-rgb),.18)}.eyebrow{display:inline-block;margin-bottom:12px;color:var(--accent);font-size:.82rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase}h1{font-size:clamp(2rem,4vw,3.2rem);margin:0 0 12px}h2{font-size:1.35rem;margin:0 0 12px}h3{font-size:1.05rem;margin:0 0 10px}p{margin:0;line-height:1.6}.stack{display:grid;gap:12px}.metric{padding:18px;border:1px solid var(--line);border-radius:16px;background:#fff}.metric strong{display:block;font-size:1.8rem;margin-bottom:8px}.list{margin:14px 0 0;padding-left:18px;color:var(--muted);line-height:1.7}.alert{padding:16px 18px;margin-bottom:18px}.alert-success{background:rgba(var(--brand-rgb),.08)}.alert-warning{background:rgba(var(--accent-rgb),.1)}.alert-error{background:rgba(154,31,31,.1)}.alert-info{background:rgba(var(--brand-rgb),.08)}.badge{display:inline-flex;align-items:center;padding:7px 12px;border-radius:999px;font-size:.86rem;font-weight:700}.badge-neutral{background:rgba(var(--brand-rgb),.08);color:var(--brand)}.badge-success{background:rgba(var(--brand-rgb),.12);color:var(--brand)}.badge-warning{background:rgba(var(--accent-rgb),.14);color:#8c6500}.table{overflow-x:auto}.table table{width:100%;border-collapse:collapse;min-width:720px}.table th,.table td{padding:13px 10px;border-bottom:1px solid var(--line);text-align:left;vertical-align:top}.table th{font-size:.85rem;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}form.grid{grid-template-columns:repeat(2,minmax(0,1fr))}label{display:flex;flex-direction:column;gap:8px;font-weight:700}input,select,textarea{width:100%;padding:12px 14px;border-radius:14px;border:1px solid rgba(37,24,15,.15);font:inherit;background:#fff;color:var(--ink)}textarea{min-height:120px}.footer{margin-top:18px;text-align:center;color:var(--muted);font-size:.92rem}@media(max-width:960px){.grid-2,.grid-3,.grid-4,form.grid{grid-template-columns:1fr}.bar{align-items:flex-start;flex-direction:column}.tenant-nav__desktop{display:none}.tenant-nav__mobile{display:block}.table table{min-width:0}}@media(min-width:961px){.tenant-nav__mobile{display:none}}
|
||||
:root{<?= $themeCss ?>--line:rgba(37,24,15,.14);--shadow:0 18px 40px rgba(37,24,15,.08);--radius:18px}
|
||||
*{box-sizing:border-box}
|
||||
body{margin:0;min-height:100vh;font-family:"Aptos","Segoe UI",sans-serif;color:var(--ink);background:linear-gradient(180deg,#f9f6ef 0%,var(--bg) 100%)}
|
||||
a{color:inherit;text-decoration:none}
|
||||
h1,h2,h3{font-family:Georgia,serif;letter-spacing:-.02em}
|
||||
.button,button{display:inline-flex;align-items:center;justify-content:center;padding:10px 14px;border-radius:999px;border:1px solid transparent;background:var(--brand);color:#fff;font:inherit;font-weight:700;cursor:pointer}
|
||||
.button.secondary,.button--ghost{background:#fff;color:var(--brand);border-color:rgba(var(--brand-rgb),.18)}
|
||||
.page-shell{width:min(1460px,calc(100vw - 32px));margin:20px auto 40px;display:grid;grid-template-columns:minmax(280px,300px) minmax(0,1fr);gap:20px;align-items:start}
|
||||
.sidebar,.hero,.card,.alert{border:1px solid var(--line);border-radius:var(--radius);background:var(--card);box-shadow:var(--shadow)}
|
||||
.sidebar{position:sticky;top:20px;display:grid;gap:16px;padding:18px;background:rgba(255,251,244,.96)}
|
||||
.sidebar__brand{display:grid;gap:6px;padding-bottom:14px;border-bottom:1px solid rgba(37,24,15,.1)}
|
||||
.sidebar__eyebrow,.eyebrow{display:inline-block;color:var(--accent);text-transform:uppercase;letter-spacing:.14em;font-size:.8rem;font-weight:800}
|
||||
.sidebar__eyebrow{margin:0}
|
||||
.sidebar__title{margin:0;font-size:1.55rem;line-height:1.05}
|
||||
.sidebar__subtitle,.muted,p{color:var(--muted)}
|
||||
.sidebar__meta,.actions,.context{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
|
||||
.sidebar__section{display:inline-block;color:var(--accent);text-transform:uppercase;letter-spacing:.14em;font-size:.76rem;font-weight:800}
|
||||
.sidebar__nav,.sidebar__stack,.stack{display:grid;gap:10px}
|
||||
.sidebar__link{display:flex;align-items:center;justify-content:space-between;padding:12px 14px;border-radius:16px;border:1px solid rgba(var(--brand-rgb),.12);background:#fff;color:var(--brand);font-weight:700}
|
||||
.sidebar__link.active{background:var(--brand);color:#fff}
|
||||
.sidebar__footer{display:grid;gap:12px;padding-top:14px;border-top:1px solid rgba(37,24,15,.1)}
|
||||
.sidebar__mobile{display:none}
|
||||
.sidebar__mobile[open]{z-index:20}
|
||||
.sidebar__toggle{display:flex;align-items:center;justify-content:space-between;gap:12px;cursor:pointer;list-style:none;padding:12px 14px;border-radius:16px;border:1px solid rgba(var(--brand-rgb),.12);background:#fff;color:var(--brand);font-weight:700}
|
||||
.sidebar__toggle::-webkit-details-marker{display:none}
|
||||
.sidebar__toggle::after{content:"";width:11px;height:11px;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(45deg);transition:transform .2s ease}
|
||||
.sidebar__mobile[open] .sidebar__toggle::after{transform:rotate(225deg)}
|
||||
.sidebar__panel{margin-top:12px;padding:14px;border-radius:18px;border:1px solid var(--line);background:#fffdf9;box-shadow:var(--shadow)}
|
||||
.content{min-width:0;display:grid;gap:18px}
|
||||
.hero,.card{padding:24px}
|
||||
.hero{margin-bottom:0;background:linear-gradient(180deg,#fffdf8 0%,#f9f4ea 100%)}
|
||||
.grid{display:grid;gap:18px}.grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-4{grid-template-columns:repeat(4,minmax(0,1fr))}
|
||||
h1{font-size:clamp(2rem,4vw,3.2rem);margin:0 0 12px}h2{font-size:1.35rem;margin:0 0 12px}h3{font-size:1.05rem;margin:0 0 10px}p{margin:0;line-height:1.6}
|
||||
.metric{padding:18px;border:1px solid var(--line);border-radius:16px;background:#fff}.metric strong{display:block;font-size:1.8rem;margin-bottom:8px}
|
||||
.list{margin:14px 0 0;padding-left:18px;color:var(--muted);line-height:1.7}
|
||||
.alert{padding:16px 18px;margin-bottom:0}.alert-success{background:rgba(var(--brand-rgb),.08)}.alert-warning{background:rgba(var(--accent-rgb),.1)}.alert-error{background:rgba(154,31,31,.1)}.alert-info{background:rgba(var(--brand-rgb),.08)}
|
||||
.badge{display:inline-flex;align-items:center;padding:7px 12px;border-radius:999px;font-size:.86rem;font-weight:700}
|
||||
.badge-neutral{background:rgba(var(--brand-rgb),.08);color:var(--brand)}.badge-success{background:rgba(var(--brand-rgb),.12);color:var(--brand)}.badge-warning{background:rgba(var(--accent-rgb),.14);color:#8c6500}
|
||||
.table{overflow-x:auto}.table table{width:100%;border-collapse:collapse;min-width:720px}.table th,.table td{padding:13px 10px;border-bottom:1px solid var(--line);text-align:left;vertical-align:top}.table th{font-size:.85rem;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
|
||||
form.grid{grid-template-columns:repeat(2,minmax(0,1fr))}label{display:flex;flex-direction:column;gap:8px;font-weight:700}input,select,textarea{width:100%;padding:12px 14px;border-radius:14px;border:1px solid rgba(37,24,15,.15);font:inherit;background:#fff;color:var(--ink)}textarea{min-height:120px}
|
||||
.footer{margin-top:0;text-align:center;color:var(--muted);font-size:.92rem}
|
||||
@media(max-width:960px){.page-shell{grid-template-columns:1fr;width:min(100vw - 20px,1460px)}.sidebar{position:static}.sidebar__desktop{display:none}.sidebar__mobile{display:block}.grid-2,.grid-3,.grid-4,form.grid{grid-template-columns:1fr}.table table{min-width:0}}
|
||||
@media(min-width:961px){.sidebar__mobile{display:none}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<header class="bar">
|
||||
<div class="brand">
|
||||
<strong>Die Kaffeeliste</strong>
|
||||
<span>Kaffeeliste, Hinweise und Support in einem Menü.</span>
|
||||
<main class="page-shell">
|
||||
<aside class="sidebar" aria-label="Bereichsnavigation">
|
||||
<div class="sidebar__brand">
|
||||
<p class="sidebar__eyebrow">Die Kaffeeliste</p>
|
||||
<h1 class="sidebar__title"><?= $auth === null ? 'Start' : h((string) ($auth['tenant_name'] ?? 'Tenant')) ?></h1>
|
||||
<p class="sidebar__subtitle"><?= $auth === null ? 'Zentrale Anmeldung, Verwaltung und Tenant-Zugriff.' : 'Alle Bereiche des Tenants in einer gemeinsamen Navigation.' ?></p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="tenant-nav-wrap" aria-label="Bereichsnavigation">
|
||||
<div class="tenant-nav">
|
||||
<div class="tenant-nav__desktop">
|
||||
<nav class="tenant-nav__links" aria-label="Navigation">
|
||||
<?php if ($auth === null): ?>
|
||||
<div class="sidebar__meta">
|
||||
<?= badge('Startseite') ?>
|
||||
<?= badge('Mandantenfähig', 'success') ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="sidebar__desktop">
|
||||
<span class="sidebar__section">Bereiche</span>
|
||||
<nav class="sidebar__nav" aria-label="Navigation">
|
||||
<?php if ($auth === null): ?>
|
||||
<a href="/" class="sidebar__link <?= $page === 'home' ? 'active' : '' ?>" <?= $page === 'home' ? 'aria-current="page"' : '' ?>>Start</a>
|
||||
<a href="/login/" class="sidebar__link <?= $page === 'login' ? 'active' : '' ?>" <?= $page === 'login' ? 'aria-current="page"' : '' ?>>Anmeldung</a>
|
||||
<a href="/admin/login/" class="sidebar__link <?= $page === 'tenants' ? 'active' : '' ?>" <?= $page === 'tenants' ? 'aria-current="page"' : '' ?>>Verwaltung</a>
|
||||
<?php else: ?>
|
||||
<?php foreach ($tenantNavItems as $item): ?>
|
||||
<a href="<?= h((string) ($item['href'] ?? '/')) ?>" class="sidebar__link <?= $page === (string) ($item['key'] ?? '') ? 'active' : '' ?>" <?= $page === (string) ($item['key'] ?? '') ? 'aria-current="page"' : '' ?>><?= h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</nav>
|
||||
<div class="sidebar__footer">
|
||||
<?php if ($auth !== null): ?>
|
||||
<form method="post" action="/logout/"><button type="submit" class="button secondary">Abmelden</button></form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<details class="sidebar__mobile">
|
||||
<summary class="sidebar__toggle">Menü</summary>
|
||||
<div class="sidebar__panel">
|
||||
<nav class="sidebar__stack" aria-label="Mobile Navigation">
|
||||
<?php if ($auth === null): ?>
|
||||
<a href="/" class="tenant-nav__link <?= $page === 'home' ? 'active' : '' ?>" <?= $page === 'home' ? 'aria-current="page"' : '' ?>>Start</a>
|
||||
<a href="/login/" class="tenant-nav__link <?= $page === 'login' ? 'active' : '' ?>" <?= $page === 'login' ? 'aria-current="page"' : '' ?>>Anmeldung</a>
|
||||
<a href="/admin/login/" class="tenant-nav__link <?= $page === 'tenants' ? 'active' : '' ?>" <?= $page === 'tenants' ? 'aria-current="page"' : '' ?>>Verwaltung</a>
|
||||
<a href="/" class="sidebar__link <?= $page === 'home' ? 'active' : '' ?>" <?= $page === 'home' ? 'aria-current="page"' : '' ?>>Start</a>
|
||||
<a href="/login/" class="sidebar__link <?= $page === 'login' ? 'active' : '' ?>" <?= $page === 'login' ? 'aria-current="page"' : '' ?>>Anmeldung</a>
|
||||
<a href="/admin/login/" class="sidebar__link <?= $page === 'tenants' ? 'active' : '' ?>" <?= $page === 'tenants' ? 'aria-current="page"' : '' ?>>Verwaltung</a>
|
||||
<?php else: ?>
|
||||
<?php foreach ($tenantNavItems as $item): ?>
|
||||
<a href="<?= h((string) ($item['href'] ?? '/')) ?>" class="tenant-nav__link <?= $page === (string) ($item['key'] ?? '') ? 'active' : '' ?>" <?= $page === (string) ($item['key'] ?? '') ? 'aria-current="page"' : '' ?>><?= h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<a href="<?= h((string) ($item['href'] ?? '/')) ?>" class="sidebar__link <?= $page === (string) ($item['key'] ?? '') ? 'active' : '' ?>" <?= $page === (string) ($item['key'] ?? '') ? 'aria-current="page"' : '' ?>><?= h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</nav>
|
||||
<?php if ($auth !== null): ?>
|
||||
<form class="tenant-nav__logout" method="post" action="/logout/"><button type="submit" class="button secondary">Abmelden</button></form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<details class="tenant-nav__mobile">
|
||||
<summary class="tenant-nav__toggle">Navigation</summary>
|
||||
<div class="tenant-nav__panel">
|
||||
<nav class="tenant-nav__stack" aria-label="Mobile Navigation">
|
||||
<?php if ($auth === null): ?>
|
||||
<a href="/" class="tenant-nav__link <?= $page === 'home' ? 'active' : '' ?>" <?= $page === 'home' ? 'aria-current="page"' : '' ?>>Start</a>
|
||||
<a href="/login/" class="tenant-nav__link <?= $page === 'login' ? 'active' : '' ?>" <?= $page === 'login' ? 'aria-current="page"' : '' ?>>Anmeldung</a>
|
||||
<a href="/admin/login/" class="tenant-nav__link <?= $page === 'tenants' ? 'active' : '' ?>" <?= $page === 'tenants' ? 'aria-current="page"' : '' ?>>Verwaltung</a>
|
||||
<?php else: ?>
|
||||
<?php foreach ($tenantNavItems as $item): ?>
|
||||
<a href="<?= h((string) ($item['href'] ?? '/')) ?>" class="tenant-nav__link <?= $page === (string) ($item['key'] ?? '') ? 'active' : '' ?>" <?= $page === (string) ($item['key'] ?? '') ? 'aria-current="page"' : '' ?>><?= h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</nav>
|
||||
<div class="sidebar__footer">
|
||||
<?php if ($auth !== null): ?>
|
||||
<form class="tenant-nav__logout" method="post" action="/logout/"><button type="submit" class="button secondary">Abmelden</button></form>
|
||||
<form method="post" action="/logout/"><button type="submit" class="button secondary">Abmelden</button></form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php if ($auth !== null): ?>
|
||||
<section class="card">
|
||||
<div class="context">
|
||||
<?= badge((string) $auth['tenant_name']) ?>
|
||||
<span class="muted"><?= h((string) $auth['display_name']) ?> ist angemeldet als <?= h((string) $auth['email']) ?></span>
|
||||
<?= app_is_platform_admin($auth) ? badge('Global-Admin', 'success') : (app_is_tenant_admin($auth) ? badge('Tenant-Admin', 'success') : badge('Mitglied')) ?>
|
||||
<?= badge('Lizenz ' . (string) ($tenantLicense['plan_name'] ?? 'Free')) ?>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
</details>
|
||||
</aside>
|
||||
|
||||
<div class="content">
|
||||
<?php if ($auth !== null && !empty($auth['acting_as_platform_admin'])): ?>
|
||||
<section class="alert alert-info">
|
||||
Du siehst diesen Mandanten mit erweitertem Global-Admin-Zugriff.
|
||||
@@ -810,6 +851,7 @@ $themeCss = app_tenant_theme_root_css($tenantSettings);
|
||||
<?php endif; ?>
|
||||
|
||||
<p class="footer">Die Kaffeeliste | zentrale Anmeldung, Tenant-Verwaltung und alle Kernprozesse der modernen Kaffeeliste</p>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -59,46 +59,158 @@ $themeCss = app_tenant_theme_root_css($tenantSettings);
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Die Kaffeeliste - Umfragen</title>
|
||||
<title>Die Kaffeeliste</title>
|
||||
<style>
|
||||
:root{<?= $themeCss ?>--line:rgba(37,24,15,.14);--shadow:0 16px 36px rgba(37,24,15,.08);--radius:18px;--radius-lg:16px;--content-width:1200px}
|
||||
:root{<?= $themeCss ?>--line:rgba(37,24,15,.14);--shadow:0 18px 40px rgba(37,24,15,.08);--radius:18px}
|
||||
*{box-sizing:border-box}
|
||||
body{margin:0;min-height:100vh;font-family:"Aptos","Segoe UI",sans-serif;color:var(--ink);background:linear-gradient(180deg,#f9f6ef 0%,var(--bg) 100%)}
|
||||
body{
|
||||
margin:0;
|
||||
min-height:100vh;
|
||||
font-family:"Aptos","Segoe UI",sans-serif;
|
||||
color:var(--ink);
|
||||
background:linear-gradient(180deg,#f9f6ef 0%,var(--bg) 100%);
|
||||
}
|
||||
a{color:inherit;text-decoration:none}
|
||||
h1,h2,h3,.brand__title{font-family:Georgia,serif;letter-spacing:-.02em}
|
||||
.shell{width:min(var(--content-width),calc(100vw - 32px));margin:20px auto 40px}
|
||||
.bar,.hero,.panel,.table-card,.note{border:1px solid var(--line);border-radius:var(--radius);background:var(--card);box-shadow:var(--shadow)}
|
||||
.bar{display:flex;justify-content:space-between;gap:16px;align-items:center;padding:18px 22px;margin-bottom:18px}
|
||||
.brand{display:grid;gap:4px}
|
||||
.brand__title{font-size:1.18rem;font-weight:700}
|
||||
.brand__subtitle{color:var(--muted)}
|
||||
.toolbar,.meta,.stack{display:flex;flex-wrap:wrap;gap:10px}
|
||||
.meta,.stack{display:flex;flex-wrap:wrap;gap:10px}
|
||||
.tenant-nav-wrap{margin-bottom:18px}
|
||||
.tenant-nav{display:grid;gap:12px;padding:14px 16px;border:1px solid var(--line);border-radius:20px;background:rgba(255,251,244,.92);box-shadow:var(--shadow)}
|
||||
.tenant-nav__desktop{display:flex;align-items:center;gap:14px;justify-content:space-between}
|
||||
.tenant-nav__links{display:flex;gap:10px;flex:1 1 auto;overflow-x:auto;scrollbar-width:none}
|
||||
.tenant-nav__links::-webkit-scrollbar{display:none}
|
||||
.tenant-nav__link,.button,.pill,button{display:inline-flex;align-items:center;justify-content:center;padding:10px 14px;border-radius:999px;font-weight:700;border:1px solid transparent}
|
||||
.tenant-nav__link{background:#fff;color:var(--brand);border-color:rgba(var(--brand-rgb),.12);white-space:nowrap}
|
||||
.tenant-nav__link.active{background:var(--brand);color:#fff}
|
||||
.tenant-nav__mobile{display:none;position:relative}
|
||||
.tenant-nav__mobile[open]{z-index:20}
|
||||
.tenant-nav__toggle{display:inline-flex;align-items:center;gap:10px;list-style:none;cursor:pointer;padding:10px 14px;border-radius:999px;background:#fff;color:var(--brand);font-weight:700;border:1px solid rgba(var(--brand-rgb),.12)}
|
||||
.tenant-nav__toggle::-webkit-details-marker{display:none}
|
||||
.tenant-nav__toggle::before{content:"";width:18px;height:12px;border-top:2px solid currentColor;border-bottom:2px solid currentColor;box-shadow:inset 0 -4px 0 0 currentColor}
|
||||
.tenant-nav__panel{margin-top:12px;padding:14px;border-radius:18px;border:1px solid var(--line);background:#fffdf9;box-shadow:var(--shadow)}
|
||||
.tenant-nav__stack{display:grid;gap:10px}
|
||||
.tenant-nav__logout{display:flex;justify-content:flex-end}
|
||||
.badge,.pill{display:inline-flex;align-items:center;padding:7px 12px;border-radius:999px;background:#fff;color:var(--brand);font-weight:700;font-size:.86rem;border:1px solid rgba(var(--brand-rgb),.12)}
|
||||
.badge--solid{background:var(--brand);color:#fff}
|
||||
.hero{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(260px,.65fr);gap:20px;padding:24px;margin-bottom:18px;background:linear-gradient(180deg,#fffdf8 0%,#f9f4ea 100%)}
|
||||
h1,h2,h3,.brand__title,.hero__title{font-family:Georgia,serif;letter-spacing:-.02em}
|
||||
.button,button{
|
||||
display:inline-flex;
|
||||
align-items:center;
|
||||
justify-content:center;
|
||||
padding:10px 14px;
|
||||
border-radius:999px;
|
||||
border:1px solid transparent;
|
||||
background:var(--brand);
|
||||
color:#fff;
|
||||
font:inherit;
|
||||
font-weight:700;
|
||||
cursor:pointer;
|
||||
}
|
||||
.button--ghost{
|
||||
background:#fff;
|
||||
color:var(--brand);
|
||||
border-color:rgba(var(--brand-rgb),.18);
|
||||
}
|
||||
.page-shell{
|
||||
width:min(1460px,calc(100vw - 32px));
|
||||
margin:20px auto 40px;
|
||||
display:grid;
|
||||
grid-template-columns:minmax(280px,300px) minmax(0,1fr);
|
||||
gap:20px;
|
||||
align-items:start;
|
||||
}
|
||||
.sidebar,.hero,.panel,.table-card,.note{
|
||||
border:1px solid var(--line);
|
||||
border-radius:var(--radius);
|
||||
background:var(--card);
|
||||
box-shadow:var(--shadow);
|
||||
}
|
||||
.sidebar{
|
||||
position:sticky;
|
||||
top:20px;
|
||||
display:grid;
|
||||
gap:16px;
|
||||
padding:18px;
|
||||
background:rgba(255,251,244,.96);
|
||||
}
|
||||
.sidebar__brand{
|
||||
display:grid;
|
||||
gap:6px;
|
||||
padding-bottom:14px;
|
||||
border-bottom:1px solid rgba(37,24,15,.1);
|
||||
}
|
||||
.sidebar__eyebrow{
|
||||
margin:0;
|
||||
color:var(--accent);
|
||||
text-transform:uppercase;
|
||||
letter-spacing:.16em;
|
||||
font-size:.78rem;
|
||||
font-weight:800;
|
||||
}
|
||||
.sidebar__title,.panel h2,.table-card h2{font-family:Georgia,serif;letter-spacing:-.02em}
|
||||
.sidebar__title{
|
||||
margin:0;
|
||||
font-size:1.55rem;
|
||||
line-height:1.05;
|
||||
}
|
||||
.sidebar__subtitle,.muted{color:var(--muted)}
|
||||
.sidebar__meta,.toolbar,.meta{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
|
||||
.stack{display:grid;gap:10px}
|
||||
.sidebar__section{
|
||||
display:inline-block;
|
||||
color:var(--accent);
|
||||
text-transform:uppercase;
|
||||
letter-spacing:.14em;
|
||||
font-size:.76rem;
|
||||
font-weight:800;
|
||||
}
|
||||
.sidebar__nav{display:grid;gap:10px}
|
||||
.sidebar__link{
|
||||
display:flex;
|
||||
align-items:center;
|
||||
justify-content:space-between;
|
||||
padding:12px 14px;
|
||||
border-radius:16px;
|
||||
border:1px solid rgba(var(--brand-rgb),.12);
|
||||
background:#fff;
|
||||
color:var(--brand);
|
||||
font-weight:700;
|
||||
}
|
||||
.sidebar__link.active{background:var(--brand);color:#fff}
|
||||
.sidebar__footer{
|
||||
display:grid;
|
||||
gap:12px;
|
||||
padding-top:14px;
|
||||
border-top:1px solid rgba(37,24,15,.1);
|
||||
}
|
||||
.sidebar__mobile{display:none}
|
||||
.sidebar__mobile[open]{z-index:20}
|
||||
.sidebar__toggle{
|
||||
display:flex;
|
||||
align-items:center;
|
||||
justify-content:space-between;
|
||||
gap:12px;
|
||||
cursor:pointer;
|
||||
list-style:none;
|
||||
padding:12px 14px;
|
||||
border-radius:16px;
|
||||
border:1px solid rgba(var(--brand-rgb),.12);
|
||||
background:#fff;
|
||||
color:var(--brand);
|
||||
font-weight:700;
|
||||
}
|
||||
.sidebar__toggle::-webkit-details-marker{display:none}
|
||||
.sidebar__toggle::after{
|
||||
content:"";
|
||||
width:11px;
|
||||
height:11px;
|
||||
border-right:2px solid currentColor;
|
||||
border-bottom:2px solid currentColor;
|
||||
transform:rotate(45deg);
|
||||
transition:transform .2s ease;
|
||||
}
|
||||
.sidebar__mobile[open] .sidebar__toggle::after{transform:rotate(225deg)}
|
||||
.sidebar__panel{
|
||||
margin-top:12px;
|
||||
padding:14px;
|
||||
border-radius:18px;
|
||||
border:1px solid var(--line);
|
||||
background:#fffdf9;
|
||||
box-shadow:var(--shadow);
|
||||
}
|
||||
.sidebar__stack{display:grid;gap:10px}
|
||||
.content{min-width:0;display:grid;gap:18px}
|
||||
.hero{
|
||||
display:grid;
|
||||
grid-template-columns:minmax(0,1.35fr) minmax(260px,.65fr);
|
||||
gap:20px;
|
||||
padding:24px;
|
||||
margin-bottom:0;
|
||||
background:linear-gradient(180deg,#fffdf8 0%,#f9f4ea 100%);
|
||||
}
|
||||
.hero__kicker{margin:0 0 10px;color:var(--accent);text-transform:uppercase;letter-spacing:.15em;font-size:.8rem;font-weight:800}
|
||||
.hero__title{margin:0 0 12px;font-size:clamp(1.9rem,4vw,3rem);line-height:1.05}
|
||||
.hero__lead{margin:0;color:var(--muted);max-width:70ch;line-height:1.7}
|
||||
.hero__actions{display:flex;flex-wrap:wrap;gap:12px;margin-top:16px}
|
||||
.button{background:var(--brand);color:#fff}
|
||||
.button--ghost{background:#fff;color:var(--brand);border-color:rgba(var(--brand-rgb),.18)}
|
||||
.grid{display:grid;gap:18px}
|
||||
.grid--2{grid-template-columns:repeat(2,minmax(0,1fr))}
|
||||
.grid--3{grid-template-columns:repeat(3,minmax(0,1fr))}
|
||||
@@ -123,47 +235,90 @@ $themeCss = app_tenant_theme_root_css($tenantSettings);
|
||||
.note{padding:16px 18px;margin-top:16px;background:rgba(var(--brand-rgb),.06)}
|
||||
.list-reset{margin:0;padding-left:18px}
|
||||
.list-reset li+li{margin-top:10px}
|
||||
@media(max-width:960px){.hero,.grid--2,.grid--3{grid-template-columns:1fr}.bar{align-items:flex-start;flex-direction:column}.tenant-nav__desktop{display:none}.tenant-nav__mobile{display:block}}
|
||||
@media(min-width:961px){.tenant-nav__mobile{display:none}}
|
||||
.badge{
|
||||
display:inline-flex;
|
||||
align-items:center;
|
||||
padding:7px 12px;
|
||||
border-radius:999px;
|
||||
background:#fff;
|
||||
color:var(--brand);
|
||||
font-weight:700;
|
||||
font-size:.86rem;
|
||||
border:1px solid rgba(var(--brand-rgb),.12);
|
||||
white-space:nowrap;
|
||||
}
|
||||
.badge--solid{background:var(--brand);color:#fff}
|
||||
.pill{
|
||||
display:inline-flex;
|
||||
align-items:center;
|
||||
padding:7px 12px;
|
||||
border-radius:999px;
|
||||
border:1px solid rgba(var(--brand-rgb),.15);
|
||||
background:rgba(var(--brand-rgb),.07);
|
||||
color:var(--brand);
|
||||
font-size:.84rem;
|
||||
font-weight:700;
|
||||
white-space:nowrap;
|
||||
}
|
||||
@media(max-width:960px){
|
||||
.page-shell{grid-template-columns:1fr;width:min(100vw - 20px,1460px)}
|
||||
.sidebar{position:static}
|
||||
.sidebar__desktop{display:none}
|
||||
.sidebar__mobile{display:block}
|
||||
.hero,.grid--2,.grid--3{grid-template-columns:1fr}
|
||||
}
|
||||
@media(min-width:961px){
|
||||
.sidebar__mobile{display:none}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<header class="bar">
|
||||
<div class="brand">
|
||||
<strong class="brand__title">Die Kaffeeliste</strong>
|
||||
<span class="brand__subtitle">Umfragen und Freigaben im Tenant.</span>
|
||||
<main class="page-shell">
|
||||
<aside class="sidebar" aria-label="Bereichsnavigation">
|
||||
<div class="sidebar__brand">
|
||||
<p class="sidebar__eyebrow">Die Kaffeeliste</p>
|
||||
<h1 class="sidebar__title">Umfragen</h1>
|
||||
<p class="sidebar__subtitle">Umfragen und Freigaben im Tenant.</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="tenant-nav-wrap" aria-label="Bereichsnavigation">
|
||||
<div class="tenant-nav">
|
||||
<div class="tenant-nav__desktop">
|
||||
<nav class="tenant-nav__links" aria-label="Tenant-Menü">
|
||||
<div class="sidebar__meta">
|
||||
<span class="badge"><?= h($tenantName) ?></span>
|
||||
<span class="badge"><?= h((string) ($tenantLicense['plan_name'] ?? 'Free')) ?></span>
|
||||
<span class="badge badge--solid">Snapshot</span>
|
||||
</div>
|
||||
|
||||
<div class="sidebar__desktop">
|
||||
<span class="sidebar__section">Bereiche</span>
|
||||
<nav class="sidebar__nav" aria-label="Tenant-Menü">
|
||||
<?php foreach ($tenantNavItems as $item): ?>
|
||||
<a class="sidebar__link <?= (($item['key'] ?? '') === 'surveys') ? 'active' : '' ?>" href="<?= h((string) ($item['href'] ?? '/')) ?>" <?= (($item['key'] ?? '') === 'surveys') ? 'aria-current="page"' : '' ?>><?= h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<?php endforeach; ?>
|
||||
</nav>
|
||||
<div class="sidebar__footer">
|
||||
<form method="post" action="/logout/"><button type="submit" class="button button--ghost">Abmelden</button></form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<details class="sidebar__mobile">
|
||||
<summary class="sidebar__toggle">Menü</summary>
|
||||
<div class="sidebar__panel">
|
||||
<nav class="sidebar__stack" aria-label="Mobiles Tenant-Menü">
|
||||
<?php foreach ($tenantNavItems as $item): ?>
|
||||
<a class="tenant-nav__link <?= (($item['key'] ?? '') === 'surveys') ? 'active' : '' ?>" href="<?= h((string) ($item['href'] ?? '/')) ?>" <?= (($item['key'] ?? '') === 'surveys') ? 'aria-current="page"' : '' ?>><?= h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<a class="sidebar__link <?= (($item['key'] ?? '') === 'surveys') ? 'active' : '' ?>" href="<?= h((string) ($item['href'] ?? '/')) ?>" <?= (($item['key'] ?? '') === 'surveys') ? 'aria-current="page"' : '' ?>><?= h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<?php endforeach; ?>
|
||||
</nav>
|
||||
<form class="tenant-nav__logout" method="post" action="/logout/"><button type="submit" class="button button--ghost">Abmelden</button></form>
|
||||
</div>
|
||||
<details class="tenant-nav__mobile">
|
||||
<summary class="tenant-nav__toggle">Navigation</summary>
|
||||
<div class="tenant-nav__panel">
|
||||
<nav class="tenant-nav__stack" aria-label="Mobiles Tenant-Menü">
|
||||
<?php foreach ($tenantNavItems as $item): ?>
|
||||
<a class="tenant-nav__link <?= (($item['key'] ?? '') === 'surveys') ? 'active' : '' ?>" href="<?= h((string) ($item['href'] ?? '/')) ?>" <?= (($item['key'] ?? '') === 'surveys') ? 'aria-current="page"' : '' ?>><?= h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<?php endforeach; ?>
|
||||
</nav>
|
||||
<form class="tenant-nav__logout" method="post" action="/logout/"><button type="submit" class="button button--ghost">Abmelden</button></form>
|
||||
<div class="sidebar__footer">
|
||||
<form method="post" action="/logout/"><button type="submit" class="button button--ghost">Abmelden</button></form>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</details>
|
||||
</aside>
|
||||
|
||||
<div class="content">
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Umfragen</p>
|
||||
<h1 class="hero__title">Umfragen</h1>
|
||||
<h2 class="hero__title">Umfragen</h2>
|
||||
<p class="hero__lead">
|
||||
Entwürfe bleiben intern bearbeitbar. Mitglieder sehen nur veröffentlichte Stände.
|
||||
</p>
|
||||
@@ -336,6 +491,7 @@ $themeCss = app_tenant_theme_root_css($tenantSettings);
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -28,10 +28,13 @@
|
||||
:root {
|
||||
{!! $layoutThemeCss !!}
|
||||
--line: rgba(44, 32, 23, 0.14);
|
||||
--line-strong: rgba(44, 32, 23, 0.2);
|
||||
--shadow: 0 18px 42px rgba(68, 48, 34, 0.08);
|
||||
--shadow-soft: 0 12px 26px rgba(68, 48, 34, 0.05);
|
||||
--radius-xl: 24px;
|
||||
--radius-lg: 18px;
|
||||
--content-width: 1220px;
|
||||
--sidebar-width: 292px;
|
||||
--content-width: 1260px;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
@@ -41,6 +44,7 @@
|
||||
min-height: 100vh;
|
||||
color: var(--text);
|
||||
background:
|
||||
radial-gradient(circle at top left, rgba(var(--brand-rgb), 0.08), transparent 32%),
|
||||
linear-gradient(180deg, #f8f1e6 0%, var(--bg) 100%);
|
||||
font-family: "Trebuchet MS", "Aptos", "Segoe UI", sans-serif;
|
||||
line-height: 1.55;
|
||||
@@ -55,32 +59,45 @@
|
||||
a:hover { text-decoration: underline; }
|
||||
img { max-width: 100%; }
|
||||
|
||||
.app-shell { min-height: 100vh; }
|
||||
.app-header {
|
||||
.app-shell {
|
||||
width: min(var(--content-width), calc(100% - 28px));
|
||||
margin: 14px auto;
|
||||
min-height: calc(100vh - 28px);
|
||||
display: grid;
|
||||
grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.app-sidebar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 50;
|
||||
border-bottom: 1px solid var(--line);
|
||||
background: rgba(249, 242, 231, 0.96);
|
||||
backdrop-filter: blur(12px);
|
||||
top: 14px;
|
||||
align-self: start;
|
||||
min-height: calc(100vh - 28px);
|
||||
}
|
||||
.app-header__inner,
|
||||
.app-main,
|
||||
.app-footer__inner {
|
||||
width: min(var(--content-width), calc(100% - 32px));
|
||||
margin: 0 auto;
|
||||
|
||||
.app-sidebar__panel {
|
||||
height: calc(100vh - 28px);
|
||||
display: grid;
|
||||
grid-template-rows: auto auto 1fr auto;
|
||||
gap: 20px;
|
||||
padding: 24px 20px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 30px;
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 252, 246, 0.98), rgba(249, 242, 231, 0.96));
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
.app-header__inner {
|
||||
|
||||
.brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 20px;
|
||||
padding: 18px 0;
|
||||
gap: 14px;
|
||||
min-width: 0;
|
||||
}
|
||||
.brand { display: flex; align-items: center; gap: 14px; min-width: 0; }
|
||||
|
||||
.brand__mark {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
width: 46px;
|
||||
height: 46px;
|
||||
border-radius: 16px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
@@ -89,16 +106,19 @@
|
||||
background: linear-gradient(135deg, var(--brand) 0%, #115e59 55%, var(--accent) 100%);
|
||||
box-shadow: 0 12px 26px rgba(45, 106, 79, 0.2);
|
||||
}
|
||||
.brand__text { display: grid; gap: 2px; min-width: 0; }
|
||||
.brand__title { margin: 0; font-size: 1.02rem; font-weight: 700; letter-spacing: 0.01em; }
|
||||
|
||||
.brand__text { display: grid; gap: 3px; min-width: 0; }
|
||||
.brand__title { margin: 0; font-size: 1.16rem; font-weight: 700; letter-spacing: 0.01em; }
|
||||
.brand__subtitle { margin: 0; color: var(--muted); font-size: 0.92rem; }
|
||||
|
||||
.sidebar-meta,
|
||||
.header-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.badge,
|
||||
.pill {
|
||||
display: inline-flex;
|
||||
@@ -112,54 +132,129 @@
|
||||
font-weight: 600;
|
||||
color: var(--brand-strong);
|
||||
}
|
||||
|
||||
.badge--solid { background: var(--brand); color: #fff; border-color: transparent; }
|
||||
.tenant-nav-wrap {
|
||||
width: min(var(--content-width), calc(100% - 32px));
|
||||
margin: 16px auto 0;
|
||||
|
||||
.sidebar-nav {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
align-content: start;
|
||||
}
|
||||
.tenant-nav-shell {
|
||||
|
||||
.sidebar-nav__link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding: 0.88rem 1rem;
|
||||
border-radius: 18px;
|
||||
border: 1px solid rgba(44, 32, 23, 0.08);
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
color: var(--text);
|
||||
font-size: 0.95rem;
|
||||
font-weight: 700;
|
||||
box-shadow: var(--shadow-soft);
|
||||
}
|
||||
|
||||
.sidebar-nav__link::after {
|
||||
content: "›";
|
||||
font-size: 1rem;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.sidebar-nav__link:hover {
|
||||
text-decoration: none;
|
||||
border-color: rgba(var(--brand-rgb), 0.22);
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
}
|
||||
|
||||
.sidebar-nav__link.is-active {
|
||||
background: linear-gradient(135deg, var(--brand) 0%, var(--brand-strong) 100%);
|
||||
color: #fff;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.sidebar-nav__link.is-active::after { color: rgba(255, 255, 255, 0.88); }
|
||||
|
||||
.sidebar-footer {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
align-content: end;
|
||||
}
|
||||
|
||||
.sidebar-note {
|
||||
padding: 14px 16px;
|
||||
border-radius: 18px;
|
||||
background: rgba(var(--brand-rgb), 0.08);
|
||||
border: 1px solid rgba(var(--brand-rgb), 0.12);
|
||||
color: var(--brand-strong);
|
||||
}
|
||||
|
||||
.sidebar-note strong {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.app-body {
|
||||
min-width: 0;
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr auto;
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.context-bar { padding-top: 6px; }
|
||||
|
||||
.context-bar__inner {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 20px 24px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 20px;
|
||||
border-radius: 28px;
|
||||
background: rgba(255, 251, 244, 0.92);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
.tenant-nav__desktop {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
justify-content: space-between;
|
||||
|
||||
.context-copy { display: grid; gap: 6px; }
|
||||
|
||||
.context-copy__title {
|
||||
margin: 0;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.1;
|
||||
}
|
||||
.tenant-nav__links {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex: 1 1 auto;
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
|
||||
.context-copy__lead {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
.tenant-nav__links::-webkit-scrollbar { display: none; }
|
||||
.tenant-nav__mobile {
|
||||
|
||||
.mobile-nav {
|
||||
display: none;
|
||||
position: relative;
|
||||
}
|
||||
.tenant-nav__toggle {
|
||||
|
||||
.mobile-nav[open] { z-index: 40; }
|
||||
|
||||
.mobile-nav__toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
list-style: none;
|
||||
cursor: pointer;
|
||||
padding: 0.72rem 1rem;
|
||||
padding: 0.78rem 1rem;
|
||||
border-radius: 999px;
|
||||
border: 1px solid rgba(44, 32, 23, 0.08);
|
||||
background: rgba(255, 251, 244, 0.94);
|
||||
border: 1px solid var(--line-strong);
|
||||
background: rgba(255, 255, 255, 0.94);
|
||||
color: var(--text);
|
||||
font-size: 0.92rem;
|
||||
font-size: 0.94rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
.tenant-nav__toggle::-webkit-details-marker { display: none; }
|
||||
.tenant-nav__toggle::before {
|
||||
|
||||
.mobile-nav__toggle::-webkit-details-marker { display: none; }
|
||||
|
||||
.mobile-nav__toggle::before {
|
||||
content: "";
|
||||
width: 18px;
|
||||
height: 12px;
|
||||
@@ -167,89 +262,30 @@
|
||||
border-bottom: 2px solid currentColor;
|
||||
box-shadow: inset 0 -4px 0 0 currentColor;
|
||||
}
|
||||
.tenant-nav__panel {
|
||||
margin-top: 12px;
|
||||
padding: 14px;
|
||||
border-radius: 18px;
|
||||
|
||||
.mobile-nav__panel {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: calc(100% + 12px);
|
||||
width: min(320px, calc(100vw - 32px));
|
||||
padding: 16px;
|
||||
border-radius: 24px;
|
||||
border: 1px solid var(--line);
|
||||
background: rgba(255, 252, 246, 0.98);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
.tenant-nav__stack {
|
||||
|
||||
.mobile-nav__stack {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
.tenant-nav__link {
|
||||
padding: 0.75rem 0.95rem;
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(44, 32, 23, 0.08);
|
||||
background: rgba(255, 251, 244, 0.96);
|
||||
color: var(--text);
|
||||
font-size: 0.94rem;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tenant-nav__link.is-primary {
|
||||
background: linear-gradient(135deg, var(--brand) 0%, var(--brand-strong) 100%);
|
||||
color: #fff;
|
||||
}
|
||||
.tenant-nav__link:hover {
|
||||
text-decoration: none;
|
||||
border-color: rgba(var(--brand-rgb), 0.2);
|
||||
background: #fffdf8;
|
||||
}
|
||||
.tenant-nav__logout {
|
||||
|
||||
.mobile-nav__footer {
|
||||
margin-top: 12px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.app-main { padding: 34px 0 56px; }
|
||||
.hero {
|
||||
display: grid;
|
||||
gap: 24px;
|
||||
margin-bottom: 28px;
|
||||
padding: 30px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius-xl);
|
||||
background:
|
||||
linear-gradient(135deg, rgba(255, 251, 244, 0.98), rgba(252, 247, 240, 0.95));
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
.hero--split {
|
||||
grid-template-columns: minmax(0, 1.25fr) minmax(300px, 0.75fr);
|
||||
align-items: stretch;
|
||||
}
|
||||
.hero__content,
|
||||
.hero__aside {
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
}
|
||||
.hero__kicker {
|
||||
margin: 0 0 12px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.15em;
|
||||
font-size: 0.8rem;
|
||||
color: var(--accent);
|
||||
font-weight: 700;
|
||||
}
|
||||
.hero__title {
|
||||
margin: 0;
|
||||
font-size: clamp(2rem, 4vw, 3.6rem);
|
||||
line-height: 1.05;
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
.hero__lead {
|
||||
margin: 0;
|
||||
max-width: 68ch;
|
||||
color: var(--muted);
|
||||
font-size: 1.02rem;
|
||||
}
|
||||
.hero__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 4px; }
|
||||
.hero__meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.button,
|
||||
button,
|
||||
input[type="submit"] {
|
||||
@@ -264,16 +300,69 @@
|
||||
cursor: pointer;
|
||||
box-shadow: 0 12px 24px rgba(var(--brand-rgb), 0.18);
|
||||
}
|
||||
|
||||
.button--ghost {
|
||||
background: transparent;
|
||||
color: var(--brand-strong);
|
||||
border: 1px solid rgba(var(--brand-rgb), 0.18);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.app-main { padding: 0 0 6px; }
|
||||
|
||||
.hero {
|
||||
display: grid;
|
||||
gap: 24px;
|
||||
margin-bottom: 28px;
|
||||
padding: 30px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius-xl);
|
||||
background:
|
||||
linear-gradient(135deg, rgba(255, 251, 244, 0.98), rgba(252, 247, 240, 0.95));
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.hero--split {
|
||||
grid-template-columns: minmax(0, 1.25fr) minmax(300px, 0.75fr);
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.hero__content,
|
||||
.hero__aside {
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.hero__kicker {
|
||||
margin: 0 0 12px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.15em;
|
||||
font-size: 0.8rem;
|
||||
color: var(--accent);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.hero__title {
|
||||
margin: 0;
|
||||
font-size: clamp(2rem, 4vw, 3.6rem);
|
||||
line-height: 1.05;
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
|
||||
.hero__lead {
|
||||
margin: 0;
|
||||
max-width: 68ch;
|
||||
color: var(--muted);
|
||||
font-size: 1.02rem;
|
||||
}
|
||||
|
||||
.hero__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 4px; }
|
||||
.hero__meta { display: flex; flex-wrap: wrap; gap: 10px; }
|
||||
.grid { display: grid; gap: 18px; }
|
||||
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||||
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
||||
|
||||
.card,
|
||||
.panel,
|
||||
.form-panel,
|
||||
@@ -284,6 +373,7 @@
|
||||
box-shadow: var(--shadow);
|
||||
padding: 22px;
|
||||
}
|
||||
|
||||
.card__eyebrow {
|
||||
margin: 0 0 10px;
|
||||
font-size: 0.8rem;
|
||||
@@ -292,21 +382,23 @@
|
||||
color: var(--accent);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.metric { display: grid; gap: 8px; }
|
||||
.metric__value {
|
||||
font-size: clamp(1.6rem, 2.5vw, 2.4rem);
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
|
||||
.metric__label,
|
||||
.muted { color: var(--muted); }
|
||||
|
||||
.list-reset { margin: 0; padding: 0; list-style: none; }
|
||||
.list-reset li + li { margin-top: 12px; }
|
||||
.stack { display: grid; gap: 14px; }
|
||||
.feature-list {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.feature-list { display: grid; gap: 12px; }
|
||||
|
||||
.feature-list__item {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
@@ -316,6 +408,7 @@
|
||||
background: rgba(255, 255, 255, 0.78);
|
||||
border: 1px solid rgba(31, 41, 51, 0.08);
|
||||
}
|
||||
|
||||
.feature-list__badge {
|
||||
flex: 0 0 auto;
|
||||
width: 34px;
|
||||
@@ -327,30 +420,33 @@
|
||||
color: var(--brand-strong);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.feature-list__title {
|
||||
margin: 0 0 4px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.feature-list__copy {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
font-size: 0.94rem;
|
||||
}
|
||||
|
||||
.split {
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
grid-template-columns: minmax(0, 1.4fr) minmax(0, 0.9fr);
|
||||
}
|
||||
|
||||
.auth-summary__card {
|
||||
padding: 16px;
|
||||
border-radius: 18px;
|
||||
background: rgba(255, 255, 255, 0.75);
|
||||
border: 1px solid rgba(31, 41, 51, 0.08);
|
||||
}
|
||||
.tenant-grid {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.tenant-grid { display: grid; gap: 12px; }
|
||||
|
||||
.tenant-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -361,19 +457,11 @@
|
||||
background: rgba(255, 255, 255, 0.82);
|
||||
border: 1px solid rgba(31, 41, 51, 0.08);
|
||||
}
|
||||
.tenant-row__meta {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
}
|
||||
.tenant-row__title {
|
||||
margin: 0;
|
||||
font-weight: 700;
|
||||
}
|
||||
.tenant-row__copy {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
font-size: 0.92rem;
|
||||
}
|
||||
|
||||
.tenant-row__meta { display: grid; gap: 4px; }
|
||||
.tenant-row__title { margin: 0; font-weight: 700; }
|
||||
.tenant-row__copy { margin: 0; color: var(--muted); font-size: 0.92rem; }
|
||||
|
||||
.callout {
|
||||
padding: 16px 18px;
|
||||
border-radius: 18px;
|
||||
@@ -381,21 +469,18 @@
|
||||
border: 1px solid rgba(45, 106, 79, 0.14);
|
||||
color: var(--brand-strong);
|
||||
}
|
||||
|
||||
.callout strong {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.metric--compact {
|
||||
padding: 18px 20px;
|
||||
}
|
||||
.toolbar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
.metric--compact { padding: 18px 20px; }
|
||||
.toolbar { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 18px; }
|
||||
.toolbar .badge { background: #fff; }
|
||||
|
||||
.table-card { overflow: hidden; padding: 0; }
|
||||
|
||||
.table-card__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -403,15 +488,18 @@
|
||||
gap: 16px;
|
||||
padding: 22px 22px 12px;
|
||||
}
|
||||
|
||||
.table-card__body {
|
||||
padding: 0 22px 22px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
min-width: 680px;
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: 0.95rem 0.8rem;
|
||||
@@ -419,6 +507,7 @@
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
th {
|
||||
font-size: 0.8rem;
|
||||
text-transform: uppercase;
|
||||
@@ -427,7 +516,9 @@
|
||||
font-weight: 700;
|
||||
background: rgba(249, 242, 231, 0.6);
|
||||
}
|
||||
|
||||
tr:last-child td { border-bottom: 0; }
|
||||
|
||||
.status {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
@@ -439,11 +530,14 @@
|
||||
font-weight: 700;
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
|
||||
.status--warning { background: rgba(180, 83, 9, 0.12); color: #92400e; }
|
||||
.status--danger { background: rgba(185, 28, 28, 0.12); color: #991b1b; }
|
||||
|
||||
.form-grid { display: grid; gap: 16px; }
|
||||
.field { display: grid; gap: 8px; }
|
||||
label { font-size: 0.9rem; font-weight: 700; }
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
@@ -455,7 +549,9 @@
|
||||
font: inherit;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
textarea { min-height: 120px; resize: vertical; }
|
||||
|
||||
.note {
|
||||
padding: 14px 16px;
|
||||
border-radius: 16px;
|
||||
@@ -463,8 +559,10 @@
|
||||
border: 1px solid rgba(15, 118, 110, 0.12);
|
||||
color: var(--brand-strong);
|
||||
}
|
||||
|
||||
.timeline { display: grid; gap: 14px; }
|
||||
.timeline--tight { gap: 10px; }
|
||||
|
||||
.timeline__item {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
@@ -473,9 +571,12 @@
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
border: 1px solid rgba(31, 41, 51, 0.08);
|
||||
}
|
||||
|
||||
.timeline__title { margin: 0; font-weight: 700; }
|
||||
.timeline__meta { margin: 0; color: var(--muted); font-size: 0.92rem; }
|
||||
.app-footer { padding: 0 0 38px; }
|
||||
|
||||
.app-footer { padding: 0 0 12px; }
|
||||
|
||||
.app-footer__inner {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -486,114 +587,144 @@
|
||||
color: var(--muted);
|
||||
font-size: 0.92rem;
|
||||
}
|
||||
@media (max-width: 960px) {
|
||||
|
||||
@media (max-width: 980px) {
|
||||
.app-shell {
|
||||
width: calc(100% - 20px);
|
||||
margin: 10px auto;
|
||||
min-height: calc(100vh - 20px);
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.app-sidebar { display: none; }
|
||||
.mobile-nav { display: block; }
|
||||
.context-bar { padding-top: 0; }
|
||||
.context-bar__inner { padding: 18px; }
|
||||
.grid--2,
|
||||
.grid--3,
|
||||
.grid--4,
|
||||
.split,
|
||||
.hero--split { grid-template-columns: 1fr; }
|
||||
.app-header__inner { flex-direction: column; align-items: flex-start; }
|
||||
.header-meta { justify-content: flex-start; }
|
||||
.tenant-nav__desktop { display: none; }
|
||||
.tenant-nav__mobile { display: block; }
|
||||
.hero,
|
||||
.card,
|
||||
.panel,
|
||||
.form-panel,
|
||||
.table-card { padding: 18px; }
|
||||
.tenant-nav-wrap { width: calc(100% - 32px); }
|
||||
}
|
||||
@media (min-width: 961px) {
|
||||
.tenant-nav__mobile { display: none; }
|
||||
.form-panel { padding: 18px; }
|
||||
.table-card { padding: 0; }
|
||||
table { min-width: 0; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="@yield('body_class')">
|
||||
<div class="app-shell">
|
||||
<header class="app-header">
|
||||
<div class="app-header__inner">
|
||||
<aside class="app-sidebar" aria-label="Tenant-Navigation">
|
||||
<div class="app-sidebar__panel">
|
||||
<div class="brand">
|
||||
<div class="brand__mark">K</div>
|
||||
<div class="brand__text">
|
||||
<div class="brand__text">
|
||||
<h1 class="brand__title">Die Kaffeeliste</h1>
|
||||
<p class="brand__subtitle">Kaffeekasse, Mitglieder und Verwaltung pro Tenant</p>
|
||||
<p class="brand__subtitle">Kaffeekasse und Verwaltung im Tenant</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-meta">
|
||||
@if (is_array($layoutAuth))
|
||||
<span class="badge">{{ $layoutAuth['tenant_name'] ?? 'Tenant' }}</span>
|
||||
@if (function_exists('app_can_manage_tenant') && app_can_manage_tenant($layoutAuth))
|
||||
<span class="badge badge--solid">Verwaltung</span>
|
||||
@else
|
||||
<span class="badge badge--solid">Mitglied</span>
|
||||
@endif
|
||||
@else
|
||||
<span class="badge">Klassische Oberfläche</span>
|
||||
<span class="badge badge--solid">Mandantenfähig</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="tenant-nav-wrap" aria-label="Bereichsnavigation">
|
||||
<div class="tenant-nav-shell">
|
||||
<div class="tenant-nav__desktop">
|
||||
<nav class="tenant-nav__links" aria-label="Hauptnavigation">
|
||||
@forelse ($layoutNavItems as $item)
|
||||
<nav class="sidebar-nav" aria-label="Hauptnavigation">
|
||||
@forelse ($layoutNavItems as $item)
|
||||
@php
|
||||
$itemHref = rtrim((string) ($item['href'] ?? '/'), '/');
|
||||
$itemHref = $itemHref === '' ? '/' : $itemHref;
|
||||
$isActive = $layoutPath === $itemHref;
|
||||
@endphp
|
||||
<a href="{{ $item['href'] ?? '/' }}" class="sidebar-nav__link {{ $isActive ? 'is-active' : '' }}" @if ($isActive) aria-current="page" @endif>{{ $item['label'] ?? 'Link' }}</a>
|
||||
@empty
|
||||
@php
|
||||
$guestItems = [
|
||||
['href' => '/', 'label' => 'Start'],
|
||||
['href' => '/login/', 'label' => 'Anmeldung'],
|
||||
];
|
||||
@endphp
|
||||
@foreach ($guestItems as $item)
|
||||
@php
|
||||
$itemHref = rtrim((string) ($item['href'] ?? '/'), '/');
|
||||
$itemHref = $itemHref === '' ? '/' : $itemHref;
|
||||
$isActive = $layoutPath === $itemHref;
|
||||
@endphp
|
||||
<a href="{{ $item['href'] ?? '/' }}" class="tenant-nav__link {{ $isActive ? 'is-primary' : '' }}" @if ($isActive) aria-current="page" @endif>{{ $item['label'] ?? 'Link' }}</a>
|
||||
@empty
|
||||
<a class="tenant-nav__link is-primary" href="/">Start</a>
|
||||
<a class="tenant-nav__link" href="/login/">Anmeldung</a>
|
||||
@endforelse
|
||||
</nav>
|
||||
<a href="{{ $item['href'] }}" class="sidebar-nav__link {{ $isActive ? 'is-active' : '' }}" @if ($isActive) aria-current="page" @endif>{{ $item['label'] }}</a>
|
||||
@endforeach
|
||||
@endforelse
|
||||
</nav>
|
||||
|
||||
<div class="sidebar-footer">
|
||||
<div class="sidebar-note">
|
||||
<strong>Menü statt Sprungboxen</strong>
|
||||
Bereiche werden über die Navigation geöffnet und nicht mehr im Inhalt verlinkt.
|
||||
</div>
|
||||
@if (is_array($layoutAuth))
|
||||
<form class="tenant-nav__logout" method="post" action="/logout/">
|
||||
<button type="submit" class="button button--ghost">Abmelden</button>
|
||||
<form method="post" action="/logout/">
|
||||
<button type="submit" class="button button--ghost" style="width: 100%;">Abmelden</button>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<details class="tenant-nav__mobile">
|
||||
<summary class="tenant-nav__toggle">Navigation</summary>
|
||||
<div class="tenant-nav__panel">
|
||||
<nav class="tenant-nav__stack" aria-label="Mobile Hauptnavigation">
|
||||
@forelse ($layoutNavItems as $item)
|
||||
@php
|
||||
$itemHref = rtrim((string) ($item['href'] ?? '/'), '/');
|
||||
$itemHref = $itemHref === '' ? '/' : $itemHref;
|
||||
$isActive = $layoutPath === $itemHref;
|
||||
@endphp
|
||||
<a href="{{ $item['href'] ?? '/' }}" class="tenant-nav__link {{ $isActive ? 'is-primary' : '' }}" @if ($isActive) aria-current="page" @endif>{{ $item['label'] ?? 'Link' }}</a>
|
||||
@empty
|
||||
<a class="tenant-nav__link is-primary" href="/">Start</a>
|
||||
<a class="tenant-nav__link" href="/login/">Anmeldung</a>
|
||||
@endforelse
|
||||
</nav>
|
||||
@if (is_array($layoutAuth))
|
||||
<form class="tenant-nav__logout" method="post" action="/logout/">
|
||||
<button type="submit" class="button button--ghost">Abmelden</button>
|
||||
</form>
|
||||
<div class="app-body">
|
||||
<section class="context-bar">
|
||||
<div class="context-bar__inner">
|
||||
<div class="context-copy">
|
||||
<h2 class="context-copy__title">Die Kaffeeliste</h2>
|
||||
<p class="context-copy__lead">
|
||||
@if (is_array($layoutAuth))
|
||||
Ruhige Tenant-Oberfläche mit klarer Navigation und ohne doppelte Statusinfos.
|
||||
@else
|
||||
Anmeldung, Tenant-Zugriff und Verwaltung bleiben in einer ruhigen gemeinsamen Struktur.
|
||||
@endif
|
||||
</p>
|
||||
@if (!is_array($layoutAuth))
|
||||
<div class="header-meta">
|
||||
<span class="badge">Mandantenfähig</span>
|
||||
<span class="badge">Mobil tauglich</span>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<main class="app-main">
|
||||
@yield('content')
|
||||
</main>
|
||||
<details class="mobile-nav">
|
||||
<summary class="mobile-nav__toggle">Menü</summary>
|
||||
<div class="mobile-nav__panel">
|
||||
<nav class="mobile-nav__stack" aria-label="Mobile Hauptnavigation">
|
||||
@forelse ($layoutNavItems as $item)
|
||||
@php
|
||||
$itemHref = rtrim((string) ($item['href'] ?? '/'), '/');
|
||||
$itemHref = $itemHref === '' ? '/' : $itemHref;
|
||||
$isActive = $layoutPath === $itemHref;
|
||||
@endphp
|
||||
<a href="{{ $item['href'] ?? '/' }}" class="sidebar-nav__link {{ $isActive ? 'is-active' : '' }}" @if ($isActive) aria-current="page" @endif>{{ $item['label'] ?? 'Link' }}</a>
|
||||
@empty
|
||||
<a href="/" class="sidebar-nav__link {{ $layoutPath === '/' ? 'is-active' : '' }}">Start</a>
|
||||
<a href="/login/" class="sidebar-nav__link {{ $layoutPath === '/login' ? 'is-active' : '' }}">Anmeldung</a>
|
||||
@endforelse
|
||||
</nav>
|
||||
@if (is_array($layoutAuth))
|
||||
<div class="mobile-nav__footer">
|
||||
<form method="post" action="/logout/">
|
||||
<button type="submit" class="button button--ghost">Abmelden</button>
|
||||
</form>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="app-footer">
|
||||
<div class="app-footer__inner">
|
||||
<span>Die Kaffeeliste</span>
|
||||
<span>Mitglieder, Striche, Einzahlungen, Hinweise und Exporte in einem System</span>
|
||||
</div>
|
||||
</footer>
|
||||
<main class="app-main">
|
||||
@yield('content')
|
||||
</main>
|
||||
|
||||
<footer class="app-footer">
|
||||
<div class="app-footer__inner">
|
||||
<span>Die Kaffeeliste</span>
|
||||
<span>Mitglieder, Striche, Einzahlungen, Hinweise und Exporte in einem System</span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -7,50 +7,174 @@
|
||||
<?php $themeCss = app_tenant_theme_root_css($tenantSettings ?? app_tenant_settings_defaults()); ?>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Die Kaffeeliste - Support</title>
|
||||
<title>Die Kaffeeliste</title>
|
||||
<style>
|
||||
:root{
|
||||
<?= $themeCss ?>
|
||||
--line:rgba(37,24,15,.14);
|
||||
--shadow:0 16px 36px rgba(37,24,15,.08);
|
||||
--shadow:0 18px 40px rgba(37,24,15,.08);
|
||||
--radius:18px;
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0;
|
||||
min-height:100vh;
|
||||
color:var(--ink);
|
||||
font-family:"Aptos","Segoe UI",sans-serif;
|
||||
background:linear-gradient(180deg,#f9f6ef 0%,var(--bg) 100%);
|
||||
}
|
||||
a{color:inherit}
|
||||
.shell{width:min(1240px,calc(100vw - 32px));margin:20px auto 40px}
|
||||
.bar,.hero,.card,.alert{border:1px solid var(--line);border-radius:var(--radius);background:var(--card);box-shadow:var(--shadow)}
|
||||
.bar{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:18px 22px;margin-bottom:18px;flex-wrap:wrap}
|
||||
.brand strong,.hero h1,.card h2,.card h3{font-family:Georgia,serif}
|
||||
.brand strong{font-size:1.18rem}
|
||||
.brand span,p,.muted{color:var(--muted)}
|
||||
.actions,.context{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
|
||||
.tenant-nav-wrap{margin-bottom:18px}
|
||||
.tenant-nav{display:grid;gap:12px;padding:14px 16px;border:1px solid var(--line);border-radius:20px;background:rgba(255,251,244,.92);box-shadow:var(--shadow)}
|
||||
.tenant-nav__desktop{display:flex;align-items:center;gap:14px;justify-content:space-between}
|
||||
.tenant-nav__links{display:flex;gap:10px;flex:1 1 auto;overflow-x:auto;scrollbar-width:none}
|
||||
.tenant-nav__links::-webkit-scrollbar{display:none}
|
||||
.tenant-nav__link,.button,button{display:inline-flex;align-items:center;justify-content:center;padding:10px 14px;border-radius:999px;text-decoration:none;font-weight:700;border:1px solid transparent;cursor:pointer}
|
||||
.tenant-nav__link{background:#fff;color:var(--brand);border-color:rgba(var(--brand-rgb),.12);white-space:nowrap}
|
||||
.tenant-nav__link.active{background:var(--brand);color:#fff}
|
||||
.tenant-nav__mobile{display:none;position:relative}
|
||||
.tenant-nav__mobile[open]{z-index:20}
|
||||
.tenant-nav__toggle{display:inline-flex;align-items:center;gap:10px;list-style:none;cursor:pointer;padding:10px 14px;border-radius:999px;background:#fff;color:var(--brand);font-weight:700;border:1px solid rgba(var(--brand-rgb),.12)}
|
||||
.tenant-nav__toggle::-webkit-details-marker{display:none}
|
||||
.tenant-nav__toggle::before{content:"";width:18px;height:12px;border-top:2px solid currentColor;border-bottom:2px solid currentColor;box-shadow:inset 0 -4px 0 0 currentColor}
|
||||
.tenant-nav__panel{margin-top:12px;padding:14px;border-radius:18px;border:1px solid var(--line);background:#fffdf9;box-shadow:var(--shadow)}
|
||||
.tenant-nav__stack{display:grid;gap:10px}
|
||||
.tenant-nav__logout{display:flex;justify-content:flex-end}
|
||||
.button,button{background:var(--brand);color:#fff}
|
||||
.button.secondary{background:#fff;color:var(--brand);border-color:rgba(var(--brand-rgb),.18)}
|
||||
.hero{padding:24px;margin-bottom:18px;display:grid;gap:18px;background:linear-gradient(180deg,#fffdf8 0%,#f9f4ea 100%)}
|
||||
.hero__kicker{text-transform:uppercase;letter-spacing:.16em;color:var(--accent);font-size:.8rem;font-weight:800;margin:0}
|
||||
.hero__title{margin:0;font-size:clamp(1.9rem,4vw,3rem);line-height:1.05}
|
||||
a{color:inherit;text-decoration:none}
|
||||
.button,button{
|
||||
display:inline-flex;
|
||||
align-items:center;
|
||||
justify-content:center;
|
||||
padding:10px 14px;
|
||||
border-radius:999px;
|
||||
border:1px solid transparent;
|
||||
background:var(--brand);
|
||||
color:#fff;
|
||||
font:inherit;
|
||||
font-weight:700;
|
||||
cursor:pointer;
|
||||
}
|
||||
.button--ghost{
|
||||
background:#fff;
|
||||
color:var(--brand);
|
||||
border-color:rgba(var(--brand-rgb),.18);
|
||||
}
|
||||
.page-shell{
|
||||
width:min(1460px,calc(100vw - 32px));
|
||||
margin:20px auto 40px;
|
||||
display:grid;
|
||||
grid-template-columns:minmax(280px,300px) minmax(0,1fr);
|
||||
gap:20px;
|
||||
align-items:start;
|
||||
}
|
||||
.sidebar,.hero,.card,.alert{
|
||||
border:1px solid var(--line);
|
||||
border-radius:var(--radius);
|
||||
background:var(--card);
|
||||
box-shadow:var(--shadow);
|
||||
}
|
||||
.sidebar{
|
||||
position:sticky;
|
||||
top:20px;
|
||||
display:grid;
|
||||
gap:16px;
|
||||
padding:18px;
|
||||
background:rgba(255,251,244,.96);
|
||||
}
|
||||
.sidebar__brand{
|
||||
display:grid;
|
||||
gap:6px;
|
||||
padding-bottom:14px;
|
||||
border-bottom:1px solid rgba(37,24,15,.1);
|
||||
}
|
||||
.sidebar__eyebrow{
|
||||
margin:0;
|
||||
color:var(--accent);
|
||||
text-transform:uppercase;
|
||||
letter-spacing:.16em;
|
||||
font-size:.78rem;
|
||||
font-weight:800;
|
||||
}
|
||||
.sidebar__title,.hero__title,.card h2,.card h3{
|
||||
font-family:Georgia,serif;
|
||||
letter-spacing:-.02em;
|
||||
}
|
||||
.sidebar__title{
|
||||
margin:0;
|
||||
font-size:1.55rem;
|
||||
line-height:1.05;
|
||||
}
|
||||
.sidebar__subtitle,.muted,p{color:var(--muted)}
|
||||
.sidebar__meta,.actions,.context{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
|
||||
.sidebar__section{
|
||||
display:inline-block;
|
||||
color:var(--accent);
|
||||
text-transform:uppercase;
|
||||
letter-spacing:.14em;
|
||||
font-size:.76rem;
|
||||
font-weight:800;
|
||||
}
|
||||
.sidebar__nav{display:grid;gap:10px}
|
||||
.sidebar__link{
|
||||
display:flex;
|
||||
align-items:center;
|
||||
justify-content:space-between;
|
||||
padding:12px 14px;
|
||||
border-radius:16px;
|
||||
border:1px solid rgba(var(--brand-rgb),.12);
|
||||
background:#fff;
|
||||
color:var(--brand);
|
||||
font-weight:700;
|
||||
}
|
||||
.sidebar__link.active{
|
||||
background:var(--brand);
|
||||
color:#fff;
|
||||
}
|
||||
.sidebar__footer{
|
||||
display:grid;
|
||||
gap:12px;
|
||||
padding-top:14px;
|
||||
border-top:1px solid rgba(37,24,15,.1);
|
||||
}
|
||||
.sidebar__mobile{display:none}
|
||||
.sidebar__mobile[open]{z-index:20}
|
||||
.sidebar__toggle{
|
||||
display:flex;
|
||||
align-items:center;
|
||||
justify-content:space-between;
|
||||
gap:12px;
|
||||
cursor:pointer;
|
||||
list-style:none;
|
||||
padding:12px 14px;
|
||||
border-radius:16px;
|
||||
border:1px solid rgba(var(--brand-rgb),.12);
|
||||
background:#fff;
|
||||
color:var(--brand);
|
||||
font-weight:700;
|
||||
}
|
||||
.sidebar__toggle::-webkit-details-marker{display:none}
|
||||
.sidebar__toggle::after{
|
||||
content:"";
|
||||
width:11px;
|
||||
height:11px;
|
||||
border-right:2px solid currentColor;
|
||||
border-bottom:2px solid currentColor;
|
||||
transform:rotate(45deg);
|
||||
transition:transform .2s ease;
|
||||
}
|
||||
.sidebar__mobile[open] .sidebar__toggle::after{transform:rotate(225deg)}
|
||||
.sidebar__panel{
|
||||
margin-top:12px;
|
||||
padding:14px;
|
||||
border-radius:18px;
|
||||
border:1px solid var(--line);
|
||||
background:#fffdf9;
|
||||
box-shadow:var(--shadow);
|
||||
}
|
||||
.sidebar__stack{display:grid;gap:10px}
|
||||
.content{min-width:0;display:grid;gap:18px}
|
||||
.hero{
|
||||
padding:24px;
|
||||
display:grid;
|
||||
gap:18px;
|
||||
background:linear-gradient(180deg,#fffdf8 0%,#f9f4ea 100%);
|
||||
}
|
||||
.hero__kicker{
|
||||
margin:0 0 10px;
|
||||
color:var(--accent);
|
||||
text-transform:uppercase;
|
||||
letter-spacing:.16em;
|
||||
font-size:.8rem;
|
||||
font-weight:800;
|
||||
}
|
||||
.hero__title{
|
||||
margin:0;
|
||||
font-size:clamp(1.9rem,4vw,3rem);
|
||||
line-height:1.05;
|
||||
}
|
||||
.hero__lead{margin:0;max-width:72ch;font-size:1.02rem;line-height:1.65}
|
||||
.grid{display:grid;gap:18px}
|
||||
.grid--2{grid-template-columns:repeat(2,minmax(0,1fr))}
|
||||
@@ -58,18 +182,44 @@
|
||||
.grid--4{grid-template-columns:repeat(4,minmax(0,1fr))}
|
||||
.card{padding:22px}
|
||||
.card h2,.card h3{margin:0 0 12px}
|
||||
.eyebrow{display:inline-block;margin-bottom:10px;color:var(--accent);font-size:.82rem;font-weight:800;letter-spacing:.12em;text-transform:uppercase}
|
||||
.metric{padding:18px;border-radius:16px;border:1px solid var(--line);background:#fff;display:grid;gap:8px}
|
||||
.eyebrow{
|
||||
display:inline-block;
|
||||
margin-bottom:10px;
|
||||
color:var(--accent);
|
||||
font-size:.82rem;
|
||||
font-weight:800;
|
||||
letter-spacing:.12em;
|
||||
text-transform:uppercase;
|
||||
}
|
||||
.metric{
|
||||
padding:18px;
|
||||
border-radius:16px;
|
||||
border:1px solid var(--line);
|
||||
background:#fff;
|
||||
display:grid;
|
||||
gap:8px;
|
||||
}
|
||||
.metric strong{font-size:1.8rem}
|
||||
.badge{display:inline-flex;align-items:center;padding:7px 12px;border-radius:999px;font-size:.86rem;font-weight:700}
|
||||
.badge{
|
||||
display:inline-flex;
|
||||
align-items:center;
|
||||
padding:7px 12px;
|
||||
border-radius:999px;
|
||||
font-size:.86rem;
|
||||
font-weight:700;
|
||||
border:1px solid rgba(var(--brand-rgb),.12);
|
||||
background:#fff;
|
||||
color:var(--brand);
|
||||
}
|
||||
.badge--neutral{background:rgba(var(--brand-rgb),.1);color:var(--brand)}
|
||||
.badge--success{background:rgba(17,98,61,.12);color:#11623d}
|
||||
.badge--warning{background:rgba(163,75,18,.12);color:#98510c}
|
||||
.badge--danger{background:rgba(154,31,31,.12);color:#9a1f1f}
|
||||
.alert{padding:16px 18px;margin-bottom:18px}
|
||||
.alert{padding:16px 18px}
|
||||
.alert-success{background:rgba(17,98,61,.08)}
|
||||
.alert-warning{background:rgba(163,75,18,.08)}
|
||||
.alert-error{background:rgba(154,31,31,.08)}
|
||||
.alert-info{background:rgba(var(--brand-rgb),.06)}
|
||||
.split{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(360px,.95fr);gap:18px}
|
||||
.stack{display:grid;gap:12px}
|
||||
.table{overflow-x:auto}
|
||||
@@ -83,7 +233,17 @@
|
||||
.timeline__item{padding:14px 16px;border-radius:16px;background:#fff;border:1px solid rgba(31,41,51,.08)}
|
||||
.timeline__meta{margin:0;color:var(--muted);font-size:.94rem;line-height:1.6}
|
||||
.timeline__title{margin:0 0 6px;font-weight:800}
|
||||
.pill{display:inline-flex;align-items:center;padding:7px 12px;border-radius:999px;border:1px solid rgba(var(--brand-rgb),.15);background:rgba(var(--brand-rgb),.07);color:var(--brand);font-size:.84rem;font-weight:700}
|
||||
.pill{
|
||||
display:inline-flex;
|
||||
align-items:center;
|
||||
padding:7px 12px;
|
||||
border-radius:999px;
|
||||
border:1px solid rgba(var(--brand-rgb),.15);
|
||||
background:rgba(var(--brand-rgb),.07);
|
||||
color:var(--brand);
|
||||
font-size:.84rem;
|
||||
font-weight:700;
|
||||
}
|
||||
.status-grid{display:grid;gap:8px}
|
||||
.status{display:inline-flex;align-items:center;gap:8px}
|
||||
.status::before{content:"";width:8px;height:8px;border-radius:999px;background:var(--brand)}
|
||||
@@ -93,84 +253,95 @@
|
||||
.mono{font-family:Consolas,monospace}
|
||||
.footer{margin-top:18px;text-align:center;color:var(--muted);font-size:.92rem}
|
||||
@media(max-width:1040px){
|
||||
.page-shell{grid-template-columns:1fr;width:min(100vw - 20px,1460px)}
|
||||
.sidebar{position:static}
|
||||
.sidebar__desktop{display:none}
|
||||
.sidebar__mobile{display:block}
|
||||
.split,.grid--2,.grid--3,.grid--4{grid-template-columns:1fr}
|
||||
.tenant-nav__desktop{display:none}
|
||||
.tenant-nav__mobile{display:block}
|
||||
table{min-width:0}
|
||||
}
|
||||
@media(min-width:1041px){.tenant-nav__mobile{display:none}}
|
||||
@media(min-width:1041px){
|
||||
.sidebar__mobile{display:none}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<header class="bar">
|
||||
<div class="brand">
|
||||
<strong>Die Kaffeeliste</strong>
|
||||
<span>Support, Vorgänge und Rückmeldungen im Tenant.</span>
|
||||
<main class="page-shell">
|
||||
<aside class="sidebar" aria-label="Bereichsnavigation">
|
||||
<div class="sidebar__brand">
|
||||
<p class="sidebar__eyebrow">Die Kaffeeliste</p>
|
||||
<h1 class="sidebar__title">Support</h1>
|
||||
<p class="sidebar__subtitle">Support, Vorgänge und Rückmeldungen im Tenant.</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="tenant-nav-wrap" aria-label="Bereichsnavigation">
|
||||
<div class="tenant-nav">
|
||||
<div class="tenant-nav__desktop">
|
||||
<nav class="tenant-nav__links" aria-label="Tenant-Menü">
|
||||
<?php foreach ($tenantNavItems as $item): ?>
|
||||
<a href="<?= support_h((string) ($item['href'] ?? '/')) ?>" class="tenant-nav__link <?= (($item['key'] ?? '') === 'support') ? 'active' : '' ?>" <?= (($item['key'] ?? '') === 'support') ? 'aria-current="page"' : '' ?>><?= support_h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<?php endforeach; ?>
|
||||
</nav>
|
||||
<form class="tenant-nav__logout" method="post" action="/logout/"><button type="submit" class="button secondary">Abmelden</button></form>
|
||||
</div>
|
||||
<details class="tenant-nav__mobile">
|
||||
<summary class="tenant-nav__toggle">Navigation</summary>
|
||||
<div class="tenant-nav__panel">
|
||||
<nav class="tenant-nav__stack" aria-label="Mobiles Tenant-Menü">
|
||||
<?php foreach ($tenantNavItems as $item): ?>
|
||||
<a href="<?= support_h((string) ($item['href'] ?? '/')) ?>" class="tenant-nav__link <?= (($item['key'] ?? '') === 'support') ? 'active' : '' ?>" <?= (($item['key'] ?? '') === 'support') ? 'aria-current="page"' : '' ?>><?= support_h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<?php endforeach; ?>
|
||||
</nav>
|
||||
<form class="tenant-nav__logout" method="post" action="/logout/"><button type="submit" class="button secondary">Abmelden</button></form>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="hero">
|
||||
<p class="hero__kicker">Support</p>
|
||||
<h1 class="hero__title">Support</h1>
|
||||
<p class="hero__lead">
|
||||
Mitglieder legen hier Vorgänge an. Verantwortliche verfolgen, beantworten und schließen sie im selben Verlauf.
|
||||
</p>
|
||||
<div class="context">
|
||||
<div class="sidebar__meta">
|
||||
<?= support_badge($isManager ? 'Verantwortlichen-Sicht' : 'Mitgliedersicht', 'success') ?>
|
||||
<?= support_badge('Tenant-weit') ?>
|
||||
<?= support_badge('Status und Routing', 'warning') ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php if ($flash !== null): ?>
|
||||
<section class="alert alert-<?= support_h((string) ($flash['type'] ?? 'success')) ?>">
|
||||
<?= support_h((string) ($flash['message'] ?? '')) ?>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
<div class="sidebar__desktop">
|
||||
<span class="sidebar__section">Bereiche</span>
|
||||
<nav class="sidebar__nav" aria-label="Tenant-Menü">
|
||||
<?php foreach ($tenantNavItems as $item): ?>
|
||||
<a href="<?= support_h((string) ($item['href'] ?? '/')) ?>" class="sidebar__link <?= (($item['key'] ?? '') === 'support') ? 'active' : '' ?>" <?= (($item['key'] ?? '') === 'support') ? 'aria-current="page"' : '' ?>><?= support_h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<?php endforeach; ?>
|
||||
</nav>
|
||||
<div class="sidebar__footer">
|
||||
<form method="post" action="/logout/"><button type="submit" class="button button--ghost">Abmelden</button></form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($dbError !== null): ?>
|
||||
<section class="alert alert-warning"><?= support_h($dbError) ?></section>
|
||||
<?php elseif (!$supportTablesReady): ?>
|
||||
<section class="alert alert-warning">
|
||||
Das Support-Modul ist strukturell vorbereitet, aber die Support-Tabellen sind noch nicht angelegt.
|
||||
Bitte führe die Migrationen aus, bevor du das Modul produktiv nutzt.
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
<details class="sidebar__mobile">
|
||||
<summary class="sidebar__toggle">Menü</summary>
|
||||
<div class="sidebar__panel">
|
||||
<nav class="sidebar__stack" aria-label="Mobiles Tenant-Menü">
|
||||
<?php foreach ($tenantNavItems as $item): ?>
|
||||
<a href="<?= support_h((string) ($item['href'] ?? '/')) ?>" class="sidebar__link <?= (($item['key'] ?? '') === 'support') ? 'active' : '' ?>" <?= (($item['key'] ?? '') === 'support') ? 'aria-current="page"' : '' ?>><?= support_h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<?php endforeach; ?>
|
||||
</nav>
|
||||
<div class="sidebar__footer">
|
||||
<form method="post" action="/logout/"><button type="submit" class="button button--ghost">Abmelden</button></form>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</aside>
|
||||
|
||||
<?php if ($supportTablesReady): ?>
|
||||
<section class="grid grid--4">
|
||||
<article class="metric"><strong><?= support_h((string) ($summary['all'] ?? 0)) ?></strong><h3>Alle Vorgänge</h3><p>Support-Anfragen im aktuellen Tenant.</p></article>
|
||||
<article class="metric"><strong><?= support_h((string) ($summary['new'] ?? 0)) ?></strong><h3>Neu</h3><p>Neue Vorgänge ohne Bearbeitung.</p></article>
|
||||
<article class="metric"><strong><?= support_h((string) ($summary['waiting_on_user'] ?? 0)) ?></strong><h3>Warten auf Antwort</h3><p>Vorgänge mit Rückfrage an Mitglieder.</p></article>
|
||||
<article class="metric"><strong><?= support_h((string) ($summary['resolved'] ?? 0)) ?></strong><h3>Erledigt</h3><p>Abgeschlossene oder gelöste Anfragen.</p></article>
|
||||
<div class="content">
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Support</p>
|
||||
<h2 class="hero__title">Support</h2>
|
||||
<p class="hero__lead">
|
||||
Mitglieder legen hier Vorgänge an. Verantwortliche verfolgen, beantworten und schließen sie im selben Verlauf.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="split" style="margin-top:18px">
|
||||
<?php if ($flash !== null): ?>
|
||||
<section class="alert alert-<?= support_h((string) ($flash['type'] ?? 'success')) ?>">
|
||||
<?= support_h((string) ($flash['message'] ?? '')) ?>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($dbError !== null): ?>
|
||||
<section class="alert alert-warning"><?= support_h($dbError) ?></section>
|
||||
<?php elseif (!$supportTablesReady): ?>
|
||||
<section class="alert alert-warning">
|
||||
Das Support-Modul ist strukturell vorbereitet, aber die Support-Tabellen sind noch nicht angelegt.
|
||||
Bitte führe die Migrationen aus, bevor du das Modul produktiv nutzt.
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($supportTablesReady): ?>
|
||||
<section class="grid grid--4">
|
||||
<article class="metric"><strong><?= support_h((string) ($summary['all'] ?? 0)) ?></strong><h3>Alle Vorgänge</h3><p>Support-Anfragen im aktuellen Tenant.</p></article>
|
||||
<article class="metric"><strong><?= support_h((string) ($summary['new'] ?? 0)) ?></strong><h3>Neu</h3><p>Neue Vorgänge ohne Bearbeitung.</p></article>
|
||||
<article class="metric"><strong><?= support_h((string) ($summary['waiting_on_user'] ?? 0)) ?></strong><h3>Warten auf Antwort</h3><p>Vorgänge mit Rückfrage an Mitglieder.</p></article>
|
||||
<article class="metric"><strong><?= support_h((string) ($summary['resolved'] ?? 0)) ?></strong><h3>Erledigt</h3><p>Abgeschlossene oder gelöste Anfragen.</p></article>
|
||||
</section>
|
||||
|
||||
<section class="split">
|
||||
<article class="card">
|
||||
<p class="eyebrow"><?= $isManager ? 'Neuen Vorgang anlegen' : 'Anfrage anlegen' ?></p>
|
||||
<h2>Support-Vorgang erstellen</h2>
|
||||
@@ -280,7 +451,7 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="grid grid--2" style="margin-top:18px">
|
||||
<section class="grid grid--2">
|
||||
<article class="card">
|
||||
<p class="eyebrow">Detailansicht</p>
|
||||
<h2>Ausgewählter Vorgang</h2>
|
||||
@@ -394,9 +565,10 @@
|
||||
<?php endif; ?>
|
||||
</article>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<p class="footer">Die Kaffeeliste | Support, Hinweise und Betriebsprozesse im Tenant-Menü</p>
|
||||
<p class="footer">Die Kaffeeliste | Support, Hinweise und Betriebsprozesse im Tenant-Menü</p>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
<?php $themeCss = app_tenant_theme_root_css($tenantSettings ?? app_tenant_settings_defaults()); ?>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Die Kaffeeliste - Rollen</title>
|
||||
<title>Die Kaffeeliste</title>
|
||||
<style>
|
||||
:root{
|
||||
<?= $themeCss ?>
|
||||
--line:rgba(37,24,15,.14);
|
||||
--shadow:0 16px 36px rgba(37,24,15,.08);
|
||||
--shadow:0 18px 40px rgba(37,24,15,.08);
|
||||
--radius:18px;
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
@@ -25,37 +25,150 @@
|
||||
}
|
||||
a{color:inherit;text-decoration:none}
|
||||
h1,h2,h3{font-family:Georgia,serif;letter-spacing:-.02em}
|
||||
.shell{width:min(1240px,calc(100vw - 32px));margin:20px auto 40px}
|
||||
.bar,.hero,.card,.table-card,.note{border:1px solid var(--line);border-radius:var(--radius);background:var(--card);box-shadow:var(--shadow)}
|
||||
.bar{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:18px 22px;margin-bottom:18px;flex-wrap:wrap}
|
||||
.brand{display:grid;gap:4px}
|
||||
.brand strong{font-size:1.18rem}
|
||||
.brand span,.muted{color:var(--muted)}
|
||||
.actions,.context,.meta{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
|
||||
.tenant-nav-wrap{margin-bottom:18px}
|
||||
.tenant-nav{display:grid;gap:12px;padding:14px 16px;border:1px solid var(--line);border-radius:20px;background:rgba(255,251,244,.92);box-shadow:var(--shadow)}
|
||||
.tenant-nav__desktop{display:flex;align-items:center;gap:14px;justify-content:space-between}
|
||||
.tenant-nav__links{display:flex;gap:10px;flex:1 1 auto;overflow-x:auto;scrollbar-width:none}
|
||||
.tenant-nav__links::-webkit-scrollbar{display:none}
|
||||
.tenant-nav__link,.badge,.pill{display:inline-flex;align-items:center;justify-content:center;padding:10px 14px;border-radius:999px;background:#fff;color:var(--brand);font-weight:700;border:1px solid rgba(var(--brand-rgb),.12);white-space:nowrap}
|
||||
.tenant-nav__link.active{background:var(--brand);color:#fff}
|
||||
.tenant-nav__mobile{display:none;position:relative}
|
||||
.tenant-nav__mobile[open]{z-index:20}
|
||||
.tenant-nav__toggle{display:inline-flex;align-items:center;gap:10px;list-style:none;cursor:pointer;padding:10px 14px;border-radius:999px;background:#fff;color:var(--brand);font-weight:700;border:1px solid rgba(var(--brand-rgb),.12)}
|
||||
.tenant-nav__toggle::-webkit-details-marker{display:none}
|
||||
.tenant-nav__toggle::before{content:"";width:18px;height:12px;border-top:2px solid currentColor;border-bottom:2px solid currentColor;box-shadow:inset 0 -4px 0 0 currentColor}
|
||||
.tenant-nav__panel{margin-top:12px;padding:14px;border-radius:18px;border:1px solid var(--line);background:#fffdf9;box-shadow:var(--shadow)}
|
||||
.tenant-nav__stack{display:grid;gap:10px}
|
||||
.tenant-nav__logout{display:flex;justify-content:flex-end}
|
||||
.badge,.pill{padding:7px 12px;font-size:.86rem}
|
||||
.badge--solid{background:var(--brand);color:#fff}
|
||||
.hero{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(260px,.6fr);gap:20px;padding:24px;margin-bottom:18px;background:linear-gradient(180deg,#fffdf8 0%,#f9f4ea 100%)}
|
||||
.hero__kicker{margin:0 0 10px;color:var(--accent);text-transform:uppercase;letter-spacing:.15em;font-size:.8rem;font-weight:800}
|
||||
.button,button{
|
||||
display:inline-flex;
|
||||
align-items:center;
|
||||
justify-content:center;
|
||||
padding:10px 14px;
|
||||
border-radius:999px;
|
||||
border:1px solid transparent;
|
||||
background:var(--brand);
|
||||
color:#fff;
|
||||
font:inherit;
|
||||
font-weight:700;
|
||||
cursor:pointer;
|
||||
}
|
||||
.button--ghost{
|
||||
background:#fff;
|
||||
color:var(--brand);
|
||||
border-color:rgba(var(--brand-rgb),.18);
|
||||
}
|
||||
.page-shell{
|
||||
width:min(1460px,calc(100vw - 32px));
|
||||
margin:20px auto 40px;
|
||||
display:grid;
|
||||
grid-template-columns:minmax(280px,300px) minmax(0,1fr);
|
||||
gap:20px;
|
||||
align-items:start;
|
||||
}
|
||||
.sidebar,.hero,.card,.table-card,.note{
|
||||
border:1px solid var(--line);
|
||||
border-radius:var(--radius);
|
||||
background:var(--card);
|
||||
box-shadow:var(--shadow);
|
||||
}
|
||||
.sidebar{
|
||||
position:sticky;
|
||||
top:20px;
|
||||
display:grid;
|
||||
gap:16px;
|
||||
padding:18px;
|
||||
background:rgba(255,251,244,.96);
|
||||
}
|
||||
.sidebar__brand{
|
||||
display:grid;
|
||||
gap:6px;
|
||||
padding-bottom:14px;
|
||||
border-bottom:1px solid rgba(37,24,15,.1);
|
||||
}
|
||||
.sidebar__eyebrow{
|
||||
margin:0;
|
||||
color:var(--accent);
|
||||
text-transform:uppercase;
|
||||
letter-spacing:.16em;
|
||||
font-size:.78rem;
|
||||
font-weight:800;
|
||||
}
|
||||
.sidebar__title,.hero__title,.card h2,.card h3{font-family:Georgia,serif;letter-spacing:-.02em}
|
||||
.sidebar__title{
|
||||
margin:0;
|
||||
font-size:1.55rem;
|
||||
line-height:1.05;
|
||||
}
|
||||
.sidebar__subtitle,.muted{color:var(--muted)}
|
||||
.sidebar__meta,.actions,.context,.meta{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
|
||||
.sidebar__section{
|
||||
display:inline-block;
|
||||
color:var(--accent);
|
||||
text-transform:uppercase;
|
||||
letter-spacing:.14em;
|
||||
font-size:.76rem;
|
||||
font-weight:800;
|
||||
}
|
||||
.sidebar__nav{display:grid;gap:10px}
|
||||
.sidebar__link{
|
||||
display:flex;
|
||||
align-items:center;
|
||||
justify-content:space-between;
|
||||
padding:12px 14px;
|
||||
border-radius:16px;
|
||||
border:1px solid rgba(var(--brand-rgb),.12);
|
||||
background:#fff;
|
||||
color:var(--brand);
|
||||
font-weight:700;
|
||||
}
|
||||
.sidebar__link.active{background:var(--brand);color:#fff}
|
||||
.sidebar__footer{
|
||||
display:grid;
|
||||
gap:12px;
|
||||
padding-top:14px;
|
||||
border-top:1px solid rgba(37,24,15,.1);
|
||||
}
|
||||
.sidebar__mobile{display:none}
|
||||
.sidebar__mobile[open]{z-index:20}
|
||||
.sidebar__toggle{
|
||||
display:flex;
|
||||
align-items:center;
|
||||
justify-content:space-between;
|
||||
gap:12px;
|
||||
cursor:pointer;
|
||||
list-style:none;
|
||||
padding:12px 14px;
|
||||
border-radius:16px;
|
||||
border:1px solid rgba(var(--brand-rgb),.12);
|
||||
background:#fff;
|
||||
color:var(--brand);
|
||||
font-weight:700;
|
||||
}
|
||||
.sidebar__toggle::-webkit-details-marker{display:none}
|
||||
.sidebar__toggle::after{
|
||||
content:"";
|
||||
width:11px;
|
||||
height:11px;
|
||||
border-right:2px solid currentColor;
|
||||
border-bottom:2px solid currentColor;
|
||||
transform:rotate(45deg);
|
||||
transition:transform .2s ease;
|
||||
}
|
||||
.sidebar__mobile[open] .sidebar__toggle::after{transform:rotate(225deg)}
|
||||
.sidebar__panel{
|
||||
margin-top:12px;
|
||||
padding:14px;
|
||||
border-radius:18px;
|
||||
border:1px solid var(--line);
|
||||
background:#fffdf9;
|
||||
box-shadow:var(--shadow);
|
||||
}
|
||||
.sidebar__stack{display:grid;gap:10px}
|
||||
.content{min-width:0;display:grid;gap:18px}
|
||||
.hero{
|
||||
display:grid;
|
||||
grid-template-columns:minmax(0,1.4fr) minmax(260px,.6fr);
|
||||
gap:20px;
|
||||
padding:24px;
|
||||
background:linear-gradient(180deg,#fffdf8 0%,#f9f4ea 100%);
|
||||
}
|
||||
.hero__kicker{
|
||||
margin:0 0 10px;
|
||||
color:var(--accent);
|
||||
text-transform:uppercase;
|
||||
letter-spacing:.15em;
|
||||
font-size:.8rem;
|
||||
font-weight:800;
|
||||
}
|
||||
.hero__title{margin:0 0 12px;font-size:clamp(1.9rem,4vw,3rem);line-height:1.05}
|
||||
.hero__lead{margin:0;color:var(--muted);max-width:70ch;line-height:1.7}
|
||||
.hero__actions{display:flex;flex-wrap:wrap;gap:12px;margin-top:16px}
|
||||
.button{display:inline-flex;align-items:center;justify-content:center;padding:10px 14px;border-radius:999px;border:1px solid transparent;background:var(--brand);color:#fff;font-weight:700}
|
||||
.button--ghost{background:#fff;color:var(--brand);border:1px solid rgba(var(--brand-rgb),.18)}
|
||||
.grid{display:grid;gap:18px}
|
||||
.grid--2{grid-template-columns:repeat(2,minmax(0,1fr))}
|
||||
.grid--3{grid-template-columns:repeat(3,minmax(0,1fr))}
|
||||
@@ -77,47 +190,90 @@
|
||||
.stack{display:grid;gap:12px}
|
||||
.chip-list{display:flex;flex-wrap:wrap;gap:8px}
|
||||
.chip{display:inline-flex;align-items:center;padding:5px 10px;border-radius:999px;background:rgba(var(--brand-rgb),.08);color:var(--brand);font-size:.84rem;font-weight:700}
|
||||
@media(max-width:960px){.hero,.grid--2,.grid--3,.grid--4{grid-template-columns:1fr}.bar{align-items:flex-start;flex-direction:column}.tenant-nav__desktop{display:none}.tenant-nav__mobile{display:block}}
|
||||
@media(min-width:961px){.tenant-nav__mobile{display:none}}
|
||||
.badge{
|
||||
display:inline-flex;
|
||||
align-items:center;
|
||||
padding:7px 12px;
|
||||
border-radius:999px;
|
||||
background:#fff;
|
||||
color:var(--brand);
|
||||
font-weight:700;
|
||||
font-size:.86rem;
|
||||
border:1px solid rgba(var(--brand-rgb),.12);
|
||||
white-space:nowrap;
|
||||
}
|
||||
.badge--solid{background:var(--brand);color:#fff}
|
||||
.pill{
|
||||
display:inline-flex;
|
||||
align-items:center;
|
||||
padding:7px 12px;
|
||||
border-radius:999px;
|
||||
border:1px solid rgba(var(--brand-rgb),.15);
|
||||
background:rgba(var(--brand-rgb),.07);
|
||||
color:var(--brand);
|
||||
font-size:.84rem;
|
||||
font-weight:700;
|
||||
white-space:nowrap;
|
||||
}
|
||||
@media(max-width:960px){
|
||||
.page-shell{grid-template-columns:1fr;width:min(100vw - 20px,1460px)}
|
||||
.sidebar{position:static}
|
||||
.sidebar__desktop{display:none}
|
||||
.sidebar__mobile{display:block}
|
||||
.hero,.grid--2,.grid--3,.grid--4{grid-template-columns:1fr}
|
||||
}
|
||||
@media(min-width:961px){
|
||||
.sidebar__mobile{display:none}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<header class="bar">
|
||||
<div class="brand">
|
||||
<strong>Die Kaffeeliste</strong>
|
||||
<span>Rollen und Rechte im Tenant.</span>
|
||||
<main class="page-shell">
|
||||
<aside class="sidebar" aria-label="Bereichsnavigation">
|
||||
<div class="sidebar__brand">
|
||||
<p class="sidebar__eyebrow">Die Kaffeeliste</p>
|
||||
<h1 class="sidebar__title">Rollen</h1>
|
||||
<p class="sidebar__subtitle">Rollen und Rechte im Tenant.</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="tenant-nav-wrap" aria-label="Bereichsnavigation">
|
||||
<div class="tenant-nav">
|
||||
<div class="tenant-nav__desktop">
|
||||
<nav class="tenant-nav__links" aria-label="Tenant-Menü">
|
||||
<div class="sidebar__meta">
|
||||
<span class="badge">lokal + ADFS/OIDC</span>
|
||||
<span class="badge">Rollenmatrix</span>
|
||||
<span class="badge">Delegation</span>
|
||||
</div>
|
||||
|
||||
<div class="sidebar__desktop">
|
||||
<span class="sidebar__section">Bereiche</span>
|
||||
<nav class="sidebar__nav" aria-label="Tenant-Menü">
|
||||
<?php foreach ($tenantNavItems as $item): ?>
|
||||
<a class="sidebar__link <?= (($item['key'] ?? '') === 'roles') ? 'active' : '' ?>" href="<?= tenant_roles_h((string) ($item['href'] ?? '/')) ?>" <?= (($item['key'] ?? '') === 'roles') ? 'aria-current="page"' : '' ?>><?= tenant_roles_h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<?php endforeach; ?>
|
||||
</nav>
|
||||
<div class="sidebar__footer">
|
||||
<form method="post" action="/logout/"><button type="submit" class="button button--ghost">Abmelden</button></form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<details class="sidebar__mobile">
|
||||
<summary class="sidebar__toggle">Menü</summary>
|
||||
<div class="sidebar__panel">
|
||||
<nav class="sidebar__stack" aria-label="Mobiles Tenant-Menü">
|
||||
<?php foreach ($tenantNavItems as $item): ?>
|
||||
<a class="tenant-nav__link <?= (($item['key'] ?? '') === 'roles') ? 'active' : '' ?>" href="<?= tenant_roles_h((string) ($item['href'] ?? '/')) ?>" <?= (($item['key'] ?? '') === 'roles') ? 'aria-current="page"' : '' ?>><?= tenant_roles_h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<a class="sidebar__link <?= (($item['key'] ?? '') === 'roles') ? 'active' : '' ?>" href="<?= tenant_roles_h((string) ($item['href'] ?? '/')) ?>" <?= (($item['key'] ?? '') === 'roles') ? 'aria-current="page"' : '' ?>><?= tenant_roles_h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<?php endforeach; ?>
|
||||
</nav>
|
||||
<form class="tenant-nav__logout" method="post" action="/logout/"><button type="submit" class="button button--ghost">Abmelden</button></form>
|
||||
</div>
|
||||
<details class="tenant-nav__mobile">
|
||||
<summary class="tenant-nav__toggle">Navigation</summary>
|
||||
<div class="tenant-nav__panel">
|
||||
<nav class="tenant-nav__stack" aria-label="Mobiles Tenant-Menü">
|
||||
<?php foreach ($tenantNavItems as $item): ?>
|
||||
<a class="tenant-nav__link <?= (($item['key'] ?? '') === 'roles') ? 'active' : '' ?>" href="<?= tenant_roles_h((string) ($item['href'] ?? '/')) ?>" <?= (($item['key'] ?? '') === 'roles') ? 'aria-current="page"' : '' ?>><?= tenant_roles_h((string) ($item['label'] ?? 'Link')) ?></a>
|
||||
<?php endforeach; ?>
|
||||
</nav>
|
||||
<form class="tenant-nav__logout" method="post" action="/logout/"><button type="submit" class="button button--ghost">Abmelden</button></form>
|
||||
<div class="sidebar__footer">
|
||||
<form method="post" action="/logout/"><button type="submit" class="button button--ghost">Abmelden</button></form>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</details>
|
||||
</aside>
|
||||
|
||||
<div class="content">
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Rollen</p>
|
||||
<h1 class="hero__title">Rollen und Rechte</h1>
|
||||
<h2 class="hero__title">Rollen und Rechte</h2>
|
||||
<p class="hero__lead">
|
||||
Tenant-Admins behalten den Gesamtzugriff. Fachrollen für Finanzen, Support und Umfragen werden gezielt delegiert.
|
||||
</p>
|
||||
@@ -264,6 +420,7 @@
|
||||
</ul>
|
||||
</article>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user