'Ma', 2 => 'Di', 3 => 'Wo', 4 => 'Do', 5 => 'Vr', 6 => 'Za', 7 => 'Zo']; $dutchFullDays = [1 => 'Maandag', 2 => 'Dinsdag', 3 => 'Woensdag', 4 => 'Donderdag', 5 => 'Vrijdag', 6 => 'Zaterdag', 7 => 'Zondag']; $dutchMonths = ['', 'januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december']; $dutchShortMonths = ['', 'jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec']; $formattedSelectedDate = $dutchFullDays[(int)date('N', $selectedTs)] . ' ' . date('j', $selectedTs) . ' ' . $dutchMonths[(int)date('n', $selectedTs)] . ' ' . date('Y', $selectedTs); $formattedWeekRange = date('j', $mondayTs) . ' ' . $dutchShortMonths[(int)date('n', $mondayTs)] . ' – ' . date('j', $sundayTs) . ' ' . $dutchShortMonths[(int)date('n', $sundayTs)] . ' ' . date('Y', $sundayTs); // 1. Haal integratiestatussen op $userIntegrations = []; try { $stmtInt = $db->prepare("SELECT * FROM integrations WHERE user_id = ?"); $stmtInt->execute([$userId]); foreach ($stmtInt->fetchAll() as $row) { $userIntegrations[$row['provider']] = $row; } } catch (Throwable $e) { error_log("Fout bij ophalen integraties: " . $e->getMessage()); ensure_tables_exist($db); } $isOutlookConnected = !empty($userIntegrations['OUTLOOK']['access_token']) && empty($userIntegrations['OUTLOOK']['is_demo_mode']); $outlookIntegrationSettings = json_decode($userIntegrations['OUTLOOK']['settings'] ?? '{}', true) ?: []; $syncIntervalSeconds = isset($outlookIntegrationSettings['sync_interval_seconds']) ? (int)$outlookIntegrationSettings['sync_interval_seconds'] : 30; $weekOutlookEvents = []; $isLiveOutlook = false; if ($isOutlookConnected) { try { // Haal afspraken op voor het volledige datumbereik van de week $weekOutlookEvents = microsoft_fetch_events_range($userId, $weekStart, $weekEnd); $isLiveOutlook = true; // Synchroniseer / reconcilieer Fociz taken direct met actuele Outlook data microsoft_reconcile_tasks_with_outlook($userId, $weekStart, $weekEnd, $weekOutlookEvents); } catch (Throwable $e) { error_log("Outlook synchronisatiefout in planner: " . $e->getMessage()); $isLiveOutlook = false; $weekOutlookEvents = []; } } else { // Demo data indien Microsoft Outlook nog niet gekoppeld is $weekOutlookEvents = [ [ 'id' => 'evt-1', 'subject' => 'Voorbeeld: Team Standup & Sync', 'date' => $today, 'start' => '09:00', 'end' => '09:30', 'location' => 'Microsoft Teams', 'meeting_url' => 'https://teams.microsoft.com', 'source' => 'SANDBOX', ], [ 'id' => 'evt-2', 'subject' => 'Voorbeeld: Roadmap Review met Stakeholders', 'date' => $today, 'start' => '11:00', 'end' => '12:00', 'location' => 'Vergaderruimte A & Teams', 'meeting_url' => 'https://teams.microsoft.com', 'source' => 'SANDBOX', ], [ 'id' => 'evt-3', 'subject' => 'Voorbeeld: Architectuur & DB Evaluatie', 'date' => $today, 'start' => '14:30', 'end' => '15:30', 'location' => 'Online Teams Call', 'meeting_url' => 'https://teams.microsoft.com', 'source' => 'SANDBOX', ] ]; } // 2. Haal dagplanning op of maak aan voor $selectedDate $dailyPlan = null; try { $stmtPlan = $db->prepare("SELECT * FROM daily_plans WHERE user_id = ? AND plan_date = ?"); $stmtPlan->execute([$userId, $selectedDate]); $dailyPlan = $stmtPlan->fetch(); if (!$dailyPlan) { $defaultGoal = ($selectedDate === $today) ? 'Mijn belangrijkste doel van vandaag behalen' : 'Focusdoel voor deze dag bepalen'; $stmtCreatePlan = $db->prepare(" INSERT INTO daily_plans (user_id, plan_date, focus_goal) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id) "); $stmtCreatePlan->execute([$userId, $selectedDate, $defaultGoal]); $planId = (int)$db->lastInsertId(); $dailyPlan = ['id' => $planId, 'plan_date' => $selectedDate, 'focus_goal' => $defaultGoal, 'notes' => '']; } } catch (Throwable $e) { error_log("Fout bij dagplanning ophalen/aanmaken: " . $e->getMessage()); ensure_tables_exist($db); $dailyPlan = ['id' => 0, 'plan_date' => $selectedDate, 'focus_goal' => 'Mijn belangrijkste doel van vandaag behalen', 'notes' => '']; } $planId = !empty($dailyPlan['id']) ? (int)$dailyPlan['id'] : 0; // 3. Haal taken op voor de geselecteerde dag (vers bijgewerkt na eventuele reconciliatie) $tasks = []; try { $stmtTasks = $db->prepare(" SELECT * FROM tasks WHERE user_id = ? AND (daily_plan_id = ? " . ($selectedDate === $today ? "OR daily_plan_id IS NULL" : "") . ") ORDER BY is_completed ASC, priority ASC, time_block_start ASC, created_at DESC "); $stmtTasks->execute([$userId, $planId]); $tasks = $stmtTasks->fetchAll() ?: []; } catch (Throwable $e) { error_log("Fout bij ophalen taken: " . $e->getMessage()); } // 4. Haal weekstatistieken voor taken op (aantal per dag) $weekTaskStats = []; try { $stmtWeekTasks = $db->prepare(" SELECT dp.plan_date, COUNT(t.id) as total_tasks, SUM(CASE WHEN t.is_completed = 1 THEN 1 ELSE 0 END) as completed_tasks FROM daily_plans dp LEFT JOIN tasks t ON t.daily_plan_id = dp.id AND t.user_id = ? WHERE dp.user_id = ? AND dp.plan_date BETWEEN ? AND ? GROUP BY dp.plan_date "); $stmtWeekTasks->execute([$userId, $userId, $weekStart, $weekEnd]); foreach ($stmtWeekTasks->fetchAll() as $row) { $weekTaskStats[$row['plan_date']] = [ 'total' => (int)$row['total_tasks'], 'completed' => (int)$row['completed_tasks'], ]; } } catch (Throwable $e) { error_log("Fout bij weekstatistieken ophalen: " . $e->getMessage()); } // Groepeer Outlook afspraken per datum $outlookEventsByDate = []; foreach ($weekOutlookEvents as $evt) { $evtDate = $evt['date'] ?? $selectedDate; $outlookEventsByDate[$evtDate][] = $evt; } // 7 Dagen van de week samenstellen voor de weekselector $weekDays = []; for ($i = 0; $i < 7; $i++) { $dayTs = strtotime("+{$i} days", $mondayTs); $dayDate = date('Y-m-d', $dayTs); $dayN = (int)date('N', $dayTs); $dayM = (int)date('n', $dayTs); $tStat = $weekTaskStats[$dayDate] ?? ['total' => 0, 'completed' => 0]; $mCount = count($outlookEventsByDate[$dayDate] ?? []); $weekDays[] = [ 'date' => $dayDate, 'day_num' => date('j', $dayTs), 'short_name' => $dutchShortDays[$dayN], 'full_name' => $dutchFullDays[$dayN], 'month_short' => $dutchShortMonths[$dayM], 'is_today' => ($dayDate === $today), 'is_selected' => ($dayDate === $selectedDate), 'task_count' => $tStat['total'], 'completed_count' => $tStat['completed'], 'meeting_count' => $mCount, ]; } // 5. Haal Jira issues op voor de snelle import widget $jiraIssues = []; $isJiraLive = false; try { $jiraData = jira_get_user_issues($userId); $jiraIssues = $jiraData['issues'] ?? []; $isJiraLive = !empty($jiraData['success']) && empty($jiraData['is_demo']); } catch (Throwable $e) { error_log("Fout bij ophalen Jira issues: " . $e->getMessage()); } // Filter Outlook events die afkomstig zijn van Fociz taken voor de geselecteerde dag om duplicaten op de tijdlijn te voorkomen $dayOutlookEvents = $outlookEventsByDate[$selectedDate] ?? []; $syncedTaskExternalIds = []; foreach ($tasks as $t) { if (!empty($t['external_id'])) { $syncedTaskExternalIds[$t['external_id']] = true; } } $displayedOutlookEvents = []; foreach ($dayOutlookEvents as $evt) { if (!empty($evt['id']) && isset($syncedTaskExternalIds[$evt['id']])) { continue; } $displayedOutlookEvents[] = $evt; } // Bereken initiële status-hash voor achtergrondsynchronisatie $dayEventsForHash = []; foreach ($displayedOutlookEvents as $e) { $dayEventsForHash[] = [ 'id' => $e['id'] ?? '', 'start' => $e['start'] ?? '', 'end' => $e['end'] ?? '', 'subject' => $e['subject'] ?? '', ]; } $tasksForHash = array_map(function($t) { return [ 'id' => $t['id'], 'title' => $t['title'], 'time_block_start' => $t['time_block_start'], 'time_block_end' => $t['time_block_end'], 'is_completed' => $t['is_completed'], ]; }, $tasks); $initialSyncHash = md5(json_encode([ 'events' => $dayEventsForHash, 'tasks' => $tasksForHash ])); // 6. Tijdlijn uren & Werkdag Standaarden (Release v1.4) $workdayStartStr = $workdaySettings['workday_start'] ?? '08:30'; $workdayEndStr = $workdaySettings['workday_end'] ?? '17:30'; $lunchStart = $workdaySettings['lunch_start'] ?? '12:30'; $lunchEnd = $workdaySettings['lunch_end'] ?? '13:00'; $lunchHour = (int)explode(':', $lunchStart)[0]; $startHour = (int)explode(':', $workdayStartStr)[0]; $endHourParts = explode(':', $workdayEndStr); $endHour = (int)$endHourParts[0]; if (!empty($endHourParts[1]) && (int)$endHourParts[1] > 0) { $endHour++; } if ($startHour < 6) $startHour = 6; if ($endHour > 23) $endHour = 23; foreach ($displayedOutlookEvents as $e) { if (!empty($e['start'])) { $h = (int)explode(':', $e['start'])[0]; if ($h < $startHour && $h >= 6) $startHour = $h; if ($h > $endHour && $h <= 23) $endHour = $h + 1; } } foreach ($tasks as $t) { if (!empty($t['time_block_start'])) { $h = (int)explode(':', $t['time_block_start'])[0]; if ($h < $startHour && $h >= 6) $startHour = $h; if ($h > $endHour && $h <= 23) $endHour = $h + 1; } } $hours = []; for ($h = $startHour; $h <= $endHour; $h++) { $hours[] = sprintf('%02d:00', $h); } ?>
VANDAAG GEKOZEN DAG

Dagplanning & Structuur

Focus Modus

Pomodoro werkstation & concentratie

Doeltaak: Kies een taak hieronder

Dagtaken & Prioriteiten

Nog geen taken gepland voor .

Klik op 'Nieuwe Taak' of importeer een Jira ticket hieronder.

JIRA OUTLOOK

Mijn Jira Tickets

Beheren
Geen openstaande tickets gevonden in Jira.
•

Dagnotities & Kladblok

Tijdlijn & Time-blocking

Outlook 365 –
- Lunchpauze (Gereserveerd)
Pauze
0) { ob_end_clean(); } header('Content-Type: application/json; charset=utf-8'); echo json_encode([ 'success' => true, 'selectedDate' => $selectedDate, 'formattedDate' => $formattedSelectedDate, 'weekStart' => $weekStart, 'weekEnd' => $weekEnd, 'weekNumber' => $weekNumber, 'yearNumber' => $yearNumber, 'formattedWeek' => $formattedWeekRange, 'syncHash' => $initialSyncHash, 'focusGoal' => $dailyPlan['focus_goal'] ?? '', 'dailyNotes' => $dailyPlan['notes'] ?? '', 'title' => 'Fociz — Dagplanning (' . $formattedSelectedDate . ')', 'html' => $contentHtml, ]); exit; } ?>