Skip to content

fix: resolve clients/projects save failures with three targeted fixes#154

Merged
AdamJ merged 2 commits into
mainfrom
claude/clients-projects-save-bug-oDErQ
May 30, 2026
Merged

fix: resolve clients/projects save failures with three targeted fixes#154
AdamJ merged 2 commits into
mainfrom
claude/clients-projects-save-bug-oDErQ

Conversation

@AdamJ
Copy link
Copy Markdown
Owner

@AdamJ AdamJ commented May 30, 2026

Bug 1 — stale closure in forceSyncToDatabase:
ProjectList.tsx calls addProject/updateProject/archiveProject and then
immediately awaits forceSyncToDatabase(). Because React state updates are
asynchronous, the projects captured in forceSyncToDatabase's useCallback
closure is the pre-mutation list — so the just-added/changed project is
never included in the save. Fix: add a projectsRef (mirroring the existing
clientsRef pattern) that is updated synchronously in every project mutation
and during loadData. forceSyncToDatabase now reads projectsRef.current
instead of the closure variable, and projects is removed from its dep
array.

Bug 2 — client mutations wrongly set hasUnsavedChanges:
addClient, archiveClient, and restoreClient called setHasUnsavedChanges(true)
even though callers immediately persist the change via persistClient /
persistClients. This left the save icon orange after every client operation
even when the data was already written. Since clients are excluded from
forceSyncToDatabase's bulk save, clearing hasUnsavedChanges via that path
was unrelated to whether the client data was safe. Fix: remove the
setHasUnsavedChanges(true) calls from the three client mutators.

Bug 3 — saved edits to default projects discarded on reload:
The project load merge always started from hardcoded defaults and only
appended saved projects whose name+client didn't match any default. A saved
modified default (same name+client, different hourlyRate or color) was
silently dropped and replaced by the hardcoded version. Fix: when a saved
project matches a default by name+client, replace the default entry with the
saved one rather than skipping it.

https://claude.ai/code/session_01K9hQPH6ddsadiAF19VGnJQ

claude added 2 commits May 30, 2026 20:44
Bug 1 — stale closure in forceSyncToDatabase:
ProjectList.tsx calls addProject/updateProject/archiveProject and then
immediately awaits forceSyncToDatabase(). Because React state updates are
asynchronous, the `projects` captured in forceSyncToDatabase's useCallback
closure is the pre-mutation list — so the just-added/changed project is
never included in the save. Fix: add a projectsRef (mirroring the existing
clientsRef pattern) that is updated synchronously in every project mutation
and during loadData. forceSyncToDatabase now reads projectsRef.current
instead of the closure variable, and `projects` is removed from its dep
array.

Bug 2 — client mutations wrongly set hasUnsavedChanges:
addClient, archiveClient, and restoreClient called setHasUnsavedChanges(true)
even though callers immediately persist the change via persistClient /
persistClients. This left the save icon orange after every client operation
even when the data was already written. Since clients are excluded from
forceSyncToDatabase's bulk save, clearing hasUnsavedChanges via that path
was unrelated to whether the client data was safe. Fix: remove the
setHasUnsavedChanges(true) calls from the three client mutators.

Bug 3 — saved edits to default projects discarded on reload:
The project load merge always started from hardcoded defaults and only
appended saved projects whose name+client didn't match any default. A saved
modified default (same name+client, different hourlyRate or color) was
silently dropped and replaced by the hardcoded version. Fix: when a saved
project matches a default by name+client, replace the default entry with the
saved one rather than skipping it.

https://claude.ai/code/session_01K9hQPH6ddsadiAF19VGnJQ
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label May 30, 2026
@AdamJ AdamJ added the fix For general fixes or bundled fixes label May 30, 2026
@github-project-automation github-project-automation Bot moved this to To triage in TimeTrackerPro May 30, 2026
@AdamJ AdamJ moved this from To triage to In review in TimeTrackerPro May 30, 2026
@AdamJ AdamJ merged commit 61c8ac6 into main May 30, 2026
3 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in TimeTrackerPro May 30, 2026
@AdamJ AdamJ deleted the claude/clients-projects-save-bug-oDErQ branch May 30, 2026 21:16
AdamJ pushed a commit that referenced this pull request May 31, 2026
…tabase

forceSyncToDatabase was closing over the React state value `plannedTasks`
(initially []) rather than `plannedTasksRef.current`. If the function fired
before the initial Supabase load completed (e.g. online event, manual sync
button, category/project save in another component), it called
savePlannedTasks([]) which hit the delete-all branch and wiped the table.

Mirrors the projectsRef fix from #154: update plannedTasksRef.current
synchronously in loadData and in every mutation (addPlannedTask,
updatePlannedTask, deletePlannedTask, movePlannedTask, pullPlannedTaskToDay),
use plannedTasksRef.current in forceSyncToDatabase, and drop plannedTasks
from its dependency array.

https://claude.ai/code/session_01CJG4Vxc5RpXbuF1NuWF4cG
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation fix For general fixes or bundled fixes

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants