diff --git a/.manus/db/db-query-1764540522642.json b/.manus/db/db-query-1764540522642.json new file mode 100644 index 0000000..70e5758 --- /dev/null +++ b/.manus/db/db-query-1764540522642.json @@ -0,0 +1,9 @@ +{ + "query": "CREATE TABLE IF NOT EXISTS `rappels` (\n `id` int AUTO_INCREMENT NOT NULL,\n `nom` varchar(255) NOT NULL,\n `templateType` varchar(50) NOT NULL,\n `joursAvant` int NOT NULL,\n `heureEnvoi` varchar(5) NOT NULL DEFAULT '09:00',\n `actif` boolean NOT NULL DEFAULT true,\n `derniereExecution` timestamp NULL,\n `createdAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n `updatedAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n CONSTRAINT `rappels_id` PRIMARY KEY(`id`)\n)", + "command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.root --database 7PAT67UmWoxv8vwp8Bbcv6 --execute CREATE TABLE IF NOT EXISTS `rappels` (\n `id` int AUTO_INCREMENT NOT NULL,\n `nom` varchar(255) NOT NULL,\n `templateType` varchar(50) NOT NULL,\n `joursAvant` int NOT NULL,\n `heureEnvoi` varchar(5) NOT NULL DEFAULT '09:00',\n `actif` boolean NOT NULL DEFAULT true,\n `derniereExecution` timestamp NULL,\n `createdAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n `updatedAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n CONSTRAINT `rappels_id` PRIMARY KEY(`id`)\n)", + "rows": [], + "messages": [], + "stdout": "", + "stderr": "", + "execution_time_ms": 112 +} \ No newline at end of file diff --git a/client/src/pages/AdminRappels.tsx b/client/src/pages/AdminRappels.tsx index 8d46119..ace3657 100644 --- a/client/src/pages/AdminRappels.tsx +++ b/client/src/pages/AdminRappels.tsx @@ -12,22 +12,34 @@ import { } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -import { Textarea } from "@/components/ui/textarea"; import { Switch } from "@/components/ui/switch"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { trpc } from "@/lib/trpc"; import { Bell, Edit, Plus, Trash2 } from "lucide-react"; import { toast } from "sonner"; +// Types de templates disponibles pour les rappels +const TEMPLATE_TYPES = [ + { value: "rappel", label: "Rappel J-7", joursAvant: 7 }, + { value: "rappelJ1", label: "Rappel J-1", joursAvant: 1 }, +]; + export default function AdminRappels() { const [isCreateOpen, setIsCreateOpen] = useState(false); const [isEditOpen, setIsEditOpen] = useState(false); const [editingRappel, setEditingRappel] = useState(null); const [formData, setFormData] = useState({ nom: "", - joursAvant: 0, - sujet: "", - contenu: "", + templateType: "", + joursAvant: 7, + heureEnvoi: "09:00", actif: true, }); @@ -67,18 +79,28 @@ export default function AdminRappels() { }, }); + const toggleActifMutation = trpc.rappels.toggleActif.useMutation({ + onSuccess: () => { + toast.success("Statut modifié avec succès"); + refetch(); + }, + onError: (error) => { + toast.error(`Erreur: ${error.message}`); + }, + }); + const resetForm = () => { setFormData({ nom: "", - joursAvant: 0, - sujet: "", - contenu: "", + templateType: "", + joursAvant: 7, + heureEnvoi: "09:00", actif: true, }); }; const handleCreate = () => { - if (!formData.nom || !formData.sujet || !formData.contenu) { + if (!formData.nom || !formData.templateType) { toast.error("Veuillez remplir tous les champs obligatoires"); return; } @@ -89,9 +111,9 @@ export default function AdminRappels() { setEditingRappel(rappel); setFormData({ nom: rappel.nom, + templateType: rappel.templateType, joursAvant: rappel.joursAvant, - sujet: rappel.sujet, - contenu: rappel.contenu, + heureEnvoi: rappel.heureEnvoi, actif: rappel.actif, }); setIsEditOpen(true); @@ -99,7 +121,7 @@ export default function AdminRappels() { const handleUpdate = () => { if (!editingRappel) return; - if (!formData.nom || !formData.sujet || !formData.contenu) { + if (!formData.nom || !formData.templateType) { toast.error("Veuillez remplir tous les champs obligatoires"); return; } @@ -115,6 +137,24 @@ export default function AdminRappels() { } }; + const handleToggleActif = (id: number, actif: boolean) => { + toggleActifMutation.mutate({ id, actif: !actif }); + }; + + const handleTemplateTypeChange = (value: string) => { + const template = TEMPLATE_TYPES.find(t => t.value === value); + setFormData({ + ...formData, + templateType: value, + joursAvant: template?.joursAvant || 7, + nom: template?.label || "", + }); + }; + + const getTemplateName = (type: string) => { + return TEMPLATE_TYPES.find(t => t.value === type)?.label || type; + }; + return (
@@ -146,8 +186,9 @@ export default function AdminRappels() { Nom + Type Délai - Sujet + Heure Statut Actions @@ -157,18 +198,20 @@ export default function AdminRappels() { rappels.map((rappel) => ( {rappel.nom} + {getTemplateName(rappel.templateType)} J-{rappel.joursAvant} - {rappel.sujet} + {rappel.heureEnvoi} - handleToggleActif(rappel.id, rappel.actif)} + className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium cursor-pointer ${ rappel.actif - ? "bg-green-100 text-green-800" - : "bg-gray-100 text-gray-800" + ? "bg-green-100 text-green-800 hover:bg-green-200" + : "bg-gray-100 text-gray-800 hover:bg-gray-200" }`} > {rappel.actif ? "Actif" : "Inactif"} - +
@@ -192,7 +235,7 @@ export default function AdminRappels() { )) ) : ( - + Aucun rappel configuré @@ -212,13 +255,35 @@ export default function AdminRappels() {
+
+ + +

+ Le template d'email correspondant sera utilisé pour l'envoi +

+
+
setFormData({ ...formData, nom: e.target.value })} - placeholder="Ex: Rappel J-15" + placeholder="Ex: Rappel automatique J-7" />
@@ -232,7 +297,7 @@ export default function AdminRappels() { onChange={(e) => setFormData({ ...formData, joursAvant: parseInt(e.target.value) || 0 }) } - placeholder="Ex: 15" + placeholder="Ex: 7" />

Le rappel sera envoyé ce nombre de jours avant le début de la séquence @@ -240,26 +305,15 @@ export default function AdminRappels() {

- + setFormData({ ...formData, sujet: e.target.value })} - placeholder="Ex: Rappel - Formation dans 15 jours" - /> -
- -
- -