@eztrak/shared 0.2.4 → 0.2.5

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 CHANGED
@@ -26,6 +26,27 @@ import { cn, formatDate, getApiError, isEmpty } from "@eztrak/shared/utils";
26
26
 
27
27
  `cn` combines [`clsx`](https://github.com/lukeed/clsx) with [`tailwind-merge`](https://github.com/dcastil/tailwind-merge).
28
28
 
29
+ RTK Query errors (pass your app's toast / SweetAlert):
30
+
31
+ ```js
32
+ import { handleApiError } from "@eztrak/shared/utils";
33
+ import { toast } from "react-toastify";
34
+ import Swal from "sweetalert2";
35
+
36
+ handleApiError(error, {
37
+ toast: (msg) => toast.error(msg),
38
+ showAlert: true,
39
+ alert: ({ title, html }) =>
40
+ Swal.fire({
41
+ title,
42
+ html,
43
+ icon: "error",
44
+ confirmButtonText: "OK",
45
+ confirmButtonColor: "#FF7335",
46
+ }),
47
+ });
48
+ ```
49
+
29
50
  ### Hooks
30
51
 
31
52
  ```js
@@ -45,7 +66,7 @@ import { cn, useGridHeight } from "@eztrak/shared";
45
66
  | Subpath | Description |
46
67
  | --- | --- |
47
68
  | `@eztrak/shared` | Main entry — re-exports utils and hooks |
48
- | `@eztrak/shared/utils` | `cn`, date/format helpers, API error helpers, form field helpers |
69
+ | `@eztrak/shared/utils` | `cn`, `handleApiError`, date/format helpers, API error helpers, form field helpers |
49
70
  | `@eztrak/shared/hooks` | `usePaginationUrlSync`, `useGridHeight` |
50
71
 
51
72
  ## Requirements
@@ -13,6 +13,48 @@ var truncateText = (text, maxLength = 20) => {
13
13
  }
14
14
  return text.slice(0, maxLength - 3) + "...";
15
15
  };
16
+ function formatValidationErrorsHtml(errors) {
17
+ const items = Object.keys(errors).flatMap(
18
+ (field) => (errors[field] || []).map((msg) => `<li>${msg}</li>`)
19
+ );
20
+ return `
21
+ <div style="text-align:left">
22
+ <p>Please review and correct the following:</p>
23
+ <ul style="margin:8px 0 0 16px; list-style:disc;">
24
+ ${items.join("")}
25
+ </ul>
26
+ </div>
27
+ `;
28
+ }
29
+ function handleApiError(error, { showAlert = false, fallbackMessage, toast, alert } = {}) {
30
+ if (!error) return;
31
+ const status = error.status ?? error.originalStatus;
32
+ const data = error.data;
33
+ if (status === 200) {
34
+ return;
35
+ }
36
+ if (data?.errors && typeof data.errors === "object") {
37
+ const errors = data.errors;
38
+ if (showAlert && alert) {
39
+ alert({
40
+ title: "Validation errors",
41
+ html: formatValidationErrorsHtml(errors)
42
+ });
43
+ } else if (toast) {
44
+ Object.keys(errors).forEach((field) => {
45
+ (errors[field] || []).forEach((errorMessage) => {
46
+ toast(errorMessage);
47
+ });
48
+ });
49
+ }
50
+ return;
51
+ }
52
+ if (status === 404) {
53
+ return;
54
+ }
55
+ const message = fallbackMessage || data?.message || data?.title || error.error || "An error occurred. Please try again.";
56
+ toast?.(message);
57
+ }
16
58
  function getApiError(apiError) {
17
59
  if (!apiError) return "An unknown error occurred";
18
60
  if (typeof apiError === "string") {
@@ -189,6 +231,8 @@ var getFieldsByInputType = (fields = [], key) => {
189
231
  export {
190
232
  cn,
191
233
  truncateText,
234
+ formatValidationErrorsHtml,
235
+ handleApiError,
192
236
  getApiError,
193
237
  normalizeApiListItems,
194
238
  capitalizeText,
@@ -209,4 +253,4 @@ export {
209
253
  removeByPropertyValues,
210
254
  getFieldsByInputType
211
255
  };
212
- //# sourceMappingURL=chunk-WARJTN5T.mjs.map
256
+ //# sourceMappingURL=chunk-QVRMHJS4.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/cn.ts","../src/utils/helpers.ts"],"sourcesContent":["import clsx from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: Parameters<typeof clsx>) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","export const truncateText = (text: string | null | undefined, maxLength = 20) => {\n if (!text) return \"\";\n if (text.length <= maxLength) {\n return text;\n }\n return text.slice(0, maxLength - 3) + \"...\";\n};\n\nexport type RtkQueryError = {\n status?: number | string;\n originalStatus?: number;\n data?: {\n errors?: Record<string, string[]>;\n message?: string;\n title?: string;\n };\n error?: string;\n};\n\nexport interface HandleApiErrorOptions {\n showAlert?: boolean;\n fallbackMessage?: string;\n /** Called for each validation message when showAlert is false, and for generic errors */\n toast?: (message: string) => void;\n /** Called for validation errors when showAlert is true (e.g. wire to SweetAlert) */\n alert?: (params: { title: string; html: string }) => void;\n}\n\nexport function formatValidationErrorsHtml(\n errors: Record<string, string[]>\n): string {\n const items = Object.keys(errors).flatMap((field) =>\n (errors[field] || []).map((msg) => `<li>${msg}</li>`)\n );\n return `\n <div style=\"text-align:left\">\n <p>Please review and correct the following:</p>\n <ul style=\"margin:8px 0 0 16px; list-style:disc;\">\n ${items.join(\"\")}\n </ul>\n </div>\n `;\n}\n\n/**\n * Handles RTK Query / fetchBaseQuery error shapes: validation errors, 404 (silent), and generic messages.\n * Pass `toast` and optionally `alert` from your app (react-toastify, SweetAlert, etc.).\n */\nexport function handleApiError(\n error: RtkQueryError | null | undefined,\n { showAlert = false, fallbackMessage, toast, alert }: HandleApiErrorOptions = {}\n): void {\n if (!error) return;\n\n const status = error.status ?? error.originalStatus;\n const data = error.data;\n\n if (status === 200) {\n return;\n }\n\n if (data?.errors && typeof data.errors === \"object\") {\n const errors = data.errors;\n\n if (showAlert && alert) {\n alert({\n title: \"Validation errors\",\n html: formatValidationErrorsHtml(errors),\n });\n } else if (toast) {\n Object.keys(errors).forEach((field) => {\n (errors[field] || []).forEach((errorMessage) => {\n toast(errorMessage);\n });\n });\n }\n return;\n }\n\n if (status === 404) {\n return;\n }\n\n const message =\n fallbackMessage ||\n data?.message ||\n data?.title ||\n error.error ||\n \"An error occurred. Please try again.\";\n\n toast?.(message);\n}\n\nexport function getApiError(apiError: unknown): string {\n if (!apiError) return \"An unknown error occurred\";\n\n if (typeof apiError === \"string\") {\n return apiError;\n }\n\n const error = apiError as {\n response?: { data?: Record<string, unknown> };\n message?: string;\n };\n\n if (error.response?.data) {\n const responseData = error.response.data;\n\n if (typeof responseData === \"string\") {\n return responseData;\n }\n\n const errors = responseData.errors;\n if (errors && typeof errors === \"object\") {\n for (const key in errors) {\n const messages = (errors as Record<string, unknown>)[key];\n if (Array.isArray(messages) && messages.length > 0) {\n return String(messages[0]);\n }\n }\n }\n\n if (responseData.message) {\n return String(responseData.message);\n }\n\n if (responseData.title) {\n return String(responseData.title);\n }\n }\n\n if (error.message) {\n return error.message;\n }\n\n return \"An unknown error occurred\";\n}\n\nexport const normalizeApiListItems = (responseData: unknown): unknown[] => {\n if (responseData == null) return [];\n if (Array.isArray(responseData)) return responseData;\n\n const record = responseData as Record<string, unknown>;\n const data = record.data;\n\n if (\n data &&\n typeof data === \"object\" &&\n !Array.isArray(data) &&\n Array.isArray((data as { items?: unknown[] }).items)\n ) {\n return (data as { items: unknown[] }).items;\n }\n\n const returnModel = record.returnModel as { items?: unknown[] } | undefined;\n if (Array.isArray(returnModel?.items)) return returnModel.items;\n if (Array.isArray(data)) return data;\n if (typeof data === \"object\" && data !== null) {\n return [data];\n }\n return [];\n};\n\nexport function capitalizeText(name: string | null | undefined): string {\n if (!name) return \"\";\n return name\n .split(\" \")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\" \");\n}\n\nexport function toLowerCaseText(text: string | null | undefined): string {\n if (!text) return \"\";\n return text.toLowerCase();\n}\n\nexport const formatDate = (dateString: string | null | undefined): string => {\n if (dateString === null || dateString === undefined) return \"-\";\n const date = new Date(dateString);\n\n if (isNaN(date.getTime())) {\n return dateString;\n }\n\n const month = (date.getMonth() + 1).toString().padStart(2, \"0\");\n const day = date.getDate().toString().padStart(2, \"0\");\n const year = date.getFullYear().toString().slice(-2);\n return `${month}/${day}/${year}`;\n};\n\nexport const isEmpty = (obj: object): boolean => {\n return Object.keys(obj).length === 0;\n};\n\nexport const toDateInputValue = (date: string | Date | null | undefined): string => {\n if (!date) return \"\";\n\n let d: Date;\n\n if (typeof date === \"string\") {\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\n return date;\n }\n d = new Date(date);\n } else {\n d = new Date(date);\n }\n\n if (isNaN(d.getTime())) return \"\";\n\n const localDate = new Date(d.getTime() - d.getTimezoneOffset() * 60000);\n const year = localDate.getFullYear();\n const month = (localDate.getMonth() + 1).toString().padStart(2, \"0\");\n const day = localDate.getDate().toString().padStart(2, \"0\");\n\n return `${year}-${month}-${day}`;\n};\n\nexport function convertCommaDataToArray(data: string | null | undefined): string[] {\n if (!data || data.trim() === \"\") {\n return [];\n }\n return data.split(\",\").map((item) => item.trim());\n}\n\nexport function checkIfExistsInArray<T>(array: T[], searchValue: T): boolean {\n return array.includes(searchValue);\n}\n\nexport const currencyFormatter = (value: number | null | undefined): string => {\n return value?.toLocaleString(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n }) ?? \"\";\n};\n\nexport const parseCurrencyValueToNumber = (value: unknown): number => {\n if (value == null || value === \"\") return 0;\n\n const raw =\n typeof value === \"object\" && value !== null && \"value\" in value\n ? (value as { value: unknown }).value\n : value;\n\n const stringValue = raw == null || raw === \"\" ? \"\" : String(raw);\n const numericValue = stringValue.replace(/[$,]/g, \"\");\n return parseFloat(numericValue) || 0;\n};\n\nexport function flattenTableData<T extends Record<string, unknown>>(\n data: T[] | null | undefined,\n columns: { field?: string }[] | null | undefined\n): T[] {\n if (!Array.isArray(data)) return [];\n return data.map((row) => {\n const flatRow = { ...row };\n (columns ?? []).forEach((col) => {\n const key = col.field;\n if (!key) return;\n if (key.includes(\".\")) {\n const value = key.split(\".\").reduce<unknown>(\n (acc, part) => (acc as Record<string, unknown> | undefined)?.[part],\n row\n );\n (flatRow as Record<string, unknown>)[key] = value ?? \"\";\n }\n });\n return flatRow;\n });\n}\n\nexport const getErrorMessages = (error: {\n data?: {\n errors?: Record<string, string[]>;\n title?: string;\n error?: { name?: string[] };\n };\n} | null | undefined): string => {\n if (error?.data?.errors) {\n return Object.values(error.data.errors).flat().join(\"\\n\");\n }\n return (\n error?.data?.title ??\n error?.data?.error?.name?.[0] ??\n \"Failed to save\"\n );\n};\n\nexport const getFieldsByCategory = <T extends { category?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields?.filter(({ category = \"\" }) => category === key);\n};\n\nexport const getFieldsByName = <T extends { name?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields.filter(({ name = \"\" }) => name === key);\n};\n\nexport const deserializeJson = <T = unknown>(jsonString: string): T | null => {\n try {\n return JSON.parse(jsonString) as T;\n } catch (error) {\n console.error(\"Error parsing JSON:\", error);\n return null;\n }\n};\n\nexport const formatDateTime = (dateString: string | null | undefined): string => {\n if (!dateString) return \"Invalid Date\";\n const date = new Date(dateString);\n if (isNaN(date.getTime())) return \"Invalid Date\";\n const options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"numeric\",\n hour12: true,\n };\n return date.toLocaleString(\"en-US\", options);\n};\n\nexport const removeByPropertyValues = <T extends Record<string, unknown>>(\n items: T[] = [],\n property: keyof T & string,\n values: unknown[] = [],\n { caseInsensitive = false }: { caseInsensitive?: boolean } = {}\n): T[] => {\n if (!Array.isArray(items) || !property) return Array.isArray(items) ? items : [];\n const normalize = (v: unknown) =>\n caseInsensitive && typeof v === \"string\" ? v.toLowerCase() : v;\n const valuesArr = Array.isArray(values) ? values : [values];\n const toRemove = new Set(valuesArr.map(normalize));\n return items.filter((item) => !toRemove.has(normalize(item?.[property])));\n};\n\nexport const getFieldsByInputType = <T extends { inputType?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields.filter(({ inputType = \"\" }) => inputType === key);\n};\n"],"mappings":"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","names":[]}
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- export { capitalizeText, checkIfExistsInArray, cn, convertCommaDataToArray, currencyFormatter, deserializeJson, flattenTableData, formatDate, formatDateTime, getApiError, getErrorMessages, getFieldsByCategory, getFieldsByInputType, getFieldsByName, isEmpty, normalizeApiListItems, parseCurrencyValueToNumber, removeByPropertyValues, toDateInputValue, toLowerCaseText, truncateText } from './utils/index.mjs';
1
+ export { HandleApiErrorOptions, RtkQueryError, capitalizeText, checkIfExistsInArray, cn, convertCommaDataToArray, currencyFormatter, deserializeJson, flattenTableData, formatDate, formatDateTime, formatValidationErrorsHtml, getApiError, getErrorMessages, getFieldsByCategory, getFieldsByInputType, getFieldsByName, handleApiError, isEmpty, normalizeApiListItems, parseCurrencyValueToNumber, removeByPropertyValues, toDateInputValue, toLowerCaseText, truncateText } from './utils/index.mjs';
2
2
  export { UseGridHeightOptions, useGridHeight, usePaginationUrlSync } from './hooks/index.mjs';
