@critical-path/react 0.1.3 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @critical-path/react
2
2
 
3
+ ## 0.1.6
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [4b92228]
8
+ - @critical-path/core@0.3.0
9
+ - @critical-path/client@0.1.5
10
+
11
+ ## 0.1.5
12
+
13
+ ### Patch Changes
14
+
15
+ - 3470b61: add optimistic updates with error rollback to Svelte state classes and React hooks
16
+
17
+ ## 0.1.4
18
+
19
+ ### Patch Changes
20
+
21
+ - Updated dependencies [df22aad]
22
+ - @critical-path/core@0.2.1
23
+ - @critical-path/client@0.1.4
24
+
3
25
  ## 0.1.3
4
26
 
5
27
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGrE,wBAAgB,WAAW;;;;;2BAuBW,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC;EAOpF;AAED,wBAAgB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM;;;;;wBAuBR,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC;+BAMrC,MAAM,UAAU,UAAU;yBAMhC,MAAM;EAMzC;AAED,wBAAgB,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM;;;;;;uBAYV,MAAM,gBAAgB,UAAU;wBAhC/B,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC;EAqC9E"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGrE,wBAAgB,WAAW;;;;;2BAuBW,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC;EAyBpF;AAED,wBAAgB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM;;;;;wBAuBR,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC;+BAwBrC,MAAM,UAAU,UAAU;yBA4BhC,MAAM;EA+BzC;AAED,wBAAgB,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM;;;;;;uBAYV,MAAM,gBAAgB,UAAU;wBAjG/B,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC;EAsG9E"}
package/dist/hooks.js CHANGED
@@ -23,9 +23,26 @@ export function useProjects() {
23
23
  fetchProjects();
24
24
  }, [fetchProjects]);
25
25
  const createProject = async (input) => {
26
- const created = await client.createProject(input);
27
- setProjects((prev) => [...prev, created]);
28
- return created;
26
+ const tempId = `temp_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;
27
+ const now = new Date().toISOString();
28
+ const tempProject = {
29
+ ...input,
30
+ id: tempId,
31
+ createdAt: now,
32
+ updatedAt: now
33
+ };
34
+ setProjects((prev) => [...prev, tempProject]);
35
+ try {
36
+ const created = await client.createProject(input);
37
+ setProjects((prev) => prev.map((p) => (p.id === tempId ? created : p)));
38
+ return created;
39
+ }
40
+ catch (err) {
41
+ setProjects((prev) => prev.filter((p) => p.id !== tempId));
42
+ const errorObj = err instanceof Error ? err : new Error(String(err));
43
+ setError(errorObj);
44
+ throw errorObj;
45
+ }
29
46
  };
30
47
  return { projects, loading, error, refresh: fetchProjects, createProject };
31
48
  }
@@ -52,18 +69,79 @@ export function useTasks(projectId) {
52
69
  fetchTasks();
53
70
  }, [fetchTasks]);
54
71
  const createTask = async (input) => {
55
- const created = await client.createTask(input);
56
- setTasks((prev) => [...prev, created]);
57
- return created;
72
+ const tempId = `temp_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;
73
+ const now = new Date().toISOString();
74
+ const tempTask = {
75
+ ...input,
76
+ id: tempId,
77
+ createdAt: now,
78
+ updatedAt: now
79
+ };
80
+ setTasks((prev) => [...prev, tempTask]);
81
+ try {
82
+ const created = await client.createTask(input);
83
+ setTasks((prev) => prev.map((t) => (t.id === tempId ? created : t)));
84
+ return created;
85
+ }
86
+ catch (err) {
87
+ setTasks((prev) => prev.filter((t) => t.id !== tempId));
88
+ const errorObj = err instanceof Error ? err : new Error(String(err));
89
+ setError(errorObj);
90
+ throw errorObj;
91
+ }
58
92
  };
