diff --git a/backend/server.ts b/backend/server.ts
index 5f5b6dc..abc47b1 100644
--- a/backend/server.ts
+++ b/backend/server.ts
@@ -18,7 +18,7 @@ import challengeRoutes from './src/routes/challenge.routes';
import defaultRoute from './src/routes/default.routes';
import discordRoutes from './src/routes/discord.routes';
import emailRoutes from './src/routes/email.routes';
-import eventRoutes from './src/routes/event.routes';
+import settingsRoutes from './src/routes/settings.routes';
import factionRoutes from './src/routes/faction.routes';
import imexportRouter from './src/routes/im_export.routes';
import newsRoutes from './src/routes/news.routes';
@@ -59,7 +59,7 @@ async function startServer() {
app.use('/api/role', authenticateUser, roleRoutes);
app.use('/api/user', authenticateUser, userRoutes);
app.use('/api/team', authenticateUser, teamRoutes);
- app.use('/api/event', authenticateUser, eventRoutes);
+ app.use('/api/settings', authenticateUser, settingsRoutes);
app.use('/api/faction', authenticateUser, factionRoutes);
app.use('/api/imexport', authenticateUser, imexportRouter);
app.use('/api/permanence', authenticateUser, permanenceRoutes);
diff --git a/backend/src/controllers/event.controller.ts b/backend/src/controllers/event.controller.ts
deleted file mode 100644
index b32b11c..0000000
--- a/backend/src/controllers/event.controller.ts
+++ /dev/null
@@ -1,199 +0,0 @@
-import * as event_service from '../services/event.service';
-import * as team_service from '../services/team.service';
-import { Conflict, Error, Ok, Teapot, Unauthorized } from '../shared/http/responses';
-import { shotgun_password } from '../shared/secrets/secrets';
-import type { AppRequestHandler } from '../types/http';
-import type { ShotgunBody, ToggleStatusBody } from '../dto/event.dto';
-
-export const checkShotgunStatus: AppRequestHandler = async (_req, res) => {
- try {
- const status = await event_service.getEventsStatus();
- Ok(res, {
- data: { status: Boolean(status?.shotgun_open), password: status?.shotgun_open ? shotgun_password : '' },
- });
- } catch (error) {
- Error(res, { msg: 'Error while catching shotgun status :' + error });
- }
-};
-
-export const checkPreRegisterStatus: AppRequestHandler = async (_req, res) => {
- try {
- const status = await event_service.getEventsStatus();
- Ok(res, { data: status?.pre_registration_open });
- } catch (error) {
- Error(res, { msg: 'Error while catching pre-registration status :' + error });
- }
-};
-
-export const checkSDIStatus: AppRequestHandler = async (_req, res) => {
- try {
- const status = await event_service.getEventsStatus();
- Ok(res, { data: status?.sdi_open });
- } catch (error) {
- Error(res, { msg: 'Error while catching SDI status :' + error });
- }
-};
-
-export const checkWEIStatus: AppRequestHandler = async (_req, res) => {
- try {
- const status = await event_service.getEventsStatus();
- Ok(res, { data: status?.wei_open });
- } catch (error) {
- Error(res, { msg: 'Error while catching WEI status :' + error });
- }
-};
-
-export const checkFoodStatus: AppRequestHandler = async (_req, res) => {
- try {
- const status = await event_service.getEventsStatus();
- Ok(res, { data: status?.food_open });
- } catch (error) {
- Error(res, { msg: 'Error while catching Food status :' + error });
- }
-};
-
-export const checkChallStatus: AppRequestHandler = async (_req, res) => {
- try {
- const status = await event_service.getEventsStatus();
- Ok(res, { data: status?.chall_open });
- } catch (error) {
- Error(res, { msg: 'Error while catching Challenge status :' + error });
- }
-};
-
-export const getShotgunAttempts: AppRequestHandler = async (_req, res) => {
- try {
- const shotgunAttempts = await event_service.getAllTeamShotguns();
- const shotgunAttemptsWithLeaders = await Promise.all(
- shotgunAttempts.map(async (attempt) => {
- if (!attempt.teamId) {
- return { ...attempt, leaderCount: 0 };
- }
-
- const teamUsers = await team_service.getTeamUsers(attempt.teamId);
- const leaderCount = teamUsers.filter((user) => user.permission !== 'Nouveau').length;
-
- return { ...attempt, leaderCount };
- }),
- );
-
- Ok(res, { data: shotgunAttemptsWithLeaders });
- } catch (error) {
- Error(res, { msg: 'Erreur lors de la récupération des tentatives shotgun : ' + error });
- }
-};
-
-export const shotgunAttempt: AppRequestHandler = async (req, res) => {
- const { password } = req.body;
-
- const userId = req.user?.userId;
-
- if (!userId) {
- Unauthorized(res, { msg: 'Utilisateur non authentifié.' });
- return;
- }
-
- if (!shotgun_password) {
- Error(res, { msg: 'Mot de passe shotgun non configuré côté serveur.' });
- return;
- }
-
- if (password !== shotgun_password) {
- Teapot(res, { msg: 'Le mot de passe shotgun est incorrect.' });
- return;
- }
-
- const status = await event_service.getEventsStatus();
- if (!status?.shotgun_open) {
- Unauthorized(res, { msg: 'Le shotgun est fermé.' });
- return;
- }
- try {
- const userTeam = await team_service.getUserTeam(userId);
-
- if (!userTeam) {
- Error(res, { msg: "Erreur : Tu n'as pas d'équipe !" });
- return;
- }
-
- const alreadyShotgun = await event_service.alreadyShotgun(userTeam);
-
- if (alreadyShotgun) {
- Conflict(res, { msg: 'Votre équipe est déjà dans le shotgun.' });
- return;
- }
-
- await event_service.validateShotgun(userTeam);
- Ok(res, { msg: 'Shotgun validé !' });
- return;
- } catch (error) {
- Error(res, { msg: 'Erreur pendant le shotguns : ' + error });
- return;
- }
-};
-
-export const togglePreRegistration: AppRequestHandler = async (req, res) => {
- const { preRegistrationOpen } = req.body;
-
- try {
- const result = await event_service.updatepreRegistrationStatus(preRegistrationOpen);
- Ok(res, { msg: 'Paramètres mis à jour.', data: result });
- } catch {
- Error(res, { msg: 'Erreur lors de la mise à jour.' });
- }
-};
-
-export const toggleShotgun: AppRequestHandler = async (req, res) => {
- const { shotgunOpen } = req.body;
-
- try {
- const result = await event_service.updateShotgunStatus(shotgunOpen);
- Ok(res, { msg: 'Paramètres mis à jour.', data: result });
- } catch {
- Error(res, { msg: 'Erreur lors de la mise à jour.' });
- }
-};
-
-export const toggleSDI: AppRequestHandler = async (req, res) => {
- const { sdiOpen } = req.body;
-
- try {
- const result = await event_service.updateSDIStatus(sdiOpen);
- Ok(res, { msg: 'Paramètres mis à jour.', data: result });
- } catch {
- Error(res, { msg: 'Erreur lors de la mise à jour.' });
- }
-};
-
-export const toggleWEI: AppRequestHandler = async (req, res) => {
- const { weiOpen } = req.body;
-
- try {
- const result = await event_service.updateWEIStatus(weiOpen);
- Ok(res, { msg: 'Paramètres mis à jour.', data: result });
- } catch {
- Error(res, { msg: 'Erreur lors de la mise à jour.' });
- }
-};
-
-export const toggleFood: AppRequestHandler = async (req, res) => {
- const { foodOpen } = req.body;
-
- try {
- const result = await event_service.updateFoodStatus(foodOpen);
- Ok(res, { msg: 'Paramètres mis à jour.', data: result });
- } catch {
- Error(res, { msg: 'Erreur lors de la mise à jour.' });
- }
-};
-
-export const toggleChall: AppRequestHandler = async (req, res) => {
- const { challOpen } = req.body;
-
- try {
- const result = await event_service.updateChallStatus(challOpen);
- Ok(res, { msg: 'Paramètres mis à jour.', data: result });
- } catch {
- Error(res, { msg: 'Erreur lors de la mise à jour.' });
- }
-};
diff --git a/backend/src/controllers/im_export.controller.ts b/backend/src/controllers/im_export.controller.ts
index 668c40f..ee1505f 100644
--- a/backend/src/controllers/im_export.controller.ts
+++ b/backend/src/controllers/im_export.controller.ts
@@ -1,6 +1,6 @@
import fs from 'fs';
import path from 'path';
-import * as event_service from '../services/event.service';
+import * as settings_service from '../services/settings.service';
import * as export_service from '../services/im_export.service';
import * as permanence_service from '../services/permanence.service';
import * as team_service from '../services/team.service';
@@ -22,7 +22,7 @@ export const exportAllDataToSheets: AppRequestHandler = async (_req, res) => {
const userList = await user_service.getUsersAll();
const teamList = await team_service.getTeamsAll();
const permanenceList = await permanence_service.getAllPermanencesWithUsers();
- const shotgunList = await event_service.getAllTeamShotguns();
+ const shotgunList = await settings_service.getAllTeamShotguns();
// 2. Mapping -> format pour Google Sheets (array de array)
const usersValues = [
diff --git a/backend/src/controllers/settings.controller.ts b/backend/src/controllers/settings.controller.ts
new file mode 100644
index 0000000..004e768
--- /dev/null
+++ b/backend/src/controllers/settings.controller.ts
@@ -0,0 +1,139 @@
+import * as settings_service from '../services/settings.service';
+import * as team_service from '../services/team.service';
+import { Conflict, Error, Ok, Teapot, Unauthorized } from '../shared/http/responses';
+import { shotgun_password } from '../shared/secrets/secrets';
+import type { AppRequestHandler } from '../types/http';
+import type { ShotgunBody, ToggleStatusBody } from '../dto/event.dto';
+
+export const getSettingStatus: AppRequestHandler = async (req, res) => {
+ const { setting } = req.params;
+
+ if (!setting || !settings_service.isSetting(setting)) {
+ Error(res, { msg: 'Setting événement inconnu.' });
+ return;
+ }
+
+ try {
+ const status = await settings_service.getSettingStatus(setting);
+ if (setting === 'shotgun') {
+ Ok(res, { data: { status, password: status ? shotgun_password : '' } });
+ } else {
+ Ok(res, { data: status });
+ }
+ } catch (error) {
+ Error(res, { msg: 'Erreur lors de la récupération du statut :' + error });
+ }
+};
+
+export const getAvailableSettings: AppRequestHandler = async (req, res) => {
+ try {
+ const userPermission = req.user?.userPermission ?? '';
+ const userRoles = req.user?.userRoles?.map((role) => role.roleName) ?? [];
+ const settings = await settings_service.getAvailableSettings(userPermission, userRoles);
+ Ok(res, { data: settings });
+ } catch (error) {
+ Error(res, { msg: 'Erreur lors de la récupération des settings :' + error });
+ }
+};
+
+export const getAdminSettings: AppRequestHandler = async (_req, res) => {
+ try {
+ const settings = await settings_service.getAllSettings();
+ Ok(res, { data: settings });
+ } catch (error) {
+ Error(res, { msg: 'Erreur lors de la récupération des settings :' + error });
+ }
+};
+
+export const getShotgunAttempts: AppRequestHandler = async (_req, res) => {
+ try {
+ const shotgunAttempts = await settings_service.getAllTeamShotguns();
+ const shotgunAttemptsWithLeaders = await Promise.all(
+ shotgunAttempts.map(async (attempt) => {
+ if (!attempt.teamId) {
+ return { ...attempt, leaderCount: 0 };
+ }
+
+ const teamUsers = await team_service.getTeamUsers(attempt.teamId);
+ const leaderCount = teamUsers.filter((user) => user.permission !== 'Nouveau').length;
+
+ return { ...attempt, leaderCount };
+ }),
+ );
+
+ Ok(res, { data: shotgunAttemptsWithLeaders });
+ } catch (error) {
+ Error(res, { msg: 'Erreur lors de la récupération des tentatives shotgun : ' + error });
+ }
+};
+
+export const shotgunAttempt: AppRequestHandler = async (req, res) => {
+ const { password } = req.body;
+
+ const userId = req.user?.userId;
+
+ if (!userId) {
+ Unauthorized(res, { msg: 'Utilisateur non authentifié.' });
+ return;
+ }
+
+ if (!shotgun_password) {
+ Error(res, { msg: 'Mot de passe shotgun non configuré côté serveur.' });
+ return;
+ }
+
+ if (password !== shotgun_password) {
+ Teapot(res, { msg: 'Le mot de passe shotgun est incorrect.' });
+ return;
+ }
+
+ const status = await settings_service.getSettingsStatus();
+ if (!status?.shotgun_open) {
+ Unauthorized(res, { msg: 'Le shotgun est fermé.' });
+ return;
+ }
+ try {
+ const userTeam = await team_service.getUserTeam(userId);
+
+ if (!userTeam) {
+ Error(res, { msg: "Erreur : Tu n'as pas d'équipe !" });
+ return;
+ }
+
+ const alreadyShotgun = await settings_service.alreadyShotgun(userTeam);
+
+ if (alreadyShotgun) {
+ Conflict(res, { msg: 'Votre équipe est déjà dans le shotgun.' });
+ return;
+ }
+
+ await settings_service.validateShotgun(userTeam);
+ Ok(res, { msg: 'Shotgun validé !' });
+ return;
+ } catch (error) {
+ Error(res, { msg: 'Erreur pendant le shotguns : ' + error });
+ return;
+ }
+};
+
+export const updateSettingStatus: AppRequestHandler = async (req, res) => {
+ const { setting } = req.params;
+ const { open } = req.body;
+
+ if (!setting || !settings_service.isSetting(setting)) {
+ Error(res, { msg: 'Setting événement inconnu.' });
+ return;
+ }
+
+ if (typeof open !== 'boolean') {
+ Error(res, { msg: "Le champ 'open' doit être un booléen." });
+ return;
+ }
+
+ try {
+ const result = await settings_service.updateSettingStatus(setting, open);
+ Ok(res, { msg: 'Paramètres mis à jour.', data: result });
+ } catch (error) {
+ Error(res, { msg: 'Erreur lors de la mise à jour : ' + error });
+ }
+};
diff --git a/backend/src/controllers/team.controller.ts b/backend/src/controllers/team.controller.ts
index 5377d9a..78a6461 100644
--- a/backend/src/controllers/team.controller.ts
+++ b/backend/src/controllers/team.controller.ts
@@ -1,5 +1,5 @@
import { type Event } from '../schemas/Basic/event.schema';
-import * as event_service from '../services/event.service';
+import * as settings_service from '../services/settings.service';
import * as faction_service from '../services/faction.service';
import * as team_service from '../services/team.service';
import { Error, Ok } from '../shared/http/responses';
@@ -14,7 +14,7 @@ export const createNewTeam: AppRequestHandler = async (req, res)
Error(res, { msg: "Il n'y a pas de nom d'équipe" });
return;
}
- const status: Event = await event_service.getEventsStatus();
+ const status: Event = await settings_service.getSettingsStatus();
if (!status?.pre_registration_open) {
Error(res, { msg: "L'enregistrement d'équipe est fermé." });
return;
diff --git a/backend/src/dto/event.dto.ts b/backend/src/dto/event.dto.ts
index d70cf2f..b126d58 100644
--- a/backend/src/dto/event.dto.ts
+++ b/backend/src/dto/event.dto.ts
@@ -3,10 +3,5 @@ export type ShotgunBody = {
};
export type ToggleStatusBody = {
- preRegistrationOpen?: boolean;
- shotgunOpen?: boolean;
- sdiOpen?: boolean;
- weiOpen?: boolean;
- foodOpen?: boolean;
- challOpen?: boolean;
+ open?: boolean;
};
diff --git a/backend/src/routes/event.routes.ts b/backend/src/routes/event.routes.ts
deleted file mode 100644
index 206174d..0000000
--- a/backend/src/routes/event.routes.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import express from 'express';
-import * as eventController from '../controllers/event.controller';
-import { checkRole } from '../middlewares/user.middleware';
-
-const eventRouter = express.Router();
-
-// User routes
-eventRouter.get("/user/shotgunstatus", checkRole("Student", []), eventController.checkShotgunStatus);
-eventRouter.get("/user/preregisterstatus", checkRole("Student", []), eventController.checkPreRegisterStatus);
-eventRouter.get("/user/sdistatus", eventController.checkSDIStatus);
-eventRouter.get("/user/weistatus", eventController.checkWEIStatus);
-eventRouter.get("/user/foodstatus", eventController.checkFoodStatus);
-eventRouter.get("/user/challstatus", eventController.checkChallStatus);
-eventRouter.post("/user/shotgunattempt", checkRole("Student", []), eventController.shotgunAttempt);
-
-// Admin routes
-eventRouter.post("/admin/shotguntoggle", checkRole("Admin", []), eventController.toggleShotgun);
-eventRouter.get("/admin/shotgunattempts", checkRole("Admin", ["Respo CE"]), eventController.getShotgunAttempts);
-eventRouter.post("/admin/preregistrationtoggle", checkRole("Admin", []), eventController.togglePreRegistration);
-eventRouter.post("/admin/sditoggle", checkRole("Admin", []), eventController.toggleSDI);
-eventRouter.post("/admin/weitoggle", checkRole("Admin", []), eventController.toggleWEI);
-eventRouter.post("/admin/foodtoggle", checkRole("Admin", []), eventController.toggleFood);
-eventRouter.post("/admin/challtoggle", checkRole("Admin", []), eventController.toggleChall);
-
-export default eventRouter;
diff --git a/backend/src/routes/settings.routes.ts b/backend/src/routes/settings.routes.ts
new file mode 100644
index 0000000..4e8ddc8
--- /dev/null
+++ b/backend/src/routes/settings.routes.ts
@@ -0,0 +1,17 @@
+import express from 'express';
+import * as settingsController from '../controllers/settings.controller';
+import { checkRole } from '../middlewares/user.middleware';
+
+const settingsRouter = express.Router();
+
+// User routes
+settingsRouter.get('/user/status', settingsController.getAvailableSettings);
+settingsRouter.get('/user/status/:setting', settingsController.getSettingStatus);
+settingsRouter.post('/user/shotgunattempt', checkRole('Student', []), settingsController.shotgunAttempt);
+
+// Admin routes
+settingsRouter.get('/admin/shotgunattempts', checkRole('Admin', ['Respo CE']), settingsController.getShotgunAttempts);
+settingsRouter.get('/admin/settings', checkRole('Admin', []), settingsController.getAdminSettings);
+settingsRouter.patch('/admin/status/:setting', checkRole('Admin', []), settingsController.updateSettingStatus);
+
+export default settingsRouter;
diff --git a/backend/src/schemas/Basic/event.schema.ts b/backend/src/schemas/Basic/event.schema.ts
index 0ca2969..466fd24 100644
--- a/backend/src/schemas/Basic/event.schema.ts
+++ b/backend/src/schemas/Basic/event.schema.ts
@@ -1,13 +1,14 @@
-import { boolean, pgTable, serial } from "drizzle-orm/pg-core";
+import { boolean, pgTable, serial } from 'drizzle-orm/pg-core';
-export const eventSchema = pgTable("events", {
- id: serial("id").primaryKey(),
- pre_registration_open: boolean("pre_registration_open").default(false),
- shotgun_open: boolean("shotgun_open").default(false),
- sdi_open: boolean("sdi_open").default(false),
- wei_open: boolean("wei_open").default(false),
- food_open: boolean("food_open").default(false),
- chall_open: boolean("chall_open").default(false),
+export const eventSchema = pgTable('events', {
+ id: serial('id').primaryKey(),
+ pre_registration_open: boolean('pre_registration_open').default(false),
+ shotgun_open: boolean('shotgun_open').default(false),
+ sdi_open: boolean('sdi_open').default(false),
+ wei_open: boolean('wei_open').default(false),
+ food_open: boolean('food_open').default(false),
+ chall_open: boolean('chall_open').default(false),
+ maker_battle_group_open: boolean('chall_open').default(false),
});
export type Event = typeof eventSchema.$inferSelect;
diff --git a/backend/src/services/event.service.ts b/backend/src/services/event.service.ts
deleted file mode 100644
index 1457dec..0000000
--- a/backend/src/services/event.service.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import { asc, eq } from "drizzle-orm";
-import { db } from "../database/db";
-import { eventSchema } from "../schemas/Basic/event.schema";
-import { teamSchema } from "../schemas/Basic/team.schema";
-import { teamShotgunSchema } from "../schemas/Relational/teamshotgun.schema";
-
-export const getEventsStatus = async () => {
- const events = await db.select().from(eventSchema);
- if (events.length > 0) {
- return events[0]; // Renvoie le premier événement s'il existe
- } else {
- return null; // ou une valeur par défaut
- }
-};
-
-export const validateShotgun = async (teamId: number) => {
- await db.transaction(async (tx) => {
- await tx.insert(teamShotgunSchema).values({ team_id: teamId });
- })
-};
-
-export const alreadyShotgun = async (teamId: number) => {
- const shotgunTeam = await db.select({ shotgunId: teamShotgunSchema.id })
- .from(teamShotgunSchema)
- .where(eq(teamShotgunSchema.team_id, teamId));
-
- if (shotgunTeam[0]) {
- return true
- }
- else {
- return false
- }
-};
-
-export const updatepreRegistrationStatus = async (preRegistrationOpen: boolean) => {
- return await db.update(eventSchema)
- .set({ pre_registration_open: preRegistrationOpen })
- .returning();
-};
-
-export const updateShotgunStatus = async (shotgunOpen: boolean) => {
- return await db.update(eventSchema)
- .set({ shotgun_open: shotgunOpen })
- .returning();
-};
-
-export const getAllTeamShotguns = async () => {
- return await db
- .select({
- id: teamShotgunSchema.id,
- teamId: teamShotgunSchema.team_id,
- timestamp: teamShotgunSchema.timestamp,
- teamName: teamSchema.name,
- teamType: teamSchema.type,
- })
- .from(teamShotgunSchema)
- .leftJoin(teamSchema, eq(teamShotgunSchema.team_id, teamSchema.id))
- .orderBy(asc(teamShotgunSchema.timestamp), asc(teamShotgunSchema.id));
-};
-
-export const updateSDIStatus = async (sdiOpen: boolean) => {
- return await db.update(eventSchema)
- .set({ sdi_open: sdiOpen })
- .returning();
-};
-
-export const updateWEIStatus = async (weiOpen: boolean) => {
- return await db.update(eventSchema)
- .set({ wei_open: weiOpen })
- .returning();
-};
-
-export const updateFoodStatus = async (foodOpen: boolean) => {
- return await db.update(eventSchema)
- .set({ food_open: foodOpen })
- .returning();
-};
-
-export const updateChallStatus = async (challOpen: boolean) => {
- return await db.update(eventSchema)
- .set({ chall_open: challOpen })
- .returning();
-};
diff --git a/backend/src/services/settings.service.ts b/backend/src/services/settings.service.ts
new file mode 100644
index 0000000..43055a0
--- /dev/null
+++ b/backend/src/services/settings.service.ts
@@ -0,0 +1,116 @@
+import { asc, eq } from 'drizzle-orm';
+import { db } from '../database/db';
+import { eventSchema } from '../schemas/Basic/event.schema';
+import { teamSchema } from '../schemas/Basic/team.schema';
+import { teamShotgunSchema } from '../schemas/Relational/teamshotgun.schema';
+
+export const settingColumns = {
+ preRegistration: 'pre_registration_open',
+ shotgun: 'shotgun_open',
+ sdi: 'sdi_open',
+ wei: 'wei_open',
+ food: 'food_open',
+ challenge: 'chall_open',
+ makerBattleGroup: 'maker_battle_group_open',
+} as const;
+
+export type Setting = keyof typeof settingColumns;
+
+type SettingDefinition = {
+ key: Setting;
+ label: string;
+ column: (typeof settingColumns)[Setting];
+ roles: string[];
+};
+
+export const settingDefinitions: SettingDefinition[] = [
+ { key: 'preRegistration', label: 'Pré-inscription', column: 'pre_registration_open', roles: [] },
+ { key: 'shotgun', label: 'Shotgun', column: 'shotgun_open', roles: [] },
+ { key: 'sdi', label: 'SDI (Billetterie)', column: 'sdi_open', roles: [] },
+ { key: 'wei', label: 'WEI (Billetterie + Tentes)', column: 'wei_open', roles: [] },
+ { key: 'food', label: 'Nourriture (Billetterie)', column: 'food_open', roles: [] },
+ { key: 'challenge', label: 'Challenges (Affichage des challenges)', column: 'chall_open', roles: [] },
+ {
+ key: 'makerBattleGroup',
+ label: 'Groupes de défis TC & Branche (Affichage des groupes)',
+ column: 'maker_battle_group_open',
+ roles: [],
+ },
+];
+
+export const isSetting = (setting: string): setting is Setting => setting in settingColumns;
+
+export const getSettingsStatus = async () => {
+ const events = await db.select().from(eventSchema);
+ if (events.length > 0) {
+ return events[0]; // Renvoie le premier événement s'il existe
+ } else {
+ return null; // ou une valeur par défaut
+ }
+};
+
+export const getSettingStatus = async (setting: Setting) => {
+ const settings = await getSettingsStatus();
+ return settings ? Boolean(settings[settingColumns[setting] as keyof typeof settings]) : false;
+};
+
+const canAccessSetting = (definition: SettingDefinition, userPermission: string, userRoles: string[]) =>
+ userPermission === 'Admin' ||
+ definition.roles.length === 0 ||
+ definition.roles.includes(userPermission) ||
+ definition.roles.some((role) => userRoles.includes(role));
+
+export const getAvailableSettings = async (userPermission: string, userRoles: string[]) => {
+ const settings = await getSettingsStatus();
+
+ return settingDefinitions
+ .filter((definition) => canAccessSetting(definition, userPermission, userRoles))
+ .map(({ key, label, roles, column }) => ({
+ key,
+ label,
+ roles,
+ open: settings ? Boolean(settings[column as keyof typeof settings]) : false,
+ }));
+};
+
+export const getAllSettings = async () => getAvailableSettings('Admin', []);
+
+export const validateShotgun = async (teamId: number) => {
+ await db.transaction(async (tx) => {
+ await tx.insert(teamShotgunSchema).values({ team_id: teamId });
+ });
+};
+
+export const alreadyShotgun = async (teamId: number) => {
+ const shotgunTeam = await db
+ .select({ shotgunId: teamShotgunSchema.id })
+ .from(teamShotgunSchema)
+ .where(eq(teamShotgunSchema.team_id, teamId));
+
+ if (shotgunTeam[0]) {
+ return true;
+ } else {
+ return false;
+ }
+};
+
+export const updateSettingStatus = async (setting: Setting, open: boolean) => {
+ return await db
+ .update(eventSchema)
+ .set({ [settingColumns[setting]]: open })
+ .returning();
+};
+
+export const getAllTeamShotguns = async () => {
+ return await db
+ .select({
+ id: teamShotgunSchema.id,
+ teamId: teamShotgunSchema.team_id,
+ timestamp: teamShotgunSchema.timestamp,
+ teamName: teamSchema.name,
+ teamType: teamSchema.type,
+ })
+ .from(teamShotgunSchema)
+ .leftJoin(teamSchema, eq(teamShotgunSchema.team_id, teamSchema.id))
+ .orderBy(asc(teamShotgunSchema.timestamp), asc(teamShotgunSchema.id));
+};
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 46b0562..5b14d8b 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -12,7 +12,7 @@ const AdminPageBanned = lazy(() => import('./pages/admin/adminBanned'));
const AdminPageBus = lazy(() => import('./pages/admin/adminBus'));
const AdminPageChallenges = lazy(() => import('./pages/admin/adminChallenges'));
const AdminPageEmail = lazy(() => import('./pages/admin/adminEmail'));
-const AdminPageEvents = lazy(() => import('./pages/admin/adminEvents'));
+const AdminPageSettings = lazy(() => import('./pages/admin/adminSettings'));
const AdminPageExport = lazy(() => import('./pages/admin/adminExport'));
const AdminPageFaction = lazy(() => import('./pages/admin/adminFaction'));
const AdminPageGames = lazy(() => import('./pages/admin/adminGames'));
@@ -264,10 +264,10 @@ const App: React.FC = () => {
}
/>
-
+
}
/>
diff --git a/frontend/src/components/Admin/adminEvent.tsx b/frontend/src/components/Admin/adminSettings.tsx
similarity index 57%
rename from frontend/src/components/Admin/adminEvent.tsx
rename to frontend/src/components/Admin/adminSettings.tsx
index 2e85f79..126ca88 100644
--- a/frontend/src/components/Admin/adminEvent.tsx
+++ b/frontend/src/components/Admin/adminSettings.tsx
@@ -2,57 +2,22 @@ import { CheckCircle, Loader2, XCircle } from 'lucide-react';
import { useEffect, useState } from 'react';
import Swal from 'sweetalert2';
-import {
- checkChallengeStatus,
- checkFoodStatus,
- checkPreRegisterStatus,
- checkSDIStatus,
- checkShotgunStatus,
- checkWEIStatus,
- toggleChallenge,
- toggleFood,
- togglePreRegistration,
- toggleSDI,
- toggleShotgun,
- toggleWEI,
-} from '../../services/requests/event.service';
+import type { Setting } from '../../interfaces/settings.interface';
+import { getAdminSettings, updateSetting } from '../../services/requests/settings.service';
import { Button } from '../ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '../ui/card';
-export const AdminEvents = () => {
+export const AdminSettings = () => {
const [loading, setLoading] = useState(false);
const [loadingStatuses, setLoadingStatuses] = useState(true);
- const [statuses, setStatuses] = useState({
- preRegistration: false,
- shotgun: false,
- sdi: false,
- wei: false,
- food: false,
- chall: false,
- });
+ const [settings, setSettings] = useState([]);
// Charger les statuts au montage
useEffect(() => {
const fetchStatuses = async () => {
try {
- const [preReg, shot, sdi, wei, food, chall] = await Promise.all([
- checkPreRegisterStatus(),
- checkShotgunStatus(),
- checkSDIStatus(),
- checkWEIStatus(),
- checkFoodStatus(),
- checkChallengeStatus(),
- ]);
-
- setStatuses({
- preRegistration: preReg,
- shotgun: shot.status,
- sdi,
- wei,
- food,
- chall,
- });
+ setSettings(await getAdminSettings());
} catch {
Swal.fire({
icon: 'error',
@@ -67,19 +32,18 @@ export const AdminEvents = () => {
}, []);
// Fonction générique pour toggle un événement
- const handleToggle = async (
- key: keyof typeof statuses,
- toggleFn: (value: boolean) => Promise,
- successMsg: string,
- ) => {
+ const handleToggle = async (setting: Setting) => {
setLoading(true);
try {
- await toggleFn(!statuses[key]);
- setStatuses((prev) => ({ ...prev, [key]: !prev[key] }));
+ const open = !setting.open;
+ await updateSetting(setting.key, open);
+ setSettings((previous) =>
+ previous.map((current) => (current.key === setting.key ? { ...current, open } : current)),
+ );
Swal.fire({
icon: 'success',
title: 'Succès',
- text: successMsg,
+ text: `${setting.label} mis à jour !`,
timer: 1500,
showConfirmButton: false,
});
@@ -94,40 +58,6 @@ export const AdminEvents = () => {
}
};
- // Configuration des événements
- const events = [
- {
- key: 'preRegistration' as const,
- label: 'Pré-inscription',
- toggleFn: togglePreRegistration,
- },
- {
- key: 'shotgun' as const,
- label: 'Shotgun',
- toggleFn: toggleShotgun,
- },
- {
- key: 'sdi' as const,
- label: 'SDI (Billetterie)',
- toggleFn: toggleSDI,
- },
- {
- key: 'wei' as const,
- label: 'WEI (Billetterie + Tentes)',
- toggleFn: toggleWEI,
- },
- {
- key: 'food' as const,
- label: 'Nourriture (Billetterie)',
- toggleFn: toggleFood,
- },
- {
- key: 'chall' as const,
- label: 'Challenges (Affichage des challenges)',
- toggleFn: toggleChallenge,
- },
- ];
-
if (loadingStatuses) {
return (
@@ -141,15 +71,15 @@ export const AdminEvents = () => {
- ⚙️ Gestion des Événements
+ ⚙️ Gestion des settings
- {events.map(({ key, label, toggleFn }) => {
- const isActive = statuses[key];
+ {settings.map((setting) => {
+ const isActive = setting.open;
return (
{isActive ? (
@@ -157,11 +87,11 @@ export const AdminEvents = () => {
) : (
)}
- {label}
+ {setting.label}
handleToggle(key, toggleFn, `${label} mis à jour !`)}
+ onClick={() => handleToggle(setting)}
disabled={loading}
className={`transition-colors duration-300 ${
isActive
diff --git a/frontend/src/components/Admin/adminShotgun.tsx b/frontend/src/components/Admin/adminShotgun.tsx
index f2a9f29..218c65d 100644
--- a/frontend/src/components/Admin/adminShotgun.tsx
+++ b/frontend/src/components/Admin/adminShotgun.tsx
@@ -1,8 +1,8 @@
import { useEffect, useMemo, useState } from 'react';
import { Link } from 'react-router-dom';
-import { type ShotgunAttemptRow } from '../../interfaces/event.interface';
-import { getShotgunAttemptsAdmin } from '../../services/requests/event.service';
+import { type ShotgunAttemptRow } from '../../interfaces/settings.interface';
+import { getShotgunAttemptsAdmin } from '../../services/requests/settings.service';
import { Button } from '../ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '../ui/card';
diff --git a/frontend/src/components/WEI_SDI_Food/foodSection.tsx b/frontend/src/components/WEI_SDI_Food/foodSection.tsx
index ccd4fb0..f8aa861 100644
--- a/frontend/src/components/WEI_SDI_Food/foodSection.tsx
+++ b/frontend/src/components/WEI_SDI_Food/foodSection.tsx
@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react';
-import { checkFoodStatus } from '../../services/requests/event.service';
+import { checkFoodStatus } from '../../services/requests/settings.service';
// import { getPermission } from '../../services/requests/user.service';
import { checkUploadAvailability } from '../../utils/utils';
import { Card, CardContent, CardHeader, CardTitle } from '../ui/card';
diff --git a/frontend/src/components/WEI_SDI_Food/sdiSection.tsx b/frontend/src/components/WEI_SDI_Food/sdiSection.tsx
index 572359d..59e1e5c 100644
--- a/frontend/src/components/WEI_SDI_Food/sdiSection.tsx
+++ b/frontend/src/components/WEI_SDI_Food/sdiSection.tsx
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
import { useOnboarding } from '../../contexts/onboarding';
import { decodeToken, getToken } from '../../services/requests/auth.service';
-import { checkSDIStatus } from '../../services/requests/event.service';
+import { checkSDIStatus } from '../../services/requests/settings.service';
import { Card, CardContent, CardHeader, CardTitle } from '../ui/card';
export const SdiSection = () => {
diff --git a/frontend/src/components/WEI_SDI_Food/weiSection.tsx b/frontend/src/components/WEI_SDI_Food/weiSection.tsx
index c728b01..ca2e0c9 100644
--- a/frontend/src/components/WEI_SDI_Food/weiSection.tsx
+++ b/frontend/src/components/WEI_SDI_Food/weiSection.tsx
@@ -3,7 +3,7 @@ import { useEffect, useState } from 'react';
import { useOnboarding } from '../../contexts/onboarding';
import { useUser } from '../../contexts/user';
import { decodeToken, getToken } from '../../services/requests/auth.service';
-import { checkWEIStatus } from '../../services/requests/event.service';
+import { checkWEIStatus } from '../../services/requests/settings.service';
import { Card, CardContent, CardHeader, CardTitle } from '../ui/card';
export const WeiSection = () => {
diff --git a/frontend/src/components/challenge/challengeList.tsx b/frontend/src/components/challenge/challengeList.tsx
index 9deba70..1f141f5 100644
--- a/frontend/src/components/challenge/challengeList.tsx
+++ b/frontend/src/components/challenge/challengeList.tsx
@@ -4,8 +4,8 @@ import Swal from 'sweetalert2';
import { type Challenge } from '../../interfaces/challenge.interface';
import { type Faction } from '../../interfaces/faction.interface';
import { getAllChallenges, getFactionsPoints } from '../../services/requests/challenge.service';
-import { checkChallengeStatus } from '../../services/requests/event.service';
import { getAllFactionsUser } from '../../services/requests/faction.service';
+import { checkChallengeStatus } from '../../services/requests/settings.service';
import { Card, CardContent, CardHeader, CardTitle } from '../ui/card';
export const UserChallengeList = () => {
diff --git a/frontend/src/components/navbar.tsx b/frontend/src/components/navbar.tsx
index 79bd146..6c56745 100644
--- a/frontend/src/components/navbar.tsx
+++ b/frontend/src/components/navbar.tsx
@@ -92,13 +92,13 @@ export const Navbar = () => {
{ label: 'Bus', to: '/admin/bus', rolesAllowed: ['Admin'] },
{ label: 'Challenge', to: '/admin/challenge', rolesAllowed: ['Admin', 'Arbitre'] },
{ label: 'Email', to: '/admin/email', rolesAllowed: ['Admin'] },
- { label: 'Events', to: '/admin/events', rolesAllowed: ['Admin'] },
{ label: 'Export / Import', to: '/admin/export-import', rolesAllowed: ['Admin'] },
{ label: 'Factions', to: '/admin/factions', rolesAllowed: ['Admin', 'Respo CE'] },
{ label: 'Games', to: '/admin/games', rolesAllowed: ['Admin'] },
{ label: 'News', to: '/admin/news', rolesAllowed: ['Admin', 'Communication'] },
{ label: 'Permanences', to: '/admin/permanences', rolesAllowed: ['Admin', 'Respo CE'] },
{ label: 'Roles', to: '/admin/roles', rolesAllowed: ['Admin'] },
+ { label: 'Settings', to: '/admin/settings', rolesAllowed: ['Admin'] },
{ label: 'Shotgun', to: '/admin/shotgun', rolesAllowed: ['Admin', 'Respo CE'] },
{ label: 'Teams', to: '/admin/teams', rolesAllowed: ['Admin', 'Respo CE'] },
{ label: 'Tentes', to: '/admin/tent', rolesAllowed: ['Admin'] },
diff --git a/frontend/src/components/shotgun/preregisterCESection.tsx b/frontend/src/components/shotgun/preregisterCESection.tsx
index 8a8e907..3c03751 100644
--- a/frontend/src/components/shotgun/preregisterCESection.tsx
+++ b/frontend/src/components/shotgun/preregisterCESection.tsx
@@ -1,7 +1,7 @@
-import { useEffect, useState } from "react";
+import { useEffect, useState } from 'react';
-import { checkPreRegisterStatus } from "../../services/requests/event.service";
-import { Card, CardContent, CardHeader, CardTitle } from "../ui/card";
+import { checkPreRegisterStatus } from '../../services/requests/settings.service';
+import { Card, CardContent, CardHeader, CardTitle } from '../ui/card';
export const PreregisterCESection = () => {
const [isPreRegistrationOpen, setIsPreRegistrationOpen] = useState(false);
@@ -12,7 +12,7 @@ export const PreregisterCESection = () => {
const status = await checkPreRegisterStatus();
setIsPreRegistrationOpen(status);
} catch {
- alert("Erreur lors de la récupération du statut de pré-inscription.");
+ alert('Erreur lors de la récupération du statut de pré-inscription.');
}
};
fetchStatus();
@@ -35,8 +35,7 @@ export const PreregisterCESection = () => {
src="https://forms.gle/32yHKGSTzfFvp7NP9"
className="absolute inset-0 w-full h-full border-none"
title="Formulaire de pré-inscription CE"
- loading="lazy"
- >
+ loading="lazy">
Chargement…
diff --git a/frontend/src/components/shotgun/preregisterTeamSection.tsx b/frontend/src/components/shotgun/preregisterTeamSection.tsx
index 6e3fa46..cd8eae0 100644
--- a/frontend/src/components/shotgun/preregisterTeamSection.tsx
+++ b/frontend/src/components/shotgun/preregisterTeamSection.tsx
@@ -1,15 +1,15 @@
-import { useEffect, useState } from "react";
-import Select from "react-select";
+import { useEffect, useState } from 'react';
+import Select from 'react-select';
-import { checkPreRegisterStatus } from "../../services/requests/event.service";
-import { createTeam } from "../../services/requests/team.service";
-import { getUsers } from "../../services/requests/user.service";
-import { Button } from "../ui/button";
-import { Card, CardContent, CardHeader, CardTitle } from "../ui/card";
-import { Input } from "../ui/input";
+import { checkPreRegisterStatus } from '../../services/requests/settings.service';
+import { createTeam } from '../../services/requests/team.service';
+import { getUsers } from '../../services/requests/user.service';
+import { Button } from '../ui/button';
+import { Card, CardContent, CardHeader, CardTitle } from '../ui/card';
+import { Input } from '../ui/input';
export const PreregisterTeamSection = () => {
- const [teamName, setTeamName] = useState("");
+ const [teamName, setTeamName] = useState('');
const [members, setMembers] = useState([]);
const [isPreRegistrationOpen, setIsPreRegistrationOpen] = useState(false);
const [users, setUsers] = useState<{ userId: number; firstName: string; lastName: string }[]>([]);
@@ -20,7 +20,7 @@ export const PreregisterTeamSection = () => {
const status = await checkPreRegisterStatus();
setIsPreRegistrationOpen(status);
} catch {
- alert("Erreur lors de la récupération du statut de pré-inscription.");
+ alert('Erreur lors de la récupération du statut de pré-inscription.');
}
};
fetchStatus();
@@ -32,7 +32,7 @@ export const PreregisterTeamSection = () => {
const userList = await getUsers();
setUsers(userList);
} catch {
- alert("Erreur lors de la récupération des utilisateurs.");
+ alert('Erreur lors de la récupération des utilisateurs.');
}
};
fetchUsers();
@@ -72,20 +72,23 @@ export const PreregisterTeamSection = () => {
{isPreRegistrationOpen ? (
<>
- Etape 1: le GForm de motivation !
+
+ Etape 1: le GForm de motivation !
+
- Etape 2: Sélection des membres
+
+ Etape 2: Sélection des membres
+
@@ -141,15 +144,15 @@ export const PreregisterTeamSection = () => {
- Si tu ne trouves pas un coéquipier, c'est qu'il ne s'est jamais connecté sur ce site !
+ Si tu ne trouves pas un coéquipier, c'est qu'il ne s'est jamais connecté sur ce
+ site !
Il lui suffit de se connecter une fois pour apparaitre dans cette liste.
+ className="w-full py-3 text-lg bg-blue-600 text-white rounded-xl shadow-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 transition duration-300">
Enregistrer l'équipe
@@ -162,6 +165,6 @@ export const PreregisterTeamSection = () => {
)}
-
+
);
};
diff --git a/frontend/src/components/shotgun/shotgunSection.tsx b/frontend/src/components/shotgun/shotgunSection.tsx
index ba41295..8c62380 100644
--- a/frontend/src/components/shotgun/shotgunSection.tsx
+++ b/frontend/src/components/shotgun/shotgunSection.tsx
@@ -1,17 +1,17 @@
-import { type AxiosError } from "axios";
-import { useEffect, useState } from "react";
+import { type AxiosError } from 'axios';
+import { useEffect, useState } from 'react';
-import { type ApiErrorResponse } from "../../interfaces/event.interface";
-import { attemptShotgun, checkShotgunStatus } from "../../services/requests/event.service";
-import { Button } from "../ui/button";
-import { Card, CardContent, CardHeader, CardTitle } from "../ui/card";
-import { Input } from "../ui/input";
+import { type ApiErrorResponse } from '../../interfaces/settings.interface';
+import { attemptShotgun, checkShotgunStatus } from '../../services/requests/settings.service';
+import { Button } from '../ui/button';
+import { Card, CardContent, CardHeader, CardTitle } from '../ui/card';
+import { Input } from '../ui/input';
export const Shotgun = () => {
const [status, setStatus] = useState(false);
- const [message, setMessage] = useState("");
- const [inputValue, setInputValue] = useState("");
- const [shotgunPassword, setShotgunPassword] = useState("");
+ const [message, setMessage] = useState('');
+ const [inputValue, setInputValue] = useState('');
+ const [shotgunPassword, setShotgunPassword] = useState('');
useEffect(() => {
const fetchStatus = async () => {
@@ -26,12 +26,12 @@ export const Shotgun = () => {
e.preventDefault();
if (!shotgunPassword) {
- setMessage("❌ Erreur : mot de passe shotgun indisponible.");
+ setMessage('❌ Erreur : mot de passe shotgun indisponible.');
return;
}
if (inputValue !== shotgunPassword) {
- setMessage("❌ Erreur : Mot de passe de Shotgun incorrect.");
+ setMessage('❌ Erreur : Mot de passe de Shotgun incorrect.');
return;
}
@@ -40,16 +40,14 @@ export const Shotgun = () => {
setMessage(response.message);
} catch (error) {
const axiosError = error as AxiosError;
- setMessage(axiosError.response?.data?.message || "Une erreur est survenue.");
+ setMessage(axiosError.response?.data?.message || 'Une erreur est survenue.');
}
};
return (
-
- Shotgun 🎯
-
+ Shotgun 🎯
Tape exactement la bonne phrase pour valider ton shotgun (majuscules incluses).
@@ -57,9 +55,10 @@ export const Shotgun = () => {
- Mot à entrer :{" "}
-
- {shotgunPassword || "patience..."}
+ Mot à entrer :{' '}
+
+ {shotgunPassword || 'patience...'}
{!status && (
@@ -80,17 +79,18 @@ export const Shotgun = () => {
/>
+ className="w-full py-3 text-lg bg-purple-600 text-white rounded-xl shadow-md hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-purple-500 transition duration-300">
Shotgun !
{message && (
+ className={`text-center text-lg mt-4 ${
+ message.includes('Erreur') ||
+ message.toLowerCase().includes('déjà') ||
+ message.toLowerCase().includes('incorrect')
+ ? 'text-red-500'
+ : 'text-green-600'
+ }`}>
{message}
)}
diff --git a/frontend/src/components/tent/tentSection.tsx b/frontend/src/components/tent/tentSection.tsx
index a641ab9..cd6ca7a 100644
--- a/frontend/src/components/tent/tentSection.tsx
+++ b/frontend/src/components/tent/tentSection.tsx
@@ -6,7 +6,7 @@ import { useOnboarding } from '../../contexts/onboarding';
import { type Tent } from '../../interfaces/tent.interface';
import { type User } from '../../interfaces/user.interface';
import { decodeToken, getToken } from '../../services/requests/auth.service';
-import { checkWEIStatus } from '../../services/requests/event.service';
+import { checkWEIStatus } from '../../services/requests/settings.service';
import { cancelTent, createTent, getUserTent } from '../../services/requests/tent.service';
import { getUsers } from '../../services/requests/user.service';
import { Button } from '../ui/button';
diff --git a/frontend/src/interfaces/event.interface.ts b/frontend/src/interfaces/settings.interface.ts
similarity index 84%
rename from frontend/src/interfaces/event.interface.ts
rename to frontend/src/interfaces/settings.interface.ts
index 5954848..983c50f 100644
--- a/frontend/src/interfaces/event.interface.ts
+++ b/frontend/src/interfaces/settings.interface.ts
@@ -3,6 +3,12 @@ export interface ShotgunStatusData {
password: string;
}
+export interface Setting {
+ key: string;
+ label: string;
+ open: boolean;
+}
+
export interface ShotgunAttemptPayload {
password: string;
}
diff --git a/frontend/src/pages/admin/adminEvents.tsx b/frontend/src/pages/admin/adminSettings.tsx
similarity index 63%
rename from frontend/src/pages/admin/adminEvents.tsx
rename to frontend/src/pages/admin/adminSettings.tsx
index 27b200f..b53e27c 100644
--- a/frontend/src/pages/admin/adminEvents.tsx
+++ b/frontend/src/pages/admin/adminSettings.tsx
@@ -1,15 +1,15 @@
-import { AdminEvents } from '../../components/Admin/adminEvent';
import { AdminLayout } from '../../components/Admin/adminLayout';
+import { AdminSettings } from '../../components/Admin/adminSettings';
import { RevealSection } from '../../components/ui/revealSection';
-const AdminPageEvents: React.FC = () => (
+const AdminPageSettings: React.FC = () => (
);
-export default AdminPageEvents;
+export default AdminPageSettings;
diff --git a/frontend/src/services/requests/event.service.ts b/frontend/src/services/requests/event.service.ts
deleted file mode 100644
index bc46a59..0000000
--- a/frontend/src/services/requests/event.service.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import { type ApiMessageResponse, type ShotgunAttemptPayload, type ShotgunAttemptRow, type ShotgunStatusData } from '../../interfaces/event.interface';
-import api from '../api';
-
-export const checkShotgunStatus = async (): Promise
=> {
- const response = await api.get<{ data: ShotgunStatusData }>("/event/user/shotgunstatus");
- return response.data.data;
-};
-
-export const checkPreRegisterStatus = async () => {
- const response = await api.get("/event/user/preregisterstatus");
- return response.data.data;
-};
-
-export const checkSDIStatus = async () => {
- const response = await api.get("/event/user/sdistatus");
- return response.data.data;
-};
-
-export const checkWEIStatus = async () => {
- const response = await api.get("/event/user/weistatus");
- return response.data.data;
-};
-
-export const checkFoodStatus = async () => {
- const response = await api.get("/event/user/foodstatus");
- return response.data.data;
-};
-
-export const checkChallengeStatus = async () => {
- const response = await api.get("/event/user/challstatus");
- return response.data.data;
-};
-
-export const attemptShotgun = async (payload: ShotgunAttemptPayload): Promise => {
- const response = await api.post("event/user/shotgunattempt", payload);
- return response.data;
-};
-
-export const getShotgunAttemptsAdmin = async (): Promise => {
- const response = await api.get<{ data: ShotgunAttemptRow[] }>("/event/admin/shotgunattempts");
- return response.data.data;
-};
-
-export const toggleShotgun = async (shotgunOpen: boolean) => {
- const response = await api.post(`event/admin/shotguntoggle`, { shotgunOpen });
- return response.data;
-};
-
-export const togglePreRegistration = async (preRegistrationOpen: boolean) => {
- const response = await api.post(`event/admin/preregistrationtoggle`, { preRegistrationOpen });
- return response.data;
-};
-
-export const toggleSDI = async (sdiOpen: boolean) => {
- const response = await api.post(`event/admin/sditoggle`, { sdiOpen });
- return response.data;
-};
-
-export const toggleWEI = async (weiOpen: boolean) => {
- const response = await api.post(`event/admin/weitoggle`, { weiOpen });
- return response.data;
-};
-
-export const toggleFood = async (foodOpen: boolean) => {
- const response = await api.post(`event/admin/foodtoggle`, { foodOpen });
- return response.data;
-};
-
-export const toggleChallenge = async (challOpen: boolean) => {
- const response = await api.post(`event/admin/challtoggle`, { challOpen });
- return response.data;
-};
diff --git a/frontend/src/services/requests/settings.service.ts b/frontend/src/services/requests/settings.service.ts
new file mode 100644
index 0000000..dea7186
--- /dev/null
+++ b/frontend/src/services/requests/settings.service.ts
@@ -0,0 +1,55 @@
+import {
+ type ApiMessageResponse,
+ type Setting,
+ type ShotgunAttemptPayload,
+ type ShotgunAttemptRow,
+ type ShotgunStatusData,
+} from '../../interfaces/settings.interface';
+import api from '../api';
+
+export const checkShotgunStatus = async (): Promise => {
+ const response = await api.get<{ data: ShotgunStatusData }>('/settings/user/status/shotgun');
+ return response.data.data;
+};
+
+const getSetting = async (key: string): Promise => {
+ const response = await api.get<{ data: Array }>('/settings/user/status');
+ const setting = response.data.data.find((item) => item.key === key);
+ if (!setting) throw new Error(`Le setting ${key} n'est pas disponible.`);
+ return setting;
+};
+
+export const getSettings = async (): Promise => {
+ const response = await api.get<{ data: Setting[] }>('/settings/user/status');
+ return response.data.data;
+};
+
+export const getAdminSettings = async (): Promise => {
+ const response = await api.get<{ data: Setting[] }>('/settings/admin/settings');
+ return response.data.data;
+};
+
+export const updateSetting = async (key: string, open: boolean) => {
+ const response = await api.patch(`/settings/admin/status/${key}`, { open });
+ return response.data;
+};
+
+export const checkPreRegisterStatus = async () => (await getSetting('preRegistration')).open;
+
+export const checkSDIStatus = async () => (await getSetting('sdi')).open;
+
+export const checkWEIStatus = async () => (await getSetting('wei')).open;
+
+export const checkFoodStatus = async () => (await getSetting('food')).open;
+
+export const checkChallengeStatus = async () => (await getSetting('challenge')).open;
+
+export const attemptShotgun = async (payload: ShotgunAttemptPayload): Promise => {
+ const response = await api.post('settings/user/shotgunattempt', payload);
+ return response.data;
+};
+
+export const getShotgunAttemptsAdmin = async (): Promise => {
+ const response = await api.get<{ data: ShotgunAttemptRow[] }>('/settings/admin/shotgunattempts');
+ return response.data.data;
+};