diff --git a/.manus/db/db-query-1768243292659.json b/.manus/db/db-query-1768243292659.json
new file mode 100644
index 0000000..1808947
--- /dev/null
+++ b/.manus/db/db-query-1768243292659.json
@@ -0,0 +1,9 @@
+{
+ "query": "ALTER TABLE parametres ADD COLUMN envoiAutomatiqueAttestations BOOLEAN DEFAULT true NOT NULL;",
+ "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 ALTER TABLE parametres ADD COLUMN envoiAutomatiqueAttestations BOOLEAN DEFAULT true NOT NULL;",
+ "rows": [],
+ "messages": [],
+ "stdout": "",
+ "stderr": "",
+ "execution_time_ms": 1061
+}
\ No newline at end of file
diff --git a/.manus/db/db-query-1768243299627.json b/.manus/db/db-query-1768243299627.json
new file mode 100644
index 0000000..d6d259e
--- /dev/null
+++ b/.manus/db/db-query-1768243299627.json
@@ -0,0 +1,9 @@
+{
+ "query": "CREATE TABLE historiqueAttestations (\n id INT AUTO_INCREMENT PRIMARY KEY,\n sequenceId INT NOT NULL,\n apprenantId INT NOT NULL,\n dateEnvoi TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n statut ENUM('envoye', 'erreur') NOT NULL,\n messageErreur TEXT NULL,\n urlAttestation VARCHAR(500) NULL,\n createdAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (sequenceId) REFERENCES sequences(id) ON DELETE CASCADE,\n FOREIGN KEY (apprenantId) REFERENCES apprenants(id) ON DELETE CASCADE\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 historiqueAttestations (\n id INT AUTO_INCREMENT PRIMARY KEY,\n sequenceId INT NOT NULL,\n apprenantId INT NOT NULL,\n dateEnvoi TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n statut ENUM('envoye', 'erreur') NOT NULL,\n messageErreur TEXT NULL,\n urlAttestation VARCHAR(500) NULL,\n createdAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (sequenceId) REFERENCES sequences(id) ON DELETE CASCADE,\n FOREIGN KEY (apprenantId) REFERENCES apprenants(id) ON DELETE CASCADE\n);",
+ "rows": [],
+ "messages": [],
+ "stdout": "",
+ "stderr": "",
+ "execution_time_ms": 261
+}
\ No newline at end of file
diff --git a/client/src/App.tsx b/client/src/App.tsx
index 59688d4..fa1087e 100644
--- a/client/src/App.tsx
+++ b/client/src/App.tsx
@@ -30,6 +30,7 @@ import AdminRappelsStats from "./pages/admin/AdminRappelsStats";
import AdminFormateurs from "./pages/admin/AdminFormateurs";
import AdminNotifications from "./pages/admin/AdminNotifications";
import AdminAttestations from "./pages/admin/AdminAttestations";
+import HistoriqueAttestations from "./pages/HistoriqueAttestations";
import AdminParametres from "./pages/AdminParametres";
import QuestionnaireReponse from "./pages/QuestionnaireReponse";
import Inscription from "./pages/Inscription";
@@ -56,6 +57,7 @@ function Router() {
+
diff --git a/client/src/components/DashboardLayout.tsx b/client/src/components/DashboardLayout.tsx
index ec686ec..20513e5 100644
--- a/client/src/components/DashboardLayout.tsx
+++ b/client/src/components/DashboardLayout.tsx
@@ -77,6 +77,7 @@ const menuSections = [
{ icon: Mail, label: "Notifications", path: "/admin/notifications" },
{ icon: TrendingUp, label: "Suivi Questionnaires", path: "/admin/questionnaires/suivi" },
{ icon: Bell, label: "Rappels", path: "/admin/rappels/historique" },
+ { icon: FileText, label: "Historique Attestations", path: "/admin/historique-attestations" },
]
},
{
diff --git a/client/src/pages/AdminParametres.tsx b/client/src/pages/AdminParametres.tsx
index c3fc98b..771f24b 100644
--- a/client/src/pages/AdminParametres.tsx
+++ b/client/src/pages/AdminParametres.tsx
@@ -19,6 +19,7 @@ export default function AdminParametres() {
const [delaiExpirationQR, setDelaiExpirationQR] = useState(30);
const [dureeValiditeToken, setDureeValiditeToken] = useState(24);
const [notificationsActives, setNotificationsActives] = useState(true);
+ const [envoiAutomatiqueAttestations, setEnvoiAutomatiqueAttestations] = useState(true);
const [testUrlStatus, setTestUrlStatus] = useState<{ loading: boolean; result?: { accessible: boolean; message: string } }>({ loading: false });
// Initialiser les valeurs quand les données sont chargées
@@ -28,6 +29,7 @@ export default function AdminParametres() {
setDelaiExpirationQR(parametres.delaiExpirationQR);
setDureeValiditeToken(parametres.dureeValiditeToken);
setNotificationsActives(parametres.notificationsActives);
+ setEnvoiAutomatiqueAttestations(parametres.envoiAutomatiqueAttestations);
}
}, [parametres]);
@@ -72,6 +74,7 @@ export default function AdminParametres() {
delaiExpirationQR,
dureeValiditeToken,
notificationsActives,
+ envoiAutomatiqueAttestations,
});
};
@@ -221,6 +224,23 @@ export default function AdminParametres() {
/>
+ {/* Envoi automatique des attestations */}
+
+
+
+
+ Envoyer automatiquement les attestations de formation aux apprenants à la fin de chaque séquence
+
+
+
+
+