function formatDate(dateStr) { const d = new Date(dateStr); return d.toLocaleDateString('fr-FR', { year: 'numeric', month: 'long', day: 'numeric' }); } function showError(message) { document.getElementById('error').innerHTML = `
`; } function statTile(value, label) { return `Aucun calendrier configuré.
'; container.querySelectorAll('.remove-my-feed-btn').forEach((btn) => { btn.addEventListener('click', () => onRemoveMyFeed(parseInt(btn.dataset.feedId, 10))); }); } async function onAddMyFeed(e) { e.preventDefault(); const form = e.target; const label = form.label.value.trim(); const icsUrl = form.icsUrl.value.trim(); const submitBtn = form.querySelector('button[type="submit"]'); submitBtn.disabled = true; submitBtn.textContent = 'Vérification…'; try { await api.post('/api/calendar/my-feeds', { label, icsUrl }); form.reset(); await loadMyFeeds(); } catch (err) { showError(err.message); } finally { submitBtn.disabled = false; submitBtn.textContent = '+ Ajouter'; } } async function onRemoveMyFeed(feedId) { try { await api.del(`/api/calendar/my-feeds/${feedId}`); await loadMyFeeds(); } catch (err) { showError(err.message); } } async function loadIcsFeedUrl() { const { path } = await api.get('/api/users/me/ics-feed-url'); const httpsUrl = `${window.location.origin}${path}`; const webcalUrl = `webcal://${window.location.host}${path}`; document.getElementById('ics-feed-url').value = webcalUrl; document.getElementById('ics-feed-open-link').href = webcalUrl; document.getElementById('copy-ics-feed-btn').dataset.url = httpsUrl; } async function onCopyIcsFeedUrl(e) { const btn = e.target; try { await navigator.clipboard.writeText(btn.dataset.url); const original = btn.textContent; btn.textContent = 'Copié !'; setTimeout(() => { btn.textContent = original; }, 1500); } catch (err) { showError("Impossible de copier le lien : " + err.message); } } async function onSaveDisplayName(e) { e.preventDefault(); const form = e.target; const displayName = form.displayName.value.trim(); try { await api.patch('/api/users/me/display-name', { displayName }); window.location.reload(); } catch (err) { showError(err.message); } } async function onResetDisplayName() { try { await api.patch('/api/users/me/display-name', { displayName: '' }); window.location.reload(); } catch (err) { showError(err.message); } } (async function init() { await initNav(null); try { const profile = await api.get('/api/users/me/profile'); const container = document.getElementById('content'); container.innerHTML = `Par défaut, le nom fourni par Authentik est utilisé. Vous pouvez le remplacer par un nom personnalisé ci-dessous — cela n'affecte pas votre compte Authentik.
Ajoutez le lien ICS (iCal) d'un ou plusieurs de vos calendriers (Google, Outlook, Apple...) pour apparaître dans les disponibilités du groupe sur la page Disponibilités. L'application ne conserve jamais le contenu de vos calendriers — seul un statut disponible/occupé par créneau est déduit et enregistré.
Chargement…
Abonnez-vous à ce lien depuis Google Calendar, Apple Calendar ou Outlook pour voir les répétitions (proposées et confirmées) directement dans votre calendrier personnel, mises à jour automatiquement. Ce lien est personnel, ne le partagez pas.
Identité gérée par Authentik — pour changer votre email ou mot de passe, ${profile.authentikAccountUrl ? `rendez-vous sur votre compte Authentik.` : 'rendez-vous sur votre compte Authentik.'}