Simple todo
This commit is contained in:
+413
@@ -87,6 +87,419 @@ try {
|
||||
exit;
|
||||
}
|
||||
|
||||
// 1d. Snelle Bullet Notities ophalen
|
||||
if ($action === 'get_bullets') {
|
||||
$date = $_GET['date'] ?? $today;
|
||||
|
||||
$stmt = $db->prepare("
|
||||
SELECT b.*, t.time_block_start as live_start, t.time_block_end as live_end, t.status as task_status
|
||||
FROM dashboard_bullets b
|
||||
LEFT JOIN tasks t ON b.scheduled_task_id = t.id
|
||||
WHERE b.user_id = ? AND b.plan_date = ?
|
||||
ORDER BY b.position ASC, b.id ASC
|
||||
");
|
||||
$stmt->execute([$user['id'], $date]);
|
||||
$bullets = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Tel openstaande items van eerdere dagen
|
||||
$stmtPast = $db->prepare("
|
||||
SELECT COUNT(*) FROM dashboard_bullets
|
||||
WHERE user_id = ? AND plan_date < ? AND is_completed = 0
|
||||
");
|
||||
$stmtPast->execute([$user['id'], $date]);
|
||||
$pastOpenCount = (int)$stmtPast->fetchColumn();
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'bullets' => $bullets,
|
||||
'past_open_count' => $pastOpenCount
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 1e. Bullet notitie toevoegen
|
||||
if ($action === 'add_bullet') {
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$date = !empty($data['date']) ? trim($data['date']) : $today;
|
||||
$content = trim($data['content'] ?? '');
|
||||
|
||||
if ($content === '') {
|
||||
echo json_encode(['success' => false, 'error' => 'Notitie mag niet leeg zijn']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Bepaal positie
|
||||
$stmtPos = $db->prepare("SELECT COALESCE(MAX(position), 0) + 1 FROM dashboard_bullets WHERE user_id = ? AND plan_date = ?");
|
||||
$stmtPos->execute([$user['id'], $date]);
|
||||
$pos = (int)$stmtPos->fetchColumn();
|
||||
|
||||
$stmt = $db->prepare("
|
||||
INSERT INTO dashboard_bullets (user_id, plan_date, content, position)
|
||||
VALUES (?, ?, ?, ?)
|
||||
");
|
||||
$stmt->execute([$user['id'], $date, $content, $pos]);
|
||||
$bulletId = (int)$db->lastInsertId();
|
||||
|
||||
$stmtFetch = $db->prepare("SELECT * FROM dashboard_bullets WHERE id = ?");
|
||||
$stmtFetch->execute([$bulletId]);
|
||||
$newBullet = $stmtFetch->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'bullet' => $newBullet
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 1f. Bullet notitie status wisselen (afvinken / openen)
|
||||
if ($action === 'toggle_bullet') {
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$bulletId = (int)($data['bullet_id'] ?? 0);
|
||||
$isCompleted = !empty($data['is_completed']) ? 1 : 0;
|
||||
|
||||
$stmt = $db->prepare("UPDATE dashboard_bullets SET is_completed = ? WHERE id = ? AND user_id = ?");
|
||||
$stmt->execute([$isCompleted, $bulletId, $user['id']]);
|
||||
|
||||
// Als er een gekoppelde taak is, werk de status daarvan ook bij
|
||||
$stmtCheck = $db->prepare("SELECT scheduled_task_id FROM dashboard_bullets WHERE id = ? AND user_id = ?");
|
||||
$stmtCheck->execute([$bulletId, $user['id']]);
|
||||
$taskId = (int)$stmtCheck->fetchColumn();
|
||||
|
||||
if ($taskId > 0) {
|
||||
$taskStatus = $isCompleted ? 'DONE' : 'TODO';
|
||||
$stmtTask = $db->prepare("UPDATE tasks SET is_completed = ?, status = ? WHERE id = ? AND user_id = ?");
|
||||
$stmtTask->execute([$isCompleted, $taskStatus, $taskId, $user['id']]);
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true, 'is_completed' => $isCompleted]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 1g. Bullet notitie bewerken
|
||||
if ($action === 'update_bullet') {
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$bulletId = (int)($data['bullet_id'] ?? 0);
|
||||
$content = trim($data['content'] ?? '');
|
||||
|
||||
if ($content === '') {
|
||||
echo json_encode(['success' => false, 'error' => 'Inhoud mag niet leeg zijn']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("UPDATE dashboard_bullets SET content = ? WHERE id = ? AND user_id = ?");
|
||||
$stmt->execute([$content, $bulletId, $user['id']]);
|
||||
|
||||
// Indien gekoppeld aan taak, werk ook taaktitel bij
|
||||
$stmtCheck = $db->prepare("SELECT scheduled_task_id FROM dashboard_bullets WHERE id = ? AND user_id = ?");
|
||||
$stmtCheck->execute([$bulletId, $user['id']]);
|
||||
$taskId = (int)$stmtCheck->fetchColumn();
|
||||
if ($taskId > 0) {
|
||||
$stmtTask = $db->prepare("UPDATE tasks SET title = ? WHERE id = ? AND user_id = ?");
|
||||
$stmtTask->execute([$content, $taskId, $user['id']]);
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 1h. Bullet notitie verwijderen
|
||||
if ($action === 'delete_bullet') {
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$bulletId = (int)($data['bullet_id'] ?? 0);
|
||||
$deleteTask = !empty($data['delete_task']);
|
||||
|
||||
// Check voor gekoppelde taak
|
||||
$stmtCheck = $db->prepare("SELECT scheduled_task_id FROM dashboard_bullets WHERE id = ? AND user_id = ?");
|
||||
$stmtCheck->execute([$bulletId, $user['id']]);
|
||||
$taskId = (int)$stmtCheck->fetchColumn();
|
||||
|
||||
if ($taskId > 0 && $deleteTask) {
|
||||
// Verwijder eventuele Outlook afspraak
|
||||
$stmtTask = $db->prepare("SELECT external_id FROM tasks WHERE id = ? AND user_id = ?");
|
||||
$stmtTask->execute([$taskId, $user['id']]);
|
||||
$externalId = $stmtTask->fetchColumn();
|
||||
if (!empty($externalId) && function_exists('microsoft_delete_event')) {
|
||||
try {
|
||||
microsoft_delete_event($user['id'], $externalId);
|
||||
} catch (Throwable $e) {}
|
||||
}
|
||||
$stmtDelTask = $db->prepare("DELETE FROM tasks WHERE id = ? AND user_id = ?");
|
||||
$stmtDelTask->execute([$taskId, $user['id']]);
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("DELETE FROM dashboard_bullets WHERE id = ? AND user_id = ?");
|
||||
$stmt->execute([$bulletId, $user['id']]);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 1i. Bullet inplannen in agenda / vrij blok
|
||||
if ($action === 'schedule_bullet') {
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$bulletId = (int)($data['bullet_id'] ?? 0);
|
||||
$date = !empty($data['date']) ? trim($data['date']) : $today;
|
||||
$title = !empty($data['title']) ? trim($data['title']) : '';
|
||||
$startTime = !empty($data['start_time']) ? trim($data['start_time']) : '';
|
||||
$endTime = !empty($data['end_time']) ? trim($data['end_time']) : '';
|
||||
$duration = max(5, (int)($data['duration_minutes'] ?? 30));
|
||||
$priority = in_array($data['priority'] ?? '', ['P1', 'P2', 'P3']) ? $data['priority'] : 'P2';
|
||||
$syncOutlook = !empty($data['sync_to_outlook']);
|
||||
|
||||
// Haal bullet op
|
||||
$stmtB = $db->prepare("SELECT * FROM dashboard_bullets WHERE id = ? AND user_id = ?");
|
||||
$stmtB->execute([$bulletId, $user['id']]);
|
||||
$bullet = $stmtB->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$bullet) {
|
||||
echo json_encode(['success' => false, 'error' => 'Notitie niet gevonden']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (empty($title)) {
|
||||
$title = $bullet['content'];
|
||||
}
|
||||
|
||||
if (empty($startTime)) {
|
||||
echo json_encode(['success' => false, 'error' => 'Kies een starttijd voor het agendablok']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (empty($endTime)) {
|
||||
$dtEnd = new DateTime("{$date} {$startTime}:00", new DateTimeZone('Europe/Amsterdam'));
|
||||
$dtEnd->modify("+{$duration} minutes");
|
||||
$endTime = $dtEnd->format('H:i');
|
||||
}
|
||||
|
||||
// Zorg dat daily_plan bestaat
|
||||
$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 = (int)$db->lastInsertId();
|
||||
|
||||
$source = 'FOCIZ';
|
||||
$externalId = null;
|
||||
$externalUrl = null;
|
||||
$outlookSyncMsg = null;
|
||||
|
||||
// Microsoft Outlook synchronisatie
|
||||
if ($syncOutlook) {
|
||||
require_once __DIR__ . '/../includes/integrations/microsoft.php';
|
||||
try {
|
||||
$msResult = microsoft_create_event($user['id'], [
|
||||
'subject' => $title,
|
||||
'description' => "Ingepland vanuit Snelle Notities / Bullet Todo's",
|
||||
'date' => $date,
|
||||
'start_time' => $startTime,
|
||||
'end_time' => $endTime,
|
||||
'duration_minutes' => $duration,
|
||||
]);
|
||||
if (!empty($msResult['success']) && !empty($msResult['event_id'])) {
|
||||
$source = 'OUTLOOK';
|
||||
$externalId = $msResult['event_id'];
|
||||
$externalUrl = $msResult['web_link'] ?? null;
|
||||
$outlookSyncMsg = 'Succesvol gesynchroniseerd met Microsoft Outlook agenda.';
|
||||
}
|
||||
} catch (Throwable $e) {}
|
||||
}
|
||||
|
||||
$taskId = (int)($bullet['scheduled_task_id'] ?? 0);
|
||||
if ($taskId > 0) {
|
||||
// Update bestaande taak
|
||||
$stmtUpdateTask = $db->prepare("
|
||||
UPDATE tasks
|
||||
SET daily_plan_id = ?, title = ?, priority = ?, time_block_start = ?, time_block_end = ?, duration_minutes = ?, source = ?, external_id = COALESCE(?, external_id), external_url = COALESCE(?, external_url)
|
||||
WHERE id = ? AND user_id = ?
|
||||
");
|
||||
$stmtUpdateTask->execute([$planId, $title, $priority, $startTime, $endTime, $duration, $source, $externalId, $externalUrl, $taskId, $user['id']]);
|
||||
} else {
|
||||
// Nieuwe taak aanmaken
|
||||
$stmtInsertTask = $db->prepare("
|
||||
INSERT INTO tasks (user_id, daily_plan_id, title, description, priority, time_block_start, time_block_end, duration_minutes, status, source, external_id, external_url)
|
||||
VALUES (?, ?, ?, 'Ingepland vanuit Snelle Notities', ?, ?, ?, ?, 'TODO', ?, ?, ?)
|
||||
");
|
||||
$stmtInsertTask->execute([$user['id'], $planId, $title, $priority, $startTime, $endTime, $duration, $source, $externalId, $externalUrl]);
|
||||
$taskId = (int)$db->lastInsertId();
|
||||
}
|
||||
|
||||
// Update de bullet record
|
||||
$stmtUpdateB = $db->prepare("
|
||||
UPDATE dashboard_bullets
|
||||
SET scheduled_task_id = ?, scheduled_date = ?, scheduled_start_time = ?, scheduled_end_time = ?
|
||||
WHERE id = ? AND user_id = ?
|
||||
");
|
||||
$stmtUpdateB->execute([$taskId, $date, $startTime, $endTime, $bulletId, $user['id']]);
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'task_id' => $taskId,
|
||||
'scheduled_date' => $date,
|
||||
'scheduled_start_time' => $startTime,
|
||||
'scheduled_end_time' => $endTime,
|
||||
'outlook_message' => $outlookSyncMsg
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 1j. Bullet uit agenda halen
|
||||
if ($action === 'unschedule_bullet') {
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$bulletId = (int)($data['bullet_id'] ?? 0);
|
||||
|
||||
$stmtB = $db->prepare("SELECT scheduled_task_id FROM dashboard_bullets WHERE id = ? AND user_id = ?");
|
||||
$stmtB->execute([$bulletId, $user['id']]);
|
||||
$taskId = (int)$stmtB->fetchColumn();
|
||||
|
||||
if ($taskId > 0) {
|
||||
$stmtTask = $db->prepare("SELECT external_id FROM tasks WHERE id = ? AND user_id = ?");
|
||||
$stmtTask->execute([$taskId, $user['id']]);
|
||||
$externalId = $stmtTask->fetchColumn();
|
||||
if (!empty($externalId) && function_exists('microsoft_delete_event')) {
|
||||
try {
|
||||
microsoft_delete_event($user['id'], $externalId);
|
||||
} catch (Throwable $e) {}
|
||||
}
|
||||
$stmtDel = $db->prepare("DELETE FROM tasks WHERE id = ? AND user_id = ?");
|
||||
$stmtDel->execute([$taskId, $user['id']]);
|
||||
}
|
||||
|
||||
$stmtUpdate = $db->prepare("
|
||||
UPDATE dashboard_bullets
|
||||
SET scheduled_task_id = NULL, scheduled_date = NULL, scheduled_start_time = NULL, scheduled_end_time = NULL
|
||||
WHERE id = ? AND user_id = ?
|
||||
");
|
||||
$stmtUpdate->execute([$bulletId, $user['id']]);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 1k. Openstaande bullets van eerdere dagen overnemen naar geselecteerde dag
|
||||
if ($action === 'carryover_bullets') {
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$targetDate = !empty($data['target_date']) ? trim($data['target_date']) : $today;
|
||||
|
||||
// Verplaats alle openstaande notities van eerdere dagen naar targetDate
|
||||
$stmt = $db->prepare("
|
||||
UPDATE dashboard_bullets
|
||||
SET plan_date = ?
|
||||
WHERE user_id = ? AND plan_date < ? AND is_completed = 0
|
||||
");
|
||||
$stmt->execute([$targetDate, $user['id'], $targetDate]);
|
||||
$movedCount = $stmt->rowCount();
|
||||
|
||||
echo json_encode(['success' => true, 'moved_count' => $movedCount]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 1l. Haal alle beschikbare vrije agendablokken op voor een specifieke dag
|
||||
if ($action === 'get_day_free_slots') {
|
||||
$targetDate = $_GET['date'] ?? $today;
|
||||
$duration = max(5, (int)($_GET['duration_minutes'] ?? 30));
|
||||
|
||||
$workdaySettings = get_workday_settings();
|
||||
$workdayStartStr = $workdaySettings['workday_start'] ?? '08:30';
|
||||
$workdayEndStr = $workdaySettings['workday_end'] ?? '17:00';
|
||||
$lunchStartStr = $workdaySettings['lunch_start'] ?? '12:30';
|
||||
$lunchEndStr = $workdaySettings['lunch_end'] ?? '13:00';
|
||||
|
||||
$toMins = function(string $timeStr): int {
|
||||
$parts = explode(':', trim($timeStr));
|
||||
return ((int)($parts[0] ?? 0) * 60) + (int)($parts[1] ?? 0);
|
||||
};
|
||||
$toTimeStr = function(int $mins): string {
|
||||
$h = (int)floor($mins / 60);
|
||||
$m = $mins % 60;
|
||||
return sprintf('%02d:%02d', $h, $m);
|
||||
};
|
||||
|
||||
$workdayStartMin = $toMins($workdayStartStr);
|
||||
$workdayEndMin = $toMins($workdayEndStr);
|
||||
$lunchStartMin = $toMins($lunchStartStr);
|
||||
$lunchEndMin = $toMins($lunchEndStr);
|
||||
|
||||
$tz = new DateTimeZone('Europe/Amsterdam');
|
||||
$now = new DateTime('now', $tz);
|
||||
$isToday = ($targetDate === $now->format('Y-m-d'));
|
||||
|
||||
// Starttijd afronden naar kwartier
|
||||
$earliestMin = $workdayStartMin;
|
||||
if ($isToday) {
|
||||
$nowMin = ((int)$now->format('G') * 60) + (int)$now->format('i');
|
||||
if ($nowMin % 15 !== 0) {
|
||||
$nowMin = (int)(ceil($nowMin / 15) * 15);
|
||||
}
|
||||
$earliestMin = max($workdayStartMin, $nowMin);
|
||||
}
|
||||
|
||||
$busyIntervals = [];
|
||||
if ($lunchEndMin > $lunchStartMin) {
|
||||
$busyIntervals[] = [$lunchStartMin, $lunchEndMin];
|
||||
}
|
||||
|
||||
// Taken op deze dag
|
||||
$stmtTasks = $db->prepare("
|
||||
SELECT time_block_start, time_block_end, duration_minutes
|
||||
FROM tasks t
|
||||
INNER JOIN daily_plans dp ON t.daily_plan_id = dp.id
|
||||
WHERE t.user_id = ? AND dp.plan_date = ? AND t.time_block_start IS NOT NULL AND t.time_block_start != '' AND t.status != 'CANCELLED'
|
||||
");
|
||||
$stmtTasks->execute([$user['id'], $targetDate]);
|
||||
while ($t = $stmtTasks->fetch()) {
|
||||
$tStart = $toMins($t['time_block_start']);
|
||||
$tDur = (int)($t['duration_minutes'] ?: 30);
|
||||
$tEnd = !empty($t['time_block_end']) ? $toMins($t['time_block_end']) : ($tStart + $tDur);
|
||||
if ($tEnd > $tStart) {
|
||||
$busyIntervals[] = [$tStart, $tEnd];
|
||||
}
|
||||
}
|
||||
|
||||
// Outlook afspraken
|
||||
if (function_exists('microsoft_fetch_events')) {
|
||||
try {
|
||||
$outlookEvents = microsoft_fetch_events($user['id'], $targetDate, false);
|
||||
foreach ($outlookEvents as $oe) {
|
||||
if (!empty($oe['is_all_day'])) continue;
|
||||
if (empty($oe['start']) || empty($oe['end'])) continue;
|
||||
$oStart = $toMins($oe['start']);
|
||||
$oEnd = $toMins($oe['end']);
|
||||
if ($oEnd > $oStart) {
|
||||
$busyIntervals[] = [$oStart, $oEnd];
|
||||
}
|
||||
}
|
||||
} catch (Throwable $e) {}
|
||||
}
|
||||
|
||||
$freeSlots = [];
|
||||
for ($slotStart = $earliestMin; ($slotStart + $duration) <= $workdayEndMin; $slotStart += 15) {
|
||||
$slotEnd = $slotStart + $duration;
|
||||
$collision = false;
|
||||
foreach ($busyIntervals as [$bStart, $bEnd]) {
|
||||
if ($slotStart < $bEnd && $slotEnd > $bStart) {
|
||||
$collision = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$collision) {
|
||||
$freeSlots[] = [
|
||||
'start' => $toTimeStr($slotStart),
|
||||
'end' => $toTimeStr($slotEnd),
|
||||
'label' => $toTimeStr($slotStart) . ' - ' . $toTimeStr($slotEnd)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'date' => $targetDate,
|
||||
'duration_minutes' => $duration,
|
||||
'free_slots' => $freeSlots
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 2. Taak toevoegen
|
||||
if ($action === 'add_task') {
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
Reference in New Issue
Block a user