This commit is contained in:
parent
db4b99aee3
commit
1dee8b528f
30 changed files with 3491 additions and 2444 deletions
66
website/src/features/toolboxes/modules/ChecklistModule.jsx
Normal file
66
website/src/features/toolboxes/modules/ChecklistModule.jsx
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import { useState } from "react";
|
||||
|
||||
export function ChecklistModule({ toolboxId, moduleId, context }) {
|
||||
const data = context.normalizeChecklistData(context.getModuleData(toolboxId, moduleId, { items: [] }));
|
||||
const [label, setLabel] = useState("");
|
||||
const [qty, setQty] = useState(1);
|
||||
|
||||
function save(items) {
|
||||
context.setModuleData(toolboxId, moduleId, { items });
|
||||
}
|
||||
|
||||
function addItem(event) {
|
||||
event.preventDefault();
|
||||
const cleanLabel = label.trim();
|
||||
if (!cleanLabel) return;
|
||||
save([...data.items, { id: context.uid("item"), label: cleanLabel, qtyTarget: Math.max(1, Number(qty) || 1), qtyCurrent: 0 }]);
|
||||
setLabel("");
|
||||
setQty(1);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<form className="inline-form checklist-add-form" onSubmit={addItem}>
|
||||
<input name="label" placeholder="Nouvel item" value={label} onChange={(event) => setLabel(event.target.value)} />
|
||||
<input className="checklist-qty-input" name="qty" type="number" min="1" value={qty} onChange={(event) => setQty(event.target.value)} aria-label="Quantité cible" />
|
||||
<button className="primary">Ajouter</button>
|
||||
</form>
|
||||
<ul className="checklist">
|
||||
{data.items.map((item) => (
|
||||
<ChecklistItem key={item.id} item={item} toolboxId={toolboxId} moduleId={moduleId} context={context} items={data.items} save={save} />
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ChecklistItem({ item, context, items, save }) {
|
||||
const done = context.clampQty(item.qtyCurrent, item.qtyTarget) >= item.qtyTarget;
|
||||
|
||||
function updateItem(updater) {
|
||||
save(items.map((entry) => entry.id === item.id ? updater(entry) : entry));
|
||||
}
|
||||
|
||||
return (
|
||||
<li className={`checklist-item ${done ? "is-complete" : ""}`}>
|
||||
<div className="checklist-item-main">
|
||||
{item.qtyTarget === 1 ? (
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={done}
|
||||
onChange={(event) => updateItem((entry) => ({ ...entry, qtyTarget: 1, qtyCurrent: event.target.checked ? 1 : 0 }))}
|
||||
aria-label={`Terminer ${item.label}`}
|
||||
/>
|
||||
) : (
|
||||
<div className="checklist-qty-controls" aria-label={`Quantité ${item.label}`}>
|
||||
<button type="button" onClick={() => updateItem((entry) => ({ ...entry, qtyCurrent: context.clampQty(entry.qtyCurrent - 1, entry.qtyTarget) }))} aria-label="Retirer une quantité">-</button>
|
||||
<small>{context.clampQty(item.qtyCurrent, item.qtyTarget)}/{item.qtyTarget}</small>
|
||||
<button type="button" onClick={() => updateItem((entry) => ({ ...entry, qtyCurrent: context.clampQty(entry.qtyCurrent + 1, entry.qtyTarget) }))} aria-label="Ajouter une quantité">+</button>
|
||||
</div>
|
||||
)}
|
||||
<span>{item.label}</span>
|
||||
</div>
|
||||
<button onClick={() => save(items.filter((entry) => entry.id !== item.id))} aria-label={`Supprimer ${item.label}`}>×</button>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue