Compare commits

...

2 Commits

+49 -48
View File
@@ -13,24 +13,20 @@ $isAdmin = ($userRole === 'ADMIN');
?> ?>
<style> <style>
/* Volledige breedte benutting en soepele schermmaximalisatie */ /* Soepele overgang voor de lanes container bij maximaliseren */
#boardMainWrapper { #lanesSectionWrapper {
width: 100% !important;
max-width: 100% !important;
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1); transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
} }
#boardMainWrapper.is-maximized { #lanesSectionWrapper.is-maximized {
padding-left: 0 !important; max-width: 100% !important;
padding-right: 0 !important;
}
#boardMainWrapper #boardLanesContainer {
width: 100% !important; width: 100% !important;
} }
</style> </style>
<div id="boardMainWrapper" class="space-y-4 w-full max-w-none"> <div id="boardPageContainer" class="space-y-4 w-full">
<!-- Bovenbalk: Bord Titel, Filters & Actieknoppen --> <!-- Bovenbalk: Bord Titel, Filters & Actieknoppen (ALTIJD vaste standaard breedte) -->
<div class="max-w-7xl mx-auto w-full">
<div class="fociz-card p-4 sm:p-5"> <div class="fociz-card p-4 sm:p-5">
<div class="flex flex-col xl:flex-row xl:items-center justify-between gap-4"> <div class="flex flex-col xl:flex-row xl:items-center justify-between gap-4">
@@ -120,28 +116,34 @@ $isAdmin = ($userRole === 'ADMIN');
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- Lanes Sectie: Wisselt tussen standaard gecentreerde breedte (max-w-7xl) en volledig scherm (max-w-none w-full) -->
<div id="lanesSectionWrapper" class="max-w-7xl mx-auto w-full transition-all duration-300">
<!-- Strook direct boven de lane blokken: klein maximaliseer-icoon rechts --> <!-- Strook direct boven de lane blokken: klein maximaliseer-icoon rechts -->
<div class="flex items-center justify-between px-1 -mb-1"> <div class="flex items-center justify-between px-1 mb-2">
<div class="text-[11px] font-semibold text-slate-500 dark:text-slate-400" id="boardLanesSummary"></div> <div class="text-[11px] font-semibold text-slate-500 dark:text-slate-400" id="boardLanesSummary"></div>
<button <button
id="btnToggleMaximize" id="btnToggleMaximize"
onclick="toggleBoardMaximize()" onclick="toggleBoardMaximize()"
title="Bord maximaliseren naar volledige vensterbreedte" title="Kolommen maximaliseren naar volledige vensterbreedte"
class="w-7 h-7 rounded-lg bg-white dark:bg-[#111624] hover:bg-slate-100 dark:hover:bg-slate-800 border border-slate-200 dark:border-slate-800 text-slate-600 dark:text-slate-300 flex items-center justify-center transition cursor-pointer shadow-2xs hover:scale-105 active:scale-95 ml-auto" class="w-7 h-7 rounded-lg bg-white dark:bg-[#111624] hover:bg-slate-100 dark:hover:bg-slate-800 border border-slate-200 dark:border-slate-800 text-slate-600 dark:text-slate-300 flex items-center justify-center transition cursor-pointer shadow-2xs hover:scale-105 active:scale-95 ml-auto"
> >
<i id="maximizeIcon" data-lucide="maximize-2" class="w-3.5 h-3.5"></i> <i id="maximizeIcon" data-lucide="maximize-2" class="w-3.5 h-3.5"></i>
</button> </button>
</div> </div>
<!-- Kanban Board Container (Horizontaal scrollbaar indien te smal, past automatisch in de breedte) --> <!-- Kanban Board Container (past zich in standaardmodus soepel aan zonder scrollbalk) -->
<div id="boardLanesContainer" class="flex gap-4 overflow-x-auto pb-8 pt-1 min-h-[650px] items-start select-none w-full transition-all duration-300"> <div id="boardLanesContainer" class="flex gap-3 overflow-x-auto pb-2 pt-1 min-h-[440px] items-start select-none w-full transition-all duration-300">
<div class="flex items-center justify-center w-full py-20 text-slate-400 text-sm"> <div class="flex items-center justify-center w-full py-20 text-slate-400 text-sm">
<i data-lucide="loader-2" class="w-5 h-5 animate-spin mr-2"></i> <i data-lucide="loader-2" class="w-5 h-5 animate-spin mr-2"></i>
<span>Bord laden...</span> <span>Bord laden...</span>
</div> </div>
</div> </div>
</div>
</div> </div>
<!-- MODAL 1: Taak (Post-it / Opdracht) Toevoegen of Bewerken --> <!-- MODAL 1: Taak (Post-it / Opdracht) Toevoegen of Bewerken -->
@@ -635,9 +637,9 @@ function renderCards() {
const dotColorClass = LANE_ACCENT_COLORS[lane.color] || 'bg-slate-500'; const dotColorClass = LANE_ACCENT_COLORS[lane.color] || 'bg-slate-500';
// Lane kolom HTML (past zich automatisch aan de schermbreedte aan) // Lane kolom HTML: flex-1 en min-w-[160px] zodat 5+ lanes in standaardmodus binnen 1280px passen zonder scrollbalk
const laneEl = document.createElement('div'); const laneEl = document.createElement('div');
laneEl.className = 'flex-1 min-w-[260px] rounded-2xl bg-slate-100/70 dark:bg-[#0c0f17]/70 border border-slate-200/80 dark:border-slate-800/80 p-3.5 flex flex-col shadow-xs max-h-[82vh] transition-all duration-200'; laneEl.className = 'flex-1 min-w-0 sm:min-w-[160px] rounded-2xl bg-slate-100/70 dark:bg-[#0c0f17]/70 border border-slate-200/80 dark:border-slate-800/80 p-3 flex flex-col shadow-xs max-h-[calc(100vh-310px)] min-h-[440px] transition-all duration-200';
laneEl.setAttribute('data-lane-id', lane.id); laneEl.setAttribute('data-lane-id', lane.id);
let cardsHtml = ''; let cardsHtml = '';
@@ -695,16 +697,16 @@ function renderCards() {
ondragstart="onCardDragStart(event, ${card.id})" ondragstart="onCardDragStart(event, ${card.id})"
ondragend="onCardDragEnd(event)" ondragend="onCardDragEnd(event)"
onclick="onCardClick(event, ${card.id})" onclick="onCardClick(event, ${card.id})"
class="group/card relative p-3.5 rounded-xl border ${colorClass} shadow-2xs hover:shadow-md hover:-translate-y-0.5 transition cursor-grab active:cursor-grabbing mb-2.5" class="group/card relative p-3 rounded-xl border ${colorClass} shadow-2xs hover:shadow-md hover:-translate-y-0.5 transition cursor-grab active:cursor-grabbing mb-2.5"
> >
<div class="flex items-start justify-between gap-2 mb-1.5"> <div class="flex items-start justify-between gap-1.5 mb-1.5">
<h4 class="text-xs font-bold leading-snug line-clamp-2"> <h4 class="text-xs font-bold leading-snug line-clamp-2 break-words">
${escapeHtml(card.title)} ${escapeHtml(card.title)}
</h4> </h4>
${priorityBadge} <div class="flex-shrink-0">${priorityBadge}</div>
</div> </div>
${card.description ? `<p class="text-[11px] opacity-80 line-clamp-2 leading-relaxed mb-2.5">${escapeHtml(card.description)}</p>` : ''} ${card.description ? `<p class="text-[11px] opacity-80 line-clamp-2 leading-relaxed mb-2.5 break-words">${escapeHtml(card.description)}</p>` : ''}
<div class="flex items-center justify-between mt-auto"> <div class="flex items-center justify-between mt-auto">
${assigneeHtml} ${assigneeHtml}
@@ -725,14 +727,14 @@ function renderCards() {
laneEl.innerHTML = ` laneEl.innerHTML = `
<!-- Lane Header --> <!-- Lane Header -->
<div class="flex items-center justify-between pb-3 mb-3 border-b border-slate-200/80 dark:border-slate-800/80"> <div class="flex items-center justify-between pb-2.5 mb-2.5 border-b border-slate-200/80 dark:border-slate-800/80">
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2 min-w-0">
<span class="w-2.5 h-2.5 rounded-full ${dotColorClass}"></span> <span class="w-2.5 h-2.5 rounded-full ${dotColorClass} flex-shrink-0"></span>
<h3 class="text-xs font-bold text-slate-800 dark:text-slate-200 uppercase tracking-wider"> <h3 class="text-xs font-bold text-slate-800 dark:text-slate-200 uppercase tracking-wider truncate">
${escapeHtml(lane.title)} ${escapeHtml(lane.title)}
</h3> </h3>
</div> </div>
<span class="px-2 py-0.5 rounded-full text-[10px] font-bold bg-white dark:bg-slate-800 text-slate-600 dark:text-slate-400 border border-slate-200 dark:border-slate-700 shadow-2xs"> <span class="px-2 py-0.5 rounded-full text-[10px] font-bold bg-white dark:bg-slate-800 text-slate-600 dark:text-slate-400 border border-slate-200 dark:border-slate-700 shadow-2xs flex-shrink-0 ml-1">
${cards.length} ${cards.length}
</span> </span>
</div> </div>
@@ -1206,40 +1208,39 @@ function escapeHtml(str) {
.replace(/'/g, '&#039;'); .replace(/'/g, '&#039;');
} }
// 10. Bord Maximaliseren & Verkleinen (Soepele breedte-overgang) // 10. Kolommen Maximaliseren & Verkleinen (Soepele breedte-overgang)
// De site-header blijft ALTIJD staan.
// De bovenbalk (Hoofdbord, filters, actieknoppen) behoudt altijd de vaste standaard breedte.
// ALLEEN de aparte lanes wisselen tussen standaard gecentreerde breedte en de volledige schermbreedte.
let isBoardMaximized = localStorage.getItem('fociz_board_maximized') === 'true'; let isBoardMaximized = localStorage.getItem('fociz_board_maximized') === 'true';
function applyMaximizeState(isMax) { function applyMaximizeState(isMax) {
const wrapper = document.getElementById('boardMainWrapper'); const lanesWrapper = document.getElementById('lanesSectionWrapper');
const mainContainer = document.getElementById('focizMainContainer'); const mainContainer = document.getElementById('focizMainContainer');
const icon = document.getElementById('maximizeIcon'); const icon = document.getElementById('maximizeIcon');
const btn = document.getElementById('btnToggleMaximize'); const btn = document.getElementById('btnToggleMaximize');
if (!wrapper || !btn) return; if (!lanesWrapper || !btn) return;
// Zorg dat header altijd zichtbaar blijft
document.querySelector('header')?.classList.remove('hidden');
if (mainContainer) {
mainContainer.style.maxWidth = '';
mainContainer.style.paddingLeft = '';
mainContainer.style.paddingRight = '';
}
if (isMax) { if (isMax) {
wrapper.classList.add('is-maximized'); lanesWrapper.classList.remove('max-w-7xl', 'mx-auto');
if (mainContainer) { lanesWrapper.classList.add('is-maximized', 'max-w-none', 'w-full', 'px-1', 'sm:px-3');
mainContainer.style.maxWidth = '100vw'; btn.setAttribute('title', 'Kolommen verkleinen naar standaard breedte (Escape)');
mainContainer.style.width = '100%';
mainContainer.style.paddingLeft = '0.5rem';
mainContainer.style.paddingRight = '0.5rem';
}
document.querySelector('header')?.classList.add('hidden');
btn.setAttribute('title', 'Bord verkleinen / navigatie tonen (Escape)');
if (icon) { if (icon) {
icon.setAttribute('data-lucide', 'minimize-2'); icon.setAttribute('data-lucide', 'minimize-2');
} }
} else { } else {
wrapper.classList.remove('is-maximized'); lanesWrapper.classList.remove('is-maximized', 'max-w-none', 'px-1', 'sm:px-3');
if (mainContainer) { lanesWrapper.classList.add('max-w-7xl', 'mx-auto', 'w-full');
mainContainer.style.maxWidth = ''; btn.setAttribute('title', 'Kolommen maximaliseren naar volledige vensterbreedte');
mainContainer.style.width = '';
mainContainer.style.paddingLeft = '';
mainContainer.style.paddingRight = '';
}
document.querySelector('header')?.classList.remove('hidden');
btn.setAttribute('title', 'Bord maximaliseren (volledig venster)');
if (icon) { if (icon) {
icon.setAttribute('data-lucide', 'maximize-2'); icon.setAttribute('data-lucide', 'maximize-2');
} }