@ram_28/kf-ai-sdk 1.0.19 → 1.0.20

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.
Files changed (64) hide show
  1. package/README.md +45 -12
  2. package/dist/components/hooks/useFilter/types.d.ts +14 -11
  3. package/dist/components/hooks/useFilter/types.d.ts.map +1 -1
  4. package/dist/components/hooks/useFilter/useFilter.d.ts +1 -1
  5. package/dist/components/hooks/useFilter/useFilter.d.ts.map +1 -1
  6. package/dist/components/hooks/useForm/apiClient.d.ts.map +1 -1
  7. package/dist/components/hooks/useForm/useForm.d.ts.map +1 -1
  8. package/dist/components/hooks/useKanban/types.d.ts +5 -22
  9. package/dist/components/hooks/useKanban/types.d.ts.map +1 -1
  10. package/dist/components/hooks/useKanban/useKanban.d.ts.map +1 -1
  11. package/dist/components/hooks/useTable/types.d.ts +19 -31
  12. package/dist/components/hooks/useTable/types.d.ts.map +1 -1
  13. package/dist/components/hooks/useTable/useTable.d.ts.map +1 -1
  14. package/dist/error-handling-CAoD0Kwb.cjs +1 -0
  15. package/dist/error-handling-CrhTtD88.js +14 -0
  16. package/dist/filter.cjs +1 -1
  17. package/dist/filter.mjs +1 -1
  18. package/dist/form.cjs +1 -1
  19. package/dist/form.mjs +338 -327
  20. package/dist/index.d.ts +18 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/kanban.cjs +2 -2
  23. package/dist/kanban.mjs +332 -322
  24. package/dist/table.cjs +1 -1
  25. package/dist/table.mjs +113 -96
  26. package/dist/table.types.d.ts +1 -1
  27. package/dist/table.types.d.ts.map +1 -1
  28. package/dist/types/common.d.ts +26 -6
  29. package/dist/types/common.d.ts.map +1 -1
  30. package/dist/useFilter-DzpP_ag0.cjs +1 -0
  31. package/dist/useFilter-H5bgAZQF.js +120 -0
  32. package/dist/utils/api/buildListOptions.d.ts +43 -0
  33. package/dist/utils/api/buildListOptions.d.ts.map +1 -0
  34. package/dist/utils/api/index.d.ts +2 -0
  35. package/dist/utils/api/index.d.ts.map +1 -0
  36. package/dist/utils/error-handling.d.ts +41 -0
  37. package/dist/utils/error-handling.d.ts.map +1 -0
  38. package/dist/utils/index.d.ts +2 -0
  39. package/dist/utils/index.d.ts.map +1 -1
  40. package/docs/QUICK_REFERENCE.md +142 -420
  41. package/docs/useAuth.md +52 -340
  42. package/docs/useFilter.md +858 -162
  43. package/docs/useForm.md +712 -501
  44. package/docs/useKanban.md +534 -279
  45. package/docs/useTable.md +725 -214
  46. package/package.json +1 -1
  47. package/sdk/components/hooks/useFilter/types.ts +14 -11
  48. package/sdk/components/hooks/useFilter/useFilter.ts +20 -18
  49. package/sdk/components/hooks/useForm/apiClient.ts +2 -1
  50. package/sdk/components/hooks/useForm/useForm.ts +35 -11
  51. package/sdk/components/hooks/useKanban/types.ts +7 -23
  52. package/sdk/components/hooks/useKanban/useKanban.ts +54 -18
  53. package/sdk/components/hooks/useTable/types.ts +26 -32
  54. package/sdk/components/hooks/useTable/useTable.llm.txt +8 -22
  55. package/sdk/components/hooks/useTable/useTable.ts +70 -25
  56. package/sdk/index.ts +154 -10
  57. package/sdk/table.types.ts +3 -0
  58. package/sdk/types/common.ts +31 -6
  59. package/sdk/utils/api/buildListOptions.ts +120 -0
  60. package/sdk/utils/api/index.ts +2 -0
  61. package/sdk/utils/error-handling.ts +150 -0
  62. package/sdk/utils/index.ts +6 -0
  63. package/dist/useFilter-Dofowpr_.cjs +0 -1
  64. package/dist/useFilter-Dv-mr9QW.js +0 -117
