From 02058598809746fa2236b8d098abf3b0afad7548 Mon Sep 17 00:00:00 2001 From: Manus Date: Wed, 13 May 2026 10:40:13 -0400 Subject: [PATCH] =?UTF-8?q?Checkpoint:=20Impl=C3=A9mentation=20des=20fonct?= =?UTF-8?q?ionnalit=C3=A9s=20de=20communication=20:=20formulaire=20de=20co?= =?UTF-8?q?ntact=20avec=20choix=20email/canal,=20canaux=20de=20discussion?= =?UTF-8?q?=20int=C3=A9gr=C3=A9s=20(page=20Mes=20=C3=89changes),=20demande?= =?UTF-8?q?s=20de=20mise=20en=20relation=20avec=20gestion=20admin=20des=20?= =?UTF-8?q?canaux,=20navigation=20mise=20=C3=A0=20jour=20dans=20DashboardL?= =?UTF-8?q?ayout,=20bouton=20Demande=20de=20mise=20en=20relation=20sur=20f?= =?UTF-8?q?iche=20=C3=A9tablissement.=20Migration=20DB=20:=20tables=20cana?= =?UTF-8?q?ux=5Fdiscussion,=20membres=5Fcanal,=20messages=5Fcanal,=20deman?= =?UTF-8?q?des=5Fmise=5Fen=5Frelation.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VERSION | 1 + client/src/App.tsx | 4 + client/src/components/ContactModal.tsx | 171 ++- client/src/components/DashboardLayout.tsx | 18 +- client/src/pages/FicheEtablissement.tsx | 9 + client/src/pages/MesEchanges.tsx | 279 +++++ client/src/pages/MiseEnRelation.tsx | 417 ++++++++ drizzle/0004_empty_energizer.sql | 52 + drizzle/meta/0004_snapshot.json | 1160 +++++++++++++++++++++ drizzle/meta/_journal.json | 7 + drizzle/schema.ts | 57 + server/db.ts | 226 +++- server/routers.ts | 93 +- 13 files changed, 2437 insertions(+), 57 deletions(-) create mode 100644 VERSION create mode 100644 client/src/pages/MesEchanges.tsx create mode 100644 client/src/pages/MiseEnRelation.tsx create mode 100644 drizzle/0004_empty_energizer.sql create mode 100644 drizzle/meta/0004_snapshot.json diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..13d71a7 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +v11-1777031516 diff --git a/client/src/App.tsx b/client/src/App.tsx index da8cc0a..b22d699 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -14,6 +14,8 @@ import LoginLocal from "./pages/LoginLocal"; import MesSolutions from "./pages/MesSolutions"; import SolutionsLogicielles from "./pages/SolutionsLogicielles"; import Statistiques from "./pages/Statistiques"; +import MesEchanges from "./pages/MesEchanges"; +import MiseEnRelation from "./pages/MiseEnRelation"; function Router() { return ( @@ -31,6 +33,8 @@ function Router() { + + {/* Fallback */} diff --git a/client/src/components/ContactModal.tsx b/client/src/components/ContactModal.tsx index 59b65e9..2ccf905 100644 --- a/client/src/components/ContactModal.tsx +++ b/client/src/components/ContactModal.tsx @@ -1,5 +1,5 @@ import { trpc } from "@/lib/trpc"; -import { Building2, Mail, Send, X } from "lucide-react"; +import { Building2, Mail, MessageSquare, Send, X } from "lucide-react"; import { useState } from "react"; import { toast } from "sonner"; @@ -9,87 +9,158 @@ interface ContactModalProps { onClose: () => void; } +type Mode = "choix" | "email" | "canal"; + export default function ContactModal({ etablissementId, etablissementNom, onClose }: ContactModalProps) { + const [mode, setMode] = useState("choix"); const [message, setMessage] = useState(""); - const sendMutation = trpc.contact.envoyer.useMutation({ + const sendEmailMutation = trpc.contact.envoyer.useMutation({ onSuccess: () => { - toast.success("Votre demande de contact a été envoyée avec succès."); + toast.success("Votre demande a été transmise au référent numérique par email."); onClose(); }, - onError: (err) => { - toast.error("Erreur lors de l'envoi : " + err.message); - }, + onError: (err) => toast.error("Erreur lors de l'envoi : " + err.message), }); - const handleSubmit = (e: React.FormEvent) => { + const createCanalMutation = trpc.canaux.create.useMutation({ + onSuccess: () => { + toast.success("Un canal de discussion a été ouvert. Retrouvez-le dans « Mes Échanges »."); + onClose(); + }, + onError: (err) => toast.error("Erreur : " + err.message), + }); + + const etabQuery = trpc.etablissements.byId.useQuery({ id: etablissementId }); + const referentId = etabQuery.data?.referentId; + + const handleSubmitEmail = (e: React.FormEvent) => { e.preventDefault(); if (!message.trim()) return; - sendMutation.mutate({ etablissementCibleId: etablissementId, message }); + sendEmailMutation.mutate({ etablissementCibleId: etablissementId, message }); + }; + + const handleSubmitCanal = (e: React.FormEvent) => { + e.preventDefault(); + if (!message.trim()) return; + const membreIds = referentId ? [referentId] : []; + createCanalMutation.mutate({ + titre: `Contact — ${etablissementNom}`, + description: message, + type: "contact_referent", + visibilite: "prive", + etablissementId, + membreIds, + }); }; return (
- {/* En-tête */}
-

Demande de contact

+

Contacter le référent numérique

{etablissementNom}
-
- {/* Formulaire */} -
-
- -