@fctc/widget-logic 1.1.4 → 1.1.6

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.js CHANGED
@@ -20,13 +20,525 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/hooks.ts
21
21
  var hooks_exports = {};
22
22
  __export(hooks_exports, {
23
+ useAuth: () => useAuth,
24
+ useCallAction: () => useCallAction,
23
25
  useClickOutside: () => useClickOutside,
24
- useDebounce: () => useDebounce
26
+ useConfig: () => useConfig,
27
+ useDebounce: () => useDebounce,
28
+ useDetail: () => useDetail,
29
+ useListData: () => useListData,
30
+ useMenu: () => useMenu,
31
+ useProfile: () => useProfile,
32
+ useUser: () => useUser,
33
+ useViewV2: () => useViewV2
25
34
  });
26
35
  module.exports = __toCommonJS(hooks_exports);
27
36
 
28
- // src/hooks/use-click-outside.ts
37
+ // src/hooks/core/use-call-action.ts
38
+ var import_interface_logic = require("@fctc/interface-logic");
29
39
  var import_react = require("react");
40
+ var useCallAction = () => {
41
+ const queryLoadAction = (0, import_interface_logic.useLoadAction)();
42
+ const queryRunAction = (0, import_interface_logic.useRunAction)();
43
+ const [data, setData] = (0, import_react.useState)(void 0);
44
+ const callAction = async ({
45
+ aid,
46
+ actionType = "ir.actions.act_window"
47
+ }) => {
48
+ const context = (0, import_interface_logic.getEnv)().context;
49
+ let res = void 0;
50
+ if (actionType === "ir.actions.act_window") {
51
+ res = await queryLoadAction.mutateAsync({
52
+ idAction: aid,
53
+ context
54
+ });
55
+ } else if (actionType === "ir.actions.server") {
56
+ res = await queryRunAction.mutateAsync({
57
+ idAction: aid,
58
+ context
59
+ });
60
+ }
61
+ setData(res);
62
+ return res;
63
+ };
64
+ return [data, callAction];
65
+ };
66
+
67
+ // src/hooks/core/use-config.ts
68
+ var import_interface_logic2 = require("@fctc/interface-logic");
69
+ var import_react2 = require("react");
70
+ var useConfig = ({ localStorageUtils, sessionStorageUtils }) => {
71
+ const dispatch = (0, import_interface_logic2.useAppDispatch)();
72
+ const envConfig = (0, import_react2.useMemo)(() => {
73
+ return {
74
+ mode: "development",
75
+ baseUrl: "https://api.vitrust.app/c2/api/v2",
76
+ config: {
77
+ grantType: "password",
78
+ clientId: "C52foVQSMpnNOcAP2CBIIkupOSfxUarF8nlOPfXM",
79
+ clientSecret: "rColINr4a9QBFQPqQB8YU1XfBjqzwerDMJGBxsFK"
80
+ }
81
+ };
82
+ }, []);
83
+ const config = (0, import_react2.useMemo)(() => {
84
+ return {
85
+ VITE_SIDEBAR_TYPE: "grid/sidebar",
86
+ VITE_APP_DOMAIN: "https://api.vitrust.app/c2/",
87
+ VITE_IS_EDU: true,
88
+ VITE_LOGO_WHITE_LOGIN: "https://static.vitrust.app/vitrust/3a/3a1301f614dea6ee19ebf99b68f57e3fd46011d2.png",
89
+ VITE_LOGO_BLACK_LOGIN: "https://static.vitrust.app/vitrust/32/3223918780da7a439f916faac9abf0bfe98dfa07.png",
90
+ VITE_BACKGROUND_SIDEBAR: "linear-gradient(178deg, rgb(1, 106, 13) -0.89%, rgb(4, 179, 66) 99.46%",
91
+ VITE_BANNER: "https://static.vitrust.app/vitrust/5d/5d20cab0627182b4ed5cba4ee42c58b98b663e5b.svg",
92
+ VITE_BG_BUTTON: "#008F3C",
93
+ VITE_BACKGROUND_PAGE: "#F9FAFB"
94
+ };
95
+ }, []);
96
+ (0, import_react2.useEffect)(() => {
97
+ try {
98
+ const env = (0, import_interface_logic2.getEnv)();
99
+ env.setupEnv({
100
+ baseUrl: envConfig.baseUrl,
101
+ port: 3e3,
102
+ config: {
103
+ grantType: envConfig.config.grantType,
104
+ clientId: envConfig.config.clientId,
105
+ clientSecret: envConfig.config.clientSecret
106
+ },
107
+ db: "preschool",
108
+ localStorageUtils: localStorageUtils(),
109
+ sessionStorageUtils: sessionStorageUtils()
110
+ });
111
+ dispatch((0, import_interface_logic2.setEnvFile)(config));
112
+ } catch (error) {
113
+ console.error("Error loading env or config:", error);
114
+ }
115
+ }, [dispatch, envConfig, config]);
116
+ return { envConfig, config };
117
+ };
118
+
119
+ // src/hooks/core/use-detail.ts
120
+ var import_interface_logic3 = require("@fctc/interface-logic");
121
+ var import_react_query = require("@tanstack/react-query");
122
+ var import_react3 = require("react");
123
+ var useDetail = (accessToken, sub) => {
124
+ const dispatch = (0, import_interface_logic3.useAppDispatch)();
125
+ const fetchGetDetail = (0, import_interface_logic3.useGetDetail)();
126
+ const userDetailQuery = (0, import_react_query.useQuery)({
127
+ queryKey: ["userDetailQuery", sub && accessToken],
128
+ queryFn: () => {
129
+ return fetchGetDetail.mutateAsync({
130
+ model: "res.users",
131
+ ids: [sub],
132
+ specification: { image_256: {} }
133
+ });
134
+ },
135
+ enabled: !!sub && !!accessToken
136
+ });
137
+ (0, import_react3.useEffect)(() => {
138
+ if (userDetailQuery.data) {
139
+ const userPicture = userDetailQuery.data;
140
+ dispatch(
141
+ (0, import_interface_logic3.setProfile)({ ...userPicture, image: userPicture?.[0]?.image_256 })
142
+ );
143
+ }
144
+ }, [userDetailQuery.data, dispatch]);
145
+ return userDetailQuery;
146
+ };
147
+
148
+ // src/hooks/core/use-list-data.ts
149
+ var import_react5 = require("react");
150
+ var import_interface_logic4 = require("@fctc/interface-logic");
151
+
152
+ // src/utils/function.ts
153
+ var import_react4 = require("react");
154
+ var getDateRange = (currentDate, unit) => {
155
+ const date = new Date(currentDate);
156
+ let dateStart, dateEnd;
157
+ function formatDate(d) {
158
+ 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");
159
+ }
160
+ switch (unit) {
161
+ case "month":
162
+ dateStart = new Date(
163
+ date.getFullYear(),
164
+ date.getMonth() + 1,
165
+ date.getDate(),
166
+ 23,
167
+ 59,
168
+ 59
169
+ );
170
+ dateStart.setHours(dateStart.getHours() - 7);
171
+ dateEnd = new Date(date.getFullYear(), date.getMonth(), 0, 0, 0, 0);
172
+ dateEnd.setHours(dateEnd.getHours() - 7);
173
+ break;
174
+ case "day":
175
+ dateStart = new Date(
176
+ date.getFullYear(),
177
+ date.getMonth(),
178
+ date.getDate(),
179
+ 23,
180
+ 59,
181
+ 59
182
+ );
183
+ dateStart.setHours(dateStart.getHours() - 7);
184
+ dateEnd = new Date(
185
+ date.getFullYear(),
186
+ date.getMonth(),
187
+ date.getDate(),
188
+ 0,
189
+ 0,
190
+ 0
191
+ );
192
+ dateEnd.setHours(dateEnd.getHours() - 7);
193
+ break;
194
+ case "week":
195
+ const dayOfWeek = date.getDay();
196
+ const daysToMonday = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
197
+ const daysToSunday = dayOfWeek === 0 ? 0 : 7 - dayOfWeek;
198
+ dateStart = new Date(
199
+ date.getFullYear(),
200
+ date.getMonth(),
201
+ date.getDate() + daysToSunday,
202
+ 23,
203
+ 59,
204
+ 59
205
+ );
206
+ dateStart.setHours(dateStart.getHours() - 7);
207
+ dateEnd = new Date(
208
+ date.getFullYear(),
209
+ date.getMonth(),
210
+ date.getDate() + daysToMonday,
211
+ 0,
212
+ 0,
213
+ 0
214
+ );
215
+ dateEnd.setHours(dateEnd.getHours() - 7);
216
+ break;
217
+ case "year":
218
+ dateStart = new Date(date.getFullYear(), 11, 31, 23, 59, 59);
219
+ dateStart.setHours(dateStart.getHours() - 7);
220
+ dateEnd = new Date(date.getFullYear() - 1, 11, 31, 0, 0, 0);
221
+ dateEnd.setHours(dateEnd.getHours() - 7);
222
+ break;
223
+ default:
224
+ throw new Error(
225
+ "\u0110\u01A1n v\u1ECB kh\xF4ng h\u1EE3p l\u1EC7. Ch\u1EC9 ch\u1EA5p nh\u1EADn: week, day, month, year"
226
+ );
227
+ }
228
+ return [
229
+ ["date_start", "<=", formatDate(dateStart)],
230
+ ["date_end", ">=", formatDate(dateEnd)]
231
+ ];
232
+ };
233
+ var convertFieldsToArray = (fields) => {
234
+ const defaultFields = ["display_name", "date_start", "date_end"];
235
+ if (!fields || !Array.isArray(fields)) {
236
+ return defaultFields;
237
+ }
238
+ const inputFields = fields.filter((field) => field && field.type_co === "field").map((field) => field.name);
239
+ return [...defaultFields, ...inputFields];
240
+ };
241
+ function useAsyncState(initialValue = [true, null]) {
242
+ return (0, import_react4.useReducer)(
243
+ (_state, action = null) => [false, action],
244
+ initialValue
245
+ );
246
+ }
247
+ async function setStorageItemAsync(key, value) {
248
+ try {
249
+ if (value === null) {
250
+ localStorage.removeItem(key);
251
+ } else {
252
+ localStorage.setItem(key, value);
253
+ }
254
+ } catch (e) {
255
+ console.error("Local storage is unavailable:", e);
256
+ }
257
+ }
258
+ function useStorageState(key) {
259
+ const [state, setState] = useAsyncState();
260
+ (0, import_react4.useEffect)(() => {
261
+ try {
262
+ const storedValue = localStorage.getItem(key);
263
+ setState(storedValue);
264
+ } catch (e) {
265
+ console.error("Local storage is unavailable:", e);
266
+ }
267
+ }, [key]);
268
+ const setValue = (0, import_react4.useCallback)(
269
+ (value) => {
270
+ setState(value);
271
+ setStorageItemAsync(key, value);
272
+ },
273
+ [key]
274
+ );
275
+ return [state, setValue];
276
+ }
277
+
278
+ // src/hooks/core/use-list-data.ts
279
+ var useListData = ({
280
+ action,
281
+ context,
282
+ viewResponse
283
+ }) => {
284
+ const { groupByDomain } = (0, import_interface_logic4.useAppSelector)(import_interface_logic4.selectSearch);
285
+ const initModel = (0, import_interface_logic4.useModel)();
286
+ const [type, setType] = (0, import_react5.useState)("list");
287
+ const [mode, setMode] = (0, import_react5.useState)("month");
288
+ const [currentDate, setCurrentDate] = (0, import_react5.useState)(/* @__PURE__ */ new Date());
289
+ const { pageLimit, page, order } = (0, import_interface_logic4.useAppSelector)(import_interface_logic4.selectList);
290
+ const listDataProps = (0, import_react5.useMemo)(() => {
291
+ const actData = action?.result;
292
+ if (!viewResponse || !actData || !context) {
293
+ return null;
294
+ }
295
+ const specification = initModel.initModel({
296
+ name: String(actData.res_model),
297
+ view: viewResponse || {},
298
+ actContext: context,
299
+ fields: type === "kanban" ? viewResponse?.views?.kanban?.fields : type === "calendar" ? viewResponse?.views?.calendar?.fields : viewResponse?.views?.list?.fields
300
+ }).getSpecification();
301
+ const domain = type === "calendar" ? getDateRange(currentDate, mode) : actData?.domain ? Array.isArray(actData?.domain) ? [...actData?.domain] : (0, import_interface_logic4.evalJSONDomain)(actData?.domain, context) : [];
302
+ const limit = type === "calendar" ? 2500 : pageLimit;
303
+ const offset = page * pageLimit;
304
+ const fields = type === "calendar" ? convertFieldsToArray(viewResponse?.views?.calendar?.fields) || [] : typeof groupByDomain === "object" ? groupByDomain?.fields : void 0;
305
+ const groupby = typeof groupByDomain === "object" ? [groupByDomain?.contexts?.[0]?.group_by] : [];
306
+ const sort = order ? order : viewResponse?.views?.list?.default_order ? (0, import_interface_logic4.formatSortingString)(viewResponse?.views?.list?.default_order) : "";
307
+ return {
308
+ model: actData.res_model,
309
+ specification,
310
+ domain,
311
+ limit,
312
+ offset,
313
+ fields,
314
+ groupby,
315
+ context,
316
+ sort,
317
+ type
318
+ };
319
+ }, [
320
+ action?.result,
321
+ context,
322
+ currentDate,
323
+ groupByDomain,
324
+ initModel,
325
+ mode,
326
+ order,
327
+ page,
328
+ pageLimit,
329
+ type,
330
+ viewResponse
331
+ ]);
332
+ const list = (0, import_interface_logic4.useGetListData)(
333
+ listDataProps,
334
+ [listDataProps],
335
+ !!listDataProps
336
+ );
337
+ return {
338
+ ...list,
339
+ state: {
340
+ type,
341
+ setType,
342
+ mode,
343
+ setMode,
344
+ currentDate,
345
+ setCurrentDate
346
+ }
347
+ };
348
+ };
349
+
350
+ // src/hooks/core/use-menu.ts
351
+ var import_react6 = require("react");
352
+ var import_interface_logic5 = require("@fctc/interface-logic");
353
+
354
+ // src/utils/constants.ts
355
+ var languages = [
356
+ { id: "vi_VN", name: "VIE" },
357
+ { id: "en_US", name: "ENG" }
358
+ ];
359
+ var API_APP_URL = {
360
+ baseUrl: "https://api.vitrust.app",
361
+ c2: "https://api.vitrust.app/c2",
362
+ apiV2: "https://api.vitrust.app/c2/api/v2"
363
+ };
364
+
365
+ // src/hooks/core/use-menu.ts
366
+ var useMenu = ({ context }) => {
367
+ const menuData = (0, import_interface_logic5.useGetMenu)(context, !!context);
368
+ const [menuid, setMenuId] = (0, import_react6.useState)(void 0);
369
+ const [action, setAction] = useCallAction();
370
+ const configedIconData = (0, import_react6.useMemo)(() => {
371
+ const data = menuData.data;
372
+ return data?.map((item) => {
373
+ return {
374
+ ...item,
375
+ child_id: item?.child_id?.map((child) => {
376
+ return {
377
+ ...child,
378
+ url_icon: API_APP_URL.c2 + "/" + child.url_icon
379
+ };
380
+ }) ?? [],
381
+ url_icon: API_APP_URL.c2 + "/" + item.url_icon
382
+ };
383
+ });
384
+ }, [menuData.data]);
385
+ const handleChangeMenu = async ({
386
+ menu,
387
+ subMenu
388
+ }) => {
389
+ const aid = subMenu?.action?.id?.id;
390
+ const actionType = subMenu?.action?.type;
391
+ await setAction({
392
+ aid: Number(aid),
393
+ actionType
394
+ });
395
+ if (menu) {
396
+ setMenuId(menu.id?.toString() ?? "");
397
+ }
398
+ };
399
+ (0, import_react6.useEffect)(() => {
400
+ const firstRecord = configedIconData?.[0];
401
+ const firstChild = firstRecord?.child_id?.[0];
402
+ if (firstChild && firstRecord) {
403
+ handleChangeMenu({ menu: firstRecord, subMenu: firstChild });
404
+ }
405
+ }, [configedIconData]);
406
+ return {
407
+ ...menuData,
408
+ data: configedIconData,
409
+ action: { handleChangeMenu },
410
+ state: { menuid, action },
411
+ context
412
+ };
413
+ };
414
+
415
+ // src/hooks/core/use-profile.ts
416
+ var import_react_query2 = require("@tanstack/react-query");
417
+ var import_react7 = require("react");
418
+ var import_react_i18next = require("react-i18next");
419
+ var import_interface_logic6 = require("@fctc/interface-logic");
420
+ var useProfile = (accessToken) => {
421
+ const getProfile = (0, import_interface_logic6.useGetProfile)();
422
+ const dispatch = (0, import_interface_logic6.useAppDispatch)();
423
+ const { i18n } = (0, import_react_i18next.useTranslation)();
424
+ const fetchUserProfile = async () => {
425
+ return await getProfile.mutateAsync();
426
+ };
427
+ const userInfoQuery = (0, import_react_query2.useQuery)({
428
+ queryKey: ["userInfo", accessToken],
429
+ queryFn: fetchUserProfile,
430
+ enabled: !!accessToken
431
+ });
432
+ (0, import_react7.useEffect)(() => {
433
+ if (userInfoQuery.data) {
434
+ const userInfo = userInfoQuery.data;
435
+ const env = (0, import_interface_logic6.getEnv)();
436
+ env.setUid(userInfo?.sub);
437
+ dispatch((0, import_interface_logic6.setDataUser)(userInfo));
438
+ const userLocale = languages.find((lang) => lang?.id === userInfo?.locale);
439
+ env.setLang(userLocale?.id);
440
+ i18n.changeLanguage(userLocale?.id.split("_")[0]);
441
+ }
442
+ }, [dispatch, userInfoQuery.data]);
443
+ const context = (0, import_react7.useMemo)(() => {
444
+ if (userInfoQuery.data?.sub && userInfoQuery.data?.locale) {
445
+ return {
446
+ uid: Number(userInfoQuery.data.sub),
447
+ allowed_company_ids: [],
448
+ lang: String(userInfoQuery.data.locale),
449
+ tz: "Asia/Saigon"
450
+ };
451
+ }
452
+ return void 0;
453
+ }, [userInfoQuery.data]);
454
+ return { ...userInfoQuery, context };
455
+ };
456
+
457
+ // src/hooks/core/use-user.ts
458
+ var useUser = (accessToken) => {
459
+ const userProfile = useProfile(accessToken);
460
+ const userDetail = useDetail(accessToken, userProfile.data?.sub);
461
+ return { userProfile, userDetail, context: userProfile.context };
462
+ };
463
+
464
+ // src/hooks/core/use-view-v2.ts
465
+ var import_react8 = require("react");
466
+ var import_interface_logic7 = require("@fctc/interface-logic");
467
+ var useViewV2 = ({
468
+ action,
469
+ context
470
+ }) => {
471
+ const viewParams = (0, import_react8.useMemo)(() => {
472
+ if (!action?.result) {
473
+ return void 0;
474
+ }
475
+ const actionResult = action?.result;
476
+ return {
477
+ model: String(actionResult?.res_model),
478
+ views: [
479
+ ...Array.isArray(actionResult?.views) ? actionResult?.views.map(
480
+ (view2) => view2[1] === "list" ? [view2[0], "list"] : view2
481
+ ) : [],
482
+ [
483
+ Array.isArray(actionResult?.search_view_id) ? actionResult?.search_view_id[0] : actionResult?.search_view_id,
484
+ "search"
485
+ ]
486
+ ],
487
+ context
488
+ };
489
+ }, [action, context]);
490
+ const view = (0, import_interface_logic7.useGetView)(
491
+ viewParams || {},
492
+ !!viewParams
493
+ );
494
+ return {
495
+ ...view,
496
+ context
497
+ };
498
+ };
499
+
500
+ // src/hooks/core/use-auth.ts
501
+ var import_interface_logic8 = require("@fctc/interface-logic");
502
+ var useAuth = () => {
503
+ const [[isLoading, accessToken], setAccessToken] = useStorageState("TOKEN");
504
+ const loginMutate = (0, import_interface_logic8.useLoginCredential)();
505
+ const dispatch = (0, import_interface_logic8.useAppDispatch)();
506
+ const signIn = async (email, password) => {
507
+ try {
508
+ loginMutate.mutate(
509
+ {
510
+ email,
511
+ password,
512
+ path: "/authentication/oauth2/token"
513
+ },
514
+ {
515
+ onSuccess: (res) => {
516
+ setAccessToken(res.access_token);
517
+ },
518
+ onError: (err) => {
519
+ }
520
+ }
521
+ );
522
+ } catch (error) {
523
+ throw new Error("Login failed");
524
+ }
525
+ };
526
+ const signOut = async () => {
527
+ dispatch((0, import_interface_logic8.setMenuList)([]));
528
+ dispatch((0, import_interface_logic8.setDataUser)({}));
529
+ dispatch((0, import_interface_logic8.setProfile)({}));
530
+ setAccessToken(null);
531
+ };
532
+ return {
533
+ signIn,
534
+ signOut,
535
+ accessToken,
536
+ isLoading
537
+ };
538
+ };
539
+
540
+ // src/hooks/utils/use-click-outside.ts
541
+ var import_react9 = require("react");
30
542
  var DEFAULT_EVENTS = ["mousedown", "touchstart"];