@@ -28,12 +28,9 @@ const table = useTable<ProductType>({
28
28
  { fieldId: "Category", label: "Category", enableSorting: true },
29
29
  { fieldId: "Stock", label: "Stock", enableSorting: true },
30
30
  ],
31
- enableSorting: true,
32
- enableFiltering: true,
33
- enablePagination: true,
34
31
  initialState: {
35
32
  pagination: { pageNo: 1, pageSize: 10 },
36
- sorting: { field: "Title", direction: "asc" },
33
+ sort: [{ Title: "ASC" }],
37
34
  },
38
35
  });
39
36
  ```
@@ -46,14 +43,9 @@ const table = useTable<ProductType>({
46
43
  |----------|------|----------|-------------|
47
44
  | `source` | `string` | Yes | Data source identifier (Business Data Object name) |
48
45
  | `columns` | `ColumnDefinition<T>[]` | Yes | Column configurations |
49
- | `enableSorting` | `boolean` | No | Enable sorting functionality |
50
- | `enableFiltering` | `boolean` | No | Enable filtering functionality |
51
- | `enablePagination` | `boolean` | No | Enable pagination |
52
- | `fieldDefinitions` | `Record<keyof T, FieldDefinition>` | No | Field definitions for filter validation |
53
- | `initialState` | `object` | No | Initial state for pagination, sorting, filters |
46
+ | `initialState` | `object` | No | Initial state for pagination, sorting, filters. Pagination defaults to `{ pageNo: 1, pageSize: 10 }` |
54
47
  | `onError` | `(error: Error) => void` | No | Error callback |
55
48
  | `onSuccess` | `(data: T[]) => void` | No | Success callback |
56
- | `onFilterError` | `(errors: ValidationError[]) => void` | No | Filter error callback |
57
49
 
58
50
  ### ColumnDefinition<T>
59
51
 
@@ -113,14 +105,14 @@ const table = useTable<ProductType>({
113
105
  | `filter.addCondition` | `(condition) => string` | Add a filter condition, returns ID |
114
106
  | `filter.updateCondition` | `(id, updates) => boolean` | Update a condition |
115
107
  | `filter.removeCondition` | `(id) => boolean` | Remove a condition |
116
- | `filter.clearConditions` | `() => void` | Clear all conditions |
108
+ | `filter.clearAllConditions` | `() => void` | Clear all conditions |
117
109
  | `filter.getCondition` | `(id) => FilterConditionWithId` | Get a specific condition |
118
110
  | `filter.setLogicalOperator` | `(operator) => void` | Set logical operator |
119
111
 
120
112
  #### Pagination
121
113
  | Property | Type | Description |
122
114
  |----------|------|-------------|
123
- | `pagination.currentPage` | `number` | Current page (1-indexed) |
115
+ | `pagination.pageNo` | `number` | Current page (1-indexed) |
124
116
  | `pagination.pageSize` | `number` | Items per page |
125
117
  | `pagination.totalPages` | `number` | Total number of pages |
126
118
  | `pagination.totalItems` | `number` | Total item count |
@@ -179,12 +171,9 @@ const table = useTable<SellerProduct>({
179
171
  { fieldId: "Category", label: "Category", enableSorting: true },
180
172
  { fieldId: "Stock", label: "Stock", enableSorting: true },
181
173
  ],
182
- enableSorting: true,
183
- enableFiltering: true,
184
- enablePagination: true,
185
174
  initialState: {
186
175
  pagination: { pageNo: 1, pageSize: 10 },
187
- sorting: { field: "Title", direction: "asc" },
176
+ sort: [{ Title: "ASC" }],
188
177
  },
189
178
  });
190
179
 
@@ -220,18 +209,15 @@ const table = useTable<SellerProduct>({
220
209
  const table = useTable<BuyerProduct>({
221
210
  source: "BDO_AmazonProductMaster",
222
211
  columns: [...],
223
- enableSorting: true,
224
- enableFiltering: true,
225
- enablePagination: true,
226
212
  initialState: {
227
213
  pagination: { pageNo: 1, pageSize: 10 },
228
- sorting: { field: "Title", direction: "asc" },
214
+ sort: [{ Title: "ASC" }],
229
215
  },
230
216
  });
231
217
 
232
218
  // Category filter
233
219
  const handleCategoryChange = (category: string) => {
234
- table.filter.clearConditions();
220
+ table.filter.clearAllConditions();
235
221
  if (category !== "all") {
236
222
  table.filter.addCondition({
237
223
  lhsField: "Category",
@@ -296,7 +282,7 @@ const handleSortChange = (value: string) => {
296
282
  <Button
297
283
  onClick={() => {
298
284
  table.search.clear();
299
- table.filter.clearConditions();
285
+ table.filter.clearAllConditions();
300
286
  }}
301
287
  >
302
288
  Clear All Filters
@@ -1,7 +1,8 @@
1
- import { useState, useMemo, useCallback } from "react";
1
+ import { useState, useMemo, useCallback, useRef, useEffect } from "react";
2
2
  import { useQuery } from "@tanstack/react-query";
3
3
  import { api } from "../../../api";
4
4
  import type { ListResponseType, ListOptionsType } from "../../../types/common";
5
+ import { toError } from "../../../utils/error-handling";
5
6
  import { useFilter } from "../useFilter";
6
7
  import type { UseTableOptionsType, UseTableReturnType } from "./types";
7
8
 
@@ -10,7 +11,8 @@ import type { UseTableOptionsType, UseTableReturnType } from "./types";
10
11
  // ============================================================
11
12
 
12
13
  interface SearchState {
13
- query: string;
14
+ query: string; // Immediate UI value
15
+ debouncedQuery: string; // Debounced value for API queries
14
16
  }
15
17
 
16
18
  interface SortingState<T> {
@@ -36,12 +38,26 @@ export function useTable<T = any>(
36
38
 
37
39
  const [search, setSearch] = useState<SearchState>({
38
40
  query: "",
41
+ debouncedQuery: "",
39
42
  });
40
43
 
41
- const [sorting, setSorting] = useState<SortingState<T>>({
42
- field: options.initialState?.sorting?.field || null,
43
- direction: options.initialState?.sorting?.direction || null,
44
- });
44
+ // Debounce timeout ref for search
45
+ const searchDebounceRef = useRef<NodeJS.Timeout | null>(null);
46
+ const SEARCH_DEBOUNCE_MS = 300;
47
+
48
+ // Parse initial sort from API format [{ "fieldName": "ASC" }] to internal state
49
+ const getInitialSortState = (): SortingState<T> => {
50
+ const sortConfig = options.initialState?.sort;
51
+ if (sortConfig && sortConfig.length > 0) {
52
+ const firstSort = sortConfig[0];
53
+ const field = Object.keys(firstSort)[0] as keyof T;
54
+ const direction = firstSort[field as string]?.toLowerCase() as "asc" | "desc";
55
+ return { field, direction };
56
+ }
57
+ return { field: null, direction: null };
58
+ };
59
+
60
+ const [sorting, setSorting] = useState<SortingState<T>>(getInitialSortState);
45
61
 
46
62
  const [pagination, setPagination] = useState<PaginationState>({
47
63
  pageNo: options.initialState?.pagination?.pageNo || 1,
@@ -52,9 +68,9 @@ export function useTable<T = any>(
52
68
  // FILTER HOOK INTEGRATION
53
69
  // ============================================================
54
70
 
55
- const filter = useFilter({
56
- initialConditions: options.initialState?.filters,
57
- initialOperator: options.initialState?.filterOperator || "And",
71
+ const filter = useFilter<T>({
72
+ conditions: options.initialState?.filter?.conditions,
73
+ operator: options.initialState?.filter?.operator || "And",
58
74
  });
59
75
 
60
76
  // ============================================================
@@ -65,9 +81,9 @@ export function useTable<T = any>(
65
81
  const countApiOptions = useMemo((): ListOptionsType => {
66
82
  const opts: ListOptionsType = {};
67
83
 
68
- // Add search query (affects count)
69
- if (search.query) {
70
- opts.Search = search.query;
84
+ // Add debounced search query (affects count)
85
+ if (search.debouncedQuery) {
86
+ opts.Search = search.debouncedQuery;
71
87
  }
72
88
 
73
89
  // Add filter conditions (affects count)
@@ -76,7 +92,7 @@ export function useTable<T = any>(
76
92
  }
77
93
 
78
94
  return opts;
79
- }, [search.query, filter.payload]);
95
+ }, [search.debouncedQuery, filter.payload]);
80
96
 
81
97
  // Options for list query - includes all options
82
98
  const apiOptions = useMemo((): ListOptionsType => {
@@ -92,13 +108,11 @@ export function useTable<T = any>(
92
108
  }
93
109
 
94
110
  // Add pagination
95
- if (options.enablePagination) {
96
- opts.Page = pagination.pageNo;
97
- opts.PageSize = pagination.pageSize;
98
- }
111
+ opts.Page = pagination.pageNo;
112
+ opts.PageSize = pagination.pageSize;
99
113
 
100
114
  return opts;
101
- }, [countApiOptions, sorting, pagination, options.enablePagination]);
115
+ }, [countApiOptions, sorting, pagination]);
102
116
 
103
117
  // ============================================================
104
118
  // DATA FETCHING
@@ -121,7 +135,7 @@ export function useTable<T = any>(
121
135
  return response;
122
136
  } catch (err) {
123
137
  if (options.onError) {
124
- options.onError(err as Error);
138
+ options.onError(toError(err));
125
139
  }
126
140
  throw err;
127
141
  }
@@ -144,7 +158,7 @@ export function useTable<T = any>(
144
158
  return await api<T>(options.source).count(countApiOptions);
145
159
  } catch (err) {
146
160
  if (options.onError) {
147
- options.onError(err as Error);
161
+ options.onError(toError(err));
148
162
  }
149
163
  throw err;
150
164
  }
@@ -197,12 +211,43 @@ export function useTable<T = any>(
197
211
  // ============================================================
198
212
 
199
213
  const setSearchQuery = useCallback((value: string) => {
200
- setSearch({ query: value });
201
- setPagination((prev) => ({ ...prev, pageNo: 1 }));
214
+ // Validate search query length to prevent DoS
215
+ if (value.length > 255) {
216
+ console.warn("Search query exceeds maximum length of 255 characters");
217
+ return;
218
+ }
219
+
220
+ // Update immediate value for UI
221
+ setSearch((prev) => ({ ...prev, query: value }));
222
+
223
+ // Clear existing debounce timeout
224
+ if (searchDebounceRef.current) {
225
+ clearTimeout(searchDebounceRef.current);
226
+ }
227
+
228
+ // Debounce the actual API query update
229
+ searchDebounceRef.current = setTimeout(() => {
230
+ setSearch((prev) => ({ ...prev, debouncedQuery: value }));
231
+ setPagination((prev) => ({ ...prev, pageNo: 1 }));
232
+ }, SEARCH_DEBOUNCE_MS);
202
233
  }, []);
203
234
 
204
235
  const clearSearch = useCallback(() => {
205
- setSearch({ query: "" });
236
+ // Clear debounce timeout
237
+ if (searchDebounceRef.current) {
238
+ clearTimeout(searchDebounceRef.current);
239
+ }
240
+ setSearch({ query: "", debouncedQuery: "" });
241
+ setPagination((prev) => ({ ...prev, pageNo: 1 }));
242
+ }, []);
243
+
244
+ // Cleanup debounce timeout on unmount
245
+ useEffect(() => {
246
+ return () => {
247
+ if (searchDebounceRef.current) {
248
+ clearTimeout(searchDebounceRef.current);
249
+ }
250
+ };
206
251
  }, []);
207
252
 
208
253
  // ============================================================
@@ -263,7 +308,7 @@ export function useTable<T = any>(
263
308
  isFetching: isFetching || isCountFetching,
264
309
 
265
310
  // Error Handling
266
- error: (error || countError) as Error | null,
311
+ error: error ? toError(error) : countError ? toError(countError) : null,
267
312
 
268
313
  // Search (Flat Access)
269
314
  search: {
@@ -286,7 +331,7 @@ export function useTable<T = any>(
286
331
 
287
332
  // Pagination (Flat Access)
288
333
  pagination: {
289
- currentPage: pagination.pageNo,
334
+ pageNo: pagination.pageNo,
290
335
  pageSize: pagination.pageSize,
291
336
  totalPages,
292
337
  totalItems,
package/sdk/index.ts CHANGED
@@ -1,16 +1,160 @@
1
- // Core SDK exports
1
+ // ============================================================
2
+ // @ram_28/kf-ai-sdk - Main Entry Point
3
+ // ============================================================
4
+ // This is the primary export file for the SDK, providing a unified
5
+ // interface to all hooks, types, utilities, and API functions.
2
6
 
3
- // Type system
4
- export * from './types';
7
+ // ============================================================
8
+ // HOOKS - Core functionality for building applications
9
+ // ============================================================
5
10
 
6
- // API client
7
- export * from './api';
11
+ // Table hook - Data tables with sorting, pagination, and filtering
12
+ export { useTable } from './components/hooks/useTable';
13
+ export type {
14
+ UseTableOptionsType,
15
+ UseTableReturnType,
16
+ } from './components/hooks/useTable';
8
17
 
9
- // Utilities
10
- export * from './utils';
18
+ // Form hook - Schema-driven forms with validation
19
+ export { useForm } from './components/hooks/useForm';
20
+ export type {
21
+ UseFormOptionsType,
22
+ UseFormReturnType,
23
+ FormFieldConfigType,
24
+ FormSchemaConfigType,
25
+ } from './components/hooks/useForm';
11
26
 
12
- // Components
13
- export * from './components';
27
+ // Kanban hook - Kanban board state management
28
+ export { useKanban } from './components/hooks/useKanban';
29
+ export type {
30
+ UseKanbanOptionsType,
31
+ UseKanbanReturnType,
32
+ KanbanCardType,
33
+ KanbanColumnType,
34
+ ColumnConfigType,
35
+ } from './components/hooks/useKanban';
36
+
37
+ // Filter hook - Advanced filtering with logical operators
38
+ export { useFilter, isCondition, isConditionGroup } from './components/hooks/useFilter';
39
+ export type {
40
+ UseFilterOptionsType,
41
+ UseFilterReturnType,
42
+ } from './components/hooks/useFilter';
43
+
44
+ // ============================================================
45
+ // AUTHENTICATION - User authentication and authorization
46
+ // ============================================================
47
+
48
+ export { AuthProvider, useAuth } from './auth';
49
+ export type {
50
+ UseAuthReturnType,
51
+ UserDetailsType,
52
+ AuthStatusType,
53
+ AuthProviderPropsType,
54
+ } from './auth/types';
55
+
56
+ // ============================================================
57
+ // API CLIENT - Type-safe CRUD operations
58
+ // ============================================================
59
+
60
+ export { api, setApiBaseUrl, getApiBaseUrl, getBdoSchema } from './api';
61
+
62
+ // ============================================================
63
+ // TYPES - Core type definitions
64
+ // ============================================================
65
+
66
+ // Common types
67
+ export type {
68
+ SortType,
69
+ SortDirectionType,
70
+ FilterType,
71
+ ConditionType,
72
+ ConditionGroupType,
73
+ ConditionOperatorType,
74
+ ConditionGroupOperatorType,
75
+ ListResponseType,
76
+ ListOptionsType,
77
+ ColumnDefinitionType,
78
+ } from './types/common';
79
+
80
+ // Base field types
81
+ export type {
82
+ IdFieldType,
83
+ StringFieldType,
84
+ TextAreaFieldType,
85
+ NumberFieldType,
86
+ LongFieldType,
87
+ BooleanFieldType,
88
+ DateFieldType,
89
+ DateTimeFieldType,
90
+ CurrencyFieldType,
91
+ SelectFieldType,
92
+ LookupFieldType,
93
+ ArrayFieldType,
94
+ JSONFieldType,
95
+ } from './types/base-fields';
14
96
 
15
- // Authentication
97
+ // ============================================================
98
+ // UTILITIES - Helper functions
99
+ // ============================================================
100
+
101
+ // Formatting utilities
102
+ export {
103
+ formatCurrency,
104
+ formatDate,
105
+ formatDateTime,
106
+ formatNumber,
107
+ formatBoolean,
108
+ formatArray,
109
+ formatJSON,
110
+ formatFieldValue,
111
+ } from './utils/formatting';
112
+
113
+ // Class name utility
114
+ export { cn } from './utils/cn';
115
+
116
+ // Error handling utilities
117
+ export {
118
+ toError,
119
+ isError,
120
+ getErrorMessage,
121
+ isNetworkError,
122
+ isTimeoutError,
123
+ isAbortError,
124
+ tryCatch,
125
+ wrapError,
126
+ } from './utils/error-handling';
127
+
128
+ // API utilities
129
+ export {
130
+ buildListOptions,
131
+ buildCountOptions,
132
+ combineFilters,
133
+ } from './utils/api';
134
+
135
+ // ============================================================
136
+ // UI COMPONENTS - Pre-built React components
137
+ // ============================================================
138
+
139
+ export {
140
+ Kanban,
141
+ KanbanColumn,
142
+ KanbanColumnHeader,
143
+ KanbanColumnTitle,
144
+ KanbanColumnContent,
145
+ KanbanCard,
146
+ KanbanCardTitle,
147
+ KanbanCardDescription,
148
+ KanbanColumnFooter,
149
+ } from './components/ui';
150
+
151
+ // ============================================================
152
+ // LEGACY EXPORTS - For backwards compatibility
153
+ // ============================================================
154
+
155
+ // Re-export everything from submodules for backwards compatibility
156
+ export * from './types';
157
+ export * from './api';
158
+ export * from './utils';
159
+ export * from './components';
16
160
  export * from './auth';
@@ -10,4 +10,7 @@ export type {
10
10
 
11
11
  // Column definition
12
12
  ColumnDefinitionType,
13
+
14
+ // State types
15
+ PaginationStateType,
13
16
  } from './components/hooks/useTable/types';
@@ -37,14 +37,15 @@ export type FilterRHSTypeType = "Constant" | "BOField" | "AppVariable";
37
37
 
38
38
  /**
39
39
  * Leaf condition (actual field comparison)
40
+ * @template T - Data type for type-safe field names (defaults to any)
40
41
  */
41
- export interface ConditionType {
42
+ export interface ConditionType<T = any> {
42
43
  /** Optional ID for hook state management (omitted in API payload) */
43
44
  id?: string;
44
45
  /** Condition operator */
45
46
  Operator: ConditionOperatorType;
46
- /** Left-hand side field name */
47
- LHSField: string;
47
+ /** Left-hand side field name (keyof T when generic is provided) */
48
+ LHSField: T extends any ? keyof T | string : string;
48
49
  /** Right-hand side value */
49
50
  RHSValue: any;
50
51
  /** Right-hand side type (optional, defaults to Constant) */
@@ -53,20 +54,22 @@ export interface ConditionType {
53
54
 
54
55
  /**
55
56
  * Group combining conditions (recursive structure)
57
+ * @template T - Data type for type-safe field names (defaults to any)
56
58
  */
57
- export interface ConditionGroupType {
59
+ export interface ConditionGroupType<T = any> {
58
60
  /** Optional ID for hook state management (omitted in API payload) */
59
61
  id?: string;
60
62
  /** Group operator (And, Or, Not) */
61
63
  Operator: ConditionGroupOperatorType;
62
64
  /** Nested conditions (can be Condition or ConditionGroup) */
63
- Condition: Array<ConditionType | ConditionGroupType>;
65
+ Condition: Array<ConditionType<T> | ConditionGroupType<T>>;
64
66
  }
65
67
 
66
68
  /**
67
69
  * Root filter type (alias for ConditionGroup)
70
+ * @template T - Data type for type-safe field names (defaults to any)
68
71
  */
69
- export type FilterType = ConditionGroupType;
72
+ export type FilterType<T = any> = ConditionGroupType<T>;
70
73
 
71
74
  /**
72
75
  * DateTime encoding format used by the API
@@ -296,3 +299,25 @@ export interface FetchFieldResponseType {
296
299
  /** Array of field options */
297
300
  Data: FetchFieldOptionType[];
298
301
  }
302
+
303
+ // ============================================================
304
+ // SHARED COMPONENT TYPES
305
+ // ============================================================
306
+
307
+ /**
308
+ * Column definition for data display and behavior
309
+ * Used by useTable and useKanban for defining field configurations
310
+ * @template T - Data type for type-safe field names
311
+ */
312
+ export interface ColumnDefinitionType<T> {
313
+ /** Field name from the data type */
314
+ fieldId: keyof T;
315
+ /** Display label (optional, defaults to fieldId) */
316
+ label?: string;
317
+ /** Enable sorting for this field */
318
+ enableSorting?: boolean;
319
+ /** Enable filtering for this field */
320
+ enableFiltering?: boolean;
321
+ /** Custom transform function (overrides auto-formatting) */
322
+ transform?: (value: any, item: T) => React.ReactNode;
323
+ }
@@ -0,0 +1,120 @@
1
+ // ============================================================
2
+ // BUILD LIST OPTIONS UTILITY
3
+ // ============================================================
4
+ // Shared utility for building API list options across hooks
5
+
6
+ import type { ListOptionsType, FilterType, SortType } from "../../types/common";
7
+
8
+ /**
9
+ * Options for building list API request options
10
+ */
11
+ export interface BuildListOptionsParams<T = any> {
12
+ /** Search query string */
13
+ search?: string;
14
+ /** Filter payload */
15
+ filter?: FilterType<T>;
16
+ /** Sort configuration */
17
+ sort?: {
18
+ field: keyof T | null;
19
+ direction: "asc" | "desc" | null;
20
+ };
21
+ /** Sort array in API format */
22
+ sortArray?: SortType;
23
+ /** Pagination settings */
24
+ pagination?: {
25
+ pageNo: number;
26
+ pageSize: number;
27
+ };
28
+ }
29
+
30
+ /**
31
+ * Build list options for count queries
32
+ * Excludes pagination and sorting (they don't affect count)
33
+ */
34
+ export function buildCountOptions<T = any>(
35
+ params: Pick<BuildListOptionsParams<T>, "search" | "filter">
36
+ ): ListOptionsType {
37
+ const opts: ListOptionsType = {};
38
+
39
+ if (params.search) {
40
+ opts.Search = params.search;
41
+ }
42
+
43
+ if (params.filter) {
44
+ opts.Filter = params.filter;
45
+ }
46
+
47
+ return opts;
48
+ }
49
+
50
+ /**
51
+ * Build list options for data queries
52
+ * Includes all options: search, filter, sort, pagination
53
+ */
54
+ export function buildListOptions<T = any>(
55
+ params: BuildListOptionsParams<T>
56
+ ): ListOptionsType {
57
+ const opts: ListOptionsType = buildCountOptions({
58
+ search: params.search,
59
+ filter: params.filter,
60
+ });
61
+
62
+ // Add sorting - convert internal format to API format
63
+ if (params.sort?.field && params.sort?.direction) {
64
+ opts.Sort = [
65
+ {
66
+ [String(params.sort.field)]:
67
+ params.sort.direction === "asc" ? "ASC" : "DESC",
68
+ },
69
+ ];
70
+ } else if (params.sortArray) {
71
+ opts.Sort = params.sortArray;
72
+ }
73
+
74
+ // Add pagination
75
+ if (params.pagination) {
76
+ opts.Page = params.pagination.pageNo;
77
+ opts.PageSize = params.pagination.pageSize;
78
+ }
79
+
80
+ return opts;
81
+ }
82
+
83
+ /**
84
+ * Combine filter payload with additional column filter
85
+ * Used for kanban column-specific queries
86
+ */
87
+ export function combineFilters<T = any>(
88
+ baseFilter: FilterType<T> | undefined,
89
+ additionalCondition: {
90
+ LHSField: string;
91
+ Operator: string;
92
+ RHSValue: any;
93
+ RHSType?: string;
94
+ }
95
+ ): FilterType<T> {
96
+ const columnFilterObject = {
97
+ ...additionalCondition,
98
+ RHSType: additionalCondition.RHSType || "Constant",
99
+ };
100
+
101
+ if (!baseFilter) {
102
+ return {
103
+ Operator: "And",
104
+ Condition: [columnFilterObject],
105
+ } as FilterType<T>;
106
+ }
107
+
108
+ // If base is And, append. If base is Or/Not, wrap in new And.
109
+ if (baseFilter.Operator === "And") {
110
+ return {
111
+ ...baseFilter,
112
+ Condition: [...(baseFilter.Condition || []), columnFilterObject],
113
+ } as FilterType<T>;
114
+ }
115
+
116
+ return {
117
+ Operator: "And",
118
+ Condition: [baseFilter, columnFilterObject],
119
+ } as FilterType<T>;
120
+ }
@@ -0,0 +1,2 @@
1
+ // API utilities
2
+ export * from "./buildListOptions";