@fctc/widget-logic 1.2.0 → 1.2.2

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/dist/hooks.mjs ADDED
@@ -0,0 +1,849 @@
1
+ // src/hooks/core/use-call-action.ts
2
+ import { getEnv, useLoadAction, useRunAction } from "@fctc/interface-logic";
3
+ import { useState } from "react";
4
+ var useCallAction = () => {
5
+ const queryLoadAction = useLoadAction();
6
+ const queryRunAction = useRunAction();
7
+ const [data, setData] = useState(void 0);
8
+ const callAction = async ({
9
+ aid,
10
+ actionType = "ir.actions.act_window"
11
+ }) => {
12
+ const context = getEnv().context;
13
+ let res = void 0;
14
+ if (actionType === "ir.actions.act_window") {
15
+ res = await queryLoadAction.mutateAsync({
16
+ idAction: aid,
17
+ context
18
+ });
19
+ } else if (actionType === "ir.actions.server") {
20
+ res = await queryRunAction.mutateAsync({
21
+ idAction: aid,
22
+ context
23
+ });
24
+ }
25
+ setData(res);
26
+ return res;
27
+ };
28
+ return [data, callAction];
29
+ };
30
+
31
+ // src/hooks/core/use-config.ts
32
+ import {
33
+ getEnv as getEnv2,
34
+ setEnvFile,
35
+ useAppDispatch
36
+ } from "@fctc/interface-logic";
37
+ import { useEffect, useMemo } from "react";
38
+ var useConfig = ({ localStorageUtils, sessionStorageUtils }) => {
39
+ const dispatch = useAppDispatch();
40
+ const envConfig = useMemo(() => {
41
+ return {
42
+ mode: "development",
43
+ baseUrl: "https://api.vitrust.app/c2/api/v2",
44
+ config: {
45
+ grantType: "password",
46
+ clientId: "C52foVQSMpnNOcAP2CBIIkupOSfxUarF8nlOPfXM",
47
+ clientSecret: "rColINr4a9QBFQPqQB8YU1XfBjqzwerDMJGBxsFK"
48
+ }
49
+ };
50
+ }, []);
51
+ const config = useMemo(() => {
52
+ return {
53
+ VITE_SIDEBAR_TYPE: "grid/sidebar",
54
+ VITE_APP_DOMAIN: "https://api.vitrust.app/c2/",
55
+ VITE_IS_EDU: true,
56
+ VITE_LOGO_WHITE_LOGIN: "https://static.vitrust.app/vitrust/3a/3a1301f614dea6ee19ebf99b68f57e3fd46011d2.png",
57
+ VITE_LOGO_BLACK_LOGIN: "https://static.vitrust.app/vitrust/32/3223918780da7a439f916faac9abf0bfe98dfa07.png",
58
+ VITE_BACKGROUND_SIDEBAR: "linear-gradient(178deg, rgb(1, 106, 13) -0.89%, rgb(4, 179, 66) 99.46%",
59
+ VITE_BANNER: "https://static.vitrust.app/vitrust/5d/5d20cab0627182b4ed5cba4ee42c58b98b663e5b.svg",
60
+ VITE_BG_BUTTON: "#008F3C",
61
+ VITE_BACKGROUND_PAGE: "#F9FAFB"
62
+ };
63
+ }, []);
64
+ useEffect(() => {
65
+ try {
66
+ const env = getEnv2();
67
+ env.setupEnv({
68
+ baseUrl: envConfig.baseUrl,
69
+ port: 3e3,
70
+ config: {
71
+ grantType: envConfig.config.grantType,
72
+ clientId: envConfig.config.clientId,
73
+ clientSecret: envConfig.config.clientSecret
74
+ },
75
+ db: "preschool",
76
+ localStorageUtils: localStorageUtils(),
77
+ sessionStorageUtils: sessionStorageUtils()
78
+ });
79
+ dispatch(setEnvFile(config));
80
+ } catch (error) {
81
+ console.error("Error loading env or config:", error);
82
+ }
83
+ }, [dispatch, envConfig, config]);
84
+ return { envConfig, config };
85
+ };
86
+
87
+ // src/hooks/core/use-detail.ts
88
+ import { setProfile, useAppDispatch as useAppDispatch2, useGetDetail } from "@fctc/interface-logic";
89
+ import { useQuery } from "@tanstack/react-query";
90
+ import { useEffect as useEffect2 } from "react";
91
+ var useDetail = (accessToken, sub) => {
92
+ const dispatch = useAppDispatch2();
93
+ const fetchGetDetail = useGetDetail();
94
+ const userDetailQuery = useQuery({
95
+ queryKey: ["userDetailQuery", sub && accessToken],
96
+ queryFn: () => {
97
+ return fetchGetDetail.mutateAsync({
98
+ model: "res.users",
99
+ ids: [sub],
100
+ specification: { image_256: {} }
101
+ });
102
+ },
103
+ enabled: !!sub && !!accessToken
104
+ });
105
+ useEffect2(() => {
106
+ if (userDetailQuery.data) {
107
+ const userPicture = userDetailQuery.data;
108
+ dispatch(
109
+ setProfile({ ...userPicture, image: userPicture?.[0]?.image_256 })
110
+ );
111
+ }
112
+ }, [userDetailQuery.data, dispatch]);
113
+ return userDetailQuery;
114
+ };
115
+
116
+ // src/hooks/core/use-list-data.ts
117
+ import { useMemo as useMemo2, useState as useState3 } from "react";
118
+ import {
119
+ evalJSONDomain,
120
+ formatSortingString,
121
+ selectList,
122
+ selectSearch,
123
+ useAppSelector,
124
+ useGetListData,
125
+ useModel
126
+ } from "@fctc/interface-logic";
127
+
128
+ // src/utils/function.ts
129
+ import { useCallback, useEffect as useEffect3, useReducer, useRef, useState as useState2 } from "react";
130
+ var getDateRange = (currentDate, unit) => {
131
+ const date = new Date(currentDate);
132
+ let dateStart, dateEnd;
133
+ function formatDate(d) {
134
+ return d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0") + " " + String(d.getHours()).padStart(2, "0") + ":" + String(d.getMinutes()).padStart(2, "0") + ":" + String(d.getSeconds()).padStart(2, "0");
135
+ }
136
+ switch (unit) {
137
+ case "month":
138
+ dateStart = new Date(
139
+ date.getFullYear(),
140
+ date.getMonth() + 1,
141
+ date.getDate(),
142
+ 23,
143
+ 59,
144
+ 59
145
+ );
146
+ dateStart.setHours(dateStart.getHours() - 7);
147
+ dateEnd = new Date(date.getFullYear(), date.getMonth(), 0, 0, 0, 0);
148
+ dateEnd.setHours(dateEnd.getHours() - 7);
149
+ break;
150
+ case "day":
151
+ dateStart = new Date(
152
+ date.getFullYear(),
153
+ date.getMonth(),
154
+ date.getDate(),
155
+ 23,
156
+ 59,
157
+ 59
158
+ );
159
+ dateStart.setHours(dateStart.getHours() - 7);
160
+ dateEnd = new Date(
161
+ date.getFullYear(),
162
+ date.getMonth(),
163
+ date.getDate(),
164
+ 0,
165
+ 0,
166
+ 0
167
+ );
168
+ dateEnd.setHours(dateEnd.getHours() - 7);
169
+ break;
170
+ case "week":
171
+ const dayOfWeek = date.getDay();
172
+ const daysToMonday = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
173
+ const daysToSunday = dayOfWeek === 0 ? 0 : 7 - dayOfWeek;
174
+ dateStart = new Date(
175
+ date.getFullYear(),
176
+ date.getMonth(),
177
+ date.getDate() + daysToSunday,
178
+ 23,
179
+ 59,
180
+ 59
181
+ );
182
+ dateStart.setHours(dateStart.getHours() - 7);
183
+ dateEnd = new Date(
184
+ date.getFullYear(),
185
+ date.getMonth(),
186
+ date.getDate() + daysToMonday,
187
+ 0,
188
+ 0,
189
+ 0
190
+ );
191
+ dateEnd.setHours(dateEnd.getHours() - 7);
192
+ break;
193
+ case "year":
194
+ dateStart = new Date(date.getFullYear(), 11, 31, 23, 59, 59);
195
+ dateStart.setHours(dateStart.getHours() - 7);
196
+ dateEnd = new Date(date.getFullYear() - 1, 11, 31, 0, 0, 0);
197
+ dateEnd.setHours(dateEnd.getHours() - 7);
198
+ break;
199
+ default:
200
+ throw new Error(
201
+ "\u0110\u01A1n v\u1ECB kh\xF4ng h\u1EE3p l\u1EC7. Ch\u1EC9 ch\u1EA5p nh\u1EADn: week, day, month, year"
202
+ );
203
+ }
204
+ return [
205
+ ["date_start", "<=", formatDate(dateStart)],
206
+ ["date_end", ">=", formatDate(dateEnd)]
207
+ ];
208
+ };
209
+ var convertFieldsToArray = (fields) => {
210
+ const defaultFields = ["display_name", "date_start", "date_end"];
211
+ if (!fields || !Array.isArray(fields)) {
212
+ return defaultFields;
213
+ }
214
+ const inputFields = fields.filter((field) => field && field.type_co === "field").map((field) => field.name);
215
+ return [...defaultFields, ...inputFields];
216
+ };
217
+ function combineContexts(contexts) {
218
+ if (contexts.some((context) => !context)) {
219
+ return void 0;
220
+ } else {
221
+ const res = contexts.reduce((acc, context) => {
222
+ return { ...acc, ...context };
223
+ }, {});
224
+ return res;
225
+ }
226
+ }
227
+ function useAsyncState(initialValue = [true, null]) {
228
+ return useReducer(
229
+ (_state, action = null) => [false, action],
230
+ initialValue
231
+ );
232
+ }
233
+ async function setStorageItemAsync(key, value) {
234
+ try {
235
+ if (value === null) {
236
+ localStorage.removeItem(key);
237
+ } else {
238
+ localStorage.setItem(key, value);
239
+ }
240
+ } catch (e) {
241
+ console.error("Local storage is unavailable:", e);
242
+ }
243
+ }
244
+ function useStorageState(key) {
245
+ const [state, setState] = useAsyncState();
246
+ useEffect3(() => {
247
+ try {
248
+ const storedValue = localStorage.getItem(key);
249
+ setState(storedValue);
250
+ } catch (e) {
251
+ console.error("Local storage is unavailable:", e);
252
+ }
253
+ }, [key]);
254
+ const setValue = useCallback(
255
+ (value) => {
256
+ setState(value);
257
+ setStorageItemAsync(key, value);
258
+ },
259
+ [key]
260
+ );
261
+ return [state, setValue];
262
+ }
263
+
264
+ // src/hooks/core/use-list-data.ts
265
+ var useListData = ({
266
+ action,
267
+ context,
268
+ viewResponse
269
+ }) => {
270
+ const { groupByDomain } = useAppSelector(selectSearch);
271
+ const initModel = useModel();
272
+ const [type, setType] = useState3("list");
273
+ const [mode, setMode] = useState3("month");
274
+ const [currentDate, setCurrentDate] = useState3(/* @__PURE__ */ new Date());
275
+ const { pageLimit, page, order } = useAppSelector(selectList);
276
+ const listDataProps = useMemo2(() => {
277
+ const actData = action?.result;
278
+ if (!viewResponse || !actData || !context) {
279
+ return null;
280
+ }
281
+ const specification = initModel.initModel({
282
+ name: String(actData.res_model),
283
+ view: viewResponse || {},
284
+ actContext: context,
285
+ fields: type === "kanban" ? viewResponse?.views?.kanban?.fields : type === "calendar" ? viewResponse?.views?.calendar?.fields : viewResponse?.views?.list?.fields
286
+ }).getSpecification();
287
+ const domain = type === "calendar" ? getDateRange(currentDate, mode) : actData?.domain ? Array.isArray(actData?.domain) ? [...actData?.domain] : evalJSONDomain(actData?.domain, context) : [];
288
+ const limit = type === "calendar" ? 2500 : pageLimit;
289
+ const offset = page * pageLimit;
290
+ const fields = type === "calendar" ? convertFieldsToArray(viewResponse?.views?.calendar?.fields) || [] : typeof groupByDomain === "object" ? groupByDomain?.fields : void 0;
291
+ const groupby = typeof groupByDomain === "object" ? [groupByDomain?.contexts?.[0]?.group_by] : [];
292
+ const sort = order ? order : viewResponse?.views?.list?.default_order ? formatSortingString(viewResponse?.views?.list?.default_order) : "";
293
+ return {
294
+ model: actData.res_model,
295
+ specification,
296
+ domain,
297
+ limit,
298
+ offset,
299
+ fields,
300
+ groupby,
301
+ context,
302
+ sort,
303
+ type
304
+ };
305
+ }, [
306
+ action?.result,
307
+ context,
308
+ currentDate,
309
+ groupByDomain,
310
+ initModel,
311
+ mode,
312
+ order,
313
+ page,
314
+ pageLimit,
315
+ type,
316
+ viewResponse
317
+ ]);
318
+ const list = useGetListData(
319
+ listDataProps,
320
+ [listDataProps],
321
+ !!listDataProps
322
+ );
323
+ return {
324
+ ...list,
325
+ state: {
326
+ type,
327
+ setType,
328
+ mode,
329
+ setMode,
330
+ currentDate,
331
+ setCurrentDate
332
+ }
333
+ };
334
+ };
335
+
336
+ // src/hooks/core/use-menu.ts
337
+ import { useEffect as useEffect4, useMemo as useMemo3, useState as useState4 } from "react";
338
+ import { useGetMenu } from "@fctc/interface-logic";
339
+
340
+ // src/utils/constants.ts
341
+ var languages = [
342
+ { id: "vi_VN", name: "VIE" },
343
+ { id: "en_US", name: "ENG" }
344
+ ];
345
+ var API_APP_URL = {
346
+ baseUrl: "https://api.vitrust.app",
347
+ c2: "https://api.vitrust.app/c2",
348
+ apiV2: "https://api.vitrust.app/c2/api/v2"
349
+ };
350
+
351
+ // src/hooks/core/use-menu.ts
352
+ var useMenu = ({ context }) => {
353
+ const menuData = useGetMenu(context, !!context);
354
+ const [menuid, setMenuId] = useState4(void 0);
355
+ const [action, setAction] = useCallAction();
356
+ const configedIconData = useMemo3(() => {
357
+ const data = menuData.data;
358
+ return data?.map((item) => {
359
+ return {
360
+ ...item,
361
+ child_id: item?.child_id?.map((child) => {
362
+ return {
363
+ ...child,
364
+ url_icon: API_APP_URL.c2 + "/" + child.url_icon
365
+ };
366
+ }) ?? [],
367
+ url_icon: API_APP_URL.c2 + "/" + item.url_icon
368
+ };
369
+ });
370
+ }, [menuData.data]);
371
+ const handleChangeMenu = async ({
372
+ menu,
373
+ subMenu
374
+ }) => {
375
+ const aid = subMenu?.action?.id?.id;
376
+ const actionType = subMenu?.action?.type;
377
+ await setAction({
378
+ aid: Number(aid),
379
+ actionType
380
+ });
381
+ if (menu) {
382
+ setMenuId(menu.id?.toString() ?? "");
383
+ }
384
+ };
385
+ useEffect4(() => {
386
+ const firstRecord = configedIconData?.[0];
387
+ const firstChild = firstRecord?.child_id?.[0];
388
+ if (firstChild && firstRecord) {
389
+ handleChangeMenu({ menu: firstRecord, subMenu: firstChild });
390
+ }
391
+ }, [configedIconData]);
392
+ return {
393
+ ...menuData,
394
+ data: configedIconData,
395
+ action: { handleChangeMenu },
396
+ state: { menuid, action },
397
+ context
398
+ };
399
+ };
400
+
401
+ // src/hooks/core/use-profile.ts
402
+ import { useQuery as useQuery2 } from "@tanstack/react-query";
403
+ import { useEffect as useEffect5, useMemo as useMemo4 } from "react";
404
+ import { useTranslation } from "react-i18next";
405
+ import {
406
+ getEnv as getEnv3,
407
+ setDataUser,
408
+ useAppDispatch as useAppDispatch3,
409
+ useGetProfile
410
+ } from "@fctc/interface-logic";
411
+ var useProfile = (accessToken) => {
412
+ const getProfile = useGetProfile();
413
+ const dispatch = useAppDispatch3();
414
+ const { i18n } = useTranslation();
415
+ const fetchUserProfile = async () => {
416
+ return await getProfile.mutateAsync();
417
+ };
418
+ const userInfoQuery = useQuery2({
419
+ queryKey: ["userInfo", accessToken],
420
+ queryFn: fetchUserProfile,
421
+ enabled: !!accessToken
422
+ });
423
+ useEffect5(() => {
424
+ if (userInfoQuery.data) {
425
+ const userInfo = userInfoQuery.data;
426
+ const env = getEnv3();
427
+ env.setUid(userInfo?.sub);
428
+ dispatch(setDataUser(userInfo));
429
+ const userLocale = languages.find((lang) => lang?.id === userInfo?.locale);
430
+ env.setLang(userLocale?.id);
431
+ i18n.changeLanguage(userLocale?.id.split("_")[0]);
432
+ }
433
+ }, [dispatch, userInfoQuery.data]);
434
+ const context = useMemo4(() => {
435
+ if (userInfoQuery.data?.sub && userInfoQuery.data?.locale) {
436
+ return {
437
+ uid: Number(userInfoQuery.data.sub),
438
+ allowed_company_ids: [],
439
+ lang: String(userInfoQuery.data.locale),
440
+ tz: "Asia/Saigon"
441
+ };
442
+ }
443
+ return void 0;
444
+ }, [userInfoQuery.data]);
445
+ return { ...userInfoQuery, context };
446
+ };
447
+
448
+ // src/hooks/core/use-user.ts
449
+ var useUser = (accessToken) => {
450
+ const userProfile = useProfile(accessToken);
451
+ const userDetail = useDetail(accessToken, userProfile.data?.sub);
452
+ return { userProfile, userDetail, context: userProfile.context };
453
+ };
454
+
455
+ // src/hooks/core/use-view-v2.ts
456
+ import { useMemo as useMemo5 } from "react";
457
+ import { useGetView } from "@fctc/interface-logic";
458
+ var useViewV2 = ({
459
+ action,
460
+ context
461
+ }) => {
462
+ const viewParams = useMemo5(() => {
463
+ if (!action?.result) {
464
+ return void 0;
465
+ }
466
+ const actionResult = action?.result;
467
+ return {
468
+ model: String(actionResult?.res_model),
469
+ views: [
470
+ ...Array.isArray(actionResult?.views) ? actionResult?.views.map(
471
+ (view2) => view2[1] === "list" ? [view2[0], "list"] : view2
472
+ ) : [],
473
+ [
474
+ Array.isArray(actionResult?.search_view_id) ? actionResult?.search_view_id[0] : actionResult?.search_view_id,
475
+ "search"
476
+ ]
477
+ ],
478
+ context
479
+ };
480
+ }, [action, context]);
481
+ const view = useGetView(
482
+ viewParams || {},
483
+ !!viewParams
484
+ );
485
+ return {
486
+ ...view,
487
+ context
488
+ };
489
+ };
490
+
491
+ // src/hooks/core/use-auth.ts
492
+ import {
493
+ setDataUser as setDataUser2,
494
+ setMenuList,
495
+ setProfile as setProfile2,
496
+ useAppDispatch as useAppDispatch4,
497
+ useLoginCredential
498
+ } from "@fctc/interface-logic";
499
+ var useAuth = () => {
500
+ const [[isLoading, accessToken], setAccessToken] = useStorageState("TOKEN");
501
+ const loginMutate = useLoginCredential();
502
+ const dispatch = useAppDispatch4();
503
+ const signIn = async (email, password) => {
504
+ try {
505
+ loginMutate.mutate(
506
+ {
507
+ email,
508
+ password,
509
+ path: "/authentication/oauth2/token"
510
+ },
511
+ {
512
+ onSuccess: (res) => {
513
+ setAccessToken(res.access_token);
514
+ },
515
+ onError: (err) => {
516
+ }
517
+ }
518
+ );
519
+ } catch (error) {
520
+ throw new Error("Login failed");
521
+ }
522
+ };
523
+ const signOut = async () => {
524
+ dispatch(setMenuList([]));
525
+ dispatch(setDataUser2({}));
526
+ dispatch(setProfile2({}));
527
+ setAccessToken(null);
528
+ };
529
+ return {
530
+ signIn,
531
+ signOut,
532
+ accessToken,
533
+ isLoading
534
+ };
535
+ };
536
+
537
+ // src/hooks/core/use-app-provider.tsx
538
+ import { createContext, useContext, useMemo as useMemo7 } from "react";
539
+
540
+ // src/hooks/core/use-company.ts
541
+ import {
542
+ getEnv as getEnv4,
543
+ useGetCompanyInfo,
544
+ useGetCurrentCompany
545
+ } from "@fctc/interface-logic";
546
+ import { useQuery as useQuery3 } from "@tanstack/react-query";
547
+ import { useEffect as useEffect6, useMemo as useMemo6 } from "react";
548
+ var useCompany = (accessToken) => {
549
+ const getCurrentCompany = useGetCurrentCompany();
550
+ const fetchCurrentCompany = async () => {
551
+ return await getCurrentCompany.mutateAsync();
552
+ };
553
+ const currentCompany = useQuery3({
554
+ queryKey: ["currentCompany", accessToken],
555
+ queryFn: fetchCurrentCompany,
556
+ enabled: !!accessToken
557
+ });
558
+ const current_company_id = useMemo6(() => {
559
+ return currentCompany.data?.current_company_id;
560
+ }, [currentCompany.data]);
561
+ useEffect6(() => {
562
+ if (current_company_id) {
563
+ const companyIDs = [current_company_id];
564
+ const env = getEnv4();
565
+ env.setAllowCompanies([...companyIDs]);
566
+ env.setCompanies(companyIDs);
567
+ }
568
+ }, [current_company_id]);
569
+ const getCompanyInfo = useGetCompanyInfo();
570
+ const companyInfo = useQuery3({
571
+ queryKey: ["companyInfoQuery", current_company_id, accessToken],
572
+ queryFn: () => getCompanyInfo.mutateAsync(Number(current_company_id)),
573
+ enabled: !!current_company_id && !!accessToken
574
+ });
575
+ useEffect6(() => {
576
+ if (companyInfo.data) {
577
+ const companyInfoData = companyInfo.data;
578
+ if (companyInfoData?.length) {
579
+ const env = getEnv4();
580
+ env.setDefaultCompany(companyInfoData[0]);
581
+ }
582
+ }
583
+ }, [companyInfo.data]);
584
+ return {
585
+ currentCompany,
586
+ companyInfo,
587
+ context: { allowed_company_ids: [current_company_id] }
588
+ };
589
+ };
590
+ var use_company_default = useCompany;
591
+
592
+ // src/hooks/core/use-app-provider.tsx
593
+ import { evalJSONContext, MainProvider } from "@fctc/interface-logic";
594
+ import { jsx } from "react/jsx-runtime";
595
+ var AppProviderInitialValue = {
596
+ config: {},
597
+ user: {},
598
+ auth: {},
599
+ company: {},
600
+ action: {},
601
+ menu: {},
602
+ view: {},
603
+ list: {}
604
+ };
605
+ var ReactContext = createContext(AppProviderInitialValue);
606
+ var AppProvider = ({ children }) => {
607
+ const config = useConfig({});
608
+ const auth = useAuth();
609
+ const user = useUser(auth.accessToken);
610
+ const company = use_company_default(auth.accessToken);
611
+ const menuContext = useMemo7(() => {
612
+ return combineContexts([user.context, company.context]);
613
+ }, [user.context, company.context]);
614
+ const menu = useMenu({ context: menuContext });
615
+ const action = useMemo7(() => {
616
+ return menu.state.action;
617
+ }, [menu.state.action]);
618
+ const viewContext = useMemo7(() => {
619
+ return combineContexts([
620
+ menuContext,
621
+ { ...evalJSONContext(action?.result?.context) }
622
+ ]);
623
+ }, [menuContext, action?.result?.context]);
624
+ const view = useViewV2({
625
+ action,
626
+ context: viewContext
627
+ });
628
+ const list = useListData({
629
+ action,
630
+ viewResponse: view.data,
631
+ context: viewContext
632
+ });
633
+ return /* @__PURE__ */ jsx(
634
+ ReactContext.Provider,
635
+ {
636
+ value: {
637
+ config,
638
+ auth,
639
+ user,
640
+ company,
641
+ menu,
642
+ list,
643
+ action,
644
+ view
645
+ },
646
+ children: /* @__PURE__ */ jsx(MainProvider, { children })
647
+ }
648
+ );
649
+ };
650
+ var useAppProvider = () => {
651
+ const context = useContext(ReactContext);
652
+ if (!context) {
653
+ return AppProviderInitialValue;
654
+ }
655
+ return context;
656
+ };
657
+
658
+ // src/hooks/utils/use-click-outside.ts
659
+ import { useEffect as useEffect7, useRef as useRef2 } from "react";
660
+ var DEFAULT_EVENTS = ["mousedown", "touchstart"];
661
+ var useClickOutside = ({
662
+ handler,
663
+ events = DEFAULT_EVENTS,
664
+ nodes = [],
665
+ refs
666
+ }) => {
667
+ const ref = useRef2(null);
668
+ useEffect7(() => {
669
+ const listener = (event) => {
670
+ const { target } = event;
671
+ if (refs && refs?.length > 0 && refs?.some((r) => r.current?.contains(target))) {
672
+ return;
673
+ }
674
+ if (!(target instanceof HTMLElement)) return;
675
+ const shouldIgnore = target.hasAttribute("data-ignore-outside-clicks") || !document.body.contains(target) && target.tagName !== "HTML";
676
+ const shouldTrigger = nodes.length > 0 ? nodes.every((node) => node && !event.composedPath().includes(node)) : ref.current && !ref.current.contains(target);
677
+ if (shouldTrigger && !shouldIgnore) {
678
+ handler(event);
679
+ }
680
+ };
681
+ events.forEach((event) => document.addEventListener(event, listener));
682
+ return () => {
683
+ events.forEach((event) => document.removeEventListener(event, listener));
684
+ };
685
+ }, [handler, nodes, events]);
686
+ return ref;
687
+ };
688
+
689
+ // src/hooks/utils/use-debounce.ts
690
+ import { useEffect as useEffect8, useState as useState5 } from "react";
691
+ function useDebounce(value, delay) {
692
+ const [debouncedValue, setDebouncedValue] = useState5(value);
693
+ useEffect8(() => {
694
+ const handler = setTimeout(() => {
695
+ setDebouncedValue(value);
696
+ }, delay);
697
+ return () => {
698
+ clearTimeout(handler);
699
+ };
700
+ }, [value, delay]);
701
+ return [debouncedValue];
702
+ }
703
+
704
+ // src/hooks/api/use-switch-locale.ts
705
+ import {
706
+ getEnv as getEnv5,
707
+ selectEnv,
708
+ useAppSelector as useAppSelector2,
709
+ useSwitchLocale
710
+ } from "@fctc/interface-logic";
711
+ import { useCallback as useCallback2 } from "react";
712
+ var useSwitchLocaleHandler = () => {
713
+ const switchUserLocale = useSwitchLocale();
714
+ const env = getEnv5();
715
+ const { context } = useAppSelector2(selectEnv);
716
+ const switchLocale = useCallback2(
717
+ async (langId) => {
718
+ if (!langId) return;
719
+ await switchUserLocale.mutateAsync({
720
+ data: {
721
+ id: parseInt(context?.uid),
722
+ values: { lang: langId }
723
+ }
724
+ });
725
+ env.setLang(langId);
726
+ },
727
+ [switchUserLocale]
728
+ );
729
+ return {
730
+ switchLocale,
731
+ isLoading: switchUserLocale.isPending,
732
+ error: switchUserLocale.error
733
+ };
734
+ };
735
+
736
+ // src/hooks/api/use-login.ts
737
+ import { useLoginCredential as useLoginCredential2 } from "@fctc/interface-logic";
738
+ import { useCallback as useCallback3 } from "react";
739
+ var useLoginHandler = () => {
740
+ const loginMutate = useLoginCredential2();
741
+ const login = useCallback3(
742
+ ({
743
+ email,
744
+ password,
745
+ path
746
+ }, {
747
+ onSuccess,
748
+ onError
749
+ }) => {
750
+ loginMutate.mutate(
751
+ {
752
+ email,
753
+ password,
754
+ path
755
+ },
756
+ {
757
+ onSuccess,
758
+ onError
759
+ }
760
+ );
761
+ },
762
+ [loginMutate]
763
+ );
764
+ return {
765
+ login,
766
+ isLoading: loginMutate.isPending,
767
+ error: loginMutate.error
768
+ };
769
+ };
770
+
771
+ // src/hooks/api/use-forgot-password.ts
772
+ import { useForgotPassword } from "@fctc/interface-logic";
773
+ import { useCallback as useCallback4 } from "react";
774
+ var useForgotPasswordHandler = () => {
775
+ const forgotPasswordMutate = useForgotPassword();
776
+ const sendForgotPassword = useCallback4(
777
+ (email, {
778
+ onSuccess,
779
+ onError
780
+ } = {}) => {
781
+ forgotPasswordMutate.mutate(email, {
782
+ onSuccess,
783
+ onError
784
+ });
785
+ },
786
+ [forgotPasswordMutate]
787
+ );
788
+ return {
789
+ sendForgotPassword,
790
+ isLoading: forgotPasswordMutate.isPending,
791
+ error: forgotPasswordMutate.error
792
+ };
793
+ };
794
+
795
+ // src/hooks/api/use-reset-password.ts
796
+ import { useResetPassword } from "@fctc/interface-logic";
797
+ import { useCallback as useCallback5 } from "react";
798
+ var useResetPasswordHandler = () => {
799
+ const resetPasswordMutate = useResetPassword();
800
+ const resetPassword = useCallback5(
801
+ ({
802
+ password,
803
+ confirmPassword,
804
+ token
805
+ }, {
806
+ onSuccess,
807
+ onError
808
+ }) => {
809
+ resetPasswordMutate.mutate(
810
+ {
811
+ data: {
812
+ password,
813
+ confirmPassword
814
+ },
815
+ token
816
+ },
817
+ {
818
+ onSuccess,
819
+ onError
820
+ }
821
+ );
822
+ },
823
+ [resetPasswordMutate]
824
+ );
825
+ return {
826
+ resetPassword,
827
+ isLoading: resetPasswordMutate.isPending,
828
+ error: resetPasswordMutate.error
829
+ };
830
+ };
831
+ export {
832
+ AppProvider,
833
+ useAppProvider,
834
+ useAuth,
835
+ useCallAction,
836
+ useClickOutside,
837
+ useConfig,
838
+ useDebounce,
839
+ useDetail,
840
+ useForgotPasswordHandler,
841
+ useListData,
842
+ useLoginHandler,
843
+ useMenu,
844
+ useProfile,
845
+ useResetPasswordHandler,
846
+ useSwitchLocaleHandler,
847
+ useUser,
848
+ useViewV2
849
+ };