@eztrak/shared 0.9.0 → 0.12.0
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 +184 -2
- package/dist/chunk-7PPCJV2M.mjs +56 -0
- package/dist/chunk-7PPCJV2M.mjs.map +1 -0
- package/dist/{chunk-GVIHLI67.mjs → chunk-BMX2RODZ.mjs} +85 -11
- package/dist/chunk-BMX2RODZ.mjs.map +1 -0
- package/dist/{chunk-2MTTG7D2.mjs → chunk-PHK4IOCF.mjs} +168 -56
- package/dist/chunk-PHK4IOCF.mjs.map +1 -0
- package/dist/components/index.d.mts +17 -1
- package/dist/components/index.d.ts +17 -1
- package/dist/components/index.js +267 -79
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +8 -4
- package/dist/index.d.mts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +329 -77
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +31 -4
- package/dist/utils/index.d.mts +26 -2
- package/dist/utils/index.d.ts +26 -2
- package/dist/utils/index.js +148 -10
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +25 -2
- package/package.json +3 -1
- package/dist/chunk-2MTTG7D2.mjs.map +0 -1
- package/dist/chunk-GED6IT3S.mjs +0 -1
- package/dist/chunk-GED6IT3S.mjs.map +0 -1
- package/dist/chunk-GVIHLI67.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -72,6 +72,31 @@ truncateText("A very long description here", 10); // "A very ..."
|
|
|
72
72
|
truncateFileName("annual-financial-report-2026.pdf", 20); // "annual-financ....pdf"
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
+
Browser local storage helpers (JSON serialize/deserialize, safe fallbacks):
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
import {
|
|
79
|
+
getItem,
|
|
80
|
+
setItem,
|
|
81
|
+
loadUserState,
|
|
82
|
+
saveUserState,
|
|
83
|
+
USER_STATE_STORAGE_KEY,
|
|
84
|
+
} from "@eztrak/shared/utils";
|
|
85
|
+
|
|
86
|
+
// User auth state (default key: "authState")
|
|
87
|
+
saveUserState({ access_token: "...", name: "Ali" });
|
|
88
|
+
const user = loadUserState();
|
|
89
|
+
|
|
90
|
+
// Generic key/value storage
|
|
91
|
+
setItem("selectedProject", { id: 1, name: "Project A" });
|
|
92
|
+
const project = getItem("selectedProject");
|
|
93
|
+
|
|
94
|
+
// Explicit fallback when a key is missing
|
|
95
|
+
const permissions = getItem("userPermissionsNew", []);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Backward-compatible aliases are also exported: `get` / `set`, `getItemFromLocalStorage`, `storeItemInLocalStorage`, and `saveItemLocalStorage`.
|
|
99
|
+
|
|
75
100
|
RTK Query errors (toast or SweetAlert — no extra wiring):
|
|
76
101
|
|
|
77
102
|
```js
|
|
@@ -84,11 +109,64 @@ handleApiError(error, { fallbackMessage: "Save failed" });
|
|
|
84
109
|
handleApiError(error, { showAlert: true });
|
|
85
110
|
```
|
|
86
111
|
|
|
87
|
-
|
|
112
|
+
### confirmationAlert
|
|
113
|
+
|
|
114
|
+
Standard SweetAlert2 confirmation dialog for all Eztrak apps (Main, Vault, Pilot, PBF). Use **one function** with an options object — no per-module copies in `utils.js`.
|
|
115
|
+
|
|
116
|
+
**Import:**
|
|
88
117
|
|
|
89
118
|
```js
|
|
119
|
+
import { confirmationAlert } from "@eztrak/shared";
|
|
120
|
+
// or
|
|
90
121
|
import { confirmationAlert } from "@eztrak/shared/utils";
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Signature:**
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
confirmationAlert(
|
|
128
|
+
onConfirm: () => void | Promise<void>,
|
|
129
|
+
options?: ConfirmationAlertOptions
|
|
130
|
+
): void
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
`onConfirm` may be sync or `async`. When a loader is active, the modal stays open until `onConfirm` resolves; on failure it shows an error message inside the dialog.
|
|
134
|
+
|
|
135
|
+
#### Options
|
|
91
136
|
|
|
137
|
+
| Prop | Type | Default | Description |
|
|
138
|
+
| --- | --- | --- | --- |
|
|
139
|
+
| `title` | `string` | `"Are you sure?"` (or `"Confirmation Required"` when `inputExpectedValue` is set) | Dialog heading |
|
|
140
|
+
| `text` | `string` | — | Plain-text message (ignored when `html` is used without input) |
|
|
141
|
+
| `html` | `string` | — | Custom HTML body (e.g. project delete instructions) |
|
|
142
|
+
| `icon` | `"warning" \| "info" \| "question" \| "error" \| "success"` | `"warning"` | SweetAlert2 icon |
|
|
143
|
+
| `confirmButtonText` | `string` | `"Yes"` | Confirm button label |
|
|
144
|
+
| `cancelButtonText` | `string` | `"Cancel"` | Cancel button label |
|
|
145
|
+
| `confirmButtonColor` | `string` | `"#FF7335"` | Confirm button color (brand orange) |
|
|
146
|
+
| `cancelButtonColor` | `string` | `"#ff0000"` | Cancel button color |
|
|
147
|
+
| `showLoaderOnConfirm` | `boolean` | `false` | Show loader while `onConfirm` runs (API deletes/updates) |
|
|
148
|
+
| `inputExpectedValue` | `string` | — | User must type this value to confirm (trimmed, **case-sensitive**) |
|
|
149
|
+
| `inputPlaceholder` | `string` | `"Type confirmation text to proceed"` | Placeholder for the confirmation input |
|
|
150
|
+
| `reverseButtons` | `boolean` | — | Swap Cancel / Confirm order (e.g. logout) |
|
|
151
|
+
| `focusCancel` | `boolean` | — | Focus Cancel on open (e.g. logout) |
|
|
152
|
+
| `zIndex` | `number` | — | Stack the modal above tables/overlays |
|
|
153
|
+
|
|
154
|
+
#### Behavior modes
|
|
155
|
+
|
|
156
|
+
1. **Simple confirm** — no `showLoaderOnConfirm`, no `inputExpectedValue`
|
|
157
|
+
User clicks Yes → `onConfirm()` runs → modal closes.
|
|
158
|
+
|
|
159
|
+
2. **Loader confirm** — `showLoaderOnConfirm: true`
|
|
160
|
+
User clicks confirm → loader → `onConfirm()` awaited → success closes modal; error shows validation message and keeps modal open.
|
|
161
|
+
|
|
162
|
+
3. **Typed confirm** — `inputExpectedValue` set
|
|
163
|
+
Input field appears; user must type the exact value (`typed.trim() === expected.trim()`). Loader is enabled automatically.
|
|
164
|
+
|
|
165
|
+
#### Examples
|
|
166
|
+
|
|
167
|
+
**Simple Yes/No (column reset, generic confirm):**
|
|
168
|
+
|
|
169
|
+
```js
|
|
92
170
|
confirmationAlert(() => resetLayout(), {
|
|
93
171
|
title: "Reset column layout to default",
|
|
94
172
|
text: "Reset column order, widths, and visibility to defaults?",
|
|
@@ -96,6 +174,108 @@ confirmationAlert(() => resetLayout(), {
|
|
|
96
174
|
});
|
|
97
175
|
```
|
|
98
176
|
|
|
177
|
+
**Custom button colors:**
|
|
178
|
+
|
|
179
|
+
```js
|
|
180
|
+
confirmationAlert(() => handleDelete(), {
|
|
181
|
+
title: "Delete this item?",
|
|
182
|
+
confirmButtonText: "Yes, delete it!",
|
|
183
|
+
confirmButtonColor: "#B91C1C",
|
|
184
|
+
cancelButtonColor: "#6b7280",
|
|
185
|
+
showLoaderOnConfirm: true,
|
|
186
|
+
});
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Bulk delete with API loader:**
|
|
190
|
+
|
|
191
|
+
```js
|
|
192
|
+
confirmationAlert(async () => {
|
|
193
|
+
await dispatch(deleteItems(ids)).unwrap();
|
|
194
|
+
}, {
|
|
195
|
+
text: "Are you sure you want to delete selected items?",
|
|
196
|
+
confirmButtonText: "OK",
|
|
197
|
+
showLoaderOnConfirm: true,
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Type `DELETE` to confirm:**
|
|
202
|
+
|
|
203
|
+
```js
|
|
204
|
+
confirmationAlert(() => bulkDelete(), {
|
|
205
|
+
text: "Are you sure you want to delete selected items?",
|
|
206
|
+
inputExpectedValue: "DELETE",
|
|
207
|
+
confirmButtonText: "Confirm",
|
|
208
|
+
});
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Delete project — type project name:**
|
|
212
|
+
|
|
213
|
+
```js
|
|
214
|
+
confirmationAlert(async () => {
|
|
215
|
+
await deleteProject(projectId);
|
|
216
|
+
}, {
|
|
217
|
+
title: "Delete Project",
|
|
218
|
+
html: `
|
|
219
|
+
<p style="font-size:14px">To confirm, please type the project name below:</p>
|
|
220
|
+
<p style="font-weight:bold;color:#d9534f">${projectName}</p>
|
|
221
|
+
`,
|
|
222
|
+
inputExpectedValue: projectName,
|
|
223
|
+
inputPlaceholder: "Enter project name",
|
|
224
|
+
confirmButtonText: "Delete",
|
|
225
|
+
showLoaderOnConfirm: true,
|
|
226
|
+
});
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Logout:**
|
|
230
|
+
|
|
231
|
+
```js
|
|
232
|
+
confirmationAlert(() => authService.logout(), {
|
|
233
|
+
title: "Logout Confirmation",
|
|
234
|
+
text: "Are you sure you want to logout?",
|
|
235
|
+
icon: "question",
|
|
236
|
+
confirmButtonText: "Yes, Logout",
|
|
237
|
+
cancelButtonColor: "#6b7280",
|
|
238
|
+
reverseButtons: true,
|
|
239
|
+
focusCancel: true,
|
|
240
|
+
});
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**Modal above AG Grid / overlays:**
|
|
244
|
+
|
|
245
|
+
```js
|
|
246
|
+
confirmationAlert(() => deleteRow(), {
|
|
247
|
+
text: "Are you sure?",
|
|
248
|
+
showLoaderOnConfirm: true,
|
|
249
|
+
zIndex: 9999,
|
|
250
|
+
});
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
#### Replacing local helpers
|
|
254
|
+
|
|
255
|
+
When migrating, remove duplicate functions from app `utils.js` and use `confirmationAlert` from `@eztrak/shared` instead:
|
|
256
|
+
|
|
257
|
+
| Old local function | Replacement |
|
|
258
|
+
| --- | --- |
|
|
259
|
+
| `confirmationAlert(onConfirm, text, icon)` (main-app 3-arg) | `confirmationAlert(onConfirm, { text, icon, confirmButtonText: "OK" })` |
|
|
260
|
+
| `confirmationAlert(onConfirm, { ... })` (vault/pilot/pbf) | Same options; change import to `@eztrak/shared` |
|
|
261
|
+
| `showDeleteConfirmation(onConfirm)` | `confirmationAlert(onConfirm, { text: "...", confirmButtonText: "OK", showLoaderOnConfirm: true })` |
|
|
262
|
+
| `showDeletePrompt(onConfirm, projectName)` | `confirmationAlert(onConfirm, { title: "Delete Project", html: "...", inputExpectedValue: projectName, showLoaderOnConfirm: true, confirmButtonText: "Delete" })` |
|
|
263
|
+
| `showLogoutConfirmation(onConfirm)` | `confirmationAlert(onConfirm, { title: "Logout Confirmation", text: "...", icon: "question", reverseButtons: true, focusCancel: true, cancelButtonColor: "#6b7280" })` |
|
|
264
|
+
| `confirmationAlertWithInput(onConfirm, "DELETE", text)` | `confirmationAlert(onConfirm, { text, inputExpectedValue: "DELETE", confirmButtonText: "Confirm" })` |
|
|
265
|
+
|
|
266
|
+
**Not replaced by this helper:** `showDeleteConfirmationAlert` (red button + inline “Deleting…” spinner on the button) — keep that component or pass equivalent colors + `showLoaderOnConfirm` if the default center loader is acceptable.
|
|
267
|
+
|
|
268
|
+
**Direct `Swal.fire({ ... })` calls** in budget/RFQ/forecast flows are separate one-off UIs; migrate only when those screens are touched.
|
|
269
|
+
|
|
270
|
+
#### TypeScript
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
import {
|
|
274
|
+
confirmationAlert,
|
|
275
|
+
type ConfirmationAlertOptions,
|
|
276
|
+
} from "@eztrak/shared";
|
|
277
|
+
```
|
|
278
|
+
|
|
99
279
|
### Hooks
|
|
100
280
|
|
|
101
281
|
```js
|
|
@@ -584,6 +764,8 @@ Pass classes per slot — they merge with the default `eztrak-tabs-*` styles via
|
|
|
584
764
|
```js
|
|
585
765
|
import {
|
|
586
766
|
cn,
|
|
767
|
+
confirmationAlert,
|
|
768
|
+
handleApiError,
|
|
587
769
|
useGridHeight,
|
|
588
770
|
EztrakTabs,
|
|
589
771
|
CustomPagination,
|
|
@@ -613,7 +795,7 @@ Opens on [http://localhost:6006](http://localhost:6006) with stories for `Eztrak
|
|
|
613
795
|
| Subpath | Description |
|
|
614
796
|
| --- | --- |
|
|
615
797
|
| `@eztrak/shared` | Main entry — re-exports utils, hooks, and components |
|
|
616
|
-
| `@eztrak/shared/utils` | `cn`, `handleApiError`, `confirmationAlert`, date/format helpers, API error helpers, form field helpers |
|
|
798
|
+
| `@eztrak/shared/utils` | `cn`, `handleApiError`, `confirmationAlert`, `ConfirmationAlertOptions`, `getItem`, `setItem`, `loadUserState`, `saveUserState`, date/format helpers, API error helpers, form field helpers |
|
|
617
799
|
| `@eztrak/shared/hooks` | `usePaginationUrlSync`, `useGridHeight` |
|
|
618
800
|
| `@eztrak/shared/components` | `EztrakTabs`, `CustomPagination`, `CustomCellEditor`, `SearchInput`, `ResetFiltersButton`, `TooltipText`, `ToolTip`, `CardSkeleton`, `Modal`, `Loader`, `TableLayoutToolbarControls`, `ResetColumnsButton`, and related types |
|
|
619
801
|
| `@eztrak/shared/components/tabs.css` | Default tab styles (CSS variables) |
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// src/utils/localStorage.ts
|
|
2
|
+
var USER_STATE_STORAGE_KEY = "authState";
|
|
3
|
+
function getStorage() {
|
|
4
|
+
if (typeof window === "undefined") return null;
|
|
5
|
+
return window.localStorage;
|
|
6
|
+
}
|
|
7
|
+
function getItem(key, fallback = null) {
|
|
8
|
+
try {
|
|
9
|
+
const raw = getStorage()?.getItem(key);
|
|
10
|
+
if (raw === null || raw === void 0) {
|
|
11
|
+
return fallback;
|
|
12
|
+
}
|
|
13
|
+
return JSON.parse(raw);
|
|
14
|
+
} catch {
|
|
15
|
+
return fallback;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function setItem(key, value) {
|
|
19
|
+
try {
|
|
20
|
+
getStorage()?.setItem(key, JSON.stringify(value));
|
|
21
|
+
} catch {
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function removeItem(key) {
|
|
25
|
+
try {
|
|
26
|
+
getStorage()?.removeItem(key);
|
|
27
|
+
} catch {
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function loadUserState(key = USER_STATE_STORAGE_KEY) {
|
|
31
|
+
const value = getItem(key, void 0);
|
|
32
|
+
return value === null ? void 0 : value;
|
|
33
|
+
}
|
|
34
|
+
function saveUserState(state, key = USER_STATE_STORAGE_KEY) {
|
|
35
|
+
setItem(key, state);
|
|
36
|
+
}
|
|
37
|
+
var get = getItem;
|
|
38
|
+
var set = setItem;
|
|
39
|
+
var getItemFromLocalStorage = getItem;
|
|
40
|
+
var storeItemInLocalStorage = setItem;
|
|
41
|
+
var saveItemLocalStorage = setItem;
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
USER_STATE_STORAGE_KEY,
|
|
45
|
+
getItem,
|
|
46
|
+
setItem,
|
|
47
|
+
removeItem,
|
|
48
|
+
loadUserState,
|
|
49
|
+
saveUserState,
|
|
50
|
+
get,
|
|
51
|
+
set,
|
|
52
|
+
getItemFromLocalStorage,
|
|
53
|
+
storeItemInLocalStorage,
|
|
54
|
+
saveItemLocalStorage
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=chunk-7PPCJV2M.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/localStorage.ts"],"sourcesContent":["export const USER_STATE_STORAGE_KEY = \"authState\";\r\n\r\nfunction getStorage(): Storage | null {\r\n if (typeof window === \"undefined\") return null;\r\n return window.localStorage;\r\n}\r\n\r\nexport function getItem<T>(key: string, fallback: T | null = null): T | null {\r\n try {\r\n const raw = getStorage()?.getItem(key);\r\n if (raw === null || raw === undefined) {\r\n return fallback;\r\n }\r\n return JSON.parse(raw) as T;\r\n } catch {\r\n return fallback;\r\n }\r\n}\r\n\r\nexport function setItem<T>(key: string, value: T): void {\r\n try {\r\n getStorage()?.setItem(key, JSON.stringify(value));\r\n } catch {\r\n // Ignore write errors (quota exceeded, private mode, etc.)\r\n }\r\n}\r\n\r\nexport function removeItem(key: string): void {\r\n try {\r\n getStorage()?.removeItem(key);\r\n } catch {\r\n // Ignore remove errors\r\n }\r\n}\r\n\r\nexport function loadUserState<T = unknown>(\r\n key: string = USER_STATE_STORAGE_KEY\r\n): T | undefined {\r\n const value = getItem<T | undefined>(key, undefined);\r\n return value === null ? undefined : value;\r\n}\r\n\r\nexport function saveUserState<T = unknown>(\r\n state: T,\r\n key: string = USER_STATE_STORAGE_KEY\r\n): void {\r\n setItem(key, state);\r\n}\r\n\r\n/** Task-aligned aliases */\r\nexport const get = getItem;\r\nexport const set = setItem;\r\n\r\n/** Backward-compatible aliases used in federation apps */\r\nexport const getItemFromLocalStorage = getItem;\r\nexport const storeItemInLocalStorage = setItem;\r\nexport const saveItemLocalStorage = setItem;\r\n"],"mappings":";AAAO,IAAM,yBAAyB;AAEtC,SAAS,aAA6B;AACpC,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,SAAO,OAAO;AAChB;AAEO,SAAS,QAAW,KAAa,WAAqB,MAAgB;AAC3E,MAAI;AACF,UAAM,MAAM,WAAW,GAAG,QAAQ,GAAG;AACrC,QAAI,QAAQ,QAAQ,QAAQ,QAAW;AACrC,aAAO;AAAA,IACT;AACA,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,QAAW,KAAa,OAAgB;AACtD,MAAI;AACF,eAAW,GAAG,QAAQ,KAAK,KAAK,UAAU,KAAK,CAAC;AAAA,EAClD,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,WAAW,KAAmB;AAC5C,MAAI;AACF,eAAW,GAAG,WAAW,GAAG;AAAA,EAC9B,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,cACd,MAAc,wBACC;AACf,QAAM,QAAQ,QAAuB,KAAK,MAAS;AACnD,SAAO,UAAU,OAAO,SAAY;AACtC;AAEO,SAAS,cACd,OACA,MAAc,wBACR;AACN,UAAQ,KAAK,KAAK;AACpB;AAGO,IAAM,MAAM;AACZ,IAAM,MAAM;AAGZ,IAAM,0BAA0B;AAChC,IAAM,0BAA0B;AAChC,IAAM,uBAAuB;","names":[]}
|
|
@@ -255,18 +255,92 @@ function handleApiError(error, { showAlert = false, fallbackMessage } = {}) {
|
|
|
255
255
|
const message = fallbackMessage || data?.message || data?.title || error.error || "An error occurred. Please try again.";
|
|
256
256
|
toast.error(message);
|
|
257
257
|
}
|
|
258
|
+
var BRAND_ORANGE = "#FF7335";
|
|
259
|
+
var CANCEL_RED = "#ff0000";
|
|
260
|
+
function getConfirmErrorMessage(error) {
|
|
261
|
+
if (error && typeof error === "object") {
|
|
262
|
+
const err = error;
|
|
263
|
+
return err.data?.message || err.data?.title || err.message || "Something went wrong. Please try again.";
|
|
264
|
+
}
|
|
265
|
+
return "Something went wrong. Please try again.";
|
|
266
|
+
}
|
|
258
267
|
function confirmationAlert(onConfirm, options = {}) {
|
|
259
|
-
|
|
260
|
-
title
|
|
261
|
-
text
|
|
262
|
-
|
|
268
|
+
const {
|
|
269
|
+
title = options.inputExpectedValue ? "Confirmation Required" : "Are you sure?",
|
|
270
|
+
text,
|
|
271
|
+
html,
|
|
272
|
+
icon = "warning",
|
|
273
|
+
confirmButtonText = "Yes",
|
|
274
|
+
cancelButtonText = "Cancel",
|
|
275
|
+
confirmButtonColor = BRAND_ORANGE,
|
|
276
|
+
cancelButtonColor = CANCEL_RED,
|
|
277
|
+
showLoaderOnConfirm = false,
|
|
278
|
+
inputExpectedValue,
|
|
279
|
+
inputPlaceholder = "Type confirmation text to proceed",
|
|
280
|
+
reverseButtons,
|
|
281
|
+
focusCancel,
|
|
282
|
+
zIndex
|
|
283
|
+
} = options;
|
|
284
|
+
const hasInput = Boolean(inputExpectedValue);
|
|
285
|
+
const useLoader = showLoaderOnConfirm || hasInput;
|
|
286
|
+
const inputHtml = html ?? (hasInput ? `
|
|
287
|
+
${text ? `<p style="margin-bottom: 15px;">${text}</p>` : ""}
|
|
288
|
+
<p style="margin-bottom: 10px; font-weight: bold; color: #666;">
|
|
289
|
+
Please type "<span style="color: ${BRAND_ORANGE}; font-weight: bold;">${inputExpectedValue}</span>" to confirm:
|
|
290
|
+
</p>
|
|
291
|
+
` : void 0);
|
|
292
|
+
const swalOptions = {
|
|
293
|
+
title,
|
|
294
|
+
icon,
|
|
263
295
|
showCancelButton: true,
|
|
264
|
-
confirmButtonText
|
|
265
|
-
cancelButtonText
|
|
266
|
-
confirmButtonColor
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
296
|
+
confirmButtonText,
|
|
297
|
+
cancelButtonText,
|
|
298
|
+
confirmButtonColor,
|
|
299
|
+
cancelButtonColor,
|
|
300
|
+
reverseButtons,
|
|
301
|
+
focusCancel,
|
|
302
|
+
allowOutsideClick: () => !Swal.isLoading(),
|
|
303
|
+
allowEscapeKey: () => !Swal.isLoading(),
|
|
304
|
+
didOpen: () => {
|
|
305
|
+
if (zIndex == null) return;
|
|
306
|
+
const container = Swal.getContainer();
|
|
307
|
+
if (container) container.style.zIndex = String(zIndex);
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
if (hasInput) {
|
|
311
|
+
swalOptions.html = inputHtml;
|
|
312
|
+
swalOptions.input = "text";
|
|
313
|
+
swalOptions.inputPlaceholder = inputPlaceholder;
|
|
314
|
+
swalOptions.inputValidator = (value) => {
|
|
315
|
+
if (!value?.trim()) return "You need to enter the confirmation text!";
|
|
316
|
+
if (value.trim() !== inputExpectedValue.trim()) {
|
|
317
|
+
return `Please type "${inputExpectedValue}" exactly as shown!`;
|
|
318
|
+
}
|
|
319
|
+
return null;
|
|
320
|
+
};
|
|
321
|
+
} else if (html) {
|
|
322
|
+
swalOptions.html = html;
|
|
323
|
+
} else {
|
|
324
|
+
swalOptions.text = text;
|
|
325
|
+
}
|
|
326
|
+
if (useLoader) {
|
|
327
|
+
swalOptions.showLoaderOnConfirm = true;
|
|
328
|
+
swalOptions.preConfirm = (inputValue) => {
|
|
329
|
+
if (hasInput && inputValue?.trim() !== inputExpectedValue.trim()) {
|
|
330
|
+
Swal.showValidationMessage(
|
|
331
|
+
`Please type "${inputExpectedValue}" exactly as shown!`
|
|
332
|
+
);
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
335
|
+
return Promise.resolve().then(() => onConfirm()).catch((error) => {
|
|
336
|
+
Swal.showValidationMessage(getConfirmErrorMessage(error));
|
|
337
|
+
throw error;
|
|
338
|
+
});
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
void Swal.fire(swalOptions).then((result) => {
|
|
342
|
+
if (result.isConfirmed && !useLoader) {
|
|
343
|
+
void Promise.resolve(onConfirm());
|
|
270
344
|
}
|
|
271
345
|
});
|
|
272
346
|
}
|
|
@@ -299,4 +373,4 @@ export {
|
|
|
299
373
|
handleApiError,
|
|
300
374
|
confirmationAlert
|
|
301
375
|
};
|
|
302
|
-
//# sourceMappingURL=chunk-
|
|
376
|
+
//# sourceMappingURL=chunk-BMX2RODZ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/cn.ts","../src/utils/helpers.ts","../src/utils/handleApiError.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 = (\r\n text: string | number | null | undefined,\r\n maxLength = 20\r\n): string => {\r\n if (text === null || text === undefined) return \"\";\r\n const value = String(text);\r\n if (value.length <= maxLength) {\r\n return value;\r\n }\r\n return value.slice(0, maxLength - 3) + \"...\";\r\n};\r\n\r\nexport const truncateFileName = (\r\n fileName: string | null | undefined,\r\n maxLength = 20\r\n): string => {\r\n if (!fileName) return \"\";\r\n if (fileName.length <= maxLength) {\r\n return fileName;\r\n }\r\n const extension = fileName.slice(fileName.lastIndexOf(\".\"));\r\n const truncatedName =\r\n fileName.slice(0, maxLength - extension.length - 3) + \"...\";\r\n return truncatedName + extension;\r\n};\r\n\r\nexport function getApiError(apiError: unknown): string {\r\n if (!apiError) return \"An unknown error occurred\";\r\n\r\n if (typeof apiError === \"string\") {\r\n return apiError;\r\n }\r\n\r\n const error = apiError as {\r\n response?: { data?: Record<string, unknown> };\r\n message?: string;\r\n };\r\n\r\n if (error.response?.data) {\r\n const responseData = error.response.data;\r\n\r\n if (typeof responseData === \"string\") {\r\n return responseData;\r\n }\r\n\r\n const errors = responseData.errors;\r\n if (errors && typeof errors === \"object\") {\r\n for (const key in errors) {\r\n const messages = (errors as Record<string, unknown>)[key];\r\n if (Array.isArray(messages) && messages.length > 0) {\r\n return String(messages[0]);\r\n }\r\n }\r\n }\r\n\r\n if (responseData.message) {\r\n return String(responseData.message);\r\n }\r\n\r\n if (responseData.title) {\r\n return String(responseData.title);\r\n }\r\n }\r\n\r\n if (error.message) {\r\n return error.message;\r\n }\r\n\r\n return \"An unknown error occurred\";\r\n}\r\n\r\nexport const normalizeApiListItems = (responseData: unknown): unknown[] => {\r\n if (responseData == null) return [];\r\n if (Array.isArray(responseData)) return responseData;\r\n\r\n const record = responseData as Record<string, unknown>;\r\n const data = record.data;\r\n\r\n if (\r\n data &&\r\n typeof data === \"object\" &&\r\n !Array.isArray(data) &&\r\n Array.isArray((data as { items?: unknown[] }).items)\r\n ) {\r\n return (data as { items: unknown[] }).items;\r\n }\r\n\r\n const returnModel = record.returnModel as { items?: unknown[] } | undefined;\r\n if (Array.isArray(returnModel?.items)) return returnModel.items;\r\n if (Array.isArray(data)) return data;\r\n if (typeof data === \"object\" && data !== null) {\r\n return [data];\r\n }\r\n return [];\r\n};\r\n\r\nexport function capitalizeText(name: string | null | undefined): string {\r\n if (!name) return \"\";\r\n return name\r\n .split(\" \")\r\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\r\n .join(\" \");\r\n}\r\n\r\nexport function toLowerCaseText(text: string | null | undefined): string {\r\n if (!text) return \"\";\r\n return text.toLowerCase();\r\n}\r\n\r\nexport const formatDate = (dateString: string | null | undefined): string => {\r\n if (dateString === null || dateString === undefined) return \"-\";\r\n const date = new Date(dateString);\r\n\r\n if (isNaN(date.getTime())) {\r\n return dateString;\r\n }\r\n\r\n const month = (date.getMonth() + 1).toString().padStart(2, \"0\");\r\n const day = date.getDate().toString().padStart(2, \"0\");\r\n const year = date.getFullYear().toString().slice(-2);\r\n return `${month}/${day}/${year}`;\r\n};\r\n\r\nexport const isEmpty = (obj: object): boolean => {\r\n return Object.keys(obj).length === 0;\r\n};\r\n\r\nexport const toDateInputValue = (date: string | Date | null | undefined): string => {\r\n if (!date) return \"\";\r\n\r\n let d: Date;\r\n\r\n if (typeof date === \"string\") {\r\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\r\n return date;\r\n }\r\n d = new Date(date);\r\n } else {\r\n d = new Date(date);\r\n }\r\n\r\n if (isNaN(d.getTime())) return \"\";\r\n\r\n const localDate = new Date(d.getTime() - d.getTimezoneOffset() * 60000);\r\n const year = localDate.getFullYear();\r\n const month = (localDate.getMonth() + 1).toString().padStart(2, \"0\");\r\n const day = localDate.getDate().toString().padStart(2, \"0\");\r\n\r\n return `${year}-${month}-${day}`;\r\n};\r\n\r\nexport function convertCommaDataToArray(data: string | null | undefined): string[] {\r\n if (!data || data.trim() === \"\") {\r\n return [];\r\n }\r\n return data.split(\",\").map((item) => item.trim());\r\n}\r\n\r\nexport function checkIfExistsInArray<T>(array: T[], searchValue: T): boolean {\r\n return array.includes(searchValue);\r\n}\r\n\r\nexport const currencyFormatter = (value: number | null | undefined): string => {\r\n return value?.toLocaleString(\"en-US\", {\r\n style: \"currency\",\r\n currency: \"USD\",\r\n }) ?? \"\";\r\n};\r\nexport const formatNumber = (number: number | string | null | undefined): string => {\r\n if (isNaN(Number(number)) || number === null || number === undefined) {\r\n return \"0\";\r\n }\r\n\r\n const formattedNumber = Number(number)\r\n .toString()\r\n .replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\r\n\r\n return formattedNumber;\r\n};\r\n\r\nexport const parseCurrencyValueToNumber = (value: unknown): number => {\r\n if (value == null || value === \"\") return 0;\r\n\r\n const raw =\r\n typeof value === \"object\" && value !== null && \"value\" in value\r\n ? (value as { value: unknown }).value\r\n : value;\r\n\r\n const stringValue = raw == null || raw === \"\" ? \"\" : String(raw);\r\n const numericValue = stringValue.replace(/[$,]/g, \"\");\r\n return parseFloat(numericValue) || 0;\r\n};\r\n\r\nexport function flattenTableData<T extends Record<string, unknown>>(\r\n data: T[] | null | undefined,\r\n columns: { field?: string }[] | null | undefined\r\n): T[] {\r\n if (!Array.isArray(data)) return [];\r\n return data.map((row) => {\r\n const flatRow = { ...row };\r\n (columns ?? []).forEach((col) => {\r\n const key = col.field;\r\n if (!key) return;\r\n if (key.includes(\".\")) {\r\n const value = key.split(\".\").reduce<unknown>(\r\n (acc, part) => (acc as Record<string, unknown> | undefined)?.[part],\r\n row\r\n );\r\n (flatRow as Record<string, unknown>)[key] = value ?? \"\";\r\n }\r\n });\r\n return flatRow;\r\n });\r\n}\r\n\r\nexport const getErrorMessages = (error: {\r\n data?: {\r\n errors?: Record<string, string[]>;\r\n title?: string;\r\n error?: { name?: string[] };\r\n };\r\n} | null | undefined): string => {\r\n if (error?.data?.errors) {\r\n return Object.values(error.data.errors).flat().join(\"\\n\");\r\n }\r\n return (\r\n error?.data?.title ??\r\n error?.data?.error?.name?.[0] ??\r\n \"Failed to save\"\r\n );\r\n};\r\n\r\nexport const getFieldsByCategory = <T extends { category?: string }>(\r\n fields: T[] = [],\r\n key: string\r\n): T[] => {\r\n return fields?.filter(({ category = \"\" }) => category === key);\r\n};\r\n\r\nexport const getFieldsByName = <T extends { name?: string }>(\r\n fields: T[] = [],\r\n key: string\r\n): T[] => {\r\n return fields.filter(({ name = \"\" }) => name === key);\r\n};\r\n\r\nexport const deserializeJson = <T = unknown>(jsonString: string): T | null => {\r\n try {\r\n return JSON.parse(jsonString) as T;\r\n } catch (error) {\r\n console.error(\"Error parsing JSON:\", error);\r\n return null;\r\n }\r\n};\r\n\r\nexport const formatDateTime = (dateString: string | null | undefined): string => {\r\n if (!dateString) return \"Invalid Date\";\r\n const date = new Date(dateString);\r\n if (isNaN(date.getTime())) return \"Invalid Date\";\r\n const options: Intl.DateTimeFormatOptions = {\r\n year: \"numeric\",\r\n month: \"numeric\",\r\n day: \"numeric\",\r\n hour: \"numeric\",\r\n minute: \"numeric\",\r\n hour12: true,\r\n };\r\n return date.toLocaleString(\"en-US\", options);\r\n};\r\n\r\nexport const removeByPropertyValues = <T extends Record<string, unknown>>(\r\n items: T[] = [],\r\n property: keyof T & string,\r\n values: unknown[] = [],\r\n { caseInsensitive = false }: { caseInsensitive?: boolean } = {}\r\n): T[] => {\r\n if (!Array.isArray(items) || !property) return Array.isArray(items) ? items : [];\r\n const normalize = (v: unknown) =>\r\n caseInsensitive && typeof v === \"string\" ? v.toLowerCase() : v;\r\n const valuesArr = Array.isArray(values) ? values : [values];\r\n const toRemove = new Set(valuesArr.map(normalize));\r\n return items.filter((item) => !toRemove.has(normalize(item?.[property])));\r\n};\r\n\r\nexport const getFieldsByInputType = <T extends { inputType?: string }>(\r\n fields: T[] = [],\r\n key: string\r\n): T[] => {\r\n return fields.filter(({ inputType = \"\" }) => inputType === key);\r\n};\r\n","import toast from \"react-hot-toast\";\r\nimport Swal, { type SweetAlertOptions, type SweetAlertResult } from \"sweetalert2\";\r\n\r\nexport type RtkQueryError = {\r\n status?: number | string;\r\n originalStatus?: number;\r\n data?: {\r\n errors?: Record<string, string[]>;\r\n message?: string;\r\n title?: string;\r\n };\r\n error?: string;\r\n};\r\n\r\nexport interface HandleApiErrorOptions {\r\n showAlert?: boolean;\r\n fallbackMessage?: string;\r\n}\r\n\r\nexport function formatValidationErrorsHtml(\r\n errors: Record<string, string[]>\r\n): string {\r\n const items = Object.keys(errors).flatMap((field) =>\r\n (errors[field] || []).map((msg) => `<li>${msg}</li>`)\r\n );\r\n return `\r\n <div style=\"text-align:left\">\r\n <p>Please review and correct the following:</p>\r\n <ul style=\"margin:8px 0 0 16px; list-style:disc;\">\r\n ${items.join(\"\")}\r\n </ul>\r\n </div>\r\n `;\r\n}\r\n\r\nfunction showValidationAlert(html: string): void {\r\n void Swal.fire({\r\n title: \"Validation errors\",\r\n html,\r\n icon: \"error\",\r\n confirmButtonText: \"OK\",\r\n showCancelButton: false,\r\n confirmButtonColor: \"#FF7335\",\r\n });\r\n}\r\n\r\n/** Handles RTK Query errors with built-in toast.error or SweetAlert (when showAlert is true). */\r\nexport function handleApiError(\r\n error: RtkQueryError | null | undefined,\r\n { showAlert = false, fallbackMessage }: HandleApiErrorOptions = {}\r\n): void {\r\n if (!error) return;\r\n\r\n const status = error.status ?? error.originalStatus;\r\n const data = error.data;\r\n\r\n if (status === 200) {\r\n return;\r\n }\r\n\r\n if (data?.errors && typeof data.errors === \"object\") {\r\n const errors = data.errors;\r\n\r\n if (showAlert) {\r\n showValidationAlert(formatValidationErrorsHtml(errors));\r\n } else {\r\n Object.keys(errors).forEach((field) => {\r\n (errors[field] || []).forEach((errorMessage) => {\r\n toast.error(errorMessage);\r\n });\r\n });\r\n }\r\n return;\r\n }\r\n\r\n if (status === 404) {\r\n return;\r\n }\r\n\r\n const message =\r\n fallbackMessage ||\r\n data?.message ||\r\n data?.title ||\r\n error.error ||\r\n \"An error occurred. Please try again.\";\r\n\r\n toast.error(message);\r\n}\r\n\r\nconst BRAND_ORANGE = \"#FF7335\";\r\nconst CANCEL_RED = \"#ff0000\";\r\n\r\nexport interface ConfirmationAlertOptions {\r\n title?: string;\r\n text?: string;\r\n html?: string;\r\n icon?: \"warning\" | \"info\" | \"question\" | \"error\" | \"success\";\r\n confirmButtonText?: string;\r\n cancelButtonText?: string;\r\n confirmButtonColor?: string;\r\n cancelButtonColor?: string;\r\n showLoaderOnConfirm?: boolean;\r\n /** Type exactly — trimmed, case-sensitive. */\r\n inputExpectedValue?: string;\r\n inputPlaceholder?: string;\r\n reverseButtons?: boolean;\r\n focusCancel?: boolean;\r\n zIndex?: number;\r\n}\r\n\r\nfunction getConfirmErrorMessage(error: unknown): string {\r\n if (error && typeof error === \"object\") {\r\n const err = error as {\r\n message?: string;\r\n data?: { message?: string; title?: string };\r\n };\r\n return (\r\n err.data?.message ||\r\n err.data?.title ||\r\n err.message ||\r\n \"Something went wrong. Please try again.\"\r\n );\r\n }\r\n return \"Something went wrong. Please try again.\";\r\n}\r\n\r\nexport function confirmationAlert(\r\n onConfirm: () => void | Promise<void>,\r\n options: ConfirmationAlertOptions = {}\r\n): void {\r\n const {\r\n title = options.inputExpectedValue ? \"Confirmation Required\" : \"Are you sure?\",\r\n text,\r\n html,\r\n icon = \"warning\",\r\n confirmButtonText = \"Yes\",\r\n cancelButtonText = \"Cancel\",\r\n confirmButtonColor = BRAND_ORANGE,\r\n cancelButtonColor = CANCEL_RED,\r\n showLoaderOnConfirm = false,\r\n inputExpectedValue,\r\n inputPlaceholder = \"Type confirmation text to proceed\",\r\n reverseButtons,\r\n focusCancel,\r\n zIndex,\r\n } = options;\r\n\r\n const hasInput = Boolean(inputExpectedValue);\r\n const useLoader = showLoaderOnConfirm || hasInput;\r\n\r\n const inputHtml =\r\n html ??\r\n (hasInput\r\n ? `\r\n ${text ? `<p style=\"margin-bottom: 15px;\">${text}</p>` : \"\"}\r\n <p style=\"margin-bottom: 10px; font-weight: bold; color: #666;\">\r\n Please type \"<span style=\"color: ${BRAND_ORANGE}; font-weight: bold;\">${inputExpectedValue}</span>\" to confirm:\r\n </p>\r\n `\r\n : undefined);\r\n\r\n const swalOptions: SweetAlertOptions = {\r\n title,\r\n icon,\r\n showCancelButton: true,\r\n confirmButtonText,\r\n cancelButtonText,\r\n confirmButtonColor,\r\n cancelButtonColor,\r\n reverseButtons,\r\n focusCancel,\r\n allowOutsideClick: () => !Swal.isLoading(),\r\n allowEscapeKey: () => !Swal.isLoading(),\r\n didOpen: () => {\r\n if (zIndex == null) return;\r\n const container = Swal.getContainer();\r\n if (container) container.style.zIndex = String(zIndex);\r\n },\r\n };\r\n\r\n if (hasInput) {\r\n swalOptions.html = inputHtml;\r\n swalOptions.input = \"text\";\r\n swalOptions.inputPlaceholder = inputPlaceholder;\r\n swalOptions.inputValidator = (value: string) => {\r\n if (!value?.trim()) return \"You need to enter the confirmation text!\";\r\n if (value.trim() !== inputExpectedValue!.trim()) {\r\n return `Please type \"${inputExpectedValue}\" exactly as shown!`;\r\n }\r\n return null;\r\n };\r\n } else if (html) {\r\n swalOptions.html = html;\r\n } else {\r\n swalOptions.text = text;\r\n }\r\n\r\n if (useLoader) {\r\n swalOptions.showLoaderOnConfirm = true;\r\n swalOptions.preConfirm = (inputValue: string) => {\r\n if (hasInput && inputValue?.trim() !== inputExpectedValue!.trim()) {\r\n Swal.showValidationMessage(\r\n `Please type \"${inputExpectedValue}\" exactly as shown!`\r\n );\r\n return false;\r\n }\r\n return Promise.resolve()\r\n .then(() => onConfirm())\r\n .catch((error) => {\r\n Swal.showValidationMessage(getConfirmErrorMessage(error));\r\n throw error;\r\n });\r\n };\r\n }\r\n\r\n void Swal.fire(swalOptions).then((result: SweetAlertResult) => {\r\n if (result.isConfirmed && !useLoader) {\r\n void Promise.resolve(onConfirm());\r\n }\r\n });\r\n}\r\n"],"mappings":"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","names":[]}
|