@ram_28/kf-ai-sdk 2.0.14 → 2.0.15
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 +2 -1
- 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.cjs +1 -1
- package/dist/bdo.mjs +228 -472
- 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 +11 -7
- 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/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 +26 -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/createResolver-AIgUwoS6.cjs +1 -0
- package/dist/createResolver-ZHXQ7QMa.js +1078 -0
- package/dist/form.cjs +1 -1
- package/dist/form.mjs +252 -314
- package/dist/{metadata-DpfI3zRN.js → metadata-Cc1mBcLS.js} +1 -1
- package/dist/{metadata-DgLSJkF5.cjs → metadata-DWXQPDav.cjs} +1 -1
- 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 +16 -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/useTable-CeRklbdT.cjs +1 -0
- package/dist/useTable-DS0-WInw.js +203 -0
- package/dist/workflow/Activity.d.ts +9 -9
- package/dist/workflow/Activity.d.ts.map +1 -1
- 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 +12 -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 +716 -338
- package/dist/workflow.types.d.ts +1 -0
- package/dist/workflow.types.d.ts.map +1 -1
- package/docs/gaps.md +410 -0
- package/docs/useActivityTable.md +481 -0
- package/docs/useBDOTable.md +317 -0
- package/docs/workflow.md +143 -34
- package/package.json +1 -1
- 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 +21 -8
- package/sdk/components/hooks/useActivityForm/useActivityForm.ts +628 -0
- package/sdk/components/hooks/useActivityTable/index.ts +8 -0
- package/sdk/components/hooks/useActivityTable/types.ts +45 -0
- package/sdk/components/hooks/useActivityTable/useActivityTable.ts +71 -0
- package/sdk/components/hooks/useBDOTable/index.ts +2 -0
- package/sdk/components/hooks/useBDOTable/types.ts +24 -0
- package/sdk/components/hooks/useBDOTable/useBDOTable.ts +15 -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/table.ts +4 -1
- package/sdk/table.types.ts +7 -4
- package/sdk/types/base-fields.ts +4 -4
- package/sdk/workflow/Activity.ts +14 -13
- package/sdk/workflow/client.ts +21 -8
- package/sdk/workflow/createFieldFromMeta.ts +110 -0
- package/sdk/workflow/index.ts +1 -6
- package/sdk/workflow/types.ts +13 -12
- 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/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/sdk/{workflow/components → components/hooks}/useActivityForm/index.ts +0 -0
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
# useActivityTable
|
|
2
|
+
|
|
3
|
+
Thin wrapper around `useTable` for listing workflow activity (business process) instances. It provides the same search, sort, filter, and pagination capabilities tailored to activity data.
|
|
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. Accessing entity fields at the top level
|
|
22
|
+
|
|
23
|
+
Entity fields live under `ADO`, not at the top level. This is different from BDO tables.
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
// ❌ WRONG — entity fields are not at the top level
|
|
27
|
+
row.StartDate
|
|
28
|
+
row.LeaveType
|
|
29
|
+
row.ManagerApproved
|
|
30
|
+
|
|
31
|
+
// ✅ CORRECT — access entity fields through ADO
|
|
32
|
+
row.ADO.StartDate
|
|
33
|
+
row.ADO.LeaveType
|
|
34
|
+
row.ADO.ManagerApproved
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. Passing a Workflow instead of an Activity
|
|
38
|
+
|
|
39
|
+
The first argument must be an `Activity` instance, not a `Workflow` instance.
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
// ❌ WRONG — passing the workflow class
|
|
43
|
+
const wf = new SimpleLeaveProcess();
|
|
44
|
+
useActivityTable(wf, { status: ActivityTableStatus.InProgress });
|
|
45
|
+
|
|
46
|
+
// ✅ CORRECT — pass the activity instance
|
|
47
|
+
const activity = new SimpleLeaveProcess().employeeInputActivity();
|
|
48
|
+
useActivityTable(activity, { status: ActivityTableStatus.InProgress });
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 3. Using string literals instead of ActivityTableStatus
|
|
52
|
+
|
|
53
|
+
While string literals work at runtime, always use the `ActivityTableStatus` constant for type safety and readability.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// ❌ WRONG — raw string (no type safety, easy to typo)
|
|
57
|
+
useActivityTable(activity, { status: "inProgress" });
|
|
58
|
+
useActivityTable(activity, { status: "in_progress" });
|
|
59
|
+
|
|
60
|
+
// ✅ CORRECT — use the constant
|
|
61
|
+
useActivityTable(activity, { status: ActivityTableStatus.InProgress });
|
|
62
|
+
useActivityTable(activity, { status: ActivityTableStatus.Completed });
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 4. Forgetting to memoize the activity instance
|
|
66
|
+
|
|
67
|
+
Like BDO instances passed to `useBDOTable`, the activity instance should be memoized to prevent unnecessary re-renders and refetches.
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// ❌ WRONG — creates a new activity on every render
|
|
71
|
+
const activity = new SimpleLeaveProcess().employeeInputActivity();
|
|
72
|
+
useActivityTable(activity, { status: ActivityTableStatus.InProgress });
|
|
73
|
+
|
|
74
|
+
// ✅ CORRECT — memoize with useMemo
|
|
75
|
+
const activity = useMemo(
|
|
76
|
+
() => new SimpleLeaveProcess().employeeInputActivity(),
|
|
77
|
+
[],
|
|
78
|
+
);
|
|
79
|
+
useActivityTable(activity, { status: ActivityTableStatus.InProgress });
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 5. Using useTable directly for activity data
|
|
83
|
+
|
|
84
|
+
Use `useActivityTable` instead of `useTable` for activity data. The hook handles the query key construction, endpoint selection based on status, and proper typing automatically.
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// ❌ WRONG — manual setup with useTable
|
|
88
|
+
useTable({
|
|
89
|
+
queryKey: ["activity-table", bpId, activityId, "inprogress"],
|
|
90
|
+
listFn: (opts) => activity._getOps().inProgressList(opts),
|
|
91
|
+
countFn: (opts) => activity._getOps().inProgressMetric(opts),
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// ✅ CORRECT — let useActivityTable handle it
|
|
95
|
+
useActivityTable(activity, { status: ActivityTableStatus.InProgress });
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 6. Calling `.get()` on activity table rows
|
|
99
|
+
|
|
100
|
+
Table rows are plain objects, not `ActivityInstance` proxies. There is no `.get()` method.
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// ❌ WRONG — rows are plain objects
|
|
104
|
+
row.ADO.StartDate.get();
|
|
105
|
+
row.Status.get();
|
|
106
|
+
|
|
107
|
+
// ✅ CORRECT — access values directly
|
|
108
|
+
row.ADO.StartDate;
|
|
109
|
+
row.Status;
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Example: Employee Leave Request Table
|
|
115
|
+
|
|
116
|
+
Display in-progress leave requests with search, pagination, and a detail view.
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
import { useMemo, useState } from "react";
|
|
120
|
+
import { useActivityTable, ActivityTableStatus } from "@ram_28/kf-ai-sdk/workflow";
|
|
121
|
+
import type { ActivityRowType } from "@ram_28/kf-ai-sdk/workflow";
|
|
122
|
+
import {
|
|
123
|
+
SimpleLeaveProcess,
|
|
124
|
+
EmployeeInputActivity,
|
|
125
|
+
} from "@/bdo/workflows/SimpleLeaveProcess";
|
|
126
|
+
|
|
127
|
+
function EmployeeLeaveTable() {
|
|
128
|
+
const activity = useMemo(() => new SimpleLeaveProcess().employeeInputActivity(), []);
|
|
129
|
+
const [selectedId, setSelectedId] = useState<string | null>(null);
|
|
130
|
+
|
|
131
|
+
const {
|
|
132
|
+
rows,
|
|
133
|
+
totalItems,
|
|
134
|
+
isLoading,
|
|
135
|
+
isFetching,
|
|
136
|
+
error,
|
|
137
|
+
search,
|
|
138
|
+
sort,
|
|
139
|
+
pagination,
|
|
140
|
+
refetch,
|
|
141
|
+
} = useActivityTable(activity, {
|
|
142
|
+
status: ActivityTableStatus.InProgress,
|
|
143
|
+
initialState: {
|
|
144
|
+
pagination: { pageNo: 1, pageSize: 10 },
|
|
145
|
+
},
|
|
146
|
+
onError: (err) => console.error("Failed to load leave requests:", err.message),
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
if (isLoading) return <div>Loading...</div>;
|
|
150
|
+
if (error) return <div>Error: {error.message}</div>;
|
|
151
|
+
|
|
152
|
+
return (
|
|
153
|
+
<div>
|
|
154
|
+
<h2>My Leave Requests ({totalItems})</h2>
|
|
155
|
+
|
|
156
|
+
{/* Search */}
|
|
157
|
+
<div>
|
|
158
|
+
<input
|
|
159
|
+
type="text"
|
|
160
|
+
placeholder="Search by leave type..."
|
|
161
|
+
value={search.query}
|
|
162
|
+
onChange={(e) => search.set("ADO", e.target.value)}
|
|
163
|
+
/>
|
|
164
|
+
{search.query && <button onClick={search.clear}>Clear</button>}
|
|
165
|
+
{isFetching && <span>Loading...</span>}
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
{/* Table */}
|
|
169
|
+
<table>
|
|
170
|
+
<thead>
|
|
171
|
+
<tr>
|
|
172
|
+
<th>ID</th>
|
|
173
|
+
<th>Status</th>
|
|
174
|
+
<th>Assigned To</th>
|
|
175
|
+
<th
|
|
176
|
+
style={{ cursor: "pointer" }}
|
|
177
|
+
onClick={() => sort.toggle("ADO" as any)}
|
|
178
|
+
>
|
|
179
|
+
Leave Type
|
|
180
|
+
</th>
|
|
181
|
+
<th>Start Date</th>
|
|
182
|
+
<th>End Date</th>
|
|
183
|
+
<th>Days</th>
|
|
184
|
+
<th>Action</th>
|
|
185
|
+
</tr>
|
|
186
|
+
</thead>
|
|
187
|
+
<tbody>
|
|
188
|
+
{rows.map((row) => (
|
|
189
|
+
<tr key={row._id}>
|
|
190
|
+
<td>{row._id}</td>
|
|
191
|
+
<td>{row.Status}</td>
|
|
192
|
+
<td>{row.AssignedTo.map((u) => u._name).join(", ")}</td>
|
|
193
|
+
<td>{row.ADO.LeaveType}</td>
|
|
194
|
+
<td>{row.ADO.StartDate}</td>
|
|
195
|
+
<td>{row.ADO.EndDate}</td>
|
|
196
|
+
<td>{row.ADO.LeaveDays}</td>
|
|
197
|
+
<td>
|
|
198
|
+
<button onClick={() => setSelectedId(row._id)}>View</button>
|
|
199
|
+
</td>
|
|
200
|
+
</tr>
|
|
201
|
+
))}
|
|
202
|
+
</tbody>
|
|
203
|
+
</table>
|
|
204
|
+
|
|
205
|
+
{/* Pagination */}
|
|
206
|
+
<div>
|
|
207
|
+
<button
|
|
208
|
+
onClick={pagination.goToPrevious}
|
|
209
|
+
disabled={!pagination.canGoPrevious}
|
|
210
|
+
>
|
|
211
|
+
Previous
|
|
212
|
+
</button>
|
|
213
|
+
<span>
|
|
214
|
+
Page {pagination.pageNo} of {pagination.totalPages}
|
|
215
|
+
</span>
|
|
216
|
+
<button
|
|
217
|
+
onClick={pagination.goToNext}
|
|
218
|
+
disabled={!pagination.canGoNext}
|
|
219
|
+
>
|
|
220
|
+
Next
|
|
221
|
+
</button>
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Example: Manager Approval Table
|
|
231
|
+
|
|
232
|
+
Display pending approvals with status tabs for in-progress and completed items.
|
|
233
|
+
|
|
234
|
+
```tsx
|
|
235
|
+
import { useMemo, useState } from "react";
|
|
236
|
+
import {
|
|
237
|
+
useActivityTable,
|
|
238
|
+
ActivityTableStatus,
|
|
239
|
+
} from "@ram_28/kf-ai-sdk/workflow";
|
|
240
|
+
import type {
|
|
241
|
+
ActivityRowType,
|
|
242
|
+
UseActivityTableOptionsType,
|
|
243
|
+
} from "@ram_28/kf-ai-sdk/workflow";
|
|
244
|
+
import {
|
|
245
|
+
SimpleLeaveProcess,
|
|
246
|
+
ManagerApprovalActivity,
|
|
247
|
+
} from "@/bdo/workflows/SimpleLeaveProcess";
|
|
248
|
+
|
|
249
|
+
type StatusTab = "inprogress" | "completed";
|
|
250
|
+
|
|
251
|
+
function ManagerApprovalTable() {
|
|
252
|
+
const activity = useMemo(
|
|
253
|
+
() => new SimpleLeaveProcess().managerApprovalActivity(),
|
|
254
|
+
[],
|
|
255
|
+
);
|
|
256
|
+
const [activeTab, setActiveTab] = useState<StatusTab>("inprogress");
|
|
257
|
+
const [selectedId, setSelectedId] = useState<string | null>(null);
|
|
258
|
+
|
|
259
|
+
const options: UseActivityTableOptionsType<ManagerApprovalActivity> = {
|
|
260
|
+
status: activeTab,
|
|
261
|
+
initialState: {
|
|
262
|
+
pagination: { pageNo: 1, pageSize: 10 },
|
|
263
|
+
},
|
|
264
|
+
onError: (err) => console.error("Fetch failed:", err.message),
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const {
|
|
268
|
+
rows,
|
|
269
|
+
totalItems,
|
|
270
|
+
isLoading,
|
|
271
|
+
isFetching,
|
|
272
|
+
error,
|
|
273
|
+
search,
|
|
274
|
+
sort,
|
|
275
|
+
filter,
|
|
276
|
+
pagination,
|
|
277
|
+
refetch,
|
|
278
|
+
} = useActivityTable(activity, options);
|
|
279
|
+
|
|
280
|
+
if (selectedId) {
|
|
281
|
+
return (
|
|
282
|
+
<ApprovalForm
|
|
283
|
+
activityInstanceId={selectedId}
|
|
284
|
+
onComplete={() => {
|
|
285
|
+
setSelectedId(null);
|
|
286
|
+
refetch();
|
|
287
|
+
}}
|
|
288
|
+
/>
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return (
|
|
293
|
+
<div>
|
|
294
|
+
{/* Status tabs */}
|
|
295
|
+
<div>
|
|
296
|
+
<button
|
|
297
|
+
onClick={() => setActiveTab("inprogress")}
|
|
298
|
+
disabled={activeTab === "inprogress"}
|
|
299
|
+
>
|
|
300
|
+
Pending
|
|
301
|
+
</button>
|
|
302
|
+
<button
|
|
303
|
+
onClick={() => setActiveTab("completed")}
|
|
304
|
+
disabled={activeTab === "completed"}
|
|
305
|
+
>
|
|
306
|
+
Completed
|
|
307
|
+
</button>
|
|
308
|
+
</div>
|
|
309
|
+
|
|
310
|
+
<h2>
|
|
311
|
+
{activeTab === "inprogress" ? "Pending" : "Completed"} Approvals ({totalItems})
|
|
312
|
+
</h2>
|
|
313
|
+
|
|
314
|
+
{/* Search */}
|
|
315
|
+
<input
|
|
316
|
+
type="text"
|
|
317
|
+
placeholder="Search..."
|
|
318
|
+
value={search.query}
|
|
319
|
+
onChange={(e) => search.set("_id", e.target.value)}
|
|
320
|
+
/>
|
|
321
|
+
|
|
322
|
+
{isLoading && <div>Loading...</div>}
|
|
323
|
+
{error && <div>Error: {error.message}</div>}
|
|
324
|
+
|
|
325
|
+
{/* Table */}
|
|
326
|
+
<table>
|
|
327
|
+
<thead>
|
|
328
|
+
<tr>
|
|
329
|
+
<th>ID</th>
|
|
330
|
+
<th
|
|
331
|
+
style={{ cursor: "pointer" }}
|
|
332
|
+
onClick={() => sort.toggle("Status")}
|
|
333
|
+
>
|
|
334
|
+
Status
|
|
335
|
+
{sort.field === "Status" && (
|
|
336
|
+
<span>{sort.direction === "ASC" ? " ↑" : " ↓"}</span>
|
|
337
|
+
)}
|
|
338
|
+
</th>
|
|
339
|
+
<th>Assigned To</th>
|
|
340
|
+
<th>Approved</th>
|
|
341
|
+
<th>Reason</th>
|
|
342
|
+
{activeTab === "inprogress" && <th>Action</th>}
|
|
343
|
+
</tr>
|
|
344
|
+
</thead>
|
|
345
|
+
<tbody>
|
|
346
|
+
{rows.map((row) => (
|
|
347
|
+
<tr key={row._id}>
|
|
348
|
+
<td>{row._id}</td>
|
|
349
|
+
<td>{row.Status}</td>
|
|
350
|
+
<td>{row.AssignedTo.map((u) => u._name).join(", ")}</td>
|
|
351
|
+
<td>{row.ADO.ManagerApproved ? "Yes" : "No"}</td>
|
|
352
|
+
<td>{row.ADO.ManagerReason}</td>
|
|
353
|
+
{activeTab === "inprogress" && (
|
|
354
|
+
<td>
|
|
355
|
+
<button onClick={() => setSelectedId(row._id)}>Review</button>
|
|
356
|
+
</td>
|
|
357
|
+
)}
|
|
358
|
+
</tr>
|
|
359
|
+
))}
|
|
360
|
+
</tbody>
|
|
361
|
+
</table>
|
|
362
|
+
|
|
363
|
+
{/* Pagination */}
|
|
364
|
+
<div>
|
|
365
|
+
<button
|
|
366
|
+
onClick={pagination.goToPrevious}
|
|
367
|
+
disabled={!pagination.canGoPrevious}
|
|
368
|
+
>
|
|
369
|
+
Previous
|
|
370
|
+
</button>
|
|
371
|
+
<span>
|
|
372
|
+
Page {pagination.pageNo} of {pagination.totalPages}
|
|
373
|
+
</span>
|
|
374
|
+
<button
|
|
375
|
+
onClick={pagination.goToNext}
|
|
376
|
+
disabled={!pagination.canGoNext}
|
|
377
|
+
>
|
|
378
|
+
Next
|
|
379
|
+
</button>
|
|
380
|
+
<select
|
|
381
|
+
value={pagination.pageSize}
|
|
382
|
+
onChange={(e) => pagination.setPageSize(Number(e.target.value))}
|
|
383
|
+
>
|
|
384
|
+
<option value={10}>10 per page</option>
|
|
385
|
+
<option value={25}>25 per page</option>
|
|
386
|
+
<option value={50}>50 per page</option>
|
|
387
|
+
</select>
|
|
388
|
+
</div>
|
|
389
|
+
</div>
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## Accessing Entity Fields
|
|
397
|
+
|
|
398
|
+
Activity row data has a two-level structure. System fields (`_id`, `Status`, `AssignedTo`, `CompletedAt`) are at the top level. Entity-specific fields are nested under the `ADO` property.
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
// System fields — top level
|
|
402
|
+
row._id
|
|
403
|
+
row.Status
|
|
404
|
+
row.AssignedTo.map((u) => u._name)
|
|
405
|
+
row.CompletedAt
|
|
406
|
+
|
|
407
|
+
// Entity fields — under ADO
|
|
408
|
+
row.ADO.StartDate
|
|
409
|
+
row.ADO.LeaveType
|
|
410
|
+
row.ADO.LeaveDays
|
|
411
|
+
row.ADO.ManagerApproved
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## Type Definitions
|
|
417
|
+
|
|
418
|
+
### ActivityTableStatus
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
export const ActivityTableStatus = {
|
|
422
|
+
InProgress: "inprogress",
|
|
423
|
+
Completed: "completed",
|
|
424
|
+
} as const;
|
|
425
|
+
|
|
426
|
+
export type ActivityTableStatusType =
|
|
427
|
+
(typeof ActivityTableStatus)[keyof typeof ActivityTableStatus];
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### ActivityRowType\<A\>
|
|
431
|
+
|
|
432
|
+
Row type for activity table data. System fields at top level, entity fields under `ADO`.
|
|
433
|
+
|
|
434
|
+
```typescript
|
|
435
|
+
export type ActivityRowType<A extends Activity<any, any, any>> =
|
|
436
|
+
A extends Activity<infer E, any, any>
|
|
437
|
+
? ActivityInstanceFieldsType & { ADO: E }
|
|
438
|
+
: never;
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### UseActivityTableOptionsType\<A\>
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
export interface UseActivityTableOptionsType<A extends Activity<any, any, any>> {
|
|
445
|
+
/** Which activity instances to fetch — determines endpoint */
|
|
446
|
+
status: ActivityTableStatusType;
|
|
447
|
+
|
|
448
|
+
/** Initial state for sort, pagination, and filter */
|
|
449
|
+
initialState?: {
|
|
450
|
+
sort?: SortType;
|
|
451
|
+
pagination?: PaginationStateType;
|
|
452
|
+
filter?: UseFilterOptionsType<ActivityRowType<A>>;
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
/** Called when data fetch fails */
|
|
456
|
+
onError?: (error: Error) => void;
|
|
457
|
+
|
|
458
|
+
/** Called with fetched rows after successful load */
|
|
459
|
+
onSuccess?: (data: ActivityRowType<A>[]) => void;
|
|
460
|
+
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### UseActivityTableReturnType\<A\>
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
export type UseActivityTableReturnType<A extends Activity<any, any, any>> =
|
|
467
|
+
UseTableReturnType<ActivityRowType<A>>;
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
The return type is identical to `UseTableReturnType`. All properties — `rows`, `totalItems`, `isLoading`, `isFetching`, `error`, `search`, `sort`, `filter`, `pagination`, and `refetch` — behave the same.
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
## Search, Sort, Filter, and Pagination
|
|
475
|
+
|
|
476
|
+
These features are inherited from the base `useTable` hook. `useActivityTable` passes `initialState`, `onError`, and `onSuccess` straight through.
|
|
477
|
+
|
|
478
|
+
- **Search** — `search.set(field, query)`, `search.clear()`, 300ms debounce
|
|
479
|
+
- **Sort** — `sort.toggle(field)`, `sort.set(field, direction)`, `sort.clear()`
|
|
480
|
+
- **Filter** — `filter.addCondition(...)`, `filter.removeCondition(...)`, `filter.clearAllConditions()`
|
|
481
|
+
- **Pagination** — `pagination.goToNext()`, `pagination.goToPrevious()`, `pagination.goToPage(n)`, `pagination.setPageSize(n)`
|