3
3
  import 'clsx';
4
4
  import 'react-router-dom';
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { capitalizeText, checkIfExistsInArray, cn, convertCommaDataToArray, currencyFormatter, deserializeJson, flattenTableData, formatDate, formatDateTime, getApiError, getErrorMessages, getFieldsByCategory, getFieldsByInputType, getFieldsByName, isEmpty, normalizeApiListItems, parseCurrencyValueToNumber, removeByPropertyValues, toDateInputValue, toLowerCaseText, truncateText } from './utils/index.js';
1
+ export { HandleApiErrorOptions, RtkQueryError, capitalizeText, checkIfExistsInArray, cn, convertCommaDataToArray, currencyFormatter, deserializeJson, flattenTableData, formatDate, formatDateTime, formatValidationErrorsHtml, getApiError, getErrorMessages, getFieldsByCategory, getFieldsByInputType, getFieldsByName, handleApiError, isEmpty, normalizeApiListItems, parseCurrencyValueToNumber, removeByPropertyValues, toDateInputValue, toLowerCaseText, truncateText } from './utils/index.js';
2
2
  export { UseGridHeightOptions, useGridHeight, usePaginationUrlSync } from './hooks/index.js';
3
3
  import 'clsx';
4
4
  import 'react-router-dom';
package/dist/index.js CHANGED
@@ -39,11 +39,13 @@ __export(src_exports, {
39
39
  flattenTableData: () => flattenTableData,
40
40
  formatDate: () => formatDate,
41
41
  formatDateTime: () => formatDateTime,
42
+ formatValidationErrorsHtml: () => formatValidationErrorsHtml,
42
43
  getApiError: () => getApiError,
43
44
  getErrorMessages: () => getErrorMessages,
44
45
  getFieldsByCategory: () => getFieldsByCategory,
45
46
  getFieldsByInputType: () => getFieldsByInputType,
46
47
  getFieldsByName: () => getFieldsByName,
48
+ handleApiError: () => handleApiError,
47
49
  isEmpty: () => isEmpty,
48
50
  normalizeApiListItems: () => normalizeApiListItems,
49
51
  parseCurrencyValueToNumber: () => parseCurrencyValueToNumber,
@@ -71,6 +73,48 @@ var truncateText = (text, maxLength = 20) => {
71
73
  }
72
74
  return text.slice(0, maxLength - 3) + "...";
73
75
  };
76
+ function formatValidationErrorsHtml(errors) {
77
+ const items = Object.keys(errors).flatMap(
78
+ (field) => (errors[field] || []).map((msg) => `<li>${msg}</li>`)
79
+ );
80
+ return `
81
+ <div style="text-align:left">
82
+ <p>Please review and correct the following:</p>
83
+ <ul style="margin:8px 0 0 16px; list-style:disc;">
84
+ ${items.join("")}
85
+ </ul>
86
+ </div>
87
+ `;
88
+ }
89
+ function handleApiError(error, { showAlert = false, fallbackMessage, toast, alert } = {}) {
90
+ if (!error) return;
91
+ const status = error.status ?? error.originalStatus;
92
+ const data = error.data;
93
+ if (status === 200) {
94
+ return;
95
+ }
96
+ if (data?.errors && typeof data.errors === "object") {
97
+ const errors = data.errors;
98
+ if (showAlert && alert) {
99
+ alert({
100
+ title: "Validation errors",
101
+ html: formatValidationErrorsHtml(errors)
102
+ });
103
+ } else if (toast) {
104
+ Object.keys(errors).forEach((field) => {
105
+ (errors[field] || []).forEach((errorMessage) => {
106
+ toast(errorMessage);
107
+ });
108
+ });
109
+ }
110
+ return;
111
+ }
112
+ if (status === 404) {
113
+ return;
114
+ }
115
+ const message = fallbackMessage || data?.message || data?.title || error.error || "An error occurred. Please try again.";
116
+ toast?.(message);
117
+ }
74
118
  function getApiError(apiError) {
75
119
  if (!apiError) return "An unknown error occurred";
76
120
  if (typeof apiError === "string") {
@@ -321,11 +365,13 @@ var useGridHeight = ({
321
365
  flattenTableData,
322
366
  formatDate,
323
367
  formatDateTime,
368
+ formatValidationErrorsHtml,
324
369
  getApiError,
325
370
  getErrorMessages,
326
371
  getFieldsByCategory,
327
372
  getFieldsByInputType,
328
373
  getFieldsByName,
374
+ handleApiError,
329
375
  isEmpty,
330
376
  normalizeApiListItems,
331
377
  parseCurrencyValueToNumber,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/utils/cn.ts","../src/utils/helpers.ts","../src/hooks/usePaginationUrlSync.ts","../src/hooks/useGridHeight.ts"],"sourcesContent":["export * from \"./utils\";\nexport * from \"./hooks\";\n","import clsx from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: Parameters<typeof clsx>) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","export const truncateText = (text: string | null | undefined, maxLength = 20) => {\n if (!text) return \"\";\n if (text.length <= maxLength) {\n return text;\n }\n return text.slice(0, maxLength - 3) + \"...\";\n};\n\nexport function getApiError(apiError: unknown): string {\n if (!apiError) return \"An unknown error occurred\";\n\n if (typeof apiError === \"string\") {\n return apiError;\n }\n\n const error = apiError as {\n response?: { data?: Record<string, unknown> };\n message?: string;\n };\n\n if (error.response?.data) {\n const responseData = error.response.data;\n\n if (typeof responseData === \"string\") {\n return responseData;\n }\n\n const errors = responseData.errors;\n if (errors && typeof errors === \"object\") {\n for (const key in errors) {\n const messages = (errors as Record<string, unknown>)[key];\n if (Array.isArray(messages) && messages.length > 0) {\n return String(messages[0]);\n }\n }\n }\n\n if (responseData.message) {\n return String(responseData.message);\n }\n\n if (responseData.title) {\n return String(responseData.title);\n }\n }\n\n if (error.message) {\n return error.message;\n }\n\n return \"An unknown error occurred\";\n}\n\nexport const normalizeApiListItems = (responseData: unknown): unknown[] => {\n if (responseData == null) return [];\n if (Array.isArray(responseData)) return responseData;\n\n const record = responseData as Record<string, unknown>;\n const data = record.data;\n\n if (\n data &&\n typeof data === \"object\" &&\n !Array.isArray(data) &&\n Array.isArray((data as { items?: unknown[] }).items)\n ) {\n return (data as { items: unknown[] }).items;\n }\n\n const returnModel = record.returnModel as { items?: unknown[] } | undefined;\n if (Array.isArray(returnModel?.items)) return returnModel.items;\n if (Array.isArray(data)) return data;\n if (typeof data === \"object\" && data !== null) {\n return [data];\n }\n return [];\n};\n\nexport function capitalizeText(name: string | null | undefined): string {\n if (!name) return \"\";\n return name\n .split(\" \")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\" \");\n}\n\nexport function toLowerCaseText(text: string | null | undefined): string {\n if (!text) return \"\";\n return text.toLowerCase();\n}\n\nexport const formatDate = (dateString: string | null | undefined): string => {\n if (dateString === null || dateString === undefined) return \"-\";\n const date = new Date(dateString);\n\n if (isNaN(date.getTime())) {\n return dateString;\n }\n\n const month = (date.getMonth() + 1).toString().padStart(2, \"0\");\n const day = date.getDate().toString().padStart(2, \"0\");\n const year = date.getFullYear().toString().slice(-2);\n return `${month}/${day}/${year}`;\n};\n\nexport const isEmpty = (obj: object): boolean => {\n return Object.keys(obj).length === 0;\n};\n\nexport const toDateInputValue = (date: string | Date | null | undefined): string => {\n if (!date) return \"\";\n\n let d: Date;\n\n if (typeof date === \"string\") {\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\n return date;\n }\n d = new Date(date);\n } else {\n d = new Date(date);\n }\n\n if (isNaN(d.getTime())) return \"\";\n\n const localDate = new Date(d.getTime() - d.getTimezoneOffset() * 60000);\n const year = localDate.getFullYear();\n const month = (localDate.getMonth() + 1).toString().padStart(2, \"0\");\n const day = localDate.getDate().toString().padStart(2, \"0\");\n\n return `${year}-${month}-${day}`;\n};\n\nexport function convertCommaDataToArray(data: string | null | undefined): string[] {\n if (!data || data.trim() === \"\") {\n return [];\n }\n return data.split(\",\").map((item) => item.trim());\n}\n\nexport function checkIfExistsInArray<T>(array: T[], searchValue: T): boolean {\n return array.includes(searchValue);\n}\n\nexport const currencyFormatter = (value: number | null | undefined): string => {\n return value?.toLocaleString(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n }) ?? \"\";\n};\n\nexport const parseCurrencyValueToNumber = (value: unknown): number => {\n if (value == null || value === \"\") return 0;\n\n const raw =\n typeof value === \"object\" && value !== null && \"value\" in value\n ? (value as { value: unknown }).value\n : value;\n\n const stringValue = raw == null || raw === \"\" ? \"\" : String(raw);\n const numericValue = stringValue.replace(/[$,]/g, \"\");\n return parseFloat(numericValue) || 0;\n};\n\nexport function flattenTableData<T extends Record<string, unknown>>(\n data: T[] | null | undefined,\n columns: { field?: string }[] | null | undefined\n): T[] {\n if (!Array.isArray(data)) return [];\n return data.map((row) => {\n const flatRow = { ...row };\n (columns ?? []).forEach((col) => {\n const key = col.field;\n if (!key) return;\n if (key.includes(\".\")) {\n const value = key.split(\".\").reduce<unknown>(\n (acc, part) => (acc as Record<string, unknown> | undefined)?.[part],\n row\n );\n (flatRow as Record<string, unknown>)[key] = value ?? \"\";\n }\n });\n return flatRow;\n });\n}\n\nexport const getErrorMessages = (error: {\n data?: {\n errors?: Record<string, string[]>;\n title?: string;\n error?: { name?: string[] };\n };\n} | null | undefined): string => {\n if (error?.data?.errors) {\n return Object.values(error.data.errors).flat().join(\"\\n\");\n }\n return (\n error?.data?.title ??\n error?.data?.error?.name?.[0] ??\n \"Failed to save\"\n );\n};\n\nexport const getFieldsByCategory = <T extends { category?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields?.filter(({ category = \"\" }) => category === key);\n};\n\nexport const getFieldsByName = <T extends { name?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields.filter(({ name = \"\" }) => name === key);\n};\n\nexport const deserializeJson = <T = unknown>(jsonString: string): T | null => {\n try {\n return JSON.parse(jsonString) as T;\n } catch (error) {\n console.error(\"Error parsing JSON:\", error);\n return null;\n }\n};\n\nexport const formatDateTime = (dateString: string | null | undefined): string => {\n if (!dateString) return \"Invalid Date\";\n const date = new Date(dateString);\n if (isNaN(date.getTime())) return \"Invalid Date\";\n const options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"numeric\",\n hour12: true,\n };\n return date.toLocaleString(\"en-US\", options);\n};\n\nexport const removeByPropertyValues = <T extends Record<string, unknown>>(\n items: T[] = [],\n property: keyof T & string,\n values: unknown[] = [],\n { caseInsensitive = false }: { caseInsensitive?: boolean } = {}\n): T[] => {\n if (!Array.isArray(items) || !property) return Array.isArray(items) ? items : [];\n const normalize = (v: unknown) =>\n caseInsensitive && typeof v === \"string\" ? v.toLowerCase() : v;\n const valuesArr = Array.isArray(values) ? values : [values];\n const toRemove = new Set(valuesArr.map(normalize));\n return items.filter((item) => !toRemove.has(normalize(item?.[property])));\n};\n\nexport const getFieldsByInputType = <T extends { inputType?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields.filter(({ inputType = \"\" }) => inputType === key);\n};\n","import { useEffect } from \"react\";\nimport type { SetURLSearchParams } from \"react-router-dom\";\n\nexport const usePaginationUrlSync = (\n searchParams: URLSearchParams,\n setSearchParams: SetURLSearchParams,\n page: number,\n setPage: (page: number) => void,\n perPage: number,\n setPerPage: (perPage: number) => void,\n defaultPage = 1,\n defaultPerPage = 20\n) => {\n useEffect(() => {\n const currentUrlPage = parseInt(searchParams.get(\"page\") ?? \"\") || defaultPage;\n const currentUrlPerPage =\n parseInt(searchParams.get(\"perPage\") ?? \"\") || defaultPerPage;\n const hasPageParam = searchParams.has(\"page\");\n const hasPerPageParam = searchParams.has(\"perPage\");\n\n if (!hasPageParam || !hasPerPageParam) {\n const newParams = new URLSearchParams(searchParams);\n\n if (!hasPageParam) {\n newParams.set(\"page\", defaultPage.toString());\n }\n\n if (!hasPerPageParam) {\n newParams.set(\"perPage\", defaultPerPage.toString());\n }\n\n setSearchParams(newParams, { replace: true });\n return;\n }\n\n if (currentUrlPage !== page) {\n setPage(currentUrlPage);\n }\n\n if (currentUrlPerPage !== perPage) {\n setPerPage(currentUrlPerPage);\n }\n }, [\n searchParams,\n setSearchParams,\n page,\n setPage,\n perPage,\n setPerPage,\n defaultPage,\n defaultPerPage,\n ]);\n};\n","import { useEffect, useState } from \"react\";\n\nexport interface UseGridHeightOptions {\n height?: string;\n headerId?: string;\n footerId?: string;\n offset?: number;\n}\n\nexport const useGridHeight = ({\n height,\n headerId = \"layout-header\",\n footerId = \"layout-footer\",\n offset = 390,\n}: UseGridHeightOptions = {}) => {\n const [gridHeight, setGridHeight] = useState(height || \"300px\");\n\n useEffect(() => {\n if (height) {\n setGridHeight(height);\n return;\n }\n\n const calculateHeight = () => {\n const header = document.getElementById(headerId);\n const footer = document.getElementById(footerId);\n\n const headerHeight = header ? header.offsetHeight : 0;\n const footerHeight = footer ? footer.offsetHeight : 0;\n const totalHeight = window.innerHeight;\n\n const remainingHeight = totalHeight - headerHeight - footerHeight - offset;\n setGridHeight(`${remainingHeight}px`);\n };\n\n calculateHeight();\n window.addEventListener(\"resize\", calculateHeight);\n return () => window.removeEventListener(\"resize\", calculateHeight);\n }, [height, headerId, footerId, offset]);\n\n return gridHeight;\n};\n"],"mappings":"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","names":["clsx","import_react"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/utils/cn.ts","../src/utils/helpers.ts","../src/hooks/usePaginationUrlSync.ts","../src/hooks/useGridHeight.ts"],"sourcesContent":["export * from \"./utils\";\nexport * from \"./hooks\";\n","import clsx from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: Parameters<typeof clsx>) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","export const truncateText = (text: string | null | undefined, maxLength = 20) => {\n if (!text) return \"\";\n if (text.length <= maxLength) {\n return text;\n }\n return text.slice(0, maxLength - 3) + \"...\";\n};\n\nexport type RtkQueryError = {\n status?: number | string;\n originalStatus?: number;\n data?: {\n errors?: Record<string, string[]>;\n message?: string;\n title?: string;\n };\n error?: string;\n};\n\nexport interface HandleApiErrorOptions {\n showAlert?: boolean;\n fallbackMessage?: string;\n /** Called for each validation message when showAlert is false, and for generic errors */\n toast?: (message: string) => void;\n /** Called for validation errors when showAlert is true (e.g. wire to SweetAlert) */\n alert?: (params: { title: string; html: string }) => void;\n}\n\nexport function formatValidationErrorsHtml(\n errors: Record<string, string[]>\n): string {\n const items = Object.keys(errors).flatMap((field) =>\n (errors[field] || []).map((msg) => `<li>${msg}</li>`)\n );\n return `\n <div style=\"text-align:left\">\n <p>Please review and correct the following:</p>\n <ul style=\"margin:8px 0 0 16px; list-style:disc;\">\n ${items.join(\"\")}\n </ul>\n </div>\n `;\n}\n\n/**\n * Handles RTK Query / fetchBaseQuery error shapes: validation errors, 404 (silent), and generic messages.\n * Pass `toast` and optionally `alert` from your app (react-toastify, SweetAlert, etc.).\n */\nexport function handleApiError(\n error: RtkQueryError | null | undefined,\n { showAlert = false, fallbackMessage, toast, alert }: HandleApiErrorOptions = {}\n): void {\n if (!error) return;\n\n const status = error.status ?? error.originalStatus;\n const data = error.data;\n\n if (status === 200) {\n return;\n }\n\n if (data?.errors && typeof data.errors === \"object\") {\n const errors = data.errors;\n\n if (showAlert && alert) {\n alert({\n title: \"Validation errors\",\n html: formatValidationErrorsHtml(errors),\n });\n } else if (toast) {\n Object.keys(errors).forEach((field) => {\n (errors[field] || []).forEach((errorMessage) => {\n toast(errorMessage);\n });\n });\n }\n return;\n }\n\n if (status === 404) {\n return;\n }\n\n const message =\n fallbackMessage ||\n data?.message ||\n data?.title ||\n error.error ||\n \"An error occurred. Please try again.\";\n\n toast?.(message);\n}\n\nexport function getApiError(apiError: unknown): string {\n if (!apiError) return \"An unknown error occurred\";\n\n if (typeof apiError === \"string\") {\n return apiError;\n }\n\n const error = apiError as {\n response?: { data?: Record<string, unknown> };\n message?: string;\n };\n\n if (error.response?.data) {\n const responseData = error.response.data;\n\n if (typeof responseData === \"string\") {\n return responseData;\n }\n\n const errors = responseData.errors;\n if (errors && typeof errors === \"object\") {\n for (const key in errors) {\n const messages = (errors as Record<string, unknown>)[key];\n if (Array.isArray(messages) && messages.length > 0) {\n return String(messages[0]);\n }\n }\n }\n\n if (responseData.message) {\n return String(responseData.message);\n }\n\n if (responseData.title) {\n return String(responseData.title);\n }\n }\n\n if (error.message) {\n return error.message;\n }\n\n return \"An unknown error occurred\";\n}\n\nexport const normalizeApiListItems = (responseData: unknown): unknown[] => {\n if (responseData == null) return [];\n if (Array.isArray(responseData)) return responseData;\n\n const record = responseData as Record<string, unknown>;\n const data = record.data;\n\n if (\n data &&\n typeof data === \"object\" &&\n !Array.isArray(data) &&\n Array.isArray((data as { items?: unknown[] }).items)\n ) {\n return (data as { items: unknown[] }).items;\n }\n\n const returnModel = record.returnModel as { items?: unknown[] } | undefined;\n if (Array.isArray(returnModel?.items)) return returnModel.items;\n if (Array.isArray(data)) return data;\n if (typeof data === \"object\" && data !== null) {\n return [data];\n }\n return [];\n};\n\nexport function capitalizeText(name: string | null | undefined): string {\n if (!name) return \"\";\n return name\n .split(\" \")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\" \");\n}\n\nexport function toLowerCaseText(text: string | null | undefined): string {\n if (!text) return \"\";\n return text.toLowerCase();\n}\n\nexport const formatDate = (dateString: string | null | undefined): string => {\n if (dateString === null || dateString === undefined) return \"-\";\n const date = new Date(dateString);\n\n if (isNaN(date.getTime())) {\n return dateString;\n }\n\n const month = (date.getMonth() + 1).toString().padStart(2, \"0\");\n const day = date.getDate().toString().padStart(2, \"0\");\n const year = date.getFullYear().toString().slice(-2);\n return `${month}/${day}/${year}`;\n};\n\nexport const isEmpty = (obj: object): boolean => {\n return Object.keys(obj).length === 0;\n};\n\nexport const toDateInputValue = (date: string | Date | null | undefined): string => {\n if (!date) return \"\";\n\n let d: Date;\n\n if (typeof date === \"string\") {\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\n return date;\n }\n d = new Date(date);\n } else {\n d = new Date(date);\n }\n\n if (isNaN(d.getTime())) return \"\";\n\n const localDate = new Date(d.getTime() - d.getTimezoneOffset() * 60000);\n const year = localDate.getFullYear();\n const month = (localDate.getMonth() + 1).toString().padStart(2, \"0\");\n const day = localDate.getDate().toString().padStart(2, \"0\");\n\n return `${year}-${month}-${day}`;\n};\n\nexport function convertCommaDataToArray(data: string | null | undefined): string[] {\n if (!data || data.trim() === \"\") {\n return [];\n }\n return data.split(\",\").map((item) => item.trim());\n}\n\nexport function checkIfExistsInArray<T>(array: T[], searchValue: T): boolean {\n return array.includes(searchValue);\n}\n\nexport const currencyFormatter = (value: number | null | undefined): string => {\n return value?.toLocaleString(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n }) ?? \"\";\n};\n\nexport const parseCurrencyValueToNumber = (value: unknown): number => {\n if (value == null || value === \"\") return 0;\n\n const raw =\n typeof value === \"object\" && value !== null && \"value\" in value\n ? (value as { value: unknown }).value\n : value;\n\n const stringValue = raw == null || raw === \"\" ? \"\" : String(raw);\n const numericValue = stringValue.replace(/[$,]/g, \"\");\n return parseFloat(numericValue) || 0;\n};\n\nexport function flattenTableData<T extends Record<string, unknown>>(\n data: T[] | null | undefined,\n columns: { field?: string }[] | null | undefined\n): T[] {\n if (!Array.isArray(data)) return [];\n return data.map((row) => {\n const flatRow = { ...row };\n (columns ?? []).forEach((col) => {\n const key = col.field;\n if (!key) return;\n if (key.includes(\".\")) {\n const value = key.split(\".\").reduce<unknown>(\n (acc, part) => (acc as Record<string, unknown> | undefined)?.[part],\n row\n );\n (flatRow as Record<string, unknown>)[key] = value ?? \"\";\n }\n });\n return flatRow;\n });\n}\n\nexport const getErrorMessages = (error: {\n data?: {\n errors?: Record<string, string[]>;\n title?: string;\n error?: { name?: string[] };\n };\n} | null | undefined): string => {\n if (error?.data?.errors) {\n return Object.values(error.data.errors).flat().join(\"\\n\");\n }\n return (\n error?.data?.title ??\n error?.data?.error?.name?.[0] ??\n \"Failed to save\"\n );\n};\n\nexport const getFieldsByCategory = <T extends { category?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields?.filter(({ category = \"\" }) => category === key);\n};\n\nexport const getFieldsByName = <T extends { name?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields.filter(({ name = \"\" }) => name === key);\n};\n\nexport const deserializeJson = <T = unknown>(jsonString: string): T | null => {\n try {\n return JSON.parse(jsonString) as T;\n } catch (error) {\n console.error(\"Error parsing JSON:\", error);\n return null;\n }\n};\n\nexport const formatDateTime = (dateString: string | null | undefined): string => {\n if (!dateString) return \"Invalid Date\";\n const date = new Date(dateString);\n if (isNaN(date.getTime())) return \"Invalid Date\";\n const options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"numeric\",\n hour12: true,\n };\n return date.toLocaleString(\"en-US\", options);\n};\n\nexport const removeByPropertyValues = <T extends Record<string, unknown>>(\n items: T[] = [],\n property: keyof T & string,\n values: unknown[] = [],\n { caseInsensitive = false }: { caseInsensitive?: boolean } = {}\n): T[] => {\n if (!Array.isArray(items) || !property) return Array.isArray(items) ? items : [];\n const normalize = (v: unknown) =>\n caseInsensitive && typeof v === \"string\" ? v.toLowerCase() : v;\n const valuesArr = Array.isArray(values) ? values : [values];\n const toRemove = new Set(valuesArr.map(normalize));\n return items.filter((item) => !toRemove.has(normalize(item?.[property])));\n};\n\nexport const getFieldsByInputType = <T extends { inputType?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields.filter(({ inputType = \"\" }) => inputType === key);\n};\n","import { useEffect } from \"react\";\nimport type { SetURLSearchParams } from \"react-router-dom\";\n\nexport const usePaginationUrlSync = (\n searchParams: URLSearchParams,\n setSearchParams: SetURLSearchParams,\n page: number,\n setPage: (page: number) => void,\n perPage: number,\n setPerPage: (perPage: number) => void,\n defaultPage = 1,\n defaultPerPage = 20\n) => {\n useEffect(() => {\n const currentUrlPage = parseInt(searchParams.get(\"page\") ?? \"\") || defaultPage;\n const currentUrlPerPage =\n parseInt(searchParams.get(\"perPage\") ?? \"\") || defaultPerPage;\n const hasPageParam = searchParams.has(\"page\");\n const hasPerPageParam = searchParams.has(\"perPage\");\n\n if (!hasPageParam || !hasPerPageParam) {\n const newParams = new URLSearchParams(searchParams);\n\n if (!hasPageParam) {\n newParams.set(\"page\", defaultPage.toString());\n }\n\n if (!hasPerPageParam) {\n newParams.set(\"perPage\", defaultPerPage.toString());\n }\n\n setSearchParams(newParams, { replace: true });\n return;\n }\n\n if (currentUrlPage !== page) {\n setPage(currentUrlPage);\n }\n\n if (currentUrlPerPage !== perPage) {\n setPerPage(currentUrlPerPage);\n }\n }, [\n searchParams,\n setSearchParams,\n page,\n setPage,\n perPage,\n setPerPage,\n defaultPage,\n defaultPerPage,\n ]);\n};\n","import { useEffect, useState } from \"react\";\n\nexport interface UseGridHeightOptions {\n height?: string;\n headerId?: string;\n footerId?: string;\n offset?: number;\n}\n\nexport const useGridHeight = ({\n height,\n headerId = \"layout-header\",\n footerId = \"layout-footer\",\n offset = 390,\n}: UseGridHeightOptions = {}) => {\n const [gridHeight, setGridHeight] = useState(height || \"300px\");\n\n useEffect(() => {\n if (height) {\n setGridHeight(height);\n return;\n }\n\n const calculateHeight = () => {\n const header = document.getElementById(headerId);\n const footer = document.getElementById(footerId);\n\n const headerHeight = header ? header.offsetHeight : 0;\n const footerHeight = footer ? footer.offsetHeight : 0;\n const totalHeight = window.innerHeight;\n\n const remainingHeight = totalHeight - headerHeight - footerHeight - offset;\n setGridHeight(`${remainingHeight}px`);\n };\n\n calculateHeight();\n window.addEventListener(\"resize\", calculateHeight);\n return () => window.removeEventListener(\"resize\", calculateHeight);\n }, [height, headerId, footerId, offset]);\n\n return gridHeight;\n};\n"],"mappings":"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","names":["clsx","import_react"]}
package/dist/index.mjs CHANGED
@@ -8,11 +8,13 @@ import {
8
8
  flattenTableData,
9
9
  formatDate,
10
10
  formatDateTime,
11
+ formatValidationErrorsHtml,
11
12
  getApiError,
12
13
  getErrorMessages,
13
14
  getFieldsByCategory,
14
15
  getFieldsByInputType,
15
16
  getFieldsByName,
17
+ handleApiError,
16
18
  isEmpty,
17
19
  normalizeApiListItems,
18
20
  parseCurrencyValueToNumber,
@@ -20,7 +22,7 @@ import {
20
22
  toDateInputValue,
21
23
  toLowerCaseText,
22
24
  truncateText
23
- } from "./chunk-WARJTN5T.mjs";
25
+ } from "./chunk-QVRMHJS4.mjs";
24
26
  import {
25
27
  useGridHeight,
26
28
  usePaginationUrlSync
@@ -35,11 +37,13 @@ export {
35
37
  flattenTableData,
36
38
  formatDate,
37
39
  formatDateTime,
40
+ formatValidationErrorsHtml,
38
41
  getApiError,
39
42
  getErrorMessages,
40
43
  getFieldsByCategory,
41
44
  getFieldsByInputType,
42
45
  getFieldsByName,
46
+ handleApiError,
43
47
  isEmpty,
44
48
  normalizeApiListItems,
45
49
  parseCurrencyValueToNumber,
@@ -3,6 +3,33 @@ import clsx from 'clsx';
3
3
  declare function cn(...inputs: Parameters<typeof clsx>): string;
4
4
 
5
5
  declare const truncateText: (text: string | null | undefined, maxLength?: number) => string;
6
+ type RtkQueryError = {
7
+ status?: number | string;
8
+ originalStatus?: number;
9
+ data?: {
10
+ errors?: Record<string, string[]>;
11
+ message?: string;
12
+ title?: string;
13
+ };
14
+ error?: string;
15
+ };
16
+ interface HandleApiErrorOptions {
17
+ showAlert?: boolean;
18
+ fallbackMessage?: string;
19
+ /** Called for each validation message when showAlert is false, and for generic errors */
20
+ toast?: (message: string) => void;
21
+ /** Called for validation errors when showAlert is true (e.g. wire to SweetAlert) */
22
+ alert?: (params: {
23
+ title: string;
24
+ html: string;
25
+ }) => void;
26
+ }
27
+ declare function formatValidationErrorsHtml(errors: Record<string, string[]>): string;
28
+ /**
29
+ * Handles RTK Query / fetchBaseQuery error shapes: validation errors, 404 (silent), and generic messages.
30
+ * Pass `toast` and optionally `alert` from your app (react-toastify, SweetAlert, etc.).
31
+ */
32
+ declare function handleApiError(error: RtkQueryError | null | undefined, { showAlert, fallbackMessage, toast, alert }?: HandleApiErrorOptions): void;
6
33
  declare function getApiError(apiError: unknown): string;
7
34
  declare const normalizeApiListItems: (responseData: unknown) => unknown[];
8
35
  declare function capitalizeText(name: string | null | undefined): string;
@@ -41,4 +68,4 @@ declare const getFieldsByInputType: <T extends {
41
68
  inputType?: string;
42
69
  }>(fields: T[] | undefined, key: string) => T[];
43
70
 
44
- export { capitalizeText, checkIfExistsInArray, cn, convertCommaDataToArray, currencyFormatter, deserializeJson, flattenTableData, formatDate, formatDateTime, getApiError, getErrorMessages, getFieldsByCategory, getFieldsByInputType, getFieldsByName, isEmpty, normalizeApiListItems, parseCurrencyValueToNumber, removeByPropertyValues, toDateInputValue, toLowerCaseText, truncateText };
71
+ export { type HandleApiErrorOptions, type RtkQueryError, capitalizeText, checkIfExistsInArray, cn, convertCommaDataToArray, currencyFormatter, deserializeJson, flattenTableData, formatDate, formatDateTime, formatValidationErrorsHtml, getApiError, getErrorMessages, getFieldsByCategory, getFieldsByInputType, getFieldsByName, handleApiError, isEmpty, normalizeApiListItems, parseCurrencyValueToNumber, removeByPropertyValues, toDateInputValue, toLowerCaseText, truncateText };
@@ -3,6 +3,33 @@ import clsx from 'clsx';
3
3
  declare function cn(...inputs: Parameters<typeof clsx>): string;
4
4
 
5
5
  declare const truncateText: (text: string | null | undefined, maxLength?: number) => string;
6
+ type RtkQueryError = {
7
+ status?: number | string;
8
+ originalStatus?: number;
9
+ data?: {
10
+ errors?: Record<string, string[]>;
11
+ message?: string;
12
+ title?: string;
13
+ };
14
+ error?: string;
15
+ };
16
+ interface HandleApiErrorOptions {
17
+ showAlert?: boolean;
18
+ fallbackMessage?: string;
19
+ /** Called for each validation message when showAlert is false, and for generic errors */
20
+ toast?: (message: string) => void;
21
+ /** Called for validation errors when showAlert is true (e.g. wire to SweetAlert) */
22
+ alert?: (params: {
23
+ title: string;
24
+ html: string;
25
+ }) => void;
26
+ }
27
+ declare function formatValidationErrorsHtml(errors: Record<string, string[]>): string;
28
+ /**
29
+ * Handles RTK Query / fetchBaseQuery error shapes: validation errors, 404 (silent), and generic messages.
30
+ * Pass `toast` and optionally `alert` from your app (react-toastify, SweetAlert, etc.).
31
+ */
32
+ declare function handleApiError(error: RtkQueryError | null | undefined, { showAlert, fallbackMessage, toast, alert }?: HandleApiErrorOptions): void;
6
33
  declare function getApiError(apiError: unknown): string;
7
34
  declare const normalizeApiListItems: (responseData: unknown) => unknown[];
8
35
  declare function capitalizeText(name: string | null | undefined): string;
@@ -41,4 +68,4 @@ declare const getFieldsByInputType: <T extends {
41
68
  inputType?: string;
42
69
  }>(fields: T[] | undefined, key: string) => T[];
43
70
 
44
- export { capitalizeText, checkIfExistsInArray, cn, convertCommaDataToArray, currencyFormatter, deserializeJson, flattenTableData, formatDate, formatDateTime, getApiError, getErrorMessages, getFieldsByCategory, getFieldsByInputType, getFieldsByName, isEmpty, normalizeApiListItems, parseCurrencyValueToNumber, removeByPropertyValues, toDateInputValue, toLowerCaseText, truncateText };
71
+ export { type HandleApiErrorOptions, type RtkQueryError, capitalizeText, checkIfExistsInArray, cn, convertCommaDataToArray, currencyFormatter, deserializeJson, flattenTableData, formatDate, formatDateTime, formatValidationErrorsHtml, getApiError, getErrorMessages, getFieldsByCategory, getFieldsByInputType, getFieldsByName, handleApiError, isEmpty, normalizeApiListItems, parseCurrencyValueToNumber, removeByPropertyValues, toDateInputValue, toLowerCaseText, truncateText };
@@ -39,11 +39,13 @@ __export(utils_exports, {
39
39
  flattenTableData: () => flattenTableData,
40
40
  formatDate: () => formatDate,
41
41
  formatDateTime: () => formatDateTime,
42
+ formatValidationErrorsHtml: () => formatValidationErrorsHtml,
42
43
  getApiError: () => getApiError,
43
44
  getErrorMessages: () => getErrorMessages,
44
45
  getFieldsByCategory: () => getFieldsByCategory,
45
46
  getFieldsByInputType: () => getFieldsByInputType,
46
47
  getFieldsByName: () => getFieldsByName,
48
+ handleApiError: () => handleApiError,
47
49
  isEmpty: () => isEmpty,
48
50
  normalizeApiListItems: () => normalizeApiListItems,
49
51
  parseCurrencyValueToNumber: () => parseCurrencyValueToNumber,
@@ -69,6 +71,48 @@ var truncateText = (text, maxLength = 20) => {
69
71
  }
70
72
  return text.slice(0, maxLength - 3) + "...";
71
73
  };
74
+ function formatValidationErrorsHtml(errors) {
75
+ const items = Object.keys(errors).flatMap(
76
+ (field) => (errors[field] || []).map((msg) => `<li>${msg}</li>`)
77
+ );
78
+ return `
79
+ <div style="text-align:left">
80
+ <p>Please review and correct the following:</p>
81
+ <ul style="margin:8px 0 0 16px; list-style:disc;">
82
+ ${items.join("")}
83
+ </ul>
84
+ </div>
85
+ `;
86
+ }
87
+ function handleApiError(error, { showAlert = false, fallbackMessage, toast, alert } = {}) {
88
+ if (!error) return;
89
+ const status = error.status ?? error.originalStatus;
90
+ const data = error.data;
91
+ if (status === 200) {
92
+ return;
93
+ }
94
+ if (data?.errors && typeof data.errors === "object") {
95
+ const errors = data.errors;
96
+ if (showAlert && alert) {
97
+ alert({
98
+ title: "Validation errors",
99
+ html: formatValidationErrorsHtml(errors)
100
+ });
101
+ } else if (toast) {
102
+ Object.keys(errors).forEach((field) => {
103
+ (errors[field] || []).forEach((errorMessage) => {
104
+ toast(errorMessage);
105
+ });
106
+ });
107
+ }
108
+ return;
109
+ }
110
+ if (status === 404) {
111
+ return;
112
+ }
113
+ const message = fallbackMessage || data?.message || data?.title || error.error || "An error occurred. Please try again.";
114
+ toast?.(message);
115
+ }
72
116
  function getApiError(apiError) {
73
117
  if (!apiError) return "An unknown error occurred";
74
118
  if (typeof apiError === "string") {
@@ -252,11 +296,13 @@ var getFieldsByInputType = (fields = [], key) => {
252
296
  flattenTableData,
253
297
  formatDate,
254
298
  formatDateTime,
299
+ formatValidationErrorsHtml,
255
300
  getApiError,
256
301
  getErrorMessages,
257
302
  getFieldsByCategory,
258
303
  getFieldsByInputType,
259
304
  getFieldsByName,
305
+ handleApiError,
260
306
  isEmpty,
261
307
  normalizeApiListItems,
262
308
  parseCurrencyValueToNumber,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/index.ts","../../src/utils/cn.ts","../../src/utils/helpers.ts"],"sourcesContent":["export { cn } from \"./cn\";\r\nexport * from \"./helpers\";\r\n","import clsx from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: Parameters<typeof clsx>) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","export const truncateText = (text: string | null | undefined, maxLength = 20) => {\n if (!text) return \"\";\n if (text.length <= maxLength) {\n return text;\n }\n return text.slice(0, maxLength - 3) + \"...\";\n};\n\nexport function getApiError(apiError: unknown): string {\n if (!apiError) return \"An unknown error occurred\";\n\n if (typeof apiError === \"string\") {\n return apiError;\n }\n\n const error = apiError as {\n response?: { data?: Record<string, unknown> };\n message?: string;\n };\n\n if (error.response?.data) {\n const responseData = error.response.data;\n\n if (typeof responseData === \"string\") {\n return responseData;\n }\n\n const errors = responseData.errors;\n if (errors && typeof errors === \"object\") {\n for (const key in errors) {\n const messages = (errors as Record<string, unknown>)[key];\n if (Array.isArray(messages) && messages.length > 0) {\n return String(messages[0]);\n }\n }\n }\n\n if (responseData.message) {\n return String(responseData.message);\n }\n\n if (responseData.title) {\n return String(responseData.title);\n }\n }\n\n if (error.message) {\n return error.message;\n }\n\n return \"An unknown error occurred\";\n}\n\nexport const normalizeApiListItems = (responseData: unknown): unknown[] => {\n if (responseData == null) return [];\n if (Array.isArray(responseData)) return responseData;\n\n const record = responseData as Record<string, unknown>;\n const data = record.data;\n\n if (\n data &&\n typeof data === \"object\" &&\n !Array.isArray(data) &&\n Array.isArray((data as { items?: unknown[] }).items)\n ) {\n return (data as { items: unknown[] }).items;\n }\n\n const returnModel = record.returnModel as { items?: unknown[] } | undefined;\n if (Array.isArray(returnModel?.items)) return returnModel.items;\n if (Array.isArray(data)) return data;\n if (typeof data === \"object\" && data !== null) {\n return [data];\n }\n return [];\n};\n\nexport function capitalizeText(name: string | null | undefined): string {\n if (!name) return \"\";\n return name\n .split(\" \")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\" \");\n}\n\nexport function toLowerCaseText(text: string | null | undefined): string {\n if (!text) return \"\";\n return text.toLowerCase();\n}\n\nexport const formatDate = (dateString: string | null | undefined): string => {\n if (dateString === null || dateString === undefined) return \"-\";\n const date = new Date(dateString);\n\n if (isNaN(date.getTime())) {\n return dateString;\n }\n\n const month = (date.getMonth() + 1).toString().padStart(2, \"0\");\n const day = date.getDate().toString().padStart(2, \"0\");\n const year = date.getFullYear().toString().slice(-2);\n return `${month}/${day}/${year}`;\n};\n\nexport const isEmpty = (obj: object): boolean => {\n return Object.keys(obj).length === 0;\n};\n\nexport const toDateInputValue = (date: string | Date | null | undefined): string => {\n if (!date) return \"\";\n\n let d: Date;\n\n if (typeof date === \"string\") {\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\n return date;\n }\n d = new Date(date);\n } else {\n d = new Date(date);\n }\n\n if (isNaN(d.getTime())) return \"\";\n\n const localDate = new Date(d.getTime() - d.getTimezoneOffset() * 60000);\n const year = localDate.getFullYear();\n const month = (localDate.getMonth() + 1).toString().padStart(2, \"0\");\n const day = localDate.getDate().toString().padStart(2, \"0\");\n\n return `${year}-${month}-${day}`;\n};\n\nexport function convertCommaDataToArray(data: string | null | undefined): string[] {\n if (!data || data.trim() === \"\") {\n return [];\n }\n return data.split(\",\").map((item) => item.trim());\n}\n\nexport function checkIfExistsInArray<T>(array: T[], searchValue: T): boolean {\n return array.includes(searchValue);\n}\n\nexport const currencyFormatter = (value: number | null | undefined): string => {\n return value?.toLocaleString(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n }) ?? \"\";\n};\n\nexport const parseCurrencyValueToNumber = (value: unknown): number => {\n if (value == null || value === \"\") return 0;\n\n const raw =\n typeof value === \"object\" && value !== null && \"value\" in value\n ? (value as { value: unknown }).value\n : value;\n\n const stringValue = raw == null || raw === \"\" ? \"\" : String(raw);\n const numericValue = stringValue.replace(/[$,]/g, \"\");\n return parseFloat(numericValue) || 0;\n};\n\nexport function flattenTableData<T extends Record<string, unknown>>(\n data: T[] | null | undefined,\n columns: { field?: string }[] | null | undefined\n): T[] {\n if (!Array.isArray(data)) return [];\n return data.map((row) => {\n const flatRow = { ...row };\n (columns ?? []).forEach((col) => {\n const key = col.field;\n if (!key) return;\n if (key.includes(\".\")) {\n const value = key.split(\".\").reduce<unknown>(\n (acc, part) => (acc as Record<string, unknown> | undefined)?.[part],\n row\n );\n (flatRow as Record<string, unknown>)[key] = value ?? \"\";\n }\n });\n return flatRow;\n });\n}\n\nexport const getErrorMessages = (error: {\n data?: {\n errors?: Record<string, string[]>;\n title?: string;\n error?: { name?: string[] };\n };\n} | null | undefined): string => {\n if (error?.data?.errors) {\n return Object.values(error.data.errors).flat().join(\"\\n\");\n }\n return (\n error?.data?.title ??\n error?.data?.error?.name?.[0] ??\n \"Failed to save\"\n );\n};\n\nexport const getFieldsByCategory = <T extends { category?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields?.filter(({ category = \"\" }) => category === key);\n};\n\nexport const getFieldsByName = <T extends { name?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields.filter(({ name = \"\" }) => name === key);\n};\n\nexport const deserializeJson = <T = unknown>(jsonString: string): T | null => {\n try {\n return JSON.parse(jsonString) as T;\n } catch (error) {\n console.error(\"Error parsing JSON:\", error);\n return null;\n }\n};\n\nexport const formatDateTime = (dateString: string | null | undefined): string => {\n if (!dateString) return \"Invalid Date\";\n const date = new Date(dateString);\n if (isNaN(date.getTime())) return \"Invalid Date\";\n const options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"numeric\",\n hour12: true,\n };\n return date.toLocaleString(\"en-US\", options);\n};\n\nexport const removeByPropertyValues = <T extends Record<string, unknown>>(\n items: T[] = [],\n property: keyof T & string,\n values: unknown[] = [],\n { caseInsensitive = false }: { caseInsensitive?: boolean } = {}\n): T[] => {\n if (!Array.isArray(items) || !property) return Array.isArray(items) ? items : [];\n const normalize = (v: unknown) =>\n caseInsensitive && typeof v === \"string\" ? v.toLowerCase() : v;\n const valuesArr = Array.isArray(values) ? values : [values];\n const toRemove = new Set(valuesArr.map(normalize));\n return items.filter((item) => !toRemove.has(normalize(item?.[property])));\n};\n\nexport const getFieldsByInputType = <T extends { inputType?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields.filter(({ inputType = \"\" }) => inputType === key);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAAiB;AACjB,4BAAwB;AAEjB,SAAS,MAAM,QAAiC;AACrD,aAAO,mCAAQ,YAAAA,SAAK,MAAM,CAAC;AAC7B;;;ACLO,IAAM,eAAe,CAAC,MAAiC,YAAY,OAAO;AAC/E,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,UAAU,WAAW;AAC5B,WAAO;AAAA,EACT;AACA,SAAO,KAAK,MAAM,GAAG,YAAY,CAAC,IAAI;AACxC;AAEO,SAAS,YAAY,UAA2B;AACrD,MAAI,CAAC,SAAU,QAAO;AAEtB,MAAI,OAAO,aAAa,UAAU;AAChC,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ;AAKd,MAAI,MAAM,UAAU,MAAM;AACxB,UAAM,eAAe,MAAM,SAAS;AAEpC,QAAI,OAAO,iBAAiB,UAAU;AACpC,aAAO;AAAA,IACT;AAEA,UAAM,SAAS,aAAa;AAC5B,QAAI,UAAU,OAAO,WAAW,UAAU;AACxC,iBAAW,OAAO,QAAQ;AACxB,cAAM,WAAY,OAAmC,GAAG;AACxD,YAAI,MAAM,QAAQ,QAAQ,KAAK,SAAS,SAAS,GAAG;AAClD,iBAAO,OAAO,SAAS,CAAC,CAAC;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAEA,QAAI,aAAa,SAAS;AACxB,aAAO,OAAO,aAAa,OAAO;AAAA,IACpC;AAEA,QAAI,aAAa,OAAO;AACtB,aAAO,OAAO,aAAa,KAAK;AAAA,IAClC;AAAA,EACF;AAEA,MAAI,MAAM,SAAS;AACjB,WAAO,MAAM;AAAA,EACf;AAEA,SAAO;AACT;AAEO,IAAM,wBAAwB,CAAC,iBAAqC;AACzE,MAAI,gBAAgB,KAAM,QAAO,CAAC;AAClC,MAAI,MAAM,QAAQ,YAAY,EAAG,QAAO;AAExC,QAAM,SAAS;AACf,QAAM,OAAO,OAAO;AAEpB,MACE,QACA,OAAO,SAAS,YAChB,CAAC,MAAM,QAAQ,IAAI,KACnB,MAAM,QAAS,KAA+B,KAAK,GACnD;AACA,WAAQ,KAA8B;AAAA,EACxC;AAEA,QAAM,cAAc,OAAO;AAC3B,MAAI,MAAM,QAAQ,aAAa,KAAK,EAAG,QAAO,YAAY;AAC1D,MAAI,MAAM,QAAQ,IAAI,EAAG,QAAO;AAChC,MAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,WAAO,CAAC,IAAI;AAAA,EACd;AACA,SAAO,CAAC;AACV;AAEO,SAAS,eAAe,MAAyC;AACtE,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,KACJ,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,EAAE,YAAY,CAAC,EACxE,KAAK,GAAG;AACb;AAEO,SAAS,gBAAgB,MAAyC;AACvE,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,KAAK,YAAY;AAC1B;AAEO,IAAM,aAAa,CAAC,eAAkD;AAC3E,MAAI,eAAe,QAAQ,eAAe,OAAW,QAAO;AAC5D,QAAM,OAAO,IAAI,KAAK,UAAU;AAEhC,MAAI,MAAM,KAAK,QAAQ,CAAC,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,KAAK,SAAS,IAAI,GAAG,SAAS,EAAE,SAAS,GAAG,GAAG;AAC9D,QAAM,MAAM,KAAK,QAAQ,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG;AACrD,QAAM,OAAO,KAAK,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE;AACnD,SAAO,GAAG,KAAK,IAAI,GAAG,IAAI,IAAI;AAChC;AAEO,IAAM,UAAU,CAAC,QAAyB;AAC/C,SAAO,OAAO,KAAK,GAAG,EAAE,WAAW;AACrC;AAEO,IAAM,mBAAmB,CAAC,SAAmD;AAClF,MAAI,CAAC,KAAM,QAAO;AAElB,MAAI;AAEJ,MAAI,OAAO,SAAS,UAAU;AAC5B,QAAI,sBAAsB,KAAK,IAAI,GAAG;AACpC,aAAO;AAAA,IACT;AACA,QAAI,IAAI,KAAK,IAAI;AAAA,EACnB,OAAO;AACL,QAAI,IAAI,KAAK,IAAI;AAAA,EACnB;AAEA,MAAI,MAAM,EAAE,QAAQ,CAAC,EAAG,QAAO;AAE/B,QAAM,YAAY,IAAI,KAAK,EAAE,QAAQ,IAAI,EAAE,kBAAkB,IAAI,GAAK;AACtE,QAAM,OAAO,UAAU,YAAY;AACnC,QAAM,SAAS,UAAU,SAAS,IAAI,GAAG,SAAS,EAAE,SAAS,GAAG,GAAG;AACnE,QAAM,MAAM,UAAU,QAAQ,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG;AAE1D,SAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG;AAChC;AAEO,SAAS,wBAAwB,MAA2C;AACjF,MAAI,CAAC,QAAQ,KAAK,KAAK,MAAM,IAAI;AAC/B,WAAO,CAAC;AAAA,EACV;AACA,SAAO,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC;AAClD;AAEO,SAAS,qBAAwB,OAAY,aAAyB;AAC3E,SAAO,MAAM,SAAS,WAAW;AACnC;AAEO,IAAM,oBAAoB,CAAC,UAA6C;AAC7E,SAAO,OAAO,eAAe,SAAS;AAAA,IACpC,OAAO;AAAA,IACP,UAAU;AAAA,EACZ,CAAC,KAAK;AACR;AAEO,IAAM,6BAA6B,CAAC,UAA2B;AACpE,MAAI,SAAS,QAAQ,UAAU,GAAI,QAAO;AAE1C,QAAM,MACJ,OAAO,UAAU,YAAY,UAAU,QAAQ,WAAW,QACrD,MAA6B,QAC9B;AAEN,QAAM,cAAc,OAAO,QAAQ,QAAQ,KAAK,KAAK,OAAO,GAAG;AAC/D,QAAM,eAAe,YAAY,QAAQ,SAAS,EAAE;AACpD,SAAO,WAAW,YAAY,KAAK;AACrC;AAEO,SAAS,iBACd,MACA,SACK;AACL,MAAI,CAAC,MAAM,QAAQ,IAAI,EAAG,QAAO,CAAC;AAClC,SAAO,KAAK,IAAI,CAAC,QAAQ;AACvB,UAAM,UAAU,EAAE,GAAG,IAAI;AACzB,KAAC,WAAW,CAAC,GAAG,QAAQ,CAAC,QAAQ;AAC/B,YAAM,MAAM,IAAI;AAChB,UAAI,CAAC,IAAK;AACV,UAAI,IAAI,SAAS,GAAG,GAAG;AACrB,cAAM,QAAQ,IAAI,MAAM,GAAG,EAAE;AAAA,UAC3B,CAAC,KAAK,SAAU,MAA8C,IAAI;AAAA,UAClE;AAAA,QACF;AACA,QAAC,QAAoC,GAAG,IAAI,SAAS;AAAA,MACvD;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT,CAAC;AACH;AAEO,IAAM,mBAAmB,CAAC,UAMA;AAC/B,MAAI,OAAO,MAAM,QAAQ;AACvB,WAAO,OAAO,OAAO,MAAM,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI;AAAA,EAC1D;AACA,SACE,OAAO,MAAM,SACb,OAAO,MAAM,OAAO,OAAO,CAAC,KAC5B;AAEJ;AAEO,IAAM,sBAAsB,CACjC,SAAc,CAAC,GACf,QACQ;AACR,SAAO,QAAQ,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,aAAa,GAAG;AAC/D;AAEO,IAAM,kBAAkB,CAC7B,SAAc,CAAC,GACf,QACQ;AACR,SAAO,OAAO,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,SAAS,GAAG;AACtD;AAEO,IAAM,kBAAkB,CAAc,eAAiC;AAC5E,MAAI;AACF,WAAO,KAAK,MAAM,UAAU;AAAA,EAC9B,SAAS,OAAO;AACd,YAAQ,MAAM,uBAAuB,KAAK;AAC1C,WAAO;AAAA,EACT;AACF;AAEO,IAAM,iBAAiB,CAAC,eAAkD;AAC/E,MAAI,CAAC,WAAY,QAAO;AACxB,QAAM,OAAO,IAAI,KAAK,UAAU;AAChC,MAAI,MAAM,KAAK,QAAQ,CAAC,EAAG,QAAO;AAClC,QAAM,UAAsC;AAAA,IAC1C,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACA,SAAO,KAAK,eAAe,SAAS,OAAO;AAC7C;AAEO,IAAM,yBAAyB,CACpC,QAAa,CAAC,GACd,UACA,SAAoB,CAAC,GACrB,EAAE,kBAAkB,MAAM,IAAmC,CAAC,MACtD;AACR,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC,SAAU,QAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC;AAC/E,QAAM,YAAY,CAAC,MACjB,mBAAmB,OAAO,MAAM,WAAW,EAAE,YAAY,IAAI;AAC/D,QAAM,YAAY,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;AAC1D,QAAM,WAAW,IAAI,IAAI,UAAU,IAAI,SAAS,CAAC;AACjD,SAAO,MAAM,OAAO,CAAC,SAAS,CAAC,SAAS,IAAI,UAAU,OAAO,QAAQ,CAAC,CAAC,CAAC;AAC1E;AAEO,IAAM,uBAAuB,CAClC,SAAc,CAAC,GACf,QACQ;AACR,SAAO,OAAO,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,cAAc,GAAG;AAChE;","names":["clsx"]}
1
+ {"version":3,"sources":["../../src/utils/index.ts","../../src/utils/cn.ts","../../src/utils/helpers.ts"],"sourcesContent":["export { cn } from \"./cn\";\r\nexport * from \"./helpers\";\r\n","import clsx from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: Parameters<typeof clsx>) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","export const truncateText = (text: string | null | undefined, maxLength = 20) => {\n if (!text) return \"\";\n if (text.length <= maxLength) {\n return text;\n }\n return text.slice(0, maxLength - 3) + \"...\";\n};\n\nexport type RtkQueryError = {\n status?: number | string;\n originalStatus?: number;\n data?: {\n errors?: Record<string, string[]>;\n message?: string;\n title?: string;\n };\n error?: string;\n};\n\nexport interface HandleApiErrorOptions {\n showAlert?: boolean;\n fallbackMessage?: string;\n /** Called for each validation message when showAlert is false, and for generic errors */\n toast?: (message: string) => void;\n /** Called for validation errors when showAlert is true (e.g. wire to SweetAlert) */\n alert?: (params: { title: string; html: string }) => void;\n}\n\nexport function formatValidationErrorsHtml(\n errors: Record<string, string[]>\n): string {\n const items = Object.keys(errors).flatMap((field) =>\n (errors[field] || []).map((msg) => `<li>${msg}</li>`)\n );\n return `\n <div style=\"text-align:left\">\n <p>Please review and correct the following:</p>\n <ul style=\"margin:8px 0 0 16px; list-style:disc;\">\n ${items.join(\"\")}\n </ul>\n </div>\n `;\n}\n\n/**\n * Handles RTK Query / fetchBaseQuery error shapes: validation errors, 404 (silent), and generic messages.\n * Pass `toast` and optionally `alert` from your app (react-toastify, SweetAlert, etc.).\n */\nexport function handleApiError(\n error: RtkQueryError | null | undefined,\n { showAlert = false, fallbackMessage, toast, alert }: HandleApiErrorOptions = {}\n): void {\n if (!error) return;\n\n const status = error.status ?? error.originalStatus;\n const data = error.data;\n\n if (status === 200) {\n return;\n }\n\n if (data?.errors && typeof data.errors === \"object\") {\n const errors = data.errors;\n\n if (showAlert && alert) {\n alert({\n title: \"Validation errors\",\n html: formatValidationErrorsHtml(errors),\n });\n } else if (toast) {\n Object.keys(errors).forEach((field) => {\n (errors[field] || []).forEach((errorMessage) => {\n toast(errorMessage);\n });\n });\n }\n return;\n }\n\n if (status === 404) {\n return;\n }\n\n const message =\n fallbackMessage ||\n data?.message ||\n data?.title ||\n error.error ||\n \"An error occurred. Please try again.\";\n\n toast?.(message);\n}\n\nexport function getApiError(apiError: unknown): string {\n if (!apiError) return \"An unknown error occurred\";\n\n if (typeof apiError === \"string\") {\n return apiError;\n }\n\n const error = apiError as {\n response?: { data?: Record<string, unknown> };\n message?: string;\n };\n\n if (error.response?.data) {\n const responseData = error.response.data;\n\n if (typeof responseData === \"string\") {\n return responseData;\n }\n\n const errors = responseData.errors;\n if (errors && typeof errors === \"object\") {\n for (const key in errors) {\n const messages = (errors as Record<string, unknown>)[key];\n if (Array.isArray(messages) && messages.length > 0) {\n return String(messages[0]);\n }\n }\n }\n\n if (responseData.message) {\n return String(responseData.message);\n }\n\n if (responseData.title) {\n return String(responseData.title);\n }\n }\n\n if (error.message) {\n return error.message;\n }\n\n return \"An unknown error occurred\";\n}\n\nexport const normalizeApiListItems = (responseData: unknown): unknown[] => {\n if (responseData == null) return [];\n if (Array.isArray(responseData)) return responseData;\n\n const record = responseData as Record<string, unknown>;\n const data = record.data;\n\n if (\n data &&\n typeof data === \"object\" &&\n !Array.isArray(data) &&\n Array.isArray((data as { items?: unknown[] }).items)\n ) {\n return (data as { items: unknown[] }).items;\n }\n\n const returnModel = record.returnModel as { items?: unknown[] } | undefined;\n if (Array.isArray(returnModel?.items)) return returnModel.items;\n if (Array.isArray(data)) return data;\n if (typeof data === \"object\" && data !== null) {\n return [data];\n }\n return [];\n};\n\nexport function capitalizeText(name: string | null | undefined): string {\n if (!name) return \"\";\n return name\n .split(\" \")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\" \");\n}\n\nexport function toLowerCaseText(text: string | null | undefined): string {\n if (!text) return \"\";\n return text.toLowerCase();\n}\n\nexport const formatDate = (dateString: string | null | undefined): string => {\n if (dateString === null || dateString === undefined) return \"-\";\n const date = new Date(dateString);\n\n if (isNaN(date.getTime())) {\n return dateString;\n }\n\n const month = (date.getMonth() + 1).toString().padStart(2, \"0\");\n const day = date.getDate().toString().padStart(2, \"0\");\n const year = date.getFullYear().toString().slice(-2);\n return `${month}/${day}/${year}`;\n};\n\nexport const isEmpty = (obj: object): boolean => {\n return Object.keys(obj).length === 0;\n};\n\nexport const toDateInputValue = (date: string | Date | null | undefined): string => {\n if (!date) return \"\";\n\n let d: Date;\n\n if (typeof date === \"string\") {\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\n return date;\n }\n d = new Date(date);\n } else {\n d = new Date(date);\n }\n\n if (isNaN(d.getTime())) return \"\";\n\n const localDate = new Date(d.getTime() - d.getTimezoneOffset() * 60000);\n const year = localDate.getFullYear();\n const month = (localDate.getMonth() + 1).toString().padStart(2, \"0\");\n const day = localDate.getDate().toString().padStart(2, \"0\");\n\n return `${year}-${month}-${day}`;\n};\n\nexport function convertCommaDataToArray(data: string | null | undefined): string[] {\n if (!data || data.trim() === \"\") {\n return [];\n }\n return data.split(\",\").map((item) => item.trim());\n}\n\nexport function checkIfExistsInArray<T>(array: T[], searchValue: T): boolean {\n return array.includes(searchValue);\n}\n\nexport const currencyFormatter = (value: number | null | undefined): string => {\n return value?.toLocaleString(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n }) ?? \"\";\n};\n\nexport const parseCurrencyValueToNumber = (value: unknown): number => {\n if (value == null || value === \"\") return 0;\n\n const raw =\n typeof value === \"object\" && value !== null && \"value\" in value\n ? (value as { value: unknown }).value\n : value;\n\n const stringValue = raw == null || raw === \"\" ? \"\" : String(raw);\n const numericValue = stringValue.replace(/[$,]/g, \"\");\n return parseFloat(numericValue) || 0;\n};\n\nexport function flattenTableData<T extends Record<string, unknown>>(\n data: T[] | null | undefined,\n columns: { field?: string }[] | null | undefined\n): T[] {\n if (!Array.isArray(data)) return [];\n return data.map((row) => {\n const flatRow = { ...row };\n (columns ?? []).forEach((col) => {\n const key = col.field;\n if (!key) return;\n if (key.includes(\".\")) {\n const value = key.split(\".\").reduce<unknown>(\n (acc, part) => (acc as Record<string, unknown> | undefined)?.[part],\n row\n );\n (flatRow as Record<string, unknown>)[key] = value ?? \"\";\n }\n });\n return flatRow;\n });\n}\n\nexport const getErrorMessages = (error: {\n data?: {\n errors?: Record<string, string[]>;\n title?: string;\n error?: { name?: string[] };\n };\n} | null | undefined): string => {\n if (error?.data?.errors) {\n return Object.values(error.data.errors).flat().join(\"\\n\");\n }\n return (\n error?.data?.title ??\n error?.data?.error?.name?.[0] ??\n \"Failed to save\"\n );\n};\n\nexport const getFieldsByCategory = <T extends { category?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields?.filter(({ category = \"\" }) => category === key);\n};\n\nexport const getFieldsByName = <T extends { name?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields.filter(({ name = \"\" }) => name === key);\n};\n\nexport const deserializeJson = <T = unknown>(jsonString: string): T | null => {\n try {\n return JSON.parse(jsonString) as T;\n } catch (error) {\n console.error(\"Error parsing JSON:\", error);\n return null;\n }\n};\n\nexport const formatDateTime = (dateString: string | null | undefined): string => {\n if (!dateString) return \"Invalid Date\";\n const date = new Date(dateString);\n if (isNaN(date.getTime())) return \"Invalid Date\";\n const options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"numeric\",\n hour12: true,\n };\n return date.toLocaleString(\"en-US\", options);\n};\n\nexport const removeByPropertyValues = <T extends Record<string, unknown>>(\n items: T[] = [],\n property: keyof T & string,\n values: unknown[] = [],\n { caseInsensitive = false }: { caseInsensitive?: boolean } = {}\n): T[] => {\n if (!Array.isArray(items) || !property) return Array.isArray(items) ? items : [];\n const normalize = (v: unknown) =>\n caseInsensitive && typeof v === \"string\" ? v.toLowerCase() : v;\n const valuesArr = Array.isArray(values) ? values : [values];\n const toRemove = new Set(valuesArr.map(normalize));\n return items.filter((item) => !toRemove.has(normalize(item?.[property])));\n};\n\nexport const getFieldsByInputType = <T extends { inputType?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields.filter(({ inputType = \"\" }) => inputType === key);\n};\n"],"mappings":"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","names":["clsx"]}
@@ -8,11 +8,13 @@ import {
8
8
  flattenTableData,
9
9
  formatDate,
10
10
  formatDateTime,
11
+ formatValidationErrorsHtml,
11
12
  getApiError,
12
13
  getErrorMessages,
13
14
  getFieldsByCategory,
14
15
  getFieldsByInputType,
15
16
  getFieldsByName,
17
+ handleApiError,
16
18
  isEmpty,
17
19
  normalizeApiListItems,
18
20
  parseCurrencyValueToNumber,
@@ -20,7 +22,7 @@ import {
20
22
  toDateInputValue,
21
23
  toLowerCaseText,
22
24
  truncateText
23
- } from "../chunk-WARJTN5T.mjs";
25
+ } from "../chunk-QVRMHJS4.mjs";
24
26
  export {
25
27
  capitalizeText,
26
28
  checkIfExistsInArray,
@@ -31,11 +33,13 @@ export {
31
33
  flattenTableData,
32
34
  formatDate,
33
35
  formatDateTime,
36
+ formatValidationErrorsHtml,
34
37
  getApiError,
35
38
  getErrorMessages,
36
39
  getFieldsByCategory,
37
40
  getFieldsByInputType,
38
41
  getFieldsByName,
42
+ handleApiError,
39
43
  isEmpty,
40
44
  normalizeApiListItems,
41
45
  parseCurrencyValueToNumber,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eztrak/shared",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
 
5
5
  "homepage": "https://github.com/mehrancentangle/eztrak-packages",
6
6
 
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/cn.ts","../src/utils/helpers.ts"],"sourcesContent":["import clsx from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: Parameters<typeof clsx>) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","export const truncateText = (text: string | null | undefined, maxLength = 20) => {\n if (!text) return \"\";\n if (text.length <= maxLength) {\n return text;\n }\n return text.slice(0, maxLength - 3) + \"...\";\n};\n\nexport function getApiError(apiError: unknown): string {\n if (!apiError) return \"An unknown error occurred\";\n\n if (typeof apiError === \"string\") {\n return apiError;\n }\n\n const error = apiError as {\n response?: { data?: Record<string, unknown> };\n message?: string;\n };\n\n if (error.response?.data) {\n const responseData = error.response.data;\n\n if (typeof responseData === \"string\") {\n return responseData;\n }\n\n const errors = responseData.errors;\n if (errors && typeof errors === \"object\") {\n for (const key in errors) {\n const messages = (errors as Record<string, unknown>)[key];\n if (Array.isArray(messages) && messages.length > 0) {\n return String(messages[0]);\n }\n }\n }\n\n if (responseData.message) {\n return String(responseData.message);\n }\n\n if (responseData.title) {\n return String(responseData.title);\n }\n }\n\n if (error.message) {\n return error.message;\n }\n\n return \"An unknown error occurred\";\n}\n\nexport const normalizeApiListItems = (responseData: unknown): unknown[] => {\n if (responseData == null) return [];\n if (Array.isArray(responseData)) return responseData;\n\n const record = responseData as Record<string, unknown>;\n const data = record.data;\n\n if (\n data &&\n typeof data === \"object\" &&\n !Array.isArray(data) &&\n Array.isArray((data as { items?: unknown[] }).items)\n ) {\n return (data as { items: unknown[] }).items;\n }\n\n const returnModel = record.returnModel as { items?: unknown[] } | undefined;\n if (Array.isArray(returnModel?.items)) return returnModel.items;\n if (Array.isArray(data)) return data;\n if (typeof data === \"object\" && data !== null) {\n return [data];\n }\n return [];\n};\n\nexport function capitalizeText(name: string | null | undefined): string {\n if (!name) return \"\";\n return name\n .split(\" \")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\" \");\n}\n\nexport function toLowerCaseText(text: string | null | undefined): string {\n if (!text) return \"\";\n return text.toLowerCase();\n}\n\nexport const formatDate = (dateString: string | null | undefined): string => {\n if (dateString === null || dateString === undefined) return \"-\";\n const date = new Date(dateString);\n\n if (isNaN(date.getTime())) {\n return dateString;\n }\n\n const month = (date.getMonth() + 1).toString().padStart(2, \"0\");\n const day = date.getDate().toString().padStart(2, \"0\");\n const year = date.getFullYear().toString().slice(-2);\n return `${month}/${day}/${year}`;\n};\n\nexport const isEmpty = (obj: object): boolean => {\n return Object.keys(obj).length === 0;\n};\n\nexport const toDateInputValue = (date: string | Date | null | undefined): string => {\n if (!date) return \"\";\n\n let d: Date;\n\n if (typeof date === \"string\") {\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\n return date;\n }\n d = new Date(date);\n } else {\n d = new Date(date);\n }\n\n if (isNaN(d.getTime())) return \"\";\n\n const localDate = new Date(d.getTime() - d.getTimezoneOffset() * 60000);\n const year = localDate.getFullYear();\n const month = (localDate.getMonth() + 1).toString().padStart(2, \"0\");\n const day = localDate.getDate().toString().padStart(2, \"0\");\n\n return `${year}-${month}-${day}`;\n};\n\nexport function convertCommaDataToArray(data: string | null | undefined): string[] {\n if (!data || data.trim() === \"\") {\n return [];\n }\n return data.split(\",\").map((item) => item.trim());\n}\n\nexport function checkIfExistsInArray<T>(array: T[], searchValue: T): boolean {\n return array.includes(searchValue);\n}\n\nexport const currencyFormatter = (value: number | null | undefined): string => {\n return value?.toLocaleString(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n }) ?? \"\";\n};\n\nexport const parseCurrencyValueToNumber = (value: unknown): number => {\n if (value == null || value === \"\") return 0;\n\n const raw =\n typeof value === \"object\" && value !== null && \"value\" in value\n ? (value as { value: unknown }).value\n : value;\n\n const stringValue = raw == null || raw === \"\" ? \"\" : String(raw);\n const numericValue = stringValue.replace(/[$,]/g, \"\");\n return parseFloat(numericValue) || 0;\n};\n\nexport function flattenTableData<T extends Record<string, unknown>>(\n data: T[] | null | undefined,\n columns: { field?: string }[] | null | undefined\n): T[] {\n if (!Array.isArray(data)) return [];\n return data.map((row) => {\n const flatRow = { ...row };\n (columns ?? []).forEach((col) => {\n const key = col.field;\n if (!key) return;\n if (key.includes(\".\")) {\n const value = key.split(\".\").reduce<unknown>(\n (acc, part) => (acc as Record<string, unknown> | undefined)?.[part],\n row\n );\n (flatRow as Record<string, unknown>)[key] = value ?? \"\";\n }\n });\n return flatRow;\n });\n}\n\nexport const getErrorMessages = (error: {\n data?: {\n errors?: Record<string, string[]>;\n title?: string;\n error?: { name?: string[] };\n };\n} | null | undefined): string => {\n if (error?.data?.errors) {\n return Object.values(error.data.errors).flat().join(\"\\n\");\n }\n return (\n error?.data?.title ??\n error?.data?.error?.name?.[0] ??\n \"Failed to save\"\n );\n};\n\nexport const getFieldsByCategory = <T extends { category?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields?.filter(({ category = \"\" }) => category === key);\n};\n\nexport const getFieldsByName = <T extends { name?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields.filter(({ name = \"\" }) => name === key);\n};\n\nexport const deserializeJson = <T = unknown>(jsonString: string): T | null => {\n try {\n return JSON.parse(jsonString) as T;\n } catch (error) {\n console.error(\"Error parsing JSON:\", error);\n return null;\n }\n};\n\nexport const formatDateTime = (dateString: string | null | undefined): string => {\n if (!dateString) return \"Invalid Date\";\n const date = new Date(dateString);\n if (isNaN(date.getTime())) return \"Invalid Date\";\n const options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"numeric\",\n hour12: true,\n };\n return date.toLocaleString(\"en-US\", options);\n};\n\nexport const removeByPropertyValues = <T extends Record<string, unknown>>(\n items: T[] = [],\n property: keyof T & string,\n values: unknown[] = [],\n { caseInsensitive = false }: { caseInsensitive?: boolean } = {}\n): T[] => {\n if (!Array.isArray(items) || !property) return Array.isArray(items) ? items : [];\n const normalize = (v: unknown) =>\n caseInsensitive && typeof v === \"string\" ? v.toLowerCase() : v;\n const valuesArr = Array.isArray(values) ? values : [values];\n const toRemove = new Set(valuesArr.map(normalize));\n return items.filter((item) => !toRemove.has(normalize(item?.[property])));\n};\n\nexport const getFieldsByInputType = <T extends { inputType?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields.filter(({ inputType = \"\" }) => inputType === key);\n};\n"],"mappings":"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","names":[]}