Compare commits

..

3 Commits

12 changed files with 1060 additions and 632 deletions
+120 -121
View File
@@ -129,30 +129,30 @@ require_once __DIR__ . '/includes/header.php';
<div class="space-y-8 max-w-7xl mx-auto pb-12"> <div class="space-y-8 max-w-7xl mx-auto pb-12">
<!-- Top Header Banner --> <!-- Top Header Banner -->
<div class="relative overflow-hidden bg-slate-900/90 border border-slate-800 rounded-3xl p-6 sm:p-8 shadow-2xl backdrop-blur-xl"> <div class="relative overflow-hidden bg-white dark:bg-slate-900/90 border border-slate-200 dark:border-slate-800 rounded-3xl p-6 sm:p-8 shadow-sm dark:shadow-2xl backdrop-blur-xl transition">
<div class="absolute -top-24 -right-24 w-80 h-80 bg-emerald-500/10 rounded-full blur-3xl pointer-events-none"></div> <div class="absolute -top-24 -right-24 w-80 h-80 bg-emerald-500/10 rounded-full blur-3xl pointer-events-none"></div>
<div class="absolute -bottom-24 -left-24 w-80 h-80 bg-blue-500/10 rounded-full blur-3xl pointer-events-none"></div> <div class="absolute -bottom-24 -left-24 w-80 h-80 bg-blue-500/10 rounded-full blur-3xl pointer-events-none"></div>
<div class="relative z-10 flex flex-col md:flex-row md:items-center md:justify-between gap-6"> <div class="relative z-10 flex flex-col md:flex-row md:items-center md:justify-between gap-6">
<div class="space-y-2"> <div class="space-y-2">
<div class="inline-flex items-center space-x-2 px-3 py-1 rounded-full bg-emerald-500/10 border border-emerald-500/30 text-emerald-400 text-xs font-semibold tracking-wide"> <div class="inline-flex items-center space-x-2 px-3 py-1 rounded-full bg-emerald-500/10 border border-emerald-500/30 text-emerald-700 dark:text-emerald-400 text-xs font-semibold tracking-wide">
<i data-lucide="shield-alert" class="w-3.5 h-3.5"></i> <i data-lucide="shield-alert" class="w-3.5 h-3.5"></i>
<span>Beheerderspaneel • Alleen toegankelijk voor Beheer</span> <span>Beheerderspaneel • Alleen toegankelijk voor Beheer</span>
</div> </div>
<h1 class="text-3xl sm:text-4xl font-black text-white tracking-tight"> <h1 class="text-3xl sm:text-4xl font-black text-slate-900 dark:text-white tracking-tight">
Systeembeheer & Integraties Systeembeheer & Integraties
</h1> </h1>
<p class="text-sm text-slate-400 max-w-2xl leading-relaxed"> <p class="text-sm text-slate-600 dark:text-slate-400 max-w-2xl leading-relaxed">
Beheer hier de centrale organisatiekoppelingen zoals Microsoft 365 Azure App Registratie en Jira, inspecteer de teamstatus en configureer toekomstige modules. Beheer hier de centrale organisatiekoppelingen zoals Microsoft 365 Azure App Registratie en Jira, inspecteer de teamstatus en configureer toekomstige modules.
</p> </p>
</div> </div>
<div class="flex flex-wrap items-center gap-3"> <div class="flex flex-wrap items-center gap-3">
<a href="/users.php" class="inline-flex items-center space-x-2 px-4 py-2.5 rounded-xl bg-slate-800/90 hover:bg-slate-700 text-slate-200 border border-slate-700 text-xs font-semibold transition shadow-md"> <a href="/users.php" class="inline-flex items-center space-x-2 px-4 py-2.5 rounded-xl bg-slate-100 hover:bg-slate-200 dark:bg-slate-800/90 dark:hover:bg-slate-700 text-slate-800 dark:text-slate-200 border border-slate-200 dark:border-slate-700 text-xs font-semibold transition shadow-sm">
<i data-lucide="users" class="w-4 h-4 text-emerald-400"></i> <i data-lucide="users" class="w-4 h-4 text-emerald-600 dark:text-emerald-400"></i>
<span>Team & Invites (<?= $totalUsers ?>)</span> <span>Team & Invites (<?= $totalUsers ?>)</span>
</a> </a>
<a href="/profile.php" class="inline-flex items-center space-x-2 px-4 py-2.5 rounded-xl bg-emerald-600 hover:bg-emerald-500 text-slate-950 text-xs font-bold transition shadow-lg shadow-emerald-600/20"> <a href="/profile.php" class="inline-flex items-center space-x-2 px-4 py-2.5 rounded-xl bg-emerald-600 hover:bg-emerald-500 text-white dark:text-slate-950 text-xs font-bold transition shadow-lg shadow-emerald-600/20">
<i data-lucide="user" class="w-4 h-4"></i> <i data-lucide="user" class="w-4 h-4"></i>
<span>Mijn Persoonlijk Profiel</span> <span>Mijn Persoonlijk Profiel</span>
</a> </a>
@@ -162,55 +162,55 @@ require_once __DIR__ . '/includes/header.php';
<!-- Meldingen Banner --> <!-- Meldingen Banner -->
<?php if ($message): ?> <?php if ($message): ?>
<div class="p-4 rounded-2xl flex items-start space-x-3 text-sm animate-in fade-in duration-200 <?= $messageType === 'success' ? 'bg-emerald-500/10 border border-emerald-500/30 text-emerald-200' : 'bg-red-500/10 border border-red-500/30 text-red-200' ?>"> <div class="p-4 rounded-2xl flex items-start space-x-3 text-sm animate-in fade-in duration-200 <?= $messageType === 'success' ? 'bg-emerald-500/10 border border-emerald-500/30 text-emerald-800 dark:text-emerald-200' : 'bg-red-500/10 border border-red-500/30 text-red-800 dark:text-red-200' ?>">
<i data-lucide="<?= $messageType === 'success' ? 'check-circle-2' : 'alert-triangle' ?>" class="w-5 h-5 flex-shrink-0 mt-0.5 <?= $messageType === 'success' ? 'text-emerald-400' : 'text-red-400' ?>"></i> <i data-lucide="<?= $messageType === 'success' ? 'check-circle-2' : 'alert-triangle' ?>" class="w-5 h-5 flex-shrink-0 mt-0.5 <?= $messageType === 'success' ? 'text-emerald-600 dark:text-emerald-400' : 'text-red-600 dark:text-red-400' ?>"></i>
<div class="flex-1 font-medium"><?= htmlspecialchars($message) ?></div> <div class="flex-1 font-medium"><?= htmlspecialchars($message) ?></div>
</div> </div>
<?php endif; ?> <?php endif; ?>
<!-- Stat kaarten rij --> <!-- Stat kaarten rij -->
<div class="grid grid-cols-2 lg:grid-cols-4 gap-4"> <div class="grid grid-cols-2 lg:grid-cols-4 gap-4">
<div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4 flex items-center space-x-4"> <div class="bg-white dark:bg-slate-900/70 border border-slate-200 dark:border-slate-800 rounded-3xl p-5 flex items-center space-x-4 shadow-sm transition">
<div class="w-12 h-12 rounded-xl bg-emerald-500/10 border border-emerald-500/20 flex items-center justify-center text-emerald-400 flex-shrink-0"> <div class="w-12 h-12 rounded-2xl bg-emerald-500/10 border border-emerald-500/20 flex items-center justify-center text-emerald-600 dark:text-emerald-400 flex-shrink-0">
<i data-lucide="users" class="w-6 h-6"></i> <i data-lucide="users" class="w-6 h-6"></i>
</div> </div>
<div> <div>
<span class="text-xs text-slate-400 font-medium block">Totaal Teamleden</span> <span class="text-xs text-slate-500 dark:text-slate-400 font-medium block">Totaal Teamleden</span>
<span class="text-2xl font-black text-white"><?= $totalUsers ?></span> <span class="text-2xl font-black text-slate-900 dark:text-white"><?= $totalUsers ?></span>
<span class="text-[10px] text-slate-500 block"><?= $totalAdmins ?> Beheerders • <?= $totalMembers ?> Collega's</span> <span class="text-[10px] text-slate-500 dark:text-slate-500 block"><?= $totalAdmins ?> Beheerders • <?= $totalMembers ?> Collega's</span>
</div> </div>
</div> </div>
<div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4 flex items-center space-x-4"> <div class="bg-white dark:bg-slate-900/70 border border-slate-200 dark:border-slate-800 rounded-3xl p-5 flex items-center space-x-4 shadow-sm transition">
<div class="w-12 h-12 rounded-xl bg-blue-500/10 border border-blue-500/20 flex items-center justify-center text-blue-400 flex-shrink-0"> <div class="w-12 h-12 rounded-2xl bg-blue-500/10 border border-blue-500/20 flex items-center justify-center text-blue-600 dark:text-blue-400 flex-shrink-0">
<i data-lucide="calendar" class="w-6 h-6"></i> <i data-lucide="calendar" class="w-6 h-6"></i>
</div> </div>
<div> <div>
<span class="text-xs text-slate-400 font-medium block">Outlook Live Gekoppeld</span> <span class="text-xs text-slate-500 dark:text-slate-400 font-medium block">Outlook Live Gekoppeld</span>
<span class="text-2xl font-black text-white"><?= $outlookConnectedCount ?></span> <span class="text-2xl font-black text-slate-900 dark:text-white"><?= $outlookConnectedCount ?></span>
<span class="text-[10px] text-emerald-400 block"><?= $appConfig['is_configured'] ? 'Azure App Actief' : 'Configuratie nodig' ?></span> <span class="text-[10px] text-emerald-600 dark:text-emerald-400 block"><?= $appConfig['is_configured'] ? 'Azure App Actief' : 'Configuratie nodig' ?></span>
</div> </div>
</div> </div>
<div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4 flex items-center space-x-4"> <div class="bg-white dark:bg-slate-900/70 border border-slate-200 dark:border-slate-800 rounded-3xl p-5 flex items-center space-x-4 shadow-sm transition">
<div class="w-12 h-12 rounded-xl bg-indigo-500/10 border border-indigo-500/20 flex items-center justify-center text-indigo-400 flex-shrink-0"> <div class="w-12 h-12 rounded-2xl bg-indigo-500/10 border border-indigo-500/20 flex items-center justify-center text-indigo-600 dark:text-indigo-400 flex-shrink-0">
<i data-lucide="check-square" class="w-6 h-6"></i> <i data-lucide="check-square" class="w-6 h-6"></i>
</div> </div>
<div> <div>
<span class="text-xs text-slate-400 font-medium block">Jira Gekoppeld</span> <span class="text-xs text-slate-500 dark:text-slate-400 font-medium block">Jira Gekoppeld</span>
<span class="text-2xl font-black text-white"><?= $jiraConnectedCount ?></span> <span class="text-2xl font-black text-slate-900 dark:text-white"><?= $jiraConnectedCount ?></span>
<span class="text-[10px] text-slate-500 block"><?= !empty($companyJiraDomain) ? 'Domein ingesteld' : 'Geen domein' ?></span> <span class="text-[10px] text-slate-500 dark:text-slate-500 block"><?= !empty($companyJiraDomain) ? 'Domein ingesteld' : 'Geen domein' ?></span>
</div> </div>
</div> </div>
<div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4 flex items-center space-x-4"> <div class="bg-white dark:bg-slate-900/70 border border-slate-200 dark:border-slate-800 rounded-3xl p-5 flex items-center space-x-4 shadow-sm transition">
<div class="w-12 h-12 rounded-xl bg-amber-500/10 border border-amber-500/20 flex items-center justify-center text-amber-400 flex-shrink-0"> <div class="w-12 h-12 rounded-2xl bg-amber-500/10 border border-amber-500/20 flex items-center justify-center text-amber-600 dark:text-amber-400 flex-shrink-0">
<i data-lucide="mail" class="w-6 h-6"></i> <i data-lucide="mail" class="w-6 h-6"></i>
</div> </div>
<div> <div>
<span class="text-xs text-slate-400 font-medium block">Openstaande Invites</span> <span class="text-xs text-slate-500 dark:text-slate-400 font-medium block">Openstaande Invites</span>
<span class="text-2xl font-black text-white"><?= $pendingInvites ?></span> <span class="text-2xl font-black text-slate-900 dark:text-white"><?= $pendingInvites ?></span>
<a href="/users.php" class="text-[10px] text-amber-400 hover:underline block">Beheer uitnodigingen &rarr;</a> <a href="/users.php" class="text-[10px] text-amber-600 dark:text-amber-400 hover:underline block font-medium">Beheer uitnodigingen &rarr;</a>
</div> </div>
</div> </div>
</div> </div>
@@ -222,34 +222,34 @@ require_once __DIR__ . '/includes/header.php';
<div class="lg:col-span-8 space-y-8"> <div class="lg:col-span-8 space-y-8">
<!-- 1. Microsoft 365 Azure App Registratie --> <!-- 1. Microsoft 365 Azure App Registratie -->
<div class="bg-slate-900/80 border border-slate-800 rounded-3xl p-6 sm:p-7 shadow-xl"> <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 transition">
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 pb-6 border-b border-slate-800/80"> <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 pb-6 border-b border-slate-100 dark:border-slate-800/80">
<div class="flex items-center space-x-3.5"> <div class="flex items-center space-x-3.5">
<div class="w-12 h-12 rounded-2xl bg-blue-500/10 border border-blue-500/20 flex items-center justify-center text-blue-400 font-bold shadow-md"> <div class="w-12 h-12 rounded-2xl bg-blue-500/10 border border-blue-500/20 flex items-center justify-center text-blue-600 dark:text-blue-400 font-bold shadow-sm">
<i data-lucide="cloud" class="w-6 h-6"></i> <i data-lucide="cloud" class="w-6 h-6"></i>
</div> </div>
<div> <div>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<h2 class="text-lg font-bold text-white tracking-tight">Microsoft 365 & Azure App Registratie</h2> <h2 class="text-lg font-bold text-slate-900 dark:text-white tracking-tight">Microsoft 365 & Azure App Registratie</h2>
<?php if ($appConfig['is_configured']): ?> <?php if ($appConfig['is_configured']): ?>
<span class="px-2.5 py-0.5 rounded-full bg-emerald-500/15 border border-emerald-500/30 text-emerald-400 text-[10px] font-bold"> <span class="px-2.5 py-0.5 rounded-full bg-emerald-500/15 border border-emerald-500/30 text-emerald-700 dark:text-emerald-400 text-[10px] font-bold">
Geconfigureerd Geconfigureerd
</span> </span>
<?php else: ?> <?php else: ?>
<span class="px-2.5 py-0.5 rounded-full bg-amber-500/15 border border-amber-500/30 text-amber-400 text-[10px] font-bold"> <span class="px-2.5 py-0.5 rounded-full bg-amber-500/15 border border-amber-500/30 text-amber-700 dark:text-amber-400 text-[10px] font-bold">
Configuratie Vereist Configuratie Vereist
</span> </span>
<?php endif; ?> <?php endif; ?>
</div> </div>
<p class="text-xs text-slate-400">Centrale OAuth 2.0 instellingen voor de hele organisatie</p> <p class="text-xs text-slate-500 dark:text-slate-400">Centrale OAuth 2.0 instellingen voor de hele organisatie</p>
</div> </div>
</div> </div>
<?php if ($appConfig['is_configured']): ?> <?php if ($appConfig['is_configured']): ?>
<a href="<?= htmlspecialchars($adminConsentUrl) ?>" target="_blank" rel="noopener noreferrer" class="inline-flex items-center space-x-2 px-3.5 py-2 rounded-xl bg-blue-600/20 hover:bg-blue-600/30 text-blue-300 border border-blue-500/30 text-xs font-semibold transition" title="Verleen namens alle gebruikers beheerdersgoedkeuring in Azure"> <a href="<?= htmlspecialchars($adminConsentUrl) ?>" target="_blank" rel="noopener noreferrer" class="inline-flex items-center space-x-2 px-3.5 py-2 rounded-xl bg-blue-50 hover:bg-blue-100 dark:bg-blue-600/20 dark:hover:bg-blue-600/30 text-blue-700 dark:text-blue-300 border border-blue-200 dark:border-blue-500/30 text-xs font-semibold transition" title="Verleen namens alle gebruikers beheerdersgoedkeuring in Azure">
<i data-lucide="shield-check" class="w-4 h-4 text-blue-400"></i> <i data-lucide="shield-check" class="w-4 h-4 text-blue-600 dark:text-blue-400"></i>
<span>Admin Consent Verlenen</span> <span>Admin Consent Verlenen</span>
<i data-lucide="external-link" class="w-3.5 h-3.5 text-blue-400"></i> <i data-lucide="external-link" class="w-3.5 h-3.5 text-blue-600 dark:text-blue-400"></i>
</a> </a>
<?php endif; ?> <?php endif; ?>
</div> </div>
@@ -258,17 +258,17 @@ require_once __DIR__ . '/includes/header.php';
<input type="hidden" name="action" value="save_azure"> <input type="hidden" name="action" value="save_azure">
<!-- Redirect URI Kopieerbox --> <!-- Redirect URI Kopieerbox -->
<div class="p-4 rounded-2xl bg-slate-950/70 border border-slate-800 space-y-2"> <div class="p-4 rounded-2xl bg-slate-50 dark:bg-slate-950/70 border border-slate-200 dark:border-slate-800 space-y-2">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<label class="text-xs font-semibold text-slate-300 flex items-center space-x-1.5"> <label class="text-xs font-semibold text-slate-700 dark:text-slate-300 flex items-center space-x-1.5">
<i data-lucide="link" class="w-3.5 h-3.5 text-blue-400"></i> <i data-lucide="link" class="w-3.5 h-3.5 text-blue-500"></i>
<span>Redirect URI (Terugbel-URL voor Azure Portal)</span> <span>Redirect URI (Terugbel-URL voor Azure Portal)</span>
</label> </label>
<span class="text-[10px] text-slate-500">Kopieer dit exact naar de Azure Web Redirect URIs</span> <span class="text-[10px] text-slate-500">Kopieer dit exact naar de Azure Web Redirect URIs</span>
</div> </div>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<input type="text" readonly id="adminRedirectUri" value="<?= htmlspecialchars($redirectUri) ?>" class="flex-1 bg-slate-900 border border-slate-800 rounded-xl px-3 py-2 text-xs font-mono text-emerald-400 select-all focus:outline-none"> <input type="text" readonly id="adminRedirectUri" value="<?= htmlspecialchars($redirectUri) ?>" class="flex-1 bg-white dark:bg-slate-900 border border-slate-300 dark:border-slate-800 rounded-xl px-3 py-2 text-xs font-mono text-emerald-600 dark:text-emerald-400 select-all focus:outline-none">
<button type="button" onclick="copyAdminRedirectUri()" class="px-3 py-2 rounded-xl bg-slate-800 hover:bg-slate-700 text-white text-xs font-semibold flex items-center space-x-1.5 transition"> <button type="button" onclick="copyAdminRedirectUri()" class="px-3 py-2 rounded-xl bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-800 dark:text-white text-xs font-semibold flex items-center space-x-1.5 transition border border-slate-200 dark:border-transparent cursor-pointer">
<i data-lucide="copy" class="w-3.5 h-3.5" id="copyIcon"></i> <i data-lucide="copy" class="w-3.5 h-3.5" id="copyIcon"></i>
<span id="copyText">Kopiëren</span> <span id="copyText">Kopiëren</span>
</button> </button>
@@ -278,83 +278,83 @@ require_once __DIR__ . '/includes/header.php';
<!-- Client ID & Tenant ID Grid --> <!-- Client ID & Tenant ID Grid -->
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div> <div>
<label class="block text-xs font-semibold text-slate-300 mb-1.5"> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1.5">
Application (Client) ID <span class="text-red-400">*</span> Application (Client) ID <span class="text-red-500">*</span>
</label> </label>
<input type="text" name="client_id" required value="<?= htmlspecialchars($appConfig['client_id']) ?>" placeholder="bijv. 38314451-1d05-4205-88ec-..." class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-white placeholder-slate-600 focus:outline-none focus:border-blue-500"> <input type="text" name="client_id" required value="<?= htmlspecialchars($appConfig['client_id']) ?>" placeholder="bijv. 38314451-1d05-4205-88ec-..." class="w-full bg-white dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-600 focus:outline-none focus:border-blue-500">
</div> </div>
<div> <div>
<label class="block text-xs font-semibold text-slate-300 mb-1.5"> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1.5">
Directory (Tenant) ID / Domeinnaam Directory (Tenant) ID / Domeinnaam
</label> </label>
<input type="text" name="tenant_id" value="<?= htmlspecialchars((!empty($appConfig['tenant_id']) && $appConfig['tenant_id'] !== 'common') ? $appConfig['tenant_id'] : 'planningsagenda.nl') ?>" placeholder="bijv. planningsagenda.nl of Azure Tenant GUID" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-white placeholder-slate-600 focus:outline-none focus:border-blue-500 font-mono"> <input type="text" name="tenant_id" value="<?= htmlspecialchars((!empty($appConfig['tenant_id']) && $appConfig['tenant_id'] !== 'common') ? $appConfig['tenant_id'] : 'planningsagenda.nl') ?>" placeholder="bijv. planningsagenda.nl of Azure Tenant GUID" class="w-full bg-white dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-600 focus:outline-none focus:border-blue-500 font-mono">
<span class="text-[10px] text-slate-400 mt-1 block">Vul uw domeinnaam in (<code class="text-emerald-400 font-mono">planningsagenda.nl</code>) of de Directory (tenant) ID uit Azure. <em>Let op: Gebruik géén 'common' voor single-tenant apps.</em></span> <span class="text-[10px] text-slate-500 dark:text-slate-400 mt-1 block">Vul uw domeinnaam in (<code class="text-emerald-600 dark:text-emerald-400 font-mono">planningsagenda.nl</code>) of de Directory (tenant) ID uit Azure. <em>Let op: Gebruik géén 'common' voor single-tenant apps.</em></span>
</div> </div>
</div> </div>
<!-- Client Secret met toggle --> <!-- Client Secret met toggle -->
<div> <div>
<div class="flex items-center justify-between mb-1.5"> <div class="flex items-center justify-between mb-1.5">
<label class="text-xs font-semibold text-slate-300"> <label class="text-xs font-semibold text-slate-700 dark:text-slate-300">
Client Secret (Value) <span class="text-red-400">*</span> Client Secret (Value) <span class="text-red-500">*</span>
</label> </label>
<span class="text-[10px] text-slate-500">Wordt veilig en versleuteld opgeslagen</span> <span class="text-[10px] text-slate-500">Wordt veilig en versleuteld opgeslagen</span>
</div> </div>
<div class="relative"> <div class="relative">
<input type="password" id="adminClientSecret" name="client_secret" value="<?= !empty($appConfig['client_secret']) ? '••••••••••••••••' : '' ?>" placeholder="Voer de Secret Value in uit Azure..." class="w-full bg-slate-950 border border-slate-800 rounded-xl pl-3.5 pr-10 py-2.5 text-xs text-white placeholder-slate-600 focus:outline-none focus:border-blue-500"> <input type="password" id="adminClientSecret" name="client_secret" value="<?= !empty($appConfig['client_secret']) ? '••••••••••••••••' : '' ?>" placeholder="Voer de Secret Value in uit Azure..." class="w-full bg-white dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl pl-3.5 pr-10 py-2.5 text-xs text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-600 focus:outline-none focus:border-blue-500">
<button type="button" onclick="toggleAdminSecret()" class="absolute inset-y-0 right-0 pr-3 flex items-center text-slate-500 hover:text-slate-300"> <button type="button" onclick="toggleAdminSecret()" class="absolute inset-y-0 right-0 pr-3 flex items-center text-slate-400 hover:text-slate-600 dark:hover:text-slate-300">
<i data-lucide="eye" class="w-4 h-4" id="eyeSecretIcon"></i> <i data-lucide="eye" class="w-4 h-4" id="eyeSecretIcon"></i>
</button> </button>
</div> </div>
</div> </div>
<div class="pt-2 flex items-center justify-between"> <div class="pt-2 flex items-center justify-between">
<div class="text-[11px] text-slate-400"> <div class="text-[11px] text-slate-500 dark:text-slate-400">
Zodra opgeslagen kunnen al uw collega's met 1 klik hun Outlook agenda koppelen. Zodra opgeslagen kunnen al uw collega's met 1 klik hun Outlook agenda koppelen.
</div> </div>
<button type="submit" class="px-5 py-2.5 rounded-xl bg-blue-600 hover:bg-blue-500 text-white text-xs font-bold transition shadow-lg shadow-blue-500/20"> <button type="submit" class="px-5 py-2.5 rounded-xl bg-blue-600 hover:bg-blue-500 text-white text-xs font-bold transition shadow-lg shadow-blue-500/20 cursor-pointer">
Azure Gegevens Opslaan Azure Gegevens Opslaan
</button> </button>
</div> </div>
</form> </form>
<!-- Azure Setup Documentatie Accordion --> <!-- Azure Setup Documentatie Accordion -->
<div class="mt-6 pt-6 border-t border-slate-800/80"> <div class="mt-6 pt-6 border-t border-slate-100 dark:border-slate-800/80">
<button type="button" onclick="toggleAdminGuide()" class="w-full flex items-center justify-between text-xs font-semibold text-slate-300 hover:text-white transition"> <button type="button" onclick="toggleAdminGuide()" class="w-full flex items-center justify-between text-xs font-semibold text-slate-700 dark:text-slate-300 hover:text-slate-900 dark:hover:text-white transition cursor-pointer">
<span class="flex items-center space-x-2"> <span class="flex items-center space-x-2">
<i data-lucide="help-circle" class="w-4 h-4 text-blue-400"></i> <i data-lucide="help-circle" class="w-4 h-4 text-blue-500"></i>
<span>Hoe configureer ik de Azure App Registratie in 4 stappen?</span> <span>Hoe configureer ik de Azure App Registratie in 4 stappen?</span>
</span> </span>
<i data-lucide="chevron-down" class="w-4 h-4 transition-transform duration-200" id="guideArrow"></i> <i data-lucide="chevron-down" class="w-4 h-4 transition-transform duration-200" id="guideArrow"></i>
</button> </button>
<div id="adminGuideContent" class="hidden mt-4 p-4 rounded-2xl bg-slate-950/60 border border-slate-800 text-xs text-slate-300 space-y-3 leading-relaxed"> <div id="adminGuideContent" class="hidden mt-4 p-4 rounded-2xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800 text-xs text-slate-600 dark:text-slate-300 space-y-3 leading-relaxed">
<div class="flex items-start space-x-2.5"> <div class="flex items-start space-x-2.5">
<span class="w-5 h-5 rounded-full bg-blue-500/20 text-blue-400 flex items-center justify-center font-bold text-[10px] flex-shrink-0 mt-0.5">1</span> <span class="w-5 h-5 rounded-full bg-blue-500/20 text-blue-600 dark:text-blue-400 flex items-center justify-center font-bold text-[10px] flex-shrink-0 mt-0.5">1</span>
<div> <div>
<strong class="text-white">Azure Portal:</strong> Ga naar <a href="https://portal.azure.com/#view/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/~/RegisteredApps" target="_blank" class="text-blue-400 underline">portal.azure.com</a> &rarr; <em>Microsoft Entra ID</em> &rarr; <em>App registrations</em> &rarr; <em>New registration</em>. Kies "Accounts in any organizational directory and personal Microsoft accounts" (of alleen uw organisatie). <strong class="text-slate-900 dark:text-white">Azure Portal:</strong> Ga naar <a href="https://portal.azure.com/#view/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/~/RegisteredApps" target="_blank" class="text-blue-600 dark:text-blue-400 underline">portal.azure.com</a> &rarr; <em>Microsoft Entra ID</em> &rarr; <em>App registrations</em> &rarr; <em>New registration</em>. Kies "Accounts in this organizational directory only" (single-tenant).
</div> </div>
</div> </div>
<div class="flex items-start space-x-2.5"> <div class="flex items-start space-x-2.5">
<span class="w-5 h-5 rounded-full bg-blue-500/20 text-blue-400 flex items-center justify-center font-bold text-[10px] flex-shrink-0 mt-0.5">2</span> <span class="w-5 h-5 rounded-full bg-blue-500/20 text-blue-600 dark:text-blue-400 flex items-center justify-center font-bold text-[10px] flex-shrink-0 mt-0.5">2</span>
<div> <div>
<strong class="text-white">Redirect URI:</strong> Kies platform <strong>Web</strong> en vul exact in: <code class="text-emerald-400 font-mono"><?= htmlspecialchars($redirectUri) ?></code>. <strong class="text-slate-900 dark:text-white">Redirect URI:</strong> Kies platform <strong>Web</strong> en vul exact in: <code class="text-emerald-600 dark:text-emerald-400 font-mono"><?= htmlspecialchars($redirectUri) ?></code>.
</div> </div>
</div> </div>
<div class="flex items-start space-x-2.5"> <div class="flex items-start space-x-2.5">
<span class="w-5 h-5 rounded-full bg-blue-500/20 text-blue-400 flex items-center justify-center font-bold text-[10px] flex-shrink-0 mt-0.5">3</span> <span class="w-5 h-5 rounded-full bg-blue-500/20 text-blue-600 dark:text-blue-400 flex items-center justify-center font-bold text-[10px] flex-shrink-0 mt-0.5">3</span>
<div> <div>
<strong class="text-white">API Permissions:</strong> Ga naar <em>API permissions</em> &rarr; <em>Add a permission</em> &rarr; <em>Microsoft Graph</em> &rarr; <strong>Delegated permissions</strong> &rarr; Vink aan: <code class="text-blue-400">User.Read</code> en <code class="text-blue-400">Calendars.ReadWrite</code>. <strong class="text-slate-900 dark:text-white">API Permissions:</strong> Ga naar <em>API permissions</em> &rarr; <em>Add a permission</em> &rarr; <em>Microsoft Graph</em> &rarr; <strong>Delegated permissions</strong> &rarr; Vink aan: <code class="text-blue-600 dark:text-blue-400">User.Read</code> en <code class="text-blue-600 dark:text-blue-400">Calendars.ReadWrite</code>.
</div> </div>
</div> </div>
<div class="flex items-start space-x-2.5"> <div class="flex items-start space-x-2.5">
<span class="w-5 h-5 rounded-full bg-blue-500/20 text-blue-400 flex items-center justify-center font-bold text-[10px] flex-shrink-0 mt-0.5">4</span> <span class="w-5 h-5 rounded-full bg-blue-500/20 text-blue-600 dark:text-blue-400 flex items-center justify-center font-bold text-[10px] flex-shrink-0 mt-0.5">4</span>
<div> <div>
<strong class="text-white">Beheerdersgoedkeuring (Admin Consent):</strong> Klik op <em>"Grant admin consent for [Uw Organisatie]"</em>. Er verschijnt direct een groen vinkje bij alle regels. Hiermee hoeven individuele collega's geen beheerder meer te vragen! <strong class="text-slate-900 dark:text-white">Beheerdersgoedkeuring (Admin Consent):</strong> Klik op <em>"Grant admin consent for [Uw Organisatie]"</em>. Er verschijnt direct een groen vinkje bij alle regels. Hiermee hoeven individuele collega's geen beheerder meer te vragen!
</div> </div>
</div> </div>
</div> </div>
@@ -362,25 +362,25 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
<!-- 2. Atlassian Jira Bedrijfsinstellingen --> <!-- 2. Atlassian Jira Bedrijfsinstellingen -->
<div class="bg-slate-900/80 border border-slate-800 rounded-3xl p-6 sm:p-7 shadow-xl"> <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 transition">
<div class="flex items-center space-x-3.5 pb-6 border-b border-slate-800/80"> <div class="flex items-center space-x-3.5 pb-6 border-b border-slate-100 dark:border-slate-800/80">
<div class="w-12 h-12 rounded-2xl bg-indigo-500/10 border border-indigo-500/20 flex items-center justify-center text-indigo-400 font-bold shadow-md"> <div class="w-12 h-12 rounded-2xl bg-indigo-500/10 border border-indigo-500/20 flex items-center justify-center text-indigo-600 dark:text-indigo-400 font-bold shadow-sm">
<i data-lucide="trello" class="w-6 h-6"></i> <i data-lucide="trello" class="w-6 h-6"></i>
</div> </div>
<div> <div>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<h2 class="text-lg font-bold text-white tracking-tight">Atlassian Jira Organisatie-instellingen</h2> <h2 class="text-lg font-bold text-slate-900 dark:text-white tracking-tight">Atlassian Jira Organisatie-instellingen</h2>
<?php if (!empty($companyJiraDomain)): ?> <?php if (!empty($companyJiraDomain)): ?>
<span class="px-2.5 py-0.5 rounded-full bg-emerald-500/15 border border-emerald-500/30 text-emerald-400 text-[10px] font-bold"> <span class="px-2.5 py-0.5 rounded-full bg-emerald-500/15 border border-emerald-500/30 text-emerald-700 dark:text-emerald-400 text-[10px] font-bold">
Actief Actief
</span> </span>
<?php else: ?> <?php else: ?>
<span class="px-2.5 py-0.5 rounded-full bg-slate-800 text-slate-400 text-[10px] font-bold"> <span class="px-2.5 py-0.5 rounded-full bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400 text-[10px] font-bold">
Optioneel Optioneel
</span> </span>
<?php endif; ?> <?php endif; ?>
</div> </div>
<p class="text-xs text-slate-400">Standaard Jira Cloud domein voor het hele team</p> <p class="text-xs text-slate-500 dark:text-slate-400">Standaard Jira Cloud domein voor het hele team</p>
</div> </div>
</div> </div>
@@ -388,17 +388,17 @@ require_once __DIR__ . '/includes/header.php';
<input type="hidden" name="action" value="save_jira_domain"> <input type="hidden" name="action" value="save_jira_domain">
<div> <div>
<label class="block text-xs font-semibold text-slate-300 mb-1.5"> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1.5">
Standaard Jira Bedrijfsdomein Standaard Jira Bedrijfsdomein
</label> </label>
<input type="text" name="jira_domain" value="<?= htmlspecialchars($companyJiraDomain) ?>" placeholder="https://uwbedrijf.atlassian.net" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-white placeholder-slate-600 focus:outline-none focus:border-indigo-500 font-mono"> <input type="text" name="jira_domain" value="<?= htmlspecialchars($companyJiraDomain) ?>" placeholder="https://uwbedrijf.atlassian.net" class="w-full bg-white dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-600 focus:outline-none focus:border-indigo-500 font-mono">
<p class="text-[11px] text-slate-400 mt-1.5 leading-relaxed"> <p class="text-[11px] text-slate-500 dark:text-slate-400 mt-1.5 leading-relaxed">
Wanneer u dit instelt, wordt dit domein automatisch vooraf ingevuld op de profielpagina van alle collega's. Zij hoeven dan enkel nog hun eigen persoonlijke e-mailadres en Atlassian API-token in te voeren. Wanneer u dit instelt, wordt dit domein automatisch vooraf ingevuld op de profielpagina van alle collega's. Zij hoeven dan enkel nog hun eigen persoonlijke e-mailadres en Atlassian API-token in te voeren.
</p> </p>
</div> </div>
<div class="flex justify-end pt-2"> <div class="flex justify-end pt-2">
<button type="submit" class="px-5 py-2.5 rounded-xl bg-indigo-600 hover:bg-indigo-500 text-white text-xs font-bold transition shadow-lg shadow-indigo-500/20"> <button type="submit" class="px-5 py-2.5 rounded-xl bg-indigo-600 hover:bg-indigo-500 text-white text-xs font-bold transition shadow-lg shadow-indigo-500/20 cursor-pointer">
Jira Domein Opslaan Jira Domein Opslaan
</button> </button>
</div> </div>
@@ -406,56 +406,56 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
<!-- 3. Toekomstige Systeemmodules Hub --> <!-- 3. Toekomstige Systeemmodules Hub -->
<div class="bg-slate-900/80 border border-slate-800 rounded-3xl p-6 sm:p-7 shadow-xl space-y-6"> <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-6 transition">
<div class="flex items-center space-x-3.5 pb-4 border-b border-slate-800/80"> <div class="flex items-center space-x-3.5 pb-4 border-b border-slate-100 dark:border-slate-800/80">
<div class="w-12 h-12 rounded-2xl bg-teal-500/10 border border-teal-500/20 flex items-center justify-center text-teal-400 font-bold shadow-md"> <div class="w-12 h-12 rounded-2xl bg-teal-500/10 border border-teal-500/20 flex items-center justify-center text-teal-600 dark:text-teal-400 font-bold shadow-sm">
<i data-lucide="cpu" class="w-6 h-6"></i> <i data-lucide="cpu" class="w-6 h-6"></i>
</div> </div>
<div> <div>
<h2 class="text-lg font-bold text-white tracking-tight">Toekomstige Modules & Extensies</h2> <h2 class="text-lg font-bold text-slate-900 dark:text-white tracking-tight">Toekomstige Modules & Extensies</h2>
<p class="text-xs text-slate-400">Voorbereid architectuurkader voor nieuwe bedrijfssystemen</p> <p class="text-xs text-slate-500 dark:text-slate-400">Voorbereid architectuurkader voor nieuwe bedrijfssystemen</p>
</div> </div>
</div> </div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<!-- Module 1: AI Brainstorm --> <!-- Module 1: AI Brainstorm -->
<div class="p-4 rounded-2xl bg-slate-950/60 border border-slate-800/80 flex flex-col justify-between space-y-3"> <div class="p-4 rounded-2xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800/80 flex flex-col justify-between space-y-3">
<div> <div>
<div class="flex items-center justify-between mb-2"> <div class="flex items-center justify-between mb-2">
<span class="text-xs font-bold text-white flex items-center space-x-1.5"> <span class="text-xs font-bold text-slate-900 dark:text-white flex items-center space-x-1.5">
<i data-lucide="sparkles" class="w-4 h-4 text-amber-400"></i> <i data-lucide="sparkles" class="w-4 h-4 text-amber-500"></i>
<span>AI & Brainstorm Co-Pilot</span> <span>AI & Brainstorm Co-Pilot</span>
</span> </span>
<span class="px-2 py-0.5 rounded-full bg-amber-500/10 text-amber-400 text-[10px] font-semibold border border-amber-500/20"> <span class="px-2 py-0.5 rounded-full bg-amber-500/10 text-amber-700 dark:text-amber-400 text-[10px] font-semibold border border-amber-500/20">
Voorbereid Voorbereid
</span> </span>
</div> </div>
<p class="text-[11px] text-slate-400 leading-relaxed"> <p class="text-[11px] text-slate-600 dark:text-slate-400 leading-relaxed">
Centrale OpenAI of Anthropic Claude API-sleutels instellen voor automatische categorisatie van sticky notes en taakschattingen. Centrale OpenAI of Anthropic Claude API-sleutels instellen voor automatische categorisatie van sticky notes en taakschattingen.
</p> </p>
</div> </div>
<div class="pt-2 border-t border-slate-900 text-[10px] text-slate-500"> <div class="pt-2 border-t border-slate-200 dark:border-slate-900 text-[10px] text-slate-500">
Gepland voor release v1.5 Gepland voor release v1.5
</div> </div>
</div> </div>
<!-- Module 2: Dagplanning Standaarden --> <!-- Module 2: Dagplanning Standaarden -->
<div class="p-4 rounded-2xl bg-slate-950/60 border border-slate-800/80 flex flex-col justify-between space-y-3"> <div class="p-4 rounded-2xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800/80 flex flex-col justify-between space-y-3">
<div> <div>
<div class="flex items-center justify-between mb-2"> <div class="flex items-center justify-between mb-2">
<span class="text-xs font-bold text-white flex items-center space-x-1.5"> <span class="text-xs font-bold text-slate-900 dark:text-white flex items-center space-x-1.5">
<i data-lucide="clock" class="w-4 h-4 text-emerald-400"></i> <i data-lucide="clock" class="w-4 h-4 text-emerald-600 dark:text-emerald-400"></i>
<span>Organisatie Werkdag Standaarden</span> <span>Organisatie Werkdag Standaarden</span>
</span> </span>
<span class="px-2 py-0.5 rounded-full bg-emerald-500/10 text-emerald-400 text-[10px] font-semibold border border-emerald-500/20"> <span class="px-2 py-0.5 rounded-full bg-emerald-500/10 text-emerald-700 dark:text-emerald-400 text-[10px] font-semibold border border-emerald-500/20">
Binnenkort Binnenkort
</span> </span>
</div> </div>
<p class="text-[11px] text-slate-400 leading-relaxed"> <p class="text-[11px] text-slate-600 dark:text-slate-400 leading-relaxed">
Standaard kantoortijden instellen (bijv. 08:30 - 17:00), standaard Pomodoro tijden (25m / 50m) en lunchpauze blokken. Standaard kantoortijden instellen (bijv. 08:30 - 17:00), standaard Pomodoro tijden (25m / 50m) en lunchpauze blokken.
</p> </p>
</div> </div>
<div class="pt-2 border-t border-slate-900 text-[10px] text-slate-500"> <div class="pt-2 border-t border-slate-200 dark:border-slate-900 text-[10px] text-slate-500">
Gepland voor release v1.4 Gepland voor release v1.4
</div> </div>
</div> </div>
@@ -467,35 +467,35 @@ require_once __DIR__ . '/includes/header.php';
<div class="lg:col-span-4 space-y-6"> <div class="lg:col-span-4 space-y-6">
<!-- Team Status Overzicht --> <!-- Team Status Overzicht -->
<div class="bg-slate-900/80 border border-slate-800 rounded-3xl p-6 shadow-xl space-y-5"> <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 space-y-5 transition">
<div class="flex items-center justify-between pb-4 border-b border-slate-800/80"> <div class="flex items-center justify-between pb-4 border-b border-slate-100 dark:border-slate-800/80">
<div class="flex items-center space-x-2.5"> <div class="flex items-center space-x-2.5">
<i data-lucide="activity" class="w-4 h-4 text-emerald-400"></i> <i data-lucide="activity" class="w-4 h-4 text-emerald-600 dark:text-emerald-400"></i>
<h3 class="text-sm font-bold text-white">Team & Integratiestatus</h3> <h3 class="text-sm font-bold text-slate-900 dark:text-white">Team & Integratiestatus</h3>
</div> </div>
<a href="/users.php" class="text-[11px] text-emerald-400 hover:underline font-semibold"> <a href="/users.php" class="text-[11px] text-emerald-600 dark:text-emerald-400 hover:underline font-semibold">
Alle gebruikers &rarr; Alle gebruikers &rarr;
</a> </a>
</div> </div>
<div class="space-y-3"> <div class="space-y-3">
<?php foreach ($recentUsers as $u): ?> <?php foreach ($recentUsers as $u): ?>
<div class="p-3 rounded-2xl bg-slate-950/60 border border-slate-800/70 flex items-center justify-between"> <div class="p-3 rounded-2xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800/70 flex items-center justify-between">
<div class="flex items-center space-x-3 overflow-hidden"> <div class="flex items-center space-x-3 overflow-hidden">
<div class="w-8 h-8 rounded-full bg-emerald-600/20 border border-emerald-500/30 text-emerald-400 font-bold flex items-center justify-center text-xs flex-shrink-0"> <div class="w-8 h-8 rounded-full bg-emerald-600/15 border border-emerald-500/30 text-emerald-700 dark:text-emerald-400 font-bold flex items-center justify-center text-xs flex-shrink-0">
<?= strtoupper(substr($u['name'], 0, 1)) ?> <?= strtoupper(substr($u['name'], 0, 1)) ?>
</div> </div>
<div class="truncate"> <div class="truncate">
<span class="text-xs font-semibold text-white block truncate"><?= htmlspecialchars($u['name']) ?></span> <span class="text-xs font-semibold text-slate-900 dark:text-white block truncate"><?= htmlspecialchars($u['name']) ?></span>
<span class="text-[10px] text-slate-400 block truncate"><?= htmlspecialchars($u['email']) ?></span> <span class="text-[10px] text-slate-500 dark:text-slate-400 block truncate"><?= htmlspecialchars($u['email']) ?></span>
</div> </div>
</div> </div>
<div class="flex items-center space-x-1.5 flex-shrink-0"> <div class="flex items-center space-x-1.5 flex-shrink-0">
<span title="Outlook: <?= $u['has_outlook'] ? 'Live Gekoppeld' : 'Niet gekoppeld' ?>" class="w-5 h-5 rounded-md flex items-center justify-center text-[10px] <?= $u['has_outlook'] ? 'bg-blue-500/20 text-blue-300 border border-blue-500/30' : 'bg-slate-800 text-slate-600' ?>"> <span title="Outlook: <?= $u['has_outlook'] ? 'Live Gekoppeld' : 'Niet gekoppeld' ?>" class="w-5 h-5 rounded-md flex items-center justify-center text-[10px] <?= $u['has_outlook'] ? 'bg-blue-500/20 text-blue-700 dark:text-blue-300 border border-blue-500/30' : 'bg-slate-200 dark:bg-slate-800 text-slate-400 dark:text-slate-600' ?>">
<i data-lucide="calendar" class="w-3 h-3"></i> <i data-lucide="calendar" class="w-3 h-3"></i>
</span> </span>
<span title="Jira: <?= $u['has_jira'] ? 'Gekoppeld' : 'Niet gekoppeld' ?>" class="w-5 h-5 rounded-md flex items-center justify-center text-[10px] <?= $u['has_jira'] ? 'bg-indigo-500/20 text-indigo-300 border border-indigo-500/30' : 'bg-slate-800 text-slate-600' ?>"> <span title="Jira: <?= $u['has_jira'] ? 'Gekoppeld' : 'Niet gekoppeld' ?>" class="w-5 h-5 rounded-md flex items-center justify-center text-[10px] <?= $u['has_jira'] ? 'bg-indigo-500/20 text-indigo-700 dark:text-indigo-300 border border-indigo-500/30' : 'bg-slate-200 dark:bg-slate-800 text-slate-400 dark:text-slate-600' ?>">
<i data-lucide="check-square" class="w-3 h-3"></i> <i data-lucide="check-square" class="w-3 h-3"></i>
</span> </span>
</div> </div>
@@ -504,41 +504,41 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
<div class="pt-2"> <div class="pt-2">
<a href="/users.php" class="w-full flex items-center justify-center space-x-2 py-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-slate-200 text-xs font-semibold transition border border-slate-700"> <a href="/users.php" class="w-full flex items-center justify-center space-x-2 py-2.5 rounded-xl bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-800 dark:text-slate-200 text-xs font-semibold transition border border-slate-200 dark:border-slate-700 shadow-sm">
<i data-lucide="user-plus" class="w-3.5 h-3.5 text-emerald-400"></i> <i data-lucide="user-plus" class="w-3.5 h-3.5 text-emerald-600 dark:text-emerald-400"></i>
<span>Nieuwe Collega Uitnodigen</span> <span>Nieuwe Collega Uitnodigen</span>
</a> </a>
</div> </div>
</div> </div>
<!-- Systeem Gezondheid & Beveiliging --> <!-- Systeem Gezondheid & Beveiliging -->
<div class="bg-slate-900/80 border border-slate-800 rounded-3xl p-6 shadow-xl space-y-4"> <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 space-y-4 transition">
<div class="flex items-center space-x-2 text-emerald-400 text-xs font-semibold"> <div class="flex items-center space-x-2 text-emerald-600 dark:text-emerald-400 text-xs font-semibold">
<i data-lucide="shield-check" class="w-4 h-4"></i> <i data-lucide="shield-check" class="w-4 h-4"></i>
<span>Systeem & Beveiliging</span> <span>Systeem & Beveiliging</span>
</div> </div>
<div class="space-y-2.5 text-xs text-slate-300"> <div class="space-y-2.5 text-xs text-slate-700 dark:text-slate-300">
<div class="flex items-center justify-between p-2.5 rounded-xl bg-slate-950/60 border border-slate-800"> <div class="flex items-center justify-between p-2.5 rounded-xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800">
<span>Tweestapsverificatie (2FA)</span> <span>Tweestapsverificatie (2FA)</span>
<span class="text-emerald-400 font-bold flex items-center space-x-1"> <span class="text-emerald-600 dark:text-emerald-400 font-bold flex items-center space-x-1">
<i data-lucide="check" class="w-3 h-3"></i> <i data-lucide="check" class="w-3 h-3"></i>
<span>Verplicht</span> <span>Verplicht</span>
</span> </span>
</div> </div>
<div class="flex items-center justify-between p-2.5 rounded-xl bg-slate-950/60 border border-slate-800"> <div class="flex items-center justify-between p-2.5 rounded-xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800">
<span>Database Versie</span> <span>Database Versie</span>
<span class="text-slate-400 font-mono text-[11px]">MariaDB 10.x</span> <span class="text-slate-500 dark:text-slate-400 font-mono text-[11px]">MariaDB 10.x</span>
</div> </div>
<div class="flex items-center justify-between p-2.5 rounded-xl bg-slate-950/60 border border-slate-800"> <div class="flex items-center justify-between p-2.5 rounded-xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800">
<span>Push Notificaties</span> <span>Push Notificaties</span>
<span class="text-emerald-400 font-bold">Actief</span> <span class="text-emerald-600 dark:text-emerald-400 font-bold">Actief</span>
</div> </div>
<div class="flex items-center justify-between p-2.5 rounded-xl bg-slate-950/60 border border-slate-800"> <div class="flex items-center justify-between p-2.5 rounded-xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800">
<span>Graph API Sync</span> <span>Graph API Sync</span>
<span class="text-blue-400 font-bold">Live v1.0</span> <span class="text-blue-600 dark:text-blue-400 font-bold">Live v1.0</span>
</div> </div>
</div> </div>
</div> </div>
@@ -592,4 +592,3 @@ function toggleAdminGuide() {
</script> </script>
<?php require_once __DIR__ . '/includes/footer.php'; ?> <?php require_once __DIR__ . '/includes/footer.php'; ?>
+48
View File
@@ -0,0 +1,48 @@
<?php
/**
* Fociz Thema API Endpoint (Dark / Light / System)
*/
header('Content-Type: application/json; charset=utf-8');
require_once __DIR__ . '/../includes/auth.php';
$user = require_auth(true);
$userId = (int)$user['id'];
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$currentTheme = get_user_theme($userId);
echo json_encode([
'success' => true,
'theme' => $currentTheme,
]);
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$raw = file_get_contents('php://input');
$data = json_decode($raw, true);
$theme = $data['theme'] ?? ($_POST['theme'] ?? 'dark');
if (!in_array($theme, ['dark', 'light', 'system'])) {
http_response_code(400);
echo json_encode(['success' => false, 'error' => 'Ongeldig thema. Kies dark, light of system.']);
exit;
}
$ok = update_user_theme($userId, $theme);
if ($ok) {
echo json_encode([
'success' => true,
'theme' => $theme,
'message' => 'Themavoorkeur succesvol opgeslagen.',
]);
} else {
http_response_code(500);
echo json_encode(['success' => false, 'error' => 'Kon thema niet opslaan in database.']);
}
exit;
}
http_response_code(405);
echo json_encode(['success' => false, 'error' => 'Method not allowed']);
+68 -30
View File
@@ -59,23 +59,28 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// STAP 2: 2FA TOTP Code verificatie // STAP 2: 2FA TOTP Code verificatie
elseif ($step === 2) { elseif ($step === 2) {
$userId = $_SESSION['pending_2fa_user_id'] ?? null; $userId = $_SESSION['pending_2fa_user_id'] ?? null;
$totpCode = trim(str_replace(' ', '', $_POST['totp_code'] ?? '')); $totpCode = trim($_POST['totp_code'] ?? '');
if (!$userId || empty($totpCode)) { if (!$userId) {
$error = "Vul de 6-cijferige 2FA verificatiecode in."; header('Location: /auth/login.php');
exit;
}
if (empty($totpCode)) {
$error = "Vul de 6-cijferige 2FA code in uit uw authenticator app.";
} else { } else {
$stmt = $db->prepare("SELECT id, name, email, role, two_factor_secret, backup_codes FROM users WHERE id = ?"); $stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$userId]); $stmt->execute([$userId]);
$user = $stmt->fetch(); $user = $stmt->fetch();
$isValid = false; $isValid = false;
// 1. Controleer TOTP code // Controleer reguliere TOTP code
if (!empty($user['two_factor_secret']) && TOTP::verifyCode($user['two_factor_secret'], $totpCode)) { if (!empty($user['two_factor_secret'])) {
$isValid = true; $isValid = verify_totp($user['two_factor_secret'], $totpCode);
} }
// 2. Controleer optioneel backup codes // Fallback: controleer 8-karakter backup codes
if (!$isValid && !empty($user['backup_codes'])) { if (!$isValid && !empty($user['backup_codes'])) {
$backupCodes = json_decode($user['backup_codes'], true) ?: []; $backupCodes = json_decode($user['backup_codes'], true) ?: [];
$codeUpper = strtoupper($totpCode); $codeUpper = strtoupper($totpCode);
@@ -119,28 +124,62 @@ $pageTitle = "Fociz — Inloggen";
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= htmlspecialchars($pageTitle) ?></title> <title><?= htmlspecialchars($pageTitle) ?></title>
<!-- Anti-flicker script: Laad direct het gekozen thema uit localStorage vóór DOM render -->
<script>
(function() {
var activeTheme = localStorage.getItem('fociz_theme') || 'dark';
var isDark = true;
if (activeTheme === 'dark') isDark = true;
else if (activeTheme === 'light') isDark = false;
else if (activeTheme === 'system') {
isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
}
if (isDark) document.documentElement.classList.add('dark');
else document.documentElement.classList.remove('dark');
})();
</script>
<script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
colors: {
slate: {
850: '#151f32',
950: '#070b12',
}
}
}
}
}
</script>
<script src="https://unpkg.com/lucide@latest"></script> <script src="https://unpkg.com/lucide@latest"></script>
<style>body { background-color: #090d16; color: #f1f5f9; }</style> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<style>
body { font-family: 'Plus Jakarta Sans', sans-serif; }
</style>
</head> </head>
<body class="min-h-screen flex items-center justify-center p-4 bg-gradient-to-br from-[#090d16] via-[#0f172a] to-[#090d16]"> <body class="min-h-screen flex items-center justify-center p-4 bg-slate-50 dark:bg-gradient-to-br dark:from-[#090d16] dark:via-[#0f172a] dark:to-[#090d16] text-slate-900 dark:text-slate-100 transition-colors">
<?php require_once __DIR__ . '/../includes/env_badge.php'; ?> <?php require_once __DIR__ . '/../includes/env_badge.php'; ?>
<div class="w-full max-w-md bg-slate-900/90 border border-slate-800 rounded-2xl shadow-2xl backdrop-blur-xl p-8"> <div class="w-full max-w-md bg-white dark:bg-slate-900/90 border border-slate-200 dark:border-slate-800 rounded-3xl shadow-xl dark:shadow-2xl backdrop-blur-xl p-8 transition">
<!-- Header --> <!-- Header -->
<div class="text-center mb-8"> <div class="text-center mb-8">
<div class="inline-flex items-center justify-center w-14 h-14 rounded-2xl bg-emerald-500/10 border border-emerald-500/30 text-emerald-400 mb-3 shadow-lg shadow-emerald-500/10"> <div class="inline-flex items-center justify-center w-14 h-14 rounded-2xl bg-emerald-500/10 border border-emerald-500/30 text-emerald-600 dark:text-emerald-400 mb-3 shadow-lg shadow-emerald-500/10">
<i data-lucide="shield-check" class="w-8 h-8"></i> <i data-lucide="shield-check" class="w-8 h-8"></i>
</div> </div>
<h1 class="text-3xl font-extrabold tracking-tight text-white">Fociz</h1> <h1 class="text-3xl font-extrabold tracking-tight text-slate-900 dark:text-white">Fociz</h1>
<p class="text-slate-400 text-sm mt-1"> <p class="text-slate-500 dark:text-slate-400 text-sm mt-1">
Veilig inloggen met tweestapsverificatie (2FA) Veilig inloggen met tweestapsverificatie (2FA)
</p> </p>
</div> </div>
<?php if ($error): ?> <?php if ($error): ?>
<div class="mb-6 p-4 rounded-xl bg-red-500/10 border border-red-500/30 flex items-start space-x-3 text-red-400 text-sm"> <div class="mb-6 p-4 rounded-2xl bg-red-500/10 border border-red-500/30 flex items-start space-x-3 text-red-700 dark:text-red-400 text-sm">
<i data-lucide="alert-triangle" class="w-5 h-5 flex-shrink-0 mt-0.5"></i> <i data-lucide="alert-triangle" class="w-5 h-5 flex-shrink-0 mt-0.5"></i>
<span><?= htmlspecialchars($error) ?></span> <span><?= htmlspecialchars($error) ?></span>
</div> </div>
@@ -150,20 +189,20 @@ $pageTitle = "Fociz — Inloggen";
<!-- STAP 1: E-mail & Wachtwoord --> <!-- STAP 1: E-mail & Wachtwoord -->
<form method="POST" action="/auth/login.php" class="space-y-4"> <form method="POST" action="/auth/login.php" class="space-y-4">
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">E-mailadres</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">E-mailadres</label>
<div class="relative"> <div class="relative">
<input type="email" name="email" required autofocus placeholder="uw.naam@bedrijf.nl" value="<?= htmlspecialchars($_POST['email'] ?? '') ?>" class="w-full bg-slate-800/80 border border-slate-700 rounded-xl px-4 py-2.5 text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-emerald-500/50 text-sm transition"> <input type="email" name="email" required autofocus placeholder="uw.naam@bedrijf.nl" value="<?= htmlspecialchars($_POST['email'] ?? '') ?>" class="w-full bg-slate-50 dark:bg-slate-800/80 border border-slate-300 dark:border-slate-700 rounded-xl px-4 py-2.5 text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-emerald-500/50 text-sm transition">
</div> </div>
</div> </div>
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Wachtwoord</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Wachtwoord</label>
<div class="relative"> <div class="relative">
<input type="password" name="password" required placeholder="••••••••" class="w-full bg-slate-800/80 border border-slate-700 rounded-xl px-4 py-2.5 text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-emerald-500/50 text-sm transition"> <input type="password" name="password" required placeholder="••••••••" class="w-full bg-slate-50 dark:bg-slate-800/80 border border-slate-300 dark:border-slate-700 rounded-xl px-4 py-2.5 text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-emerald-500/50 text-sm transition">
</div> </div>
</div> </div>
<button type="submit" class="w-full mt-4 bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold py-3 px-4 rounded-xl transition shadow-lg shadow-emerald-500/20 flex items-center justify-center space-x-2"> <button type="submit" class="w-full mt-4 bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold py-3 px-4 rounded-xl transition shadow-lg shadow-emerald-500/20 flex items-center justify-center space-x-2 cursor-pointer">
<span>Verder naar 2FA</span> <span>Verder naar 2FA</span>
<i data-lucide="arrow-right" class="w-4 h-4"></i> <i data-lucide="arrow-right" class="w-4 h-4"></i>
</button> </button>
@@ -174,29 +213,29 @@ $pageTitle = "Fociz — Inloggen";
<!-- STAP 2: 2FA TOTP Code --> <!-- STAP 2: 2FA TOTP Code -->
<form method="POST" action="/auth/login.php" class="space-y-5"> <form method="POST" action="/auth/login.php" class="space-y-5">
<div class="text-center"> <div class="text-center">
<div class="inline-flex items-center justify-center w-12 h-12 rounded-xl bg-emerald-500/10 text-emerald-400 mb-2"> <div class="inline-flex items-center justify-center w-12 h-12 rounded-2xl bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 mb-2">
<i data-lucide="key" class="w-6 h-6"></i> <i data-lucide="key" class="w-6 h-6"></i>
</div> </div>
<p className="text-sm text-slate-300 font-medium"> <p class="text-sm text-slate-800 dark:text-slate-300 font-semibold">
Voer uw 6-cijferige verificatiecode in Voer uw 6-cijferige verificatiecode in
</p> </p>
<p class="text-xs text-slate-400 mt-1"> <p class="text-xs text-slate-500 dark:text-slate-400 mt-1">
Gekoppeld aan <strong class="text-slate-200"><?= htmlspecialchars($_SESSION['pending_2fa_user_email'] ?? '') ?></strong> Gekoppeld aan <strong class="text-slate-900 dark:text-slate-200"><?= htmlspecialchars($_SESSION['pending_2fa_user_email'] ?? '') ?></strong>
</p> </p>
</div> </div>
<div> <div>
<input type="text" name="totp_code" required autofocus maxlength="9" placeholder="000 000" class="w-full text-center tracking-[0.4em] font-mono text-2xl bg-slate-800/80 border border-slate-700 rounded-xl py-3 text-white placeholder-slate-600 focus:outline-none focus:ring-2 focus:ring-emerald-500/50 transition"> <input type="text" name="totp_code" required autofocus maxlength="9" placeholder="000 000" class="w-full text-center tracking-[0.4em] font-mono text-2xl bg-slate-50 dark:bg-slate-800/80 border border-slate-300 dark:border-slate-700 rounded-xl py-3 text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-600 focus:outline-none focus:ring-2 focus:ring-emerald-500/50 transition">
<span class="text-[11px] text-slate-500 text-center block mt-1"> <span class="text-[11px] text-slate-500 dark:text-slate-500 text-center block mt-1">
Tip: U kunt ook een 8-cijferige herstelcode invoeren. Tip: U kunt ook een 8-cijferige herstelcode invoeren.
</span> </span>
</div> </div>
<div class="flex space-x-3"> <div class="flex space-x-3">
<a href="/auth/login.php?action=restart" class="w-1/3 text-center bg-slate-800 hover:bg-slate-700 text-slate-300 font-medium py-2.5 px-3 rounded-xl transition text-sm flex items-center justify-center"> <a href="/auth/login.php?action=restart" class="w-1/3 text-center bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-300 font-medium py-2.5 px-3 rounded-xl transition text-sm flex items-center justify-center cursor-pointer">
Terug Terug
</a> </a>
<button type="submit" class="w-2/3 bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold py-2.5 px-4 rounded-xl transition shadow-lg shadow-emerald-500/20 flex items-center justify-center space-x-2"> <button type="submit" class="w-2/3 bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold py-2.5 px-4 rounded-xl transition shadow-lg shadow-emerald-500/20 flex items-center justify-center space-x-2 cursor-pointer">
<span>Inloggen</span> <span>Inloggen</span>
<i data-lucide="check-circle-2" class="w-4 h-4"></i> <i data-lucide="check-circle-2" class="w-4 h-4"></i>
</button> </button>
@@ -205,7 +244,7 @@ $pageTitle = "Fociz — Inloggen";
<?php endif; ?> <?php endif; ?>
<div class="mt-8 pt-6 border-t border-slate-800/80 text-center text-xs text-slate-500"> <div class="mt-8 pt-6 border-t border-slate-100 dark:border-slate-800/80 text-center text-xs text-slate-500">
Toegang tot Fociz is strikt op uitnodiging. Vraag uw beheerder om een uitnodigingslink. Toegang tot Fociz is strikt op uitnodiging. Vraag uw beheerder om een uitnodigingslink.
</div> </div>
</div> </div>
@@ -215,4 +254,3 @@ $pageTitle = "Fociz — Inloggen";
</script> </script>
</body> </body>
</html> </html>
+32 -33
View File
@@ -40,30 +40,30 @@ $sessions = $stmtSessions->fetchAll();
require_once __DIR__ . '/includes/header.php'; require_once __DIR__ . '/includes/header.php';
?> ?>
<div class="space-y-6"> <div class="space-y-6 max-w-7xl mx-auto">
<!-- Header --> <!-- Header -->
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 bg-slate-900/80 border border-slate-800 rounded-2xl p-6 shadow-xl"> <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 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 transition">
<div> <div>
<div class="flex items-center space-x-2 text-amber-400 text-xs font-semibold uppercase tracking-wider mb-1"> <div class="flex items-center space-x-2 text-amber-600 dark:text-amber-400 text-xs font-bold uppercase tracking-wider mb-1">
<i data-lucide="lightbulb" class="w-4 h-4"></i> <i data-lucide="lightbulb" class="w-4 h-4"></i>
<span>Creatie & Innovatie</span> <span>Creatie & Innovatie</span>
</div> </div>
<h1 class="text-2xl sm:text-3xl font-black text-white tracking-tight"> <h1 class="text-2xl sm:text-3xl font-black text-slate-900 dark:text-white tracking-tight">
Brainstorm Sessies Brainstorm Sessies
</h1> </h1>
<p class="text-slate-400 text-xs sm:text-sm mt-1"> <p class="text-slate-500 dark:text-slate-400 text-xs sm:text-sm mt-1">
Brainstorm met collega's, verzamel ideeën en knelpunten, en transformeer ze direct tot een werkbare roadmap. Brainstorm met collega's, verzamel ideeën en knelpunten, en transformeer ze direct tot een werkbare roadmap.
</p> </p>
</div> </div>
<button onclick="document.getElementById('newSessionModal').classList.remove('hidden')" class="flex items-center space-x-2 px-4 py-2.5 rounded-xl bg-amber-500 hover:bg-amber-600 text-slate-950 text-xs font-bold transition shadow-lg shadow-amber-500/20 flex-shrink-0"> <button onclick="document.getElementById('newSessionModal').classList.remove('hidden')" class="flex items-center space-x-2 px-4 py-2.5 rounded-xl bg-amber-500 hover:bg-amber-600 text-slate-950 text-xs font-bold transition shadow-lg shadow-amber-500/20 flex-shrink-0 cursor-pointer">
<i data-lucide="plus" class="w-4 h-4"></i> <i data-lucide="plus" class="w-4 h-4"></i>
<span>Nieuwe Sessie Starten</span> <span>Nieuwe Sessie Starten</span>
</button> </button>
</div> </div>
<?php if ($error): ?> <?php if ($error): ?>
<div class="p-4 rounded-xl bg-red-500/10 border border-red-500/30 text-red-400 text-sm"> <div class="p-4 rounded-2xl bg-red-500/10 border border-red-500/30 text-red-700 dark:text-red-400 text-sm">
<?= htmlspecialchars($error) ?> <?= htmlspecialchars($error) ?>
</div> </div>
<?php endif; ?> <?php endif; ?>
@@ -71,44 +71,44 @@ require_once __DIR__ . '/includes/header.php';
<!-- Grid met sessies --> <!-- Grid met sessies -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5"> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5">
<?php if (empty($sessions)): ?> <?php if (empty($sessions)): ?>
<div class="col-span-full bg-slate-900/60 border border-slate-800/80 rounded-2xl p-12 text-center"> <div class="col-span-full bg-white dark:bg-slate-900/60 border border-slate-200 dark:border-slate-800/80 rounded-3xl p-12 text-center shadow-sm">
<i data-lucide="lightbulb" class="w-12 h-12 text-amber-500/40 mx-auto mb-3"></i> <i data-lucide="lightbulb" class="w-12 h-12 text-amber-500/40 mx-auto mb-3"></i>
<h3 class="text-base font-bold text-white">Nog geen brainstormsessies gestart</h3> <h3 class="text-base font-bold text-slate-900 dark:text-white">Nog geen brainstormsessies gestart</h3>
<p class="text-xs text-slate-400 mt-1 max-w-sm mx-auto"> <p class="text-xs text-slate-500 dark:text-slate-400 mt-1 max-w-sm mx-auto">
Start uw eerste brainstormsessie om ideeën te verzamelen en ze met één klik om te vormen naar planningsitems. Start uw eerste brainstormsessie om ideeën te verzamelen en ze met één klik om te vormen naar planningsitems.
</p> </p>
<button onclick="document.getElementById('newSessionModal').classList.remove('hidden')" class="mt-4 px-4 py-2 bg-amber-500 hover:bg-amber-600 text-slate-950 font-bold rounded-xl text-xs transition"> <button onclick="document.getElementById('newSessionModal').classList.remove('hidden')" class="mt-4 px-4 py-2 bg-amber-500 hover:bg-amber-600 text-slate-950 font-bold rounded-xl text-xs transition cursor-pointer">
Sessie Starten Sessie Starten
</button> </button>
</div> </div>
<?php else: ?> <?php else: ?>
<?php foreach ($sessions as $sess): ?> <?php foreach ($sessions as $sess): ?>
<a href="/brainstorm_canvas.php?id=<?= $sess['id'] ?>" class="group bg-slate-900/80 hover:bg-slate-850 border border-slate-800 hover:border-amber-500/40 rounded-2xl p-5 shadow-lg transition flex flex-col justify-between"> <a href="/brainstorm_canvas.php?id=<?= $sess['id'] ?>" class="group bg-white hover:bg-slate-50 dark:bg-slate-900/80 dark:hover:bg-slate-850 border border-slate-200 hover:border-amber-500/50 dark:border-slate-800 dark:hover:border-amber-500/40 rounded-3xl p-5 shadow-sm hover:shadow-md dark:shadow-lg transition flex flex-col justify-between">
<div> <div>
<div class="flex items-center justify-between mb-3"> <div class="flex items-center justify-between mb-3">
<span class="px-2.5 py-0.5 rounded-full bg-amber-500/10 border border-amber-500/20 text-amber-400 font-semibold text-[11px]"> <span class="px-2.5 py-0.5 rounded-full bg-amber-500/15 border border-amber-500/30 text-amber-700 dark:text-amber-400 font-bold text-[11px]">
<?= htmlspecialchars($sess['theme']) ?> <?= htmlspecialchars($sess['theme']) ?>
</span> </span>
<span class="flex items-center space-x-1 text-slate-500 text-xs"> <span class="flex items-center space-x-1 text-slate-500 dark:text-slate-400 text-xs">
<i data-lucide="message-square" class="w-3.5 h-3.5"></i> <i data-lucide="message-square" class="w-3.5 h-3.5"></i>
<span><?= $sess['cards_count'] ?> kaarten</span> <span><?= $sess['cards_count'] ?> kaarten</span>
</span> </span>
</div> </div>
<h3 class="text-base font-bold text-white group-hover:text-amber-400 transition leading-snug"> <h3 class="text-base font-bold text-slate-900 dark:text-white group-hover:text-amber-600 dark:group-hover:text-amber-400 transition leading-snug">
<?= htmlspecialchars($sess['title']) ?> <?= htmlspecialchars($sess['title']) ?>
</h3> </h3>
<?php if (!empty($sess['description'])): ?> <?php if (!empty($sess['description'])): ?>
<p class="text-slate-400 text-xs mt-2 line-clamp-2"> <p class="text-slate-600 dark:text-slate-400 text-xs mt-2 line-clamp-2 leading-relaxed">
<?= htmlspecialchars($sess['description']) ?> <?= htmlspecialchars($sess['description']) ?>
</p> </p>
<?php endif; ?> <?php endif; ?>
</div> </div>
<div class="mt-5 pt-4 border-t border-slate-800/80 flex items-center justify-between text-xs text-slate-500"> <div class="mt-5 pt-4 border-t border-slate-100 dark:border-slate-800/80 flex items-center justify-between text-xs text-slate-500 dark:text-slate-400">
<span>Door <?= htmlspecialchars($sess['creator_name']) ?></span> <span>Door <?= htmlspecialchars($sess['creator_name']) ?></span>
<div class="flex items-center space-x-1 text-amber-400 group-hover:translate-x-1 transition font-medium"> <div class="flex items-center space-x-1 text-amber-600 dark:text-amber-400 group-hover:translate-x-1 transition font-semibold">
<span>Open canvas</span> <span>Open canvas</span>
<i data-lucide="arrow-right" class="w-3.5 h-3.5"></i> <i data-lucide="arrow-right" class="w-3.5 h-3.5"></i>
</div> </div>
@@ -120,14 +120,14 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
<!-- Modal: Nieuwe sessie --> <!-- Modal: Nieuwe sessie -->
<div id="newSessionModal" class="hidden fixed inset-0 z-50 bg-black/70 backdrop-blur-sm flex items-center justify-center p-4"> <div id="newSessionModal" class="hidden fixed inset-0 z-50 bg-black/60 dark:bg-black/70 backdrop-blur-sm flex items-center justify-center p-4">
<div class="bg-slate-900 border border-slate-800 rounded-2xl p-6 shadow-2xl max-w-lg w-full"> <div class="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-3xl p-6 sm:p-7 shadow-2xl max-w-lg w-full transition">
<div class="flex items-center justify-between mb-4 pb-3 border-b border-slate-800"> <div class="flex items-center justify-between mb-4 pb-3 border-b border-slate-100 dark:border-slate-800">
<h3 class="text-base font-bold text-white flex items-center space-x-2"> <h3 class="text-base font-bold text-slate-900 dark:text-white flex items-center space-x-2">
<i data-lucide="sparkles" class="w-4 h-4 text-amber-400"></i> <i data-lucide="sparkles" class="w-4 h-4 text-amber-500"></i>
<span>Nieuwe Brainstormsessie</span> <span>Nieuwe Brainstormsessie</span>
</h3> </h3>
<button onclick="document.getElementById('newSessionModal').classList.add('hidden')" class="text-slate-400 hover:text-white"> <button onclick="document.getElementById('newSessionModal').classList.add('hidden')" class="text-slate-400 hover:text-slate-600 dark:hover:text-white cursor-pointer">
<i data-lucide="x" class="w-5 h-5"></i> <i data-lucide="x" class="w-5 h-5"></i>
</button> </button>
</div> </div>
@@ -136,14 +136,14 @@ require_once __DIR__ . '/includes/header.php';
<input type="hidden" name="action" value="create_session"> <input type="hidden" name="action" value="create_session">
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Onderwerp / Titel</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Onderwerp / Titel</label>
<input type="text" name="title" required placeholder="Bijv. Q4 Automatisering & Klantreis" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2 text-white text-xs placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-amber-500/50"> <input type="text" name="title" required placeholder="Bijv. Q4 Automatisering & Klantreis" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3.5 py-2.5 text-slate-900 dark:text-white text-xs placeholder-slate-400 dark:placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-amber-500/50">
</div> </div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Thema / Categorie</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Thema / Categorie</label>
<select name="theme" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white text-xs focus:outline-none"> <select name="theme" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3 py-2 text-slate-900 dark:text-white text-xs focus:outline-none">
<option value="Product & Strategie">Product & Strategie</option> <option value="Product & Strategie">Product & Strategie</option>
<option value="Procesverbetering">Procesverbetering</option> <option value="Procesverbetering">Procesverbetering</option>
<option value="Klant & Service">Klant & Service</option> <option value="Klant & Service">Klant & Service</option>
@@ -152,16 +152,16 @@ require_once __DIR__ . '/includes/header.php';
</select> </select>
</div> </div>
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Doel / Beschrijving</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Doel / Beschrijving</label>
<input type="text" name="description" placeholder="Doel van deze sessie..." class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2 text-white text-xs placeholder-slate-500 focus:outline-none"> <input type="text" name="description" placeholder="Doel van deze sessie..." class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3.5 py-2 text-slate-900 dark:text-white text-xs placeholder-slate-400 dark:placeholder-slate-500 focus:outline-none">
</div> </div>
</div> </div>
<div class="flex space-x-2 pt-2"> <div class="flex space-x-2 pt-2">
<button type="submit" class="flex-1 bg-amber-500 hover:bg-amber-600 text-slate-950 font-bold py-2.5 px-4 rounded-xl text-xs transition"> <button type="submit" class="flex-1 bg-amber-500 hover:bg-amber-600 text-slate-950 font-bold py-2.5 px-4 rounded-xl text-xs transition cursor-pointer">
Sessie Aanmaken & Canvas Openen Sessie Aanmaken & Canvas Openen
</button> </button>
<button type="button" onclick="document.getElementById('newSessionModal').classList.add('hidden')" class="px-4 py-2.5 bg-slate-800 hover:bg-slate-700 text-slate-300 rounded-xl text-xs transition"> <button type="button" onclick="document.getElementById('newSessionModal').classList.add('hidden')" class="px-4 py-2.5 bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-300 rounded-xl text-xs transition cursor-pointer">
Annuleren Annuleren
</button> </button>
</div> </div>
@@ -170,4 +170,3 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
<?php require_once __DIR__ . '/includes/footer.php'; ?> <?php require_once __DIR__ . '/includes/footer.php'; ?>
+86 -59
View File
@@ -17,7 +17,7 @@ $stmtSession->execute([$sessionId]);
$session = $stmtSession->fetch(); $session = $stmtSession->fetch();
if (!$session) { if (!$session) {
echo "<div class='p-8 text-center text-red-400'>Brainstormsessie niet gevonden. <a href='/brainstorm.php' class='underline'>Terug</a></div>"; echo "<div class='p-8 text-center text-red-500'>Brainstormsessie niet gevonden. <a href='/brainstorm.php' class='underline'>Terug</a></div>";
require_once __DIR__ . '/includes/footer.php'; require_once __DIR__ . '/includes/footer.php';
exit; exit;
} }
@@ -32,41 +32,69 @@ $stmtCards->execute([$sessionId]);
$cards = $stmtCards->fetchAll(); $cards = $stmtCards->fetchAll();
$categories = [ $categories = [
'Ideeën' => ['title' => 'Ideeën & Concepten', 'icon' => 'lightbulb', 'color' => 'amber', 'border' => 'border-amber-500/40', 'bg' => 'bg-amber-950/20', 'badge' => 'bg-amber-500/20 text-amber-300'], 'Ideeën' => [
'Knelpunten' => ['title' => 'Knelpunten & Uitdagingen', 'icon' => 'alert-triangle', 'color' => 'rose', 'border' => 'border-rose-500/40', 'bg' => 'bg-rose-950/20', 'badge' => 'bg-rose-500/20 text-rose-300'], 'title' => 'Ideeën & Concepten',
'Oplossingen' => ['title' => 'Oplossingen & Features', 'icon' => 'rocket', 'color' => 'emerald', 'border' => 'border-emerald-500/40', 'bg' => 'bg-emerald-950/20', 'badge' => 'bg-emerald-500/20 text-emerald-300'], 'icon' => 'lightbulb',
'Quick Wins' => ['title' => 'Quick Wins (Direct te doen)', 'icon' => 'zap', 'color' => 'blue', 'border' => 'border-blue-500/40', 'bg' => 'bg-blue-950/20', 'badge' => 'bg-blue-500/20 text-blue-300'], 'color' => 'amber',
'border' => 'border-amber-200 dark:border-amber-500/40',
'bg' => 'bg-amber-50/60 dark:bg-amber-950/20',
'badge' => 'bg-amber-500/15 text-amber-800 dark:text-amber-300'
],
'Knelpunten' => [
'title' => 'Knelpunten & Uitdagingen',
'icon' => 'alert-triangle',
'color' => 'rose',
'border' => 'border-rose-200 dark:border-rose-500/40',
'bg' => 'bg-rose-50/60 dark:bg-rose-950/20',
'badge' => 'bg-rose-500/15 text-rose-800 dark:text-rose-300'
],
'Oplossingen' => [
'title' => 'Oplossingen & Features',
'icon' => 'rocket',
'color' => 'emerald',
'border' => 'border-emerald-200 dark:border-emerald-500/40',
'bg' => 'bg-emerald-50/60 dark:bg-emerald-950/20',
'badge' => 'bg-emerald-500/15 text-emerald-800 dark:text-emerald-300'
],
'Quick Wins' => [
'title' => 'Quick Wins (Direct te doen)',
'icon' => 'zap',
'color' => 'blue',
'border' => 'border-blue-200 dark:border-blue-500/40',
'bg' => 'bg-blue-50/60 dark:bg-blue-950/20',
'badge' => 'bg-blue-500/15 text-blue-800 dark:text-blue-300'
],
]; ];
?> ?>
<div class="space-y-6"> <div class="space-y-6 max-w-7xl mx-auto">
<!-- Top Bar --> <!-- Top Bar -->
<div class="flex flex-col lg:flex-row lg:items-center justify-between gap-4 bg-slate-900/90 border border-slate-800 rounded-2xl p-5 shadow-xl"> <div class="flex flex-col lg:flex-row lg:items-center justify-between gap-4 bg-white dark:bg-slate-900/90 border border-slate-200 dark:border-slate-800 rounded-3xl p-5 shadow-sm dark:shadow-xl transition">
<div class="flex items-center space-x-4"> <div class="flex items-center space-x-4">
<a href="/brainstorm.php" class="p-2 rounded-xl bg-slate-800 text-slate-400 hover:text-white transition"> <a href="/brainstorm.php" class="p-2.5 rounded-2xl bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white transition cursor-pointer">
<i data-lucide="arrow-left" class="w-5 h-5"></i> <i data-lucide="arrow-left" class="w-5 h-5"></i>
</a> </a>
<div> <div>
<div class="flex items-center space-x-2 text-xs"> <div class="flex items-center space-x-2 text-xs">
<span class="px-2 py-0.5 rounded bg-amber-500/10 text-amber-400 font-semibold border border-amber-500/20"> <span class="px-2 py-0.5 rounded bg-amber-500/15 text-amber-700 dark:text-amber-400 font-bold border border-amber-500/20">
<?= htmlspecialchars($session['theme']) ?> <?= htmlspecialchars($session['theme']) ?>
</span> </span>
<span class="text-slate-500">Gestart door <?= htmlspecialchars($session['creator_name']) ?></span> <span class="text-slate-500 dark:text-slate-500">Gestart door <?= htmlspecialchars($session['creator_name']) ?></span>
</div> </div>
<h1 class="text-xl sm:text-2xl font-black text-white tracking-tight mt-0.5"> <h1 class="text-xl sm:text-2xl font-black text-slate-900 dark:text-white tracking-tight mt-0.5">
<?= htmlspecialchars($session['title']) ?> <?= htmlspecialchars($session['title']) ?>
</h1> </h1>
</div> </div>
</div> </div>
<div class="flex items-center space-x-3"> <div class="flex items-center space-x-3">
<button onclick="openAddCardModal()" class="flex items-center space-x-1.5 px-3.5 py-2 rounded-xl bg-slate-800 hover:bg-slate-700 text-slate-200 text-xs font-semibold border border-slate-700 transition"> <button onclick="openAddCardModal()" class="flex items-center space-x-1.5 px-3.5 py-2 rounded-xl bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-200 text-xs font-semibold border border-slate-200 dark:border-slate-700 transition cursor-pointer shadow-sm">
<i data-lucide="plus" class="w-4 h-4 text-amber-400"></i> <i data-lucide="plus" class="w-4 h-4 text-amber-500"></i>
<span>Nieuwe Kaart</span> <span>Nieuwe Kaart</span>
</button> </button>
<!-- De Kernfeature: Zet om naar Roadmap! --> <!-- De Kernfeature: Zet om naar Roadmap! -->
<button onclick="openConvertModal()" class="flex items-center space-x-2 px-4 py-2 rounded-xl bg-gradient-to-r from-emerald-500 to-teal-400 hover:from-emerald-600 hover:to-teal-500 text-slate-950 text-xs font-bold transition shadow-lg shadow-emerald-500/20"> <button onclick="openConvertModal()" class="flex items-center space-x-2 px-4 py-2 rounded-xl bg-gradient-to-r from-emerald-500 to-teal-400 hover:from-emerald-600 hover:to-teal-500 text-slate-950 text-xs font-bold transition shadow-lg shadow-emerald-500/20 cursor-pointer">
<i data-lucide="map" class="w-4 h-4"></i> <i data-lucide="map" class="w-4 h-4"></i>
<span>Zet om naar Roadmap</span> <span>Zet om naar Roadmap</span>
</button> </button>
@@ -78,14 +106,14 @@ $categories = [
<?php foreach ($categories as $catKey => $catConfig): <?php foreach ($categories as $catKey => $catConfig):
$catCards = array_filter($cards, fn($c) => $c['category'] === $catKey); $catCards = array_filter($cards, fn($c) => $c['category'] === $catKey);
?> ?>
<div class="bg-slate-900/60 border border-slate-800/80 rounded-2xl p-4 flex flex-col min-h-[500px]"> <div class="bg-white dark:bg-slate-900/60 border border-slate-200 dark:border-slate-800/80 rounded-3xl p-4 flex flex-col min-h-[500px] shadow-sm transition">
<!-- Column Header --> <!-- Column Header -->
<div class="flex items-center justify-between pb-3 mb-3 border-b border-slate-800"> <div class="flex items-center justify-between pb-3 mb-3 border-b border-slate-100 dark:border-slate-800">
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<i data-lucide="<?= $catConfig['icon'] ?>" class="w-4 h-4 text-<?= $catConfig['color'] ?>-400"></i> <i data-lucide="<?= $catConfig['icon'] ?>" class="w-4 h-4 text-<?= $catConfig['color'] ?>-500"></i>
<h3 class="text-xs font-bold text-white uppercase tracking-wider"><?= $catConfig['title'] ?></h3> <h3 class="text-xs font-bold text-slate-900 dark:text-white uppercase tracking-wider"><?= $catConfig['title'] ?></h3>
</div> </div>
<span class="text-xs font-mono font-semibold px-2 py-0.5 rounded-full bg-slate-800 text-slate-400"> <span class="text-xs font-mono font-bold px-2 py-0.5 rounded-full bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400">
<?= count($catCards) ?> <?= count($catCards) ?>
</span> </span>
</div> </div>
@@ -93,22 +121,22 @@ $categories = [
<!-- Cards Container --> <!-- Cards Container -->
<div class="flex-1 space-y-3"> <div class="flex-1 space-y-3">
<?php if (empty($catCards)): ?> <?php if (empty($catCards)): ?>
<div class="py-8 text-center text-slate-600 text-xs"> <div class="py-8 text-center text-slate-400 dark:text-slate-600 text-xs">
Nog geen kaarten in deze categorie. Nog geen kaarten in deze categorie.
</div> </div>
<?php else: ?> <?php else: ?>
<?php foreach ($catCards as $card): ?> <?php foreach ($catCards as $card): ?>
<div class="group relative rounded-xl p-4 border <?= $catConfig['border'] ?> <?= $catConfig['bg'] ?> backdrop-blur-sm shadow-md transition hover:-translate-y-0.5" id="card-<?= $card['id'] ?>"> <div class="group relative rounded-2xl p-4 border <?= $catConfig['border'] ?> <?= $catConfig['bg'] ?> backdrop-blur-sm shadow-sm transition hover:-translate-y-0.5" id="card-<?= $card['id'] ?>">
<!-- Top: Checkbox voor selectie + Roadmap badge --> <!-- Top: Checkbox voor selectie + Roadmap badge -->
<div class="flex items-center justify-between mb-2"> <div class="flex items-center justify-between mb-2">
<label class="flex items-center space-x-2 cursor-pointer"> <label class="flex items-center space-x-2 cursor-pointer">
<input type="checkbox" value="<?= $card['id'] ?>" class="card-checkbox w-4 h-4 rounded bg-slate-900 border-slate-700 text-emerald-500 focus:ring-0"> <input type="checkbox" value="<?= $card['id'] ?>" class="card-checkbox w-4 h-4 rounded bg-white dark:bg-slate-900 border-slate-300 dark:border-slate-700 text-emerald-600 focus:ring-0">
<span class="text-[10px] text-slate-400">Selecteer</span> <span class="text-[10px] text-slate-500 dark:text-slate-400">Selecteer</span>
</label> </label>
<?php if (!empty($card['converted_to_roadmap_item_id'])): ?> <?php if (!empty($card['converted_to_roadmap_item_id'])): ?>
<span class="px-2 py-0.5 rounded-full bg-emerald-500/20 text-emerald-300 font-semibold text-[10px] flex items-center space-x-1 border border-emerald-500/30"> <span class="px-2 py-0.5 rounded-full bg-emerald-500/20 text-emerald-800 dark:text-emerald-300 font-bold text-[10px] flex items-center space-x-1 border border-emerald-500/30">
<i data-lucide="check" class="w-3 h-3"></i> <i data-lucide="check" class="w-3 h-3"></i>
<span>Op Roadmap</span> <span>Op Roadmap</span>
</span> </span>
@@ -116,23 +144,23 @@ $categories = [
</div> </div>
<!-- Inhoud --> <!-- Inhoud -->
<p class="text-xs text-slate-200 leading-relaxed whitespace-pre-wrap"> <p class="text-xs text-slate-800 dark:text-slate-200 leading-relaxed whitespace-pre-wrap font-medium">
<?= htmlspecialchars($card['content']) ?> <?= htmlspecialchars($card['content']) ?>
</p> </p>
<!-- Footer van kaart --> <!-- Footer van kaart -->
<div class="mt-3 pt-2.5 border-t border-slate-800/60 flex items-center justify-between text-[10px] text-slate-400"> <div class="mt-3 pt-2.5 border-t border-slate-200/60 dark:border-slate-800/60 flex items-center justify-between text-[10px] text-slate-500 dark:text-slate-400">
<span><?= htmlspecialchars($card['author_name'] ?? 'Collega') ?></span> <span><?= htmlspecialchars($card['author_name'] ?? 'Collega') ?></span>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<!-- Upvote button --> <!-- Upvote button -->
<button onclick="voteCard(<?= $card['id'] ?>)" class="flex items-center space-x-1 px-2 py-1 rounded-lg bg-slate-800/80 hover:bg-slate-700 text-amber-300 transition"> <button onclick="voteCard(<?= $card['id'] ?>)" class="flex items-center space-x-1 px-2 py-1 rounded-lg bg-white hover:bg-slate-100 dark:bg-slate-800/80 dark:hover:bg-slate-700 text-amber-600 dark:text-amber-300 border border-slate-200 dark:border-transparent transition shadow-xs cursor-pointer">
<i data-lucide="thumbs-up" class="w-3 h-3"></i> <i data-lucide="thumbs-up" class="w-3 h-3"></i>
<span id="votes-<?= $card['id'] ?>" class="font-bold"><?= $card['votes'] ?></span> <span id="votes-<?= $card['id'] ?>" class="font-bold"><?= $card['votes'] ?></span>
</button> </button>
<!-- Delete button --> <!-- Delete button -->
<button onclick="deleteCard(<?= $card['id'] ?>)" class="p-1 rounded text-slate-500 hover:text-red-400 transition opacity-0 group-hover:opacity-100"> <button onclick="deleteCard(<?= $card['id'] ?>)" class="p-1 rounded text-slate-400 hover:text-red-600 dark:text-slate-500 dark:hover:text-red-400 transition opacity-0 group-hover:opacity-100 cursor-pointer">
<i data-lucide="trash-2" class="w-3.5 h-3.5"></i> <i data-lucide="trash-2" class="w-3.5 h-3.5"></i>
</button> </button>
</div> </div>
@@ -143,7 +171,7 @@ $categories = [
</div> </div>
<!-- Quick add button at column bottom --> <!-- Quick add button at column bottom -->
<button onclick="openAddCardModal('<?= $catKey ?>')" class="mt-3 w-full py-2 rounded-xl border border-dashed border-slate-800 hover:border-slate-700 text-slate-500 hover:text-slate-300 text-xs transition flex items-center justify-center space-x-1"> <button onclick="openAddCardModal('<?= $catKey ?>')" class="mt-3 w-full py-2 rounded-xl border border-dashed border-slate-300 dark:border-slate-800 hover:border-slate-400 dark:hover:border-slate-700 text-slate-500 hover:text-slate-800 dark:hover:text-slate-300 text-xs transition flex items-center justify-center space-x-1 cursor-pointer">
<i data-lucide="plus" class="w-3.5 h-3.5"></i> <i data-lucide="plus" class="w-3.5 h-3.5"></i>
<span>Kaart toevoegen</span> <span>Kaart toevoegen</span>
</button> </button>
@@ -153,22 +181,22 @@ $categories = [
</div> </div>
<!-- Modal: Nieuwe Kaart Toevoegen --> <!-- Modal: Nieuwe Kaart Toevoegen -->
<div id="addCardModal" class="hidden fixed inset-0 z-50 bg-black/70 backdrop-blur-sm flex items-center justify-center p-4"> <div id="addCardModal" class="hidden fixed inset-0 z-50 bg-black/60 dark:bg-black/70 backdrop-blur-sm flex items-center justify-center p-4">
<div class="bg-slate-900 border border-slate-800 rounded-2xl p-6 shadow-2xl max-w-md w-full"> <div class="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-3xl p-6 shadow-2xl max-w-md w-full transition">
<div class="flex items-center justify-between mb-4 pb-3 border-b border-slate-800"> <div class="flex items-center justify-between mb-4 pb-3 border-b border-slate-100 dark:border-slate-800">
<h3 class="text-base font-bold text-white flex items-center space-x-2"> <h3 class="text-base font-bold text-slate-900 dark:text-white flex items-center space-x-2">
<i data-lucide="sticky-note" class="w-4 h-4 text-amber-400"></i> <i data-lucide="sticky-note" class="w-4 h-4 text-amber-500"></i>
<span>Brainstormkaart Toevoegen</span> <span>Brainstormkaart Toevoegen</span>
</h3> </h3>
<button onclick="closeAddCardModal()" class="text-slate-400 hover:text-white"> <button onclick="closeAddCardModal()" class="text-slate-400 hover:text-slate-600 dark:hover:text-white cursor-pointer">
<i data-lucide="x" class="w-5 h-5"></i> <i data-lucide="x" class="w-5 h-5"></i>
</button> </button>
</div> </div>
<div class="space-y-4"> <div class="space-y-4">
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Categorie</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Categorie</label>
<select id="modalCardCategory" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white text-xs focus:outline-none"> <select id="modalCardCategory" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3 py-2 text-slate-900 dark:text-white text-xs focus:outline-none">
<option value="Ideeën">💡 Ideeën & Concepten</option> <option value="Ideeën">💡 Ideeën & Concepten</option>
<option value="Knelpunten">⚠️ Knelpunten & Uitdagingen</option> <option value="Knelpunten">⚠️ Knelpunten & Uitdagingen</option>
<option value="Oplossingen">🚀 Oplossingen & Features</option> <option value="Oplossingen">🚀 Oplossingen & Features</option>
@@ -177,15 +205,15 @@ $categories = [
</div> </div>
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Idee / Beschrijving</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Idee / Beschrijving</label>
<textarea id="modalCardContent" rows="4" placeholder="Schrijf hier uw inzicht, idee of knelpunt..." class="w-full bg-slate-950 border border-slate-800 rounded-xl p-3 text-white text-xs placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-amber-500 resize-none"></textarea> <textarea id="modalCardContent" rows="4" placeholder="Schrijf hier uw inzicht, idee of knelpunt..." class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl p-3 text-slate-900 dark:text-white text-xs placeholder-slate-400 dark:placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-amber-500 resize-none"></textarea>
</div> </div>
<div class="flex space-x-2 pt-2"> <div class="flex space-x-2 pt-2">
<button onclick="submitNewCard()" class="flex-1 bg-amber-500 hover:bg-amber-600 text-slate-950 font-bold py-2.5 px-4 rounded-xl text-xs transition"> <button onclick="submitNewCard()" class="flex-1 bg-amber-500 hover:bg-amber-600 text-slate-950 font-bold py-2.5 px-4 rounded-xl text-xs transition cursor-pointer">
Plaats op Canvas Plaats op Canvas
</button> </button>
<button onclick="closeAddCardModal()" class="px-4 py-2.5 bg-slate-800 hover:bg-slate-700 text-slate-300 rounded-xl text-xs transition"> <button onclick="closeAddCardModal()" class="px-4 py-2.5 bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-300 rounded-xl text-xs transition cursor-pointer">
Annuleren Annuleren
</button> </button>
</div> </div>
@@ -194,27 +222,27 @@ $categories = [
</div> </div>
<!-- Modal: Zet om naar Roadmap --> <!-- Modal: Zet om naar Roadmap -->
<div id="convertModal" class="hidden fixed inset-0 z-50 bg-black/70 backdrop-blur-sm flex items-center justify-center p-4"> <div id="convertModal" class="hidden fixed inset-0 z-50 bg-black/60 dark:bg-black/70 backdrop-blur-sm flex items-center justify-center p-4">
<div class="bg-slate-900 border border-emerald-500/40 rounded-2xl p-6 shadow-2xl max-w-lg w-full"> <div class="bg-white dark:bg-slate-900 border border-emerald-500/40 rounded-3xl p-6 shadow-2xl max-w-lg w-full transition">
<div class="flex items-center justify-between mb-4 pb-3 border-b border-slate-800"> <div class="flex items-center justify-between mb-4 pb-3 border-b border-slate-100 dark:border-slate-800">
<h3 class="text-base font-bold text-white flex items-center space-x-2"> <h3 class="text-base font-bold text-slate-900 dark:text-white flex items-center space-x-2">
<i data-lucide="map" class="w-4 h-4 text-emerald-400"></i> <i data-lucide="map" class="w-4 h-4 text-emerald-600 dark:text-emerald-400"></i>
<span>Zet Brainstorm om naar Roadmap</span> <span>Zet Brainstorm om naar Roadmap</span>
</h3> </h3>
<button onclick="closeConvertModal()" class="text-slate-400 hover:text-white"> <button onclick="closeConvertModal()" class="text-slate-400 hover:text-slate-600 dark:hover:text-white cursor-pointer">
<i data-lucide="x" class="w-5 h-5"></i> <i data-lucide="x" class="w-5 h-5"></i>
</button> </button>
</div> </div>
<div class="space-y-4"> <div class="space-y-4">
<div class="bg-emerald-950/30 border border-emerald-500/20 rounded-xl p-3 text-xs text-emerald-300"> <div class="bg-emerald-50 dark:bg-emerald-950/30 border border-emerald-200 dark:border-emerald-500/20 rounded-2xl p-3 text-xs text-emerald-800 dark:text-emerald-300">
<span id="selectedCountText" class="font-bold">0</span> kaarten geselecteerd om om te zetten naar planbare roadmap items. <span id="selectedCountText" class="font-bold">0</span> kaarten geselecteerd om om te zetten naar planbare roadmap items.
</div> </div>
<div class="grid grid-cols-2 gap-3"> <div class="grid grid-cols-2 gap-3">
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Doel Kwartaal</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Doel Kwartaal</label>
<select id="roadmapQuarter" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white text-xs focus:outline-none"> <select id="roadmapQuarter" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3 py-2 text-slate-900 dark:text-white text-xs focus:outline-none">
<option value="Q1">Q1 (Jan - Mrt)</option> <option value="Q1">Q1 (Jan - Mrt)</option>
<option value="Q2">Q2 (Apr - Jun)</option> <option value="Q2">Q2 (Apr - Jun)</option>
<option value="Q3" selected>Q3 (Jul - Sep)</option> <option value="Q3" selected>Q3 (Jul - Sep)</option>
@@ -223,8 +251,8 @@ $categories = [
</div> </div>
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Item Type</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Item Type</label>
<select id="roadmapType" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white text-xs focus:outline-none"> <select id="roadmapType" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3 py-2 text-slate-900 dark:text-white text-xs focus:outline-none">
<option value="FEATURE" selected>Feature / Functionaliteit</option> <option value="FEATURE" selected>Feature / Functionaliteit</option>
<option value="EPIC">Epic (Groot project)</option> <option value="EPIC">Epic (Groot project)</option>
<option value="MILESTONE">Mijlpaal</option> <option value="MILESTONE">Mijlpaal</option>
@@ -235,8 +263,8 @@ $categories = [
<div class="grid grid-cols-2 gap-3"> <div class="grid grid-cols-2 gap-3">
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Prioriteit</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Prioriteit</label>
<select id="roadmapPriority" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white text-xs focus:outline-none"> <select id="roadmapPriority" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3 py-2 text-slate-900 dark:text-white text-xs focus:outline-none">
<option value="HIGH" selected>Hoog (Belangrijke milestone)</option> <option value="HIGH" selected>Hoog (Belangrijke milestone)</option>
<option value="CRITICAL">Kritiek (Must-have)</option> <option value="CRITICAL">Kritiek (Must-have)</option>
<option value="MEDIUM">Normaal</option> <option value="MEDIUM">Normaal</option>
@@ -245,17 +273,17 @@ $categories = [
</div> </div>
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Streefdatum (Deadline)</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Streefdatum (Deadline)</label>
<input type="date" id="roadmapDueDate" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-1.5 text-white text-xs focus:outline-none"> <input type="date" id="roadmapDueDate" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3 py-1.5 text-slate-900 dark:text-white text-xs focus:outline-none">
</div> </div>
</div> </div>
<div class="flex space-x-2 pt-2"> <div class="flex space-x-2 pt-2">
<button onclick="submitConvertToRoadmap()" class="flex-1 bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold py-2.5 px-4 rounded-xl text-xs transition shadow-lg shadow-emerald-500/20 flex items-center justify-center space-x-2"> <button onclick="submitConvertToRoadmap()" class="flex-1 bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold py-2.5 px-4 rounded-xl text-xs transition shadow-lg shadow-emerald-500/20 flex items-center justify-center space-x-2 cursor-pointer">
<i data-lucide="check-circle" class="w-4 h-4"></i> <i data-lucide="check-circle" class="w-4 h-4"></i>
<span>Definitief Toevoegen aan Roadmap</span> <span>Definitief Toevoegen aan Roadmap</span>
</button> </button>
<button onclick="closeConvertModal()" class="px-4 py-2.5 bg-slate-800 hover:bg-slate-700 text-slate-300 rounded-xl text-xs transition"> <button onclick="closeConvertModal()" class="px-4 py-2.5 bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-300 rounded-xl text-xs transition cursor-pointer">
Annuleren Annuleren
</button> </button>
</div> </div>
@@ -368,4 +396,3 @@ async function submitConvertToRoadmap() {
</script> </script>
<?php require_once __DIR__ . '/includes/footer.php'; ?> <?php require_once __DIR__ . '/includes/footer.php'; ?>
+57
View File
@@ -98,6 +98,24 @@ function ensure_notification_columns(PDO $db): void {
} }
} }
/**
* Garandeert dat de kolom voor weergavethema (dark, light, system) aanwezig is in MariaDB
*/
function ensure_theme_column(PDO $db): void {
static $themeChecked = false;
if ($themeChecked) return;
$themeChecked = true;
try {
$result = $db->query("SHOW COLUMNS FROM `users` LIKE 'theme'");
if (!$result || $result->rowCount() === 0) {
$db->exec("ALTER TABLE `users` ADD COLUMN `theme` VARCHAR(20) NOT NULL DEFAULT 'dark' AFTER `notification_settings`");
}
} catch (Throwable $e) {
// Stil negeren indien al aanwezig
}
}
/** /**
* Genereert en bewaart een persistente 'Onthoud mij' token in MariaDB en plaatst een veilige cookie * Genereert en bewaart een persistente 'Onthoud mij' token in MariaDB en plaatst een veilige cookie
*/ */
@@ -399,4 +417,43 @@ function update_user_notification_settings(int $userId, array $settings): bool {
} }
} }
/**
* Haalt het voorkeursthema op voor een gebruiker ('dark', 'light' of 'system')
*/
function get_user_theme(int $userId): string {
$db = get_db_connection();
ensure_theme_column($db);
try {
$stmt = $db->prepare("SELECT theme FROM users WHERE id = ?");
$stmt->execute([$userId]);
$theme = $stmt->fetchColumn();
if ($theme && in_array($theme, ['dark', 'light', 'system'])) {
return $theme;
}
} catch (Throwable $e) {
error_log("get_user_theme error: " . $e->getMessage());
}
return 'dark';
}
/**
* Slaat het voorkeursthema van een gebruiker op ('dark', 'light' of 'system')
*/
function update_user_theme(int $userId, string $theme): bool {
$db = get_db_connection();
ensure_theme_column($db);
$theme = in_array($theme, ['dark', 'light', 'system']) ? $theme : 'dark';
try {
$stmt = $db->prepare("UPDATE users SET theme = ? WHERE id = ?");
return $stmt->execute([$theme, $userId]);
} catch (Throwable $e) {
error_log("update_user_theme error: " . $e->getMessage());
return false;
}
}
+4 -5
View File
@@ -1,14 +1,14 @@
</main> </main>
<footer class="border-t border-slate-800/80 py-6 text-center text-xs text-slate-500"> <footer class="border-t border-slate-200 dark:border-slate-800/80 bg-white/50 dark:bg-transparent backdrop-blur-sm py-6 text-center text-xs text-slate-500 transition">
<div class="max-w-7xl mx-auto px-4 flex flex-col sm:flex-row items-center justify-between gap-2"> <div class="max-w-7xl mx-auto px-4 flex flex-col sm:flex-row items-center justify-between gap-2">
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<span class="font-bold text-slate-400">Fociz</span> <span class="font-bold text-slate-700 dark:text-slate-400">Fociz</span>
<span>&bull;</span> <span>&bull;</span>
<span>Focus & Structuur Systeem</span> <span class="text-slate-600 dark:text-slate-500">Focus & Structuur Systeem</span>
</div> </div>
<div> <div>
<span>Beveiligd met MariaDB & Tweestapsverificatie (2FA)</span> <span class="text-slate-500 dark:text-slate-500">Beveiligd met MariaDB & Tweestapsverificatie (2FA)</span>
</div> </div>
</div> </div>
</footer> </footer>
@@ -24,4 +24,3 @@
</script> </script>
</body> </body>
</html> </html>
+156 -71
View File
@@ -1,11 +1,12 @@
<?php <?php
/** /**
* Header & Navigatiebalk voor Fociz * Header & Navigatiebalk voor Fociz (Dual-Mode: Dark & Light, Executive Styling)
*/ */
require_once __DIR__ . '/auth.php'; require_once __DIR__ . '/auth.php';
$currentUser = $currentUser ?? require_auth(); $currentUser = $currentUser ?? require_auth();
$currentPage = basename($_SERVER['PHP_SELF']); $currentPage = basename($_SERVER['PHP_SELF']);
$currentUserTheme = !empty($currentUser['id']) ? get_user_theme((int)$currentUser['id']) : 'dark';
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="nl" class="dark"> <html lang="nl" class="dark">
@@ -13,6 +14,26 @@ $currentPage = basename($_SERVER['PHP_SELF']);
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= htmlspecialchars($pageTitle ?? 'Fociz — Focus, Dagplanning & Roadmap') ?></title> <title><?= htmlspecialchars($pageTitle ?? 'Fociz — Focus, Dagplanning & Roadmap') ?></title>
<!-- Anti-Flicker Theme Script: direct in head zodat er nooit een flits optreedt -->
<script>
(function() {
try {
const serverTheme = <?= json_encode($currentUserTheme ?? 'dark') ?>;
const savedTheme = localStorage.getItem('fociz_theme') || serverTheme || 'dark';
let effective = savedTheme;
if (savedTheme === 'system') {
effective = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
if (effective === 'dark') {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
} catch(e) {}
})();
</script>
<!-- Tailwind CSS CDN --> <!-- Tailwind CSS CDN -->
<script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.tailwindcss.com"></script>
<script> <script>
@@ -23,6 +44,8 @@ $currentPage = basename($_SERVER['PHP_SELF']);
colors: { colors: {
brand: { brand: {
50: '#f0fdf4', 50: '#f0fdf4',
100: '#dcfce7',
200: '#bbf7d0',
500: '#10b981', 500: '#10b981',
600: '#059669', 600: '#059669',
700: '#047857', 700: '#047857',
@@ -35,17 +58,27 @@ $currentPage = basename($_SERVER['PHP_SELF']);
<!-- Lucide Icons --> <!-- Lucide Icons -->
<script src="https://unpkg.com/lucide@latest"></script> <script src="https://unpkg.com/lucide@latest"></script>
<style> <style>
body { html.dark body {
background-color: #090d16; background-color: #090d16;
color: #f1f5f9; color: #f1f5f9;
}
html:not(.dark) body {
background-color: #f8fafc;
color: #0f172a;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
} }
::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar { width: 7px; height: 7px; }
::-webkit-scrollbar-track { background: #0f172a; } html.dark ::-webkit-scrollbar-track { background: #0b1120; }
::-webkit-scrollbar-thumb { background: #334155; border-radius: 4px; } html.dark ::-webkit-scrollbar-thumb { background: #223049; border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: #475569; } html.dark ::-webkit-scrollbar-thumb:hover { background: #334668; }
html:not(.dark) ::-webkit-scrollbar-track { background: #f1f5f9; }
html:not(.dark) ::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; }
html:not(.dark) ::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
</style> </style>
<body class="min-h-screen flex flex-col antialiased selection:bg-emerald-500 selection:text-white"> </head>
<body class="min-h-screen flex flex-col antialiased selection:bg-emerald-500 selection:text-white transition-colors duration-150">
<?php <?php
// Include flashy omgevingsindicator (Dev = Rood, Live = Groen) // Include flashy omgevingsindicator (Dev = Rood, Live = Groen)
@@ -53,104 +86,115 @@ require_once __DIR__ . '/env_badge.php';
?> ?>
<?php if ($currentUser): ?> <?php if ($currentUser): ?>
<header class="sticky top-0 z-40 bg-[#0c121e]/90 backdrop-blur-md border-b border-slate-800/80"> <header class="sticky top-0 z-40 bg-white/85 dark:bg-[#0c121e]/90 backdrop-blur-md border-b border-slate-200/80 dark:border-slate-800/80 shadow-sm dark:shadow-none transition-colors duration-150">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16"> <div class="flex items-center justify-between h-16">
<!-- Brand Logo (met linker padding zodat het badge vrij staat) --> <!-- Brand Logo (met linker padding zodat het dev/live badge vrij staat) -->
<div class="flex items-center space-x-6 pl-28 sm:pl-36"> <div class="flex items-center space-x-6 pl-28 sm:pl-36">
<a href="/planner.php" class="flex items-center space-x-2.5 group"> <a href="/planner.php" class="flex items-center space-x-2.5 group">
<div class="w-9 h-9 rounded-xl bg-gradient-to-tr from-emerald-600 to-teal-400 flex items-center justify-center text-slate-950 font-black text-lg shadow-md shadow-emerald-500/20 group-hover:scale-105 transition"> <div class="w-9 h-9 rounded-xl bg-gradient-to-tr from-emerald-600 to-teal-400 flex items-center justify-center text-slate-950 font-black text-lg shadow-md shadow-emerald-500/20 group-hover:scale-105 transition">
F F
</div> </div>
<div class="flex flex-col"> <div class="flex flex-col">
<span class="text-xl font-bold tracking-tight text-white leading-none">Fociz</span> <span class="text-xl font-bold tracking-tight text-slate-900 dark:text-white leading-none">Fociz</span>
<span class="text-[10px] text-emerald-400 tracking-wider font-semibold uppercase">Focus & Structuur</span> <span class="text-[10px] text-emerald-600 dark:text-emerald-400 tracking-wider font-semibold uppercase">Focus & Structuur</span>
</div> </div>
</a> </a>
<!-- Nav Tabs --> <!-- Nav Tabs -->
<nav class="hidden md:flex items-center space-x-1"> <nav class="hidden md:flex items-center space-x-1">
<a href="/planner.php" class="flex items-center space-x-2 px-3.5 py-2 rounded-lg text-sm font-medium transition <?= $currentPage === 'planner.php' ? 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20' : 'text-slate-400 hover:text-slate-200 hover:bg-slate-800/60' ?>"> <a href="/planner.php" class="flex items-center space-x-2 px-3 py-1.5 rounded-xl text-xs font-semibold transition <?= $currentPage === 'planner.php' ? 'bg-emerald-50 text-emerald-700 border border-emerald-200 shadow-sm dark:bg-emerald-500/10 dark:text-emerald-400 dark:border-emerald-500/20' : 'text-slate-600 hover:text-slate-900 hover:bg-slate-100 dark:text-slate-400 dark:hover:text-slate-200 dark:hover:bg-slate-800/60' ?>">
<i data-lucide="calendar" class="w-4 h-4"></i> <i data-lucide="calendar" class="w-4 h-4"></i>
<span>Dagplanning</span> <span>Dagplanning</span>
</a> </a>
<a href="/brainstorm.php" class="flex items-center space-x-2 px-3.5 py-2 rounded-lg text-sm font-medium transition <?= in_array($currentPage, ['brainstorm.php', 'brainstorm_canvas.php']) ? 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20' : 'text-slate-400 hover:text-slate-200 hover:bg-slate-800/60' ?>"> <a href="/brainstorm.php" class="flex items-center space-x-2 px-3 py-1.5 rounded-xl text-xs font-semibold transition <?= in_array($currentPage, ['brainstorm.php', 'brainstorm_canvas.php']) ? 'bg-emerald-50 text-emerald-700 border border-emerald-200 shadow-sm dark:bg-emerald-500/10 dark:text-emerald-400 dark:border-emerald-500/20' : 'text-slate-600 hover:text-slate-900 hover:bg-slate-100 dark:text-slate-400 dark:hover:text-slate-200 dark:hover:bg-slate-800/60' ?>">
<i data-lucide="lightbulb" class="w-4 h-4"></i> <i data-lucide="lightbulb" class="w-4 h-4"></i>
<span>Brainstorm</span> <span>Brainstorm</span>
</a> </a>
<a href="/roadmap.php" class="flex items-center space-x-2 px-3.5 py-2 rounded-lg text-sm font-medium transition <?= $currentPage === 'roadmap.php' ? 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20' : 'text-slate-400 hover:text-slate-200 hover:bg-slate-800/60' ?>"> <a href="/roadmap.php" class="flex items-center space-x-2 px-3 py-1.5 rounded-xl text-xs font-semibold transition <?= $currentPage === 'roadmap.php' ? 'bg-emerald-50 text-emerald-700 border border-emerald-200 shadow-sm dark:bg-emerald-500/10 dark:text-emerald-400 dark:border-emerald-500/20' : 'text-slate-600 hover:text-slate-900 hover:bg-slate-100 dark:text-slate-400 dark:hover:text-slate-200 dark:hover:bg-slate-800/60' ?>">
<i data-lucide="map" class="w-4 h-4"></i> <i data-lucide="map" class="w-4 h-4"></i>
<span>Roadmap</span> <span>Roadmap</span>
</a> </a>
<a href="/profile.php" class="flex items-center space-x-2 px-3.5 py-2 rounded-lg text-sm font-medium transition <?= $currentPage === 'profile.php' ? 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20' : 'text-slate-400 hover:text-slate-200 hover:bg-slate-800/60' ?>"> <a href="/profile.php" class="flex items-center space-x-2 px-3 py-1.5 rounded-xl text-xs font-semibold transition <?= $currentPage === 'profile.php' ? 'bg-emerald-50 text-emerald-700 border border-emerald-200 shadow-sm dark:bg-emerald-500/10 dark:text-emerald-400 dark:border-emerald-500/20' : 'text-slate-600 hover:text-slate-900 hover:bg-slate-100 dark:text-slate-400 dark:hover:text-slate-200 dark:hover:bg-slate-800/60' ?>">
<i data-lucide="user" class="w-4 h-4"></i> <i data-lucide="user" class="w-4 h-4"></i>
<span>Mijn Profiel</span> <span>Mijn Profiel</span>
</a> </a>
<?php if ($currentUser['role'] === 'ADMIN'): ?> <?php if ($currentUser['role'] === 'ADMIN'): ?>
<a href="/users.php" class="flex items-center space-x-2 px-3.5 py-2 rounded-lg text-sm font-medium transition <?= $currentPage === 'users.php' ? 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20' : 'text-slate-400 hover:text-slate-200 hover:bg-slate-800/60' ?>"> <a href="/users.php" class="flex items-center space-x-2 px-3 py-1.5 rounded-xl text-xs font-semibold transition <?= $currentPage === 'users.php' ? 'bg-emerald-50 text-emerald-700 border border-emerald-200 shadow-sm dark:bg-emerald-500/10 dark:text-emerald-400 dark:border-emerald-500/20' : 'text-slate-600 hover:text-slate-900 hover:bg-slate-100 dark:text-slate-400 dark:hover:text-slate-200 dark:hover:bg-slate-800/60' ?>">
<i data-lucide="users" class="w-4 h-4"></i> <i data-lucide="users" class="w-4 h-4"></i>
<span>Team</span> <span>Team</span>
</a> </a>
<a href="/admin.php" class="flex items-center space-x-2 px-3.5 py-2 rounded-lg text-sm font-medium transition <?= $currentPage === 'admin.php' ? 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20' : 'text-slate-400 hover:text-slate-200 hover:bg-slate-800/60' ?>"> <a href="/admin.php" class="flex items-center space-x-2 px-3 py-1.5 rounded-xl text-xs font-semibold transition <?= $currentPage === 'admin.php' ? 'bg-emerald-50 text-emerald-700 border border-emerald-200 shadow-sm dark:bg-emerald-500/10 dark:text-emerald-400 dark:border-emerald-500/20' : 'text-slate-600 hover:text-slate-900 hover:bg-slate-100 dark:text-slate-400 dark:hover:text-slate-200 dark:hover:bg-slate-800/60' ?>">
<i data-lucide="shield-check" class="w-4 h-4 text-emerald-400"></i> <i data-lucide="shield-check" class="w-4 h-4 text-emerald-600 dark:text-emerald-400"></i>
<span>Beheer</span> <span>Beheer</span>
</a> </a>
<?php endif; ?> <?php endif; ?>
</nav> </nav>
</div> </div>
<!-- Right side: User, Notifications & 2FA Status --> <!-- Right side: Theme Toggle, Notifications, 2FA Status & User -->
<div class="flex items-center space-x-2.5"> <div class="flex items-center space-x-2 sm:space-x-2.5">
<button type="button" onclick="openNotificationModal()" class="relative p-2 rounded-lg text-slate-400 hover:text-white hover:bg-slate-800 transition" title="Meldingen & Agenda Herinneringen"> <!-- 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> <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> <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> </button>
<div class="hidden sm:flex items-center space-x-1.5 px-2.5 py-1 rounded-full bg-emerald-500/10 border border-emerald-500/25 text-emerald-400 text-xs font-medium"> <!-- 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> <i data-lucide="shield-check" class="w-3.5 h-3.5"></i>
<span>2FA Actief</span> <span>2FA Actief</span>
</div> </div>
<a href="/profile.php" class="text-right hidden sm:block group hover:opacity-90 transition" title="Mijn Profiel & Instellingen"> <!-- Profiel link rechtsboven -->
<div class="text-xs font-semibold text-slate-200 group-hover:text-emerald-400 transition flex items-center justify-end space-x-1"> <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> <span><?= htmlspecialchars($currentUser['name']) ?></span>
<i data-lucide="chevron-right" class="w-3 h-3 text-slate-500 group-hover:text-emerald-400 transition"></i> <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>
</div> </div>
<div class="text-[10px] text-slate-500"> <div class="text-[10px] text-slate-500 dark:text-slate-400">
<?= $currentUser['role'] === 'ADMIN' ? 'Beheerder' : 'Collega' ?> • <?= htmlspecialchars($currentUser['email']) ?> <?= $currentUser['role'] === 'ADMIN' ? 'Beheerder' : 'Collega' ?> • <?= htmlspecialchars($currentUser['email']) ?>
</div> </div>
</a> </a>
<a href="/auth/logout.php" title="Veilig uitloggen" class="p-2 rounded-lg text-slate-400 hover:text-red-400 hover:bg-red-500/10 border border-transparent hover:border-red-500/20 transition"> <!-- 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">
<i data-lucide="log-out" class="w-4 h-4"></i> <i data-lucide="log-out" class="w-4 h-4"></i>
</a> </a>
</div> </div>
</div> </div>
<!-- Mobile Navigation --> <!-- Mobile Navigation -->
<div class="flex md:hidden items-center justify-around py-2 border-t border-slate-800/60 text-xs"> <div class="flex md:hidden items-center justify-around py-2 border-t border-slate-200/80 dark:border-slate-800/60 text-xs">
<a href="/planner.php" class="flex flex-col items-center py-1 <?= $currentPage === 'planner.php' ? 'text-emerald-400 font-bold' : 'text-slate-400' ?>"> <a href="/planner.php" class="flex flex-col items-center py-1 <?= $currentPage === 'planner.php' ? 'text-emerald-600 dark:text-emerald-400 font-bold' : 'text-slate-500 dark:text-slate-400' ?>">
<i data-lucide="calendar" class="w-4 h-4 mb-0.5"></i> <i data-lucide="calendar" class="w-4 h-4 mb-0.5"></i>
<span>Planning</span> <span>Planning</span>
</a> </a>
<a href="/brainstorm.php" class="flex flex-col items-center py-1 <?= in_array($currentPage, ['brainstorm.php', 'brainstorm_canvas.php']) ? 'text-emerald-400 font-bold' : 'text-slate-400' ?>"> <a href="/brainstorm.php" class="flex flex-col items-center py-1 <?= in_array($currentPage, ['brainstorm.php', 'brainstorm_canvas.php']) ? 'text-emerald-600 dark:text-emerald-400 font-bold' : 'text-slate-500 dark:text-slate-400' ?>">
<i data-lucide="lightbulb" class="w-4 h-4 mb-0.5"></i> <i data-lucide="lightbulb" class="w-4 h-4 mb-0.5"></i>
<span>Brainstorm</span> <span>Brainstorm</span>
</a> </a>
<a href="/roadmap.php" class="flex flex-col items-center py-1 <?= $currentPage === 'roadmap.php' ? 'text-emerald-400 font-bold' : 'text-slate-400' ?>"> <a href="/roadmap.php" class="flex flex-col items-center py-1 <?= $currentPage === 'roadmap.php' ? 'text-emerald-600 dark:text-emerald-400 font-bold' : 'text-slate-500 dark:text-slate-400' ?>">
<i data-lucide="map" class="w-4 h-4 mb-0.5"></i> <i data-lucide="map" class="w-4 h-4 mb-0.5"></i>
<span>Roadmap</span> <span>Roadmap</span>
</a> </a>
<a href="/profile.php" class="flex flex-col items-center py-1 <?= $currentPage === 'profile.php' ? 'text-emerald-400 font-bold' : 'text-slate-400' ?>"> <a href="/profile.php" class="flex flex-col items-center py-1 <?= $currentPage === 'profile.php' ? 'text-emerald-600 dark:text-emerald-400 font-bold' : 'text-slate-500 dark:text-slate-400' ?>">
<i data-lucide="user" class="w-4 h-4 mb-0.5"></i> <i data-lucide="user" class="w-4 h-4 mb-0.5"></i>
<span>Profiel</span> <span>Profiel</span>
</a> </a>
<button type="button" onclick="openNotificationModal()" class="flex flex-col items-center py-1 text-slate-400 hover:text-white"> <button type="button" onclick="focizQuickToggleTheme()" class="flex flex-col items-center py-1 text-slate-500 dark:text-slate-400">
<i data-lucide="bell" class="w-4 h-4 mb-0.5"></i> <i data-lucide="sun" class="w-4 h-4 mb-0.5 hidden dark:block text-amber-400"></i>
<span>Meldingen</span> <i data-lucide="moon" class="w-4 h-4 mb-0.5 block dark:hidden"></i>
<span>Thema</span>
</button> </button>
<?php if ($currentUser['role'] === 'ADMIN'): ?> <?php if ($currentUser['role'] === 'ADMIN'): ?>
<a href="/admin.php" class="flex flex-col items-center py-1 <?= $currentPage === 'admin.php' ? 'text-emerald-400 font-bold' : 'text-slate-400' ?>"> <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> <i data-lucide="shield" class="w-4 h-4 mb-0.5"></i>
<span>Beheer</span> <span>Beheer</span>
</a> </a>
@@ -159,21 +203,21 @@ require_once __DIR__ . '/env_badge.php';
</div> </div>
</header> </header>
<!-- Fociz Agenda Notificaties Modal --> <!-- Fociz Agenda Notificaties Modal (Dual-Mode) -->
<div id="focizNotificationModal" class="hidden fixed inset-0 z-50 bg-black/80 backdrop-blur-sm items-center justify-center p-4"> <div id="focizNotificationModal" class="hidden fixed inset-0 z-50 bg-black/60 dark:bg-black/80 backdrop-blur-sm items-center justify-center p-4">
<div class="bg-slate-900 border border-slate-800 rounded-2xl w-full max-w-md overflow-hidden shadow-2xl animate-in fade-in zoom-in-95 duration-200"> <div class="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl w-full max-w-md overflow-hidden shadow-2xl animate-in fade-in zoom-in-95 duration-200">
<!-- Modal Header --> <!-- Modal Header -->
<div class="p-5 border-b border-slate-800/80 flex items-center justify-between"> <div class="p-5 border-b border-slate-100 dark:border-slate-800/80 flex items-center justify-between">
<div class="flex items-center space-x-2.5"> <div class="flex items-center space-x-2.5">
<div class="w-9 h-9 rounded-xl bg-blue-500/10 border border-blue-500/30 text-blue-400 flex items-center justify-center font-bold"> <div class="w-9 h-9 rounded-xl bg-blue-50 dark:bg-blue-500/10 border border-blue-200 dark:border-blue-500/30 text-blue-600 dark:text-blue-400 flex items-center justify-center font-bold">
<i data-lucide="bell-ring" class="w-4 h-4"></i> <i data-lucide="bell-ring" class="w-4 h-4"></i>
</div> </div>
<div> <div>
<h3 class="text-sm font-bold text-white">Agenda Push Meldingen</h3> <h3 class="text-sm font-bold text-slate-900 dark:text-white">Agenda Push Meldingen</h3>
<p class="text-[11px] text-slate-400">Persoonlijke waarschuwingen bij actuele afspraken</p> <p class="text-[11px] text-slate-500 dark:text-slate-400">Persoonlijke waarschuwingen bij actuele afspraken</p>
</div> </div>
</div> </div>
<button type="button" onclick="closeNotificationModal()" class="text-slate-500 hover:text-white p-1 rounded-lg transition"> <button type="button" onclick="closeNotificationModal()" class="text-slate-400 hover:text-slate-700 dark:hover:text-white p-1 rounded-lg transition">
<i data-lucide="x" class="w-4 h-4"></i> <i data-lucide="x" class="w-4 h-4"></i>
</button> </button>
</div> </div>
@@ -181,19 +225,19 @@ require_once __DIR__ . '/env_badge.php';
<!-- Inhoud Formulier --> <!-- Inhoud Formulier -->
<form onsubmit="saveNotificationPreferences(event)" class="p-5 space-y-4 text-xs"> <form onsubmit="saveNotificationPreferences(event)" class="p-5 space-y-4 text-xs">
<!-- Browser Permissie Banner --> <!-- Browser Permissie Banner -->
<div id="notifPermGranted" class="hidden p-3 rounded-xl bg-emerald-500/10 border border-emerald-500/30 text-emerald-300 flex items-center justify-between"> <div id="notifPermGranted" class="hidden p-3 rounded-xl bg-emerald-50 dark:bg-emerald-500/10 border border-emerald-200 dark:border-emerald-500/30 text-emerald-800 dark:text-emerald-300 flex items-center justify-between">
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<i data-lucide="check-circle" class="w-4 h-4 text-emerald-400 flex-shrink-0"></i> <i data-lucide="check-circle" class="w-4 h-4 text-emerald-600 dark:text-emerald-400 flex-shrink-0"></i>
<span class="text-[11px]">Browser pushberichten zijn actief</span> <span class="text-[11px]">Browser pushberichten zijn actief</span>
</div> </div>
<button type="button" onclick="focizTestNotification()" class="px-2 py-1 rounded-lg bg-emerald-500/20 hover:bg-emerald-500/30 text-emerald-300 font-semibold text-[10px] transition"> <button type="button" onclick="focizTestNotification()" class="px-2 py-1 rounded-lg bg-emerald-100 dark:bg-emerald-500/20 hover:bg-emerald-200 dark:hover:bg-emerald-500/30 text-emerald-800 dark:text-emerald-300 font-semibold text-[10px] transition">
Test Melding Test Melding
</button> </button>
</div> </div>
<div id="notifPermRequest" class="p-3 rounded-xl bg-blue-500/10 border border-blue-500/30 text-blue-200 flex items-center justify-between"> <div id="notifPermRequest" class="p-3 rounded-xl bg-blue-50 dark:bg-blue-500/10 border border-blue-200 dark:border-blue-500/30 text-blue-900 dark:text-blue-200 flex items-center justify-between">
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<i data-lucide="bell" class="w-4 h-4 text-blue-400 flex-shrink-0"></i> <i data-lucide="bell" class="w-4 h-4 text-blue-600 dark:text-blue-400 flex-shrink-0"></i>
<span class="text-[11px]">Toestemming browser vereist</span> <span class="text-[11px]">Toestemming browser vereist</span>
</div> </div>
<button type="button" onclick="focizRequestPermission()" class="px-2.5 py-1 rounded-lg bg-blue-600 hover:bg-blue-500 text-white font-bold text-[10px] transition shadow"> <button type="button" onclick="focizRequestPermission()" class="px-2.5 py-1 rounded-lg bg-blue-600 hover:bg-blue-500 text-white font-bold text-[10px] transition shadow">
@@ -201,29 +245,29 @@ require_once __DIR__ . '/env_badge.php';
</button> </button>
</div> </div>
<div id="notifPermDenied" class="hidden p-3 rounded-xl bg-red-500/10 border border-red-500/30 text-red-300 text-[11px] leading-relaxed"> <div id="notifPermDenied" class="hidden p-3 rounded-xl bg-red-50 dark:bg-red-500/10 border border-red-200 dark:border-red-500/30 text-red-800 dark:text-red-300 text-[11px] leading-relaxed">
<i data-lucide="alert-triangle" class="w-4 h-4 text-red-400 inline mr-1 -mt-0.5"></i> <i data-lucide="alert-triangle" class="w-4 h-4 text-red-600 dark:text-red-400 inline mr-1 -mt-0.5"></i>
Browser meldingen zijn geblokkeerd. Klik op het slotje links in de browser adresbalk om meldingen toe te staan. Browser meldingen zijn geblokkeerd. Klik op het slotje links in de adresbalk om meldingen toe te staan.
</div> </div>
<!-- Toggle Meldingen Inschakelen --> <!-- Toggle Meldingen Inschakelen -->
<div class="flex items-center justify-between p-3 rounded-xl bg-slate-950/60 border border-slate-800"> <div class="flex items-center justify-between p-3 rounded-xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800">
<div> <div>
<span class="font-semibold text-white block">Meldingen Actief</span> <span class="font-semibold text-slate-900 dark:text-white block">Meldingen Actief</span>
<span class="text-[10px] text-slate-400">Automatisch waarschuwen bij naderende afspraken</span> <span class="text-[10px] text-slate-500 dark:text-slate-400">Automatisch waarschuwen bij naderende afspraken</span>
</div> </div>
<label class="relative inline-flex items-center cursor-pointer"> <label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" id="notifEnabledInput" class="sr-only peer"> <input type="checkbox" id="notifEnabledInput" class="sr-only peer">
<div class="w-9 h-5 bg-slate-800 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-blue-600"></div> <div class="w-9 h-5 bg-slate-200 dark:bg-slate-800 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-emerald-600"></div>
</label> </label>
</div> </div>
<!-- Vooraankondigingstijd --> <!-- Vooraankondigingstijd -->
<div> <div>
<label class="block font-semibold text-slate-300 mb-1"> <label class="block font-semibold text-slate-700 dark:text-slate-300 mb-1">
Hoeveel tijd van tevoren waarschuwen? Hoeveel tijd van tevoren waarschuwen?
</label> </label>
<select id="notifLeadTimeSelect" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white focus:outline-none focus:border-blue-500"> <select id="notifLeadTimeSelect" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 rounded-xl px-3 py-2 text-slate-900 dark:text-white focus:outline-none focus:border-emerald-500">
<option value="0">0 minuten (Precies op aanvangstijd)</option> <option value="0">0 minuten (Precies op aanvangstijd)</option>
<option value="2">2 minuten van tevoren</option> <option value="2">2 minuten van tevoren</option>
<option value="5" selected>5 minuten van tevoren (Aanbevolen)</option> <option value="5" selected>5 minuten van tevoren (Aanbevolen)</option>
@@ -236,10 +280,10 @@ require_once __DIR__ . '/env_badge.php';
<!-- Aantal Herhalingen & Interval Grid --> <!-- Aantal Herhalingen & Interval Grid -->
<div class="grid grid-cols-2 gap-3"> <div class="grid grid-cols-2 gap-3">
<div> <div>
<label class="block font-semibold text-slate-300 mb-1"> <label class="block font-semibold text-slate-700 dark:text-slate-300 mb-1">
Aantal herhalingen Aantal herhalingen
</label> </label>
<select id="notifRepeatCountSelect" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white focus:outline-none focus:border-blue-500"> <select id="notifRepeatCountSelect" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 rounded-xl px-3 py-2 text-slate-900 dark:text-white focus:outline-none focus:border-emerald-500">
<option value="1">1x (Alleen 1e melding)</option> <option value="1">1x (Alleen 1e melding)</option>
<option value="2" selected>2x (Aanbevolen)</option> <option value="2" selected>2x (Aanbevolen)</option>
<option value="3">3x</option> <option value="3">3x</option>
@@ -248,10 +292,10 @@ require_once __DIR__ . '/env_badge.php';
</div> </div>
<div> <div>
<label class="block font-semibold text-slate-300 mb-1"> <label class="block font-semibold text-slate-700 dark:text-slate-300 mb-1">
Herhalingsinterval Herhalingsinterval
</label> </label>
<select id="notifIntervalSelect" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white focus:outline-none focus:border-blue-500"> <select id="notifIntervalSelect" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 rounded-xl px-3 py-2 text-slate-900 dark:text-white focus:outline-none focus:border-emerald-500">
<option value="1">Elke 1 minuut</option> <option value="1">Elke 1 minuut</option>
<option value="2" selected>Elke 2 minuten</option> <option value="2" selected>Elke 2 minuten</option>
<option value="3">Elke 3 minuten</option> <option value="3">Elke 3 minuten</option>
@@ -261,28 +305,28 @@ require_once __DIR__ . '/env_badge.php';
</div> </div>
<!-- Geluidssignaal Toggle --> <!-- Geluidssignaal Toggle -->
<div class="flex items-center justify-between p-3 rounded-xl bg-slate-950/60 border border-slate-800"> <div class="flex items-center justify-between p-3 rounded-xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800">
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<i data-lucide="volume-2" class="w-4 h-4 text-blue-400"></i> <i data-lucide="volume-2" class="w-4 h-4 text-emerald-600 dark:text-emerald-400"></i>
<div> <div>
<span class="font-semibold text-white block">Geluidssignaal</span> <span class="font-semibold text-slate-900 dark:text-white block">Geluidssignaal</span>
<span class="text-[10px] text-slate-400">Zachte bel/chime afspelen bij melding</span> <span class="text-[10px] text-slate-500 dark:text-slate-400">Zachte chime afspelen bij melding</span>
</div> </div>
</div> </div>
<label class="relative inline-flex items-center cursor-pointer"> <label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" id="notifSoundInput" checked class="sr-only peer"> <input type="checkbox" id="notifSoundInput" checked class="sr-only peer">
<div class="w-9 h-5 bg-slate-800 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-blue-600"></div> <div class="w-9 h-5 bg-slate-200 dark:bg-slate-800 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-emerald-600"></div>
</label> </label>
</div> </div>
<div id="notifSaveStatus" class="hidden text-emerald-400 text-center font-semibold text-[11px] py-1"></div> <div id="notifSaveStatus" class="hidden text-emerald-600 dark:text-emerald-400 text-center font-semibold text-[11px] py-1"></div>
<!-- Knoppen --> <!-- Knoppen -->
<div class="pt-2 flex items-center space-x-2"> <div class="pt-2 flex items-center space-x-2">
<button type="button" onclick="closeNotificationModal()" class="flex-1 py-2 rounded-xl bg-slate-800 hover:bg-slate-700 text-slate-300 font-semibold transition"> <button type="button" onclick="closeNotificationModal()" class="flex-1 py-2 rounded-xl bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-300 font-semibold transition">
Annuleren Annuleren
</button> </button>
<button type="submit" id="saveNotifBtn" class="flex-1 py-2 rounded-xl bg-blue-600 hover:bg-blue-500 text-white font-bold transition shadow-md shadow-blue-500/20"> <button type="submit" id="saveNotifBtn" class="flex-1 py-2 rounded-xl bg-emerald-600 hover:bg-emerald-500 text-white font-bold transition shadow-md shadow-emerald-600/20">
Voorkeuren Opslaan Voorkeuren Opslaan
</button> </button>
</div> </div>
@@ -291,5 +335,46 @@ require_once __DIR__ . '/env_badge.php';
</div> </div>
<?php endif; ?> <?php endif; ?>
<main class="flex-1 max-w-7xl w-full mx-auto p-4 sm:p-6 lg:p-8"> <script>
/**
* Universele Thema-controller voor Fociz
*/
function focizSetTheme(theme, saveServer = true) {
localStorage.setItem('fociz_theme', theme);
let effective = theme;
if (theme === 'system') {
effective = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
if (effective === 'dark') {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
// Update Lucide pictogrammen in header
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
// Update profiel preview selectoren als aanwezig op pagina
if (typeof updateProfileThemeUI === 'function') {
updateProfileThemeUI(theme);
}
if (saveServer) {
fetch('/api/theme.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ theme: theme })
}).catch(() => {});
}
}
function focizQuickToggleTheme() {
const isDark = document.documentElement.classList.contains('dark');
const nextTheme = isDark ? 'light' : 'dark';
focizSetTheme(nextTheme, true);
}
</script>
<main class="flex-1 max-w-7xl w-full mx-auto p-4 sm:p-6 lg:p-8">
+91 -89
View File
@@ -112,16 +112,16 @@ $dutchMonths = ['', 'januari', 'februari', 'maart', 'april', 'mei', 'juni', 'jul
$formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(int)date('n')] . ' ' . date('Y'); $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(int)date('n')] . ' ' . date('Y');
?> ?>
<div class="space-y-6"> <div class="space-y-6 max-w-7xl mx-auto">
<!-- Top Banner: Datum, Hoofddoel & Integraties Status --> <!-- Top Banner: Datum, Hoofddoel & Integraties Status -->
<div class="bg-gradient-to-r from-slate-900 via-[#0e1626] to-slate-900 border border-slate-800 rounded-2xl p-6 shadow-2xl"> <div class="bg-white dark:bg-gradient-to-r dark:from-slate-900 dark:via-[#0e1626] dark:to-slate-900 border border-slate-200 dark:border-slate-800 rounded-3xl p-6 sm:p-7 shadow-sm dark:shadow-2xl transition">
<div class="flex flex-col lg:flex-row lg:items-center justify-between gap-4"> <div class="flex flex-col lg:flex-row lg:items-center justify-between gap-4">
<div> <div>
<div class="flex items-center space-x-2 text-emerald-400 text-xs font-semibold uppercase tracking-wider mb-1"> <div class="flex items-center space-x-2 text-emerald-600 dark:text-emerald-400 text-xs font-bold uppercase tracking-wider mb-1">
<i data-lucide="calendar" class="w-4 h-4"></i> <i data-lucide="calendar" class="w-4 h-4"></i>
<span><?= htmlspecialchars($formattedDate) ?></span> <span><?= htmlspecialchars($formattedDate) ?></span>
</div> </div>
<h1 class="text-2xl sm:text-3xl font-black text-white tracking-tight"> <h1 class="text-2xl sm:text-3xl font-black text-slate-900 dark:text-white tracking-tight">
Dagplanning & Structuur Dagplanning & Structuur
</h1> </h1>
</div> </div>
@@ -129,28 +129,28 @@ $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(i
<!-- Integratie Status Badges --> <!-- Integratie Status Badges -->
<div class="flex flex-wrap items-center gap-2"> <div class="flex flex-wrap items-center gap-2">
<?php if ($isOutlookConnected): ?> <?php if ($isOutlookConnected): ?>
<div class="flex items-center space-x-2 px-3 py-1.5 rounded-xl bg-blue-950/60 border border-blue-800/60 text-blue-300 text-xs font-medium"> <div class="flex items-center space-x-2 px-3 py-1.5 rounded-xl bg-blue-50 dark:bg-blue-950/60 border border-blue-200 dark:border-blue-800/60 text-blue-700 dark:text-blue-300 text-xs font-medium shadow-sm">
<span class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span> <span class="w-2 h-2 rounded-full bg-emerald-500 animate-pulse"></span>
<span>Outlook 365 Live</span> <span>Outlook 365 Live</span>
<button onclick="location.reload()" title="Agenda Verversen" class="p-1 text-blue-400 hover:text-white rounded transition"> <button onclick="location.reload()" title="Agenda Verversen" class="p-1 text-blue-500 hover:text-blue-800 dark:text-blue-400 dark:hover:text-white rounded transition">
<i data-lucide="refresh-cw" class="w-3 h-3"></i> <i data-lucide="refresh-cw" class="w-3 h-3"></i>
</button> </button>
</div> </div>
<?php else: ?> <?php else: ?>
<a href="/profile.php" class="flex items-center space-x-1.5 px-3 py-1.5 rounded-xl bg-slate-800/80 border border-slate-700 text-slate-300 hover:text-white hover:bg-slate-700 text-xs font-medium transition"> <a href="/profile.php" class="flex items-center space-x-1.5 px-3 py-1.5 rounded-xl bg-slate-100 hover:bg-slate-200 dark:bg-slate-800/80 dark:hover:bg-slate-700 border border-slate-200 dark:border-slate-700 text-slate-700 dark:text-slate-300 hover:text-slate-900 dark:hover:text-white text-xs font-medium transition shadow-sm">
<i data-lucide="link-2" class="w-3.5 h-3.5 text-blue-400"></i> <i data-lucide="link-2" class="w-3.5 h-3.5 text-blue-500"></i>
<span>Koppel Outlook</span> <span>Koppel Outlook</span>
</a> </a>
<?php endif; ?> <?php endif; ?>
<?php if ($isJiraLive): ?> <?php if ($isJiraLive): ?>
<a href="#jiraPanel" class="flex items-center space-x-1.5 px-3 py-1.5 rounded-xl bg-sky-950/60 border border-sky-800/60 text-sky-300 hover:text-white text-xs font-medium transition"> <a href="#jiraPanel" class="flex items-center space-x-1.5 px-3 py-1.5 rounded-xl bg-sky-50 dark:bg-sky-950/60 border border-sky-200 dark:border-sky-800/60 text-sky-700 dark:text-sky-300 hover:text-sky-900 dark:hover:text-white text-xs font-medium transition shadow-sm">
<span class="w-2 h-2 rounded-full bg-sky-400 animate-pulse"></span> <span class="w-2 h-2 rounded-full bg-sky-500 animate-pulse"></span>
<span>Jira: <?= count($jiraIssues) ?> tickets</span> <span>Jira: <?= count($jiraIssues) ?> tickets</span>
</a> </a>
<?php else: ?> <?php else: ?>
<a href="/profile.php" class="flex items-center space-x-1.5 px-3 py-1.5 rounded-xl bg-slate-800/80 border border-slate-700 text-slate-300 hover:text-white hover:bg-slate-700 text-xs font-medium transition"> <a href="/profile.php" class="flex items-center space-x-1.5 px-3 py-1.5 rounded-xl bg-slate-100 hover:bg-slate-200 dark:bg-slate-800/80 dark:hover:bg-slate-700 border border-slate-200 dark:border-slate-700 text-slate-700 dark:text-slate-300 hover:text-slate-900 dark:hover:text-white text-xs font-medium transition shadow-sm">
<i data-lucide="trello" class="w-3.5 h-3.5 text-sky-400"></i> <i data-lucide="trello" class="w-3.5 h-3.5 text-sky-500"></i>
<span>Koppel Jira</span> <span>Koppel Jira</span>
</a> </a>
<?php endif; ?> <?php endif; ?>
@@ -158,23 +158,23 @@ $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(i
</div> </div>
<!-- Dagdoel invoerveld --> <!-- Dagdoel invoerveld -->
<div class="mt-5 pt-4 border-t border-slate-800/80"> <div class="mt-5 pt-4 border-t border-slate-100 dark:border-slate-800/80">
<label class="block text-xs font-bold text-emerald-400 uppercase tracking-wider mb-1.5 flex items-center space-x-1.5"> <label class="block text-xs font-bold text-emerald-700 dark:text-emerald-400 uppercase tracking-wider mb-1.5 flex items-center space-x-1.5">
<i data-lucide="target" class="w-4 h-4"></i> <i data-lucide="target" class="w-4 h-4"></i>
<span>Mijn Belangrijkste Dagdoel (Nummer 1 Focus)</span> <span>Mijn Belangrijkste Dagdoel (Nummer 1 Focus)</span>
</label> </label>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<input <input
type="text" type="text"
id="focusGoalInput" id="focusGoalInput"
value="<?= htmlspecialchars($dailyPlan['focus_goal'] ?? '') ?>" value="<?= htmlspecialchars($dailyPlan['focus_goal'] ?? '') ?>"
placeholder="Wat moet er vandaag absoluut gebeuren voor succes?" placeholder="Wat moet er vandaag absoluut gebeuren voor succes?"
class="flex-1 bg-slate-950/70 border border-slate-700/80 rounded-xl px-4 py-2.5 text-white placeholder-slate-500 text-sm focus:outline-none focus:ring-2 focus:ring-emerald-500/50 focus:border-emerald-500 font-medium transition" class="flex-1 bg-slate-50 dark:bg-slate-950/70 border border-slate-300 dark:border-slate-700/80 rounded-xl px-4 py-2.5 text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-500 text-sm focus:outline-none focus:ring-2 focus:ring-emerald-500/50 focus:border-emerald-500 font-medium transition"
> >
<button <button
onclick="saveGoal()" onclick="saveGoal()"
id="saveGoalBtn" id="saveGoalBtn"
class="px-4 py-2.5 bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold text-xs rounded-xl transition flex items-center space-x-1 shadow-md shadow-emerald-500/20" class="px-4 py-2.5 bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold text-xs rounded-xl transition flex items-center space-x-1 shadow-md shadow-emerald-500/20 flex-shrink-0 cursor-pointer"
> >
<i data-lucide="check-circle-2" class="w-4 h-4"></i> <i data-lucide="check-circle-2" class="w-4 h-4"></i>
<span>Opslaan</span> <span>Opslaan</span>
@@ -190,101 +190,101 @@ $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(i
<div class="lg:col-span-7 space-y-6"> <div class="lg:col-span-7 space-y-6">
<!-- Focus Modus Timer --> <!-- Focus Modus Timer -->
<div class="bg-slate-900/80 border border-slate-800 rounded-2xl p-6 shadow-xl relative overflow-hidden backdrop-blur-sm"> <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">
<div class="flex items-center justify-between mb-4"> <div class="flex items-center justify-between mb-4">
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<div class="w-8 h-8 rounded-lg bg-emerald-500/10 text-emerald-400 flex items-center justify-center"> <div class="w-8 h-8 rounded-xl bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 flex items-center justify-center font-bold">
<i data-lucide="flame" class="w-4 h-4"></i> <i data-lucide="flame" class="w-4 h-4"></i>
</div> </div>
<div> <div>
<h3 class="text-sm font-bold text-white uppercase tracking-wider">Focus Modus</h3> <h3 class="text-sm font-bold text-slate-900 dark:text-white uppercase tracking-wider">Focus Modus</h3>
<p class="text-[11px] text-slate-400">Pomodoro & diepe concentratie</p> <p class="text-[11px] text-slate-500 dark:text-slate-400">Pomodoro & diepe concentratie</p>
</div> </div>
</div> </div>
<div class="flex bg-slate-950/80 p-1 rounded-xl border border-slate-800 text-xs"> <div class="flex bg-slate-100 dark:bg-slate-950/80 p-1 rounded-xl border border-slate-200 dark:border-slate-800 text-xs">
<button onclick="setTimerPreset(25)" id="btnPreset25" class="px-2.5 py-1 rounded-lg font-bold bg-emerald-500 text-slate-950 transition">25m Focus</button> <button onclick="setTimerPreset(25)" id="btnPreset25" class="px-2.5 py-1 rounded-lg font-bold bg-emerald-500 text-slate-950 transition">25m Focus</button>
<button onclick="setTimerPreset(50)" id="btnPreset50" class="px-2.5 py-1 rounded-lg text-slate-400 hover:text-slate-200 transition">50m Deep</button> <button onclick="setTimerPreset(50)" id="btnPreset50" class="px-2.5 py-1 rounded-lg text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-200 transition">50m Deep</button>
<button onclick="setTimerPreset(5)" id="btnPreset5" class="px-2.5 py-1 rounded-lg text-slate-400 hover:text-slate-200 transition">5m Pauze</button> <button onclick="setTimerPreset(5)" id="btnPreset5" class="px-2.5 py-1 rounded-lg text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-200 transition">5m Pauze</button>
</div> </div>
</div> </div>
<div class="text-center my-6"> <div class="text-center my-6">
<div id="timerDisplay" class="text-5xl sm:text-6xl font-black font-mono tracking-tight text-white mb-2">25:00</div> <div id="timerDisplay" class="text-5xl sm:text-6xl font-black font-mono tracking-tight text-slate-900 dark:text-white mb-2">25:00</div>
<div class="min-h-[22px] text-xs text-slate-400 truncate max-w-sm mx-auto flex items-center justify-center space-x-1"> <div class="min-h-[22px] text-xs text-slate-500 dark:text-slate-400 truncate max-w-sm mx-auto flex items-center justify-center space-x-1">
<span class="text-emerald-400 font-medium">Actieve focus:</span> <span class="text-emerald-600 dark:text-emerald-400 font-medium">Actieve focus:</span>
<span id="activeTaskDisplay" class="text-slate-200 font-semibold">Kies een taak hieronder</span> <span id="activeTaskDisplay" class="text-slate-800 dark:text-slate-200 font-semibold">Kies een taak hieronder</span>
</div> </div>
<div class="w-full bg-slate-950/80 h-2 rounded-full overflow-hidden mt-4 border border-slate-800/80"> <div class="w-full bg-slate-100 dark:bg-slate-950/80 h-2 rounded-full overflow-hidden mt-4 border border-slate-200 dark:border-slate-800/80">
<div id="timerProgress" class="h-full bg-gradient-to-r from-emerald-500 to-teal-400 transition-all duration-300 rounded-full" style="width: 0%"></div> <div id="timerProgress" class="h-full bg-gradient-to-r from-emerald-500 to-teal-400 transition-all duration-300 rounded-full" style="width: 0%"></div>
</div> </div>
</div> </div>
<div class="flex items-center justify-center space-x-3"> <div class="flex items-center justify-center space-x-3">
<button id="timerToggleBtn" onclick="toggleTimer()" class="flex items-center space-x-2 px-6 py-2.5 rounded-xl font-bold text-sm bg-emerald-500 hover:bg-emerald-600 text-slate-950 transition shadow-lg shadow-emerald-500/20"> <button id="timerToggleBtn" onclick="toggleTimer()" class="flex items-center space-x-2 px-6 py-2.5 rounded-xl font-bold text-sm bg-emerald-500 hover:bg-emerald-600 text-slate-950 transition shadow-lg shadow-emerald-500/20 cursor-pointer">
<i data-lucide="play" class="w-4 h-4 fill-current"></i> <i data-lucide="play" class="w-4 h-4 fill-current"></i>
<span id="timerToggleText">Start Focus</span> <span id="timerToggleText">Start Focus</span>
</button> </button>
<button onclick="resetTimer()" class="p-2.5 rounded-xl bg-slate-800/80 text-slate-400 hover:text-slate-200 hover:bg-slate-700 transition border border-slate-700/60" title="Reset"> <button onclick="resetTimer()" class="p-2.5 rounded-xl bg-slate-100 hover:bg-slate-200 dark:bg-slate-800/80 dark:hover:bg-slate-700 text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-200 transition border border-slate-200 dark:border-slate-700/60 cursor-pointer" title="Reset">
<i data-lucide="rotate-ccw" class="w-4 h-4"></i> <i data-lucide="rotate-ccw" class="w-4 h-4"></i>
</button> </button>
</div> </div>
</div> </div>
<!-- Takenlijst --> <!-- Takenlijst -->
<div class="bg-slate-900/80 border border-slate-800 rounded-2xl p-5 shadow-xl backdrop-blur-sm"> <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="flex items-center justify-between mb-4 pb-3 border-b border-slate-800"> <div class="flex items-center justify-between mb-4 pb-3 border-b border-slate-100 dark:border-slate-800">
<div> <div>
<h3 class="text-sm font-bold text-white uppercase tracking-wider flex items-center space-x-2"> <h3 class="text-sm font-bold text-slate-900 dark:text-white uppercase tracking-wider flex items-center space-x-2">
<span>Dagtaken & Prioriteiten</span> <span>Dagtaken & Prioriteiten</span>
<span class="text-xs font-normal text-slate-400">(<?= count($tasks) ?>)</span> <span class="text-xs font-normal text-slate-500 dark:text-slate-400">(<?= count($tasks) ?>)</span>
</h3> </h3>
</div> </div>
<button onclick="toggleAddTaskForm()" class="flex items-center space-x-1.5 px-3 py-1.5 rounded-xl bg-emerald-500 hover:bg-emerald-600 text-slate-950 text-xs font-bold transition shadow-md shadow-emerald-500/20"> <button onclick="toggleAddTaskForm()" class="flex items-center space-x-1.5 px-3 py-1.5 rounded-xl bg-emerald-500 hover:bg-emerald-600 text-slate-950 text-xs font-bold transition shadow-md shadow-emerald-500/20 cursor-pointer">
<i data-lucide="plus" class="w-4 h-4"></i> <i data-lucide="plus" class="w-4 h-4"></i>
<span>Nieuwe Taak</span> <span>Nieuwe Taak</span>
</button> </button>
</div> </div>
<!-- Nieuwe taak formulier (verborgen by default) --> <!-- Nieuwe taak formulier (verborgen by default) -->
<div id="addTaskForm" class="hidden mb-4 p-4 rounded-xl bg-slate-950/90 border border-emerald-500/30 space-y-3"> <div id="addTaskForm" class="hidden mb-4 p-4 rounded-2xl bg-slate-50 dark:bg-slate-950/90 border border-emerald-500/30 space-y-3 transition">
<div> <div>
<label class="block text-[11px] font-medium text-slate-400 mb-1">Taaktitel</label> <label class="block text-[11px] font-medium text-slate-600 dark:text-slate-400 mb-1">Taaktitel</label>
<input type="text" id="newTaskTitle" placeholder="Wat moet er vandaag gedaan worden?" class="w-full bg-slate-900 border border-slate-800 rounded-lg px-3 py-2 text-white text-xs placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-emerald-500"> <input type="text" id="newTaskTitle" placeholder="Wat moet er vandaag gedaan worden?" class="w-full bg-white dark:bg-slate-900 border border-slate-300 dark:border-slate-800 rounded-xl px-3 py-2 text-slate-900 dark:text-white text-xs placeholder-slate-400 dark:placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-emerald-500">
</div> </div>
<div class="grid grid-cols-2 gap-3"> <div class="grid grid-cols-2 gap-3">
<div> <div>
<label class="block text-[11px] font-medium text-slate-400 mb-1">Prioriteit</label> <label class="block text-[11px] font-medium text-slate-600 dark:text-slate-400 mb-1">Prioriteit</label>
<select id="newTaskPriority" class="w-full bg-slate-900 border border-slate-800 rounded-lg px-2.5 py-1.5 text-white text-xs focus:outline-none"> <select id="newTaskPriority" class="w-full bg-white dark:bg-slate-900 border border-slate-300 dark:border-slate-800 rounded-xl px-2.5 py-1.5 text-slate-900 dark:text-white text-xs focus:outline-none">
<option value="P1">P1 - Brandend / Hoogste Focus</option> <option value="P1">P1 - Brandend / Hoogste Focus</option>
<option value="P2" selected>P2 - Belangrijk (Standaard)</option> <option value="P2" selected>P2 - Belangrijk (Standaard)</option>
<option value="P3">P3 - Regulier / Lage druk</option> <option value="P3">P3 - Regulier / Lage druk</option>
</select> </select>
</div> </div>
<div> <div>
<label class="block text-[11px] font-medium text-slate-400 mb-1">Tijdblok (Starttijd)</label> <label class="block text-[11px] font-medium text-slate-600 dark:text-slate-400 mb-1">Tijdblok (Starttijd)</label>
<input type="text" id="newTaskTime" placeholder="Bijv. 09:30" class="w-full bg-slate-900 border border-slate-800 rounded-lg px-2.5 py-1.5 text-white text-xs font-mono focus:outline-none"> <input type="text" id="newTaskTime" placeholder="Bijv. 09:30" class="w-full bg-white dark:bg-slate-900 border border-slate-300 dark:border-slate-800 rounded-xl px-2.5 py-1.5 text-slate-900 dark:text-white text-xs font-mono focus:outline-none">
</div> </div>
</div> </div>
<div class="flex space-x-2 pt-1"> <div class="flex space-x-2 pt-1">
<button onclick="submitNewTask()" class="px-4 py-1.5 bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold rounded-lg text-xs transition">Opslaan</button> <button onclick="submitNewTask()" class="px-4 py-1.5 bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold rounded-lg text-xs transition cursor-pointer">Opslaan</button>
<button onclick="toggleAddTaskForm()" class="px-3 py-1.5 bg-slate-800 hover:bg-slate-700 text-slate-400 rounded-lg text-xs transition">Annuleren</button> <button onclick="toggleAddTaskForm()" class="px-3 py-1.5 bg-slate-200 hover:bg-slate-300 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-400 rounded-lg text-xs transition cursor-pointer">Annuleren</button>
</div> </div>
</div> </div>
<!-- Taken weergave --> <!-- Taken weergave -->
<div class="space-y-2" id="tasksContainer"> <div class="space-y-2" id="tasksContainer">
<?php if (empty($tasks)): ?> <?php if (empty($tasks)): ?>
<div class="text-center py-8 text-slate-500 text-xs"> <div class="text-center py-8 text-slate-400 dark:text-slate-500 text-xs">
Nog geen taken gepland voor vandaag. Klik op 'Nieuwe Taak' of importeer een Jira ticket hieronder. Nog geen taken gepland voor vandaag. Klik op 'Nieuwe Taak' of importeer een Jira ticket hieronder.
</div> </div>
<?php else: ?> <?php else: ?>
<?php foreach ($tasks as $task): ?> <?php foreach ($tasks as $task): ?>
<div class="group flex items-center justify-between p-3 rounded-xl border <?= $task['is_completed'] ? 'bg-slate-950/30 border-slate-900 opacity-60' : 'bg-slate-950/60 border-slate-800 hover:border-slate-700' ?> transition" id="task-row-<?= $task['id'] ?>"> <div class="group flex items-center justify-between p-3 rounded-2xl border <?= $task['is_completed'] ? 'bg-slate-50/50 dark:bg-slate-950/30 border-slate-200 dark:border-slate-900 opacity-60' : 'bg-slate-50 dark:bg-slate-950/60 border-slate-200 dark:border-slate-800 hover:border-slate-300 dark:hover:border-slate-700' ?> transition shadow-sm" id="task-row-<?= $task['id'] ?>">
<div class="flex items-center space-x-3 truncate mr-2"> <div class="flex items-center space-x-3 truncate mr-2">
<button onclick="toggleTask(<?= $task['id'] ?>, <?= $task['is_completed'] ? 0 : 1 ?>)" class="w-5 h-5 rounded-lg border flex items-center justify-center transition <?= $task['is_completed'] ? 'bg-emerald-500 border-emerald-500 text-slate-950 font-bold' : 'border-slate-700 hover:border-emerald-400 bg-slate-900' ?>"> <button onclick="toggleTask(<?= $task['id'] ?>, <?= $task['is_completed'] ? 0 : 1 ?>)" class="w-5 h-5 rounded-lg border flex items-center justify-center transition <?= $task['is_completed'] ? 'bg-emerald-500 border-emerald-500 text-slate-950 font-bold' : 'border-slate-300 dark:border-slate-700 hover:border-emerald-500 bg-white dark:bg-slate-900' ?>">
<?php if ($task['is_completed']): ?> <?php if ($task['is_completed']): ?>
<i data-lucide="check" class="w-3.5 h-3.5 stroke-[3]"></i> <i data-lucide="check" class="w-3.5 h-3.5 stroke-[3]"></i>
<?php endif; ?> <?php endif; ?>
@@ -293,24 +293,24 @@ $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(i
<div class="truncate"> <div class="truncate">
<div class="flex items-center space-x-1.5 truncate"> <div class="flex items-center space-x-1.5 truncate">
<?php if ($task['source'] === 'JIRA'): ?> <?php if ($task['source'] === 'JIRA'): ?>
<span class="px-1.5 py-0.2 rounded bg-sky-500/10 border border-sky-500/20 text-sky-400 font-mono text-[9px] font-bold"> <span class="px-1.5 py-0.2 rounded bg-sky-500/10 border border-sky-500/20 text-sky-600 dark:text-sky-400 font-mono text-[9px] font-bold">
JIRA JIRA
</span> </span>
<?php endif; ?> <?php endif; ?>
<span class="text-xs font-medium truncate <?= $task['is_completed'] ? 'line-through text-slate-500' : 'text-slate-200' ?>"> <span class="text-xs font-medium truncate <?= $task['is_completed'] ? 'line-through text-slate-400 dark:text-slate-500' : 'text-slate-800 dark:text-slate-200' ?>">
<?= htmlspecialchars($task['title']) ?> <?= htmlspecialchars($task['title']) ?>
</span> </span>
</div> </div>
<div class="flex items-center space-x-2 mt-0.5"> <div class="flex items-center space-x-2 mt-0.5">
<?php if (!empty($task['time_block_start'])): ?> <?php if (!empty($task['time_block_start'])): ?>
<span class="text-[10px] text-slate-400 font-mono flex items-center space-x-1"> <span class="text-[10px] text-slate-500 dark:text-slate-400 font-mono flex items-center space-x-1">
<i data-lucide="clock" class="w-2.5 h-2.5"></i> <i data-lucide="clock" class="w-2.5 h-2.5"></i>
<span><?= htmlspecialchars($task['time_block_start']) ?></span> <span><?= htmlspecialchars($task['time_block_start']) ?></span>
</span> </span>
<?php endif; ?> <?php endif; ?>
<?php if (!empty($task['external_url'])): ?> <?php if (!empty($task['external_url'])): ?>
<a href="<?= htmlspecialchars($task['external_url']) ?>" target="_blank" class="text-[10px] text-sky-400 hover:underline flex items-center space-x-0.5"> <a href="<?= htmlspecialchars($task['external_url']) ?>" target="_blank" class="text-[10px] text-sky-600 dark:text-sky-400 hover:underline flex items-center space-x-0.5">
<span>Open in Jira</span> <span>Open in Jira</span>
<i data-lucide="external-link" class="w-2.5 h-2.5"></i> <i data-lucide="external-link" class="w-2.5 h-2.5"></i>
</a> </a>
@@ -320,17 +320,17 @@ $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(i
</div> </div>
<div class="flex items-center space-x-2 flex-shrink-0"> <div class="flex items-center space-x-2 flex-shrink-0">
<span class="text-[10px] font-bold px-2 py-0.5 rounded-full <?= $task['priority'] === 'P1' ? 'bg-red-500/20 text-red-400 border border-red-500/30' : ($task['priority'] === 'P2' ? 'bg-amber-500/20 text-amber-400 border border-amber-500/30' : 'bg-slate-800 text-slate-400') ?>"> <span class="text-[10px] font-bold px-2 py-0.5 rounded-full <?= $task['priority'] === 'P1' ? 'bg-red-500/15 text-red-700 dark:text-red-400 border border-red-500/30' : ($task['priority'] === 'P2' ? 'bg-amber-500/15 text-amber-700 dark:text-amber-400 border border-amber-500/30' : 'bg-slate-200 dark:bg-slate-800 text-slate-600 dark:text-slate-400') ?>">
<?= htmlspecialchars($task['priority']) ?> <?= htmlspecialchars($task['priority']) ?>
</span> </span>
<?php if (!$task['is_completed']): ?> <?php if (!$task['is_completed']): ?>
<button onclick="selectFocusTask('<?= htmlspecialchars(addslashes($task['title'])) ?>')" title="Koppel aan Focus Timer" class="p-1.5 rounded-lg text-slate-400 hover:text-emerald-400 hover:bg-emerald-500/10 transition"> <button onclick="selectFocusTask('<?= htmlspecialchars(addslashes($task['title'])) ?>')" title="Koppel aan Focus Timer" class="p-1.5 rounded-lg text-slate-400 hover:text-emerald-600 dark:hover:text-emerald-400 hover:bg-emerald-500/10 transition">
<i data-lucide="flame" class="w-3.5 h-3.5"></i> <i data-lucide="flame" class="w-3.5 h-3.5"></i>
</button> </button>
<?php endif; ?> <?php endif; ?>
<button onclick="deleteTask(<?= $task['id'] ?>)" title="Verwijderen" class="p-1.5 rounded-lg text-slate-600 hover:text-red-400 hover:bg-red-500/10 opacity-0 group-hover:opacity-100 transition"> <button onclick="deleteTask(<?= $task['id'] ?>)" title="Verwijderen" class="p-1.5 rounded-lg text-slate-400 hover:text-red-600 dark:hover:text-red-400 hover:bg-red-500/10 opacity-0 group-hover:opacity-100 transition">
<i data-lucide="trash-2" class="w-3.5 h-3.5"></i> <i data-lucide="trash-2" class="w-3.5 h-3.5"></i>
</button> </button>
</div> </div>
@@ -341,38 +341,38 @@ $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(i
</div> </div>
<!-- Jira Snelle Import Widget --> <!-- Jira Snelle Import Widget -->
<div id="jiraPanel" class="bg-slate-900/80 border border-slate-800 rounded-2xl p-5 shadow-xl backdrop-blur-sm"> <div id="jiraPanel" 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="flex items-center justify-between pb-3 border-b border-slate-800 mb-3"> <div class="flex items-center justify-between pb-3 border-b border-slate-100 dark:border-slate-800 mb-3">
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<i data-lucide="trello" class="w-4 h-4 text-sky-400"></i> <i data-lucide="trello" class="w-4 h-4 text-sky-500"></i>
<h3 class="text-sm font-bold text-white uppercase tracking-wider"> <h3 class="text-sm font-bold text-slate-900 dark:text-white uppercase tracking-wider">
Mijn Jira Tickets Mijn Jira Tickets
</h3> </h3>
<span class="px-2 py-0.5 rounded-full text-[10px] font-bold <?= $isJiraLive ? 'bg-sky-500/20 text-sky-400 border border-sky-500/30' : 'bg-slate-800 text-slate-400' ?>"> <span class="px-2 py-0.5 rounded-full text-[10px] font-bold <?= $isJiraLive ? 'bg-sky-500/15 text-sky-700 dark:text-sky-400 border border-sky-500/30' : 'bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400' ?>">
<?= count($jiraIssues) ?> <?= count($jiraIssues) ?>
</span> </span>
</div> </div>
<a href="/profile.php" class="text-xs text-slate-400 hover:text-sky-300 transition flex items-center space-x-1"> <a href="/profile.php" class="text-xs text-slate-500 dark:text-slate-400 hover:text-sky-600 dark:hover:text-sky-300 transition flex items-center space-x-1">
<span>Beheren</span> <span>Beheren</span>
<i data-lucide="chevron-right" class="w-3.5 h-3.5"></i> <i data-lucide="chevron-right" class="w-3.5 h-3.5"></i>
</a> </a>
</div> </div>
<?php if (empty($jiraIssues)): ?> <?php if (empty($jiraIssues)): ?>
<div class="text-center py-6 text-slate-500 text-xs"> <div class="text-center py-6 text-slate-400 dark:text-slate-500 text-xs">
Geen openstaande tickets gevonden in Jira. Geen openstaande tickets gevonden in Jira.
</div> </div>
<?php else: ?> <?php else: ?>
<div class="space-y-2 max-h-64 overflow-y-auto pr-1"> <div class="space-y-2 max-h-64 overflow-y-auto pr-1">
<?php foreach (array_slice($jiraIssues, 0, 6) as $issue): ?> <?php foreach (array_slice($jiraIssues, 0, 6) as $issue): ?>
<div class="flex items-center justify-between p-2.5 rounded-xl bg-slate-950/60 border border-slate-800/80 hover:border-slate-700 transition"> <div class="flex items-center justify-between p-2.5 rounded-2xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800/80 hover:border-slate-300 dark:hover:border-slate-700 transition shadow-sm">
<div class="truncate mr-2"> <div class="truncate mr-2">
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<span class="font-mono text-[10px] font-bold text-sky-400 bg-sky-500/10 px-1.5 py-0.5 rounded"> <span class="font-mono text-[10px] font-bold text-sky-600 dark:text-sky-400 bg-sky-500/10 px-1.5 py-0.5 rounded">
<?= htmlspecialchars($issue['key']) ?> <?= htmlspecialchars($issue['key']) ?>
</span> </span>
<span class="text-xs font-semibold text-white truncate"> <span class="text-xs font-semibold text-slate-900 dark:text-white truncate">
<?= htmlspecialchars($issue['summary']) ?> <?= htmlspecialchars($issue['summary']) ?>
</span> </span>
</div> </div>
@@ -383,7 +383,7 @@ $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(i
<button <button
onclick="quickImportJira(this, '<?= htmlspecialchars(addslashes($issue['summary'])) ?>', '<?= htmlspecialchars($issue['key']) ?>', '<?= htmlspecialchars(addslashes($issue['url'] ?? '')) ?>')" onclick="quickImportJira(this, '<?= htmlspecialchars(addslashes($issue['summary'])) ?>', '<?= htmlspecialchars($issue['key']) ?>', '<?= htmlspecialchars(addslashes($issue['url'] ?? '')) ?>')"
class="flex items-center space-x-1 text-[11px] font-bold text-emerald-400 hover:text-emerald-300 bg-emerald-500/10 hover:bg-emerald-500/20 border border-emerald-500/20 px-2 py-1 rounded-lg transition flex-shrink-0" class="flex items-center space-x-1 text-[11px] font-bold text-emerald-700 dark:text-emerald-400 hover:text-emerald-800 dark:hover:text-emerald-300 bg-emerald-500/10 hover:bg-emerald-500/20 border border-emerald-500/20 px-2 py-1 rounded-lg transition flex-shrink-0 cursor-pointer"
title="Plan in als dagtaak" title="Plan in als dagtaak"
> >
<i data-lucide="plus" class="w-3 h-3"></i> <i data-lucide="plus" class="w-3 h-3"></i>
@@ -396,34 +396,34 @@ $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(i
</div> </div>
<!-- Dagnotities & Reflectie --> <!-- Dagnotities & Reflectie -->
<div class="bg-slate-900/80 border border-slate-800 rounded-2xl p-5 shadow-xl backdrop-blur-sm"> <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="flex items-center space-x-2 mb-3"> <div class="flex items-center space-x-2 mb-3">
<i data-lucide="book-open" class="w-4 h-4 text-emerald-400"></i> <i data-lucide="book-open" class="w-4 h-4 text-emerald-600 dark:text-emerald-400"></i>
<h3 class="text-sm font-bold text-white uppercase tracking-wider">Dagnotities & Kladblok</h3> <h3 class="text-sm font-bold text-slate-900 dark:text-white uppercase tracking-wider">Dagnotities & Kladblok</h3>
</div> </div>
<textarea <textarea
id="dailyNotesInput" id="dailyNotesInput"
rows="3" rows="3"
placeholder="Belangrijke aantekeningen, reflecties of snelle memo's voor vandaag..." placeholder="Belangrijke aantekeningen, reflecties of snelle memo's voor vandaag..."
onblur="saveGoal()" onblur="saveGoal()"
class="w-full bg-slate-950/70 border border-slate-800 rounded-xl p-3 text-white text-xs placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-emerald-500 resize-none transition" class="w-full bg-slate-50 dark:bg-slate-950/70 border border-slate-300 dark:border-slate-800 rounded-2xl p-3 text-slate-900 dark:text-white text-xs placeholder-slate-400 dark:placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-emerald-500 resize-none transition"
><?= htmlspecialchars($dailyPlan['notes'] ?? '') ?></textarea> ><?= htmlspecialchars($dailyPlan['notes'] ?? '') ?></textarea>
</div> </div>
</div> </div>
<!-- Rechter kolom: Timeblocking & Outlook Tijdlijn --> <!-- Rechter kolom: Timeblocking & Outlook Tijdlijn -->
<div class="lg:col-span-5 space-y-6"> <div class="lg:col-span-5 space-y-6">
<div class="bg-slate-900/80 border border-slate-800 rounded-2xl p-5 shadow-xl backdrop-blur-sm"> <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="flex items-center justify-between mb-4 pb-3 border-b border-slate-800"> <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"> <div class="flex items-center space-x-2">
<i data-lucide="clock" class="w-5 h-5 text-emerald-400"></i> <i data-lucide="clock" class="w-5 h-5 text-emerald-600 dark:text-emerald-400"></i>
<h3 class="text-sm font-bold text-white uppercase tracking-wider">Tijdlijn & Time-blocking</h3> <h3 class="text-sm font-bold text-slate-900 dark:text-white uppercase tracking-wider">Tijdlijn & Time-blocking</h3>
</div> </div>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<?php if ($isOutlookConnected): ?> <?php if ($isOutlookConnected): ?>
<span class="px-2 py-0.5 rounded bg-blue-500/10 border border-blue-500/20 text-blue-400 text-[10px] font-bold">Outlook 365</span> <span class="px-2 py-0.5 rounded bg-blue-500/10 border border-blue-500/20 text-blue-700 dark:text-blue-400 text-[10px] font-bold">Outlook 365</span>
<?php endif; ?> <?php endif; ?>
<span class="text-xs text-slate-400 font-mono"><?= $hours[0] ?> – <?= end($hours) ?></span> <span class="text-xs text-slate-500 dark:text-slate-400 font-mono"><?= $hours[0] ?> – <?= end($hours) ?></span>
</div> </div>
</div> </div>
@@ -442,17 +442,17 @@ $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(i
return !empty($t['time_block_start']) && (int)explode(':', $t['time_block_start'])[0] === $hourInt; 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-800/40 pb-2 last:border-0"> <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-400 pt-1 flex-shrink-0"> <div class="w-14 text-xs font-mono font-medium text-slate-500 dark:text-slate-400 pt-1 flex-shrink-0">
<?= $hour ?> <?= $hour ?>
</div> </div>
<div class="flex-1 space-y-1.5"> <div class="flex-1 space-y-1.5">
<!-- Outlook meetings --> <!-- Outlook meetings -->
<?php foreach ($slotEvents as $evt): ?> <?php foreach ($slotEvents as $evt): ?>
<div class="flex items-center justify-between p-2 rounded-xl bg-blue-950/50 border border-blue-800/60 text-blue-100 text-xs shadow-sm"> <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"> <div class="flex items-center space-x-2 truncate mr-2">
<span class="px-1.5 py-0.5 rounded bg-blue-500/20 text-blue-400 font-mono text-[10px] font-bold"> <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">
<?= htmlspecialchars($evt['start']) ?> - <?= htmlspecialchars($evt['end']) ?> <?= htmlspecialchars($evt['start']) ?> - <?= htmlspecialchars($evt['end']) ?>
</span> </span>
<span class="font-semibold truncate" title="<?= htmlspecialchars($evt['subject']) ?>"> <span class="font-semibold truncate" title="<?= htmlspecialchars($evt['subject']) ?>">
@@ -460,7 +460,7 @@ $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(i
</span> </span>
</div> </div>
<?php if (!empty($evt['meeting_url'])): ?> <?php if (!empty($evt['meeting_url'])): ?>
<a href="<?= htmlspecialchars($evt['meeting_url']) ?>" target="_blank" class="flex items-center space-x-1 text-[10px] text-blue-300 hover:text-white bg-blue-600/30 hover:bg-blue-600/50 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">
<i data-lucide="video" class="w-3 h-3"></i> <i data-lucide="video" class="w-3 h-3"></i>
<span>Deelnemen</span> <span>Deelnemen</span>
</a> </a>
@@ -470,21 +470,21 @@ $formattedDate = $dutchDays[date('w')] . ' ' . date('j') . ' ' . $dutchMonths[(i
<!-- Geplande taken --> <!-- Geplande taken -->
<?php foreach ($slotTasks as $t): ?> <?php foreach ($slotTasks as $t): ?>
<div class="flex items-center justify-between p-2 rounded-xl border text-xs <?= $t['is_completed'] ? 'bg-slate-900/40 border-slate-800 text-slate-500 line-through' : 'bg-emerald-950/30 border-emerald-800/40 text-emerald-100' ?>"> <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"> <div class="flex items-center space-x-2 truncate mr-2">
<span class="px-1.5 py-0.5 rounded bg-emerald-500/20 text-emerald-400 font-mono text-[10px] font-bold"> <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">
<?= htmlspecialchars($t['time_block_start']) ?> <?= htmlspecialchars($t['time_block_start']) ?>
</span> </span>
<span class="font-semibold truncate"><?= htmlspecialchars($t['title']) ?></span> <span class="font-semibold truncate"><?= htmlspecialchars($t['title']) ?></span>
</div> </div>
<span class="text-[10px] font-bold px-1.5 py-0.5 rounded bg-emerald-500/20 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">
<?= $t['priority'] ?> <?= $t['priority'] ?>
</span> </span>
</div> </div>
<?php endforeach; ?> <?php endforeach; ?>
<?php if (empty($slotEvents) && empty($slotTasks)): ?> <?php if (empty($slotEvents) && empty($slotTasks)): ?>
<button onclick="quickSchedule('<?= $hour ?>')" class="w-full text-left py-1 px-2 rounded-lg border border-dashed border-transparent hover:border-slate-800 hover:bg-slate-950/40 text-slate-600 hover:text-slate-400 text-xs transition"> <button onclick="quickSchedule('<?= $hour ?>')" class="w-full text-left py-1 px-2 rounded-lg border border-dashed border-transparent hover:border-slate-300 dark:hover:border-slate-800 hover:bg-slate-50 dark:hover:bg-slate-950/40 text-slate-400 dark:text-slate-600 hover:text-slate-700 dark:hover:text-slate-400 text-xs transition cursor-pointer">
+ Plan taak om <?= $hour ?> + Plan taak om <?= $hour ?>
</button> </button>
<?php endif; ?> <?php endif; ?>
@@ -522,9 +522,11 @@ function setTimerPreset(minutes) {
updateTimerDisplay(); updateTimerDisplay();
document.getElementById('timerToggleText').innerText = 'Start Focus'; document.getElementById('timerToggleText').innerText = 'Start Focus';
document.getElementById('btnPreset25').className = minutes === 25 ? 'px-2.5 py-1 rounded-lg font-bold bg-emerald-500 text-slate-950' : 'px-2.5 py-1 rounded-lg text-slate-400 hover:text-slate-200'; const inactiveClass = 'px-2.5 py-1 rounded-lg text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-200 transition';
document.getElementById('btnPreset50').className = minutes === 50 ? 'px-2.5 py-1 rounded-lg font-bold bg-emerald-500 text-slate-950' : 'px-2.5 py-1 rounded-lg text-slate-400 hover:text-slate-200'; const activeClass = 'px-2.5 py-1 rounded-lg font-bold bg-emerald-500 text-slate-950 transition';
document.getElementById('btnPreset5').className = minutes === 5 ? 'px-2.5 py-1 rounded-lg font-bold bg-teal-500 text-slate-950' : 'px-2.5 py-1 rounded-lg text-slate-400 hover:text-slate-200'; document.getElementById('btnPreset25').className = minutes === 25 ? activeClass : inactiveClass;
document.getElementById('btnPreset50').className = minutes === 50 ? activeClass : inactiveClass;
document.getElementById('btnPreset5').className = minutes === 5 ? activeClass : inactiveClass;
} }
function toggleTimer() { function toggleTimer() {
+290 -115
View File
@@ -198,47 +198,50 @@ $appConfig = microsoft_get_app_config();
// Notificatie-instellingen // Notificatie-instellingen
$notifSettings = get_user_notification_settings($userId); $notifSettings = get_user_notification_settings($userId);
// Thema ophalen
$userTheme = get_user_theme($userId);
$pageTitle = 'Mijn Profiel & Koppelingen — Fociz'; $pageTitle = 'Mijn Profiel & Koppelingen — Fociz';
require_once __DIR__ . '/includes/header.php'; require_once __DIR__ . '/includes/header.php';
?> ?>
<div class="space-y-8 max-w-5xl mx-auto pb-12"> <div class="space-y-8 max-w-5xl mx-auto pb-12">
<!-- Profiel Header Card --> <!-- Profiel Header Card -->
<div class="relative overflow-hidden bg-slate-900/90 border border-slate-800 rounded-3xl p-6 sm:p-8 shadow-2xl backdrop-blur-xl"> <div class="relative overflow-hidden bg-white dark:bg-slate-900/90 border border-slate-200 dark:border-slate-800 rounded-3xl p-6 sm:p-8 shadow-sm dark:shadow-2xl backdrop-blur-xl transition">
<div class="absolute -top-20 -right-20 w-72 h-72 bg-emerald-500/10 rounded-full blur-3xl pointer-events-none"></div> <div class="absolute -top-20 -right-20 w-72 h-72 bg-emerald-500/10 rounded-full blur-3xl pointer-events-none"></div>
<div class="relative z-10 flex flex-col sm:flex-row sm:items-center justify-between gap-6"> <div class="relative z-10 flex flex-col sm:flex-row sm:items-center justify-between gap-6">
<div class="flex items-center space-x-4 sm:space-x-5"> <div class="flex items-center space-x-4 sm:space-x-5">
<div class="w-16 h-16 sm:w-20 sm:h-20 rounded-2xl bg-gradient-to-tr from-emerald-600 to-teal-400 p-0.5 shadow-xl shadow-emerald-500/20 flex-shrink-0"> <div class="w-16 h-16 sm:w-20 sm:h-20 rounded-2xl bg-gradient-to-tr from-emerald-600 to-teal-400 p-0.5 shadow-xl shadow-emerald-500/20 flex-shrink-0">
<div class="w-full h-full rounded-2xl bg-slate-950 flex items-center justify-center font-black text-2xl sm:text-3xl text-emerald-400 uppercase"> <div class="w-full h-full rounded-2xl bg-white dark:bg-slate-950 flex items-center justify-center font-black text-2xl sm:text-3xl text-emerald-600 dark:text-emerald-400 uppercase">
<?= strtoupper(substr($userProfile['name'], 0, 1)) ?> <?= strtoupper(substr($userProfile['name'], 0, 1)) ?>
</div> </div>
</div> </div>
<div class="space-y-1"> <div class="space-y-1">
<div class="flex flex-wrap items-center gap-2"> <div class="flex flex-wrap items-center gap-2">
<h1 class="text-2xl sm:text-3xl font-black text-white tracking-tight"> <h1 class="text-2xl sm:text-3xl font-black text-slate-900 dark:text-white tracking-tight">
<?= htmlspecialchars($userProfile['name']) ?> <?= htmlspecialchars($userProfile['name']) ?>
</h1> </h1>
<?php if ($userProfile['role'] === 'ADMIN'): ?> <?php if ($userProfile['role'] === 'ADMIN'): ?>
<span class="px-2.5 py-0.5 rounded-full bg-emerald-500/20 border border-emerald-500/40 text-emerald-400 text-xs font-bold flex items-center space-x-1"> <span class="px-2.5 py-0.5 rounded-full bg-emerald-500/15 border border-emerald-500/30 text-emerald-700 dark:text-emerald-400 text-xs font-bold flex items-center space-x-1">
<i data-lucide="shield" class="w-3 h-3"></i> <i data-lucide="shield" class="w-3 h-3"></i>
<span>Beheerder</span> <span>Beheerder</span>
</span> </span>
<?php else: ?> <?php else: ?>
<span class="px-2.5 py-0.5 rounded-full bg-blue-500/20 border border-blue-500/40 text-blue-400 text-xs font-bold flex items-center space-x-1"> <span class="px-2.5 py-0.5 rounded-full bg-blue-500/15 border border-blue-500/30 text-blue-700 dark:text-blue-400 text-xs font-bold flex items-center space-x-1">
<i data-lucide="user" class="w-3 h-3"></i> <i data-lucide="user" class="w-3 h-3"></i>
<span>Collega</span> <span>Collega</span>
</span> </span>
<?php endif; ?> <?php endif; ?>
<span class="px-2.5 py-0.5 rounded-full bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 text-xs font-semibold flex items-center space-x-1"> <span class="px-2.5 py-0.5 rounded-full bg-emerald-500/10 border border-emerald-500/20 text-emerald-700 dark:text-emerald-400 text-xs font-semibold flex items-center space-x-1">
<i data-lucide="shield-check" class="w-3 h-3"></i> <i data-lucide="shield-check" class="w-3 h-3"></i>
<span>2FA Beveiligd</span> <span>2FA Beveiligd</span>
</span> </span>
</div> </div>
<p class="text-xs text-slate-400 flex items-center space-x-2"> <p class="text-xs text-slate-500 dark:text-slate-400 flex items-center space-x-2">
<span><?= htmlspecialchars($userProfile['email']) ?></span> <span><?= htmlspecialchars($userProfile['email']) ?></span>
<span>•</span> <span>•</span>
<span>Lid sinds <?= date('d-m-Y', strtotime($userProfile['created_at'])) ?></span> <span>Lid sinds <?= date('d-m-Y', strtotime($userProfile['created_at'])) ?></span>
@@ -248,8 +251,8 @@ require_once __DIR__ . '/includes/header.php';
<?php if ($userProfile['role'] === 'ADMIN'): ?> <?php if ($userProfile['role'] === 'ADMIN'): ?>
<div class="flex-shrink-0"> <div class="flex-shrink-0">
<a href="/admin.php" class="inline-flex items-center space-x-2 px-4 py-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-slate-200 border border-slate-700 text-xs font-semibold transition shadow-md"> <a href="/admin.php" class="inline-flex items-center space-x-2 px-4 py-2.5 rounded-xl bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-800 dark:text-slate-200 border border-slate-200 dark:border-slate-700 text-xs font-semibold transition shadow-sm">
<i data-lucide="shield-alert" class="w-4 h-4 text-emerald-400"></i> <i data-lucide="shield-alert" class="w-4 h-4 text-emerald-600 dark:text-emerald-400"></i>
<span>Systeembeheer Openen</span> <span>Systeembeheer Openen</span>
</a> </a>
</div> </div>
@@ -259,45 +262,180 @@ require_once __DIR__ . '/includes/header.php';
<!-- Meldingen Banner --> <!-- Meldingen Banner -->
<?php if ($message): ?> <?php if ($message): ?>
<div class="p-4 rounded-2xl flex items-start space-x-3 text-sm animate-in fade-in duration-200 <?= $messageType === 'success' ? 'bg-emerald-500/10 border border-emerald-500/30 text-emerald-200' : 'bg-red-500/10 border border-red-500/30 text-red-200' ?>"> <div class="p-4 rounded-2xl flex items-start space-x-3 text-sm animate-in fade-in duration-200 <?= $messageType === 'success' ? 'bg-emerald-500/10 border border-emerald-500/30 text-emerald-800 dark:text-emerald-200' : 'bg-red-500/10 border border-red-500/30 text-red-800 dark:text-red-200' ?>">
<i data-lucide="<?= $messageType === 'success' ? 'check-circle-2' : 'alert-triangle' ?>" class="w-5 h-5 flex-shrink-0 mt-0.5 <?= $messageType === 'success' ? 'text-emerald-400' : 'text-red-400' ?>"></i> <i data-lucide="<?= $messageType === 'success' ? 'check-circle-2' : 'alert-triangle' ?>" class="w-5 h-5 flex-shrink-0 mt-0.5 <?= $messageType === 'success' ? 'text-emerald-600 dark:text-emerald-400' : 'text-red-600 dark:text-red-400' ?>"></i>
<div class="flex-1 font-medium"><?= htmlspecialchars($message) ?></div> <div class="flex-1 font-medium"><?= htmlspecialchars($message) ?></div>
</div> </div>
<?php endif; ?> <?php endif; ?>
<!-- Sectie 1: Mijn Microsoft 365 Outlook Agenda --> <!-- Sectie 0: Weergave & Thema Instellingen (Dark & Light mode) -->
<div class="bg-slate-900/80 border border-slate-800 rounded-3xl p-6 sm:p-7 shadow-xl"> <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 transition">
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 pb-6 border-b border-slate-800/80"> <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-3 pb-6 border-b border-slate-100 dark:border-slate-800/80">
<div class="flex items-center space-x-3.5"> <div class="flex items-center space-x-3.5">
<div class="w-12 h-12 rounded-2xl bg-blue-500/10 border border-blue-500/20 flex items-center justify-center text-blue-400 font-bold shadow-md"> <div class="w-12 h-12 rounded-2xl bg-purple-500/10 border border-purple-500/20 flex items-center justify-center text-purple-600 dark:text-purple-400 font-bold shadow-sm">
<i data-lucide="palette" class="w-6 h-6"></i>
</div>
<div>
<div class="flex items-center space-x-2">
<h2 class="text-lg font-bold text-slate-900 dark:text-white tracking-tight">Weergave & Thema</h2>
<span id="themeStatusBadge" class="px-2.5 py-0.5 rounded-full bg-emerald-500/15 border border-emerald-500/30 text-emerald-700 dark:text-emerald-400 text-[10px] font-bold">
Actief: <?= ucfirst($userTheme) ?>
</span>
</div>
<p class="text-xs text-slate-500 dark:text-slate-400">Kies uw gewenste uiterlijk: rustig donker, kraakhelder licht of synchroniseer automatisch met uw apparaat.</p>
</div>
</div>
</div>
<div class="mt-6 grid grid-cols-1 sm:grid-cols-3 gap-4">
<!-- Optie 1: Donker (Dark) -->
<button type="button" onclick="selectThemePreference('dark')" id="themeBtn-dark" class="theme-card relative text-left p-4 rounded-2xl border-2 transition duration-150 flex flex-col justify-between group hover:shadow-md cursor-pointer bg-slate-900 border-slate-700 text-white">
<div class="w-full h-24 rounded-xl bg-slate-950 p-2.5 border border-slate-800 mb-3 flex flex-col justify-between overflow-hidden shadow-inner">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-1.5">
<span class="w-2 h-2 rounded-full bg-red-400/80"></span>
<span class="w-2 h-2 rounded-full bg-amber-400/80"></span>
<span class="w-2 h-2 rounded-full bg-emerald-400/80"></span>
</div>
<span class="text-[9px] font-mono text-slate-500">fociz.dark</span>
</div>
<div class="space-y-1.5">
<div class="h-2 w-3/4 bg-emerald-500/40 rounded"></div>
<div class="h-2 w-1/2 bg-slate-800 rounded"></div>
</div>
<div class="flex space-x-1">
<div class="h-3 w-8 bg-slate-800 rounded"></div>
<div class="h-3 w-10 bg-emerald-500/20 rounded"></div>
</div>
</div>
<div>
<div class="flex items-center justify-between">
<span class="text-sm font-bold text-white flex items-center space-x-1.5">
<i data-lucide="moon" class="w-4 h-4 text-purple-400"></i>
<span>Donkere Modus</span>
</span>
<span id="themeCheck-dark" class="theme-check hidden w-5 h-5 rounded-full bg-emerald-500 text-slate-950 items-center justify-center">
<i data-lucide="check" class="w-3.5 h-3.5 stroke-[3]"></i>
</span>
</div>
<p class="text-[11px] text-slate-400 mt-1 leading-relaxed">
Diepe contrasten, rustig voor de ogen in de avond of donkere werkplek.
</p>
</div>
</button>
<!-- Optie 2: Licht (Light) -->
<button type="button" onclick="selectThemePreference('light')" id="themeBtn-light" class="theme-card relative text-left p-4 rounded-2xl border-2 transition duration-150 flex flex-col justify-between group hover:shadow-md cursor-pointer bg-white border-slate-200 text-slate-900">
<div class="w-full h-24 rounded-xl bg-slate-100 p-2.5 border border-slate-200 mb-3 flex flex-col justify-between overflow-hidden shadow-inner">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-1.5">
<span class="w-2 h-2 rounded-full bg-red-400/80"></span>
<span class="w-2 h-2 rounded-full bg-amber-400/80"></span>
<span class="w-2 h-2 rounded-full bg-emerald-400/80"></span>
</div>
<span class="text-[9px] font-mono text-slate-400">fociz.light</span>
</div>
<div class="space-y-1.5">
<div class="h-2 w-3/4 bg-emerald-600/40 rounded"></div>
<div class="h-2 w-1/2 bg-slate-300 rounded"></div>
</div>
<div class="flex space-x-1">
<div class="h-3 w-8 bg-slate-200 rounded"></div>
<div class="h-3 w-10 bg-emerald-100 rounded"></div>
</div>
</div>
<div>
<div class="flex items-center justify-between">
<span class="text-sm font-bold text-slate-900 flex items-center space-x-1.5">
<i data-lucide="sun" class="w-4 h-4 text-amber-500"></i>
<span>Lichte Modus</span>
</span>
<span id="themeCheck-light" class="theme-check hidden w-5 h-5 rounded-full bg-emerald-500 text-slate-950 items-center justify-center">
<i data-lucide="check" class="w-3.5 h-3.5 stroke-[3]"></i>
</span>
</div>
<p class="text-[11px] text-slate-500 mt-1 leading-relaxed">
Kraakhelder, fris en professioneel voor overdag en felle kantoorverlichting.
</p>
</div>
</button>
<!-- Optie 3: Systeem (Auto) -->
<button type="button" onclick="selectThemePreference('system')" id="themeBtn-system" class="theme-card relative text-left p-4 rounded-2xl border-2 transition duration-150 flex flex-col justify-between group hover:shadow-md cursor-pointer bg-slate-50 dark:bg-slate-900 border-slate-300 dark:border-slate-700">
<div class="w-full h-24 rounded-xl border border-slate-300 dark:border-slate-800 mb-3 flex overflow-hidden shadow-inner">
<!-- Linker helft licht -->
<div class="w-1/2 bg-slate-100 p-2 flex flex-col justify-between border-r border-slate-200">
<div class="flex space-x-1">
<span class="w-1.5 h-1.5 rounded-full bg-slate-300"></span>
<span class="w-1.5 h-1.5 rounded-full bg-slate-300"></span>
</div>
<div class="h-2 w-3/4 bg-emerald-600/50 rounded"></div>
<div class="h-2 w-1/2 bg-slate-300 rounded"></div>
</div>
<!-- Rechter helft donker -->
<div class="w-1/2 bg-slate-950 p-2 flex flex-col justify-between">
<div class="flex justify-end space-x-1">
<span class="w-1.5 h-1.5 rounded-full bg-slate-700"></span>
<span class="w-1.5 h-1.5 rounded-full bg-slate-700"></span>
</div>
<div class="h-2 w-3/4 bg-emerald-400/50 rounded"></div>
<div class="h-2 w-1/2 bg-slate-800 rounded"></div>
</div>
</div>
<div>
<div class="flex items-center justify-between">
<span class="text-sm font-bold text-slate-900 dark:text-white flex items-center space-x-1.5">
<i data-lucide="laptop" class="w-4 h-4 text-blue-500"></i>
<span>Systeem Volgen</span>
</span>
<span id="themeCheck-system" class="theme-check hidden w-5 h-5 rounded-full bg-emerald-500 text-slate-950 items-center justify-center">
<i data-lucide="check" class="w-3.5 h-3.5 stroke-[3]"></i>
</span>
</div>
<p class="text-[11px] text-slate-500 dark:text-slate-400 mt-1 leading-relaxed">
Schakelt automatisch mee met uw Windows, macOS of browser voorkeur.
</p>
</div>
</button>
</div>
</div>
<!-- Sectie 1: Mijn Microsoft 365 Outlook Agenda -->
<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 transition">
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 pb-6 border-b border-slate-100 dark:border-slate-800/80">
<div class="flex items-center space-x-3.5">
<div class="w-12 h-12 rounded-2xl bg-blue-500/10 border border-blue-500/20 flex items-center justify-center text-blue-600 dark:text-blue-400 font-bold shadow-sm">
<i data-lucide="calendar" class="w-6 h-6"></i> <i data-lucide="calendar" class="w-6 h-6"></i>
</div> </div>
<div> <div>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<h2 class="text-lg font-bold text-white tracking-tight">Mijn Microsoft 365 Agenda</h2> <h2 class="text-lg font-bold text-slate-900 dark:text-white tracking-tight">Mijn Microsoft 365 Agenda</h2>
<?php if ($isOutlookConnected): ?> <?php if ($isOutlookConnected): ?>
<span class="px-2.5 py-0.5 rounded-full bg-emerald-500/15 border border-emerald-500/30 text-emerald-400 text-[10px] font-bold flex items-center space-x-1"> <span class="px-2.5 py-0.5 rounded-full bg-emerald-500/15 border border-emerald-500/30 text-emerald-700 dark:text-emerald-400 text-[10px] font-bold flex items-center space-x-1">
<span class="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-pulse"></span> <span class="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-pulse"></span>
<span>Live Verbonden</span> <span>Live Verbonden</span>
</span> </span>
<?php else: ?> <?php else: ?>
<span class="px-2.5 py-0.5 rounded-full bg-slate-800 text-slate-400 text-[10px] font-bold"> <span class="px-2.5 py-0.5 rounded-full bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400 text-[10px] font-bold">
Niet Gekoppeld Niet Gekoppeld
</span> </span>
<?php endif; ?> <?php endif; ?>
</div> </div>
<p class="text-xs text-slate-400">Synchroniseer uw agenda-afspraken automatisch met uw dagplanning</p> <p class="text-xs text-slate-500 dark:text-slate-400">Synchroniseer uw agenda-afspraken automatisch met uw dagplanning</p>
</div> </div>
</div> </div>
<?php if ($isOutlookConnected): ?> <?php if ($isOutlookConnected): ?>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<a href="/auth/oauth_microsoft.php" class="px-3 py-1.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-slate-300 text-xs font-medium transition" title="Opnieuw autoriseren bij Microsoft"> <a href="/auth/oauth_microsoft.php" class="px-3 py-1.5 rounded-xl bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-300 border border-slate-200 dark:border-slate-700 text-xs font-medium transition" title="Opnieuw autoriseren bij Microsoft">
Opnieuw Verbinden Opnieuw Verbinden
</a> </a>
<form method="POST" onsubmit="return confirm('Weet u zeker dat u uw Microsoft Outlook agenda wilt ontkoppelen?');"> <form method="POST" onsubmit="return confirm('Weet u zeker dat u uw Microsoft Outlook agenda wilt ontkoppelen?');">
<input type="hidden" name="action" value="disconnect_outlook"> <input type="hidden" name="action" value="disconnect_outlook">
<button type="submit" class="px-3 py-1.5 rounded-xl bg-red-500/10 hover:bg-red-500/20 text-red-400 border border-red-500/20 text-xs font-medium transition"> <button type="submit" class="px-3 py-1.5 rounded-xl bg-red-500/10 hover:bg-red-500/20 text-red-600 dark:text-red-400 border border-red-500/20 text-xs font-medium transition">
Ontkoppelen Ontkoppelen
</button> </button>
</form> </form>
@@ -308,40 +446,40 @@ require_once __DIR__ . '/includes/header.php';
<div class="mt-6"> <div class="mt-6">
<?php if ($isOutlookConnected): ?> <?php if ($isOutlookConnected): ?>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div class="p-4 rounded-2xl bg-slate-950/60 border border-slate-800 space-y-1.5"> <div class="p-4 rounded-2xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800 space-y-1.5">
<span class="text-[10px] uppercase tracking-wider font-semibold text-slate-400 block">Gekoppeld Microsoft Account</span> <span class="text-[10px] uppercase tracking-wider font-semibold text-slate-500 dark:text-slate-400 block">Gekoppeld Microsoft Account</span>
<span class="text-sm font-bold text-white block truncate"><?= htmlspecialchars($outlookSettings['account_name'] ?? 'Microsoft Gebruiker') ?></span> <span class="text-sm font-bold text-slate-900 dark:text-white block truncate"><?= htmlspecialchars($outlookSettings['account_name'] ?? 'Microsoft Gebruiker') ?></span>
<span class="text-xs text-emerald-400 block truncate"><?= htmlspecialchars($outlookSettings['account_email'] ?? $userProfile['email']) ?></span> <span class="text-xs text-emerald-600 dark:text-emerald-400 block truncate"><?= htmlspecialchars($outlookSettings['account_email'] ?? $userProfile['email']) ?></span>
</div> </div>
<div class="p-4 rounded-2xl bg-slate-950/60 border border-slate-800 space-y-1.5"> <div class="p-4 rounded-2xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800 space-y-1.5">
<span class="text-[10px] uppercase tracking-wider font-semibold text-slate-400 block">Microsoft Teams Koppeling</span> <span class="text-[10px] uppercase tracking-wider font-semibold text-slate-500 dark:text-slate-400 block">Microsoft Teams Koppeling</span>
<span class="text-sm font-bold text-white flex items-center space-x-1.5"> <span class="text-sm font-bold text-slate-900 dark:text-white flex items-center space-x-1.5">
<i data-lucide="video" class="w-4 h-4 text-blue-400"></i> <i data-lucide="video" class="w-4 h-4 text-blue-500"></i>
<span>Automatische Meeting Links</span> <span>Automatische Meeting Links</span>
</span> </span>
<span class="text-xs text-slate-400 block">Vergaderlinks in uw agenda worden direct klikbaar in uw dagplanning</span> <span class="text-xs text-slate-500 dark:text-slate-400 block">Vergaderlinks in uw agenda worden direct klikbaar in uw dagplanning</span>
</div> </div>
</div> </div>
<div class="mt-4 p-3.5 rounded-2xl bg-emerald-500/10 border border-emerald-500/20 text-emerald-300 text-xs flex items-center justify-between"> <div class="mt-4 p-3.5 rounded-2xl bg-emerald-500/10 border border-emerald-500/20 text-emerald-800 dark:text-emerald-300 text-xs flex items-center justify-between">
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<i data-lucide="check-circle" class="w-4 h-4 text-emerald-400 flex-shrink-0"></i> <i data-lucide="check-circle" class="w-4 h-4 text-emerald-600 dark:text-emerald-400 flex-shrink-0"></i>
<span>Uw agenda synchroniseert live. Afspraken van vandaag verschijnen direct in uw <a href="/planner.php" class="underline font-semibold text-white">Dagplanning</a>.</span> <span>Uw agenda synchroniseert live. Afspraken van vandaag verschijnen direct in uw <a href="/planner.php" class="underline font-semibold text-slate-900 dark:text-white">Dagplanning</a>.</span>
</div> </div>
<a href="/planner.php" class="px-3 py-1 rounded-lg bg-emerald-500/20 hover:bg-emerald-500/30 text-emerald-200 font-semibold text-xs transition flex-shrink-0"> <a href="/planner.php" class="px-3 py-1 rounded-lg bg-emerald-500/20 hover:bg-emerald-500/30 text-emerald-800 dark:text-emerald-200 font-semibold text-xs transition flex-shrink-0">
Naar Dagplanning &rarr; Naar Dagplanning &rarr;
</a> </a>
</div> </div>
<?php else: ?> <?php else: ?>
<div class="p-6 rounded-2xl bg-slate-950/60 border border-slate-800 text-center space-y-4"> <div class="p-6 rounded-2xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800 text-center space-y-4">
<div class="w-14 h-14 rounded-2xl bg-blue-500/10 border border-blue-500/20 text-blue-400 flex items-center justify-center mx-auto"> <div class="w-14 h-14 rounded-2xl bg-blue-500/10 border border-blue-500/20 text-blue-600 dark:text-blue-400 flex items-center justify-center mx-auto">
<i data-lucide="calendar-plus" class="w-7 h-7"></i> <i data-lucide="calendar-plus" class="w-7 h-7"></i>
</div> </div>
<div class="max-w-md mx-auto space-y-1"> <div class="max-w-md mx-auto space-y-1">
<h3 class="text-base font-bold text-white">Verbind uw Microsoft Outlook Agenda</h3> <h3 class="text-base font-bold text-slate-900 dark:text-white">Verbind uw Microsoft Outlook Agenda</h3>
<p class="text-xs text-slate-400 leading-relaxed"> <p class="text-xs text-slate-500 dark:text-slate-400 leading-relaxed">
Krijg uw dagelijkse afspraken automatisch te zien in Fociz en ontvang herinneringen vóórdat uw vergaderingen beginnen. Krijg uw dagelijkse afspraken automatisch te zien in Fociz en ontvang herinneringen vóórdat uw vergaderingen beginnen.
</p> </p>
</div> </div>
@@ -350,7 +488,7 @@ require_once __DIR__ . '/includes/header.php';
<div> <div>
<form method="POST"> <form method="POST">
<input type="hidden" name="action" value="connect_outlook"> <input type="hidden" name="action" value="connect_outlook">
<button type="submit" class="inline-flex items-center space-x-2 px-6 py-3 rounded-xl bg-blue-600 hover:bg-blue-500 text-white font-bold text-xs transition shadow-xl shadow-blue-500/25"> <button type="submit" class="inline-flex items-center space-x-2 px-6 py-3 rounded-xl bg-blue-600 hover:bg-blue-500 text-white font-bold text-xs transition shadow-xl shadow-blue-500/25 cursor-pointer">
<i data-lucide="log-in" class="w-4 h-4"></i> <i data-lucide="log-in" class="w-4 h-4"></i>
<span>Koppel Mijn Outlook Agenda</span> <span>Koppel Mijn Outlook Agenda</span>
</button> </button>
@@ -358,11 +496,11 @@ require_once __DIR__ . '/includes/header.php';
<span class="text-[11px] text-slate-500 block mt-2">U wordt veilig doorgestuurd naar Microsoft om in te loggen</span> <span class="text-[11px] text-slate-500 block mt-2">U wordt veilig doorgestuurd naar Microsoft om in te loggen</span>
</div> </div>
<?php else: ?> <?php else: ?>
<div class="p-3.5 rounded-xl bg-amber-500/10 border border-amber-500/30 text-amber-300 text-xs max-w-lg mx-auto"> <div class="p-3.5 rounded-xl bg-amber-500/10 border border-amber-500/30 text-amber-800 dark:text-amber-300 text-xs max-w-lg mx-auto">
<i data-lucide="alert-circle" class="w-4 h-4 text-amber-400 inline mr-1 -mt-0.5"></i> <i data-lucide="alert-circle" class="w-4 h-4 text-amber-500 inline mr-1 -mt-0.5"></i>
Microsoft 365 koppeling is nog niet geconfigureerd door de beheerder. Microsoft 365 koppeling is nog niet geconfigureerd door de beheerder.
<?php if ($userProfile['role'] === 'ADMIN'): ?> <?php if ($userProfile['role'] === 'ADMIN'): ?>
<a href="/admin.php" class="underline font-bold text-white ml-1">Stel Azure in via Systeembeheer &rarr;</a> <a href="/admin.php" class="underline font-bold text-slate-900 dark:text-white ml-1">Stel Azure in via Systeembeheer &rarr;</a>
<?php else: ?> <?php else: ?>
Vraag uw beheerder om dit in te schakelen. Vraag uw beheerder om dit in te schakelen.
<?php endif; ?> <?php endif; ?>
@@ -374,33 +512,33 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
<!-- Sectie 2: Mijn Atlassian Jira Koppeling --> <!-- Sectie 2: Mijn Atlassian Jira Koppeling -->
<div class="bg-slate-900/80 border border-slate-800 rounded-3xl p-6 sm:p-7 shadow-xl"> <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 transition">
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 pb-6 border-b border-slate-800/80"> <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 pb-6 border-b border-slate-100 dark:border-slate-800/80">
<div class="flex items-center space-x-3.5"> <div class="flex items-center space-x-3.5">
<div class="w-12 h-12 rounded-2xl bg-indigo-500/10 border border-indigo-500/20 flex items-center justify-center text-indigo-400 font-bold shadow-md"> <div class="w-12 h-12 rounded-2xl bg-indigo-500/10 border border-indigo-500/20 flex items-center justify-center text-indigo-600 dark:text-indigo-400 font-bold shadow-sm">
<i data-lucide="check-square" class="w-6 h-6"></i> <i data-lucide="check-square" class="w-6 h-6"></i>
</div> </div>
<div> <div>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<h2 class="text-lg font-bold text-white tracking-tight">Mijn Atlassian Jira Koppeling</h2> <h2 class="text-lg font-bold text-slate-900 dark:text-white tracking-tight">Mijn Atlassian Jira Koppeling</h2>
<?php if ($isJiraConnected): ?> <?php if ($isJiraConnected): ?>
<span class="px-2.5 py-0.5 rounded-full bg-emerald-500/15 border border-emerald-500/30 text-emerald-400 text-[10px] font-bold"> <span class="px-2.5 py-0.5 rounded-full bg-emerald-500/15 border border-emerald-500/30 text-emerald-700 dark:text-emerald-400 text-[10px] font-bold">
Verbonden Verbonden
</span> </span>
<?php else: ?> <?php else: ?>
<span class="px-2.5 py-0.5 rounded-full bg-slate-800 text-slate-400 text-[10px] font-bold"> <span class="px-2.5 py-0.5 rounded-full bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400 text-[10px] font-bold">
Niet Gekoppeld Niet Gekoppeld
</span> </span>
<?php endif; ?> <?php endif; ?>
</div> </div>
<p class="text-xs text-slate-400">Importeer uw toegewezen Jira issues direct naar uw dagelijkse takenlijst</p> <p class="text-xs text-slate-500 dark:text-slate-400">Importeer uw toegewezen Jira issues direct naar uw dagelijkse takenlijst</p>
</div> </div>
</div> </div>
<?php if ($isJiraConnected): ?> <?php if ($isJiraConnected): ?>
<form method="POST" onsubmit="return confirm('Weet u zeker dat u Jira wilt ontkoppelen?');"> <form method="POST" onsubmit="return confirm('Weet u zeker dat u Jira wilt ontkoppelen?');">
<input type="hidden" name="action" value="disconnect_jira"> <input type="hidden" name="action" value="disconnect_jira">
<button type="submit" class="px-3 py-1.5 rounded-xl bg-red-500/10 hover:bg-red-500/20 text-red-400 border border-red-500/20 text-xs font-medium transition"> <button type="submit" class="px-3 py-1.5 rounded-xl bg-red-500/10 hover:bg-red-500/20 text-red-600 dark:text-red-400 border border-red-500/20 text-xs font-medium transition">
Jira Ontkoppelen Jira Ontkoppelen
</button> </button>
</form> </form>
@@ -412,34 +550,34 @@ require_once __DIR__ . '/includes/header.php';
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div> <div>
<label class="block text-xs font-semibold text-slate-300 mb-1.5"> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1.5">
Jira Cloud Domein Jira Cloud Domein
</label> </label>
<input type="text" name="jira_domain" value="<?= htmlspecialchars($activeJiraDomain) ?>" placeholder="https://uwbedrijf.atlassian.net" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-white placeholder-slate-600 focus:outline-none focus:border-indigo-500 font-mono"> <input type="text" name="jira_domain" value="<?= htmlspecialchars($activeJiraDomain) ?>" placeholder="https://uwbedrijf.atlassian.net" class="w-full bg-white dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-600 focus:outline-none focus:border-indigo-500 font-mono">
<span class="text-[10px] text-slate-500 mt-1 block">Standaard ingevuld door beheerder indien beschikbaar</span> <span class="text-[10px] text-slate-500 mt-1 block">Standaard ingevuld door beheerder indien beschikbaar</span>
</div> </div>
<div> <div>
<label class="block text-xs font-semibold text-slate-300 mb-1.5"> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1.5">
Uw Jira E-mailadres Uw Jira E-mailadres
</label> </label>
<input type="email" name="jira_email" value="<?= htmlspecialchars($jiraSettings['jira_email'] ?? $userProfile['email']) ?>" placeholder="naam@bedrijf.nl" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-white placeholder-slate-600 focus:outline-none focus:border-indigo-500"> <input type="email" name="jira_email" value="<?= htmlspecialchars($jiraSettings['jira_email'] ?? $userProfile['email']) ?>" placeholder="naam@bedrijf.nl" class="w-full bg-white dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-600 focus:outline-none focus:border-indigo-500">
</div> </div>
</div> </div>
<div> <div>
<div class="flex items-center justify-between mb-1.5"> <div class="flex items-center justify-between mb-1.5">
<label class="text-xs font-semibold text-slate-300"> <label class="text-xs font-semibold text-slate-700 dark:text-slate-300">
Persoonlijk Atlassian API Token Persoonlijk Atlassian API Token
</label> </label>
<a href="https://id.atlassian.com/manage-profile/security/api-tokens" target="_blank" rel="noopener noreferrer" class="text-[10px] text-indigo-400 hover:underline flex items-center space-x-1"> <a href="https://id.atlassian.com/manage-profile/security/api-tokens" target="_blank" rel="noopener noreferrer" class="text-[10px] text-indigo-600 dark:text-indigo-400 hover:underline flex items-center space-x-1">
<span>API Token Aanmaken</span> <span>API Token Aanmaken</span>
<i data-lucide="external-link" class="w-3 h-3"></i> <i data-lucide="external-link" class="w-3 h-3"></i>
</a> </a>
</div> </div>
<div class="relative"> <div class="relative">
<input type="password" id="jiraApiTokenInput" name="jira_api_token" value="<?= !empty($jiraSettings['jira_api_token']) ? '••••••••••••••••' : '' ?>" placeholder="Plak hier uw Atlassian API token..." class="w-full bg-slate-950 border border-slate-800 rounded-xl pl-3.5 pr-10 py-2.5 text-xs text-white placeholder-slate-600 focus:outline-none focus:border-indigo-500"> <input type="password" id="jiraApiTokenInput" name="jira_api_token" value="<?= !empty($jiraSettings['jira_api_token']) ? '••••••••••••••••' : '' ?>" placeholder="Plak hier uw Atlassian API token..." class="w-full bg-white dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl pl-3.5 pr-10 py-2.5 text-xs text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-600 focus:outline-none focus:border-indigo-500">
<button type="button" onclick="toggleJiraToken()" class="absolute inset-y-0 right-0 pr-3 flex items-center text-slate-500 hover:text-slate-300"> <button type="button" onclick="toggleJiraToken()" class="absolute inset-y-0 right-0 pr-3 flex items-center text-slate-400 hover:text-slate-600 dark:hover:text-slate-300">
<i data-lucide="eye" class="w-4 h-4" id="eyeJiraIcon"></i> <i data-lucide="eye" class="w-4 h-4" id="eyeJiraIcon"></i>
</button> </button>
</div> </div>
@@ -447,12 +585,12 @@ require_once __DIR__ . '/includes/header.php';
<div class="pt-2 flex items-center justify-between"> <div class="pt-2 flex items-center justify-between">
<?php if ($isJiraConnected && !empty($jiraSettings['account_name'])): ?> <?php if ($isJiraConnected && !empty($jiraSettings['account_name'])): ?>
<span class="text-xs text-emerald-400 flex items-center space-x-1.5"> <span class="text-xs text-emerald-600 dark:text-emerald-400 flex items-center space-x-1.5">
<i data-lucide="check" class="w-4 h-4"></i> <i data-lucide="check" class="w-4 h-4"></i>
<span>Verbonden als: <strong><?= htmlspecialchars($jiraSettings['account_name']) ?></strong></span> <span>Verbonden als: <strong><?= htmlspecialchars($jiraSettings['account_name']) ?></strong></span>
</span> </span>
<?php else: ?> <?php else: ?>
<span class="text-[11px] text-slate-400">Verbinding wordt automatisch gevalideerd bij het opslaan</span> <span class="text-[11px] text-slate-500 dark:text-slate-400">Verbinding wordt automatisch gevalideerd bij het opslaan</span>
<?php endif; ?> <?php endif; ?>
<button type="submit" class="px-5 py-2.5 rounded-xl bg-indigo-600 hover:bg-indigo-500 text-white text-xs font-bold transition shadow-lg shadow-indigo-500/20"> <button type="submit" class="px-5 py-2.5 rounded-xl bg-indigo-600 hover:bg-indigo-500 text-white text-xs font-bold transition shadow-lg shadow-indigo-500/20">
@@ -463,39 +601,39 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
<!-- Sectie 3: Mijn Meldingen & Agenda Push Notificaties --> <!-- Sectie 3: Mijn Meldingen & Agenda Push Notificaties -->
<div class="bg-slate-900/80 border border-slate-800 rounded-3xl p-6 sm:p-7 shadow-xl"> <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 transition">
<div class="flex items-center space-x-3.5 pb-6 border-b border-slate-800/80"> <div class="flex items-center space-x-3.5 pb-6 border-b border-slate-100 dark:border-slate-800/80">
<div class="w-12 h-12 rounded-2xl bg-emerald-500/10 border border-emerald-500/20 flex items-center justify-center text-emerald-400 font-bold shadow-md"> <div class="w-12 h-12 rounded-2xl bg-emerald-500/10 border border-emerald-500/20 flex items-center justify-center text-emerald-600 dark:text-emerald-400 font-bold shadow-sm">
<i data-lucide="bell" class="w-6 h-6"></i> <i data-lucide="bell" class="w-6 h-6"></i>
</div> </div>
<div> <div>
<h2 class="text-lg font-bold text-white tracking-tight">Mijn Meldingen & Agenda Herinneringen</h2> <h2 class="text-lg font-bold text-slate-900 dark:text-white tracking-tight">Mijn Meldingen & Agenda Herinneringen</h2>
<p class="text-xs text-slate-400">Krijg realtime meldingen vanuit uw browser zodra een afspraak nadert</p> <p class="text-xs text-slate-500 dark:text-slate-400">Krijg realtime meldingen vanuit uw browser zodra een afspraak nadert</p>
</div> </div>
</div> </div>
<div class="mt-6 space-y-5"> <div class="mt-6 space-y-5">
<!-- Browser Permissie Banner in Profiel --> <!-- Browser Permissie Banner in Profiel -->
<div id="profileNotifPermGranted" class="hidden p-4 rounded-2xl bg-emerald-500/10 border border-emerald-500/30 text-emerald-300 flex flex-col sm:flex-row sm:items-center justify-between gap-3"> <div id="profileNotifPermGranted" class="hidden p-4 rounded-2xl bg-emerald-500/10 border border-emerald-500/30 text-emerald-800 dark:text-emerald-300 flex flex-col sm:flex-row sm:items-center justify-between gap-3">
<div class="flex items-center space-x-2.5"> <div class="flex items-center space-x-2.5">
<i data-lucide="check-circle" class="w-5 h-5 text-emerald-400 flex-shrink-0"></i> <i data-lucide="check-circle" class="w-5 h-5 text-emerald-600 dark:text-emerald-400 flex-shrink-0"></i>
<div> <div>
<strong class="block text-xs text-white">Browser Pushberichten zijn Actief</strong> <strong class="block text-xs text-slate-900 dark:text-white">Browser Pushberichten zijn Actief</strong>
<span class="text-[11px] text-emerald-300/80">Uw browser heeft toestemming om bureaubladmeldingen weer te geven.</span> <span class="text-[11px] text-emerald-700 dark:text-emerald-300/80">Uw browser heeft toestemming om bureaubladmeldingen weer te geven.</span>
</div> </div>
</div> </div>
<button type="button" onclick="focizTestNotification()" class="px-3 py-1.5 rounded-xl bg-emerald-500/20 hover:bg-emerald-500/30 text-emerald-300 font-bold text-xs transition flex items-center space-x-1.5 flex-shrink-0"> <button type="button" onclick="focizTestNotification()" class="px-3 py-1.5 rounded-xl bg-emerald-500/20 hover:bg-emerald-500/30 text-emerald-800 dark:text-emerald-300 font-bold text-xs transition flex items-center space-x-1.5 flex-shrink-0">
<i data-lucide="send" class="w-3.5 h-3.5"></i> <i data-lucide="send" class="w-3.5 h-3.5"></i>
<span>Verzend Test Melding</span> <span>Verzend Test Melding</span>
</button> </button>
</div> </div>
<div id="profileNotifPermRequest" class="p-4 rounded-2xl bg-blue-500/10 border border-blue-500/30 text-blue-200 flex flex-col sm:flex-row sm:items-center justify-between gap-3"> <div id="profileNotifPermRequest" class="p-4 rounded-2xl bg-blue-500/10 border border-blue-500/30 text-blue-800 dark:text-blue-200 flex flex-col sm:flex-row sm:items-center justify-between gap-3">
<div class="flex items-center space-x-2.5"> <div class="flex items-center space-x-2.5">
<i data-lucide="bell-ring" class="w-5 h-5 text-blue-400 flex-shrink-0"></i> <i data-lucide="bell-ring" class="w-5 h-5 text-blue-600 dark:text-blue-400 flex-shrink-0"></i>
<div> <div>
<strong class="block text-xs text-white">Toestemming van Browser Vereist</strong> <strong class="block text-xs text-slate-900 dark:text-white">Toestemming van Browser Vereist</strong>
<span class="text-[11px] text-blue-300/80">Klik op de knop om pushmeldingen in te schakelen voor Fociz.</span> <span class="text-[11px] text-blue-700 dark:text-blue-300/80">Klik op de knop om pushmeldingen in te schakelen voor Fociz.</span>
</div> </div>
</div> </div>
<button type="button" onclick="focizRequestPermission()" class="px-4 py-2 rounded-xl bg-blue-600 hover:bg-blue-500 text-white font-bold text-xs transition shadow flex-shrink-0"> <button type="button" onclick="focizRequestPermission()" class="px-4 py-2 rounded-xl bg-blue-600 hover:bg-blue-500 text-white font-bold text-xs transition shadow flex-shrink-0">
@@ -503,31 +641,31 @@ require_once __DIR__ . '/includes/header.php';
</button> </button>
</div> </div>
<div id="profileNotifPermDenied" class="hidden p-4 rounded-2xl bg-red-500/10 border border-red-500/30 text-red-300 text-xs leading-relaxed"> <div id="profileNotifPermDenied" class="hidden p-4 rounded-2xl bg-red-500/10 border border-red-500/30 text-red-800 dark:text-red-300 text-xs leading-relaxed">
<i data-lucide="alert-triangle" class="w-4 h-4 text-red-400 inline mr-1 -mt-0.5"></i> <i data-lucide="alert-triangle" class="w-4 h-4 text-red-600 dark:text-red-400 inline mr-1 -mt-0.5"></i>
Meldingen zijn momenteel geblokkeerd in uw browser. Klik links in de adresbalk op het slotje/site-instellingen en zet "Meldingen" op "Toestaan". Meldingen zijn momenteel geblokkeerd in uw browser. Klik links in de adresbalk op het slotje/site-instellingen en zet "Meldingen" op "Toestaan".
</div> </div>
<form method="POST" class="space-y-4"> <form method="POST" class="space-y-4">
<input type="hidden" name="action" value="save_notifications"> <input type="hidden" name="action" value="save_notifications">
<div class="flex items-center justify-between p-4 rounded-2xl bg-slate-950/60 border border-slate-800"> <div class="flex items-center justify-between p-4 rounded-2xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800">
<div> <div>
<span class="text-xs font-bold text-white block">Meldingen Actief</span> <span class="text-xs font-bold text-slate-900 dark:text-white block">Meldingen Actief</span>
<span class="text-[11px] text-slate-400">Automatisch waarschuwen bij naderende afspraken</span> <span class="text-[11px] text-slate-500 dark:text-slate-400">Automatisch waarschuwen bij naderende afspraken</span>
</div> </div>
<label class="relative inline-flex items-center cursor-pointer"> <label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" name="notif_enabled" <?= !empty($notifSettings['enabled']) ? 'checked' : '' ?> class="sr-only peer"> <input type="checkbox" name="notif_enabled" <?= !empty($notifSettings['enabled']) ? 'checked' : '' ?> class="sr-only peer">
<div class="w-11 h-6 bg-slate-800 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-emerald-600"></div> <div class="w-11 h-6 bg-slate-300 dark:bg-slate-800 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-emerald-600"></div>
</label> </label>
</div> </div>
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4"> <div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
<div> <div>
<label class="block text-xs font-semibold text-slate-300 mb-1.5"> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1.5">
Vooraankondiging Vooraankondiging
</label> </label>
<select name="lead_time_minutes" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-white focus:outline-none focus:border-emerald-500"> <select name="lead_time_minutes" class="w-full bg-white dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-slate-900 dark:text-white focus:outline-none focus:border-emerald-500">
<option value="0" <?= (int)$notifSettings['lead_time_minutes'] === 0 ? 'selected' : '' ?>>0 minuten (Precies op aanvang)</option> <option value="0" <?= (int)$notifSettings['lead_time_minutes'] === 0 ? 'selected' : '' ?>>0 minuten (Precies op aanvang)</option>
<option value="2" <?= (int)$notifSettings['lead_time_minutes'] === 2 ? 'selected' : '' ?>>2 minuten van tevoren</option> <option value="2" <?= (int)$notifSettings['lead_time_minutes'] === 2 ? 'selected' : '' ?>>2 minuten van tevoren</option>
<option value="5" <?= (int)$notifSettings['lead_time_minutes'] === 5 ? 'selected' : '' ?>>5 minuten van tevoren (Aanbevolen)</option> <option value="5" <?= (int)$notifSettings['lead_time_minutes'] === 5 ? 'selected' : '' ?>>5 minuten van tevoren (Aanbevolen)</option>
@@ -538,10 +676,10 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
<div> <div>
<label class="block text-xs font-semibold text-slate-300 mb-1.5"> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1.5">
Aantal herhalingen Aantal herhalingen
</label> </label>
<select name="repeat_count" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-white focus:outline-none focus:border-emerald-500"> <select name="repeat_count" class="w-full bg-white dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-slate-900 dark:text-white focus:outline-none focus:border-emerald-500">
<option value="1" <?= (int)$notifSettings['repeat_count'] === 1 ? 'selected' : '' ?>>1x (Alleen eerste melding)</option> <option value="1" <?= (int)$notifSettings['repeat_count'] === 1 ? 'selected' : '' ?>>1x (Alleen eerste melding)</option>
<option value="2" <?= (int)$notifSettings['repeat_count'] === 2 ? 'selected' : '' ?>>2x herhalen (Aanbevolen)</option> <option value="2" <?= (int)$notifSettings['repeat_count'] === 2 ? 'selected' : '' ?>>2x herhalen (Aanbevolen)</option>
<option value="3" <?= (int)$notifSettings['repeat_count'] === 3 ? 'selected' : '' ?>>3x herhalen</option> <option value="3" <?= (int)$notifSettings['repeat_count'] === 3 ? 'selected' : '' ?>>3x herhalen</option>
@@ -550,10 +688,10 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
<div> <div>
<label class="block text-xs font-semibold text-slate-300 mb-1.5"> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1.5">
Herhalingsinterval Herhalingsinterval
</label> </label>
<select name="repeat_interval_minutes" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-white focus:outline-none focus:border-emerald-500"> <select name="repeat_interval_minutes" class="w-full bg-white dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-slate-900 dark:text-white focus:outline-none focus:border-emerald-500">
<option value="1" <?= (int)$notifSettings['repeat_interval_minutes'] === 1 ? 'selected' : '' ?>>Elke 1 minuut</option> <option value="1" <?= (int)$notifSettings['repeat_interval_minutes'] === 1 ? 'selected' : '' ?>>Elke 1 minuut</option>
<option value="2" <?= (int)$notifSettings['repeat_interval_minutes'] === 2 ? 'selected' : '' ?>>Elke 2 minuten</option> <option value="2" <?= (int)$notifSettings['repeat_interval_minutes'] === 2 ? 'selected' : '' ?>>Elke 2 minuten</option>
<option value="3" <?= (int)$notifSettings['repeat_interval_minutes'] === 3 ? 'selected' : '' ?>>Elke 3 minuten</option> <option value="3" <?= (int)$notifSettings['repeat_interval_minutes'] === 3 ? 'selected' : '' ?>>Elke 3 minuten</option>
@@ -562,22 +700,22 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
</div> </div>
<div class="flex items-center justify-between p-4 rounded-2xl bg-slate-950/60 border border-slate-800"> <div class="flex items-center justify-between p-4 rounded-2xl bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800">
<div class="flex items-center space-x-2.5"> <div class="flex items-center space-x-2.5">
<i data-lucide="volume-2" class="w-4 h-4 text-emerald-400"></i> <i data-lucide="volume-2" class="w-4 h-4 text-emerald-600 dark:text-emerald-400"></i>
<div> <div>
<span class="text-xs font-bold text-white block">Subtiel Geluidssignaal</span> <span class="text-xs font-bold text-slate-900 dark:text-white block">Subtiel Geluidssignaal</span>
<span class="text-[11px] text-slate-400">Speel een zachte chime af bij binnenkomst van de herinnering</span> <span class="text-[11px] text-slate-500 dark:text-slate-400">Speel een zachte chime af bij binnenkomst van de herinnering</span>
</div> </div>
</div> </div>
<label class="relative inline-flex items-center cursor-pointer"> <label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" name="sound_enabled" <?= !empty($notifSettings['sound_enabled']) ? 'checked' : '' ?> class="sr-only peer"> <input type="checkbox" name="sound_enabled" <?= !empty($notifSettings['sound_enabled']) ? 'checked' : '' ?> class="sr-only peer">
<div class="w-11 h-6 bg-slate-800 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-emerald-600"></div> <div class="w-11 h-6 bg-slate-300 dark:bg-slate-800 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-emerald-600"></div>
</label> </label>
</div> </div>
<div class="flex justify-end pt-2"> <div class="flex justify-end pt-2">
<button type="submit" class="px-5 py-2.5 rounded-xl bg-emerald-600 hover:bg-emerald-500 text-slate-950 text-xs font-bold transition shadow-lg shadow-emerald-600/20"> <button type="submit" class="px-5 py-2.5 rounded-xl bg-emerald-600 hover:bg-emerald-500 text-white dark:text-slate-950 text-xs font-bold transition shadow-lg shadow-emerald-600/20">
Notificatievoorkeuren Opslaan Notificatievoorkeuren Opslaan
</button> </button>
</div> </div>
@@ -588,32 +726,32 @@ require_once __DIR__ . '/includes/header.php';
<!-- Sectie 4: Account & Beveiliging (Wachtwoord & 2FA) --> <!-- Sectie 4: Account & Beveiliging (Wachtwoord & 2FA) -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<!-- Profielnaam formulier --> <!-- Profielnaam formulier -->
<div class="bg-slate-900/80 border border-slate-800 rounded-3xl p-6 sm:p-7 shadow-xl space-y-4"> <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-800/80"> <div class="flex items-center space-x-3 pb-4 border-b border-slate-100 dark:border-slate-800/80">
<i data-lucide="user" class="w-5 h-5 text-emerald-400"></i> <i data-lucide="user" class="w-5 h-5 text-emerald-600 dark:text-emerald-400"></i>
<h3 class="text-base font-bold text-white">Persoonlijke Gegevens</h3> <h3 class="text-base font-bold text-slate-900 dark:text-white">Persoonlijke Gegevens</h3>
</div> </div>
<form method="POST" class="space-y-4"> <form method="POST" class="space-y-4">
<input type="hidden" name="action" value="update_profile"> <input type="hidden" name="action" value="update_profile">
<div> <div>
<label class="block text-xs font-semibold text-slate-300 mb-1.5"> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1.5">
Weergavenaam Weergavenaam
</label> </label>
<input type="text" name="name" required value="<?= htmlspecialchars($userProfile['name']) ?>" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-white focus:outline-none focus:border-emerald-500"> <input type="text" name="name" required value="<?= htmlspecialchars($userProfile['name']) ?>" class="w-full bg-white dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-slate-900 dark:text-white focus:outline-none focus:border-emerald-500">
</div> </div>
<div> <div>
<label class="block text-xs font-semibold text-slate-300 mb-1.5"> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1.5">
E-mailadres E-mailadres
</label> </label>
<input type="email" readonly disabled value="<?= htmlspecialchars($userProfile['email']) ?>" class="w-full bg-slate-950/50 border border-slate-800/60 rounded-xl px-3.5 py-2.5 text-xs text-slate-500 cursor-not-allowed"> <input type="email" readonly disabled value="<?= htmlspecialchars($userProfile['email']) ?>" class="w-full bg-slate-100 dark:bg-slate-950/50 border border-slate-200 dark:border-slate-800/60 rounded-xl px-3.5 py-2.5 text-xs text-slate-500 cursor-not-allowed">
<span class="text-[10px] text-slate-500 mt-1 block">E-mailadres is gekoppeld aan uw account en 2FA.</span> <span class="text-[10px] text-slate-500 mt-1 block">E-mailadres is gekoppeld aan uw account en 2FA.</span>
</div> </div>
<div class="flex justify-end pt-2"> <div class="flex justify-end pt-2">
<button type="submit" class="px-4 py-2 rounded-xl bg-slate-800 hover:bg-slate-700 text-white text-xs font-semibold transition border border-slate-700"> <button type="submit" class="px-4 py-2 rounded-xl bg-slate-900 hover:bg-slate-800 text-white dark:bg-slate-800 dark:hover:bg-slate-700 dark:text-white text-xs font-semibold transition border border-slate-900 dark:border-slate-700 shadow-sm">
Naam Opslaan Naam Opslaan
</button> </button>
</div> </div>
@@ -621,38 +759,38 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
<!-- Wachtwoord Wijzigen Formulier --> <!-- Wachtwoord Wijzigen Formulier -->
<div class="bg-slate-900/80 border border-slate-800 rounded-3xl p-6 sm:p-7 shadow-xl space-y-4"> <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-800/80"> <div class="flex items-center space-x-3 pb-4 border-b border-slate-100 dark:border-slate-800/80">
<i data-lucide="key" class="w-5 h-5 text-emerald-400"></i> <i data-lucide="key" class="w-5 h-5 text-emerald-600 dark:text-emerald-400"></i>
<h3 class="text-base font-bold text-white">Wachtwoord Wijzigen</h3> <h3 class="text-base font-bold text-slate-900 dark:text-white">Wachtwoord Wijzigen</h3>
</div> </div>
<form method="POST" class="space-y-3"> <form method="POST" class="space-y-3">
<input type="hidden" name="action" value="change_password"> <input type="hidden" name="action" value="change_password">
<div> <div>
<label class="block text-xs font-semibold text-slate-300 mb-1"> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">
Huidig Wachtwoord Huidig Wachtwoord
</label> </label>
<input type="password" name="current_password" required class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2 text-xs text-white focus:outline-none focus:border-emerald-500"> <input type="password" name="current_password" required class="w-full bg-white dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3.5 py-2 text-xs text-slate-900 dark:text-white focus:outline-none focus:border-emerald-500">
</div> </div>
<div> <div>
<label class="block text-xs font-semibold text-slate-300 mb-1"> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">
Nieuw Wachtwoord (min. 8 tekens) Nieuw Wachtwoord (min. 8 tekens)
</label> </label>
<input type="password" name="new_password" required minlength="8" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2 text-xs text-white focus:outline-none focus:border-emerald-500"> <input type="password" name="new_password" required minlength="8" class="w-full bg-white dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3.5 py-2 text-xs text-slate-900 dark:text-white focus:outline-none focus:border-emerald-500">
</div> </div>
<div> <div>
<label class="block text-xs font-semibold text-slate-300 mb-1"> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">
Bevestig Nieuw Wachtwoord Bevestig Nieuw Wachtwoord
</label> </label>
<input type="password" name="confirm_password" required minlength="8" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2 text-xs text-white focus:outline-none focus:border-emerald-500"> <input type="password" name="confirm_password" required minlength="8" class="w-full bg-white dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3.5 py-2 text-xs text-slate-900 dark:text-white focus:outline-none focus:border-emerald-500">
</div> </div>
<div class="flex justify-end pt-2"> <div class="flex justify-end pt-2">
<button type="submit" class="px-4 py-2 rounded-xl bg-slate-800 hover:bg-slate-700 text-white text-xs font-semibold transition border border-slate-700"> <button type="submit" class="px-4 py-2 rounded-xl bg-slate-900 hover:bg-slate-800 text-white dark:bg-slate-800 dark:hover:bg-slate-700 dark:text-white text-xs font-semibold transition border border-slate-900 dark:border-slate-700 shadow-sm">
Wachtwoord Wijzigen Wachtwoord Wijzigen
</button> </button>
</div> </div>
@@ -662,6 +800,39 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
<script> <script>
// --- Thema Selector Functionaliteit ---
function selectThemePreference(theme) {
if (typeof focizSetTheme === 'function') {
focizSetTheme(theme, true);
}
updateProfileThemeUI(theme);
}
function updateProfileThemeUI(theme) {
const themes = ['dark', 'light', 'system'];
themes.forEach(t => {
const btn = document.getElementById('themeBtn-' + t);
const check = document.getElementById('themeCheck-' + t);
if (!btn || !check) return;
if (t === theme) {
btn.classList.add('ring-2', 'ring-emerald-500', 'border-emerald-500');
check.classList.remove('hidden');
check.classList.add('flex');
} else {
btn.classList.remove('ring-2', 'ring-emerald-500', 'border-emerald-500');
check.classList.add('hidden');
check.classList.remove('flex');
}
});
const badge = document.getElementById('themeStatusBadge');
if (badge) {
const label = theme.charAt(0).toUpperCase() + theme.slice(1);
badge.innerText = 'Actief: ' + label;
}
}
function toggleJiraToken() { function toggleJiraToken() {
const input = document.getElementById('jiraApiTokenInput'); const input = document.getElementById('jiraApiTokenInput');
const icon = document.getElementById('eyeJiraIcon'); const icon = document.getElementById('eyeJiraIcon');
@@ -676,8 +847,13 @@ function toggleJiraToken() {
if (window.lucide) lucide.createIcons(); if (window.lucide) lucide.createIcons();
} }
// Sync banner status met browser permissie // Sync banner status met browser permissie & activeer actuele thema kaart
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
// Initialiseer geselecteerde thema-kaart
const activeTheme = localStorage.getItem('fociz_theme') || '<?= $userTheme ?>' || 'dark';
updateProfileThemeUI(activeTheme);
// Permissie status
if (!("Notification" in window)) return; if (!("Notification" in window)) return;
const grantedEl = document.getElementById('profileNotifPermGranted'); const grantedEl = document.getElementById('profileNotifPermGranted');
const reqEl = document.getElementById('profileNotifPermRequest'); const reqEl = document.getElementById('profileNotifPermRequest');
@@ -700,4 +876,3 @@ document.addEventListener('DOMContentLoaded', () => {
</script> </script>
<?php require_once __DIR__ . '/includes/footer.php'; ?> <?php require_once __DIR__ . '/includes/footer.php'; ?>
+57 -58
View File
@@ -35,37 +35,37 @@ $roadmapItems = $stmt->fetchAll();
$quarters = ['Q1', 'Q2', 'Q3', 'Q4']; $quarters = ['Q1', 'Q2', 'Q3', 'Q4'];
?> ?>
<div class="space-y-6"> <div class="space-y-6 max-w-7xl mx-auto">
<!-- Header --> <!-- Header -->
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 bg-slate-900/80 border border-slate-800 rounded-2xl p-6 shadow-xl"> <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 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 transition">
<div> <div>
<div class="flex items-center space-x-2 text-emerald-400 text-xs font-semibold uppercase tracking-wider mb-1"> <div class="flex items-center space-x-2 text-emerald-600 dark:text-emerald-400 text-xs font-bold uppercase tracking-wider mb-1">
<i data-lucide="map" class="w-4 h-4"></i> <i data-lucide="map" class="w-4 h-4"></i>
<span>Planning & Strategie</span> <span>Planning & Strategie</span>
</div> </div>
<h1 class="text-2xl sm:text-3xl font-black text-white tracking-tight"> <h1 class="text-2xl sm:text-3xl font-black text-slate-900 dark:text-white tracking-tight">
Roadmap & Tijdlijn Roadmap & Tijdlijn
</h1> </h1>
<p class="text-slate-400 text-xs sm:text-sm mt-1"> <p class="text-slate-500 dark:text-slate-400 text-xs sm:text-sm mt-1">
Centraal overzicht van alle mijlpalen, features en doelen, direct voortgekomen uit brainstorms en gesynchroniseerd met Jira. Centraal overzicht van alle mijlpalen, features en doelen, direct voortgekomen uit brainstorms en gesynchroniseerd met Jira.
</p> </p>
</div> </div>
<button onclick="document.getElementById('newItemModal').classList.remove('hidden')" class="flex items-center space-x-2 px-4 py-2.5 rounded-xl bg-emerald-500 hover:bg-emerald-600 text-slate-950 text-xs font-bold transition shadow-lg shadow-emerald-500/20 flex-shrink-0"> <button onclick="document.getElementById('newItemModal').classList.remove('hidden')" class="flex items-center space-x-2 px-4 py-2.5 rounded-xl bg-emerald-500 hover:bg-emerald-600 text-slate-950 text-xs font-bold transition shadow-lg shadow-emerald-500/20 flex-shrink-0 cursor-pointer">
<i data-lucide="plus" class="w-4 h-4"></i> <i data-lucide="plus" class="w-4 h-4"></i>
<span>Nieuw Item</span> <span>Nieuw Item</span>
</button> </button>
</div> </div>
<!-- Filters: Quarters & Status --> <!-- Filters: Quarters & Status -->
<div class="flex flex-wrap items-center justify-between gap-3 bg-slate-900/40 border border-slate-800/80 rounded-2xl p-4"> <div class="flex flex-wrap items-center justify-between gap-3 bg-white dark:bg-slate-900/40 border border-slate-200 dark:border-slate-800/80 rounded-2xl p-4 shadow-sm transition">
<!-- Quarter Tabs --> <!-- Quarter Tabs -->
<div class="flex items-center space-x-1 text-xs"> <div class="flex items-center space-x-1 text-xs">
<a href="/roadmap.php?quarter=ALL&status=<?= htmlspecialchars($selectedStatus) ?>" class="px-3 py-1.5 rounded-xl transition font-medium <?= $selectedQuarter === 'ALL' ? 'bg-emerald-500 text-slate-950 font-bold' : 'text-slate-400 hover:text-slate-200 hover:bg-slate-800' ?>"> <a href="/roadmap.php?quarter=ALL&status=<?= htmlspecialchars($selectedStatus) ?>" class="px-3 py-1.5 rounded-xl transition font-medium <?= $selectedQuarter === 'ALL' ? 'bg-emerald-500 text-slate-950 font-bold shadow-sm' : 'text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 hover:bg-slate-100 dark:hover:bg-slate-800' ?>">
Alle Quarters Alle Quarters
</a> </a>
<?php foreach ($quarters as $q): ?> <?php foreach ($quarters as $q): ?>
<a href="/roadmap.php?quarter=<?= $q ?>&status=<?= htmlspecialchars($selectedStatus) ?>" class="px-3 py-1.5 rounded-xl transition font-medium <?= $selectedQuarter === $q ? 'bg-emerald-500 text-slate-950 font-bold' : 'text-slate-400 hover:text-slate-200 hover:bg-slate-800' ?>"> <a href="/roadmap.php?quarter=<?= $q ?>&status=<?= htmlspecialchars($selectedStatus) ?>" class="px-3 py-1.5 rounded-xl transition font-medium <?= $selectedQuarter === $q ? 'bg-emerald-500 text-slate-950 font-bold shadow-sm' : 'text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 hover:bg-slate-100 dark:hover:bg-slate-800' ?>">
<?= $q ?> <?= $q ?>
</a> </a>
<?php endforeach; ?> <?php endforeach; ?>
@@ -73,8 +73,8 @@ $quarters = ['Q1', 'Q2', 'Q3', 'Q4'];
<!-- Status Filter --> <!-- Status Filter -->
<div class="flex items-center space-x-2 text-xs"> <div class="flex items-center space-x-2 text-xs">
<span class="text-slate-500">Status:</span> <span class="text-slate-500 dark:text-slate-400 font-medium">Status:</span>
<select onchange="window.location.href='/roadmap.php?quarter=<?= htmlspecialchars($selectedQuarter) ?>&status='+this.value" class="bg-slate-800 border border-slate-700 rounded-xl px-2.5 py-1 text-white text-xs focus:outline-none"> <select onchange="window.location.href='/roadmap.php?quarter=<?= htmlspecialchars($selectedQuarter) ?>&status='+this.value" class="bg-slate-50 dark:bg-slate-800 border border-slate-300 dark:border-slate-700 rounded-xl px-2.5 py-1 text-slate-900 dark:text-white text-xs focus:outline-none">
<option value="ALL" <?= $selectedStatus === 'ALL' ? 'selected' : '' ?>>Alle Statussen</option> <option value="ALL" <?= $selectedStatus === 'ALL' ? 'selected' : '' ?>>Alle Statussen</option>
<option value="PLANNED" <?= $selectedStatus === 'PLANNED' ? 'selected' : '' ?>>Gepland</option> <option value="PLANNED" <?= $selectedStatus === 'PLANNED' ? 'selected' : '' ?>>Gepland</option>
<option value="IN_PROGRESS" <?= $selectedStatus === 'IN_PROGRESS' ? 'selected' : '' ?>>In Uitvoering</option> <option value="IN_PROGRESS" <?= $selectedStatus === 'IN_PROGRESS' ? 'selected' : '' ?>>In Uitvoering</option>
@@ -87,38 +87,38 @@ $quarters = ['Q1', 'Q2', 'Q3', 'Q4'];
<!-- Roadmap Items Lijst --> <!-- Roadmap Items Lijst -->
<div class="space-y-4"> <div class="space-y-4">
<?php if (empty($roadmapItems)): ?> <?php if (empty($roadmapItems)): ?>
<div class="bg-slate-900/60 border border-slate-800/80 rounded-2xl p-12 text-center"> <div class="bg-white dark:bg-slate-900/60 border border-slate-200 dark:border-slate-800/80 rounded-3xl p-12 text-center shadow-sm">
<i data-lucide="map-pin" class="w-12 h-12 text-emerald-500/40 mx-auto mb-3"></i> <i data-lucide="map-pin" class="w-12 h-12 text-emerald-500/40 mx-auto mb-3"></i>
<h3 class="text-base font-bold text-white">Geen items gevonden op de roadmap</h3> <h3 class="text-base font-bold text-slate-900 dark:text-white">Geen items gevonden op de roadmap</h3>
<p class="text-xs text-slate-400 mt-1 max-w-sm mx-auto"> <p class="text-xs text-slate-500 dark:text-slate-400 mt-1 max-w-sm mx-auto">
Ga naar een <a href="/brainstorm.php" class="text-amber-400 underline">Brainstorm sessie</a> en zet ideeën met één klik om naar de roadmap, of voeg handmatig een item toe. Ga naar een <a href="/brainstorm.php" class="text-amber-600 dark:text-amber-400 underline font-semibold">Brainstorm sessie</a> en zet ideeën met één klik om naar de roadmap, of voeg handmatig een item toe.
</p> </p>
</div> </div>
<?php else: ?> <?php else: ?>
<?php foreach ($roadmapItems as $item): ?> <?php foreach ($roadmapItems as $item): ?>
<div class="bg-slate-900/80 border border-slate-800 hover:border-slate-700 rounded-2xl p-5 shadow-lg transition space-y-3" id="roadmap-item-<?= $item['id'] ?>"> <div class="bg-white dark:bg-slate-900/80 border border-slate-200 dark:border-slate-800 hover:border-slate-300 dark:hover:border-slate-700 rounded-3xl p-5 shadow-sm hover:shadow-md dark:shadow-lg transition space-y-3" id="roadmap-item-<?= $item['id'] ?>">
<!-- Top header van item --> <!-- Top header van item -->
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-2"> <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-2">
<div class="flex items-center space-x-2.5 flex-wrap"> <div class="flex items-center space-x-2.5 flex-wrap">
<!-- Quarter badge --> <!-- Quarter badge -->
<span class="px-2.5 py-0.5 rounded-full bg-emerald-500/15 text-emerald-400 font-mono text-xs font-bold border border-emerald-500/30"> <span class="px-2.5 py-0.5 rounded-full bg-emerald-500/15 text-emerald-700 dark:text-emerald-400 font-mono text-xs font-bold border border-emerald-500/30">
<?= htmlspecialchars($item['quarter']) ?> <?= htmlspecialchars($item['quarter']) ?>
</span> </span>
<!-- Type badge --> <!-- Type badge -->
<span class="px-2 py-0.5 rounded-full bg-slate-800 text-slate-300 text-[10px] font-semibold"> <span class="px-2 py-0.5 rounded-full bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-300 text-[10px] font-semibold">
<?= htmlspecialchars($item['type']) ?> <?= htmlspecialchars($item['type']) ?>
</span> </span>
<!-- Priority badge --> <!-- Priority badge -->
<span class="text-[10px] font-bold px-2 py-0.5 rounded-full <?= $item['priority'] === 'CRITICAL' ? 'bg-red-500/20 text-red-400' : ($item['priority'] === 'HIGH' ? 'bg-amber-500/20 text-amber-400' : 'bg-slate-800 text-slate-400') ?>"> <span class="text-[10px] font-bold px-2 py-0.5 rounded-full <?= $item['priority'] === 'CRITICAL' ? 'bg-red-500/15 text-red-700 dark:text-red-400 border border-red-500/30' : ($item['priority'] === 'HIGH' ? 'bg-amber-500/15 text-amber-700 dark:text-amber-400 border border-amber-500/30' : 'bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400') ?>">
<?= htmlspecialchars($item['priority']) ?> <?= htmlspecialchars($item['priority']) ?>
</span> </span>
<!-- Jira Issue Key link --> <!-- Jira Issue Key link -->
<?php if (!empty($item['jira_issue_key'])): ?> <?php if (!empty($item['jira_issue_key'])): ?>
<a href="/profile.php" class="flex items-center space-x-1 px-2 py-0.5 rounded-full bg-blue-950/60 border border-blue-800/60 text-blue-300 text-[10px] font-mono hover:underline"> <a href="/profile.php" class="flex items-center space-x-1 px-2 py-0.5 rounded-full bg-blue-50 dark:bg-blue-950/60 border border-blue-200 dark:border-blue-800/60 text-blue-700 dark:text-blue-300 text-[10px] font-mono hover:underline">
<i data-lucide="layers" class="w-3 h-3"></i> <i data-lucide="layers" class="w-3 h-3"></i>
<span><?= htmlspecialchars($item['jira_issue_key']) ?></span> <span><?= htmlspecialchars($item['jira_issue_key']) ?></span>
</a> </a>
@@ -127,14 +127,14 @@ $quarters = ['Q1', 'Q2', 'Q3', 'Q4'];
<!-- Status Selector --> <!-- Status Selector -->
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<select onchange="updateRoadmapStatus(<?= $item['id'] ?>, this.value)" class="bg-slate-950 border border-slate-700 rounded-lg px-2.5 py-1 text-xs text-slate-200 font-semibold focus:outline-none"> <select onchange="updateRoadmapStatus(<?= $item['id'] ?>, this.value)" class="bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-700 rounded-xl px-2.5 py-1 text-xs text-slate-800 dark:text-slate-200 font-semibold focus:outline-none">
<option value="PLANNED" <?= $item['status'] === 'PLANNED' ? 'selected' : '' ?>>⏳ Gepland</option> <option value="PLANNED" <?= $item['status'] === 'PLANNED' ? 'selected' : '' ?>>⏳ Gepland</option>
<option value="IN_PROGRESS" <?= $item['status'] === 'IN_PROGRESS' ? 'selected' : '' ?>>⚡ In Uitvoering</option> <option value="IN_PROGRESS" <?= $item['status'] === 'IN_PROGRESS' ? 'selected' : '' ?>>⚡ In Uitvoering</option>
<option value="REVIEW" <?= $item['status'] === 'REVIEW' ? 'selected' : '' ?>>🔍 In Review</option> <option value="REVIEW" <?= $item['status'] === 'REVIEW' ? 'selected' : '' ?>>🔍 In Review</option>
<option value="COMPLETED" <?= $item['status'] === 'COMPLETED' ? 'selected' : '' ?>>✅ Voltooid</option> <option value="COMPLETED" <?= $item['status'] === 'COMPLETED' ? 'selected' : '' ?>>✅ Voltooid</option>
</select> </select>
<button onclick="deleteRoadmapItem(<?= $item['id'] ?>)" title="Verwijderen" class="p-1.5 rounded-lg text-slate-600 hover:text-red-400 hover:bg-red-500/10 transition"> <button onclick="deleteRoadmapItem(<?= $item['id'] ?>)" title="Verwijderen" class="p-1.5 rounded-lg text-slate-400 hover:text-red-600 dark:text-slate-600 dark:hover:text-red-400 hover:bg-red-500/10 transition cursor-pointer">
<i data-lucide="trash-2" class="w-4 h-4"></i> <i data-lucide="trash-2" class="w-4 h-4"></i>
</button> </button>
</div> </div>
@@ -142,11 +142,11 @@ $quarters = ['Q1', 'Q2', 'Q3', 'Q4'];
<!-- Titel & Beschrijving --> <!-- Titel & Beschrijving -->
<div> <div>
<h3 class="text-base font-bold text-white leading-snug"> <h3 class="text-base font-bold text-slate-900 dark:text-white leading-snug">
<?= htmlspecialchars($item['title']) ?> <?= htmlspecialchars($item['title']) ?>
</h3> </h3>
<?php if (!empty($item['description'])): ?> <?php if (!empty($item['description'])): ?>
<p class="text-slate-400 text-xs mt-1 whitespace-pre-wrap"> <p class="text-slate-600 dark:text-slate-400 text-xs mt-1 whitespace-pre-wrap leading-relaxed">
<?= htmlspecialchars($item['description']) ?> <?= htmlspecialchars($item['description']) ?>
</p> </p>
<?php endif; ?> <?php endif; ?>
@@ -154,33 +154,33 @@ $quarters = ['Q1', 'Q2', 'Q3', 'Q4'];
<!-- Origin Brainstorm snippet --> <!-- Origin Brainstorm snippet -->
<?php if (!empty($item['origin_brainstorm_card_id'])): ?> <?php if (!empty($item['origin_brainstorm_card_id'])): ?>
<div class="bg-slate-950/50 rounded-xl p-2.5 text-[11px] text-slate-400 flex items-center space-x-2 border border-slate-800"> <div class="bg-slate-50 dark:bg-slate-950/50 rounded-xl p-2.5 text-[11px] text-slate-500 dark:text-slate-400 flex items-center space-x-2 border border-slate-200 dark:border-slate-800">
<i data-lucide="lightbulb" class="w-3.5 h-3.5 text-amber-400 flex-shrink-0"></i> <i data-lucide="lightbulb" class="w-3.5 h-3.5 text-amber-500 flex-shrink-0"></i>
<span class="truncate">Ontstaan uit brainstormsessie</span> <span class="truncate">Ontstaan uit brainstormsessie</span>
</div> </div>
<?php endif; ?> <?php endif; ?>
<!-- Voortgangsbalk & Deadline --> <!-- Voortgangsbalk & Deadline -->
<div class="pt-2 border-t border-slate-800/60 flex flex-col sm:flex-row sm:items-center justify-between gap-3 text-xs"> <div class="pt-2 border-t border-slate-100 dark:border-slate-800/60 flex flex-col sm:flex-row sm:items-center justify-between gap-3 text-xs">
<!-- Progress Slider --> <!-- Progress Slider -->
<div class="flex items-center space-x-3 flex-1 max-w-md"> <div class="flex items-center space-x-3 flex-1 max-w-md">
<span class="text-slate-400 text-[11px] font-medium w-16">Voortgang:</span> <span class="text-slate-500 dark:text-slate-400 text-[11px] font-medium w-16">Voortgang:</span>
<div class="flex-1 bg-slate-950 h-2 rounded-full overflow-hidden border border-slate-800"> <div class="flex-1 bg-slate-100 dark:bg-slate-950 h-2 rounded-full overflow-hidden border border-slate-200 dark:border-slate-800">
<div class="bg-gradient-to-r from-emerald-500 to-teal-400 h-full transition-all" style="width: <?= $item['progress'] ?>%"></div> <div class="bg-gradient-to-r from-emerald-500 to-teal-400 h-full transition-all" style="width: <?= $item['progress'] ?>%"></div>
</div> </div>
<span class="font-mono text-slate-200 font-bold w-10 text-right"><?= $item['progress'] ?>%</span> <span class="font-mono text-slate-800 dark:text-slate-200 font-bold w-10 text-right"><?= $item['progress'] ?>%</span>
<div class="flex space-x-1"> <div class="flex space-x-1">
<button onclick="updateRoadmapProgress(<?= $item['id'] ?>, 25)" class="px-1.5 py-0.5 rounded bg-slate-800 text-[10px] text-slate-400 hover:text-white">25%</button> <button onclick="updateRoadmapProgress(<?= $item['id'] ?>, 25)" class="px-1.5 py-0.5 rounded bg-slate-100 dark:bg-slate-800 text-[10px] text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white cursor-pointer">25%</button>
<button onclick="updateRoadmapProgress(<?= $item['id'] ?>, 50)" class="px-1.5 py-0.5 rounded bg-slate-800 text-[10px] text-slate-400 hover:text-white">50%</button> <button onclick="updateRoadmapProgress(<?= $item['id'] ?>, 50)" class="px-1.5 py-0.5 rounded bg-slate-100 dark:bg-slate-800 text-[10px] text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white cursor-pointer">50%</button>
<button onclick="updateRoadmapProgress(<?= $item['id'] ?>, 100)" class="px-1.5 py-0.5 rounded bg-emerald-500/20 text-[10px] text-emerald-400 hover:text-emerald-300 font-bold">100%</button> <button onclick="updateRoadmapProgress(<?= $item['id'] ?>, 100)" class="px-1.5 py-0.5 rounded bg-emerald-500/20 text-[10px] text-emerald-700 dark:text-emerald-400 hover:text-emerald-800 dark:hover:text-emerald-300 font-bold cursor-pointer">100%</button>
</div> </div>
</div> </div>
<!-- Deadline & Creator --> <!-- Deadline & Creator -->
<div class="flex items-center space-x-3 text-slate-500 text-[11px]"> <div class="flex items-center space-x-3 text-slate-500 text-[11px]">
<?php if (!empty($item['due_date'])): ?> <?php if (!empty($item['due_date'])): ?>
<span class="flex items-center space-x-1 text-slate-300"> <span class="flex items-center space-x-1 text-slate-700 dark:text-slate-300 font-medium">
<i data-lucide="calendar" class="w-3.5 h-3.5 text-emerald-400"></i> <i data-lucide="calendar" class="w-3.5 h-3.5 text-emerald-600 dark:text-emerald-400"></i>
<span>Deadline: <?= date('d-m-Y', strtotime($item['due_date'])) ?></span> <span>Deadline: <?= date('d-m-Y', strtotime($item['due_date'])) ?></span>
</span> </span>
<?php endif; ?> <?php endif; ?>
@@ -194,33 +194,33 @@ $quarters = ['Q1', 'Q2', 'Q3', 'Q4'];
</div> </div>
<!-- Modal: Nieuw Roadmap Item Handmatig Toevoegen --> <!-- Modal: Nieuw Roadmap Item Handmatig Toevoegen -->
<div id="newItemModal" class="hidden fixed inset-0 z-50 bg-black/70 backdrop-blur-sm flex items-center justify-center p-4"> <div id="newItemModal" class="hidden fixed inset-0 z-50 bg-black/60 dark:bg-black/70 backdrop-blur-sm flex items-center justify-center p-4">
<div class="bg-slate-900 border border-slate-800 rounded-2xl p-6 shadow-2xl max-w-lg w-full"> <div class="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-3xl p-6 shadow-2xl max-w-lg w-full transition">
<div class="flex items-center justify-between mb-4 pb-3 border-b border-slate-800"> <div class="flex items-center justify-between mb-4 pb-3 border-b border-slate-100 dark:border-slate-800">
<h3 class="text-base font-bold text-white flex items-center space-x-2"> <h3 class="text-base font-bold text-slate-900 dark:text-white flex items-center space-x-2">
<i data-lucide="map" class="w-4 h-4 text-emerald-400"></i> <i data-lucide="map" class="w-4 h-4 text-emerald-600 dark:text-emerald-400"></i>
<span>Nieuw Roadmap Item Toevoegen</span> <span>Nieuw Roadmap Item Toevoegen</span>
</h3> </h3>
<button onclick="document.getElementById('newItemModal').classList.add('hidden')" class="text-slate-400 hover:text-white"> <button onclick="document.getElementById('newItemModal').classList.add('hidden')" class="text-slate-400 hover:text-slate-600 dark:hover:text-white cursor-pointer">
<i data-lucide="x" class="w-5 h-5"></i> <i data-lucide="x" class="w-5 h-5"></i>
</button> </button>
</div> </div>
<div class="space-y-4"> <div class="space-y-4">
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Titel / Doel</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Titel / Doel</label>
<input type="text" id="manualTitle" placeholder="Bijv. 2FA Authenticatie afronden" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2 text-white text-xs placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-emerald-500"> <input type="text" id="manualTitle" placeholder="Bijv. 2FA Authenticatie afronden" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3.5 py-2 text-slate-900 dark:text-white text-xs placeholder-slate-400 dark:placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-emerald-500">
</div> </div>
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Beschrijving / Specificatie</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Beschrijving / Specificatie</label>
<textarea id="manualDescription" rows="3" placeholder="Wat houdt deze milestone of feature in?" class="w-full bg-slate-950 border border-slate-800 rounded-xl p-3 text-white text-xs placeholder-slate-500 focus:outline-none resize-none"></textarea> <textarea id="manualDescription" rows="3" placeholder="Wat houdt deze milestone of feature in?" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl p-3 text-slate-900 dark:text-white text-xs placeholder-slate-400 dark:placeholder-slate-500 focus:outline-none resize-none"></textarea>
</div> </div>
<div class="grid grid-cols-2 gap-3"> <div class="grid grid-cols-2 gap-3">
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Kwartaal</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Kwartaal</label>
<select id="manualQuarter" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white text-xs focus:outline-none"> <select id="manualQuarter" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3 py-2 text-slate-900 dark:text-white text-xs focus:outline-none">
<option value="Q1">Q1</option> <option value="Q1">Q1</option>
<option value="Q2">Q2</option> <option value="Q2">Q2</option>
<option value="Q3" selected>Q3</option> <option value="Q3" selected>Q3</option>
@@ -228,8 +228,8 @@ $quarters = ['Q1', 'Q2', 'Q3', 'Q4'];
</select> </select>
</div> </div>
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Type</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Type</label>
<select id="manualType" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white text-xs focus:outline-none"> <select id="manualType" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3 py-2 text-slate-900 dark:text-white text-xs focus:outline-none">
<option value="FEATURE" selected>Feature</option> <option value="FEATURE" selected>Feature</option>
<option value="EPIC">Epic</option> <option value="EPIC">Epic</option>
<option value="MILESTONE">Mijlpaal</option> <option value="MILESTONE">Mijlpaal</option>
@@ -240,8 +240,8 @@ $quarters = ['Q1', 'Q2', 'Q3', 'Q4'];
<div class="grid grid-cols-2 gap-3"> <div class="grid grid-cols-2 gap-3">
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Prioriteit</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Prioriteit</label>
<select id="manualPriority" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white text-xs focus:outline-none"> <select id="manualPriority" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3 py-2 text-slate-900 dark:text-white text-xs focus:outline-none">
<option value="CRITICAL">Kritiek</option> <option value="CRITICAL">Kritiek</option>
<option value="HIGH" selected>Hoog</option> <option value="HIGH" selected>Hoog</option>
<option value="MEDIUM">Normaal</option> <option value="MEDIUM">Normaal</option>
@@ -249,21 +249,21 @@ $quarters = ['Q1', 'Q2', 'Q3', 'Q4'];
</select> </select>
</div> </div>
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Jira Issue Key (optioneel)</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Jira Issue Key (optioneel)</label>
<input type="text" id="manualJiraKey" placeholder="Bijv. FOC-101" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-1.5 text-white text-xs font-mono focus:outline-none"> <input type="text" id="manualJiraKey" placeholder="Bijv. FOC-101" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3 py-1.5 text-slate-900 dark:text-white text-xs font-mono focus:outline-none">
</div> </div>
</div> </div>
<div> <div>
<label class="block text-xs font-medium text-slate-300 mb-1">Streefdatum</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Streefdatum</label>
<input type="date" id="manualDueDate" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-1.5 text-white text-xs focus:outline-none"> <input type="date" id="manualDueDate" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3 py-1.5 text-slate-900 dark:text-white text-xs focus:outline-none">
</div> </div>
<div class="flex space-x-2 pt-2"> <div class="flex space-x-2 pt-2">
<button onclick="submitManualItem()" class="flex-1 bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold py-2.5 px-4 rounded-xl text-xs transition"> <button onclick="submitManualItem()" class="flex-1 bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold py-2.5 px-4 rounded-xl text-xs transition cursor-pointer">
Toevoegen aan Roadmap Toevoegen aan Roadmap
</button> </button>
<button onclick="document.getElementById('newItemModal').classList.add('hidden')" class="px-4 py-2.5 bg-slate-800 hover:bg-slate-700 text-slate-300 rounded-xl text-xs transition"> <button onclick="document.getElementById('newItemModal').classList.add('hidden')" class="px-4 py-2.5 bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-300 rounded-xl text-xs transition cursor-pointer">
Annuleren Annuleren
</button> </button>
</div> </div>
@@ -326,4 +326,3 @@ async function submitManualItem() {
</script> </script>
<?php require_once __DIR__ . '/includes/footer.php'; ?> <?php require_once __DIR__ . '/includes/footer.php'; ?>
+51 -51
View File
@@ -65,43 +65,44 @@ $invites = $db->query("
ORDER BY i.created_at DESC ORDER BY i.created_at DESC
")->fetchAll(); ")->fetchAll();
$pageTitle = 'Team & Uitnodigingen — Fociz';
require_once __DIR__ . '/includes/header.php'; require_once __DIR__ . '/includes/header.php';
?> ?>
<div class="space-y-6"> <div class="space-y-6 max-w-7xl mx-auto pb-12">
<!-- Header --> <!-- Header -->
<div class="bg-slate-900/80 border border-slate-800 rounded-2xl p-6 shadow-xl"> <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 transition">
<div class="flex items-center space-x-2 text-emerald-400 text-xs font-semibold uppercase tracking-wider mb-1"> <div class="flex items-center space-x-2 text-emerald-600 dark:text-emerald-400 text-xs font-bold uppercase tracking-wider mb-1">
<i data-lucide="shield" class="w-4 h-4"></i> <i data-lucide="shield" class="w-4 h-4"></i>
<span>Beheerderspaneel</span> <span>Beheerderspaneel</span>
</div> </div>
<h1 class="text-2xl sm:text-3xl font-black text-white tracking-tight"> <h1 class="text-2xl sm:text-3xl font-black text-slate-900 dark:text-white tracking-tight">
Team & Uitnodigingen Team & Uitnodigingen
</h1> </h1>
<p class="text-slate-400 text-xs sm:text-sm mt-1"> <p class="text-slate-500 dark:text-slate-400 text-xs sm:text-sm mt-1">
Fociz is strikt afgesloten: nieuwe collega's kunnen enkel toegang krijgen na het ontvangen van een uitnodigingslink en verplichte 2FA-activatie. Fociz is strikt afgesloten: nieuwe collega's kunnen enkel toegang krijgen na het ontvangen van een uitnodigingslink en verplichte 2FA-activatie.
</p> </p>
</div> </div>
<?php if ($error): ?> <?php if ($error): ?>
<div class="p-4 rounded-xl bg-red-500/10 border border-red-500/30 text-red-400 text-xs font-semibold flex items-center space-x-2"> <div class="p-4 rounded-2xl bg-red-500/10 border border-red-500/30 text-red-700 dark:text-red-400 text-xs font-semibold flex items-center space-x-2">
<i data-lucide="alert-triangle" class="w-4 h-4"></i> <i data-lucide="alert-triangle" class="w-4 h-4"></i>
<span><?= htmlspecialchars($error) ?></span> <span><?= htmlspecialchars($error) ?></span>
</div> </div>
<?php endif; ?> <?php endif; ?>
<?php if ($message && $generatedLink): ?> <?php if ($message && $generatedLink): ?>
<div class="p-5 rounded-2xl bg-emerald-950/40 border border-emerald-500/40 text-white space-y-2 shadow-xl"> <div class="p-5 rounded-3xl bg-emerald-50 dark:bg-emerald-950/40 border border-emerald-300 dark:border-emerald-500/40 text-slate-900 dark:text-white space-y-2 shadow-sm dark:shadow-xl transition">
<div class="flex items-center space-x-2 text-emerald-400 font-bold text-xs"> <div class="flex items-center space-x-2 text-emerald-700 dark:text-emerald-400 font-bold text-xs">
<i data-lucide="check-circle-2" class="w-4 h-4"></i> <i data-lucide="check-circle-2" class="w-4 h-4"></i>
<span><?= htmlspecialchars($message) ?></span> <span><?= htmlspecialchars($message) ?></span>
</div> </div>
<p class="text-xs text-slate-300"> <p class="text-xs text-slate-600 dark:text-slate-300">
Kopieer onderstaande beveiligde registratielink en stuur deze naar de collega: Kopieer onderstaande beveiligde registratielink en stuur deze naar de collega:
</p> </p>
<div class="flex items-center space-x-2 bg-slate-950 p-2.5 rounded-xl border border-slate-800"> <div class="flex items-center space-x-2 bg-white dark:bg-slate-950 p-2.5 rounded-2xl border border-emerald-200 dark:border-slate-800">
<input type="text" readonly id="inviteLinkInput" value="<?= htmlspecialchars($generatedLink) ?>" class="bg-transparent text-emerald-300 font-mono text-xs flex-1 outline-none"> <input type="text" readonly id="inviteLinkInput" value="<?= htmlspecialchars($generatedLink) ?>" class="bg-transparent text-emerald-700 dark:text-emerald-300 font-mono text-xs flex-1 outline-none">
<button onclick="copyInviteLink()" class="px-3 py-1.5 bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold text-xs rounded-lg transition flex items-center space-x-1"> <button onclick="copyInviteLink()" class="px-3 py-1.5 bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold text-xs rounded-xl transition flex items-center space-x-1 cursor-pointer">
<i data-lucide="copy" class="w-3.5 h-3.5"></i> <i data-lucide="copy" class="w-3.5 h-3.5"></i>
<span id="copyBtnText">Kopiëren</span> <span id="copyBtnText">Kopiëren</span>
</button> </button>
@@ -110,9 +111,9 @@ require_once __DIR__ . '/includes/header.php';
<?php endif; ?> <?php endif; ?>
<!-- Uitnodiging Genereren Kaart --> <!-- Uitnodiging Genereren Kaart -->
<div class="bg-slate-900/80 border border-slate-800 rounded-2xl p-6 shadow-xl"> <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 transition">
<h3 class="text-base font-bold text-white mb-4 flex items-center space-x-2"> <h3 class="text-base font-bold text-slate-900 dark:text-white mb-4 flex items-center space-x-2">
<i data-lucide="user-plus" class="w-5 h-5 text-emerald-400"></i> <i data-lucide="user-plus" class="w-5 h-5 text-emerald-600 dark:text-emerald-400"></i>
<span>Nieuwe Collega Uitnodigen</span> <span>Nieuwe Collega Uitnodigen</span>
</h3> </h3>
@@ -120,20 +121,20 @@ require_once __DIR__ . '/includes/header.php';
<input type="hidden" name="action" value="create_invite"> <input type="hidden" name="action" value="create_invite">
<div class="md:col-span-6"> <div class="md:col-span-6">
<label class="block text-xs font-medium text-slate-300 mb-1">E-mailadres van collega</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">E-mailadres van collega</label>
<input type="email" name="email" required placeholder="collega@bedrijf.nl" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-4 py-2.5 text-white placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-emerald-500 text-xs"> <input type="email" name="email" required placeholder="collega@bedrijf.nl" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-4 py-2.5 text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-emerald-500 text-xs">
</div> </div>
<div class="md:col-span-3"> <div class="md:col-span-3">
<label class="block text-xs font-medium text-slate-300 mb-1">Rol</label> <label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1">Rol</label>
<select name="role" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2.5 text-white text-xs focus:outline-none"> <select name="role" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-300 dark:border-slate-800 rounded-xl px-3 py-2.5 text-slate-900 dark:text-white text-xs focus:outline-none">
<option value="MEMBER">Collega (Standaard)</option> <option value="MEMBER">Collega (Standaard)</option>
<option value="ADMIN">Mede-beheerder</option> <option value="ADMIN">Mede-beheerder</option>
</select> </select>
</div> </div>
<div class="md:col-span-3"> <div class="md:col-span-3">
<button type="submit" class="w-full bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold py-2.5 px-4 rounded-xl text-xs transition shadow-lg shadow-emerald-500/20 flex items-center justify-center space-x-2"> <button type="submit" class="w-full bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold py-2.5 px-4 rounded-xl text-xs transition shadow-lg shadow-emerald-500/20 flex items-center justify-center space-x-2 cursor-pointer">
<i data-lucide="link" class="w-4 h-4"></i> <i data-lucide="link" class="w-4 h-4"></i>
<span>Genereer Link</span> <span>Genereer Link</span>
</button> </button>
@@ -142,17 +143,17 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
<!-- Actieve Gebruikers Tabel --> <!-- Actieve Gebruikers Tabel -->
<div class="bg-slate-900/80 border border-slate-800 rounded-2xl p-6 shadow-xl space-y-4"> <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 justify-between pb-3 border-b border-slate-800"> <div class="flex items-center justify-between pb-3 border-b border-slate-100 dark:border-slate-800">
<h3 class="text-sm font-bold text-white uppercase tracking-wider flex items-center space-x-2"> <h3 class="text-sm font-bold text-slate-900 dark:text-white uppercase tracking-wider flex items-center space-x-2">
<i data-lucide="users" class="w-4 h-4 text-emerald-400"></i> <i data-lucide="users" class="w-4 h-4 text-emerald-600 dark:text-emerald-400"></i>
<span>Geregistreerde Teamleden (<?= count($users) ?>)</span> <span>Geregistreerde Teamleden (<?= count($users) ?>)</span>
</h3> </h3>
</div> </div>
<div class="overflow-x-auto"> <div class="overflow-x-auto">
<table class="w-full text-left text-xs text-slate-300"> <table class="w-full text-left text-xs text-slate-700 dark:text-slate-300">
<thead class="bg-slate-950/60 text-slate-400 uppercase text-[10px] tracking-wider border-b border-slate-800"> <thead class="bg-slate-50 dark:bg-slate-950/60 text-slate-500 dark:text-slate-400 uppercase text-[10px] tracking-wider border-b border-slate-200 dark:border-slate-800">
<tr> <tr>
<th class="p-3">Naam & E-mail</th> <th class="p-3">Naam & E-mail</th>
<th class="p-3">Rol</th> <th class="p-3">Rol</th>
@@ -161,34 +162,34 @@ require_once __DIR__ . '/includes/header.php';
<th class="p-3 text-right">Acties</th> <th class="p-3 text-right">Acties</th>
</tr> </tr>
</thead> </thead>
<tbody class="divide-y divide-slate-800/60"> <tbody class="divide-y divide-slate-100 dark:divide-slate-800/60">
<?php foreach ($users as $u): ?> <?php foreach ($users as $u): ?>
<tr class="hover:bg-slate-800/30 transition"> <tr class="hover:bg-slate-50 dark:hover:bg-slate-800/30 transition">
<td class="p-3"> <td class="p-3">
<div class="font-bold text-white"><?= htmlspecialchars($u['name']) ?></div> <div class="font-bold text-slate-900 dark:text-white"><?= htmlspecialchars($u['name']) ?></div>
<div class="text-[11px] text-slate-400 font-mono"><?= htmlspecialchars($u['email']) ?></div> <div class="text-[11px] text-slate-500 dark:text-slate-400 font-mono"><?= htmlspecialchars($u['email']) ?></div>
</td> </td>
<td class="p-3"> <td class="p-3">
<span class="px-2 py-0.5 rounded text-[10px] font-bold <?= $u['role'] === 'ADMIN' ? 'bg-emerald-500/20 text-emerald-400 border border-emerald-500/30' : 'bg-slate-800 text-slate-300' ?>"> <span class="px-2 py-0.5 rounded text-[10px] font-bold <?= $u['role'] === 'ADMIN' ? 'bg-emerald-500/15 text-emerald-700 dark:text-emerald-400 border border-emerald-500/30' : 'bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-300' ?>">
<?= $u['role'] === 'ADMIN' ? 'Beheerder' : 'Collega' ?> <?= $u['role'] === 'ADMIN' ? 'Beheerder' : 'Collega' ?>
</span> </span>
</td> </td>
<td class="p-3"> <td class="p-3">
<span class="px-2 py-0.5 rounded-full bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 text-[10px] font-medium flex items-center space-x-1 w-max"> <span class="px-2 py-0.5 rounded-full bg-emerald-500/10 text-emerald-700 dark:text-emerald-400 border border-emerald-500/20 text-[10px] font-medium flex items-center space-x-1 w-max">
<i data-lucide="shield-check" class="w-3 h-3"></i> <i data-lucide="shield-check" class="w-3 h-3"></i>
<span>2FA Actief</span> <span>2FA Actief</span>
</span> </span>
</td> </td>
<td class="p-3 text-slate-400"> <td class="p-3 text-slate-500 dark:text-slate-400">
<?= date('d-m-Y', strtotime($u['created_at'])) ?> <?= date('d-m-Y', strtotime($u['created_at'])) ?>
</td> </td>
<td class="p-3 text-right"> <td class="p-3 text-right">
<?php if ($u['id'] !== $adminUser['id']): ?> <?php if ($u['id'] !== $adminUser['id']): ?>
<a href="/users.php?delete_user=<?= $u['id'] ?>" onclick="return confirm('Gebruiker verwijderen?')" class="text-slate-500 hover:text-red-400 transition p-1"> <a href="/users.php?delete_user=<?= $u['id'] ?>" onclick="return confirm('Gebruiker verwijderen?')" class="text-slate-400 hover:text-red-600 dark:text-slate-500 dark:hover:text-red-400 transition p-1 cursor-pointer">
<i data-lucide="trash-2" class="w-4 h-4 inline"></i> <i data-lucide="trash-2" class="w-4 h-4 inline"></i>
</a> </a>
<?php else: ?> <?php else: ?>
<span class="text-[10px] text-slate-600 font-medium">Uzelf</span> <span class="text-[10px] text-slate-400 dark:text-slate-600 font-medium">Uzelf</span>
<?php endif; ?> <?php endif; ?>
</td> </td>
</tr> </tr>
@@ -199,17 +200,17 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
<!-- Uitstaande Uitnodigingen Tabel --> <!-- Uitstaande Uitnodigingen Tabel -->
<div class="bg-slate-900/80 border border-slate-800 rounded-2xl p-6 shadow-xl space-y-4"> <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 justify-between pb-3 border-b border-slate-800"> <div class="flex items-center justify-between pb-3 border-b border-slate-100 dark:border-slate-800">
<h3 class="text-sm font-bold text-white uppercase tracking-wider flex items-center space-x-2"> <h3 class="text-sm font-bold text-slate-900 dark:text-white uppercase tracking-wider flex items-center space-x-2">
<i data-lucide="mail" class="w-4 h-4 text-amber-400"></i> <i data-lucide="mail" class="w-4 h-4 text-amber-500"></i>
<span>Uitnodigingen Status (<?= count($invites) ?>)</span> <span>Uitnodigingen Status (<?= count($invites) ?>)</span>
</h3> </h3>
</div> </div>
<div class="overflow-x-auto"> <div class="overflow-x-auto">
<table class="w-full text-left text-xs text-slate-300"> <table class="w-full text-left text-xs text-slate-700 dark:text-slate-300">
<thead class="bg-slate-950/60 text-slate-400 uppercase text-[10px] tracking-wider border-b border-slate-800"> <thead class="bg-slate-50 dark:bg-slate-950/60 text-slate-500 dark:text-slate-400 uppercase text-[10px] tracking-wider border-b border-slate-200 dark:border-slate-800">
<tr> <tr>
<th class="p-3">Uitgenodigd E-mailadres</th> <th class="p-3">Uitgenodigd E-mailadres</th>
<th class="p-3">Rol</th> <th class="p-3">Rol</th>
@@ -218,29 +219,29 @@ require_once __DIR__ . '/includes/header.php';
<th class="p-3 text-right">Actie</th> <th class="p-3 text-right">Actie</th>
</tr> </tr>
</thead> </thead>
<tbody class="divide-y divide-slate-800/60"> <tbody class="divide-y divide-slate-100 dark:divide-slate-800/60">
<?php if (empty($invites)): ?> <?php if (empty($invites)): ?>
<tr><td colspan="5" class="p-4 text-center text-slate-500">Nog geen uitnodigingen verstuurd.</td></tr> <tr><td colspan="5" class="p-4 text-center text-slate-400 dark:text-slate-500">Nog geen uitnodigingen verstuurd.</td></tr>
<?php else: ?> <?php else: ?>
<?php foreach ($invites as $inv): <?php foreach ($invites as $inv):
$isUsed = !empty($inv['used_at']); $isUsed = !empty($inv['used_at']);
$isExpired = strtotime($inv['expires_at']) < time(); $isExpired = strtotime($inv['expires_at']) < time();
?> ?>
<tr class="hover:bg-slate-800/30 transition"> <tr class="hover:bg-slate-50 dark:hover:bg-slate-800/30 transition">
<td class="p-3 font-mono"><?= htmlspecialchars($inv['email']) ?></td> <td class="p-3 font-mono text-slate-900 dark:text-white"><?= htmlspecialchars($inv['email']) ?></td>
<td class="p-3"><?= htmlspecialchars($inv['role']) ?></td> <td class="p-3"><?= htmlspecialchars($inv['role']) ?></td>
<td class="p-3"> <td class="p-3">
<?php if ($isUsed): ?> <?php if ($isUsed): ?>
<span class="px-2 py-0.5 rounded text-[10px] font-bold bg-emerald-500/20 text-emerald-400">Geaccepteerd</span> <span class="px-2 py-0.5 rounded text-[10px] font-bold bg-emerald-500/15 text-emerald-700 dark:text-emerald-400 border border-emerald-500/30">Geaccepteerd</span>
<?php elseif ($isExpired): ?> <?php elseif ($isExpired): ?>
<span class="px-2 py-0.5 rounded text-[10px] font-bold bg-red-500/20 text-red-400">Verlopen</span> <span class="px-2 py-0.5 rounded text-[10px] font-bold bg-red-500/15 text-red-700 dark:text-red-400 border border-red-500/30">Verlopen</span>
<?php else: ?> <?php else: ?>
<span class="px-2 py-0.5 rounded text-[10px] font-bold bg-amber-500/20 text-amber-400">In afwachting</span> <span class="px-2 py-0.5 rounded text-[10px] font-bold bg-amber-500/15 text-amber-700 dark:text-amber-400 border border-amber-500/30">In afwachting</span>
<?php endif; ?> <?php endif; ?>
</td> </td>
<td class="p-3 text-slate-400"><?= date('d-m-Y H:i', strtotime($inv['expires_at'])) ?></td> <td class="p-3 text-slate-500 dark:text-slate-400"><?= date('d-m-Y H:i', strtotime($inv['expires_at'])) ?></td>
<td class="p-3 text-right"> <td class="p-3 text-right">
<a href="/users.php?delete_invite=<?= $inv['id'] ?>" onclick="return confirm('Uitnodiging intrekken?')" class="text-slate-500 hover:text-red-400 transition p-1"> <a href="/users.php?delete_invite=<?= $inv['id'] ?>" onclick="return confirm('Uitnodiging intrekken?')" class="text-slate-400 hover:text-red-600 dark:text-slate-500 dark:hover:text-red-400 transition p-1 cursor-pointer">
<i data-lucide="trash-2" class="w-4 h-4 inline"></i> <i data-lucide="trash-2" class="w-4 h-4 inline"></i>
</a> </a>
</td> </td>
@@ -266,4 +267,3 @@ function copyInviteLink() {
</script> </script>
<?php require_once __DIR__ . '/includes/footer.php'; ?> <?php require_once __DIR__ . '/includes/footer.php'; ?>