Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions frontend/src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import RequireAuth from "./routes/RequireAuth";
import QuizCallback from "./routes/QuizCallback";
import useAuthSession from "./hooks/useAuthSession";
import { socket } from "../socket/socket";
import PrivacyPolicy from "./pages/PrivacyPolicy";
import TermsOfService from "./pages/TermsOfService";

export default function App() {
const {
Expand Down Expand Up @@ -51,6 +53,8 @@ export default function App() {
<Routes>
<Route path="/quiz" element={<QuizCallback authChecked={authChecked} />} />
<Route path="/2fa" element={<LoginPage force2FA onLogin={handleLogin} />} />
<Route path="/privacy-policy" element={<PrivacyPolicy />} />
<Route path="/terms-of-service" element={<TermsOfService />} />

<Route
element={
Expand Down
35 changes: 30 additions & 5 deletions frontend/src/app/components/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Sparkles, MessageCircle, Send, X, Minus, LogOut, Trophy } from "lucide-react";
import { Outlet, useNavigate } from "react-router-dom";
import { Link, Outlet, useLocation, useNavigate } from "react-router-dom";
import { useState, useEffect, useRef } from "react";
import { socket } from "../../socket/socket";
import { useGame } from "../context/GameContext";
Expand All @@ -10,7 +10,11 @@ interface LayoutProps {
}

export default function Layout({ username, onLogout }: LayoutProps) {
const navigate = useNavigate();
const navigate = useNavigate();
const location = useLocation();
const hideFooter =
location.pathname.startsWith("/game/") ||
location.pathname === "/tournament";

const [userAvatar, setUserAvatar] = useState<string | null>(null);

Expand Down Expand Up @@ -163,9 +167,30 @@ return (
</nav>

{/* --- 2. CONTENU PRINCIPAL DE LA PAGE --- */}
<div className="pt-20">
<Outlet />
</div>
<div className="pt-20">
<Outlet />
{!hideFooter && (
<footer className="py-4 text-center">
<div className="flex justify-center gap-4 text-xs text-gray-500">
<Link
to="/privacy-policy"
className="hover:text-gray-700 hover:underline"
>
Privacy Policy
</Link>

<span>•</span>

<Link
to="/terms-of-service"
className="hover:text-gray-700 hover:underline"
>
Terms of Service
</Link>
</div>
</footer>
)}
</div>

{/* --- 3. WIDGET CHAT --- */}
<div className="fixed bottom-6 right-6 z-50">
Expand Down
22 changes: 21 additions & 1 deletion frontend/src/app/components/LoginPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Sparkles, Mail, Lock, User, AlertCircle, Key, Github } from "lucide-react";
import { useState } from "react";
import { Link } from "react-router-dom";

interface LoginPageProps {
onLogin?: () => void;
Expand Down Expand Up @@ -63,7 +64,7 @@ export default function LoginPage({ onLogin, force2FA = false }: LoginPageProps)
};

return (
<div className="min-h-screen bg-gradient-to-br from-violet-100 via-pink-50 to-cyan-100 flex items-center justify-center p-6">
<div className="min-h-screen bg-gradient-to-br from-violet-100 via-pink-50 to-cyan-100 flex flex-col items-center justify-center p-6">
{/* Background decorative elements */}
<div className="absolute inset-0 overflow-hidden pointer-events-none">
<div className="absolute top-20 left-20 w-72 h-72 bg-purple-300 rounded-full mix-blend-multiply filter blur-xl opacity-30 animate-blob"></div>
Expand Down Expand Up @@ -230,6 +231,25 @@ export default function LoginPage({ onLogin, force2FA = false }: LoginPageProps)
)}
</div>
</div>
<footer className="mt-6 text-center shrink-0">
<div className="flex justify-center gap-3 text-xs text-gray-400">
<Link
to="/privacy-policy"
className="hover:text-gray-600 hover:underline"
>
Privacy Policy
</Link>

<span>•</span>

<Link
to="/terms-of-service"
className="hover:text-gray-600 hover:underline"
>
Terms of Service
</Link>
</div>
</footer>
</div>
);
}
5 changes: 5 additions & 0 deletions frontend/src/app/components/PartyGame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export default function QuizPage()

function initializeMatch(data: any)
{
setGameStarted(false);
setWaitingForFinal(false);
const isPlayer1 = socket.id === data.player1.id;

Expand Down Expand Up @@ -216,6 +217,7 @@ export default function QuizPage()
setWaitingForFinal(false);
setOpponentReady(false);
setTournamentBracket(null);
setGameStarted(true);
}, 5000);
}
else
Expand All @@ -238,6 +240,9 @@ export default function QuizPage()

