Skip to content

Autosave edits in PlayerItemList's edit modal, with Saved/failed-to-save feedback #763

Description

@gaidheal1

Summary

PlayerItemList (frontend/src/components/PlayerItemList/PlayerItemList.tsx) backs the edit modal for every player-added-item panel — Tasks, Skills, Projects, Categories, and Activities (all import it: TasksPanel.tsx, SkillsPanel.tsx, ProjectsPanel.tsx, CategoriesPanel.tsx, ActivitiesPanel.tsx).

Inside that modal, most fields already autosave (e.g. TasksPanel.tsx's due-date input fires updateTask.mutate(...) onBlur at line 165, and the parent-task <select> fires on onChange at line 200). But the item name field is the odd one out: it only commits when the user clicks the explicit "Save" button (or presses Enter) — see PlayerItemList.tsx:334-356, handleEditSave.

Requested change

  1. Make the name field (and any other still-manual field in this modal, if any exist per-panel) save on change/blur, consistent with the due-date and parent-select fields, instead of requiring an explicit "Save" click.
  2. Whenever an autosave fires (from any field in the modal, across any panel using PlayerItemList), show a brief "Saved" confirmation somewhere on the panel — bottom-right suggested — that appears and fades out on its own.
  3. If an autosave fails, show a warning so the user knows the change wasn't persisted, rather than silently discarding it. This matters more than usual here precisely because there's no explicit "Save" click left to fail loudly against — without an error path, a failed autosave is invisible and the user has no cue to retry.

Implementation notes

  • There's already a global toast system (frontend/src/components/Toast/ToastManager.tsx, backed by @radix-ui/react-toast) used for e.g. WebSocket-driven notifications. Worth deciding whether "Saved"/failure feedback reuses that global toast, or whether a lighter, panel-local indicator (scoped to the open modal/panel rather than the whole app) reads better here — flag the choice made in the PR.
  • Currently there's no error handling at all on this path: useUpdateTask (frontend/src/hooks/useTasks.ts:31-40) only wires an onSuccess (cache invalidation) with no onError — a failed updateTask.mutate(...) call today fails silently. The equivalent update hooks for the other four panels should be checked too; add onError handling (or use the mutation's isError/error state) to drive the failure feedback, and check whether the field should revert to its last-saved value or stay showing the user's (unsaved) edit while surfacing the warning.
  • handleEditSave currently gates the name-field commit behind the "Save" button; look at how usePlayerItemListControls.ts and the panel-specific hooks (e.g. useTasksPanel.tsx's updateTask mutation) already wire up autosave for the other fields and follow the same pattern for the name field.
  • Once name-field save is automatic, decide what (if anything) the "Save" button in the modal should still do — it may become redundant and could be removed in favor of just "Cancel"/"Close", but that's a call for the PR, not a hard requirement here.
  • Debounce/commit-on-blur (like the due-date field) is probably preferable to firing a request on every keystroke for the name field.

Scope

Touches shared PlayerItemList component (plus each panel's mutation hook for the error-handling piece), so the fix applies to all five panels at once — no per-panel duplication needed for the modal/UI changes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Status
    Staging review

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions