sokko-g/website/src/features/games/GameListsPage.jsx
Shinuwa b221257616
All checks were successful
Deploy Sokko G / deploy (push) Successful in 15s
Improve toolbox architecture and initial bundle loading
2026-08-14 09:13:53 +02:00

103 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Rôle : affiche les listes de jeu transformables en checklist.
import { CopyChecklistItemsButton } from "./CopyChecklistItemsButton.jsx";
import { GameBreadcrumb } from "./GameBreadcrumb.jsx";
function getChecklistSections(list) {
return (list?.categories || []).map((category) => ({
title: category.title,
items: category.items.map((item) => ({ label: item.name, quantity: item.quantity }))
}));
}
function SymbolText({ text }) {
return String(text || "").split(/([♂♀])/g).map((part, index) => (
part === "♂" || part === "♀"
? <span className="game-list-symbol" key={index}>{part}</span>
: part
));
}
export function GameListsPage({ game, lists, selectedListId, onSelectList, linkedToolboxId, onCreateChecklist }) {
const selectedList = lists.find((list) => list.id === selectedListId) || lists[0] || null;
const selectedSections = getChecklistSections(selectedList);
return (
<>
<section className="page-heading game-heading">
<div>
<GameBreadcrumb game={game} />
<div className="game-title-row">
<h1>Listes</h1>
</div>
<p>Sélectionnez une liste, puis copiez-la ou créez une checklist dans la toolbox associée.</p>
<a className="game-list-help-link button" href="#/about#contribuer">Proposer une nouvelle liste</a>
</div>
</section>
{lists.length ? (
<>
<section className="game-list-selector" aria-label="Listes disponibles">
{lists.map((list) => (
<article className={`game-list-selector-item ${selectedList?.id === list.id ? "active" : ""}`} key={list.id}>
<button className="game-list-select-button" type="button" onClick={() => onSelectList(list.id)}>
<strong>{list.title}</strong>
<small>{list.itemCount} éléments</small>
</button>
<button
className="game-list-create-button primary"
type="button"
disabled={!linkedToolboxId}
onClick={() => onCreateChecklist?.(list)}
title={linkedToolboxId ? "Créer une checklist dans la toolbox associée" : "Associez une toolbox pour créer la checklist"}
aria-label={linkedToolboxId ? `Créer une checklist ${list.title}` : "Associez une toolbox pour créer la checklist"}
>
<span className="module-icon" aria-hidden="true">
<span className="module-icon-svg module-icon-checklist" />
</span>
</button>
</article>
))}
</section>
<section className="game-list-panel nebula-panel">
<header>
<div>
<h2>{selectedList.title}</h2>
</div>
<div className="game-list-actions">
<CopyChecklistItemsButton sections={selectedSections} title={`Copier ${selectedList.title.toLowerCase()} pour checklist`} />
</div>
</header>
<div className="game-list-categories">
{selectedList.categories.map((category) => (
<article className="game-list-category" key={category.id}>
<header>
<h3><SymbolText text={category.title} /></h3>
<div className="game-list-actions">
<span className="results-count">{category.items.length}</span>
<CopyChecklistItemsButton sections={[getChecklistSections({ categories: [category] })[0]]} title={`Copier ${category.title.toLowerCase()} pour checklist`} />
</div>
</header>
<ul>
{category.items.map((item) => (
<li key={`${selectedList.id}-${category.id}-${item.name}-${item.description}`}>
<div className="game-list-item-title">
<strong><SymbolText text={item.name} /></strong>
{item.hasQuantity && item.quantity !== 1 ? <em>x{item.quantity}</em> : null}
</div>
{item.description ? <span>{item.description}</span> : null}
</li>
))}
</ul>
</article>
))}
</div>
</section>
</>
) : (
<section className="empty">
<h2>Aucune liste</h2>
<p>Aucune liste n’est encore disponible pour ce jeu.</p>
</section>
)}
</>
);
}