socket.on("start_game", () =>
{
if (bracketTimeoutRef.current)
return;

setGameStarted(true);
});

Expand Down
147 changes: 147 additions & 0 deletions frontend/src/app/pages/PrivacyPolicy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import { useNavigate } from "react-router-dom";

export default function PrivacyPolicy() {
const navigate = useNavigate();

return (
<div className="min-h-screen bg-gradient-to-br from-violet-900 via-purple-900 to-indigo-900 px-6 py-10">
<div className="mx-auto max-w-4xl rounded-3xl border border-white/20 bg-white/10 p-10 text-white shadow-2xl backdrop-blur-md">
<h1 className="mb-8 text-4xl font-bold">Privacy Policy</h1>

<p className="mb-6 text-white/80">
Last updated: August 2026
</p>

<section className="mb-8">
<h2 className="mb-3 text-2xl font-semibold">
1. Introduction
</h2>
<p className="text-white/80">
This Privacy Policy explains how Culture Quiz collects,
uses and protects information when you use our multiplayer
quiz game and its related services.
</p>
</section>

<section className="mb-8">
<h2 className="mb-3 text-2xl font-semibold">
2. Information We Collect
</h2>
<p className="mb-3 text-white/80">
Depending on how you use the application, we may collect:
</p>
<ul className="list-disc space-y-2 pl-6 text-white/80">
<li>Username and email address.</li>
<li>Account authentication information.</li>
<li>
Information provided through supported authentication
providers such as 42 and GitHub.
</li>
<li>Game results, scores and statistics.</li>
<li>Tournament participation and results.</li>
<li>Information required to maintain an active game session.</li>
</ul>
</section>

<section className="mb-8">
<h2 className="mb-3 text-2xl font-semibold">
3. How We Use Your Information
</h2>
<p className="mb-3 text-white/80">
We use this information to:
</p>
<ul className="list-disc space-y-2 pl-6 text-white/80">
<li>Create and manage your account.</li>
<li>Authenticate you and protect your account.</li>
<li>Provide multiplayer games and matchmaking.</li>
<li>Organize and manage tournaments.</li>
<li>Display profiles, leaderboards and game statistics.</li>
<li>Maintain the security and reliability of the application.</li>
</ul>
</section>

<section className="mb-8">
<h2 className="mb-3 text-2xl font-semibold">
4. Authentication
</h2>
<p className="text-white/80">
Culture Quiz supports several authentication methods,
including local authentication and third-party authentication
providers. When using a third-party provider, certain
identification information may be received from that provider
in order to create or authenticate your Culture Quiz account.
</p>
</section>

<section className="mb-8">
<h2 className="mb-3 text-2xl font-semibold">
5. Cookies and Sessions
</h2>
<p className="text-white/80">
The application uses authentication cookies to maintain your
session. These cookies are used to authenticate requests and
maintain access to protected features. Authentication sessions
may also be associated with an active WebSocket connection
while you are using multiplayer features.
</p>
</section>

<section className="mb-8">
<h2 className="mb-3 text-2xl font-semibold">
6. Data Retention
</h2>
<p className="text-white/80">
Account information and game-related statistics may be retained
for as long as necessary to provide the application's features.
Session-related information is removed or invalidated when it
is no longer required.
</p>
</section>

<section className="mb-8">
<h2 className="mb-3 text-2xl font-semibold">
7. Data Security
</h2>
<p className="text-white/80">
We take reasonable technical measures to protect account and
game data against unauthorized access, modification or
disclosure. Passwords are not stored in plain text.
Authentication and sensitive operations are protected by
appropriate security mechanisms.
</p>
</section>

<section className="mb-8">
<h2 className="mb-3 text-2xl font-semibold">
8. Your Rights
</h2>
<p className="text-white/80">
Depending on applicable data protection laws, you may have
rights concerning your personal information, including the
right to access, correct or request deletion of your data.
</p>
</section>

<section>
<h2 className="mb-3 text-2xl font-semibold">
9. Contact
</h2>
<p className="text-white/80">
If you have questions about this Privacy Policy or the handling
of your personal information, please contact the Culture Quiz
project team.
</p>
</section>

<div className="mt-10 text-center">
<button
onClick={() => navigate(-1)}
className="rounded-full bg-white/20 px-6 py-2 text-sm text-white transition hover:bg-white/30"
>
← Back
</button>
</div>
</div>
</div>
);
}
Loading