Dev #18

Merged
NiekRabelink merged 4 commits from dev into main 2026-09-09 14:05:25 +00:00
8 changed files with 247 additions and 0 deletions
Showing only changes of commit 890cbe7446 - Show all commits
+11
View File
@@ -2,6 +2,17 @@
.env .env
.env*.local .env*.local
# Systeem & Editor
.DS_Store
Thumbs.db
*.log
.vscode/
.idea/
# Environment
.env
.env*.local
# Systeem & Editor # Systeem & Editor
.DS_Store .DS_Store
Thumbs.db Thumbs.db
+4
View File
@@ -542,9 +542,13 @@ require_once __DIR__ . '/includes/header.php';
<div> <div>
<label class="block text-[11px] font-medium text-slate-600 dark:text-slate-400 mb-1">Standaard tijdslot</label> <label class="block text-[11px] font-medium text-slate-600 dark:text-slate-400 mb-1">Standaard tijdslot</label>
<select name="default_task_duration" class="w-full bg-white dark:bg-[#111622] border border-slate-300 dark:border-slate-700 rounded-xl px-3 py-1.5 text-xs text-slate-900 dark:text-white focus:outline-none focus:ring-1 focus:ring-indigo-500"> <select name="default_task_duration" class="w-full bg-white dark:bg-[#111622] border border-slate-300 dark:border-slate-700 rounded-xl px-3 py-1.5 text-xs text-slate-900 dark:text-white focus:outline-none focus:ring-1 focus:ring-indigo-500">
<<<<<<< HEAD
<option value="10" <?= $workdaySettings['default_task_duration'] == 10 ? 'selected' : '' ?>>10 minuten</option> <option value="10" <?= $workdaySettings['default_task_duration'] == 10 ? 'selected' : '' ?>>10 minuten</option>
<option value="15" <?= $workdaySettings['default_task_duration'] == 15 ? 'selected' : '' ?>>15 minuten</option> <option value="15" <?= $workdaySettings['default_task_duration'] == 15 ? 'selected' : '' ?>>15 minuten</option>
<option value="20" <?= $workdaySettings['default_task_duration'] == 20 ? 'selected' : '' ?>>20 minuten</option> <option value="20" <?= $workdaySettings['default_task_duration'] == 20 ? 'selected' : '' ?>>20 minuten</option>
=======
<option value="15" <?= $workdaySettings['default_task_duration'] == 15 ? 'selected' : '' ?>>15 minuten</option>
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
<option value="30" <?= $workdaySettings['default_task_duration'] == 30 ? 'selected' : '' ?>>30 minuten (Standaard)</option> <option value="30" <?= $workdaySettings['default_task_duration'] == 30 ? 'selected' : '' ?>>30 minuten (Standaard)</option>
<option value="45" <?= $workdaySettings['default_task_duration'] == 45 ? 'selected' : '' ?>>45 minuten</option> <option value="45" <?= $workdaySettings['default_task_duration'] == 45 ? 'selected' : '' ?>>45 minuten</option>
<option value="60" <?= $workdaySettings['default_task_duration'] == 60 ? 'selected' : '' ?>>60 minuten (1 uur)</option> <option value="60" <?= $workdaySettings['default_task_duration'] == 60 ? 'selected' : '' ?>>60 minuten (1 uur)</option>
+53
View File
@@ -38,8 +38,13 @@ try {
$title = trim($data['title'] ?? ''); $title = trim($data['title'] ?? '');
$priority = in_array($data['priority'] ?? '', ['P1', 'P2', 'P3']) ? $data['priority'] : 'P2'; $priority = in_array($data['priority'] ?? '', ['P1', 'P2', 'P3']) ? $data['priority'] : 'P2';
$timeBlockStart = !empty($data['time_block_start']) ? trim($data['time_block_start']) : null; $timeBlockStart = !empty($data['time_block_start']) ? trim($data['time_block_start']) : null;
<<<<<<< HEAD
$timeBlockEnd = !empty($data['time_block_end']) ? trim($data['time_block_end']) : null; $timeBlockEnd = !empty($data['time_block_end']) ? trim($data['time_block_end']) : null;
$durationMinutes = (int)($data['duration_minutes'] ?? 0); $durationMinutes = (int)($data['duration_minutes'] ?? 0);
=======
$durationMinutes = (int)($data['duration_minutes'] ?? 30);
if ($durationMinutes <= 0) $durationMinutes = 30;
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
$date = !empty($data['date']) ? trim($data['date']) : $today; $date = !empty($data['date']) ? trim($data['date']) : $today;
$syncOutlook = !empty($data['sync_to_outlook']); $syncOutlook = !empty($data['sync_to_outlook']);
@@ -48,6 +53,7 @@ try {
exit; exit;
} }
<<<<<<< HEAD
// Als zowel start- als eindtijd zijn opgegeven, bereken exact de minuten // Als zowel start- als eindtijd zijn opgegeven, bereken exact de minuten
if (!empty($timeBlockStart) && !empty($timeBlockEnd)) { if (!empty($timeBlockStart) && !empty($timeBlockEnd)) {
$t1 = strtotime("2000-01-01 {$timeBlockStart}"); $t1 = strtotime("2000-01-01 {$timeBlockStart}");
@@ -72,6 +78,8 @@ try {
} }
} }
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
// Haal of maak daily plan op // Haal of maak daily plan op
$stmtPlan = $db->prepare(" $stmtPlan = $db->prepare("
INSERT INTO daily_plans (user_id, plan_date) INSERT INTO daily_plans (user_id, plan_date)
@@ -84,6 +92,10 @@ try {
$source = !empty($data['source']) ? substr(trim($data['source']), 0, 50) : 'FOCIZ'; $source = !empty($data['source']) ? substr(trim($data['source']), 0, 50) : 'FOCIZ';
$externalId = !empty($data['external_id']) ? substr(trim($data['external_id']), 0, 255) : null; $externalId = !empty($data['external_id']) ? substr(trim($data['external_id']), 0, 255) : null;
$externalUrl = !empty($data['external_url']) ? trim($data['external_url']) : null; $externalUrl = !empty($data['external_url']) ? trim($data['external_url']) : null;
<<<<<<< HEAD
=======
$timeBlockEnd = null;
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
$outlookSyncError = null; $outlookSyncError = null;
// Als synchronisatie naar Outlook gewenst is (of source is OUTLOOK) en nog geen extern ID heeft // Als synchronisatie naar Outlook gewenst is (of source is OUTLOOK) en nog geen extern ID heeft
@@ -98,7 +110,10 @@ try {
'description' => "Gepland via Fociz Dagplanning ({$priority})", 'description' => "Gepland via Fociz Dagplanning ({$priority})",
'date' => $date, 'date' => $date,
'start_time' => $timeBlockStart, 'start_time' => $timeBlockStart,
<<<<<<< HEAD
'end_time' => $timeBlockEnd, 'end_time' => $timeBlockEnd,
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
'duration_minutes' => $durationMinutes, 'duration_minutes' => $durationMinutes,
]); ]);
@@ -107,12 +122,30 @@ try {
$externalId = $msResult['event_id']; $externalId = $msResult['event_id'];
$externalUrl = $msResult['web_link'] ?? 'https://outlook.office.com'; $externalUrl = $msResult['web_link'] ?? 'https://outlook.office.com';
$timeBlockStart = $msResult['start_time'] ?? $timeBlockStart; $timeBlockStart = $msResult['start_time'] ?? $timeBlockStart;
<<<<<<< HEAD
$timeBlockEnd = $msResult['end_time'] ?? $timeBlockEnd; $timeBlockEnd = $msResult['end_time'] ?? $timeBlockEnd;
=======
$timeBlockEnd = $msResult['end_time'] ?? null;
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
} else { } else {
$outlookSyncError = $msResult['error'] ?? 'Kon afspraak niet aanmaken in Microsoft Outlook'; $outlookSyncError = $msResult['error'] ?? 'Kon afspraak niet aanmaken in Microsoft Outlook';
} }
} }
<<<<<<< HEAD
=======
// Bereken timeBlockEnd indien nog niet gezet maar wel starttijd bekend
if (!empty($timeBlockStart) && empty($timeBlockEnd)) {
try {
$dtEnd = new DateTime("{$date} {$timeBlockStart}:00", new DateTimeZone('Europe/Amsterdam'));
$dtEnd->modify("+{$durationMinutes} minutes");
$timeBlockEnd = $dtEnd->format('H:i');
} catch (Throwable $e) {
// negeer
}
}
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
$stmt = $db->prepare(" $stmt = $db->prepare("
INSERT INTO tasks (user_id, daily_plan_id, title, priority, time_block_start, time_block_end, duration_minutes, status, source, external_id, external_url) INSERT INTO tasks (user_id, daily_plan_id, title, priority, time_block_start, time_block_end, duration_minutes, status, source, external_id, external_url)
VALUES (?, ?, ?, ?, ?, ?, ?, 'TODO', ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, 'TODO', ?, ?, ?)
@@ -129,6 +162,7 @@ try {
'time_block_start' => $timeBlockStart, 'time_block_start' => $timeBlockStart,
'time_block_end' => $timeBlockEnd, 'time_block_end' => $timeBlockEnd,
'duration_minutes' => $durationMinutes, 'duration_minutes' => $durationMinutes,
<<<<<<< HEAD
'source' => $source, 'source' => $source,
'external_id' => $externalId, 'external_id' => $externalId,
'external_url' => $externalUrl 'external_url' => $externalUrl
@@ -214,6 +248,16 @@ try {
'time_block_start' => $timeBlockStart, 'time_block_start' => $timeBlockStart,
'time_block_end' => $timeBlockEnd, 'time_block_end' => $timeBlockEnd,
'duration_minutes' => $durationMinutes 'duration_minutes' => $durationMinutes
=======
'is_completed' => 0,
'status' => 'TODO',
'source' => $source,
'external_id' => $externalId,
'external_url' => $externalUrl,
],
'outlook_synced' => ($source === 'OUTLOOK' && !empty($externalId)),
'outlook_error' => $outlookSyncError,
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
]); ]);
exit; exit;
} }
@@ -256,7 +300,10 @@ try {
$planDate = $task['plan_date'] ?: $today; $planDate = $task['plan_date'] ?: $today;
$startTime = !empty($task['time_block_start']) ? $task['time_block_start'] : ($data['time_block_start'] ?? '09:00'); $startTime = !empty($task['time_block_start']) ? $task['time_block_start'] : ($data['time_block_start'] ?? '09:00');
<<<<<<< HEAD
$endTime = !empty($task['time_block_end']) ? $task['time_block_end'] : null; $endTime = !empty($task['time_block_end']) ? $task['time_block_end'] : null;
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
$duration = (int)($task['duration_minutes'] ?: 30); $duration = (int)($task['duration_minutes'] ?: 30);
$msResult = microsoft_create_event($user['id'], [ $msResult = microsoft_create_event($user['id'], [
@@ -264,7 +311,10 @@ try {
'description' => "Gepland via Fociz Dagplanning (" . $task['priority'] . ")", 'description' => "Gepland via Fociz Dagplanning (" . $task['priority'] . ")",
'date' => $planDate, 'date' => $planDate,
'start_time' => $startTime, 'start_time' => $startTime,
<<<<<<< HEAD
'end_time' => $endTime, 'end_time' => $endTime,
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
'duration_minutes' => $duration, 'duration_minutes' => $duration,
]); ]);
@@ -344,6 +394,7 @@ try {
exit; exit;
} }
<<<<<<< HEAD
// 6. Realtime Outlook synchronisatie & controle op gewijzigde/gewiste items // 6. Realtime Outlook synchronisatie & controle op gewijzigde/gewiste items
if ($action === 'check_outlook_sync') { if ($action === 'check_outlook_sync') {
$rawInput = file_get_contents('php://input'); $rawInput = file_get_contents('php://input');
@@ -452,6 +503,8 @@ try {
exit; exit;
} }
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
echo json_encode(['error' => 'Onbekende actie']); echo json_encode(['error' => 'Onbekende actie']);
} catch (Exception $e) { } catch (Exception $e) {
http_response_code(500); http_response_code(500);
+12
View File
@@ -1,6 +1,7 @@
# MariaDB Verbinding # MariaDB Verbinding
DB_HOST="192.168.2.33" DB_HOST="192.168.2.33"
DB_PORT="3306" DB_PORT="3306"
<<<<<<< HEAD
DB_NAME="focizdev" DB_NAME="focizdev"
DB_USER="focizdev_user" DB_USER="focizdev_user"
DB_PASS="F0c1z_Dev_Secure_2026!" DB_PASS="F0c1z_Dev_Secure_2026!"
@@ -10,6 +11,17 @@ APP_ENV="development"
# Applicatie URL (voor uitnodigingslinks en OAuth redirects: https://dev.fociz.nl of https://fociz.nl) # Applicatie URL (voor uitnodigingslinks en OAuth redirects: https://dev.fociz.nl of https://fociz.nl)
APP_URL="https://dev.fociz.nl" APP_URL="https://dev.fociz.nl"
=======
DB_NAME="fociz"
DB_USER="focizlive_user"
DB_PASS="F0c1z_Live_Secure_2026!"
# Omgeving: 'development' (knippert rood) of 'live' (knippert groen)
APP_ENV="live"
# Applicatie URL (voor uitnodigingslinks en OAuth redirects: https://dev.fociz.nl of https://fociz.nl)
APP_URL="https://www.fociz.nl"
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
# Applicatie Geheime Sleutel (willekeurige tekenreeks) # Applicatie Geheime Sleutel (willekeurige tekenreeks)
APP_SECRET="fociz-maria-db-super-secret-key-998877" APP_SECRET="fociz-maria-db-super-secret-key-998877"
+10
View File
@@ -68,16 +68,26 @@ if (!function_exists('fociz_env')) {
// MariaDB Verbindingsgegevens (uit .env of .env.example) // MariaDB Verbindingsgegevens (uit .env of .env.example)
define('DB_HOST', fociz_env('DB_HOST', '192.168.2.33')); define('DB_HOST', fociz_env('DB_HOST', '192.168.2.33'));
define('DB_PORT', fociz_env('DB_PORT', '3306')); define('DB_PORT', fociz_env('DB_PORT', '3306'));
<<<<<<< HEAD
define('DB_NAME', fociz_env('DB_NAME', 'focizdev')); define('DB_NAME', fociz_env('DB_NAME', 'focizdev'));
define('DB_USER', fociz_env('DB_USER', 'focizdev_user')); define('DB_USER', fociz_env('DB_USER', 'focizdev_user'));
define('DB_PASS', fociz_env('DB_PASS', 'F0c1z_Dev_Secure_2026!')); define('DB_PASS', fociz_env('DB_PASS', 'F0c1z_Dev_Secure_2026!'));
=======
define('DB_NAME', fociz_env('DB_NAME', 'fociz'));
define('DB_USER', fociz_env('DB_USER', 'focizlive_user'));
define('DB_PASS', fociz_env('DB_PASS', 'F0c1z_Live_Secure_2026!'));
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
define('DB_CHARSET', 'utf8mb4'); define('DB_CHARSET', 'utf8mb4');
// Bepaal de dynamische of geconfigureerde applicatie URL // Bepaal de dynamische of geconfigureerde applicatie URL
if (!function_exists('fociz_detect_app_url')) { if (!function_exists('fociz_detect_app_url')) {
function fociz_detect_app_url(): string { function fociz_detect_app_url(): string {
$envUrl = fociz_env('APP_URL'); $envUrl = fociz_env('APP_URL');
<<<<<<< HEAD
if (!empty($envUrl) && !str_contains($envUrl, 'uw-domein.nl')) { if (!empty($envUrl) && !str_contains($envUrl, 'uw-domein.nl')) {
=======
if (!empty($envUrl) && !str_contains($envUrl, 'www.fociz.nl')) {
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
return rtrim($envUrl, '/'); return rtrim($envUrl, '/');
} }
+6
View File
@@ -563,6 +563,7 @@ function microsoft_delete_event(int $userId, string $eventId): bool {
} }
/** /**
<<<<<<< HEAD
* Werkt een bestaande afspraak bij in Microsoft Outlook via Graph API (PATCH) * Werkt een bestaande afspraak bij in Microsoft Outlook via Graph API (PATCH)
*/ */
function microsoft_update_event(int $userId, string $eventId, array $eventData): bool { function microsoft_update_event(int $userId, string $eventId, array $eventData): bool {
@@ -632,6 +633,8 @@ function microsoft_update_event(int $userId, string $eventId, array $eventData):
} }
/** /**
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
* Ontkoppelt Microsoft integratie voor een gebruiker * Ontkoppelt Microsoft integratie voor een gebruiker
* Wist uitsluitend de persoonlijke tokens; behoudt de centrale Azure App gegevens indien aanwezig. * Wist uitsluitend de persoonlijke tokens; behoudt de centrale Azure App gegevens indien aanwezig.
*/ */
@@ -663,6 +666,7 @@ function microsoft_disconnect(int $userId): bool {
} }
} }
<<<<<<< HEAD
/** /**
* Haalt één specifieke afspraak op uit Microsoft Outlook via Graph API. * Haalt één specifieke afspraak op uit Microsoft Outlook via Graph API.
* Retourneert: * Retourneert:
@@ -883,3 +887,5 @@ function microsoft_reconcile_tasks_with_outlook(int $userId, string $startDate,
} }
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
+145
View File
@@ -42,7 +42,53 @@ $dutchShortMonths = ['', 'jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug',
$formattedSelectedDate = $dutchFullDays[(int)date('N', $selectedTs)] . ' ' . date('j', $selectedTs) . ' ' . $dutchMonths[(int)date('n', $selectedTs)] . ' ' . date('Y', $selectedTs); $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); $formattedWeekRange = date('j', $mondayTs) . ' ' . $dutchShortMonths[(int)date('n', $mondayTs)] . ' – ' . date('j', $sundayTs) . ' ' . $dutchShortMonths[(int)date('n', $sundayTs)] . ' ' . date('Y', $sundayTs);
<<<<<<< HEAD
// 1. Haal integratiestatussen op // 1. Haal integratiestatussen op
=======
// 1. Haal dagplanning op of maak aan voor $selectedDate
$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 (?, ?, ?)
");
$stmtCreatePlan->execute([$userId, $selectedDate, $defaultGoal]);
$planId = (int)$db->lastInsertId();
$dailyPlan = ['id' => $planId, 'plan_date' => $selectedDate, 'focus_goal' => $defaultGoal, 'notes' => ''];
}
// 2. Haal taken op voor de geselecteerde dag
$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, $dailyPlan['id']]);
$tasks = $stmtTasks->fetchAll();
// 3. Haal weekstatistieken voor taken op (aantal per dag)
$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]);
$weekTaskStats = [];
foreach ($stmtWeekTasks->fetchAll() as $row) {
$weekTaskStats[$row['plan_date']] = [
'total' => (int)$row['total_tasks'],
'completed' => (int)$row['completed_tasks'],
];
}
// 4. Haal integratiestatussen op
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
$stmtInt = $db->prepare("SELECT * FROM integrations WHERE user_id = ?"); $stmtInt = $db->prepare("SELECT * FROM integrations WHERE user_id = ?");
$stmtInt->execute([$userId]); $stmtInt->execute([$userId]);
$userIntegrations = []; $userIntegrations = [];
@@ -51,9 +97,12 @@ foreach ($stmtInt->fetchAll() as $row) {
} }
$isOutlookConnected = !empty($userIntegrations['OUTLOOK']['access_token']) && empty($userIntegrations['OUTLOOK']['is_demo_mode']); $isOutlookConnected = !empty($userIntegrations['OUTLOOK']['access_token']) && empty($userIntegrations['OUTLOOK']['is_demo_mode']);
<<<<<<< HEAD
$outlookIntegrationSettings = json_decode($userIntegrations['OUTLOOK']['settings'] ?? '{}', true) ?: []; $outlookIntegrationSettings = json_decode($userIntegrations['OUTLOOK']['settings'] ?? '{}', true) ?: [];
$syncIntervalSeconds = isset($outlookIntegrationSettings['sync_interval_seconds']) ? (int)$outlookIntegrationSettings['sync_interval_seconds'] : 30; $syncIntervalSeconds = isset($outlookIntegrationSettings['sync_interval_seconds']) ? (int)$outlookIntegrationSettings['sync_interval_seconds'] : 30;
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
$weekOutlookEvents = []; $weekOutlookEvents = [];
$isLiveOutlook = false; $isLiveOutlook = false;
@@ -61,9 +110,12 @@ if ($isOutlookConnected) {
// Haal afspraken op voor het volledige datumbereik van de week // Haal afspraken op voor het volledige datumbereik van de week
$weekOutlookEvents = microsoft_fetch_events_range($userId, $weekStart, $weekEnd); $weekOutlookEvents = microsoft_fetch_events_range($userId, $weekStart, $weekEnd);
$isLiveOutlook = true; $isLiveOutlook = true;
<<<<<<< HEAD
// Synchroniseer / reconcilieer Fociz taken direct met actuele Outlook data // Synchroniseer / reconcilieer Fociz taken direct met actuele Outlook data
microsoft_reconcile_tasks_with_outlook($userId, $weekStart, $weekEnd, $weekOutlookEvents); microsoft_reconcile_tasks_with_outlook($userId, $weekStart, $weekEnd, $weekOutlookEvents);
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
} else { } else {
// Demo data indien Microsoft Outlook nog niet gekoppeld is // Demo data indien Microsoft Outlook nog niet gekoppeld is
$weekOutlookEvents = [ $weekOutlookEvents = [
@@ -100,6 +152,7 @@ if ($isOutlookConnected) {
]; ];
} }
<<<<<<< HEAD
// 2. Haal dagplanning op of maak aan voor $selectedDate // 2. Haal dagplanning op of maak aan voor $selectedDate
$stmtPlan = $db->prepare("SELECT * FROM daily_plans WHERE user_id = ? AND plan_date = ?"); $stmtPlan = $db->prepare("SELECT * FROM daily_plans WHERE user_id = ? AND plan_date = ?");
$stmtPlan->execute([$userId, $selectedDate]); $stmtPlan->execute([$userId, $selectedDate]);
@@ -142,6 +195,8 @@ foreach ($stmtWeekTasks->fetchAll() as $row) {
]; ];
} }
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
// Groepeer Outlook afspraken per datum // Groepeer Outlook afspraken per datum
$outlookEventsByDate = []; $outlookEventsByDate = [];
foreach ($weekOutlookEvents as $evt) { foreach ($weekOutlookEvents as $evt) {
@@ -194,6 +249,7 @@ foreach ($dayOutlookEvents as $evt) {
$displayedOutlookEvents[] = $evt; $displayedOutlookEvents[] = $evt;
} }
<<<<<<< HEAD
// Bereken initiële status-hash voor achtergrondsynchronisatie // Bereken initiële status-hash voor achtergrondsynchronisatie
$dayEventsForHash = []; $dayEventsForHash = [];
foreach ($displayedOutlookEvents as $e) { foreach ($displayedOutlookEvents as $e) {
@@ -218,6 +274,8 @@ $initialSyncHash = md5(json_encode([
'tasks' => $tasksForHash 'tasks' => $tasksForHash
])); ]));
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
// 6. Tijdlijn uren & Werkdag Standaarden (Release v1.4) // 6. Tijdlijn uren & Werkdag Standaarden (Release v1.4)
$workdayStartStr = $workdaySettings['workday_start'] ?? '08:30'; $workdayStartStr = $workdaySettings['workday_start'] ?? '08:30';
$workdayEndStr = $workdaySettings['workday_end'] ?? '17:30'; $workdayEndStr = $workdaySettings['workday_end'] ?? '17:30';
@@ -280,12 +338,20 @@ for ($h = $startHour; $h <= $endHour; $h++) {
<!-- 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): ?>
<<<<<<< HEAD
<div id="outlookSyncBadge" class="flex items-center space-x-2 px-3 py-1.5 rounded-xl bg-sky-50 dark:bg-sky-500/10 border border-sky-200/80 dark:border-sky-500/20 text-sky-800 dark:text-sky-300 text-xs font-medium shadow-2xs transition"> <div id="outlookSyncBadge" class="flex items-center space-x-2 px-3 py-1.5 rounded-xl bg-sky-50 dark:bg-sky-500/10 border border-sky-200/80 dark:border-sky-500/20 text-sky-800 dark:text-sky-300 text-xs font-medium shadow-2xs transition">
<span id="outlookSyncDot" class="w-2 h-2 rounded-full bg-sky-500"></span> <span id="outlookSyncDot" class="w-2 h-2 rounded-full bg-sky-500"></span>
<span id="outlookSyncStatusText">Outlook 365 Live</span> <span id="outlookSyncStatusText">Outlook 365 Live</span>
<span id="outlookLastSyncText" class="text-[10px] text-sky-600/70 dark:text-sky-400/60 font-mono hidden sm:inline">(synced <span id="syncTimeDisplay"><?= date('H:i') ?></span>)</span> <span id="outlookLastSyncText" class="text-[10px] text-sky-600/70 dark:text-sky-400/60 font-mono hidden sm:inline">(synced <span id="syncTimeDisplay"><?= date('H:i') ?></span>)</span>
<button id="manualSyncBtn" onclick="triggerManualSync()" title="Nu handmatig synchroniseren met Outlook" class="p-0.5 hover:bg-sky-100 dark:hover:bg-sky-500/20 text-sky-600 hover:text-sky-900 dark:text-sky-400 dark:hover:text-white rounded transition cursor-pointer"> <button id="manualSyncBtn" onclick="triggerManualSync()" title="Nu handmatig synchroniseren met Outlook" class="p-0.5 hover:bg-sky-100 dark:hover:bg-sky-500/20 text-sky-600 hover:text-sky-900 dark:text-sky-400 dark:hover:text-white rounded transition cursor-pointer">
<i id="manualSyncIcon" data-lucide="refresh-cw" class="w-3 h-3"></i> <i id="manualSyncIcon" data-lucide="refresh-cw" class="w-3 h-3"></i>
=======
<div class="flex items-center space-x-2 px-3 py-1.5 rounded-xl bg-sky-50 dark:bg-sky-500/10 border border-sky-200/80 dark:border-sky-500/20 text-sky-800 dark:text-sky-300 text-xs font-medium shadow-2xs">
<span class="w-2 h-2 rounded-full bg-sky-500 animate-pulse"></span>
<span>Outlook 365 Live</span>
<button onclick="location.reload()" title="Agenda Verversen" class="p-0.5 text-sky-600 hover:text-sky-900 dark:text-sky-400 dark:hover:text-white rounded transition">
<i data-lucide="refresh-cw" class="w-3 h-3"></i>
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
</button> </button>
</div> </div>
<?php else: ?> <?php else: ?>
@@ -505,16 +571,24 @@ for ($h = $startHour; $h <= $endHour; $h++) {
<label class="block text-[11px] font-medium text-slate-600 dark: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-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-indigo-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-indigo-500">
</div> </div>
<<<<<<< HEAD
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3"> <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3">
<div> <div>
<label class="block text-[11px] font-semibold text-slate-700 dark:text-slate-300 mb-1">Prioriteit</label> <label class="block text-[11px] font-semibold text-slate-700 dark:text-slate-300 mb-1">Prioriteit</label>
<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 focus:ring-1 focus:ring-indigo-500"> <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 focus:ring-1 focus:ring-indigo-500">
=======
<div class="grid grid-cols-1 sm:grid-cols-3 gap-3">
<div>
<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-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">
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
<option value="P1">P1 - Brandend / Focus</option> <option value="P1">P1 - Brandend / 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>
<<<<<<< HEAD
<label class="block text-[11px] font-semibold text-slate-700 dark:text-slate-300 mb-1">Starttijd</label> <label class="block text-[11px] font-semibold text-slate-700 dark:text-slate-300 mb-1">Starttijd</label>
<div class="relative"> <div class="relative">
<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 pl-2.5 pr-7 py-1.5 text-slate-900 dark:text-white text-xs font-mono focus:outline-none focus:ring-1 focus:ring-indigo-500" oninput="onNewTaskTimeOrDurationChange('start')"> <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 pl-2.5 pr-7 py-1.5 text-slate-900 dark:text-white text-xs font-mono focus:outline-none focus:ring-1 focus:ring-indigo-500" oninput="onNewTaskTimeOrDurationChange('start')">
@@ -555,6 +629,22 @@ for ($h = $startHour; $h <= $endHour; $h++) {
</select> </select>
<input type="number" id="newTaskCustomDuration" min="1" max="720" placeholder="Min" class="hidden w-20 bg-white dark:bg-slate-900 border border-slate-300 dark:border-slate-800 rounded-xl px-2 py-1.5 text-slate-900 dark:text-white text-xs font-mono focus:outline-none focus:ring-1 focus:ring-indigo-500" oninput="onNewTaskTimeOrDurationChange('custom_duration')"> <input type="number" id="newTaskCustomDuration" min="1" max="720" placeholder="Min" class="hidden w-20 bg-white dark:bg-slate-900 border border-slate-300 dark:border-slate-800 rounded-xl px-2 py-1.5 text-slate-900 dark:text-white text-xs font-mono focus:outline-none focus:ring-1 focus:ring-indigo-500" oninput="onNewTaskTimeOrDurationChange('custom_duration')">
</div> </div>
=======
<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-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>
<label class="block text-[11px] font-medium text-slate-600 dark:text-slate-400 mb-1">Tijdsduur</label>
<select id="newTaskDuration" 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">
<?php
$defDuration = (int)($workdaySettings['default_task_duration'] ?? 30);
$durations = [15 => '15 minuten', 30 => '30 minuten', 45 => '45 minuten', 60 => '60 minuten (1 uur)', 90 => '90 minuten (1,5 uur)', 120 => '120 minuten (2 uur)'];
foreach ($durations as $mins => $label):
?>
<option value="<?= $mins ?>" <?= $defDuration === $mins ? 'selected' : '' ?>><?= $label ?></option>
<?php endforeach; ?>
</select>
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
</div> </div>
</div> </div>
@@ -613,7 +703,11 @@ for ($h = $startHour; $h <= $endHour; $h++) {
<?php if (!empty($task['time_block_start'])): ?> <?php if (!empty($task['time_block_start'])): ?>
<span class="text-[10px] text-slate-500 dark: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>
<<<<<<< HEAD
<span><?= htmlspecialchars($task['time_block_start']) ?><?= !empty($task['time_block_end']) ? ' - ' . htmlspecialchars($task['time_block_end']) : '' ?><?= !empty($task['duration_minutes']) ? ' (' . (int)$task['duration_minutes'] . 'm)' : '' ?></span> <span><?= htmlspecialchars($task['time_block_start']) ?><?= !empty($task['time_block_end']) ? ' - ' . htmlspecialchars($task['time_block_end']) : '' ?><?= !empty($task['duration_minutes']) ? ' (' . (int)$task['duration_minutes'] . 'm)' : '' ?></span>
=======
<span><?= htmlspecialchars($task['time_block_start']) ?><?= !empty($task['time_block_end']) ? ' - ' . htmlspecialchars($task['time_block_end']) : '' ?></span>
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
</span> </span>
<?php endif; ?> <?php endif; ?>
<?php if (!empty($task['external_url'])): ?> <?php if (!empty($task['external_url'])): ?>
@@ -639,11 +733,16 @@ for ($h = $startHour; $h <= $endHour; $h++) {
<?php endif; ?> <?php endif; ?>
<?php if (!$task['is_completed']): ?> <?php if (!$task['is_completed']): ?>
<<<<<<< HEAD
<button onclick="selectFocusTask('<?= htmlspecialchars(addslashes($task['title'])) ?>')" title="Koppel aan Focus Timer" class="p-1.5 rounded-lg text-slate-400 hover:text-amber-500 hover:bg-amber-500/10 transition cursor-pointer"> <button onclick="selectFocusTask('<?= htmlspecialchars(addslashes($task['title'])) ?>')" title="Koppel aan Focus Timer" class="p-1.5 rounded-lg text-slate-400 hover:text-amber-500 hover:bg-amber-500/10 transition cursor-pointer">
=======
<button onclick="selectFocusTask('<?= htmlspecialchars(addslashes($task['title'])) ?>')" title="Koppel aan Focus Timer" class="p-1.5 rounded-lg text-slate-400 hover:text-amber-500 hover:bg-amber-500/10 transition">
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
<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; ?>
<<<<<<< HEAD
<button onclick="openEditTaskModal(<?= htmlspecialchars(json_encode([ <button onclick="openEditTaskModal(<?= htmlspecialchars(json_encode([
'id' => (int)$task['id'], 'id' => (int)$task['id'],
'title' => $task['title'], 'title' => $task['title'],
@@ -658,6 +757,9 @@ for ($h = $startHour; $h <= $endHour; $h++) {
</button> </button>
<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 cursor-pointer"> <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 cursor-pointer">
=======
<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">
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
<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>
@@ -873,6 +975,7 @@ for ($h = $startHour; $h <= $endHour; $h++) {
</div> </div>
</div> </div>
<<<<<<< HEAD
<!-- Modal: Taak & Tijdblok Bewerken (Vrij invullen van tijden & duur) --> <!-- Modal: Taak & Tijdblok Bewerken (Vrij invullen van tijden & duur) -->
<div id="editTaskModal" class="fixed inset-0 z-50 bg-slate-900/60 backdrop-blur-xs hidden items-center justify-center p-4"> <div id="editTaskModal" class="fixed inset-0 z-50 bg-slate-900/60 backdrop-blur-xs hidden items-center justify-center p-4">
<div class="bg-white dark:bg-[#111622] border border-slate-200/90 dark:border-slate-800 rounded-2xl p-6 w-full max-w-lg shadow-2xl space-y-4"> <div class="bg-white dark:bg-[#111622] border border-slate-200/90 dark:border-slate-800 rounded-2xl p-6 w-full max-w-lg shadow-2xl space-y-4">
@@ -967,6 +1070,8 @@ for ($h = $startHour; $h <= $endHour; $h++) {
</div> </div>
</div> </div>
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
<script> <script>
// --- Focus Timer Logica (Release v1.4) --- // --- Focus Timer Logica (Release v1.4) ---
const pomodoroFocusTime = <?= (int)$workdaySettings['pomodoro_focus'] ?>; const pomodoroFocusTime = <?= (int)$workdaySettings['pomodoro_focus'] ?>;
@@ -1008,7 +1113,10 @@ function toggleTimer() {
clearInterval(timerInterval); clearInterval(timerInterval);
isRunning = false; isRunning = false;
document.getElementById('timerToggleText').innerText = 'Hervatten'; document.getElementById('timerToggleText').innerText = 'Hervatten';
<<<<<<< HEAD
saveTimerStateBeforeReload(); saveTimerStateBeforeReload();
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
} else { } else {
isRunning = true; isRunning = true;
document.getElementById('timerToggleText').innerText = 'Pauzeren'; document.getElementById('timerToggleText').innerText = 'Pauzeren';
@@ -1019,7 +1127,10 @@ function toggleTimer() {
} else { } else {
clearInterval(timerInterval); clearInterval(timerInterval);
isRunning = false; isRunning = false;
<<<<<<< HEAD
sessionStorage.removeItem('fociz_timer_state'); sessionStorage.removeItem('fociz_timer_state');
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
document.getElementById('timerToggleText').innerText = 'Start Focus'; document.getElementById('timerToggleText').innerText = 'Start Focus';
alert('Focus sessie voltooid! Neem even een korte pauze.'); alert('Focus sessie voltooid! Neem even een korte pauze.');
} }
@@ -1031,11 +1142,15 @@ function resetTimer() {
clearInterval(timerInterval); clearInterval(timerInterval);
isRunning = false; isRunning = false;
timerSeconds = totalDuration; timerSeconds = totalDuration;
<<<<<<< HEAD
sessionStorage.removeItem('fociz_timer_state'); sessionStorage.removeItem('fociz_timer_state');
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
document.getElementById('timerToggleText').innerText = 'Start Focus'; document.getElementById('timerToggleText').innerText = 'Start Focus';
updateTimerDisplay(); updateTimerDisplay();
} }
<<<<<<< HEAD
function saveTimerStateBeforeReload() { function saveTimerStateBeforeReload() {
try { try {
if (isRunning || timerSeconds < totalDuration) { if (isRunning || timerSeconds < totalDuration) {
@@ -1084,6 +1199,8 @@ window.addEventListener('beforeunload', () => {
saveTimerStateBeforeReload(); saveTimerStateBeforeReload();
}); });
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
function selectFocusTask(title) { function selectFocusTask(title) {
document.getElementById('activeTaskDisplay').innerText = title; document.getElementById('activeTaskDisplay').innerText = title;
} }
@@ -1114,6 +1231,7 @@ async function saveGoal() {
} }
} }
<<<<<<< HEAD
// --- Tijdblok Hulpfuncties & Vrije Duur Berekening --- // --- Tijdblok Hulpfuncties & Vrije Duur Berekening ---
function parseTimeToMinutes(str) { function parseTimeToMinutes(str) {
if (!str || typeof str !== 'string') return null; if (!str || typeof str !== 'string') return null;
@@ -1247,6 +1365,8 @@ function setSelectedNewTaskDuration(mins) {
if (durationDisplay) durationDisplay.innerText = `${mins}m`; if (durationDisplay) durationDisplay.innerText = `${mins}m`;
} }
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
function toggleAddTaskForm() { function toggleAddTaskForm() {
const form = document.getElementById('addTaskForm'); const form = document.getElementById('addTaskForm');
form.classList.toggle('hidden'); form.classList.toggle('hidden');
@@ -1256,6 +1376,7 @@ function toggleAddTaskForm() {
} }
function quickSchedule(hour) { function quickSchedule(hour) {
<<<<<<< HEAD
const form = document.getElementById('addTaskForm'); const form = document.getElementById('addTaskForm');
if (form && form.classList.contains('hidden')) { if (form && form.classList.contains('hidden')) {
form.classList.remove('hidden'); form.classList.remove('hidden');
@@ -1268,12 +1389,20 @@ function quickSchedule(hour) {
const outlookCheckbox = document.getElementById('newTaskSyncOutlook'); const outlookCheckbox = document.getElementById('newTaskSyncOutlook');
if (outlookCheckbox) outlookCheckbox.checked = true; if (outlookCheckbox) outlookCheckbox.checked = true;
document.getElementById('newTaskTitle')?.focus(); document.getElementById('newTaskTitle')?.focus();
=======
toggleAddTaskForm();
const timeInput = document.getElementById('newTaskTime');
if (timeInput) timeInput.value = hour;
const outlookCheckbox = document.getElementById('newTaskSyncOutlook');
if (outlookCheckbox) outlookCheckbox.checked = true;
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
} }
async function submitNewTask() { async function submitNewTask() {
const title = document.getElementById('newTaskTitle').value.trim(); const title = document.getElementById('newTaskTitle').value.trim();
const priority = document.getElementById('newTaskPriority').value; const priority = document.getElementById('newTaskPriority').value;
const time = document.getElementById('newTaskTime').value.trim(); const time = document.getElementById('newTaskTime').value.trim();
<<<<<<< HEAD
const endTime = document.getElementById('newTaskEndTime') ? document.getElementById('newTaskEndTime').value.trim() : ''; const endTime = document.getElementById('newTaskEndTime') ? document.getElementById('newTaskEndTime').value.trim() : '';
const duration = getSelectedNewTaskDurationMinutes(); const duration = getSelectedNewTaskDurationMinutes();
const syncOutlook = document.getElementById('newTaskSyncOutlook') ? document.getElementById('newTaskSyncOutlook').checked : false; const syncOutlook = document.getElementById('newTaskSyncOutlook') ? document.getElementById('newTaskSyncOutlook').checked : false;
@@ -1282,6 +1411,12 @@ async function submitNewTask() {
alert('Vul een taaktitel in.'); alert('Vul een taaktitel in.');
return; return;
} }
=======
const duration = document.getElementById('newTaskDuration') ? parseInt(document.getElementById('newTaskDuration').value) : 30;
const syncOutlook = document.getElementById('newTaskSyncOutlook') ? document.getElementById('newTaskSyncOutlook').checked : false;
if (!title) return;
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
try { try {
const res = await fetch('/api/planner.php?action=add_task', { const res = await fetch('/api/planner.php?action=add_task', {
@@ -1290,8 +1425,12 @@ async function submitNewTask() {
body: JSON.stringify({ body: JSON.stringify({
title, title,
priority, priority,
<<<<<<< HEAD
time_block_start: time, time_block_start: time,
time_block_end: endTime, time_block_end: endTime,
=======
time_block_start: time,
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
duration_minutes: duration, duration_minutes: duration,
sync_to_outlook: syncOutlook, sync_to_outlook: syncOutlook,
date: activePlannerDate date: activePlannerDate
@@ -1311,6 +1450,7 @@ async function submitNewTask() {
} }
} }
<<<<<<< HEAD
// --- Taak & Tijdblok Bewerken Modal Logica --- // --- Taak & Tijdblok Bewerken Modal Logica ---
function openEditTaskModal(task) { function openEditTaskModal(task) {
if (!task) return; if (!task) return;
@@ -1499,6 +1639,8 @@ async function submitEditTask() {
} }
} }
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
async function syncTaskToOutlook(taskId, btn) { async function syncTaskToOutlook(taskId, btn) {
if (!btn) return; if (!btn) return;
const originalHtml = btn.innerHTML; const originalHtml = btn.innerHTML;
@@ -1624,6 +1766,7 @@ async function aiSmartSchedule(btn) {
} }
} }
} }
<<<<<<< HEAD
// --- Outlook 365 Auto-Sync & Achtergrond Controle --- // --- Outlook 365 Auto-Sync & Achtergrond Controle ---
const isOutlookConnected = <?= $isOutlookConnected ? 'true' : 'false' ?>; const isOutlookConnected = <?= $isOutlookConnected ? 'true' : 'false' ?>;
let currentSyncHash = '<?= $initialSyncHash ?? '' ?>'; let currentSyncHash = '<?= $initialSyncHash ?? '' ?>';
@@ -1712,6 +1855,8 @@ document.addEventListener('DOMContentLoaded', () => {
}); });
} }
}); });
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
</script> </script>
<?php require_once __DIR__ . '/includes/footer.php'; ?> <?php require_once __DIR__ . '/includes/footer.php'; ?>
+6
View File
@@ -48,6 +48,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
exit; exit;
} }
<<<<<<< HEAD
// 2b. Outlook synchronisatievoorkeuren opslaan // 2b. Outlook synchronisatievoorkeuren opslaan
elseif ($action === 'save_outlook_settings') { elseif ($action === 'save_outlook_settings') {
$syncInterval = (int)($_POST['sync_interval_seconds'] ?? 30); $syncInterval = (int)($_POST['sync_interval_seconds'] ?? 30);
@@ -65,6 +66,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$messageType = 'success'; $messageType = 'success';
} }
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
// 3. Jira Opslaan & Testen // 3. Jira Opslaan & Testen
elseif ($action === 'save_jira') { elseif ($action === 'save_jira') {
$companyDomain = jira_get_company_domain(); $companyDomain = jira_get_company_domain();
@@ -479,6 +482,7 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
</div> </div>
<<<<<<< HEAD
<form method="POST" class="mt-4 p-4 rounded-xl bg-slate-50/70 dark:bg-slate-900/60 border border-slate-200/80 dark:border-slate-800 flex flex-col sm:flex-row sm:items-center justify-between gap-4"> <form method="POST" class="mt-4 p-4 rounded-xl bg-slate-50/70 dark:bg-slate-900/60 border border-slate-200/80 dark:border-slate-800 flex flex-col sm:flex-row sm:items-center justify-between gap-4">
<input type="hidden" name="action" value="save_outlook_settings"> <input type="hidden" name="action" value="save_outlook_settings">
<div class="space-y-1"> <div class="space-y-1">
@@ -505,6 +509,8 @@ require_once __DIR__ . '/includes/header.php';
</div> </div>
</form> </form>
=======
>>>>>>> dd738e670b78819c11e329da93db1b472808f195
<div class="mt-4 p-3.5 rounded-xl bg-teal-50 dark:bg-teal-500/10 border border-teal-200 dark:border-teal-500/20 text-teal-800 dark:text-teal-300 text-xs flex items-center justify-between"> <div class="mt-4 p-3.5 rounded-xl bg-teal-50 dark:bg-teal-500/10 border border-teal-200 dark:border-teal-500/20 text-teal-800 dark:text-teal-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-teal-600 dark:text-teal-400 flex-shrink-0"></i> <i data-lucide="check-circle" class="w-4 h-4 text-teal-600 dark:text-teal-400 flex-shrink-0"></i>