added some changes in Detail and accueil, added space between

This commit is contained in:
2026-06-26 14:21:46 +02:00
parent e939e2c0ef
commit f6da867500
5 changed files with 241 additions and 175 deletions
+144 -141
View File
@@ -1,184 +1,187 @@
.counter {
font-size: 16px;
padding: 5px 10px;
border-radius: 5px;
color: var(--accent);
background: var(--accent-bg);
border: 2px solid transparent;
transition: border-color 0.3s;
margin-bottom: 24px;
font-size: 16px;
padding: 5px 10px;
border-radius: 5px;
color: var(--accent);
background: var(--accent-bg);
border: 2px solid transparent;
transition: border-color 0.3s;
margin-bottom: 24px;
&:hover {
border-color: var(--accent-border);
}
&:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
&:hover {
border-color: var(--accent-border);
}
&:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
}
.hero {
position: relative;
.base,
.framework,
.vite {
inset-inline: 0;
margin: 0 auto;
}
.base {
width: 170px;
position: relative;
z-index: 0;
}
.framework,
.vite {
position: absolute;
}
.base,
.framework,
.vite {
inset-inline: 0;
margin: 0 auto;
}
.framework {
z-index: 1;
top: 34px;
height: 28px;
transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)
scale(1.4);
}
.base {
width: 170px;
position: relative;
z-index: 0;
}
.vite {
z-index: 0;
top: 107px;
height: 26px;
width: auto;
transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)
scale(0.8);
}
.framework,
.vite {
position: absolute;
}
.framework {
z-index: 1;
top: 34px;
height: 28px;
transform: perspective(2000px) rotateZ(300deg) rotateX(44deg)
rotateY(39deg) scale(1.4);
}
.vite {
z-index: 0;
top: 107px;
height: 26px;
width: auto;
transform: perspective(2000px) rotateZ(300deg) rotateX(40deg)
rotateY(39deg) scale(0.8);
}
}
#center {
display: flex;
flex-direction: column;
gap: 25px;
place-content: center;
place-items: center;
flex-grow: 1;
display: flex;
flex-direction: column;
gap: 25px;
place-content: center;
place-items: center;
flex-grow: 1;
@media (max-width: 1024px) {
padding: 32px 20px 24px;
gap: 18px;
}
@media (max-width: 1024px) {
padding: 32px 20px 24px;
gap: 18px;
}
}
#next-steps {
display: flex;
border-top: 1px solid var(--border);
text-align: left;
display: flex;
border-top: 1px solid var(--border);
text-align: left;
& > div {
flex: 1 1 0;
padding: 32px;
@media (max-width: 1024px) {
padding: 24px 20px;
& > div {
flex: 1 1 0;
padding: 32px;
@media (max-width: 1024px) {
padding: 24px 20px;
}
}
}
.icon {
margin-bottom: 16px;
width: 22px;
height: 22px;
}
.icon {
margin-bottom: 16px;
width: 22px;
height: 22px;
}
@media (max-width: 1024px) {
flex-direction: column;
text-align: center;
}
@media (max-width: 1024px) {
flex-direction: column;
text-align: center;
}
}
#docs {
border-right: 1px solid var(--border);
border-right: 1px solid var(--border);
@media (max-width: 1024px) {
border-right: none;
border-bottom: 1px solid var(--border);
}
@media (max-width: 1024px) {
border-right: none;
border-bottom: 1px solid var(--border);
}
}
#next-steps ul {
list-style: none;
padding: 0;
display: flex;
gap: 8px;
margin: 32px 0 0;
.logo {
height: 18px;
}
a {
color: var(--text-h);
font-size: 16px;
border-radius: 6px;
background: var(--social-bg);
list-style: none;
padding: 0;
display: flex;
padding: 6px 12px;
align-items: center;
gap: 8px;
text-decoration: none;
transition: box-shadow 0.3s;
margin: 32px 0 0;
&:hover {
box-shadow: var(--shadow);
}
.button-icon {
height: 18px;
width: 18px;
}
}
@media (max-width: 1024px) {
margin-top: 20px;
flex-wrap: wrap;
justify-content: center;
li {
flex: 1 1 calc(50% - 8px);
.logo {
height: 18px;
}
a {
width: 100%;
justify-content: center;
box-sizing: border-box;
color: var(--text-h);
font-size: 16px;
border-radius: 6px;
background: var(--social-bg);
display: flex;
padding: 6px 12px;
align-items: center;
gap: 8px;
text-decoration: none;
transition: box-shadow 0.3s;
&:hover {
box-shadow: var(--shadow);
}
.button-icon {
height: 18px;
width: 18px;
}
}
@media (max-width: 1024px) {
margin-top: 20px;
flex-wrap: wrap;
justify-content: center;
li {
flex: 1 1 calc(50% - 8px);
}
a {
width: 100%;
justify-content: center;
box-sizing: border-box;
}
}
}
}
#spacer {
height: 88px;
border-top: 1px solid var(--border);
@media (max-width: 1024px) {
.spacer {
height: 48px;
}
@media (max-width: 1024px) {
height: 28px;
}
}
.smallgap {
height: 20px;
}
.ticks {
position: relative;
width: 100%;
position: relative;
width: 100%;
&::before,
&::after {
content: '';
position: absolute;
top: -4.5px;
border: 5px solid transparent;
}
&::before,
&::after {
content: "";
position: absolute;
top: -4.5px;
border: 5px solid transparent;
}
&::before {
left: 0;
border-left-color: var(--border);
}
&::after {
right: 0;
border-right-color: var(--border);
}
&::before {
left: 0;
border-left-color: var(--border);
}
&::after {
right: 0;
border-right-color: var(--border);
}
}
+32 -3
View File
@@ -1,17 +1,46 @@
import { useState, useEffect } from "react";
import { Routes, Route } from "react-router-dom";
import Header from "./components/Header";
import Footer from "./components/Footer";
import { Routes, Route } from "react-router-dom";
import Accueil from "./pages/Accueil";
import Detail from "./pages/Detail";
import "./App.css";
function App() {
const [jeux, setJeux] = useState([]);
const [likes, setLikes] = useState(() =>
JSON.parse(localStorage.getItem("likes") || "{}"),
);
useEffect(() => {
fetch("/zelda.json")
.then((r) => r.json())
.then(setJeux);
}, []);
useEffect(() => {
localStorage.setItem("likes", JSON.stringify(likes));
}, [likes]);
function liker(id) {
setLikes((prev) => ({ ...prev, [id]: (prev[id] || 0) + 1 }));
}
return (
<>
<Header />
<Routes>
<Route path="/" element={<Accueil />} />
<Route path="/jeu/:id" element={<Detail />} />
<Route
path="/"
element={
<Accueil
jeux={jeux}
setJeux={setJeux}
likes={likes}
onLike={liker}
/>
}
/>
<Route path="/jeu/:id" element={<Detail jeux={jeux} likes={likes} />} />
</Routes>
<Footer />
</>
+1 -1
View File
@@ -4,7 +4,6 @@ import { useState } from "react";
import { Link } from "react-router-dom";
function Carte(props) {
console.log(props.gameId);
const [likes, setLikes] = useState(
() => Number(localStorage.getItem("likes-" + props.gameId)) || 0,
);
@@ -27,6 +26,7 @@ function Carte(props) {
>
{likes}
</button>
<section className="smallgap"></section>
</div>
);
}
+43 -27
View File
@@ -1,16 +1,20 @@
import Carte from "../components/Carte";
import BarreRecherche from "../components/BarreRecherche";
import { useState, useEffect } from "react";
import { useState } from "react";
function Accueil() {
function Accueil({ jeux, setJeux, likes, onLike }) {
const [recherche, setRecherche] = useState("");
const [total, setTotal] = useState(0);
const [jeux, setJeux] = useState([]);
const [chargement, setChargement] = useState(true);
const [total] = useState(0);
const [titre, setTitre] = useState("");
const [annee, setAnnee] = useState("");
const [plateforme, setPlateforme] = useState("");
const [tri, setTri] = useState("titre");
const medailles = ["🥇", "🥈", "🥉"];
const [filtreType, setFiltreType] = useState("tous");
const top = [...jeux]
.sort((a, b) => (likes[b.id] || 0) - (likes[a.id] || 0))
.slice(0, 3);
function ajouter(e) {
e.preventDefault();
@@ -30,50 +34,62 @@ function Accueil() {
const affiches = [...jeux]
.filter((j) => j.titre.toLowerCase().includes(recherche.toLowerCase()))
.filter((j) => filtreType === "tous" || j.Type === filtreType)
.sort((a, b) => {
if (tri === "titre") return a.titre.localeCompare(b.titre);
if (tri === "annee") return a.annee - b.annee;
return 0;
});
useEffect(() => {
fetch("/zelda.json")
.then((r) => r.json())
.then((data) => {
setJeux(data);
document.title = `${data.length} jeux Zelda`;
setChargement(false);
});
}, []);
if (chargement) return <p>Chargement</p>;
return (
<>
<BarreRecherche
valeur={recherche}
onChange={(e) => setRecherche(e.target.value)}
/>
<select value={tri} onChange={(e) => setTri(e.target.value)}>
<option value="titre">Titre (AZ)</option>
<option value="annee">Année</option>
</select>
<div>
<BarreRecherche
valeur={recherche}
onChange={(e) => setRecherche(e.target.value)}
/>
<select value={tri} onChange={(e) => setTri(e.target.value)}>
<option value="titre">Titre (AZ)</option>
<option value="annee">Année</option>
</select>
<button onClick={() => setFiltreType("tous")}>Tous</button>
<button onClick={() => setFiltreType("2d")}>2D</button>
<button onClick={() => setFiltreType("3d")}>3D</button>
</div>
{affiches.length === 0 && <p>Aucun jeu trouvé 😕</p>}
<section class="spacer"></section>
<div className="hall">
{top.map((j, index) => (
<p key={j.id}>
{medailles[index]} {j.titre} {likes[j.id] || 0}
</p>
))}
</div>
<section class="spacer"></section>
{affiches.map((jeu) => (
<Carte
key={jeu.id}
gameId={jeu.id}
titre={jeu.titre}
console={jeu.console}
console={jeu.plateforme}
annee={jeu.annee}
Type={jeu.Type}
onLike={() => setTotal((t) => t + 1)}
likes={likes[jeu.id] || 0}
onLike={() => onLike(jeu.id)}
/>
))}
<section class="spacer"></section>
<p> Total de likes : {total}</p>
<section class="spacer"></section>
<form onSubmit={ajouter}>
<input
value={titre}
@@ -91,7 +107,7 @@ function Accueil() {
placeholder="Console"
/>
<button type="submit">Ajouter</button>
<section id="spacer"></section>
<section class="spacer"></section>
</form>
</>
);
+21 -3
View File
@@ -1,7 +1,25 @@
import { useParams } from "react-router-dom";
import { useParams, Link } from "react-router-dom";
function Detail() {
function Detail({ jeux, likes }) {
const { id } = useParams();
return <h1>Détails du jeu {id}</h1>;
const jeu = jeux.find((j) => String(j.id) === id);
if (!jeu)
return (
<p>
Introuvable <Link to="/">retour</Link>
</p>
);
return (
<div className="detail">
<Link to="/"> Retour</Link>
<h1>{jeu.titre}</h1>
<p>
{jeu.console} {jeu.annee} {jeu.Type}
</p>
<p> Likes : {likes[jeu.id] || 0}</p>
</div>
);
}
export default Detail;