103 lines
4.5 KiB
JavaScript
103 lines
4.5 KiB
JavaScript
// 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>
|
||
)}
|
||
</>
|
||
);
|
||
}
|