Compare commits

..

2 Commits

4 changed files with 1206 additions and 4 deletions
+95
View File
@@ -486,6 +486,101 @@ try {
exit; exit;
} }
// 10. Tijdlijn Datums Snel Bijwerken (Startdatum & Einddatum via Gantt drag)
if ($action === 'update_card_dates') {
$cardId = (int)($input['card_id'] ?? 0);
$startDate = trim($input['start_date'] ?? '');
$endDate = trim($input['end_date'] ?? $startDate);
if (!$cardId || !$startDate) {
echo json_encode(['success' => false, 'error' => 'Ongeldige parameters.']);
exit;
}
$stmtCard = $db->prepare("SELECT * FROM board_cards WHERE id = ?");
$stmtCard->execute([$cardId]);
$card = $stmtCard->fetch();
if (!$card) {
echo json_encode(['success' => false, 'error' => 'Taak niet gevonden.']);
exit;
}
if (!check_board_access($db, (int)$card['board_id'], $userId, $isAdmin)) {
http_response_code(403);
echo json_encode(['success' => false, 'error' => 'Geen toegang tot dit bord.']);
exit;
}
$stmtSched = $db->prepare("
INSERT INTO board_card_schedules (card_id, schedule_type, start_date, end_date, start_time, end_time, days_of_week)
VALUES (?, 'DAILY_RANGE', ?, ?, '09:00', '17:00', '1,2,3,4,5')
ON DUPLICATE KEY UPDATE
start_date = VALUES(start_date),
end_date = VALUES(end_date),
schedule_type = 'DAILY_RANGE'
");
$stmtSched->execute([$cardId, $startDate, $endDate]);
echo json_encode([
'success' => true,
'card_id' => $cardId,
'start_date' => $startDate,
'end_date' => $endDate,
'message' => 'Tijdlijn bijgewerkt!'
]);
exit;
}
// 11. Snelle Inline Taak Aanmaken (⚡ Wat moet er gedaan worden?)
if ($action === 'quick_create_card') {
$boardId = (int)($input['board_id'] ?? 0);
$title = trim($input['title'] ?? '');
$laneId = (int)($input['lane_id'] ?? 0);
$startDate = !empty($input['start_date']) ? trim($input['start_date']) : null;
$endDate = !empty($input['end_date']) ? trim($input['end_date']) : $startDate;
if (!$boardId || empty($title)) {
echo json_encode(['success' => false, 'error' => 'Vul een titel in voor de taak.']);
exit;
}
if (!check_board_access($db, $boardId, $userId, $isAdmin)) {
http_response_code(403);
echo json_encode(['success' => false, 'error' => 'Geen toegang tot dit bord.']);
exit;
}
// Als geen lane_id is meegegeven, pak de 1e lane van het bord
if ($laneId <= 0) {
$laneId = (int)$db->query("SELECT id FROM board_lanes WHERE board_id = {$boardId} ORDER BY position ASC, id ASC LIMIT 1")->fetchColumn();
}
$maxPos = (int)$db->query("SELECT COALESCE(MAX(position), -1) FROM board_cards WHERE lane_id = {$laneId}")->fetchColumn();
$stmt = $db->prepare("
INSERT INTO board_cards (board_id, lane_id, title, description, assignee_id, priority, color, position, created_by_id)
VALUES (?, ?, ?, '', NULL, 'P2', 'yellow', ?, ?)
");
$stmt->execute([$boardId, $laneId, $title, $maxPos + 1, $userId]);
$newCardId = (int)$db->lastInsertId();
// Optioneel datums toekennen
if ($startDate) {
$stmtSched = $db->prepare("
INSERT INTO board_card_schedules (card_id, schedule_type, start_date, end_date, start_time, end_time, days_of_week)
VALUES (?, 'DAILY_RANGE', ?, ?, '09:00', '17:00', '1,2,3,4,5')
");
$stmtSched->execute([$newCardId, $startDate, $endDate]);
}
echo json_encode([
'success' => true,
'card_id' => $newCardId,
'lane_id' => $laneId,
'message' => 'Taak direct toegevoegd!'
]);
exit;
}
echo json_encode(['success' => false, 'error' => 'Onbekende actie.']); echo json_encode(['success' => false, 'error' => 'Onbekende actie.']);
} catch (Throwable $e) { } catch (Throwable $e) {
error_log("Fociz Board API Fout: " . $e->getMessage()); error_log("Fociz Board API Fout: " . $e->getMessage());
+17
View File
@@ -50,6 +50,18 @@ $isAdmin = ($userRole === 'ADMIN');
</div> </div>
</div> </div>
<!-- Weergave-schakelaar: Bord (Kanban) / Tijdlijn (Gantt) -->
<div class="inline-flex p-1 bg-slate-100/90 dark:bg-[#0c0f17] border border-slate-200/90 dark:border-slate-800/90 rounded-xl text-xs font-semibold shadow-2xs self-start xl:self-center">
<span class="flex items-center space-x-1.5 px-3 py-1.5 rounded-lg bg-white dark:bg-slate-800 text-indigo-600 dark:text-indigo-400 font-bold shadow-2xs cursor-default">
<i data-lucide="kanban" class="w-3.5 h-3.5"></i>
<span>Bord</span>
</span>
<a id="linkToTimeline" href="/timeline.php" class="flex items-center space-x-1.5 px-3 py-1.5 rounded-lg text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white hover:bg-slate-200/60 dark:hover:bg-slate-800/60 transition">
<i data-lucide="clock" class="w-3.5 h-3.5"></i>
<span>Tijdlijn</span>
</a>
</div>
<!-- Midden & Rechts: Filters & Actieknoppen --> <!-- Midden & Rechts: Filters & Actieknoppen -->
<div class="flex flex-wrap items-center gap-2"> <div class="flex flex-wrap items-center gap-2">
@@ -446,6 +458,10 @@ const LANE_ACCENT_COLORS = {
// 1. Initialisatie // 1. Initialisatie
document.addEventListener('DOMContentLoaded', async () => { document.addEventListener('DOMContentLoaded', async () => {
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get('board_id')) {
currentBoardId = parseInt(urlParams.get('board_id'), 10);
}
await loadBoardsList(); await loadBoardsList();
}); });
@@ -494,6 +510,7 @@ function onBoardSelectChange(bId) {
// 2. Data van specifiek bord inladen // 2. Data van specifiek bord inladen
async function loadBoardData(boardId) { async function loadBoardData(boardId) {
currentBoardId = boardId; currentBoardId = boardId;
document.getElementById('linkToTimeline')?.setAttribute('href', `/timeline.php?board_id=${boardId}`);
const container = document.getElementById('boardLanesContainer'); const container = document.getElementById('boardLanesContainer');
container.innerHTML = ` container.innerHTML = `
<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">
+15 -4
View File
@@ -162,9 +162,9 @@ require_once __DIR__ . '/env_badge.php';
<span>Planning</span> <span>Planning</span>
</a> </a>
<!-- Dropdown: Projecten (Bord, Brainstorm, Roadmap) --> <!-- Dropdown: Projecten (Bord, Tijdlijn, Brainstorm, Roadmap) -->
<?php <?php
$isProjectsActive = in_array($currentPage, ['board.php', 'brainstorm.php', 'brainstorm_canvas.php', 'roadmap.php']); $isProjectsActive = in_array($currentPage, ['board.php', 'timeline.php', 'brainstorm.php', 'brainstorm_canvas.php', 'roadmap.php']);
?> ?>
<div class="relative group/projects"> <div class="relative group/projects">
<button type="button" class="flex items-center space-x-1.5 px-3 py-1.5 rounded-xl text-xs font-semibold transition cursor-pointer <?= $isProjectsActive ? 'bg-indigo-50 text-indigo-700 border border-indigo-200/70 shadow-2xs dark:bg-indigo-500/10 dark:text-indigo-300 dark:border-indigo-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' ?>"> <button type="button" class="flex items-center space-x-1.5 px-3 py-1.5 rounded-xl text-xs font-semibold transition cursor-pointer <?= $isProjectsActive ? 'bg-indigo-50 text-indigo-700 border border-indigo-200/70 shadow-2xs dark:bg-indigo-500/10 dark:text-indigo-300 dark:border-indigo-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' ?>">
@@ -185,7 +185,18 @@ require_once __DIR__ . '/env_badge.php';
</div> </div>
</a> </a>
<!-- 2. Brainstorm --> <!-- 2. Tijdlijn (Gantt) -->
<a href="/timeline.php" class="flex items-start space-x-3 p-2.5 rounded-xl transition <?= $currentPage === 'timeline.php' ? 'bg-indigo-50 text-indigo-700 dark:bg-indigo-500/15 dark:text-indigo-300' : 'text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800/70' ?>">
<div class="w-8 h-8 rounded-lg bg-violet-100 dark:bg-violet-500/20 text-violet-600 dark:text-violet-400 flex items-center justify-center flex-shrink-0 mt-0.5">
<i data-lucide="clock" class="w-4 h-4"></i>
</div>
<div>
<div class="text-xs font-bold leading-tight">Tijdlijn</div>
<div class="text-[11px] text-slate-500 dark:text-slate-400 leading-snug">Gantt-planning & projectkalender</div>
</div>
</a>
<!-- 3. Brainstorm -->
<a href="/brainstorm.php" class="flex items-start space-x-3 p-2.5 rounded-xl transition <?= in_array($currentPage, ['brainstorm.php', 'brainstorm_canvas.php']) ? 'bg-indigo-50 text-indigo-700 dark:bg-indigo-500/15 dark:text-indigo-300' : 'text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800/70' ?>"> <a href="/brainstorm.php" class="flex items-start space-x-3 p-2.5 rounded-xl transition <?= in_array($currentPage, ['brainstorm.php', 'brainstorm_canvas.php']) ? 'bg-indigo-50 text-indigo-700 dark:bg-indigo-500/15 dark:text-indigo-300' : 'text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800/70' ?>">
<div class="w-8 h-8 rounded-lg bg-amber-100 dark:bg-amber-500/20 text-amber-600 dark:text-amber-400 flex items-center justify-center flex-shrink-0 mt-0.5"> <div class="w-8 h-8 rounded-lg bg-amber-100 dark:bg-amber-500/20 text-amber-600 dark:text-amber-400 flex items-center justify-center flex-shrink-0 mt-0.5">
<i data-lucide="lightbulb" class="w-4 h-4"></i> <i data-lucide="lightbulb" class="w-4 h-4"></i>
@@ -460,5 +471,5 @@ function focizQuickToggleTheme() {
} }
</script> </script>
<?php $isBoardPage = ($currentPage === 'board.php'); ?> <?php $isBoardPage = in_array($currentPage, ['board.php', 'timeline.php']); ?>
<main id="focizMainContainer" class="flex-1 <?= $isBoardPage ? 'w-full max-w-none px-3 sm:px-6 py-4' : 'max-w-7xl w-full mx-auto p-4 sm:p-6 lg:p-8' ?> transition-all duration-300"> <main id="focizMainContainer" class="flex-1 <?= $isBoardPage ? 'w-full max-w-none px-3 sm:px-6 py-4' : 'max-w-7xl w-full mx-auto p-4 sm:p-6 lg:p-8' ?> transition-all duration-300">
+1079
View File
File diff suppressed because it is too large Load Diff