Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
190 lines
8.7 KiB
PHP
190 lines
8.7 KiB
PHP
<?php
|
||
require_once __DIR__ . '/../lib/auth.php';
|
||
require_once __DIR__ . '/../lib/db.php';
|
||
require_once __DIR__ . '/../lib/layout.php';
|
||
require_login();
|
||
|
||
$name = current_name();
|
||
$user_id = current_user()['id'];
|
||
|
||
$news_items = db()->query('SELECT * FROM news ORDER BY date DESC, id DESC')->fetchAll();
|
||
|
||
$grund_labels = [
|
||
'arztbesuch' => 'Arztbesuch',
|
||
'behoerdengang' => 'Behördengang',
|
||
'sonderurlaub' => 'Sonderurlaub',
|
||
'elternzeit_pflegezeit' => 'Elternzeit / Pflegezeit',
|
||
'sonstiges' => 'Sonstiges',
|
||
];
|
||
$benefit_labels = [
|
||
'massage' => 'Massage',
|
||
'fitnessstudio' => 'Fitnessstudio',
|
||
'tankgutschein' => 'Tankgutschein',
|
||
'fortbildung' => 'Fortbildung',
|
||
];
|
||
|
||
$rows = [];
|
||
|
||
$stmt = db()->prepare('SELECT id, status, created_at, von, bis, vertretung, nachricht FROM requests_urlaubsantrag WHERE user_id=? ORDER BY created_at DESC');
|
||
$stmt->execute([$user_id]);
|
||
foreach ($stmt->fetchAll() as $r) {
|
||
$rows[] = ['type' => 'urlaub', 'type_label' => 'Urlaubsantrag', 'icon' => '🌴'] + $r + ['detail' => $r['von'] . ' – ' . $r['bis']];
|
||
}
|
||
|
||
$stmt = db()->prepare('SELECT id, status, created_at, von, bis, grund, vertretung, nachricht FROM requests_abwesenheitsantrag WHERE user_id=? ORDER BY created_at DESC');
|
||
$stmt->execute([$user_id]);
|
||
foreach ($stmt->fetchAll() as $r) {
|
||
$rows[] = ['type' => 'abwesenheit', 'type_label' => 'Abwesenheitsantrag', 'icon' => '📅'] + $r + ['detail' => ($grund_labels[$r['grund']] ?? $r['grund']) . ': ' . $r['von'] . ' – ' . $r['bis']];
|
||
}
|
||
|
||
$stmt = db()->prepare('SELECT id, status, created_at, benefit, nachricht FROM requests_benefitsantrag WHERE user_id=? ORDER BY created_at DESC');
|
||
$stmt->execute([$user_id]);
|
||
foreach ($stmt->fetchAll() as $r) {
|
||
$rows[] = ['type' => 'benefits', 'type_label' => 'Benefitsantrag', 'icon' => '🎁'] + $r + ['detail' => $benefit_labels[$r['benefit']] ?? $r['benefit']];
|
||
}
|
||
|
||
$stmt = db()->prepare('SELECT id, status, created_at, name, email, qualifikation, nachricht FROM requests_werben WHERE user_id=? ORDER BY created_at DESC');
|
||
$stmt->execute([$user_id]);
|
||
foreach ($stmt->fetchAll() as $r) {
|
||
$rows[] = ['type' => 'werben', 'type_label' => 'Mitarbeiter werben', 'icon' => '🤝'] + $r + ['detail' => $r['name'] . ($r['qualifikation'] ? ' (' . $r['qualifikation'] . ')' : '')];
|
||
}
|
||
|
||
usort($rows, fn($a, $b) => strcmp($b['created_at'], $a['created_at']));
|
||
|
||
$pending_count = count(array_filter($rows, fn($r) => $r['status'] === 'pending'));
|
||
|
||
$status_map = ['pending' => 'Ausstehend', 'accepted' => 'Angenommen', 'rejected' => 'Abgelehnt'];
|
||
|
||
layout_start('OMSORG Felix – Dashboard', 'dashboard');
|
||
?>
|
||
<h1 class="main-title">Willkommen, <span><?= e($name) ?></span>!</h1>
|
||
<p class="main-sub">Hier siehst du alle deine Anträge auf einen Blick.</p>
|
||
|
||
<?php if (!empty($news_items)): ?>
|
||
<div style="margin:28px 0 8px">
|
||
<h2 style="font-family:'KindelSerif',Georgia,serif;font-size:1.5rem;margin:0 0 14px">📢 News & Ankündigungen</h2>
|
||
<?php foreach ($news_items as $n): ?>
|
||
<div class="glass" style="padding:20px 24px;border-radius:18px;margin-bottom:12px">
|
||
<div style="color:var(--cyan2);font-size:.82rem;font-weight:900;margin-bottom:5px">
|
||
<?= e(date('d.m.Y', strtotime($n['date']))) ?>
|
||
</div>
|
||
<strong style="font-size:1.05rem;display:block;margin-bottom:6px"><?= e($n['title']) ?></strong>
|
||
<p style="margin:0;color:var(--muted);line-height:1.6;font-size:.95rem"><?= nl2br(e($n['text'])) ?></p>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($pending_count > 0): ?>
|
||
<p style="margin:18px 0 0;color:var(--muted)">
|
||
<?= $pending_count === 1 ? '1 Antrag ist noch' : $pending_count . ' Anträge sind noch' ?> <strong style="color:#ffe566">ausstehend</strong>.
|
||
</p>
|
||
<?php endif; ?>
|
||
|
||
<?php if (empty($rows)): ?>
|
||
<p style="margin-top:32px;color:var(--muted)">Du hast noch keine Anträge gestellt.</p>
|
||
<?php else: ?>
|
||
|
||
<div class="type-tabs" id="type-tabs">
|
||
<button class="type-tab active" data-type="all">Alle (<?= count($rows) ?>)</button>
|
||
<?php
|
||
$types = [];
|
||
foreach ($rows as $r) {
|
||
$types[$r['type']] = ['label' => $r['type_label'], 'icon' => $r['icon'], 'count' => ($types[$r['type']]['count'] ?? 0) + 1];
|
||
}
|
||
foreach ($types as $type => $info): ?>
|
||
<button class="type-tab" data-type="<?= e($type) ?>"><?= $info['icon'] ?> <?= e($info['label']) ?> (<?= $info['count'] ?>)</button>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
|
||
<table class="requests-table" style="margin-top:16px">
|
||
<thead>
|
||
<tr>
|
||
<th>Art</th>
|
||
<th>Details</th>
|
||
<th>Eingereicht</th>
|
||
<th>Status</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($rows as $r): ?>
|
||
<tr data-type="<?= e($r['type']) ?>">
|
||
<td><?= $r['icon'] ?> <?= e($r['type_label']) ?></td>
|
||
<td style="color:var(--muted);font-size:.93rem"><?= e($r['detail']) ?></td>
|
||
<td style="color:var(--muted);font-size:.88rem;white-space:nowrap"><?= e(date('d.m.Y', strtotime($r['created_at']))) ?></td>
|
||
<td><span class="badge badge-<?= e($r['status']) ?>"><?= e($status_map[$r['status']] ?? $r['status']) ?></span></td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
|
||
<script>
|
||
document.getElementById('type-tabs').addEventListener('click', function(e) {
|
||
const btn = e.target.closest('.type-tab');
|
||
if (!btn) return;
|
||
this.querySelectorAll('.type-tab').forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
const type = btn.dataset.type;
|
||
document.querySelectorAll('.requests-table tbody tr').forEach(row => {
|
||
row.style.display = (type === 'all' || row.dataset.type === type) ? '' : 'none';
|
||
});
|
||
});
|
||
</script>
|
||
|
||
<?php endif; ?>
|
||
<?php layout_end(); ?>
|
||
|
||
<div id="pwa-install-banner" style="display:none;position:fixed;bottom:0;left:0;right:0;background:#1a3a5c;color:#fff;padding:.85rem 1rem;z-index:8000;align-items:center;gap:.75rem;box-shadow:0 -2px 12px rgba(0,0,0,.25);">
|
||
<span style="flex:1;font-size:.95rem;">📲 <strong>OMSORG App</strong> zum Home-Bildschirm hinzufügen</span>
|
||
<button id="pwa-install-confirm" type="button" style="background:#fff;color:#1a3a5c;border:none;border-radius:8px;padding:.45rem 1rem;font-weight:700;cursor:pointer;white-space:nowrap;">Installieren</button>
|
||
<button id="pwa-install-dismiss" type="button" style="background:transparent;color:#fff;border:none;font-size:1.2rem;cursor:pointer;padding:0 .25rem;line-height:1;">✕</button>
|
||
</div>
|
||
|
||
<div id="pwa-install-modal" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.55);z-index:9000;align-items:flex-end;justify-content:center;padding:1rem;" role="dialog" aria-modal="true">
|
||
<div style="background:#fff;border-radius:16px;padding:1.5rem;width:100%;max-width:440px;color:#1a3a5c;">
|
||
<p style="margin:0 0 1.25rem;font-weight:700;font-size:1.1rem;text-align:center;">📲 App installieren</p>
|
||
<div style="background:#f0f4ff;border-radius:12px;padding:1rem 1.1rem;margin-bottom:.75rem;">
|
||
<p style="margin:0 0 .4rem;font-weight:700;font-size:.95rem;">🤖 Android (Chrome)</p>
|
||
<p style="margin:0;font-size:.9rem;line-height:1.6;color:#444;">Tippe oben rechts auf das <strong>Menü ⋮</strong> und dann auf<br><strong>„App installieren"</strong> oder <strong>„Zum Startbildschirm hinzufügen"</strong>.</p>
|
||
</div>
|
||
<div style="background:#f0f4ff;border-radius:12px;padding:1rem 1.1rem;margin-bottom:1.25rem;">
|
||
<p style="margin:0 0 .4rem;font-weight:700;font-size:.95rem;">🍎 iPhone / iPad (Safari)</p>
|
||
<p style="margin:0;font-size:.9rem;line-height:1.6;color:#444;">Tippe unten auf das <strong>Teilen-Symbol ⬆</strong> und dann auf<br><strong>„Zum Home-Bildschirm"</strong>.</p>
|
||
</div>
|
||
<button id="pwa-modal-close" style="display:block;width:100%;background:#1a3a5c;color:#fff;border:none;border-radius:8px;padding:.65rem;cursor:pointer;font-size:.95rem;font-weight:600;">Schließen</button>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
(function(){
|
||
if(window.matchMedia('(display-mode: standalone)').matches)return;
|
||
if(document.cookie.split(';').some(c=>c.trim()==='pwa_dismissed=1'))return;
|
||
const banner=document.getElementById('pwa-install-banner');
|
||
const modal=document.getElementById('pwa-install-modal');
|
||
let deferred=null;
|
||
window.addEventListener('beforeinstallprompt',function(e){
|
||
e.preventDefault();
|
||
deferred=e;
|
||
});
|
||
banner.style.display='flex';
|
||
document.getElementById('pwa-install-confirm').addEventListener('click',function(){
|
||
if(deferred){
|
||
deferred.prompt();
|
||
banner.style.display='none';
|
||
} else {
|
||
banner.style.display='none';
|
||
modal.style.display='flex';
|
||
}
|
||
});
|
||
function dismiss(){
|
||
banner.style.display='none';
|
||
document.cookie='pwa_dismissed=1;path=/;max-age='+60*60*24*365;
|
||
}
|
||
document.getElementById('pwa-install-dismiss').addEventListener('click',dismiss);
|
||
document.getElementById('pwa-modal-close').addEventListener('click',function(){
|
||
modal.style.display='none';
|
||
dismiss();
|
||
});
|
||
})();
|
||
</script>
|