feat(notifications): add browser push notifications for calendar events with personal profile settings

This commit is contained in:
2026-09-08 20:43:38 +02:00
parent 8cb7bd8acd
commit ffb340b9ea
7 changed files with 810 additions and 2 deletions
+127
View File
@@ -0,0 +1,127 @@
<?php
/**
* AJAX API voor Persoonlijke Agenda Notificaties
*/
require_once __DIR__ . '/../includes/auth.php';
require_once __DIR__ . '/../includes/integrations/microsoft.php';
$user = require_auth();
$db = get_db_connection();
header('Content-Type: application/json; charset=utf-8');
$action = $_GET['action'] ?? ($_POST['action'] ?? '');
$today = date('Y-m-d');
try {
// 1. Instellingen ophalen
if ($action === 'get_settings') {
$settings = get_user_notification_settings((int)$user['id']);
echo json_encode([
'success' => true,
'settings' => $settings,
]);
exit;
}
// 2. Instellingen opslaan
if ($action === 'save_settings') {
$input = json_decode(file_get_contents('php://input'), true) ?: $_POST;
$saved = update_user_notification_settings((int)$user['id'], $input);
$settings = get_user_notification_settings((int)$user['id']);
echo json_encode([
'success' => $saved,
'settings' => $settings,
'message' => $saved ? 'Notificatievoorkeuren succesvol opgeslagen.' : 'Fout bij opslaan.',
]);
exit;
}
// 3. Actuele agenda-afspraken van vandaag ophalen voor notificatie-evaluatie
if ($action === 'get_events') {
$userId = (int)$user['id'];
$settings = get_user_notification_settings($userId);
// Controleer of Outlook gekoppeld is
$stmtInt = $db->prepare("SELECT * FROM integrations WHERE user_id = ? AND provider = 'OUTLOOK' AND is_enabled = 1");
$stmtInt->execute([$userId]);
$outlookInt = $stmtInt->fetch();
$isLiveOutlook = !empty($outlookInt['access_token']) && empty($outlookInt['is_demo_mode']);
$events = [];
if ($isLiveOutlook) {
$events = microsoft_fetch_today_events($userId, $today);
}
// Als er geen live Outlook events zijn, haal ook taken met tijdblokken op uit Fociz dagplanning
$stmtTasks = $db->prepare("
SELECT t.id, t.title, t.time_block_start, t.time_block_end, t.source, t.external_url
FROM tasks t
LEFT JOIN daily_plans dp ON t.daily_plan_id = dp.id
WHERE t.user_id = ? AND (dp.plan_date = ? OR t.time_block_start IS NOT NULL) AND t.is_completed = 0
ORDER BY t.time_block_start ASC
");
$stmtTasks->execute([$userId, $today]);
$tasks = $stmtTasks->fetchAll();
foreach ($tasks as $t) {
if (!empty($t['time_block_start'])) {
$events[] = [
'id' => 'task_' . $t['id'],
'subject' => $t['title'],
'start' => $t['time_block_start'],
'end' => $t['time_block_end'] ?: date('H:i', strtotime($t['time_block_start'] . ' +30 minutes')),
'start_raw' => "{$today}T{$t['time_block_start']}:00",
'location' => 'Fociz Dagplanning',
'meeting_url' => $t['external_url'] ?? '/planner.php',
'is_all_day' => false,
'source' => 'FOCIZ_TASK',
];
}
}
// Als er nog steeds geen afspraken zijn (en demo mode actief), lever sandbox items zodat er altijd getest kan worden
if (empty($events) && (!empty($outlookInt['is_demo_mode']) || !$isLiveOutlook)) {
$currentHour = (int)date('H');
$nextHour = str_pad((string)(($currentHour + 1) % 24), 2, '0', STR_PAD_LEFT);
$events = [
[
'id' => 'sandbox_meeting_1',
'subject' => 'Focus Sync & Dagstart',
'start' => "{$nextHour}:00",
'end' => "{$nextHour}:30",
'start_raw' => "{$today}T{$nextHour}:00:00",
'location' => 'Microsoft Teams',
'meeting_url' => 'https://teams.microsoft.com',
'is_all_day' => false,
'source' => 'SANDBOX',
]
];
}
echo json_encode([
'success' => true,
'server_time' => date('H:i:s'),
'server_datetime' => date('Y-m-d H:i:s'),
'server_timestamp'=> time(),
'settings' => $settings,
'events' => $events,
'count' => count($events),
]);
exit;
}
echo json_encode(['error' => 'Ongeldige actie']);
exit;
} catch (Throwable $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'error' => $e->getMessage(),
]);
exit;
}