31
543
  var useClickOutside = ({
32
544
  handler,
@@ -34,8 +546,8 @@ var useClickOutside = ({
34
546
  nodes = [],
35
547
  refs
36
548
  }) => {
37
- const ref = (0, import_react.useRef)(null);
38
- (0, import_react.useEffect)(() => {
549
+ const ref = (0, import_react9.useRef)(null);
550
+ (0, import_react9.useEffect)(() => {
39
551
  const listener = (event) => {
40
552
  const { target } = event;
41
553
  if (refs && refs?.length > 0 && refs?.some((r) => r.current?.contains(target))) {
@@ -56,11 +568,11 @@ var useClickOutside = ({
56
568
  return ref;
57
569
  };
58
570
 
59
- // src/hooks/use-debounce.ts
60
- var import_react2 = require("react");
571
+ // src/hooks/utils/use-debounce.ts
572
+ var import_react10 = require("react");
61
573
  function useDebounce(value, delay) {
62
- const [debouncedValue, setDebouncedValue] = (0, import_react2.useState)(value);
63
- (0, import_react2.useEffect)(() => {
574
+ const [debouncedValue, setDebouncedValue] = (0, import_react10.useState)(value);
575
+ (0, import_react10.useEffect)(() => {
64
576
  const handler = setTimeout(() => {
65
577
  setDebouncedValue(value);
66
578
  }, delay);
@@ -72,6 +584,15 @@ function useDebounce(value, delay) {
72
584
  }
73
585
  // Annotate the CommonJS export names for ESM import in node:
74
586
  0 && (module.exports = {
587
+ useAuth,
588
+ useCallAction,
75
589
  useClickOutside,
76
- useDebounce
590
+ useConfig,
591
+ useDebounce,
592
+ useDetail,
593
+ useListData,
594
+ useMenu,
595
+ useProfile,
596
+ useUser,
597
+ useViewV2
77
598
  });