59
93
  const updateTaskStatus = async (taskId, status) => {
60
- const updated = await client.updateTask(taskId, { status });
61
- setTasks((prev) => prev.map((t) => (t.id === taskId ? updated : t)));
62
- return updated;
94
+ let previousTask;
95
+ setTasks((prev) => {
96
+ previousTask = prev.find((t) => t.id === taskId);
97
+ if (!previousTask)
98
+ return prev;
99
+ return prev.map((t) => t.id === taskId
100
+ ? { ...t, status, updatedAt: new Date().toISOString() }
101
+ : t);
102
+ });
103
+ try {
104
+ const updated = await client.updateTask(taskId, { status });
105
+ setTasks((prev) => prev.map((t) => (t.id === taskId ? updated : t)));
106
+ return updated;
107
+ }
108
+ catch (err) {
109
+ if (previousTask) {
110
+ const revertTask = previousTask;
111
+ setTasks((prev) => prev.map((t) => (t.id === taskId ? revertTask : t)));
112
+ }
113
+ const errorObj = err instanceof Error ? err : new Error(String(err));
114
+ setError(errorObj);
115
+ throw errorObj;
116
+ }
63
117
  };
64
118
  const deleteTask = async (taskId) => {
65
- await client.deleteTask(taskId);
66
- setTasks((prev) => prev.filter((t) => t.id !== taskId));
119
+ let previousTask;
120
+ let previousIndex = -1;
121
+ setTasks((prev) => {
122
+ previousIndex = prev.findIndex((t) => t.id === taskId);
123
+ if (previousIndex !== -1) {
124
+ previousTask = prev[previousIndex];
125
+ }
126
+ return prev.filter((t) => t.id !== taskId);
127
+ });
128
+ try {
129
+ await client.deleteTask(taskId);
130
+ }
131
+ catch (err) {
132
+ if (previousTask && previousIndex !== -1) {
133
+ const restoreTask = previousTask;
134
+ const indexToInsert = previousIndex;
135
+ setTasks((prev) => {
136
+ const restored = [...prev];
137
+ restored.splice(indexToInsert, 0, restoreTask);
138
+ return restored;
139
+ });
140
+ }
141
+ const errorObj = err instanceof Error ? err : new Error(String(err));
142
+ setError(errorObj);
143
+ throw errorObj;
144
+ }
67
145
  };
68
146
  return { tasks, loading, error, refresh: fetchTasks, createTask, updateTaskStatus, deleteTask };
69
147
  }
package/dist/hooks.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEtD,MAAM,UAAU,WAAW;IACzB,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;IACvC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAY,EAAE,CAAC,CAAC;IACxD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAEvD,MAAM,aAAa,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC3C,IAAI,CAAC;YACH,UAAU,CAAC,IAAI,CAAC,CAAC;YACjB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;YACxC,WAAW,CAAC,IAAI,CAAC,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;gBAAS,CAAC;YACT,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,SAAS,CAAC,GAAG,EAAE;QACb,aAAa,EAAE,CAAC;IAClB,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAEpB,MAAM,aAAa,GAAG,KAAK,EAAE,KAAsD,EAAE,EAAE;QACrF,MAAM,MAAM,GAAG,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAClF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,WAAW,GAAY;YAC3B,GAAG,KAAK;YACR,EAAE,EAAE,MAAM;YACV,SAAS,EAAE,GAAG;YACd,SAAS,EAAE,GAAG;SACf,CAAC;QAEF,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;QAE9C,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAClD,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxE,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC;YAC3D,MAAM,QAAQ,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACrE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnB,MAAM,QAAQ,CAAC;QACjB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,SAAkB;IACzC,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;IACvC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAS,EAAE,CAAC,CAAC;IAC/C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAEvD,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACxC,IAAI,CAAC;YACH,UAAU,CAAC,IAAI,CAAC,CAAC;YACjB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YAC9C,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;gBAAS,CAAC;YACT,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAExB,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,EAAE,CAAC;IACf,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,MAAM,UAAU,GAAG,KAAK,EAAE,KAAmD,EAAE,EAAE;QAC/E,MAAM,MAAM,GAAG,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAClF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAS;YACrB,GAAG,KAAK;YACR,EAAE,EAAE,MAAM;YACV,SAAS,EAAE,GAAG;YACd,SAAS,EAAE,GAAG;SACf,CAAC;QAEF,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;QAExC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YAC/C,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACrE,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC;YACxD,MAAM,QAAQ,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACrE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnB,MAAM,QAAQ,CAAC;QACjB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,gBAAgB,GAAG,KAAK,EAAE,MAAc,EAAE,MAAkB,EAAE,EAAE;QACpE,IAAI,YAA8B,CAAC;QAEnC,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE;YAChB,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;YACjD,IAAI,CAAC,YAAY;gBAAE,OAAO,IAAI,CAAC;YAC/B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACpB,CAAC,CAAC,EAAE,KAAK,MAAM;gBACb,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE;gBACvD,CAAC,CAAC,CAAC,CACN,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAC5D,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACrE,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,UAAU,GAAG,YAAY,CAAC;gBAChC,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1E,CAAC;YACD,MAAM,QAAQ,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACrE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnB,MAAM,QAAQ,CAAC;QACjB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE;QAC1C,IAAI,YAA8B,CAAC;QACnC,IAAI,aAAa,GAAG,CAAC,CAAC,CAAC;QAEvB,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE;YAChB,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;YACvD,IAAI,aAAa,KAAK,CAAC,CAAC,EAAE,CAAC;gBACzB,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;YACrC,CAAC;YACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,YAAY,IAAI,aAAa,KAAK,CAAC,CAAC,EAAE,CAAC;gBACzC,MAAM,WAAW,GAAG,YAAY,CAAC;gBACjC,MAAM,aAAa,GAAG,aAAa,CAAC;gBACpC,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE;oBAChB,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;oBAC3B,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC;oBAC/C,OAAO,QAAQ,CAAC;gBAClB,CAAC,CAAC,CAAC;YACL,CAAC;YACD,MAAM,QAAQ,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACrE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnB,MAAM,QAAQ,CAAC;QACjB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC;AAClG,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,SAAkB;IAC1C,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IAE7F,MAAM,OAAO,GAA+B;QAC1C,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC;QACpD,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC;QAC9C,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC;QAC5D,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC;QACxD,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC;QAC9C,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC;KACvD,CAAC;IAEF,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAE,YAAwB,EAAE,EAAE;QAClE,OAAO,gBAAgB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAChD,CAAC,CAAC;IAEF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;AAC3E,CAAC"}
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "@critical-path/react",
3
- "version": "0.1.3",
3
+ "version": "0.1.6",
4
4
  "description": "React Context Provider and Hooks for Critical Path headless project management framework",
5
5
  "author": "Jack James",
6
6
  "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/Pixerate/critical-path.git"
10
+ },
7
11
  "type": "module",
8
12
  "main": "./dist/index.js",
9
13
  "types": "./dist/index.d.ts",
@@ -14,8 +18,8 @@
14
18
  }
15
19
  },
16
20
  "dependencies": {
17
- "@critical-path/client": "0.1.3",
18
- "@critical-path/core": "0.2.0"
21
+ "@critical-path/client": "0.1.5",
22
+ "@critical-path/core": "0.3.0"
19
23
  },
20
24
  "peerDependencies": {
21
25
  "react": "^18.0.0 || ^19.0.0"
package/src/hooks.ts CHANGED
@@ -26,9 +26,27 @@ export function useProjects() {
26
26
  }, [fetchProjects]);
27
27
 
