add list page and multiples optis
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s

This commit is contained in:
Shinuwa 2026-07-24 16:14:14 +02:00
parent d9d22683dc
commit 959fa42454
30 changed files with 1015 additions and 45 deletions

View file

@ -0,0 +1,95 @@
import { Icon } from "../../components/Icon.jsx";
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 }))
}));
}
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 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>{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>{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>
)}
</>
);
}