@ram_28/kf-ai-sdk 2.0.14 → 2.0.16
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/README.md +10 -9
- package/dist/FileField-BWrSHNRq.js +296 -0
- package/dist/FileField-eDeuzln8.cjs +1 -0
- package/dist/api.cjs +1 -1
- package/dist/api.mjs +2 -2
- package/dist/auth.cjs +1 -1
- package/dist/auth.mjs +1 -1
- package/dist/bdo/core/BaseBdo.d.ts +1 -1
- package/dist/bdo.cjs +1 -1
- package/dist/bdo.mjs +230 -474
- package/dist/{client-DnO2KKrw.cjs → client-D5k4SYuw.cjs} +1 -1
- package/dist/{client-iQTqFDNI.js → client-_ayziI1d.js} +33 -32
- package/dist/components/hooks/index.d.ts +9 -3
- package/dist/components/hooks/index.d.ts.map +1 -1
- package/dist/{workflow/components → components/hooks}/useActivityForm/createActivityItemProxy.d.ts +9 -5
- package/dist/components/hooks/useActivityForm/createActivityItemProxy.d.ts.map +1 -0
- package/dist/components/hooks/useActivityForm/createActivityResolver.d.ts +23 -0
- package/dist/components/hooks/useActivityForm/createActivityResolver.d.ts.map +1 -0
- package/dist/components/hooks/useActivityForm/index.d.ts.map +1 -0
- package/dist/{workflow/components → components/hooks}/useActivityForm/types.d.ts +12 -8
- package/dist/components/hooks/useActivityForm/types.d.ts.map +1 -0
- package/dist/{workflow/components → components/hooks}/useActivityForm/useActivityForm.d.ts +2 -2
- package/dist/components/hooks/useActivityForm/useActivityForm.d.ts.map +1 -0
- package/dist/components/hooks/useActivityTable/index.d.ts +4 -0
- package/dist/components/hooks/useActivityTable/index.d.ts.map +1 -0
- package/dist/components/hooks/useActivityTable/types.d.ts +36 -0
- package/dist/components/hooks/useActivityTable/types.d.ts.map +1 -0
- package/dist/components/hooks/useActivityTable/useActivityTable.d.ts +4 -0
- package/dist/components/hooks/useActivityTable/useActivityTable.d.ts.map +1 -0
- package/dist/components/hooks/useBDOForm/createItemProxy.d.ts.map +1 -0
- package/dist/components/hooks/useBDOForm/createResolver.d.ts.map +1 -0
- package/dist/components/hooks/useBDOForm/index.d.ts +6 -0
- package/dist/components/hooks/useBDOForm/index.d.ts.map +1 -0
- package/dist/components/hooks/useBDOForm/shared.d.ts +50 -0
- package/dist/components/hooks/useBDOForm/shared.d.ts.map +1 -0
- package/dist/components/hooks/{useForm → useBDOForm}/types.d.ts +6 -6
- package/dist/components/hooks/useBDOForm/types.d.ts.map +1 -0
- package/dist/components/hooks/{useForm/useForm.d.ts → useBDOForm/useBDOForm.d.ts} +4 -4
- package/dist/components/hooks/useBDOForm/useBDOForm.d.ts.map +1 -0
- package/dist/components/hooks/useBDOTable/index.d.ts +3 -0
- package/dist/components/hooks/useBDOTable/index.d.ts.map +1 -0
- package/dist/components/hooks/useBDOTable/types.d.ts +24 -0
- package/dist/components/hooks/useBDOTable/types.d.ts.map +1 -0
- package/dist/components/hooks/useBDOTable/useBDOTable.d.ts +3 -0
- package/dist/components/hooks/useBDOTable/useBDOTable.d.ts.map +1 -0
- package/dist/components/hooks/useTable/index.d.ts +2 -2
- package/dist/components/hooks/useTable/index.d.ts.map +1 -1
- package/dist/components/hooks/useTable/types.d.ts +11 -10
- package/dist/components/hooks/useTable/types.d.ts.map +1 -1
- package/dist/components/hooks/useTable/useTable.d.ts +1 -1
- package/dist/components/hooks/useTable/useTable.d.ts.map +1 -1
- package/dist/form.cjs +1 -1
- package/dist/form.d.ts +1 -1
- package/dist/form.d.ts.map +1 -1
- package/dist/form.mjs +279 -344
- package/dist/form.types.d.ts +1 -1
- package/dist/form.types.d.ts.map +1 -1
- package/dist/{metadata-DpfI3zRN.js → metadata-Cc1mBcLS.js} +1 -1
- package/dist/{metadata-DgLSJkF5.cjs → metadata-DWXQPDav.cjs} +1 -1
- package/dist/shared-5a7UkED1.js +1180 -0
- package/dist/shared-nnmlRVs7.cjs +1 -0
- package/dist/table.cjs +1 -1
- package/dist/table.d.ts +1 -0
- package/dist/table.d.ts.map +1 -1
- package/dist/table.mjs +17 -192
- package/dist/table.types.d.ts +2 -1
- package/dist/table.types.d.ts.map +1 -1
- package/dist/types/base-fields.d.ts +4 -4
- package/dist/types/base-fields.d.ts.map +1 -1
- package/dist/types/constants.d.ts +3 -3
- package/dist/useTable-CeRklbdT.cjs +1 -0
- package/dist/useTable-DS0-WInw.js +203 -0
- package/dist/workflow/Activity.d.ts +19 -7
- package/dist/workflow/Activity.d.ts.map +1 -1
- package/dist/workflow/client.d.ts +2 -2
- package/dist/workflow/client.d.ts.map +1 -1
- package/dist/workflow/createFieldFromMeta.d.ts +29 -0
- package/dist/workflow/createFieldFromMeta.d.ts.map +1 -0
- package/dist/workflow/index.d.ts +1 -2
- package/dist/workflow/index.d.ts.map +1 -1
- package/dist/workflow/types.d.ts +16 -12
- package/dist/workflow/types.d.ts.map +1 -1
- package/dist/workflow.cjs +1 -1
- package/dist/workflow.d.ts +5 -2
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.mjs +687 -352
- package/dist/workflow.types.d.ts +1 -0
- package/dist/workflow.types.d.ts.map +1 -1
- package/docs/bdo.md +1 -1
- package/docs/gaps.md +360 -0
- package/docs/useActivityForm.md +393 -0
- package/docs/useActivityTable.md +418 -0
- package/docs/{useForm.md → useBDOForm.md} +24 -24
- package/docs/useBDOTable.md +284 -0
- package/docs/workflow.md +148 -297
- package/package.json +2 -2
- package/sdk/bdo/core/BaseBdo.ts +2 -2
- package/sdk/bdo/fields/UserField.ts +1 -1
- package/sdk/components/hooks/index.ts +28 -5
- package/sdk/components/hooks/useActivityForm/createActivityItemProxy.ts +400 -0
- package/sdk/components/hooks/useActivityForm/createActivityResolver.ts +87 -0
- package/sdk/{workflow/components → components/hooks}/useActivityForm/types.ts +24 -11
- package/sdk/components/hooks/useActivityForm/useActivityForm.ts +478 -0
- package/sdk/components/hooks/useActivityTable/index.ts +8 -0
- package/sdk/components/hooks/useActivityTable/types.ts +47 -0
- package/sdk/components/hooks/useActivityTable/useActivityTable.ts +40 -0
- package/sdk/components/hooks/{useForm → useBDOForm}/index.ts +4 -3
- package/sdk/components/hooks/useBDOForm/shared.ts +250 -0
- package/sdk/components/hooks/{useForm → useBDOForm}/types.ts +9 -9
- package/sdk/components/hooks/{useForm/useForm.ts → useBDOForm/useBDOForm.ts} +70 -96
- package/sdk/components/hooks/useBDOTable/index.ts +2 -0
- package/sdk/components/hooks/useBDOTable/types.ts +22 -0
- package/sdk/components/hooks/useBDOTable/useBDOTable.ts +16 -0
- package/sdk/components/hooks/useTable/index.ts +3 -3
- package/sdk/components/hooks/useTable/types.ts +16 -12
- package/sdk/components/hooks/useTable/useTable.ts +56 -49
- package/sdk/form.ts +2 -2
- package/sdk/form.types.ts +4 -4
- package/sdk/table.ts +4 -1
- package/sdk/table.types.ts +7 -4
- package/sdk/types/base-fields.ts +4 -4
- package/sdk/types/constants.ts +3 -3
- package/sdk/workflow/Activity.ts +36 -12
- package/sdk/workflow/client.ts +65 -12
- package/sdk/workflow/createFieldFromMeta.ts +110 -0
- package/sdk/workflow/index.ts +1 -6
- package/sdk/workflow/types.ts +20 -11
- package/sdk/workflow.ts +11 -2
- package/sdk/workflow.types.ts +7 -0
- package/dist/BaseField-B6da88U7.js +0 -40
- package/dist/BaseField-Drp0-OxL.cjs +0 -1
- package/dist/components/hooks/useForm/createItemProxy.d.ts.map +0 -1
- package/dist/components/hooks/useForm/createResolver.d.ts.map +0 -1
- package/dist/components/hooks/useForm/index.d.ts +0 -5
- package/dist/components/hooks/useForm/index.d.ts.map +0 -1
- package/dist/components/hooks/useForm/types.d.ts.map +0 -1
- package/dist/components/hooks/useForm/useForm.d.ts.map +0 -1
- package/dist/error-handling-CAoD0Kwb.cjs +0 -1
- package/dist/error-handling-CrhTtD88.js +0 -14
- package/dist/index.esm-Cj63v5ny.js +0 -1014
- package/dist/index.esm-DuwT11sx.cjs +0 -1
- package/dist/workflow/components/useActivityForm/createActivityItemProxy.d.ts.map +0 -1
- package/dist/workflow/components/useActivityForm/createActivityResolver.d.ts +0 -22
- package/dist/workflow/components/useActivityForm/createActivityResolver.d.ts.map +0 -1
- package/dist/workflow/components/useActivityForm/index.d.ts.map +0 -1
- package/dist/workflow/components/useActivityForm/types.d.ts.map +0 -1
- package/dist/workflow/components/useActivityForm/useActivityForm.d.ts.map +0 -1
- package/docs/useTable.md +0 -369
- package/sdk/workflow/components/useActivityForm/createActivityItemProxy.ts +0 -130
- package/sdk/workflow/components/useActivityForm/createActivityResolver.ts +0 -61
- package/sdk/workflow/components/useActivityForm/useActivityForm.ts +0 -386
- /package/dist/{workflow/components → components/hooks}/useActivityForm/index.d.ts +0 -0
- /package/dist/components/hooks/{useForm → useBDOForm}/createItemProxy.d.ts +0 -0
- /package/dist/components/hooks/{useForm → useBDOForm}/createResolver.d.ts +0 -0
- /package/sdk/{workflow/components → components/hooks}/useActivityForm/index.ts +0 -0
- /package/sdk/components/hooks/{useForm → useBDOForm}/createItemProxy.ts +0 -0
- /package/sdk/components/hooks/{useForm → useBDOForm}/createResolver.ts +0 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
# useActivityTable
|
|
2
|
+
|
|
3
|
+
Hook for listing workflow activity (business process) instances with search, sort, filter, and pagination.
|
|
4
|
+
|
|
5
|
+
## Imports
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { useActivityTable, ActivityTableStatus } from "@ram_28/kf-ai-sdk/workflow";
|
|
9
|
+
import type {
|
|
10
|
+
UseActivityTableOptionsType,
|
|
11
|
+
UseActivityTableReturnType,
|
|
12
|
+
ActivityRowType,
|
|
13
|
+
ActivityInstanceFieldsType,
|
|
14
|
+
} from "@ram_28/kf-ai-sdk/workflow";
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Common Mistakes (READ FIRST)
|
|
20
|
+
|
|
21
|
+
### 1. Passing a Workflow instead of an Activity
|
|
22
|
+
|
|
23
|
+
The `activity` property must be an `Activity` instance, not a `Workflow` instance.
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
// ❌ WRONG — passing the workflow class
|
|
27
|
+
const wf = new SimpleLeaveProcess();
|
|
28
|
+
useActivityTable({ activity: wf, status: ActivityTableStatus.InProgress });
|
|
29
|
+
|
|
30
|
+
// ✅ CORRECT — pass the activity instance
|
|
31
|
+
const activity = new SimpleLeaveProcess().employeeInputActivity();
|
|
32
|
+
useActivityTable({ activity, status: ActivityTableStatus.InProgress });
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 2. Using string literals instead of ActivityTableStatus
|
|
36
|
+
|
|
37
|
+
While string literals work at runtime, always use the `ActivityTableStatus` constant for type safety and readability.
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
// ❌ WRONG — raw string (no type safety, easy to typo)
|
|
41
|
+
useActivityTable({ activity, status: "inProgress" });
|
|
42
|
+
useActivityTable({ activity, status: "in_progress" });
|
|
43
|
+
|
|
44
|
+
// ✅ CORRECT — use the constant
|
|
45
|
+
useActivityTable({ activity, status: ActivityTableStatus.InProgress });
|
|
46
|
+
useActivityTable({ activity, status: ActivityTableStatus.Completed });
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 3. Forgetting to memoize the activity instance
|
|
50
|
+
|
|
51
|
+
Like BDO instances passed to `useBDOTable`, the activity instance should be memoized to prevent unnecessary re-renders and refetches.
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
// ❌ WRONG — creates a new activity on every render
|
|
55
|
+
const activity = new SimpleLeaveProcess().employeeInputActivity();
|
|
56
|
+
useActivityTable({ activity, status: ActivityTableStatus.InProgress });
|
|
57
|
+
|
|
58
|
+
// ✅ CORRECT — memoize with useMemo
|
|
59
|
+
const activity = useMemo(
|
|
60
|
+
() => new SimpleLeaveProcess().employeeInputActivity(),
|
|
61
|
+
[],
|
|
62
|
+
);
|
|
63
|
+
useActivityTable({ activity, status: ActivityTableStatus.InProgress });
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 4. Calling `.get()` on activity table rows
|
|
67
|
+
|
|
68
|
+
Table rows are plain objects, not `ActivityInstance` proxies. There is no `.get()` method.
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// ❌ WRONG — rows are plain objects
|
|
72
|
+
row.StartDate.get();
|
|
73
|
+
row.Status.get();
|
|
74
|
+
|
|
75
|
+
// ✅ CORRECT — access values directly
|
|
76
|
+
row.StartDate;
|
|
77
|
+
row.Status;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Example: Employee Leave Request Table
|
|
83
|
+
|
|
84
|
+
Display in-progress leave requests with search, pagination, and a detail view.
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import { useMemo, useState } from "react";
|
|
88
|
+
import { useActivityTable, ActivityTableStatus } from "@ram_28/kf-ai-sdk/workflow";
|
|
89
|
+
import type { ActivityRowType } from "@ram_28/kf-ai-sdk/workflow";
|
|
90
|
+
import {
|
|
91
|
+
SimpleLeaveProcess,
|
|
92
|
+
EmployeeInputActivity,
|
|
93
|
+
} from "@/bdo/workflows/SimpleLeaveProcess";
|
|
94
|
+
|
|
95
|
+
function EmployeeLeaveTable() {
|
|
96
|
+
const activity = useMemo(() => new SimpleLeaveProcess().employeeInputActivity(), []);
|
|
97
|
+
const [selectedId, setSelectedId] = useState<string | null>(null);
|
|
98
|
+
|
|
99
|
+
const {
|
|
100
|
+
rows,
|
|
101
|
+
totalItems,
|
|
102
|
+
isLoading,
|
|
103
|
+
isFetching,
|
|
104
|
+
error,
|
|
105
|
+
search,
|
|
106
|
+
sort,
|
|
107
|
+
pagination,
|
|
108
|
+
refetch,
|
|
109
|
+
} = useActivityTable({
|
|
110
|
+
activity,
|
|
111
|
+
status: ActivityTableStatus.InProgress,
|
|
112
|
+
initialState: {
|
|
113
|
+
pagination: { pageNo: 1, pageSize: 10 },
|
|
114
|
+
},
|
|
115
|
+
onError: (err) => console.error("Failed to load leave requests:", err.message),
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
if (isLoading) return <div>Loading...</div>;
|
|
119
|
+
if (error) return <div>Error: {error.message}</div>;
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<div>
|
|
123
|
+
<h2>My Leave Requests ({totalItems})</h2>
|
|
124
|
+
|
|
125
|
+
{/* Search */}
|
|
126
|
+
<div>
|
|
127
|
+
<input
|
|
128
|
+
type="text"
|
|
129
|
+
placeholder="Search by leave type..."
|
|
130
|
+
value={search.query}
|
|
131
|
+
onChange={(e) => search.set(activity.LeaveType.id, e.target.value)}
|
|
132
|
+
/>
|
|
133
|
+
{search.query && <button onClick={search.clear}>Clear</button>}
|
|
134
|
+
{isFetching && <span>Loading...</span>}
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
{/* Table */}
|
|
138
|
+
<table>
|
|
139
|
+
<thead>
|
|
140
|
+
<tr>
|
|
141
|
+
<th>ID</th>
|
|
142
|
+
<th>Status</th>
|
|
143
|
+
<th>Assigned To</th>
|
|
144
|
+
<th
|
|
145
|
+
style={{ cursor: "pointer" }}
|
|
146
|
+
onClick={() => sort.toggle(activity.LeaveType.id)}
|
|
147
|
+
>
|
|
148
|
+
Leave Type
|
|
149
|
+
</th>
|
|
150
|
+
<th>Start Date</th>
|
|
151
|
+
<th>End Date</th>
|
|
152
|
+
<th>Days</th>
|
|
153
|
+
<th>Action</th>
|
|
154
|
+
</tr>
|
|
155
|
+
</thead>
|
|
156
|
+
<tbody>
|
|
157
|
+
{rows.map((row) => (
|
|
158
|
+
<tr key={row._id}>
|
|
159
|
+
<td>{row._id}</td>
|
|
160
|
+
<td>{row.Status}</td>
|
|
161
|
+
<td>{row.AssignedTo.map((u) => u._name).join(", ")}</td>
|
|
162
|
+
<td>{row.LeaveType}</td>
|
|
163
|
+
<td>{row.StartDate}</td>
|
|
164
|
+
<td>{row.EndDate}</td>
|
|
165
|
+
<td>{row.LeaveDays}</td>
|
|
166
|
+
<td>
|
|
167
|
+
<button onClick={() => setSelectedId(row._id)}>View</button>
|
|
168
|
+
</td>
|
|
169
|
+
</tr>
|
|
170
|
+
))}
|
|
171
|
+
</tbody>
|
|
172
|
+
</table>
|
|
173
|
+
|
|
174
|
+
{/* Pagination */}
|
|
175
|
+
<div>
|
|
176
|
+
<button
|
|
177
|
+
onClick={pagination.goToPrevious}
|
|
178
|
+
disabled={!pagination.canGoPrevious}
|
|
179
|
+
>
|
|
180
|
+
Previous
|
|
181
|
+
</button>
|
|
182
|
+
<span>
|
|
183
|
+
Page {pagination.pageNo} of {pagination.totalPages}
|
|
184
|
+
</span>
|
|
185
|
+
<button
|
|
186
|
+
onClick={pagination.goToNext}
|
|
187
|
+
disabled={!pagination.canGoNext}
|
|
188
|
+
>
|
|
189
|
+
Next
|
|
190
|
+
</button>
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Example: Manager Approval Table
|
|
200
|
+
|
|
201
|
+
Display pending approvals with status tabs for in-progress and completed items.
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
import { useMemo, useState } from "react";
|
|
205
|
+
import {
|
|
206
|
+
useActivityTable,
|
|
207
|
+
ActivityTableStatus,
|
|
208
|
+
} from "@ram_28/kf-ai-sdk/workflow";
|
|
209
|
+
import type { ActivityRowType } from "@ram_28/kf-ai-sdk/workflow";
|
|
210
|
+
import { SimpleLeaveProcess } from "@/bdo/workflows/SimpleLeaveProcess";
|
|
211
|
+
|
|
212
|
+
type StatusTab = "inprogress" | "completed";
|
|
213
|
+
|
|
214
|
+
function ManagerApprovalTable() {
|
|
215
|
+
const activity = useMemo(
|
|
216
|
+
() => new SimpleLeaveProcess().managerApprovalActivity(),
|
|
217
|
+
[],
|
|
218
|
+
);
|
|
219
|
+
const [activeTab, setActiveTab] = useState<StatusTab>("inprogress");
|
|
220
|
+
const [selectedId, setSelectedId] = useState<string | null>(null);
|
|
221
|
+
|
|
222
|
+
const {
|
|
223
|
+
rows,
|
|
224
|
+
totalItems,
|
|
225
|
+
isLoading,
|
|
226
|
+
isFetching,
|
|
227
|
+
error,
|
|
228
|
+
search,
|
|
229
|
+
sort,
|
|
230
|
+
filter,
|
|
231
|
+
pagination,
|
|
232
|
+
refetch,
|
|
233
|
+
} = useActivityTable({
|
|
234
|
+
activity,
|
|
235
|
+
status: activeTab,
|
|
236
|
+
initialState: {
|
|
237
|
+
pagination: { pageNo: 1, pageSize: 10 },
|
|
238
|
+
},
|
|
239
|
+
onError: (err) => console.error("Fetch failed:", err.message),
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
if (selectedId) {
|
|
243
|
+
return (
|
|
244
|
+
<ApprovalForm
|
|
245
|
+
activityInstanceId={selectedId}
|
|
246
|
+
onComplete={() => {
|
|
247
|
+
setSelectedId(null);
|
|
248
|
+
refetch();
|
|
249
|
+
}}
|
|
250
|
+
/>
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return (
|
|
255
|
+
<div>
|
|
256
|
+
{/* Status tabs */}
|
|
257
|
+
<div>
|
|
258
|
+
<button
|
|
259
|
+
onClick={() => setActiveTab("inprogress")}
|
|
260
|
+
disabled={activeTab === "inprogress"}
|
|
261
|
+
>
|
|
262
|
+
Pending
|
|
263
|
+
</button>
|
|
264
|
+
<button
|
|
265
|
+
onClick={() => setActiveTab("completed")}
|
|
266
|
+
disabled={activeTab === "completed"}
|
|
267
|
+
>
|
|
268
|
+
Completed
|
|
269
|
+
</button>
|
|
270
|
+
</div>
|
|
271
|
+
|
|
272
|
+
<h2>
|
|
273
|
+
{activeTab === "inprogress" ? "Pending" : "Completed"} Approvals ({totalItems})
|
|
274
|
+
</h2>
|
|
275
|
+
|
|
276
|
+
{isLoading && <div>Loading...</div>}
|
|
277
|
+
{error && <div>Error: {error.message}</div>}
|
|
278
|
+
|
|
279
|
+
{/* Table */}
|
|
280
|
+
<table>
|
|
281
|
+
<thead>
|
|
282
|
+
<tr>
|
|
283
|
+
<th>ID</th>
|
|
284
|
+
<th
|
|
285
|
+
style={{ cursor: "pointer" }}
|
|
286
|
+
onClick={() => sort.toggle("Status")}
|
|
287
|
+
>
|
|
288
|
+
Status
|
|
289
|
+
{sort.field === "Status" && (
|
|
290
|
+
<span>{sort.direction === "ASC" ? " ↑" : " ↓"}</span>
|
|
291
|
+
)}
|
|
292
|
+
</th>
|
|
293
|
+
<th>Assigned To</th>
|
|
294
|
+
<th>Approved</th>
|
|
295
|
+
<th>Reason</th>
|
|
296
|
+
{activeTab === "inprogress" && <th>Action</th>}
|
|
297
|
+
</tr>
|
|
298
|
+
</thead>
|
|
299
|
+
<tbody>
|
|
300
|
+
{rows.map((row) => (
|
|
301
|
+
<tr key={row._id}>
|
|
302
|
+
<td>{row._id}</td>
|
|
303
|
+
<td>{row.Status}</td>
|
|
304
|
+
<td>{row.AssignedTo.map((u) => u._name).join(", ")}</td>
|
|
305
|
+
<td>{row.ManagerApproved ? "Yes" : "No"}</td>
|
|
306
|
+
<td>{row.ManagerReason}</td>
|
|
307
|
+
{activeTab === "inprogress" && (
|
|
308
|
+
<td>
|
|
309
|
+
<button onClick={() => setSelectedId(row._id)}>Review</button>
|
|
310
|
+
</td>
|
|
311
|
+
)}
|
|
312
|
+
</tr>
|
|
313
|
+
))}
|
|
314
|
+
</tbody>
|
|
315
|
+
</table>
|
|
316
|
+
|
|
317
|
+
{/* Pagination */}
|
|
318
|
+
<div>
|
|
319
|
+
<button
|
|
320
|
+
onClick={pagination.goToPrevious}
|
|
321
|
+
disabled={!pagination.canGoPrevious}
|
|
322
|
+
>
|
|
323
|
+
Previous
|
|
324
|
+
</button>
|
|
325
|
+
<span>
|
|
326
|
+
Page {pagination.pageNo} of {pagination.totalPages}
|
|
327
|
+
</span>
|
|
328
|
+
<button
|
|
329
|
+
onClick={pagination.goToNext}
|
|
330
|
+
disabled={!pagination.canGoNext}
|
|
331
|
+
>
|
|
332
|
+
Next
|
|
333
|
+
</button>
|
|
334
|
+
<select
|
|
335
|
+
value={pagination.pageSize}
|
|
336
|
+
onChange={(e) => pagination.setPageSize(Number(e.target.value))}
|
|
337
|
+
>
|
|
338
|
+
<option value={10}>10 per page</option>
|
|
339
|
+
<option value={25}>25 per page</option>
|
|
340
|
+
<option value={50}>50 per page</option>
|
|
341
|
+
</select>
|
|
342
|
+
</div>
|
|
343
|
+
</div>
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Type Definitions
|
|
351
|
+
|
|
352
|
+
### ActivityTableStatus
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
export const ActivityTableStatus = {
|
|
356
|
+
InProgress: "inprogress",
|
|
357
|
+
Completed: "completed",
|
|
358
|
+
} as const;
|
|
359
|
+
|
|
360
|
+
export type ActivityTableStatusType =
|
|
361
|
+
(typeof ActivityTableStatus)[keyof typeof ActivityTableStatus];
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### ActivityRowType\<A\>
|
|
365
|
+
|
|
366
|
+
Row type for activity table data. System fields and entity fields are flat at the top level.
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
export type ActivityRowType<A extends Activity<any, any, any>> =
|
|
370
|
+
A extends Activity<infer E, any, any>
|
|
371
|
+
? ActivityInstanceFieldsType & E
|
|
372
|
+
: never;
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### UseActivityTableOptionsType\<A\>
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
export interface UseActivityTableOptionsType<A extends Activity<any, any, any>> {
|
|
379
|
+
/** The activity instance to fetch data for */
|
|
380
|
+
activity: A;
|
|
381
|
+
|
|
382
|
+
/** Which activity instances to fetch — determines endpoint */
|
|
383
|
+
status: ActivityTableStatusType;
|
|
384
|
+
|
|
385
|
+
/** Initial state for sort, pagination, and filter */
|
|
386
|
+
initialState?: {
|
|
387
|
+
sort?: SortType;
|
|
388
|
+
pagination?: PaginationStateType;
|
|
389
|
+
filter?: UseFilterOptionsType<ActivityRowType<A>>;
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
/** Called when data fetch fails */
|
|
393
|
+
onError?: (error: Error) => void;
|
|
394
|
+
|
|
395
|
+
/** Called with fetched rows after successful load */
|
|
396
|
+
onSuccess?: (data: ActivityRowType<A>[]) => void;
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### UseActivityTableReturnType\<A\>
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
export type UseActivityTableReturnType<A extends Activity<any, any, any>> =
|
|
404
|
+
UseTableReturnType<ActivityRowType<A>>;
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
The return type is identical to `UseTableReturnType`. All properties — `rows`, `totalItems`, `isLoading`, `isFetching`, `error`, `search`, `sort`, `filter`, `pagination`, and `refetch` — behave the same.
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## Search, Sort, Filter, and Pagination
|
|
412
|
+
|
|
413
|
+
`useActivityTable` supports `initialState`, `onError`, and `onSuccess` options.
|
|
414
|
+
|
|
415
|
+
- **Search** — `search.set(field, query)`, `search.clear()`, 300ms debounce
|
|
416
|
+
- **Sort** — `sort.toggle(field)`, `sort.set(field, direction)`, `sort.clear()`
|
|
417
|
+
- **Filter** — `filter.addCondition(...)`, `filter.removeCondition(...)`, `filter.clearAllConditions()`
|
|
418
|
+
- **Pagination** — `pagination.goToNext()`, `pagination.goToPrevious()`, `pagination.goToPage(n)`, `pagination.setPageSize(n)`
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
#
|
|
1
|
+
# useBDOForm
|
|
2
2
|
|
|
3
|
-
React hook for forms with validation, API integration, and typed field handling.
|
|
3
|
+
React hook for BDO forms with validation, API integration, and typed field handling.
|
|
4
4
|
|
|
5
5
|
## Imports
|
|
6
6
|
|
|
7
7
|
```typescript
|
|
8
|
-
import {
|
|
8
|
+
import { useBDOForm } from "@ram_28/kf-ai-sdk/form";
|
|
9
9
|
import { ValidationMode, FormOperation } from "@ram_28/kf-ai-sdk/form";
|
|
10
|
-
import type {
|
|
10
|
+
import type { UseBDOFormOptionsType, UseBDOFormReturnType, FormItemType, FormRegisterType, HandleSubmitType } from "@ram_28/kf-ai-sdk/form/types";
|
|
11
11
|
import type { CreateUpdateResponseType } from "@ram_28/kf-ai-sdk/api/types";
|
|
12
12
|
|
|
13
13
|
// Pre-built components for special field types
|
|
@@ -20,34 +20,34 @@ import { FileUpload } from "@/components/ui/file-upload";
|
|
|
20
20
|
|
|
21
21
|
## Common Mistakes (READ FIRST)
|
|
22
22
|
|
|
23
|
-
### 1. Missing `operation` in
|
|
23
|
+
### 1. Missing `operation` in useBDOForm options (TS2345)
|
|
24
24
|
|
|
25
25
|
ALWAYS include `operation`. Without it, TypeScript cannot resolve the union type.
|
|
26
26
|
|
|
27
27
|
```typescript
|
|
28
28
|
// ❌ WRONG — missing operation (TS2345)
|
|
29
|
-
|
|
29
|
+
useBDOForm({ bdo: product, mode: ValidationMode.OnBlur });
|
|
30
30
|
|
|
31
31
|
// ✅ CORRECT — always include operation
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
useBDOForm({ bdo: product, operation: FormOperation.Create, mode: ValidationMode.OnBlur });
|
|
33
|
+
useBDOForm({ bdo: product, operation: FormOperation.Update, recordId: id, mode: ValidationMode.OnBlur });
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
### 2. Annotating ternary with
|
|
36
|
+
### 2. Annotating ternary with UseBDOFormOptionsType (TS2322)
|
|
37
37
|
|
|
38
|
-
`
|
|
38
|
+
`UseBDOFormOptionsType` is a discriminated union. Type-annotating a variable prevents TS narrowing. NEVER annotate — call useBDOForm inline in each branch.
|
|
39
39
|
|
|
40
40
|
```typescript
|
|
41
41
|
// ❌ WRONG — type annotation prevents union narrowing (TS2322)
|
|
42
|
-
const options:
|
|
42
|
+
const options: UseBDOFormOptionsType<typeof bdo> = id
|
|
43
43
|
? { bdo, operation: FormOperation.Update, recordId: id, mode: ValidationMode.OnBlur }
|
|
44
44
|
: { bdo, operation: FormOperation.Create, mode: ValidationMode.OnBlur };
|
|
45
|
-
const formResult =
|
|
45
|
+
const formResult = useBDOForm(options);
|
|
46
46
|
|
|
47
|
-
// ✅ CORRECT — call
|
|
47
|
+
// ✅ CORRECT — call useBDOForm inline, no type annotation
|
|
48
48
|
const formResult = id
|
|
49
|
-
?
|
|
50
|
-
:
|
|
49
|
+
? useBDOForm({ bdo, operation: FormOperation.Update, recordId: id, mode: ValidationMode.OnBlur })
|
|
50
|
+
: useBDOForm({ bdo, operation: FormOperation.Create, mode: ValidationMode.OnBlur });
|
|
51
51
|
const { register, handleSubmit, watch, setValue, item, formState: { errors, isSubmitting }, isLoading } = formResult;
|
|
52
52
|
```
|
|
53
53
|
|
|
@@ -161,11 +161,11 @@ const onSuccess = (data: CreateUpdateResponseType) => { toast.success("Saved");
|
|
|
161
161
|
|
|
162
162
|
```typescript
|
|
163
163
|
// ❌ WRONG
|
|
164
|
-
|
|
164
|
+
useBDOForm<ProductFieldType>({ ... });
|
|
165
165
|
|
|
166
166
|
// ✅ CORRECT — pass BDO class instance
|
|
167
167
|
const product = useMemo(() => new SellerProduct(), []);
|
|
168
|
-
|
|
168
|
+
useBDOForm({ bdo: product, operation: FormOperation.Create, mode: ValidationMode.OnBlur });
|
|
169
169
|
```
|
|
170
170
|
|
|
171
171
|
### 9. Wrong default values for date fields
|
|
@@ -187,7 +187,7 @@ defaultValues: { start_date: undefined }
|
|
|
187
187
|
|
|
188
188
|
import { useMemo } from "react";
|
|
189
189
|
import { useNavigate, useParams } from "react-router-dom";
|
|
190
|
-
import {
|
|
190
|
+
import { useBDOForm, ValidationMode, FormOperation } from "@ram_28/kf-ai-sdk/form";
|
|
191
191
|
import type { CreateUpdateResponseType } from "@ram_28/kf-ai-sdk/api/types";
|
|
192
192
|
import { AdminProduct } from "@/bdo/admin/Product";
|
|
193
193
|
import { ReferenceSelect } from "@/components/ui/reference-select";
|
|
@@ -203,8 +203,8 @@ export default function ProductForm() {
|
|
|
203
203
|
|
|
204
204
|
// Create/Edit ternary — NO type annotation on result
|
|
205
205
|
const formResult = id
|
|
206
|
-
?
|
|
207
|
-
:
|
|
206
|
+
? useBDOForm({ bdo, operation: FormOperation.Update, recordId: id, mode: ValidationMode.OnBlur })
|
|
207
|
+
: useBDOForm({ bdo, operation: FormOperation.Create, mode: ValidationMode.OnBlur });
|
|
208
208
|
|
|
209
209
|
const { register, handleSubmit, watch, setValue, item, formState: { errors, isSubmitting }, isLoading } = formResult;
|
|
210
210
|
|
|
@@ -310,19 +310,19 @@ export default function ProductForm() {
|
|
|
310
310
|
|
|
311
311
|
## Type Definitions
|
|
312
312
|
|
|
313
|
-
###
|
|
313
|
+
### UseBDOFormOptionsType (Discriminated Union)
|
|
314
314
|
|
|
315
315
|
```typescript
|
|
316
|
-
type
|
|
316
|
+
type UseBDOFormOptionsType<B extends BaseBdo<any, any, any>> =
|
|
317
317
|
| { bdo: B; operation: "create"; defaultValues?: Partial<EditableFieldType>; mode?: ValidationModeType; }
|
|
318
318
|
| { bdo: B; operation: "update"; recordId: string; mode?: ValidationModeType; }
|
|
319
319
|
| { bdo: B; recordId?: string; defaultValues?: Partial<EditableFieldType>; mode?: ValidationModeType; };
|
|
320
320
|
```
|
|
321
321
|
|
|
322
|
-
###
|
|
322
|
+
### UseBDOFormReturnType
|
|
323
323
|
|
|
324
324
|
```typescript
|
|
325
|
-
interface
|
|
325
|
+
interface UseBDOFormReturnType<B> {
|
|
326
326
|
item: FormItemType<EditableFieldType, ReadonlyFieldType>; // Field accessors (.get(), .set(), .upload())
|
|
327
327
|
register: FormRegisterType; // Auto-disables readonly fields
|
|
328
328
|
handleSubmit: HandleSubmitType; // Auto-calls bdo.create() or bdo.update()
|