28
28
  const createProject = async (input: Omit<Project, 'id' | 'createdAt' | 'updatedAt'>) => {
29
- const created = await client.createProject(input);
30
- setProjects((prev) => [...prev, created]);
31
- return created;
29
+ const tempId = `temp_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;
30
+ const now = new Date().toISOString();
31
+ const tempProject: Project = {
32
+ ...input,
33
+ id: tempId,
34
+ createdAt: now,
35
+ updatedAt: now
36
+ };
37
+
38
+ setProjects((prev) => [...prev, tempProject]);
39
+
40
+ try {
41
+ const created = await client.createProject(input);
42
+ setProjects((prev) => prev.map((p) => (p.id === tempId ? created : p)));
43
+ return created;
44
+ } catch (err) {
45
+ setProjects((prev) => prev.filter((p) => p.id !== tempId));
46
+ const errorObj = err instanceof Error ? err : new Error(String(err));
47
+ setError(errorObj);
48
+ throw errorObj;
49
+ }
32
50
  };
33
51
 
34
52
  return { projects, loading, error, refresh: fetchProjects, createProject };
@@ -58,20 +76,85 @@ export function useTasks(projectId?: string) {
58
76
  }, [fetchTasks]);
59
77
 
60
78
  const createTask = async (input: Omit<Task, 'id' | 'createdAt' | 'updatedAt'>) => {
61
- const created = await client.createTask(input);
62
- setTasks((prev) => [...prev, created]);
63
- return created;
79
+ const tempId = `temp_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;
80
+ const now = new Date().toISOString();
81
+ const tempTask: Task = {
82
+ ...input,
83
+ id: tempId,
84
+ createdAt: now,
85
+ updatedAt: now
86
+ };
87
+
88
+ setTasks((prev) => [...prev, tempTask]);
89
+
90
+ try {
91
+ const created = await client.createTask(input);
92
+ setTasks((prev) => prev.map((t) => (t.id === tempId ? created : t)));
93
+ return created;
94
+ } catch (err) {
95
+ setTasks((prev) => prev.filter((t) => t.id !== tempId));
96
+ const errorObj = err instanceof Error ? err : new Error(String(err));
97
+ setError(errorObj);
98
+ throw errorObj;
99
+ }
64
100
  };
65
101
 
66
102
  const updateTaskStatus = async (taskId: string, status: TaskStatus) => {
67
- const updated = await client.updateTask(taskId, { status });
68
- setTasks((prev) => prev.map((t) => (t.id === taskId ? updated : t)));
69
- return updated;
103
+ let previousTask: Task | undefined;
104
+
105
+ setTasks((prev) => {
106
+ previousTask = prev.find((t) => t.id === taskId);
107
+ if (!previousTask) return prev;
108
+ return prev.map((t) =>
109
+ t.id === taskId
110
+ ? { ...t, status, updatedAt: new Date().toISOString() }
111
+ : t
112
+ );
113
+ });
114
+
115
+ try {
116
+ const updated = await client.updateTask(taskId, { status });
117
+ setTasks((prev) => prev.map((t) => (t.id === taskId ? updated : t)));
118
+ return updated;
119
+ } catch (err) {
120
+ if (previousTask) {
121
+ const revertTask = previousTask;
122
+ setTasks((prev) => prev.map((t) => (t.id === taskId ? revertTask : t)));
123
+ }
124
+ const errorObj = err instanceof Error ? err : new Error(String(err));
125
+ setError(errorObj);
126
+ throw errorObj;
127
+ }
70
128
  };
71
129
 
72
130
  const deleteTask = async (taskId: string) => {
73
- await client.deleteTask(taskId);
74
- setTasks((prev) => prev.filter((t) => t.id !== taskId));
131
+ let previousTask: Task | undefined;
132
+ let previousIndex = -1;
133
+
134
+ setTasks((prev) => {
135
+ previousIndex = prev.findIndex((t) => t.id === taskId);
136
+ if (previousIndex !== -1) {
137
+ previousTask = prev[previousIndex];
138
+ }
139
+ return prev.filter((t) => t.id !== taskId);
140
+ });
141
+
142
+ try {
143
+ await client.deleteTask(taskId);
144
+ } catch (err) {
145
+ if (previousTask && previousIndex !== -1) {
146
+ const restoreTask = previousTask;
147
+ const indexToInsert = previousIndex;
148
+ setTasks((prev) => {
149
+ const restored = [...prev];
150
+ restored.splice(indexToInsert, 0, restoreTask);
151
+ return restored;
152
+ });
153
+ }
154
+ const errorObj = err instanceof Error ? err : new Error(String(err));
155
+ setError(errorObj);
156
+ throw errorObj;
157
+ }
75
158
  };
76
159
 
77
160
  return { tasks, loading, error, refresh: fetchTasks, createTask, updateTaskStatus, deleteTask };