Refactor inline editing into shared hook
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s
This commit is contained in:
parent
1879b245fb
commit
1e4ac4259b
9 changed files with 239 additions and 205 deletions
|
|
@ -3,6 +3,7 @@ import { useEffect, useMemo, useRef, useState } from "react";
|
|||
import { Icon } from "../../../components/Icon.jsx";
|
||||
import { InlineNotice } from "../../../components/AppOverlays.jsx";
|
||||
import { applyGroupedReorderOperation, useGroupedReorder } from "../../../hooks/useGroupedReorder.js";
|
||||
import { useInlineEdit } from "../../../hooks/useInlineEdit.js";
|
||||
|
||||
const TASK_TYPES = ["daily", "weekly", "unique"];
|
||||
const WEEK_DAYS = [
|
||||
|
|
@ -770,13 +771,10 @@ function TaskPlannerItem({
|
|||
onSetTaskCategory,
|
||||
children
|
||||
}) {
|
||||
const [titleDraft, setTitleDraft] = useState(task.title);
|
||||
const [descriptionDraft, setDescriptionDraft] = useState(task.description);
|
||||
const parentTask = parentId ? getTaskById(tasks, parentId) : null;
|
||||
const inheritedCategory = parentTask ? getEffectiveTaskCategory(parentTask, tasks, parentMap) : "";
|
||||
const categoryValue = parentTask ? inheritedCategory : task.category || "";
|
||||
const categoryEditable = !parentTask;
|
||||
const [categoryDraft, setCategoryDraft] = useState(categoryValue);
|
||||
const relations = data.relations.filter((relation) => relation.fromTaskId === task.id);
|
||||
const missingPrerequisites = relations.filter((relation) => relation.prerequisite && !tasks.find((item) => item.id === relation.toTaskId)?.checked);
|
||||
const relationTargets = tasks.filter((item) => item.id !== task.id && !relations.some((relation) => relation.toTaskId === item.id));
|
||||
|
|
@ -789,6 +787,22 @@ function TaskPlannerItem({
|
|||
reorder.isItemDropTarget(task.id) ? "is-drop-target" : "",
|
||||
reorder.getDropPlacement("item", task.id) === "after" ? "drop-after" : ""
|
||||
].filter(Boolean).join(" ");
|
||||
const titleEdit = useInlineEdit({
|
||||
value: task.title,
|
||||
transform: (draft) => String(draft || "").trim() || task.title,
|
||||
onCommit: (title) => onUpdateTask(task.id, (current) => ({ ...current, title }))
|
||||
});
|
||||
const categoryEdit = useInlineEdit({
|
||||
value: categoryValue,
|
||||
onCommit: (category) => {
|
||||
if (categoryEditable) onSetTaskCategory(task.id, category);
|
||||
}
|
||||
});
|
||||
const descriptionEdit = useInlineEdit({
|
||||
value: task.description,
|
||||
onCommit: (description) => onUpdateTask(task.id, (current) => ({ ...current, description })),
|
||||
commitOnEnter: false
|
||||
});
|
||||
|
||||
function updateChecked(event) {
|
||||
const checked = event.target.checked;
|
||||
|
|
@ -800,34 +814,6 @@ function TaskPlannerItem({
|
|||
}));
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setCategoryDraft(categoryValue);
|
||||
}, [categoryValue, task.id]);
|
||||
|
||||
useEffect(() => {
|
||||
setTitleDraft(task.title);
|
||||
}, [task.id, task.title]);
|
||||
|
||||
useEffect(() => {
|
||||
setDescriptionDraft(task.description);
|
||||
}, [task.description, task.id]);
|
||||
|
||||
function commitTitleDraft() {
|
||||
const title = titleDraft.trim() || task.title;
|
||||
if (title !== task.title) onUpdateTask(task.id, (current) => ({ ...current, title }));
|
||||
else if (titleDraft !== title) setTitleDraft(title);
|
||||
}
|
||||
|
||||
function commitDescriptionDraft() {
|
||||
const description = descriptionDraft.trim();
|
||||
if (description !== task.description) onUpdateTask(task.id, (current) => ({ ...current, description }));
|
||||
else if (descriptionDraft !== description) setDescriptionDraft(description);
|
||||
}
|
||||
|
||||
function commitCategoryDraft() {
|
||||
if (categoryEditable && categoryDraft.trim() !== (task.category || "")) onSetTaskCategory(task.id, categoryDraft);
|
||||
}
|
||||
|
||||
return (
|
||||
<li className={className} {...reorder.getItemProps({ itemId: task.id, groupId: getTaskCategoryDataset(task, tasks, parentMap), parentId })}>
|
||||
<div className="task-planner-line">
|
||||
|
|
@ -847,14 +833,10 @@ function TaskPlannerItem({
|
|||
aria-label={`${task.checked ? textContent.uncheckTitle || "Marquer non effectué" : textContent.checkTitle || "Marquer effectué"} ${task.title}`}
|
||||
/>
|
||||
<input
|
||||
className="tool-split-entry-label task-planner-title-input"
|
||||
value={titleDraft}
|
||||
onChange={(event) => setTitleDraft(event.target.value)}
|
||||
onBlur={commitTitleDraft}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === "Enter") event.currentTarget.blur();
|
||||
}}
|
||||
aria-label={textContent.titleLabel || "Titre"}
|
||||
{...titleEdit.getInputProps({
|
||||
className: "tool-split-entry-label task-planner-title-input",
|
||||
"aria-label": textContent.titleLabel || "Titre"
|
||||
})}
|
||||
/>
|
||||
<select
|
||||
className="task-planner-type-select"
|
||||
|
|
@ -906,26 +888,21 @@ function TaskPlannerItem({
|
|||
<label className={`task-planner-category-field ${categoryEditable ? "" : "is-disabled"}`}>
|
||||
<span>{textContent.categoryLabel || "Catégorie"}</span>
|
||||
<input
|
||||
value={categoryDraft}
|
||||
onChange={(event) => setCategoryDraft(event.target.value)}
|
||||
onBlur={commitCategoryDraft}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === "Enter") event.currentTarget.blur();
|
||||
}}
|
||||
disabled={!categoryEditable}
|
||||
placeholder={textContent.categoryPlaceholder || "Nom de catégorie"}
|
||||
aria-label={`${textContent.categoryLabel || "Catégorie"} ${task.title}`}
|
||||
{...categoryEdit.getInputProps({
|
||||
disabled: !categoryEditable,
|
||||
placeholder: textContent.categoryPlaceholder || "Nom de catégorie",
|
||||
"aria-label": `${textContent.categoryLabel || "Catégorie"} ${task.title}`
|
||||
})}
|
||||
/>
|
||||
</label>
|
||||
<label className="task-planner-description-field">
|
||||
<span>{textContent.descriptionLabel || "Description"}</span>
|
||||
<textarea
|
||||
className="task-planner-description"
|
||||
value={descriptionDraft}
|
||||
onChange={(event) => setDescriptionDraft(event.target.value)}
|
||||
onBlur={commitDescriptionDraft}
|
||||
placeholder={textContent.descriptionPlaceholder || "Description"}
|
||||
aria-label={`${textContent.descriptionLabel || "Description"} ${task.title}`}
|
||||
{...descriptionEdit.getInputProps({
|
||||
className: "task-planner-description",
|
||||
placeholder: textContent.descriptionPlaceholder || "Description",
|
||||
"aria-label": `${textContent.descriptionLabel || "Description"} ${task.title}`
|
||||
})}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue