sokko-g/website/src/features/toolboxes/modules/EquipmentPlannerModule.jsx

137 lines
5.1 KiB
JavaScript

// Rôle : fournit l'outil de planification d'équipements, sertissages, résumé et échange texte.
import { useMemo, useState } from "react";
import { moveItem, useGroupedReorder } from "../../../hooks/useGroupedReorder.js";
import { TextExchangeActions } from "./TextExchangeActions.jsx";
import { EQUIPMENT_ICONS } from "./equipmentPlannerOptions.js";
import { EquipmentItem } from "./EquipmentPlannerItem.jsx";
import { IconChoiceDropdown } from "./EquipmentPlannerPickers.jsx";
import { EquipmentPlannerSummary } from "./EquipmentPlannerSummary.jsx";
export function EquipmentPlannerModule({ toolboxId, moduleId, context, editing }) {
const data = context.normalizeEquipmentPlannerData(context.getModuleData(toolboxId, moduleId, { types: [], equipments: [] }));
const summary = useMemo(() => context.summarizeEquipmentPlannerData(data), [context, data]);
const textContent = context.moduleText?.equipmentPlanner || {};
const [equipmentIcon, setEquipmentIcon] = useState("helmet");
const [equipmentName, setEquipmentName] = useState("");
const {
itemReorder,
groupReorder,
getItemProps,
getGroupProps,
getGroupBoundaryProps,
isItemDragging,
isItemDropTarget,
isGroupDragging,
isGroupDropTarget,
isBoundaryDropTarget,
getDropPlacement,
shouldShowGroupBoundaries
} = useGroupedReorder({
namespace: `equipment-planner-${moduleId}`,
items: data.equipments,
getItemId: (equipment) => equipment.id,
onItemMove: (operation) => save({ ...data, equipments: moveItem(data.equipments, operation.sourceId, operation.targetId, operation.placement) })
});
const reorder = {
itemReorder,
groupReorder,
getItemProps,
getGroupProps,
getGroupBoundaryProps,
isItemDragging,
isItemDropTarget,
isGroupDragging,
isGroupDropTarget,
isBoundaryDropTarget,
getDropPlacement,
shouldShowGroupBoundaries
};
function save(nextData) {
context.setModuleData(toolboxId, moduleId, nextData, "equipmentPlanner");
}
function addEquipment(event) {
event.preventDefault();
const cleanName = equipmentName.trim();
if (!cleanName) return;
const type = data.types[0] || { id: context.uid("equipmentType"), title: "Équipements", icon: "shield", collapsed: false };
const nextData = {
...data,
types: data.types.length ? data.types : [type],
typeOrder: data.typeOrder.length ? data.typeOrder : [type.id],
equipments: [
...data.equipments,
{
id: context.uid("equipment"),
typeId: type.id,
name: cleanName,
icon: equipmentIcon,
active: true,
obtain: "",
characteristics: [],
socketItems: [],
socketLinks: [],
materials: [],
categoryOrder: [],
collapsedCategories: []
}
]
};
save(nextData);
setEquipmentName("");
}
function updateEquipment(equipmentId, updater) {
save({ ...data, equipments: data.equipments.map((equipment) => equipment.id === equipmentId ? updater(equipment) : equipment) });
}
function deleteEquipment(equipmentId) {
const nextEquipments = data.equipments.filter((equipment) => equipment.id !== equipmentId);
const usedTypeIds = new Set(nextEquipments.map((equipment) => equipment.typeId));
save({
...data,
equipments: nextEquipments,
types: data.types.filter((type) => usedTypeIds.has(type.id)),
typeOrder: data.typeOrder.filter((typeId) => usedTypeIds.has(typeId))
});
}
return (
<div className="equipment-planner-module">
{editing && (
<div className="module-add-panel">
<form className="inline-form equipment-planner-add-form" onSubmit={addEquipment}>
<IconChoiceDropdown
className="equipment-planner-equipment-icon-picker"
label={textContent.equipmentIconLabel || "Type"}
value={equipmentIcon}
options={EQUIPMENT_ICONS}
onChange={setEquipmentIcon}
/>
<input value={equipmentName} onChange={(event) => setEquipmentName(event.target.value)} placeholder={textContent.equipmentPlaceholder || "Nouvel équipement"} />
<button className="primary">{textContent.addEquipmentButton || "Ajouter"}</button>
</form>
<TextExchangeActions type="equipmentPlanner" data={data} context={context} textContent={textContent} onImport={(nextData) => save(nextData)} />
</div>
)}
<EquipmentPlannerSummary summary={summary} textContent={textContent} />
<ul className="equipment-planner-list">
{data.equipments.length ? data.equipments.map((equipment) => (
<EquipmentItem
key={equipment.id}
equipment={equipment}
reorder={reorder}
textContent={textContent}
onUpdate={(updater) => updateEquipment(equipment.id, updater)}
onDelete={() => deleteEquipment(equipment.id)}
/>
)) : (
<li className="equipment-planner-empty">{textContent.emptyEquipments || "Aucun équipement planifié."}</li>
)}
</ul>
</div>
);
}