Comment construire un agenda collaboratif avec filtres
L'agenda de TAMSIV a commencé comme un composant simple : une liste d'événements, un calendrier, une vue jour. Et puis les groupes collaboratifs sont arrivés. Soudain, un événement n'était plus personnel — il pouvait avoir des participants, des invitations, des statuts. Et avec 15 personnes dans un groupe actif, l'agenda est devenu illisible sans filtres.
J'ai dû repenser l'ensemble : système de participants avec invitations et notifications, filtres avancés pour naviguer dans le flux, événements multi-jours, et un overlay privé pour voir ses engagements personnels dans le contexte du groupe. L'agenda est devenu le composant le plus complexe de TAMSIV — mais aussi le plus utile au quotidien.
Points clés à retenir :
- Un agenda collaboratif nécessite un système de participants avec statuts (invité, accepté, refusé)
- Les filtres avancés sont indispensables dès que l'activité du groupe dépasse 10 événements/semaine
- Les événements multi-jours demandent un calcul de spans avec gestion des fuseaux horaires
- L'overlay privé dans l'agenda de groupe préserve la confidentialité tout en évitant les conflits
- 5 vues de calendrier (jour, 3 jours, semaine, mois, liste) couvrent tous les cas d'usage
Pourquoi un agenda personnel ne suffit-il pas dans une app collaborative ?
Tant que TAMSIV était une app strictement personnelle, l'agenda était simple. Tu crées un événement, tu le vois dans ton calendrier, point. Mais quand j'ai ajouté les groupes hiérarchiques, tout a changé.
Dans un groupe (famille, équipe, association), les événements sont partagés. Une réunion, un dîner de famille, un match sportif — tout le monde doit le voir. Mais tout le monde ne veut pas voir tous les événements. Le manager veut voir les réunions de son équipe, pas les sorties du groupe bowling. Le parent veut voir les activités des enfants, pas les meetings professionnels du conjoint.
C'est là que les filtres et le système de participants deviennent essentiels. Sans eux, l'agenda collaboratif est un brouhaha inutile.
Comment fonctionne le système de participants dans TAMSIV ?
Chaque événement dans TAMSIV peut avoir des participants invités parmi les membres du groupe. L'architecture repose sur une table de liaison dans le schéma collaborative :
-- Table simplifiee
calendar_event_participants (
id UUID PRIMARY KEY,
event_id UUID REFERENCES privat.calendar_events,
user_id UUID REFERENCES auth.users,
status TEXT CHECK (status IN ('invited', 'accepted', 'declined')),
invited_at TIMESTAMPTZ,
responded_at TIMESTAMPTZ
)
Le flow d'invitation est le suivant :
- Le créateur ajoute des participants lors de la création ou de l'édition de l'événement. Il choisit parmi les membres du groupe via un picker.
- Notification push : Chaque participant invité reçoit une notification FCM avec le titre de l'événement, la date et un bouton pour accepter ou décliner.
- Réponse : Le participant accepte ou décline. Son statut est mis à jour en temps réel dans la base.
- Visibilité : L'événement apparaît dans l'agenda de tous les participants (invités, acceptés). Les déclinés ne le voient plus (sauf s'ils changent d'avis).
C'est un flow similaire à ce que tu trouves dans Google Calendar, mais adapté au contexte de groupes hiérarchiques de TAMSIV. La différence principale : les participants sont limités aux membres du groupe, pas à n'importe quelle adresse email.
Quels filtres avancés sont indispensables dans un agenda de groupe ?
La FilterBar de l'agenda propose trois modes de filtrage :
- "Tous" : Affiche tous les événements du groupe. Utile pour avoir une vue d'ensemble, mais vite bruyant dans un groupe actif.
- "Mes créations" : N'affiche que les événements que tu as créés. Utile pour vérifier que tes propres événements sont bien planifiés.
- "Participating" : N'affiche que les événements où tu es participant (invité ou accepté). C'est le mode le plus utilisé — il répond à la question "À quoi dois-je être présent ?".
Ces filtres s'appliquent en temps réel, sans rechargement de page. Le ContentCacheService stocke les événements en cache, et les filtres opèrent côté client sur les données cachées. Le résultat : un changement de filtre est instantané, même avec des centaines d'événements.
En plus des filtres par participation, la FilterBar propose les 3 contextes classiques de TAMSIV :
- Privé : Tes événements personnels uniquement
- Partagé : Événements des groupes auxquels tu appartiens
- Tout : Fusion des deux vues
Ces filtres sont cohérents avec ceux du feed et des tâches. L'utilisateur retrouve les mêmes paradigmes de navigation partout dans l'app.
Comment gérer les événements multi-jours dans un composant calendrier ?
Un événement "Conférence lundi→mercredi" doit apparaître sur 3 jours dans la vue calendrier. Ça paraît trivial, mais l'implémentation est pleine de pièges.
Le composant AgendaView calcule les spans — la durée en jours de chaque événement. Pour chaque jour affiché, il détermine quels événements le couvrent et les positionne visuellement :
- Vue jour : L'événement multi-jours apparaît comme un bandeau en haut, au-dessus des événements horaires.
- Vue semaine : L'événement s'étend horizontalement sur les colonnes correspondant aux jours couverts.
- Vue mois : Même principe, avec un système de troncature si trop d'événements se chevauchent.
- Vue liste : L'événement apparaît une seule fois, avec ses dates de début et fin.
Le piège principal : les fuseaux horaires aux frontières de journée. Un événement qui commence à 23h le lundi en UTC+1 et finit à 2h le mardi couvre-t-il 1 jour ou 2 ? La réponse dépend du fuseau horaire de l'utilisateur. J'ai opté pour une logique simple : un événement couvre un jour s'il a au moins une heure de présence dans ce jour, dans le fuseau local de l'utilisateur.
Qu'est-ce que l'overlay privé et pourquoi est-il essentiel ?
Voici le scénario : tu es dans l'agenda de ton groupe professionnel. Tu veux planifier une réunion mardi à 14h. Mais mardi à 14h, tu as un rendez-vous médical personnel. Comment le savoir sans quitter l'agenda du groupe ?
C'est le rôle de l'overlay privé. Dans l'agenda de groupe, tes événements personnels apparaissent en transparence, grisés. Ils ne sont pas cliquables, pas de détails visibles — juste un bloc pour signaler "tu as déjà quelque chose ici".
Les règles de l'overlay :
- Visible uniquement par toi : Les autres membres du groupe ne voient pas tes événements privés.
- Non interactif : Pas de clic, pas de détails, pas de modification depuis la vue groupe.
- Visuel discret : Opacité réduite (30%), couleur grise, pas de titre visible. Juste un indicateur de "slot occupé".
- Désactivable : Un toggle dans les paramètres permet de masquer l'overlay si tu n'en veux pas.
Cet overlay respecte la confidentialité tout en évitant les conflits d'horaire. C'est un pattern que j'ai repris de Google Calendar (qui montre "Busy" pour les événements des autres), adapté au contexte d'un groupe où la vie privée est importante.
Comment les 5 vues de calendrier couvrent-elles tous les cas d'usage ?
TAMSIV propose 5 vues de calendrier, chacune adaptée à un besoin différent :
- Vue jour : Timeline heure par heure. Idéale pour planifier une journée chargée, voir les créneaux libres. Utilisée quand tu cherches "Quand est-ce que je suis libre aujourd'hui ?".
- Vue 3 jours : Compromis entre le détail du jour et la vision de la semaine. Mon préféré pour la planification à court terme. Tu vois aujourd'hui + les 2 prochains jours.
- Vue semaine : La vue classique business. 7 colonnes, chaque jour visible. Utile pour les équipes qui planifient à la semaine.
- Vue mois : Vue d'ensemble. Les événements sont des pastilles colorées. Utile pour repérer les périodes chargées et les jours libres. Cohérent avec la vision productivité de l'app.
- Vue liste : Liste chronologique simple. Pas de grille, pas de positionnement. Utile sur mobile quand la vue semaine est trop petite, ou pour exporter/partager.
Chaque vue conserve la date courante lors du changement de vue. Si tu es sur le mercredi 15 en vue jour et que tu passes en vue semaine, tu vois la semaine du 15. Le swipe horizontal permet de naviguer dans le temps (jour précédent/suivant, semaine précédente/suivante).
Comment l'agenda interagit-il avec le pipeline vocal de TAMSIV ?
L'un des points forts de TAMSIV, c'est la création d'événements par la voix. Tu dis "Ajoute une réunion avec Marc mardi prochain à 14h" et le dictaphone crée l'événement. Le backend utilise le function tool create_calendar_event pour extraire la date, l'heure, le titre et les participants mentionnés.
Le système de PendingCreation s'applique aussi aux événements : l'IA crée une preview, l'utilisateur peut éditer les détails (ajouter des participants, modifier l'heure) avant de valider. Ça évite les erreurs de transcription — "mardi" vs "mercredi" est une erreur STT classique.
Une fois l'événement créé, le cache Realtime propage le changement : tous les participants voient l'événement apparaître dans leur agenda sans rafraîchir. La notification push part en parallèle. L'ensemble du flow — voix → IA → création → notification → affichage — prend environ 3 secondes.
Quelles ont été les difficultés techniques majeures ?
L'agenda est le composant le plus complexe de TAMSIV. Voici les principaux défis que j'ai rencontrés :
- Performance du rendu : La vue semaine avec 50+ événements et l'overlay privé doit rester fluide. J'ai dû utiliser
React.memoagressivement et virtualiser les listes d'événements dans la vue liste. - Gestion du scroll : Le swipe horizontal pour naviguer entre les jours/semaines entre en conflit avec le scroll vertical de la timeline. J'ai utilisé un
GestureDetectorde react-native-gesture-handler avec des seuils de direction pour désambiguer. - Événements empilés : Quand 3 événements se chevauchent sur le même créneau, il faut les disposer côte à côte dans la timeline. L'algorithme de layout des événements empilés est non-trivial — c'est un problème d'interval scheduling.
- RLS Supabase : Les politiques Row Level Security pour les événements de groupe sont complexes. Un événement est visible si : tu l'as créé, OU tu es participant, OU tu es membre du groupe et l'événement est public. Trois conditions OR dans une seule politique RLS.
Comment cette architecture s'étend-elle aux futurs besoins ?
L'architecture actuelle est conçue pour évoluer. Voici les extensions prévues dans la roadmap :
- Récurrence : Événements récurrents (tous les lundis, le 1er de chaque mois). Le schéma DB est prêt, le frontend pas encore.
- Sync calendrier externe : Import/export iCal pour synchroniser avec Google Calendar, Outlook, Apple Calendar.
- Disponibilité partagée : Montrer les créneaux de disponibilité des membres du groupe pour faciliter la planification.
- Rappels personnalisés : Chaque participant peut configurer ses propres rappels (5 min avant, 1h avant, la veille).
FAQ
Peut-on inviter des participants en dehors du groupe ?
Actuellement non. Les participants sont limités aux membres du groupe dans lequel l'événement est créé. C'est un choix délibéré pour simplifier la gestion des permissions. L'invitation par email (comme Google Calendar) est prévue dans une version future.
Comment les notifications d'invitation fonctionnent-elles ?
Les invitations déclenchent une notification push via Firebase Cloud Messaging. Le participant reçoit le titre de l'événement, la date/heure, et peut accepter ou décliner directement depuis la notification (action buttons FCM). La réponse est enregistrée en temps réel dans Supabase.
L'overlay privé fonctionne-t-il dans toutes les vues ?
Oui, l'overlay privé est actif dans les 5 vues (jour, 3 jours, semaine, mois, liste). Dans la vue mois, les événements privés apparaissent comme des points gris discrets. Dans les vues temporelles (jour, semaine), ils apparaissent comme des blocs transparents.
L'agenda de TAMSIV remplace-t-il Google Calendar ?
Non, il le complète. L'agenda TAMSIV est conçu pour la gestion de tâches et de projets collaboratifs, avec la voix comme mode d'interaction principal. Google Calendar reste plus adapté pour la gestion de calendrier pur (récurrences complexes, sync multi-devices). La synchronisation entre les deux est dans la roadmap.
Peut-on créer un événement par la voix avec des participants ?
Oui. Tu peux dire "Réunion avec Marc et Sophie vendredi à 10h" et l'IA détectera les participants mentionnés, à condition qu'ils soient membres du groupe actif. Le système de PendingCreation te permet de vérifier et ajuster les participants avant validation.