cda-hackathon-quiz-app-frontend
Application frontend de quiz thématique (Front-end, Back-end, DevOps) avec parcours joueur complet (sélection, réponses, score, historique), développée en React/Redux Toolkit avec routing protégé et persistance locale. Le projet s'appuie sur une consommation d'API REST et une gestion d'état centralisée pour maintenir la cohérence de session.
🎯 Contexte et objectifs
- Concevoir une interface web de jeu orientée session utilisateur, avec un enchaînement d’écrans guidé et des états métier persistés.
- Synchroniser les interactions frontend avec une API backend (questions, classements, historique).
- Industrialiser la livraison front avec une pipeline CI/CD GitLab basée sur build Vite et déploiement automatisé.
🛠️ Réalisations
🧩 Conception
- L’architecture de build repose sur Vite et une stack frontend React/Redux dédiée à un mode SPA, avec outillage orienté état global et appels HTTP. Source: cda-hackathon-quiz-app-frontend/Hackathon-Quiz-App/package.json
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@reduxjs/toolkit": "^1.7.0",
"axios": "^0.24.0",
"react": "^17.0.2",
"react-redux": "^7.2.6",
"react-router-dom": "^6.1.1",
"redux": "^4.1.2",
"redux-logger": "^3.0.6"
},
"devDependencies": {
"@vitejs/plugin-react": "^1.0.7",
"vite": "^2.7.2"
}
}
- Le store centralise les slices
authetgameviaconfigureStore, ce qui formalise la séparation auth/session et logique de quiz. Source: cda-hackathon-quiz-app-frontend/Hackathon-Quiz-App/src/js/store/store.js
import { configureStore } from "@reduxjs/toolkit";
import logger from "redux-logger";
import auth from "../features/auth/authSlice";
import game from "../features/game/gameSlice"
const reducer = {
auth:auth,
game:game,
}
export const store = configureStore({
reducer,
});
💻 Développement
- Backend :
Le frontend consomme des endpoints métiers dédiés (
/questions,/rankings,/history) via une instance Axios configurable par environnement. Source: cda-hackathon-quiz-app-frontend/Hackathon-Quiz-App/src/js/utils/api.js
import axios from 'axios'
import { API_BASE_URL } from './constants'
const instance = axios.create({
baseURL: API_BASE_URL
})
export default instance
- Frontend :
Le routage React Router v6 impose des accès protégés via
RequireAuthpour les pages de jeu, score et historique. Source: cda-hackathon-quiz-app-frontend/Hackathon-Quiz-App/src/js/App.jsx
<Routes>
<Route path="/home" element={<HomePage />} />
<Route path="/" element={<Navigate replace to="/home" />} />
<Route path="/games/nickname" element={<ChooseNickname />}></Route>
<Route
path="/games/choose-category"
element={<RequireAuth><ChooseCategoryQuestion /></RequireAuth>}
></Route>
<Route path="/games/choose-mode" element={<RequireAuth><ChooseModeQuestion /></RequireAuth>}></Route>
<Route path="/games/questions" element={<RequireAuth><ChooseResponsePage /></RequireAuth>}></Route>
<Route path="/score" element={<RequireAuth><ScorePage /></RequireAuth>}></Route>
<Route path="/history" element={<RequireAuth><HistoricPage /></RequireAuth>}></Route>
<Route path="/historyDetails" element={<RequireAuth><HistoricDetailsPage /></RequireAuth>}></Route>
</Routes>
La garde d’authentification restaure une session depuis localStorage et redirige vers /home si le pseudo n’est pas disponible.
Source: cda-hackathon-quiz-app-frontend/Hackathon-Quiz-App/src/js/features/auth/requireAuth.jsx
export const RequireAuth = ({ children }) => {
let location = useLocation();
const dispatch = useDispatch()
const currentPlayer = getLocalStorageItem("nickname");
useEffect(() => {
const currentPlayer = getLocalStorageItem("nickname");
if (typeof(currentPlayer) === "string") {
dispatch(login(currentPlayer));
}
}, []);
if (typeof(currentPlayer) !== "string") {
return <Navigate to="/home" state={{ from: location }} />;
}
return children;
};
La logique de jeu implémente le chargement des questions par catégorie, puis stocke l’état de partie (questionsFetched, gameInfo) pour piloter les écrans suivants.
Source: cda-hackathon-quiz-app-frontend/Hackathon-Quiz-App/src/js/components/CategoryQuestion.jsx
async function fetchQuestions() {
let body = "";
if (category !== "" && getLocalStorageItem("currentCategory") !== category) {
body = category;
} else if (
category === "" &&
(getLocalStorageItem("currentCategory") !== null ||
getLocalStorageItem("currentCategory") !== undefined)
) {
body = getLocalStorageItem("currentCategory");
} else {
return;
}
const result = await api.get(`/questions/${body}`);
if (result.status === 200 && result.data.data !== false) {
await dispatch(categoryChosen(result.data.data[0].categoryId));
setLocalStorageItem(result.data.data,"questionsFetched")
}
}
La page score orchestre un classement filtrable (catégorie + mode de score) et propage les résultats dans Redux. Source: cda-hackathon-quiz-app-frontend/Hackathon-Quiz-App/src/js/views/ScorePage.jsx
async function fetchRankings(cat = 'total', avg = false) {
try {
const rankings = await api.get(`/rankings/${cat}/${avg}`);
if (rankings.status === 200) {
if (rankings.data.data) {
dispatch(updateRankings(rankings.data.data));
return rankings.data.data;
}
}
} catch (err) {
console.log(`Erreur lors de la requête : /rankings/${cat}/${avg}`);
}
}
🏗️ DevOps & Qualité
- Une pipeline GitLab CI exécute l’installation des dépendances et le build Vite, puis publie les fichiers de distribution. Source: cda-hackathon-quiz-app-frontend/.gitlab-ci.yml
image: node:13
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
stages:
- build
- deploy
build_parcel_master:
stage: build
script:
- cd ./Hackathon-Quiz-App/
- npm install
- npm run build
artifacts:
expire_in: 20 mins
paths:
- ./Hackathon-Quiz-App/dist
📈 Résultats
- Sur la base de l’historique Git du dépôt analysé, le travail couvre la période 2021-12-13 -> 2026-02-14, avec 91 commits réalisés par 8 contributeurs. L’implémentation délivre un frontend de quiz complet avec parcours protégé, pilotage d’état Redux, orchestration des appels API et affichage de classements/historique. Le dépôt montre aussi une logique de livraison continue avec build et packaging automatisés. Le bénéfice technique est une base SPA immédiatement exécutable et déployable pour un jeu orienté API.
🔧 Environnement technique
- Frontend: React 17, React Router 6, Redux Toolkit, React Redux, Redux Logger, Vite.
- Intégration API: Axios, configuration
import.meta.env. - State management: slices
authetgame, persistancelocalStorage. - UX métier: flow catégorie/mode/question, score, historique, filtre de classement.
- DevOps: GitLab CI (build + artifacts + déploiement automatisé).