prepare(" INSERT INTO daily_plans (user_id, plan_date, focus_goal, notes) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE focus_goal = VALUES(focus_goal), notes = VALUES(notes) "); $stmt->execute([$user['id'], $date, $focusGoal, $notes]); echo json_encode(['success' => true]); exit; } // 2. Taak toevoegen if ($action === 'add_task') { $data = json_decode(file_get_contents('php://input'), true); $title = trim($data['title'] ?? ''); $priority = in_array($data['priority'] ?? '', ['P1', 'P2', 'P3']) ? $data['priority'] : 'P2'; $timeBlockStart = !empty($data['time_block_start']) ? trim($data['time_block_start']) : null; $durationMinutes = (int)($data['duration_minutes'] ?? 30); if ($durationMinutes <= 0) $durationMinutes = 30; $date = !empty($data['date']) ? trim($data['date']) : $today; $syncOutlook = !empty($data['sync_to_outlook']); if (empty($title)) { echo json_encode(['error' => 'Titel is verplicht']); exit; } // Haal of maak daily plan op $stmtPlan = $db->prepare(" INSERT INTO daily_plans (user_id, plan_date) VALUES (?, ?) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id) "); $stmtPlan->execute([$user['id'], $date]); $planId = $db->lastInsertId(); $source = !empty($data['source']) ? substr(trim($data['source']), 0, 50) : 'FOCIZ'; $externalId = !empty($data['external_id']) ? substr(trim($data['external_id']), 0, 255) : null; $externalUrl = !empty($data['external_url']) ? trim($data['external_url']) : null; $timeBlockEnd = null; // Als er een tijdblok is en de gebruiker heeft synchronisatie naar Outlook gekozen (of source is OUTLOOK) if (($syncOutlook || $source === 'OUTLOOK') && !empty($timeBlockStart) && empty($externalId)) { $msResult = microsoft_create_event($user['id'], [ 'subject' => $title, 'description' => "Gepland via Fociz Dagplanning ({$priority})", 'date' => $date, 'start_time' => $timeBlockStart, 'duration_minutes' => $durationMinutes, ]); if (!empty($msResult['success']) && !empty($msResult['event_id'])) { $source = 'OUTLOOK'; $externalId = $msResult['event_id']; $externalUrl = $msResult['web_link'] ?? 'https://outlook.office.com'; $timeBlockEnd = $msResult['end_time'] ?? null; } } // 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 } } $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) VALUES (?, ?, ?, ?, ?, ?, ?, 'TODO', ?, ?, ?) "); $stmt->execute([$user['id'], $planId, $title, $priority, $timeBlockStart, $timeBlockEnd, $durationMinutes, $source, $externalId, $externalUrl]); $taskId = (int)$db->lastInsertId(); echo json_encode([ 'success' => true, 'task' => [ 'id' => $taskId, 'title' => $title, 'priority' => $priority, 'time_block_start' => $timeBlockStart, 'time_block_end' => $timeBlockEnd, 'duration_minutes' => $durationMinutes, 'is_completed' => 0, 'status' => 'TODO', 'source' => $source, 'external_id' => $externalId, 'external_url' => $externalUrl, ], 'outlook_synced' => ($source === 'OUTLOOK' && !empty($externalId)), ]); exit; } // 3. Bestaande taak handmatig naar Microsoft Outlook synchroniseren if ($action === 'sync_task_to_outlook') { $data = json_decode(file_get_contents('php://input'), true); $taskId = (int)($data['task_id'] ?? 0); if (!$taskId) { echo json_encode(['error' => 'Geen taak-ID opgegeven']); exit; } // Haal taak inclusief plan datum op $stmtTask = $db->prepare(" SELECT t.*, dp.plan_date FROM tasks t LEFT JOIN daily_plans dp ON t.daily_plan_id = dp.id WHERE t.id = ? AND t.user_id = ? "); $stmtTask->execute([$taskId, $user['id']]); $task = $stmtTask->fetch(); if (!$task) { echo json_encode(['error' => 'Taak niet gevonden']); exit; } // Als al gesynchroniseerd if (!empty($task['external_id']) && $task['source'] === 'OUTLOOK') { echo json_encode([ 'success' => true, 'already_synced' => true, 'external_id' => $task['external_id'], 'external_url' => $task['external_url'] ]); exit; } $planDate = $task['plan_date'] ?: $today; $startTime = !empty($task['time_block_start']) ? $task['time_block_start'] : ($data['time_block_start'] ?? '09:00'); $duration = (int)($task['duration_minutes'] ?: 30); $msResult = microsoft_create_event($user['id'], [ 'subject' => $task['title'], 'description' => "Gepland via Fociz Dagplanning (" . $task['priority'] . ")", 'date' => $planDate, 'start_time' => $startTime, 'duration_minutes' => $duration, ]); if (empty($msResult['success']) || empty($msResult['event_id'])) { echo json_encode(['error' => $msResult['error'] ?? 'Kon afspraak niet aanmaken in Microsoft Outlook']); exit; } // Sla Outlook ID en bron op in de taak $stmtUp = $db->prepare(" UPDATE tasks SET source = 'OUTLOOK', external_id = ?, external_url = ?, time_block_start = COALESCE(time_block_start, ?), time_block_end = ? WHERE id = ? AND user_id = ? "); $stmtUp->execute([ $msResult['event_id'], $msResult['web_link'] ?? 'https://outlook.office.com', $msResult['start_time'], $msResult['end_time'], $taskId, $user['id'] ]); echo json_encode([ 'success' => true, 'external_id' => $msResult['event_id'], 'external_url' => $msResult['web_link'] ?? 'https://outlook.office.com', 'start_time' => $msResult['start_time'], 'end_time' => $msResult['end_time'], ]); exit; } // 4. Taak status toggelen (voltooid / open) if ($action === 'toggle_task') { $data = json_decode(file_get_contents('php://input'), true); $taskId = (int)($data['task_id'] ?? 0); $isCompleted = !empty($data['is_completed']) ? 1 : 0; $status = $isCompleted ? 'DONE' : 'TODO'; $stmt = $db->prepare(" UPDATE tasks SET is_completed = ?, status = ? WHERE id = ? AND user_id = ? "); $stmt->execute([$isCompleted, $status, $taskId, $user['id']]); echo json_encode(['success' => true]); exit; } // 5. Taak verwijderen (verwijder ook eventueel gekoppelde Outlook afspraak) if ($action === 'delete_task') { $data = json_decode(file_get_contents('php://input'), true); $taskId = (int)($data['task_id'] ?? 0); // Haal eerst op of deze taak aan Outlook was gekoppeld $stmtCheck = $db->prepare("SELECT external_id, source FROM tasks WHERE id = ? AND user_id = ?"); $stmtCheck->execute([$taskId, $user['id']]); $taskToDelete = $stmtCheck->fetch(); if ($taskToDelete && !empty($taskToDelete['external_id']) && $taskToDelete['source'] === 'OUTLOOK') { try { microsoft_delete_event($user['id'], $taskToDelete['external_id']); } catch (Throwable $t) { error_log("Fout bij verwijderen Outlook afspraak voor taak {$taskId}: " . $t->getMessage()); } } $stmt = $db->prepare("DELETE FROM tasks WHERE id = ? AND user_id = ?"); $stmt->execute([$taskId, $user['id']]); echo json_encode(['success' => true]); exit; } echo json_encode(['error' => 'Onbekende actie']); } catch (Exception $e) { http_response_code(500); echo json_encode(['error' => $e->getMessage()]); }