structure refacto & file documentation
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s
This commit is contained in:
parent
d7871736c8
commit
895fec2b40
84 changed files with 2629 additions and 2313 deletions
102
website/src/pages/AboutPage.jsx
Normal file
102
website/src/pages/AboutPage.jsx
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
// Rôle : présente le projet, son fonctionnement local et les repères de contribution.
|
||||
import React, { useEffect } from "react";
|
||||
import { RichText } from "../components/RichText.jsx";
|
||||
|
||||
export function AboutPage({ siteContent }) {
|
||||
const content = siteContent.about;
|
||||
const limits = Array.isArray(content.limits) ? content.limits : [];
|
||||
const storageSectionIndex = content.sections.findIndex((section) => section.title.toLowerCase().includes("stockage"));
|
||||
const normalizeReminder = (item, index) => typeof item === "string" ? { title: `Point ${index + 1}`, text: item, icon: "toolbox" } : item;
|
||||
useEffect(() => {
|
||||
if (!location.hash.includes("#contribuer")) return;
|
||||
requestAnimationFrame(() => document.querySelector("#contribuer")?.scrollIntoView({ behavior: "smooth", block: "start" }));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="about-page">
|
||||
<section className="page-hero">
|
||||
<div>
|
||||
<p className="eyebrow">{content.eyebrow}</p>
|
||||
<h1>{content.title}</h1>
|
||||
<p><RichText text={content.description} /></p>
|
||||
</div>
|
||||
</section>
|
||||
<section className="about-story-section nebula-panel" aria-labelledby="about-story-title">
|
||||
<div className="about-section-heading">
|
||||
<p className="eyebrow">Principes</p>
|
||||
<h2 id="about-story-title">Comment ça fonctionne</h2>
|
||||
</div>
|
||||
<div className="about-story-list">
|
||||
{content.sections.map((section, index) => (
|
||||
<article className="about-story-item" key={section.title}>
|
||||
<span>{String(index + 1).padStart(2, "0")}</span>
|
||||
<div>
|
||||
<h3>{section.title}</h3>
|
||||
<p><RichText text={section.text} /></p>
|
||||
{index === storageSectionIndex && limits.length > 0 && (
|
||||
<div className="about-storage-reminders">
|
||||
<p className="eyebrow">{content.limitsTitle}</p>
|
||||
<ul className="about-reminders-list">
|
||||
{limits.map((item, itemIndex) => {
|
||||
const reminder = normalizeReminder(item, itemIndex);
|
||||
return (
|
||||
<li className="about-reminder-item" key={reminder.title || reminder.text}>
|
||||
<span className="module-icon" aria-hidden="true">
|
||||
<span className={`module-icon-svg module-icon-${reminder.icon || "toolbox"}`} />
|
||||
</span>
|
||||
<div>
|
||||
<h4>{reminder.title}</h4>
|
||||
<p><RichText text={reminder.text} /></p>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
<section className="about-tools-section nebula-panel">
|
||||
<div className="page-heading">
|
||||
<div>
|
||||
<p className="eyebrow">Toolbox</p>
|
||||
<h2>{content.toolsTitle}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div className="about-tools-list">
|
||||
{content.tools.map((tool) => (
|
||||
<article className="about-tool-item" key={tool.name}>
|
||||
<span className="module-icon" aria-hidden="true">
|
||||
<span className={`module-icon-svg module-icon-${tool.icon || "notepad"}`} />
|
||||
</span>
|
||||
<div>
|
||||
<h3>{tool.name}</h3>
|
||||
<p><RichText text={tool.description} /></p>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
{content.contribute && (
|
||||
<section className="about-contribute-section nebula-panel" id="contribuer" aria-labelledby="about-contribute-title">
|
||||
<div className="about-section-heading">
|
||||
<p className="eyebrow">{content.contribute.eyebrow}</p>
|
||||
<h2 id="about-contribute-title">{content.contribute.title}</h2>
|
||||
</div>
|
||||
<div className="about-contribute-content">
|
||||
<p><RichText text={content.contribute.description} /></p>
|
||||
<pre><code>{content.contribute.example}</code></pre>
|
||||
<div className="about-prompt-box">
|
||||
<h3>{content.contribute.promptTitle}</h3>
|
||||
<p><RichText text={content.contribute.promptIntro} /></p>
|
||||
<pre><code>{content.contribute.promptText}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
49
website/src/pages/HomePage.jsx
Normal file
49
website/src/pages/HomePage.jsx
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// Rôle : affiche la page d'accueil et les contenus éditoriaux principaux.
|
||||
import React from "react";
|
||||
import { TOOLBOX_MODULES } from "../features/toolboxes/modules/index.jsx";
|
||||
import { RichText } from "../components/RichText.jsx";
|
||||
|
||||
export function HomePage({ siteContent, toolboxes }) {
|
||||
const content = siteContent.home;
|
||||
const toolCount = Object.keys(TOOLBOX_MODULES).length;
|
||||
return (
|
||||
<>
|
||||
<section className="hero">
|
||||
<div>
|
||||
<p className="eyebrow">{content.hero.eyebrow}</p>
|
||||
<h1>{content.hero.title}</h1>
|
||||
<p>{content.hero.description}</p>
|
||||
<div className="actions">
|
||||
<a className="button primary" href="#/toolboxes">{content.hero.primaryAction}</a>
|
||||
<a className="button" href="#/games">{content.hero.secondaryAction}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="home-stats hero-stats" aria-label="Statistiques locales du site">
|
||||
<article><strong>{toolboxes.length}</strong><span>{toolboxes.length > 1 ? content.stats.toolboxPlural : content.stats.toolboxSingular}</span></article>
|
||||
<article><strong>{toolCount}</strong><span>{toolCount > 1 ? content.stats.toolPlural : content.stats.toolSingular}</span></article>
|
||||
</div>
|
||||
</section>
|
||||
<section className="origin-section nebula-panel" aria-labelledby="origin-title">
|
||||
<div className="origin-copy">
|
||||
<p className="eyebrow">{content.origin.eyebrow}</p>
|
||||
<h2 id="origin-title">{content.origin.title}</h2>
|
||||
<div className="home-dialogue" aria-label={content.origin.dialogueAriaLabel}>
|
||||
{content.origin.lines.map((line, index) => <DialogueLine key={index} line={line} />)}
|
||||
<small className="dialogue-caption">{content.origin.caption}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div className="home-visual" aria-label="Illustration Sokko G">
|
||||
<img src="/static/img/dragon.png" alt={content.origin.visualAlt} />
|
||||
</div>
|
||||
</section>
|
||||
<footer className="home-legal">
|
||||
<p>{content.legal.copyright}</p>
|
||||
<p>{content.legal.disclaimer}</p>
|
||||
</footer>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function DialogueLine({ line }) {
|
||||
return <p className={`dialogue-line dialogue-line-${line.speaker === "app" ? "app" : "user"}`}><RichText text={line.text || ""} /></p>;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue