diff --git a/client/src/pages/AdminFormations.tsx b/client/src/pages/AdminFormations.tsx index 8291174..14a5c27 100644 --- a/client/src/pages/AdminFormations.tsx +++ b/client/src/pages/AdminFormations.tsx @@ -22,7 +22,6 @@ export default function AdminFormations() { const [formData, setFormData] = useState({ nom: "", description: "", - publicCible: "autre" as "directeur" | "chef_service" | "autre", lienUnique: "", actif: true, }); @@ -64,7 +63,7 @@ export default function AdminFormations() { }); const resetForm = () => { - setFormData({ nom: "", description: "", publicCible: "autre" as "directeur" | "chef_service" | "autre", lienUnique: "", actif: true }); + setFormData({ nom: "", description: "", lienUnique: "", actif: true }); setEditingId(null); }; @@ -72,7 +71,6 @@ export default function AdminFormations() { setFormData({ nom: formation.nom, description: formation.description || "", - publicCible: formation.publicCible || "autre", lienUnique: formation.lienUnique, actif: formation.actif, }); @@ -169,22 +167,6 @@ export default function AdminFormations() { rows={3} /> -
- - -
Nom Description - Public cible Lien d'inscription Statut Actions - {filteredFormations.map((formation) => { - const publicCibleLabel = formation.publicCible === "directeur" ? "Directeur" : formation.publicCible === "chef_service" ? "Chef de service" : "Autre"; - return ( + {filteredFormations.map((formation) => ( {formation.nom} {formation.description || "-"} - {publicCibleLabel} - ); - })} + ))} ) : ( diff --git a/client/src/pages/AdminSequences.tsx b/client/src/pages/AdminSequences.tsx index d5c9ee3..bfb30f9 100644 --- a/client/src/pages/AdminSequences.tsx +++ b/client/src/pages/AdminSequences.tsx @@ -33,6 +33,7 @@ export default function AdminSequences() { formationId: "", nom: "", lieu: "", + publicCible: "autre" as "directeur" | "chef_service" | "autre", capaciteMax: "12", dateBlocage: "", statut: "ouverte" as "ouverte" | "bloquee" | "terminee", @@ -85,6 +86,7 @@ export default function AdminSequences() { formationId: "", nom: "", lieu: "", + publicCible: "autre", capaciteMax: "12", dateBlocage: "", statut: "ouverte", @@ -135,6 +137,7 @@ export default function AdminSequences() { formationId: sequence.formationId.toString(), nom: sequence.nom || "", lieu: sequence.lieu || "", + publicCible: sequence.publicCible || "autre", capaciteMax: sequence.capaciteMax?.toString() || "12", dateBlocage: safeFormatDate(sequence.dateBlocage), statut: sequence.statut || "ouverte", @@ -159,6 +162,7 @@ export default function AdminSequences() { formationId: parseInt(formData.formationId), nom: formData.nom, lieu: formData.lieu, + publicCible: formData.publicCible, capaciteMax: parseInt(formData.capaciteMax), dateBlocage: formData.dateBlocage, statut: formData.statut, @@ -350,6 +354,23 @@ export default function AdminSequences() { />
+
+ + +
+
Nom Dates Lieu + Public cible Capacité Statut Actions @@ -581,6 +603,7 @@ export default function AdminSequences() {
{sequence.lieu} + {sequence.publicCible === "directeur" ? "Directeur" : sequence.publicCible === "chef_service" ? "Chef de service" : "Autre"} {sequence.capaciteMax} diff --git a/client/src/pages/Inscription.tsx b/client/src/pages/Inscription.tsx index 118ebae..1bd2b3b 100644 --- a/client/src/pages/Inscription.tsx +++ b/client/src/pages/Inscription.tsx @@ -230,10 +230,6 @@ export default function Inscription() { {formation.description}

)} -
- - Public cible : {formation.publicCible === "directeur" ? "Directeurs" : formation.publicCible === "chef_service" ? "Chefs de service" : "Autre"} -
{/* Sessions disponibles */} @@ -277,6 +273,10 @@ export default function Inscription() { {sequence.lieu} +
+ + Public cible : {sequence.publicCible === "directeur" ? "Directeurs" : sequence.publicCible === "chef_service" ? "Chefs de service" : "Autre"} +
{sequence.placesRestantes} places disponibles diff --git a/drizzle/0005_cuddly_bushwacker.sql b/drizzle/0005_cuddly_bushwacker.sql new file mode 100644 index 0000000..d89c7ad --- /dev/null +++ b/drizzle/0005_cuddly_bushwacker.sql @@ -0,0 +1,2 @@ +ALTER TABLE `sequences` ADD `publicCible` enum('directeur','chef_service','autre') NOT NULL;--> statement-breakpoint +ALTER TABLE `formations` DROP COLUMN `publicCible`; \ No newline at end of file diff --git a/drizzle/meta/0005_snapshot.json b/drizzle/meta/0005_snapshot.json new file mode 100644 index 0000000..9929baf --- /dev/null +++ b/drizzle/meta/0005_snapshot.json @@ -0,0 +1,492 @@ +{ + "version": "5", + "dialect": "mysql", + "id": "b9b19655-1104-4112-ac8d-d568013faea2", + "prevId": "9dc05bf2-d92e-4abf-be1e-7357b388c9a5", + "tables": { + "apprenants": { + "name": "apprenants", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "nom": { + "name": "nom", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "prenom": { + "name": "prenom", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "varchar(320)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "codeEtablissement": { + "name": "codeEtablissement", + "type": "varchar(50)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "fonction": { + "name": "fonction", + "type": "enum('directeur','chef_service','autre')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "onUpdate": true, + "default": "(now())" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "apprenants_id": { + "name": "apprenants_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": { + "apprenants_email_unique": { + "name": "apprenants_email_unique", + "columns": [ + "email" + ] + } + }, + "checkConstraint": {} + }, + "datesFormation": { + "name": "datesFormation", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "sequenceId": { + "name": "sequenceId", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "dateDebut": { + "name": "dateDebut", + "type": "datetime", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "dateFin": { + "name": "dateFin", + "type": "datetime", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "ordre": { + "name": "ordre", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "datesFormation_id": { + "name": "datesFormation_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "formations": { + "name": "formations", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "nom": { + "name": "nom", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "lienUnique": { + "name": "lienUnique", + "type": "varchar(100)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "actif": { + "name": "actif", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "onUpdate": true, + "default": "(now())" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "formations_id": { + "name": "formations_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": { + "formations_lienUnique_unique": { + "name": "formations_lienUnique_unique", + "columns": [ + "lienUnique" + ] + } + }, + "checkConstraint": {} + }, + "inscriptions": { + "name": "inscriptions", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "apprenantId": { + "name": "apprenantId", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sequenceId": { + "name": "sequenceId", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "statut": { + "name": "statut", + "type": "enum('confirmee','liste_attente','annulee')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "dateInscription": { + "name": "dateInscription", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "onUpdate": true, + "default": "(now())" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "inscriptions_id": { + "name": "inscriptions_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "sequences": { + "name": "sequences", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "formationId": { + "name": "formationId", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "nom": { + "name": "nom", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "lieu": { + "name": "lieu", + "type": "varchar(500)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "publicCible": { + "name": "publicCible", + "type": "enum('directeur','chef_service','autre')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "capaciteMax": { + "name": "capaciteMax", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 12 + }, + "dateBlocage": { + "name": "dateBlocage", + "type": "datetime", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "statut": { + "name": "statut", + "type": "enum('ouverte','bloquee','terminee')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'ouverte'" + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "onUpdate": true, + "default": "(now())" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "sequences_id": { + "name": "sequences_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "users": { + "name": "users", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "openId": { + "name": "openId", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "varchar(320)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "loginMethod": { + "name": "loginMethod", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "enum('user','admin')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'user'" + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "onUpdate": true, + "default": "(now())" + }, + "lastSignedIn": { + "name": "lastSignedIn", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "users_id": { + "name": "users_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": { + "users_openId_unique": { + "name": "users_openId_unique", + "columns": [ + "openId" + ] + } + }, + "checkConstraint": {} + } + }, + "views": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "tables": {}, + "indexes": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index aa3420e..2596aee 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -36,6 +36,13 @@ "when": 1763047968048, "tag": "0004_futuristic_malice", "breakpoints": true + }, + { + "idx": 5, + "version": "5", + "when": 1763050409917, + "tag": "0005_cuddly_bushwacker", + "breakpoints": true } ] } \ No newline at end of file diff --git a/drizzle/schema.ts b/drizzle/schema.ts index c06cea2..5d7693a 100644 --- a/drizzle/schema.ts +++ b/drizzle/schema.ts @@ -32,8 +32,6 @@ export const formations = mysqlTable("formations", { id: int("id").autoincrement().primaryKey(), nom: varchar("nom", { length: 255 }).notNull(), description: text("description"), - /** Public cible de la formation (Directeur, Chef de service, Autre) */ - publicCible: mysqlEnum("publicCible", ["directeur", "chef_service", "autre"]).notNull(), /** Lien unique pour l'inscription à cette formation */ lienUnique: varchar("lienUnique", { length: 100 }).notNull().unique(), actif: boolean("actif").default(true).notNull(), @@ -71,6 +69,8 @@ export const sequences = mysqlTable("sequences", { nom: varchar("nom", { length: 255 }).notNull(), /** Lieu de la formation */ lieu: varchar("lieu", { length: 500 }).notNull(), + /** Public cible de la séquence (Directeur, Chef de service, Autre) */ + publicCible: mysqlEnum("publicCible", ["directeur", "chef_service", "autre"]).notNull(), /** Capacité maximale (12 par défaut) */ capaciteMax: int("capaciteMax").default(12).notNull(), /** Date de blocage des inscriptions (J-15 avant la première date) */ diff --git a/server/routers.ts b/server/routers.ts index c77598f..0acdc40 100644 --- a/server/routers.ts +++ b/server/routers.ts @@ -47,7 +47,6 @@ export const appRouter = router({ create: adminProcedure.input(z.object({ nom: z.string().min(1), description: z.string().optional(), - publicCible: z.enum(["directeur", "chef_service", "autre"]), lienUnique: z.string().min(1), actif: z.boolean().optional(), })).mutation(async ({ input }) => { @@ -59,7 +58,6 @@ export const appRouter = router({ id: z.number(), nom: z.string().min(1).optional(), description: z.string().optional(), - publicCible: z.enum(["directeur", "chef_service", "autre"]).optional(), lienUnique: z.string().min(1).optional(), actif: z.boolean().optional(), })).mutation(async ({ input }) => { @@ -156,6 +154,7 @@ export const appRouter = router({ formationId: z.number(), nom: z.string().min(1), lieu: z.string().min(1), + publicCible: z.enum(["directeur", "chef_service", "autre"]), capaciteMax: z.number().default(12), dateBlocage: z.string(), statut: z.enum(["ouverte", "bloquee", "terminee"]).optional(), @@ -194,6 +193,7 @@ export const appRouter = router({ formationId: z.number(), nom: z.string().min(1), lieu: z.string().min(1), + publicCible: z.enum(["directeur", "chef_service", "autre"]), capaciteMax: z.number(), dateBlocage: z.string(), statut: z.enum(["ouverte", "bloquee", "terminee"]), diff --git a/todo.md b/todo.md index 1fdeff0..531e075 100644 --- a/todo.md +++ b/todo.md @@ -122,3 +122,11 @@ - [x] Mettre à jour le schéma de base de données pour les formations - [x] Mettre à jour les formulaires de gestion des formations - [x] Afficher le public cible dans les listes et exports + +- [x] Déplacer le champ "Public cible" des formations vers les séquences +- [x] Retirer publicCible du schéma formations +- [x] Ajouter publicCible au schéma sequences +- [x] Mettre à jour les procédures tRPC pour sequences +- [x] Mettre à jour le formulaire de création/édition de séquences +- [x] Afficher le public cible dans la liste des séquences +- [x] Afficher le public cible par séquence sur la page d'inscription publique