Dev #16

Merged
NiekRabelink merged 2 commits from dev into main 2026-09-09 10:35:08 +00:00
3 changed files with 104 additions and 87 deletions
Showing only changes of commit 2f336f54a8 - Show all commits
+16 -32
View File
@@ -132,39 +132,28 @@ require_once __DIR__ . '/env_badge.php';
</nav>
</div>
<!-- Right side: Theme Toggle, Notifications, 2FA Status & User -->
<div class="flex items-center space-x-2 sm:space-x-2.5">
<!-- 1-Click Snelle Thema Wisselaar (Zon / Maan) -->
<button type="button" onclick="focizQuickToggleTheme()" class="p-2 rounded-xl text-slate-500 hover:text-slate-900 hover:bg-slate-100 dark:text-slate-400 dark:hover:text-white dark:hover:bg-slate-800 transition" title="Thema wisselen (Donker / Licht)">
<i data-lucide="sun" class="w-4 h-4 hidden dark:block text-amber-400"></i>
<i data-lucide="moon" class="w-4 h-4 block dark:hidden text-slate-700"></i>
</button>
<!-- Notificatiebel -->
<button type="button" onclick="openNotificationModal()" class="relative p-2 rounded-xl text-slate-500 hover:text-slate-900 hover:bg-slate-100 dark:text-slate-400 dark:hover:text-white dark:hover:bg-slate-800 transition" title="Meldingen & Agenda Herinneringen">
<i data-lucide="bell" class="w-4 h-4"></i>
<span id="focizNotificationDot" class="hidden absolute top-1.5 right-1.5 w-2 h-2 rounded-full bg-blue-500 animate-pulse"></span>
</button>
<!-- 2FA Badge -->
<div class="hidden sm:flex items-center space-x-1.5 px-2.5 py-1 rounded-full bg-emerald-50 dark:bg-emerald-500/10 border border-emerald-200 dark:border-emerald-500/25 text-emerald-700 dark:text-emerald-400 text-xs font-semibold">
<i data-lucide="shield-check" class="w-3.5 h-3.5"></i>
<span>2FA Actief</span>
</div>
<!-- Right side: Clean User Profile & Logout -->
<div class="flex items-center space-x-2 sm:space-x-3">
<!-- Profiel link rechtsboven -->
<a href="/profile.php" class="text-right hidden sm:block group hover:opacity-90 transition pl-1" title="Mijn Profiel & Instellingen">
<div class="text-xs font-semibold text-slate-800 dark:text-slate-200 group-hover:text-emerald-600 dark:group-hover:text-emerald-400 transition flex items-center justify-end space-x-1">
<span><?= htmlspecialchars($currentUser['name']) ?></span>
<i data-lucide="chevron-right" class="w-3 h-3 text-slate-400 dark:text-slate-500 group-hover:text-emerald-600 dark:group-hover:text-emerald-400 transition"></i>
<a href="/profile.php" class="flex items-center space-x-2.5 group hover:opacity-90 transition px-2.5 py-1.5 rounded-xl hover:bg-slate-100 dark:hover:bg-slate-800/60" title="Mijn Profiel & Instellingen">
<div class="w-8 h-8 rounded-xl bg-gradient-to-tr from-emerald-600 to-teal-400 p-0.5 flex-shrink-0 shadow-sm">
<div class="w-full h-full rounded-[10px] bg-white dark:bg-slate-950 flex items-center justify-center font-bold text-xs text-emerald-600 dark:text-emerald-400 uppercase">
<?= strtoupper(substr($currentUser['name'], 0, 1)) ?>
</div>
<div class="text-[10px] text-slate-500 dark:text-slate-400">
<?= $currentUser['role'] === 'ADMIN' ? 'Beheerder' : 'Collega' ?> • <?= htmlspecialchars($currentUser['email']) ?>
</div>
<div class="text-left hidden sm:block">
<div class="text-xs font-semibold text-slate-800 dark:text-slate-200 group-hover:text-emerald-600 dark:group-hover:text-emerald-400 transition leading-tight">
<?= htmlspecialchars($currentUser['name']) ?>
</div>
<div class="text-[10px] text-slate-500 dark:text-slate-400 leading-tight">
<?= $currentUser['role'] === 'ADMIN' ? 'Beheerder' : 'Collega' ?>
</div>
</div>
<i data-lucide="chevron-right" class="w-3.5 h-3.5 text-slate-400 dark:text-slate-500 group-hover:text-emerald-600 dark:group-hover:text-emerald-400 transition hidden sm:block"></i>
</a>
<!-- Uitloggen -->
<a href="/auth/logout.php" title="Veilig uitloggen" class="p-2 rounded-xl text-slate-500 hover:text-red-600 hover:bg-red-50 dark:text-slate-400 dark:hover:text-red-400 dark:hover:bg-red-500/10 transition">
<a href="/auth/logout.php" title="Veilig uitloggen" class="p-2 rounded-xl text-slate-400 hover:text-red-600 hover:bg-red-50 dark:text-slate-400 dark:hover:text-red-400 dark:hover:bg-red-500/10 transition">
<i data-lucide="log-out" class="w-4 h-4"></i>
</a>
</div>
@@ -188,11 +177,6 @@ require_once __DIR__ . '/env_badge.php';
<i data-lucide="user" class="w-4 h-4 mb-0.5"></i>
<span>Profiel</span>
</a>
<button type="button" onclick="focizQuickToggleTheme()" class="flex flex-col items-center py-1 text-slate-500 dark:text-slate-400">
<i data-lucide="sun" class="w-4 h-4 mb-0.5 hidden dark:block text-amber-400"></i>
<i data-lucide="moon" class="w-4 h-4 mb-0.5 block dark:hidden"></i>
<span>Thema</span>
</button>
<?php if ($currentUser['role'] === 'ADMIN'): ?>
<a href="/admin.php" class="flex flex-col items-center py-1 <?= $currentPage === 'admin.php' ? 'text-emerald-600 dark:text-emerald-400 font-bold' : 'text-slate-500 dark:text-slate-400' ?>">
<i data-lucide="shield" class="w-4 h-4 mb-0.5"></i>
+33 -23
View File
@@ -131,6 +131,10 @@ $dutchDays = ['Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrijdag'
$dutchMonths = ['', 'januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'];
$formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(int)date('n')] . ' ' . date('Y');
?>
<style>
.line-clamp-1 { display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
.line-clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
</style>
<div class="space-y-6 max-w-7xl mx-auto">
<!-- Top Banner: Datum, Hoofddoel & Integraties Status -->
@@ -207,7 +211,7 @@ $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(i
<div class="grid grid-cols-1 lg:grid-cols-12 gap-6">
<!-- Linker kolom: Focus Timer & Taken -->
<div class="lg:col-span-7 space-y-6">
<div class="lg:col-span-7 space-y-6 min-w-0">
<!-- Focus Modus Timer -->
<div class="bg-white dark:bg-slate-900/80 border border-slate-200 dark:border-slate-800 rounded-3xl p-6 shadow-sm dark:shadow-xl relative overflow-hidden backdrop-blur-sm transition">
@@ -467,8 +471,8 @@ $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(i
</div>
<!-- Rechter kolom: Timeblocking & Outlook Tijdlijn -->
<div class="lg:col-span-5 space-y-6">
<div class="bg-white dark:bg-slate-900/80 border border-slate-200 dark:border-slate-800 rounded-3xl p-6 shadow-sm dark:shadow-xl backdrop-blur-sm transition">
<div class="lg:col-span-5 space-y-6 min-w-0">
<div class="bg-white dark:bg-slate-900/80 border border-slate-200 dark:border-slate-800 rounded-3xl p-5 sm:p-6 shadow-sm dark:shadow-xl backdrop-blur-sm transition overflow-hidden">
<div class="flex items-center justify-between mb-4 pb-3 border-b border-slate-100 dark:border-slate-800">
<div class="flex items-center space-x-2">
<i data-lucide="clock" class="w-5 h-5 text-emerald-600 dark:text-emerald-400"></i>
@@ -482,7 +486,7 @@ $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(i
</div>
</div>
<div class="space-y-2">
<div class="space-y-2.5">
<?php foreach ($hours as $hour):
$hourInt = (int)explode(':', $hour)[0];
@@ -497,65 +501,71 @@ $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(i
return !empty($t['time_block_start']) && (int)explode(':', $t['time_block_start'])[0] === $hourInt;
});
?>
<div class="flex items-start group min-h-[50px] border-b border-slate-100 dark:border-slate-800/40 pb-2 last:border-0">
<div class="w-14 text-xs font-mono font-medium text-slate-500 dark:text-slate-400 pt-1 flex-shrink-0">
<div class="flex items-start group min-h-[50px] border-b border-slate-100 dark:border-slate-800/40 pb-2.5 last:border-0 min-w-0">
<div class="w-12 sm:w-14 text-xs font-mono font-medium text-slate-500 dark:text-slate-400 pt-1 flex-shrink-0">
<?= $hour ?>
</div>
<div class="flex-1 space-y-1.5">
<div class="flex-1 space-y-1.5 min-w-0">
<!-- Outlook meetings -->
<?php foreach ($slotEvents as $evt): ?>
<div class="flex items-center justify-between p-2 rounded-xl bg-blue-50 dark:bg-blue-950/50 border border-blue-200 dark:border-blue-800/60 text-blue-900 dark:text-blue-100 text-xs shadow-sm">
<div class="flex items-center space-x-2 truncate mr-2">
<span class="px-1.5 py-0.5 rounded bg-blue-500/15 text-blue-700 dark:text-blue-400 font-mono text-[10px] font-bold">
<div class="p-2.5 rounded-2xl bg-blue-50/80 dark:bg-blue-950/50 border border-blue-200/80 dark:border-blue-800/60 text-blue-900 dark:text-blue-100 text-xs shadow-sm min-w-0 overflow-hidden">
<div class="flex items-start justify-between gap-2 min-w-0">
<div class="flex items-start space-x-2 min-w-0 flex-1">
<span class="px-1.5 py-0.5 rounded-lg bg-blue-500/15 text-blue-700 dark:text-blue-300 font-mono text-[10px] font-bold flex-shrink-0 whitespace-nowrap mt-0.5">
<?= htmlspecialchars($evt['start']) ?> - <?= htmlspecialchars($evt['end']) ?>
</span>
<span class="font-semibold truncate" title="<?= htmlspecialchars($evt['subject']) ?>">
<span class="font-semibold text-xs leading-snug break-words line-clamp-2 min-w-0 flex-1" title="<?= htmlspecialchars($evt['subject']) ?>">
<?= htmlspecialchars($evt['subject']) ?>
</span>
</div>
<div class="flex items-center space-x-1.5 flex-shrink-0">
<div class="flex items-center space-x-1 flex-shrink-0">
<?php if (!empty($evt['meeting_url'])): ?>
<a href="<?= htmlspecialchars($evt['meeting_url']) ?>" target="_blank" class="flex items-center space-x-1 text-[10px] text-white bg-blue-600 hover:bg-blue-700 px-2 py-0.5 rounded-lg flex-shrink-0 transition">
<a href="<?= htmlspecialchars($evt['meeting_url']) ?>" target="_blank" class="flex items-center space-x-1 text-[10px] text-white bg-blue-600 hover:bg-blue-700 px-2 py-0.5 rounded-lg flex-shrink-0 transition font-medium">
<i data-lucide="video" class="w-3 h-3"></i>
<span>Deelnemen</span>
<span class="hidden sm:inline">Deelnemen</span>
</a>
<?php elseif (!empty($evt['web_link'])): ?>
<a href="<?= htmlspecialchars($evt['web_link']) ?>" target="_blank" class="flex items-center space-x-1 text-[10px] text-blue-600 dark:text-blue-300 hover:underline px-1.5 py-0.5 transition">
<a href="<?= htmlspecialchars($evt['web_link']) ?>" target="_blank" class="flex items-center space-x-1 text-[10px] text-blue-600 dark:text-blue-300 hover:underline px-1 py-0.5 transition font-medium">
<i data-lucide="external-link" class="w-3 h-3"></i>
<span>Outlook</span>
<span class="hidden sm:inline">Outlook</span>
</a>
<?php endif; ?>
</div>
</div>
</div>
<?php endforeach; ?>
<!-- Geplande taken -->
<?php foreach ($slotTasks as $t): ?>
<div class="flex items-center justify-between p-2 rounded-xl border text-xs <?= $t['is_completed'] ? 'bg-slate-100 dark:bg-slate-900/40 border-slate-200 dark:border-slate-800 text-slate-400 dark:text-slate-500 line-through' : 'bg-emerald-50 dark:bg-emerald-950/30 border-emerald-200 dark:border-emerald-800/40 text-emerald-900 dark:text-emerald-100' ?>">
<div class="flex items-center space-x-2 truncate mr-2">
<span class="px-1.5 py-0.5 rounded bg-emerald-500/15 text-emerald-700 dark:text-emerald-400 font-mono text-[10px] font-bold">
<div class="p-2.5 rounded-2xl border text-xs min-w-0 overflow-hidden <?= $t['is_completed'] ? 'bg-slate-100/70 dark:bg-slate-900/40 border-slate-200 dark:border-slate-800 text-slate-400 dark:text-slate-500 line-through' : 'bg-emerald-50/80 dark:bg-emerald-950/30 border-emerald-200/80 dark:border-emerald-800/40 text-emerald-900 dark:text-emerald-100 shadow-sm' ?>">
<div class="flex items-start justify-between gap-2 min-w-0">
<div class="flex items-start space-x-2 min-w-0 flex-1">
<span class="px-1.5 py-0.5 rounded-lg bg-emerald-500/15 text-emerald-700 dark:text-emerald-300 font-mono text-[10px] font-bold flex-shrink-0 whitespace-nowrap mt-0.5">
<?= htmlspecialchars($t['time_block_start']) ?><?= !empty($t['time_block_end']) ? ' - ' . htmlspecialchars($t['time_block_end']) : '' ?>
</span>
<span class="font-semibold truncate"><?= htmlspecialchars($t['title']) ?></span>
<span class="font-semibold text-xs leading-snug break-words line-clamp-2 min-w-0 flex-1" title="<?= htmlspecialchars($t['title']) ?>">
<?= htmlspecialchars($t['title']) ?>
</span>
</div>
<div class="flex items-center space-x-1.5 flex-shrink-0">
<?php if (!empty($t['external_id']) && $t['source'] === 'OUTLOOK'): ?>
<span class="text-[9px] font-bold px-1.5 py-0.5 rounded bg-blue-500/15 text-blue-700 dark:text-blue-400 border border-blue-500/20 flex items-center space-x-1" title="In Outlook agenda">
<span class="text-[9px] font-bold px-1.5 py-0.5 rounded bg-blue-500/15 text-blue-700 dark:text-blue-300 border border-blue-500/25 flex items-center space-x-1 whitespace-nowrap" title="In Outlook agenda">
<i data-lucide="calendar" class="w-2.5 h-2.5"></i>
<span class="hidden sm:inline">In Outlook</span>
</span>
<?php elseif ($isOutlookConnected && !$t['is_completed']): ?>
<button onclick="syncTaskToOutlook(<?= $t['id'] ?>, this)" title="Synchroniseer naar Outlook Agenda" class="text-[9px] font-bold px-1.5 py-0.5 rounded bg-blue-500/10 hover:bg-blue-500/20 text-blue-700 dark:text-blue-300 border border-blue-500/20 flex items-center space-x-1 transition cursor-pointer">
<button onclick="syncTaskToOutlook(<?= $t['id'] ?>, this)" title="Synchroniseer naar Outlook Agenda" class="text-[9px] font-bold px-1.5 py-0.5 rounded bg-blue-500/10 hover:bg-blue-500/20 text-blue-700 dark:text-blue-300 border border-blue-500/20 flex items-center space-x-1 transition cursor-pointer whitespace-nowrap">
<i data-lucide="calendar-plus" class="w-2.5 h-2.5"></i>
<span class="hidden sm:inline">Naar Outlook</span>
</button>
<?php endif; ?>
<span class="text-[10px] font-bold px-1.5 py-0.5 rounded bg-emerald-500/20 text-emerald-700 dark:text-emerald-400">
<span class="text-[10px] font-bold px-1.5 py-0.5 rounded bg-emerald-500/20 text-emerald-700 dark:text-emerald-400 flex-shrink-0">
<?= $t['priority'] ?>
</span>
</div>
</div>
</div>
<?php endforeach; ?>
<?php if (empty($slotEvents) && empty($slotTasks)): ?>
+24 -1
View File
@@ -724,7 +724,30 @@ require_once __DIR__ . '/includes/header.php';
</div>
<!-- Sectie 4: Account & Beveiliging (Wachtwoord & 2FA) -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<div class="space-y-6">
<!-- 2FA Beveiliging Card -->
<div class="p-5 rounded-3xl bg-emerald-50/80 dark:bg-emerald-500/10 border border-emerald-200 dark:border-emerald-500/25 flex flex-col sm:flex-row sm:items-center justify-between gap-4 shadow-sm">
<div class="flex items-center space-x-3.5">
<div class="w-12 h-12 rounded-2xl bg-emerald-500/20 border border-emerald-500/30 flex items-center justify-center text-emerald-600 dark:text-emerald-400 font-bold shadow-sm flex-shrink-0">
<i data-lucide="shield-check" class="w-6 h-6"></i>
</div>
<div>
<div class="flex items-center space-x-2">
<h3 class="text-sm font-bold text-slate-900 dark:text-white">Tweestapsverificatie (2FA) is Actief</h3>
<span class="px-2 py-0.5 rounded-full bg-emerald-500 text-slate-950 font-bold text-[10px]">Beveiligd</span>
</div>
<p class="text-xs text-slate-600 dark:text-slate-400 mt-0.5">
Uw Fociz account is optimaal beveiligd met een Authenticator app (TOTP) voor maximale privacy- en dataveiligheid.
</p>
</div>
</div>
<div class="text-xs font-mono font-medium text-emerald-700 dark:text-emerald-400 flex items-center space-x-1.5 flex-shrink-0 self-end sm:self-center">
<i data-lucide="lock" class="w-4 h-4"></i>
<span>Verplicht & Actief</span>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Profielnaam formulier -->
<div class="bg-white dark:bg-slate-900/80 border border-slate-200 dark:border-slate-800 rounded-3xl p-6 sm:p-7 shadow-sm dark:shadow-xl space-y-4 transition">
<div class="flex items-center space-x-3 pb-4 border-b border-slate-100 dark:border-slate-800/80">