@fctc/widget-logic 1.1.4 → 1.1.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/dist/index.mjs CHANGED
@@ -4031,8 +4031,623 @@ var require_moment = __commonJS({
4031
4031
  }
4032
4032
  });
4033
4033
 
4034
- // src/hooks/use-click-outside.ts
4035
- import { useEffect, useRef } from "react";
4034
+ // src/hooks/core/use-call-action.ts
4035
+ import { getEnv, useLoadAction, useRunAction } from "@fctc/interface-logic";
4036
+ import { useState } from "react";
4037
+ var useCallAction = () => {
4038
+ const queryLoadAction = useLoadAction();
4039
+ const queryRunAction = useRunAction();
4040
+ const [data, setData] = useState(void 0);
4041
+ const callAction = async ({
4042
+ aid,
4043
+ actionType = "ir.actions.act_window"
4044
+ }) => {
4045
+ const context = getEnv().context;
4046
+ let res = void 0;
4047
+ if (actionType === "ir.actions.act_window") {
4048
+ res = await queryLoadAction.mutateAsync({
4049
+ idAction: aid,
4050
+ context
4051
+ });
4052
+ } else if (actionType === "ir.actions.server") {
4053
+ res = await queryRunAction.mutateAsync({
4054
+ idAction: aid,
4055
+ context
4056
+ });
4057
+ }
4058
+ setData(res);
4059
+ return res;
4060
+ };
4061
+ return [data, callAction];
4062
+ };
4063
+
4064
+ // src/hooks/core/use-config.ts
4065
+ import {
4066
+ getEnv as getEnv2,
4067
+ setEnvFile,
4068
+ useAppDispatch
4069
+ } from "@fctc/interface-logic";
4070
+ import { useEffect, useMemo } from "react";
4071
+ var useConfig = ({ localStorageUtils, sessionStorageUtils }) => {
4072
+ const dispatch = useAppDispatch();
4073
+ const envConfig = useMemo(() => {
4074
+ return {
4075
+ mode: "development",
4076
+ baseUrl: "https://api.vitrust.app/c2/api/v2",
4077
+ config: {
4078
+ grantType: "password",
4079
+ clientId: "C52foVQSMpnNOcAP2CBIIkupOSfxUarF8nlOPfXM",
4080
+ clientSecret: "rColINr4a9QBFQPqQB8YU1XfBjqzwerDMJGBxsFK"
4081
+ }
4082
+ };
4083
+ }, []);
4084
+ const config = useMemo(() => {
4085
+ return {
4086
+ VITE_SIDEBAR_TYPE: "grid/sidebar",
4087
+ VITE_APP_DOMAIN: "https://api.vitrust.app/c2/",
4088
+ VITE_IS_EDU: true,
4089
+ VITE_LOGO_WHITE_LOGIN: "https://static.vitrust.app/vitrust/3a/3a1301f614dea6ee19ebf99b68f57e3fd46011d2.png",
4090
+ VITE_LOGO_BLACK_LOGIN: "https://static.vitrust.app/vitrust/32/3223918780da7a439f916faac9abf0bfe98dfa07.png",
4091
+ VITE_BACKGROUND_SIDEBAR: "linear-gradient(178deg, rgb(1, 106, 13) -0.89%, rgb(4, 179, 66) 99.46%",
4092
+ VITE_BANNER: "https://static.vitrust.app/vitrust/5d/5d20cab0627182b4ed5cba4ee42c58b98b663e5b.svg",
4093
+ VITE_BG_BUTTON: "#008F3C",
4094
+ VITE_BACKGROUND_PAGE: "#F9FAFB"
4095
+ };
4096
+ }, []);
4097
+ useEffect(() => {
4098
+ try {
4099
+ const env = getEnv2();
4100
+ env.setupEnv({
4101
+ baseUrl: envConfig.baseUrl,
4102
+ port: 3e3,
4103
+ config: {
4104
+ grantType: envConfig.config.grantType,
4105
+ clientId: envConfig.config.clientId,
4106
+ clientSecret: envConfig.config.clientSecret
4107
+ },
4108
+ db: "preschool",
4109
+ localStorageUtils: localStorageUtils(),
4110
+ sessionStorageUtils: sessionStorageUtils()
4111
+ });
4112
+ dispatch(setEnvFile(config));
4113
+ } catch (error) {
4114
+ console.error("Error loading env or config:", error);
4115
+ }
4116
+ }, [dispatch, envConfig, config]);
4117
+ return { envConfig, config };
4118
+ };
4119
+
4120
+ // src/hooks/core/use-detail.ts
4121
+ import { setProfile, useAppDispatch as useAppDispatch2, useGetDetail } from "@fctc/interface-logic";
4122
+ import { useQuery } from "@tanstack/react-query";
4123
+ import { useEffect as useEffect2 } from "react";
4124
+ var useDetail = (accessToken, sub) => {
4125
+ const dispatch = useAppDispatch2();
4126
+ const fetchGetDetail = useGetDetail();
4127
+ const userDetailQuery = useQuery({
4128
+ queryKey: ["userDetailQuery", sub && accessToken],
4129
+ queryFn: () => {
4130
+ return fetchGetDetail.mutateAsync({
4131
+ model: "res.users",
4132
+ ids: [sub],
4133
+ specification: { image_256: {} }
4134
+ });
4135
+ },
4136
+ enabled: !!sub && !!accessToken
4137
+ });
4138
+ useEffect2(() => {
4139
+ if (userDetailQuery.data) {
4140
+ const userPicture = userDetailQuery.data;
4141
+ dispatch(
4142
+ setProfile({ ...userPicture, image: userPicture?.[0]?.image_256 })
4143
+ );
4144
+ }
4145
+ }, [userDetailQuery.data, dispatch]);
4146
+ return userDetailQuery;
4147
+ };
4148
+
4149
+ // src/hooks/core/use-list-data.ts
4150
+ import { useMemo as useMemo2, useState as useState3 } from "react";
4151
+ import {
4152
+ evalJSONDomain,
4153
+ formatSortingString,
4154
+ selectList,
4155
+ selectSearch,
4156
+ useAppSelector,
4157
+ useGetListData,
4158
+ useModel
4159
+ } from "@fctc/interface-logic";
4160
+
4161
+ // src/utils/function.ts
4162
+ import { useCallback, useEffect as useEffect3, useReducer, useRef, useState as useState2 } from "react";
4163
+ var countSum = (data, field) => {
4164
+ if (!data || !field) return 0;
4165
+ return data.reduce(
4166
+ (total, item) => total + (item?.[`${field}_count`] || 0),
4167
+ 0
4168
+ );
4169
+ };
4170
+ function mergeButtons(fields) {
4171
+ const buttons = fields?.filter((f) => f.type_co === "button");
4172
+ const others = fields?.filter((f) => f.type_co !== "button");
4173
+ if (buttons?.length) {
4174
+ others.push({
4175
+ type_co: "buttons",
4176
+ buttons
4177
+ });
4178
+ }
4179
+ return others;
4180
+ }
4181
+ function isElementVisible(el) {
4182
+ const style = window.getComputedStyle(el);
4183
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0";
4184
+ }
4185
+ function arraysAreEqual(a, b) {
4186
+ if (a.length !== b.length) return false;
4187
+ const setA = new Set(a);
4188
+ const setB = new Set(b);
4189
+ if (setA.size !== setB.size) return false;
4190
+ for (const val of setA) {
4191
+ if (!setB.has(val)) return false;
4192
+ }
4193
+ return true;
4194
+ }
4195
+ function useGetRowIds(tableRef) {
4196
+ const [rowIds, setRowIds] = useState2([]);
4197
+ const lastRowIdsRef = useRef([]);
4198
+ const updateVisibleRowIds = useCallback(() => {
4199
+ const table = tableRef?.current;
4200
+ if (!table) return;
4201
+ const rows = table.querySelectorAll("tr[data-row-id]");
4202
+ const ids = [];
4203
+ rows.forEach((row) => {
4204
+ const el = row;
4205
+ if (isElementVisible(el)) {
4206
+ const id = el.getAttribute("data-row-id");
4207
+ if (id) ids.push(id);
4208
+ }
4209
+ });
4210
+ const uniqueIds = Array.from(new Set(ids));
4211
+ if (!arraysAreEqual(lastRowIdsRef.current, uniqueIds)) {
4212
+ lastRowIdsRef.current = uniqueIds;
4213
+ setRowIds(uniqueIds);
4214
+ }
4215
+ }, [tableRef]);
4216
+ useEffect3(() => {
4217
+ const table = tableRef?.current;
4218
+ if (!table) return;
4219
+ const observer = new MutationObserver(() => {
4220
+ updateVisibleRowIds();
4221
+ });
4222
+ observer.observe(table, {
4223
+ childList: true,
4224
+ subtree: true,
4225
+ attributes: true,
4226
+ attributeFilter: ["style", "class"]
4227
+ });
4228
+ updateVisibleRowIds();
4229
+ return () => {
4230
+ observer.disconnect();
4231
+ };
4232
+ }, [updateVisibleRowIds, tableRef]);
4233
+ return { rowIds, refresh: updateVisibleRowIds };
4234
+ }
4235
+ var getDateRange = (currentDate, unit) => {
4236
+ const date = new Date(currentDate);
4237
+ let dateStart, dateEnd;
4238
+ function formatDate(d) {
4239
+ 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");
4240
+ }
4241
+ switch (unit) {
4242
+ case "month":
4243
+ dateStart = new Date(
4244
+ date.getFullYear(),
4245
+ date.getMonth() + 1,
4246
+ date.getDate(),
4247
+ 23,
4248
+ 59,
4249
+ 59
4250
+ );
4251
+ dateStart.setHours(dateStart.getHours() - 7);
4252
+ dateEnd = new Date(date.getFullYear(), date.getMonth(), 0, 0, 0, 0);
4253
+ dateEnd.setHours(dateEnd.getHours() - 7);
4254
+ break;
4255
+ case "day":
4256
+ dateStart = new Date(
4257
+ date.getFullYear(),
4258
+ date.getMonth(),
4259
+ date.getDate(),
4260
+ 23,
4261
+ 59,
4262
+ 59
4263
+ );
4264
+ dateStart.setHours(dateStart.getHours() - 7);
4265
+ dateEnd = new Date(
4266
+ date.getFullYear(),
4267
+ date.getMonth(),
4268
+ date.getDate(),
4269
+ 0,
4270
+ 0,
4271
+ 0
4272
+ );
4273
+ dateEnd.setHours(dateEnd.getHours() - 7);
4274
+ break;
4275
+ case "week":
4276
+ const dayOfWeek = date.getDay();
4277
+ const daysToMonday = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
4278
+ const daysToSunday = dayOfWeek === 0 ? 0 : 7 - dayOfWeek;
4279
+ dateStart = new Date(
4280
+ date.getFullYear(),
4281
+ date.getMonth(),
4282
+ date.getDate() + daysToSunday,
4283
+ 23,
4284
+ 59,
4285
+ 59
4286
+ );
4287
+ dateStart.setHours(dateStart.getHours() - 7);
4288
+ dateEnd = new Date(
4289
+ date.getFullYear(),
4290
+ date.getMonth(),
4291
+ date.getDate() + daysToMonday,
4292
+ 0,
4293
+ 0,
4294
+ 0
4295
+ );
4296
+ dateEnd.setHours(dateEnd.getHours() - 7);
4297
+ break;
4298
+ case "year":
4299
+ dateStart = new Date(date.getFullYear(), 11, 31, 23, 59, 59);
4300
+ dateStart.setHours(dateStart.getHours() - 7);
4301
+ dateEnd = new Date(date.getFullYear() - 1, 11, 31, 0, 0, 0);
4302
+ dateEnd.setHours(dateEnd.getHours() - 7);
4303
+ break;
4304
+ default:
4305
+ throw new Error(
4306
+ "\u0110\u01A1n v\u1ECB kh\xF4ng h\u1EE3p l\u1EC7. Ch\u1EC9 ch\u1EA5p nh\u1EADn: week, day, month, year"
4307
+ );
4308
+ }
4309
+ return [
4310
+ ["date_start", "<=", formatDate(dateStart)],
4311
+ ["date_end", ">=", formatDate(dateEnd)]
4312
+ ];
4313
+ };
4314
+ var convertFieldsToArray = (fields) => {
4315
+ const defaultFields = ["display_name", "date_start", "date_end"];
4316
+ if (!fields || !Array.isArray(fields)) {
4317
+ return defaultFields;
4318
+ }
4319
+ const inputFields = fields.filter((field) => field && field.type_co === "field").map((field) => field.name);
4320
+ return [...defaultFields, ...inputFields];
4321
+ };
4322
+ function combineContexts(contexts) {
4323
+ if (contexts.some((context) => !context)) {
4324
+ return void 0;
4325
+ } else {
4326
+ const res = contexts.reduce((acc, context) => {
4327
+ return { ...acc, ...context };
4328
+ }, {});
4329
+ return res;
4330
+ }
4331
+ }
4332
+ var STORAGES = {
4333
+ TOKEN: "accessToken",
4334
+ USER_INFO: "USER_INFO"
4335
+ };
4336
+ function useAsyncState(initialValue = [true, null]) {
4337
+ return useReducer(
4338
+ (_state, action = null) => [false, action],
4339
+ initialValue
4340
+ );
4341
+ }
4342
+ async function setStorageItemAsync(key, value) {
4343
+ try {
4344
+ if (value === null) {
4345
+ localStorage.removeItem(key);
4346
+ } else {
4347
+ localStorage.setItem(key, value);
4348
+ }
4349
+ } catch (e) {
4350
+ console.error("Local storage is unavailable:", e);
4351
+ }
4352
+ }
4353
+ function useStorageState(key) {
4354
+ const [state, setState] = useAsyncState();
4355
+ useEffect3(() => {
4356
+ try {
4357
+ const storedValue = localStorage.getItem(key);
4358
+ setState(storedValue);
4359
+ } catch (e) {
4360
+ console.error("Local storage is unavailable:", e);
4361
+ }
4362
+ }, [key]);
4363
+ const setValue = useCallback(
4364
+ (value) => {
4365
+ setState(value);
4366
+ setStorageItemAsync(key, value);
4367
+ },
4368
+ [key]
4369
+ );
4370
+ return [state, setValue];
4371
+ }
4372
+
4373
+ // src/hooks/core/use-list-data.ts
4374
+ var useListData = ({
4375
+ action,
4376
+ context,
4377
+ viewResponse
4378
+ }) => {
4379
+ const { groupByDomain } = useAppSelector(selectSearch);
4380
+ const initModel = useModel();
4381
+ const [type, setType] = useState3("list");
4382
+ const [mode, setMode] = useState3("month");
4383
+ const [currentDate, setCurrentDate] = useState3(/* @__PURE__ */ new Date());
4384
+ const { pageLimit, page, order } = useAppSelector(selectList);
4385
+ const listDataProps = useMemo2(() => {
4386
+ const actData = action?.result;
4387
+ if (!viewResponse || !actData || !context) {
4388
+ return null;
4389
+ }
4390
+ const specification = initModel.initModel({
4391
+ name: String(actData.res_model),
4392
+ view: viewResponse || {},
4393
+ actContext: context,
4394
+ fields: type === "kanban" ? viewResponse?.views?.kanban?.fields : type === "calendar" ? viewResponse?.views?.calendar?.fields : viewResponse?.views?.list?.fields
4395
+ }).getSpecification();
4396
+ const domain = type === "calendar" ? getDateRange(currentDate, mode) : actData?.domain ? Array.isArray(actData?.domain) ? [...actData?.domain] : evalJSONDomain(actData?.domain, context) : [];
4397
+ const limit = type === "calendar" ? 2500 : pageLimit;
4398
+ const offset = page * pageLimit;
4399
+ const fields = type === "calendar" ? convertFieldsToArray(viewResponse?.views?.calendar?.fields) || [] : typeof groupByDomain === "object" ? groupByDomain?.fields : void 0;
4400
+ const groupby = typeof groupByDomain === "object" ? [groupByDomain?.contexts?.[0]?.group_by] : [];
4401
+ const sort = order ? order : viewResponse?.views?.list?.default_order ? formatSortingString(viewResponse?.views?.list?.default_order) : "";
4402
+ return {
4403
+ model: actData.res_model,
4404
+ specification,
4405
+ domain,
4406
+ limit,
4407
+ offset,
4408
+ fields,
4409
+ groupby,
4410
+ context,
4411
+ sort,
4412
+ type
4413
+ };
4414
+ }, [
4415
+ action?.result,
4416
+ context,
4417
+ currentDate,
4418
+ groupByDomain,
4419
+ initModel,
4420
+ mode,
4421
+ order,
4422
+ page,
4423
+ pageLimit,
4424
+ type,
4425
+ viewResponse
4426
+ ]);
4427
+ const list = useGetListData(
4428
+ listDataProps,
4429
+ [listDataProps],
4430
+ !!listDataProps
4431
+ );
4432
+ return {
4433
+ ...list,
4434
+ state: {
4435
+ type,
4436
+ setType,
4437
+ mode,
4438
+ setMode,
4439
+ currentDate,
4440
+ setCurrentDate
4441
+ }
4442
+ };
4443
+ };
4444
+
4445
+ // src/hooks/core/use-menu.ts
4446
+ import { useEffect as useEffect4, useMemo as useMemo3, useState as useState4 } from "react";
4447
+ import { useGetMenu } from "@fctc/interface-logic";
4448
+
4449
+ // src/utils/constants.ts
4450
+ var languages = [
4451
+ { id: "vi_VN", name: "VIE" },
4452
+ { id: "en_US", name: "ENG" }
4453
+ ];
4454
+ var API_PRESCHOOL_URL = {
4455
+ baseURL: "https://preschool.vitrust.app"
4456
+ };
4457
+ var API_APP_URL = {
4458
+ baseUrl: "https://api.vitrust.app",
4459
+ c2: "https://api.vitrust.app/c2",
4460
+ apiV2: "https://api.vitrust.app/c2/api/v2"
4461
+ };
4462
+
4463
+ // src/hooks/core/use-menu.ts
4464
+ var useMenu = ({ context }) => {
4465
+ const menuData = useGetMenu(context, !!context);
4466
+ const [menuid, setMenuId] = useState4(void 0);
4467
+ const [action, setAction] = useCallAction();
4468
+ const configedIconData = useMemo3(() => {
4469
+ const data = menuData.data;
4470
+ return data?.map((item) => {
4471
+ return {
4472
+ ...item,
4473
+ child_id: item?.child_id?.map((child) => {
4474
+ return {
4475
+ ...child,
4476
+ url_icon: API_APP_URL.c2 + "/" + child.url_icon
4477
+ };
4478
+ }) ?? [],
4479
+ url_icon: API_APP_URL.c2 + "/" + item.url_icon
4480
+ };
4481
+ });
4482
+ }, [menuData.data]);
4483
+ const handleChangeMenu = async ({
4484
+ menu,
4485
+ subMenu
4486
+ }) => {
4487
+ const aid = subMenu?.action?.id?.id;
4488
+ const actionType = subMenu?.action?.type;
4489
+ await setAction({
4490
+ aid: Number(aid),
4491
+ actionType
4492
+ });
4493
+ if (menu) {
4494
+ setMenuId(menu.id?.toString() ?? "");
4495
+ }
4496
+ };
4497
+ useEffect4(() => {
4498
+ const firstRecord = configedIconData?.[0];
4499
+ const firstChild = firstRecord?.child_id?.[0];
4500
+ if (firstChild && firstRecord) {
4501
+ handleChangeMenu({ menu: firstRecord, subMenu: firstChild });
4502
+ }
4503
+ }, [configedIconData]);
4504
+ return {
4505
+ ...menuData,
4506
+ data: configedIconData,
4507
+ action: { handleChangeMenu },
4508
+ state: { menuid, action },
4509
+ context
4510
+ };
4511
+ };
4512
+
4513
+ // src/hooks/core/use-profile.ts
4514
+ import { useQuery as useQuery2 } from "@tanstack/react-query";
4515
+ import { useEffect as useEffect5, useMemo as useMemo4 } from "react";
4516
+ import { useTranslation } from "react-i18next";
4517
+ import {
4518
+ getEnv as getEnv3,
4519
+ setDataUser,
4520
+ useAppDispatch as useAppDispatch3,
4521
+ useGetProfile
4522
+ } from "@fctc/interface-logic";
4523
+ var useProfile = (accessToken) => {
4524
+ const getProfile = useGetProfile();
4525
+ const dispatch = useAppDispatch3();
4526
+ const { i18n: i18n2 } = useTranslation();
4527
+ const fetchUserProfile = async () => {
4528
+ return await getProfile.mutateAsync();
4529
+ };
4530
+ const userInfoQuery = useQuery2({
4531
+ queryKey: ["userInfo", accessToken],
4532
+ queryFn: fetchUserProfile,
4533
+ enabled: !!accessToken
4534
+ });
4535
+ useEffect5(() => {
4536
+ if (userInfoQuery.data) {
4537
+ const userInfo = userInfoQuery.data;
4538
+ const env = getEnv3();
4539
+ env.setUid(userInfo?.sub);
4540
+ dispatch(setDataUser(userInfo));
4541
+ const userLocale = languages.find((lang) => lang?.id === userInfo?.locale);
4542
+ env.setLang(userLocale?.id);
4543
+ i18n2.changeLanguage(userLocale?.id.split("_")[0]);
4544
+ }
4545
+ }, [dispatch, userInfoQuery.data]);
4546
+ const context = useMemo4(() => {
4547
+ if (userInfoQuery.data?.sub && userInfoQuery.data?.locale) {
4548
+ return {
4549
+ uid: Number(userInfoQuery.data.sub),
4550
+ allowed_company_ids: [],
4551
+ lang: String(userInfoQuery.data.locale),
4552
+ tz: "Asia/Saigon"
4553
+ };
4554
+ }
4555
+ return void 0;
4556
+ }, [userInfoQuery.data]);
4557
+ return { ...userInfoQuery, context };
4558
+ };
4559
+
4560
+ // src/hooks/core/use-user.ts
4561
+ var useUser = (accessToken) => {
4562
+ const userProfile = useProfile(accessToken);
4563
+ const userDetail = useDetail(accessToken, userProfile.data?.sub);
4564
+ return { userProfile, userDetail, context: userProfile.context };
4565
+ };
4566
+
4567
+ // src/hooks/core/use-view-v2.ts
4568
+ import { useMemo as useMemo5 } from "react";
4569
+ import { useGetView } from "@fctc/interface-logic";
4570
+ var useViewV2 = ({
4571
+ action,
4572
+ context
4573
+ }) => {
4574
+ const viewParams = useMemo5(() => {
4575
+ if (!action?.result) {
4576
+ return void 0;
4577
+ }
4578
+ const actionResult = action?.result;
4579
+ return {
4580
+ model: String(actionResult?.res_model),
4581
+ views: [
4582
+ ...Array.isArray(actionResult?.views) ? actionResult?.views.map(
4583
+ (view2) => view2[1] === "list" ? [view2[0], "list"] : view2
4584
+ ) : [],
4585
+ [
4586
+ Array.isArray(actionResult?.search_view_id) ? actionResult?.search_view_id[0] : actionResult?.search_view_id,
4587
+ "search"
4588
+ ]
4589
+ ],
4590
+ context
4591
+ };
4592
+ }, [action, context]);
4593
+ const view = useGetView(
4594
+ viewParams || {},
4595
+ !!viewParams
4596
+ );
4597
+ return {
4598
+ ...view,
4599
+ context
4600
+ };
4601
+ };
4602
+
4603
+ // src/hooks/core/use-auth.ts
4604
+ import {
4605
+ setDataUser as setDataUser2,
4606
+ setMenuList,
4607
+ setProfile as setProfile2,
4608
+ useAppDispatch as useAppDispatch4,
4609
+ useLoginCredential
4610
+ } from "@fctc/interface-logic";
4611
+ var useAuth = () => {
4612
+ const [[isLoading, accessToken], setAccessToken] = useStorageState("TOKEN");
4613
+ const loginMutate = useLoginCredential();
4614
+ const dispatch = useAppDispatch4();
4615
+ const signIn = async (email, password) => {
4616
+ try {
4617
+ loginMutate.mutate(
4618
+ {
4619
+ email,
4620
+ password,
4621
+ path: "/authentication/oauth2/token"
4622
+ },
4623
+ {
4624
+ onSuccess: (res) => {
4625
+ setAccessToken(res.access_token);
4626
+ },
4627
+ onError: (err) => {
4628
+ }
4629
+ }
4630
+ );
4631
+ } catch (error) {
4632
+ throw new Error("Login failed");
4633
+ }
4634
+ };
4635
+ const signOut = async () => {
4636
+ dispatch(setMenuList([]));
4637
+ dispatch(setDataUser2({}));
4638
+ dispatch(setProfile2({}));
4639
+ setAccessToken(null);
4640
+ };
4641
+ return {
4642
+ signIn,
4643
+ signOut,
4644
+ accessToken,
4645
+ isLoading
4646
+ };
4647
+ };
4648
+
4649
+ // src/hooks/utils/use-click-outside.ts
4650
+ import { useEffect as useEffect6, useRef as useRef2 } from "react";
4036
4651
  var DEFAULT_EVENTS = ["mousedown", "touchstart"];
4037
4652
  var useClickOutside = ({
4038
4653
  handler,
@@ -4040,8 +4655,8 @@ var useClickOutside = ({
4040
4655
  nodes = [],
4041
4656
  refs
4042
4657
  }) => {
4043
- const ref = useRef(null);
4044
- useEffect(() => {
4658
+ const ref = useRef2(null);
4659
+ useEffect6(() => {
4045
4660
  const listener = (event) => {
4046
4661
  const { target } = event;
4047
4662
  if (refs && refs?.length > 0 && refs?.some((r) => r.current?.contains(target))) {
@@ -4062,11 +4677,11 @@ var useClickOutside = ({
4062
4677
  return ref;
4063
4678
  };
4064
4679
 
4065
- // src/hooks/use-debounce.ts
4066
- import { useEffect as useEffect2, useState } from "react";
4680
+ // src/hooks/utils/use-debounce.ts
4681
+ import { useEffect as useEffect7, useState as useState5 } from "react";
4067
4682
  function useDebounce(value, delay) {
4068
- const [debouncedValue, setDebouncedValue] = useState(value);
4069
- useEffect2(() => {
4683
+ const [debouncedValue, setDebouncedValue] = useState5(value);
4684
+ useEffect7(() => {
4070
4685
  const handler = setTimeout(() => {
4071
4686
  setDebouncedValue(value);
4072
4687
  }, delay);
@@ -4184,19 +4799,19 @@ var CloseIcon = ({ className = "" }) => {
4184
4799
  };
4185
4800
 
4186
4801
  // src/widget/basic/status-dropdown-field/controller.ts
4187
- import { useEffect as useEffect3, useRef as useRef2, useState as useState2 } from "react";
4188
- import { getEnv, useSave } from "@fctc/interface-logic";
4802
+ import { useEffect as useEffect8, useRef as useRef3, useState as useState6 } from "react";
4803
+ import { getEnv as getEnv4, useSave } from "@fctc/interface-logic";
4189
4804
  var statusDropdownController = (props) => {
4190
4805
  const { selection, isForm, id, model, name, state, onRefetch } = props;
4191
- const env = getEnv();
4806
+ const env = getEnv4();
4192
4807
  const colors = {
4193
4808
  normal: "bg-[#e9ecef]",
4194
4809
  done: "bg-primary",
4195
4810
  blocked: "bg-red-500"
4196
4811
  };
4197
- const [isOpen, setIsOpen] = useState2(false);
4198
- const buttonRef = useRef2(null);
4199
- useEffect3(() => {
4812
+ const [isOpen, setIsOpen] = useState6(false);
4813
+ const buttonRef = useRef3(null);
4814
+ useEffect8(() => {
4200
4815
  const handleClickOutside = (event) => {
4201
4816
  if (buttonRef.current && !buttonRef.current.contains(event.target)) {
4202
4817
  setIsOpen(false);
@@ -4237,14 +4852,14 @@ var statusDropdownController = (props) => {
4237
4852
  };
4238
4853
 
4239
4854
  // src/widget/basic/many2one-field/controller.ts
4240
- import { useCallback, useEffect as useEffect4, useMemo, useState as useState3 } from "react";
4855
+ import { useCallback as useCallback2, useEffect as useEffect9, useMemo as useMemo6, useState as useState7 } from "react";
4241
4856
  import {
4242
4857
  evalJSONContext,
4243
- evalJSONDomain,
4858
+ evalJSONDomain as evalJSONDomain2,
4244
4859
  selectEnv,
4245
4860
  selectNavbar,
4246
4861
  setListSubject,
4247
- useAppSelector,
4862
+ useAppSelector as useAppSelector2,
4248
4863
  useGetSelection
4249
4864
  } from "@fctc/interface-logic";
4250
4865
  var many2oneFieldController = (props) => {
@@ -4261,15 +4876,15 @@ var many2oneFieldController = (props) => {
4261
4876
  showDetail = true,
4262
4877
  actionData
4263
4878
  } = props;
4264
- const [options, setOptions] = useState3([]);
4265
- const [isShowModalMany2Many, setIsShowModalMany2Many] = useState3(false);
4266
- const [tempSelectedOption, setTempSelectedOption] = useState3(null);
4267
- const { menuList } = useAppSelector(selectNavbar);
4268
- const { context } = useAppSelector(selectEnv);
4269
- const [domainModal, setDomainModal] = useState3(null);
4879
+ const [options, setOptions] = useState7([]);
4880
+ const [isShowModalMany2Many, setIsShowModalMany2Many] = useState7(false);
4881
+ const [tempSelectedOption, setTempSelectedOption] = useState7(null);
4882
+ const { menuList } = useAppSelector2(selectNavbar);
4883
+ const { context } = useAppSelector2(selectEnv);
4884
+ const [domainModal, setDomainModal] = useState7(null);
4270
4885
  const initValue = methods?.getValues(name);
4271
- const domainObject = useMemo(
4272
- () => evalJSONDomain(domain, JSON.parse(JSON.stringify(formValues)) ?? {}),
4886
+ const domainObject = useMemo6(
4887
+ () => evalJSONDomain2(domain, JSON.parse(JSON.stringify(formValues)) ?? {}),
4273
4888
  [domain, formValues]
4274
4889
  );
4275
4890
  const optionsObject = evalJSONContext(fieldOptions) || {};
@@ -4278,7 +4893,7 @@ var many2oneFieldController = (props) => {
4278
4893
  ...fieldContext,
4279
4894
  ...context
4280
4895
  };
4281
- const actionId = useMemo(
4896
+ const actionId = useMemo6(
4282
4897
  () => menuList?.flatMap(
4283
4898
  (item) => item?.child_id.filter(
4284
4899
  (childItem) => childItem?.is_display && childItem?.action?.res_model === relation
@@ -4306,18 +4921,18 @@ var many2oneFieldController = (props) => {
4306
4921
  queryKey,
4307
4922
  enabled: false
4308
4923
  });
4309
- const selectOptions = useMemo(() => {
4924
+ const selectOptions = useMemo6(() => {
4310
4925
  return dataOfSelection?.records?.map((val) => ({
4311
4926
  value: val?.id,
4312
4927
  label: val?.display_name || val?.name
4313
4928
  })) || [];
4314
4929
  }, [dataOfSelection]);
4315
- useEffect4(() => {
4930
+ useEffect9(() => {
4316
4931
  setOptions(selectOptions);
4317
4932
  setDomainModal(domainObject);
4318
4933
  if (relation === "student.subject") setListSubject(selectOptions);
4319
4934
  }, [selectOptions]);
4320
- useEffect4(() => {
4935
+ useEffect9(() => {
4321
4936
  if (!propValue && tempSelectedOption) {
4322
4937
  methods.setValue(name, null);
4323
4938
  setTempSelectedOption(null);
@@ -4328,15 +4943,15 @@ var many2oneFieldController = (props) => {
4328
4943
  });
4329
4944
  }
4330
4945
  }, [propValue]);
4331
- const fetchMoreOptions = useCallback(() => {
4946
+ const fetchMoreOptions = useCallback2(() => {
4332
4947
  refetch();
4333
4948
  }, [refetch]);
4334
- useEffect4(() => {
4949
+ useEffect9(() => {
4335
4950
  if (actionId) {
4336
4951
  localStorage.setItem("aid", actionId);
4337
4952
  }
4338
4953
  }, [actionId]);
4339
- const handleChooseRecord = useCallback(
4954
+ const handleChooseRecord = useCallback2(
4340
4955
  (idRecord) => {
4341
4956
  const newOption = options.find(
4342
4957
  (option) => option.value === idRecord
@@ -4361,8 +4976,8 @@ var many2oneFieldController = (props) => {
4361
4976
  },
4362
4977
  [options, methods, name, onChange]
4363
4978
  );
4364
- const handleClose = useCallback(() => setIsShowModalMany2Many(false), []);
4365
- const handleSelectChange = useCallback(
4979
+ const handleClose = useCallback2(() => setIsShowModalMany2Many(false), []);
4980
+ const handleSelectChange = useCallback2(
4366
4981
  (selectedOption) => {
4367
4982
  if (!selectedOption) {
4368
4983
  methods.setValue(name, null, { shouldDirty: true });
@@ -4414,18 +5029,15 @@ var many2oneFieldController = (props) => {
4414
5029
  // src/widget/basic/many2one-button-field/controller.ts
4415
5030
  import {
4416
5031
  evalJSONContext as evalJSONContext2,
4417
- evalJSONDomain as evalJSONDomain2,
4418
- getEnv as getEnv2,
5032
+ evalJSONDomain as evalJSONDomain3,
5033
+ getEnv as getEnv5,
4419
5034
  useGetSelection as useGetSelection2
4420
5035
  } from "@fctc/interface-logic";
4421
- var many2oneButtonController = ({
4422
- relation,
4423
- methods,
4424
- domain
4425
- }) => {
5036
+ var many2oneButtonController = (props) => {
5037
+ const { domain, methods, relation } = props;
4426
5038
  const actionDataString = sessionStorage.getItem("actionData");
4427
- const env = getEnv2();
4428
- const domainObject = evalJSONDomain2(domain, methods?.getValues() || {});
5039
+ const env = getEnv5();
5040
+ const domainObject = evalJSONDomain3(domain, methods?.getValues() || {});
4429
5041
  const actionData = actionDataString && actionDataString !== "undefined" ? JSON.parse(actionDataString) : {};
4430
5042
  const { data: dataOfSelection } = useGetSelection2({
4431
5043
  data: {
@@ -4445,41 +5057,35 @@ var many2oneButtonController = ({
4445
5057
  };
4446
5058
 
4447
5059
  // src/widget/basic/many2many-field/controller.ts
4448
- import { useEffect as useEffect6, useMemo as useMemo2, useState as useState5 } from "react";
5060
+ import { useEffect as useEffect11, useMemo as useMemo8, useState as useState9 } from "react";
4449
5061
  import {
4450
5062
  evalJSONContext as evalJSONContext3,
4451
- formatSortingString,
4452
- getEnv as getEnv3,
4453
- selectSearch,
5063
+ formatSortingString as formatSortingString2,
5064
+ getEnv as getEnv6,
5065
+ selectSearch as selectSearch3,
4454
5066
  setFirstDomain,
4455
5067
  setGroupByDomain,
4456
5068
  setPage,
4457
5069
  setViewDataStore,
4458
- useAppDispatch,
4459
- useAppSelector as useAppSelector2,
5070
+ useAppDispatch as useAppDispatch5,
5071
+ useAppSelector as useAppSelector4,
4460
5072
  useGetFormView,
4461
- useGetListData,
4462
- useGetView,
4463
- useModel
5073
+ useGetListData as useGetListData2,
5074
+ useGetView as useGetView2,
5075
+ useModel as useModel2
4464
5076
  } from "@fctc/interface-logic";
4465
5077
 
4466
- // src/widget/table/use-table.ts
4467
- import { domainHelper } from "@fctc/interface-logic";
4468
- import { useEffect as useEffect5, useState as useState4 } from "react";
4469
- function mergeButtons(fields) {
4470
- const buttons = fields?.filter((f) => f.type_co === "button");
4471
- const others = fields?.filter((f) => f.type_co !== "button");
4472
- if (buttons?.length) {
4473
- others.push({
4474
- type_co: "buttons",
4475
- buttons
4476
- });
4477
- }
4478
- return others;
4479
- }
4480
- var useTableHandler = ({ data }) => {
4481
- const [rows, setRows] = useState4(data.records || []);
4482
- const [columns, setColumns] = useState4([]);
5078
+ // src/widget/advance/table/table-view/controller.ts
5079
+ import {
5080
+ domainHelper,
5081
+ selectList as selectList2,
5082
+ selectSearch as selectSearch2,
5083
+ useAppSelector as useAppSelector3
5084
+ } from "@fctc/interface-logic";
5085
+ import { useEffect as useEffect10, useMemo as useMemo7, useRef as useRef4, useState as useState8 } from "react";
5086
+ var tableController = ({ data }) => {
5087
+ const [rows, setRows] = useState8(data.records || []);
5088
+ const [columns, setColumns] = useState8([]);
4483
5089
  const dataModelFields = data.fields?.map((field) => {
4484
5090
  return {
4485
5091
  ...data.dataModel?.[field?.name],
@@ -4507,7 +5113,7 @@ var useTableHandler = ({ data }) => {
4507
5113
  return item.display_name ? { ...transformedItem, item: item.display_name } : transformedItem;
4508
5114
  });
4509
5115
  };
4510
- useEffect5(() => {
5116
+ useEffect10(() => {
4511
5117
  setRows(transformData(data.records || null));
4512
5118
  }, [data.records]);
4513
5119
  const handleGetColumns = () => {
@@ -4528,7 +5134,7 @@ var useTableHandler = ({ data }) => {
4528
5134
  }
4529
5135
  return cols;
4530
5136
  };
4531
- useEffect5(() => {
5137
+ useEffect10(() => {
4532
5138
  const columns2 = handleGetColumns();
4533
5139
  setColumns(columns2);
4534
5140
  }, [data.records]);
@@ -4569,17 +5175,14 @@ var many2manyFieldController = (props) => {
4569
5175
  options,
4570
5176
  sessionStorageUtils
4571
5177
  } = props;
4572
- const appDispatch = useAppDispatch();
5178
+ const appDispatch = useAppDispatch5();
4573
5179
  const actionData = sessionStorageUtils.getActionData();
4574
5180
  const [debouncedPage] = useDebounce(page, 500);
4575
- const [order, setOrder] = useState5();
4576
- const [isLoadedData, setIsLoadedData] = useState5(false);
4577
- const [domainMany2Many, setDomainMany2Many] = useState5(domain);
4578
- const env = getEnv3();
4579
- const {
4580
- // tableHead,
4581
- selectedTags
4582
- } = useAppSelector2(selectSearch);
5181
+ const [order, setOrder] = useState9();
5182
+ const [isLoadedData, setIsLoadedData] = useState9(false);
5183
+ const [domainMany2Many, setDomainMany2Many] = useState9(domain);
5184
+ const env = getEnv6();
5185
+ const { selectedTags } = useAppSelector4(selectSearch3);
4583
5186
  const viewParams = {
4584
5187
  model: relation,
4585
5188
  views: [
@@ -4588,11 +5191,11 @@ var many2manyFieldController = (props) => {
4588
5191
  ],
4589
5192
  context
4590
5193
  };
4591
- const { data: viewResponse, isFetched: isViewReponseFetched } = useGetView(
5194
+ const { data: viewResponse, isFetched: isViewReponseFetched } = useGetView2(
4592
5195
  viewParams,
4593
5196
  actionData
4594
5197
  );
4595
- const baseModel = useMemo2(
5198
+ const baseModel = useMemo8(
4596
5199
  () => ({
4597
5200
  name: String(relation),
4598
5201
  view: viewResponse || {},
@@ -4604,14 +5207,14 @@ var many2manyFieldController = (props) => {
4604
5207
  }),
4605
5208
  [model, viewResponse]
4606
5209
  );
4607
- const initModel = useModel();
4608
- const modelInstance = useMemo2(() => {
5210
+ const initModel = useModel2();
5211
+ const modelInstance = useMemo8(() => {
4609
5212
  if (viewResponse) {
4610
5213
  return initModel.initModel(baseModel);
4611
5214
  }
4612
5215
  return null;
4613
5216
  }, [baseModel, viewResponse]);
4614
- const specification = useMemo2(() => {
5217
+ const specification = useMemo8(() => {
4615
5218
  if (modelInstance) {
4616
5219
  return modelInstance.getSpecification();
4617
5220
  }
@@ -4656,7 +5259,7 @@ var many2manyFieldController = (props) => {
4656
5259
  context,
4657
5260
  fields: groupByDomain?.fields,
4658
5261
  groupby: [groupByDomain?.contexts[0]?.group_by],
4659
- sort: order ? order : default_order ? formatSortingString(default_order) : ""
5262
+ sort: order ? order : default_order ? formatSortingString2(default_order) : ""
4660
5263
  };
4661
5264
  const enabled = isLoadedData && !!specification && !!relation && !!domainMany2Many && !!viewResponse;
4662
5265
  const {
@@ -4664,8 +5267,8 @@ var many2manyFieldController = (props) => {
4664
5267
  isLoading: isDataLoading,
4665
5268
  isFetched: isDataResponseFetched,
4666
5269
  isPlaceholderData
4667
- } = useGetListData(data, queryKey, enabled);
4668
- useEffect6(() => {
5270
+ } = useGetListData2(data, queryKey, enabled);
5271
+ useEffect11(() => {
4669
5272
  if (viewResponse) {
4670
5273
  fetchData();
4671
5274
  }
@@ -4681,7 +5284,7 @@ var many2manyFieldController = (props) => {
4681
5284
  setIsLoadedData(false);
4682
5285
  };
4683
5286
  }, [viewResponse]);
4684
- const { rows, columns, typeTable } = useTableHandler({
5287
+ const { rows, columns, typeTable } = tableController({
4685
5288
  data: {
4686
5289
  fields: fields?.[`${aid}_${relation}_popupmany2many`] || viewResponse?.views?.list?.fields,
4687
5290
  records: dataResponse?.records ?? dataResponse?.groups,
@@ -4704,13 +5307,13 @@ var many2manyFieldController = (props) => {
4704
5307
  queryKey: [`form-view-action-${relation}`],
4705
5308
  enabled: false
4706
5309
  });
4707
- useEffect6(() => {
5310
+ useEffect11(() => {
4708
5311
  if (isSuccess && dataFormViewResponse) {
4709
5312
  sessionStorage.setItem("actionData", JSON.stringify(dataFormViewResponse));
4710
5313
  window.location.href = `/form/menu?model=${relation}`;
4711
5314
  }
4712
5315
  }, [isSuccess]);
4713
- useEffect6(() => {
5316
+ useEffect11(() => {
4714
5317
  if (domainMany2Many && !isLoadedData) {
4715
5318
  setIsLoadedData(true);
4716
5319
  }
@@ -4722,45 +5325,15 @@ var many2manyFieldController = (props) => {
4722
5325
  console.log(error);
4723
5326
  }
4724
5327
  };
4725
- return {
4726
- rows,
4727
- columns,
4728
- typeTable,
4729
- handleCreateNewOnPage,
4730
- isLoadedData,
4731
- domainMany2Many,
4732
- isDataLoading,
4733
- isDataResponseFetched,
4734
- isPlaceholderData,
4735
- queryKey,
4736
- data,
4737
- specification,
4738
- enabled,
4739
- isViewReponseFetched,
4740
- actionData,
4741
- viewResponse,
4742
- debouncedPage,
4743
- order,
4744
- default_order,
4745
- optionsObject,
4746
- setDomainMany2Many,
4747
- // tableHead,
4748
- selectedTags,
4749
- initModel,
4750
- modelInstance,
4751
- baseModel,
4752
- dataResponse,
4753
- isLoading: isDataLoading,
4754
- setOrder
4755
- };
5328
+ return {};
4756
5329
  };
4757
5330
 
4758
5331
  // src/widget/basic/many2many-tags-field/controller.ts
4759
- import { useMemo as useMemo3 } from "react";
5332
+ import { useMemo as useMemo9 } from "react";
4760
5333
  import {
4761
5334
  evalJSONContext as evalJSONContext4,
4762
- evalJSONDomain as evalJSONDomain3,
4763
- getEnv as getEnv4,
5335
+ evalJSONDomain as evalJSONDomain4,
5336
+ getEnv as getEnv7,
4764
5337
  useGetSelection as useGetSelection3,
4765
5338
  WIDGETAVATAR,
4766
5339
  WIDGETCOLOR
@@ -4775,10 +5348,10 @@ var many2manyTagsController = (props) => {
4775
5348
  placeholderNoOption
4776
5349
  } = props;
4777
5350
  const isUser = relation === "res.users" || relation === "res.partner";
4778
- const env = getEnv4();
5351
+ const env = getEnv7();
4779
5352
  const addtionalFields = optionsFields ? evalJSONContext4(optionsFields) : null;
4780
- const domainObject = useMemo3(
4781
- () => evalJSONDomain3(domain, JSON.parse(JSON.stringify(formValues || {}))),
5353
+ const domainObject = useMemo9(
5354
+ () => evalJSONDomain4(domain, JSON.parse(JSON.stringify(formValues || {}))),
4782
5355
  [domain, formValues]
4783
5356
  );
4784
5357
  const data = {
@@ -4820,13 +5393,13 @@ var many2manyTagsController = (props) => {
4820
5393
  };
4821
5394
 
4822
5395
  // src/widget/basic/status-bar-field/controller.ts
4823
- import { useState as useState6 } from "react";
5396
+ import { useState as useState10 } from "react";
4824
5397
  import {
4825
- evalJSONDomain as evalJSONDomain4,
5398
+ evalJSONDomain as evalJSONDomain5,
4826
5399
  selectEnv as selectEnv2,
4827
- useAppSelector as useAppSelector3,
5400
+ useAppSelector as useAppSelector5,
4828
5401
  useChangeStatus,
4829
- useGetListData as useGetListData2
5402
+ useGetListData as useGetListData3
4830
5403
  } from "@fctc/interface-logic";
4831
5404
  var durationController = (props) => {
4832
5405
  const {
@@ -4844,14 +5417,14 @@ var durationController = (props) => {
4844
5417
  name: "",
4845
5418
  fold: ""
4846
5419
  };
4847
- const [disabled, setDisabled] = useState6(false);
4848
- const [modelStatus, setModalStatus] = useState6(false);
4849
- const { context } = useAppSelector3(selectEnv2);
5420
+ const [disabled, setDisabled] = useState10(false);
5421
+ const [modelStatus, setModalStatus] = useState10(false);
5422
+ const { context } = useAppSelector5(selectEnv2);
4850
5423
  const queryKey = [`data-status-duration`, specification];
4851
5424
  const listDataProps = {
4852
5425
  model: relation,
4853
5426
  specification,
4854
- domain: evalJSONDomain4(domain, JSON.parse(JSON.stringify(formValues))),
5427
+ domain: evalJSONDomain5(domain, JSON.parse(JSON.stringify(formValues))),
4855
5428
  limit: 10,
4856
5429
  offset: 0,
4857
5430
  fields: "",
@@ -4861,7 +5434,7 @@ var durationController = (props) => {
4861
5434
  },
4862
5435
  sort: ""
4863
5436
  };
4864
- const { data: dataResponse } = useGetListData2(listDataProps, queryKey);
5437
+ const { data: dataResponse } = useGetListData3(listDataProps, queryKey);
4865
5438
  const { mutate: fetchChangeStatus } = useChangeStatus();
4866
5439
  const handleClick = async (stage_id) => {
4867
5440
  setDisabled(true);
@@ -4902,13 +5475,13 @@ import { evalJSONContext as evalJSONContext5, useSave as useSave2 } from "@fctc/
4902
5475
  var priorityFieldController = (props) => {
4903
5476
  const {
4904
5477
  value,
4905
- selection,
4906
5478
  isForm,
4907
5479
  name,
4908
5480
  methods,
4909
- id,
4910
5481
  onChange,
4911
5482
  model,
5483
+ selection,
5484
+ id,
4912
5485
  actionData,
4913
5486
  viewData,
4914
5487
  context
@@ -4952,7 +5525,7 @@ var priorityFieldController = (props) => {
4952
5525
  };
4953
5526
 
4954
5527
  // src/widget/basic/float-time-field/controller.ts
4955
- import { useState as useState7 } from "react";
5528
+ import { useState as useState11 } from "react";
4956
5529
  import { convertFloatToTime, convertTimeToFloat } from "@fctc/interface-logic";
4957
5530
  var floatTimeFiledController = ({
4958
5531
  onChange: fieldOnChange,
@@ -4962,11 +5535,11 @@ var floatTimeFiledController = ({
4962
5535
  props
4963
5536
  }) => {
4964
5537
  const { name, defaultValue = 0, onChange } = props;
4965
- const [input, setInput] = useState7(
5538
+ const [input, setInput] = useState11(
4966
5539
  convertFloatToTime(value ?? defaultValue)
4967
5540
  );
4968
- const [formattedTime, setFormattedTime] = useState7("");
4969
- const [errors, setErrors] = useState7("");
5541
+ const [formattedTime, setFormattedTime] = useState11("");
5542
+ const [errors, setErrors] = useState11("");
4970
5543
  const handleInputChange = (e) => {
4971
5544
  const raw = e.target.value.replace(/[^\d:]/g, "");
4972
5545
  setInput(raw);
@@ -5039,7 +5612,31 @@ var floatTimeFiledController = ({
5039
5612
  };
5040
5613
 
5041
5614
  // src/widget/basic/float-field/controller.ts
5042
- import { useEffect as useEffect7, useRef as useRef3, useState as useState8 } from "react";
5615
+ import { useEffect as useEffect12, useRef as useRef5, useState as useState12 } from "react";
5616
+
5617
+ // src/utils/i18n.ts
5618
+ import { initReactI18next } from "react-i18next";
5619
+ import i18n from "i18next";
5620
+ import LanguageDetector from "i18next-browser-languagedetector";
5621
+ i18n.use(LanguageDetector).use(initReactI18next).init({
5622
+ resources: {
5623
+ vi: { translation: vi },
5624
+ en: { translation: en }
5625
+ },
5626
+ fallbackLng: "vi",
5627
+ lng: "vi_VN",
5628
+ debug: false,
5629
+ nonExplicitSupportedLngs: true,
5630
+ interpolation: {
5631
+ escapeValue: false
5632
+ },
5633
+ detection: {
5634
+ caches: ["cookie"]
5635
+ }
5636
+ });
5637
+ var i18n_default = i18n;
5638
+
5639
+ // src/widget/basic/float-field/controller.ts
5043
5640
  var floatController = ({
5044
5641
  onChange,
5045
5642
  value,
@@ -5047,10 +5644,10 @@ var floatController = ({
5047
5644
  }) => {
5048
5645
  const { name, required, methods, onChange: handleOnchange, string } = props;
5049
5646
  const { setError, clearErrors } = methods;
5050
- const [inputValue, setInputValue] = useState8(
5647
+ const [inputValue, setInputValue] = useState12(
5051
5648
  value !== void 0 && value !== null ? useFormatFloatNumber(value) : ""
5052
5649
  );
5053
- useEffect7(() => {
5650
+ useEffect12(() => {
5054
5651
  if (value !== void 0 && value !== null && value !== parseFloat(inputValue?.replace(/,/g, ""))) {
5055
5652
  setInputValue(useFormatFloatNumber(value));
5056
5653
  clearErrors(name);
@@ -5058,9 +5655,9 @@ var floatController = ({
5058
5655
  setInputValue("");
5059
5656
  }
5060
5657
  }, [value, name, clearErrors]);
5061
- const isDirtyRef = useRef3(false);
5062
- const inputRef = useRef3(null);
5063
- const lastCommittedValueRef = useRef3(null);
5658
+ const isDirtyRef = useRef5(false);
5659
+ const inputRef = useRef5(null);
5660
+ const lastCommittedValueRef = useRef5(null);
5064
5661
  const handleInputChange = (e) => {
5065
5662
  const newValue = e.target.value;
5066
5663
  const valueWithoutCommas = newValue.replace(/,/g, "");
@@ -5078,8 +5675,8 @@ var floatController = ({
5078
5675
  if (!isNaN(parsedValue)) {
5079
5676
  if (parsedValue < 0) {
5080
5677
  setError(name, {
5081
- type: "validate"
5082
- // message: i18n.t('invalid_number'),
5678
+ type: "validate",
5679
+ message: i18n_default.t("invalid_number")
5083
5680
  });
5084
5681
  } else {
5085
5682
  onChange(parsedValue);
@@ -5102,8 +5699,8 @@ var floatController = ({
5102
5699
  if (rawValue === "" || rawValue === ".") {
5103
5700
  if (required) {
5104
5701
  setError(name, {
5105
- type: "required"
5106
- // message: `${string} ${t('must_required')}`,
5702
+ type: "required",
5703
+ message: `${string} ${i18n_default.t("must_required")}`
5107
5704
  });
5108
5705
  }
5109
5706
  onChange(null);
@@ -5112,8 +5709,8 @@ var floatController = ({
5112
5709
  } else if (!isNaN(parsedValue)) {
5113
5710
  if (parsedValue < 0) {
5114
5711
  setError(name, {
5115
- type: "validate"
5116
- // message: i18n.t('invalid_number'),
5712
+ type: "validate",
5713
+ message: i18n_default.t("invalid_number")
5117
5714
  });
5118
5715
  setInputValue("");
5119
5716
  lastCommittedValueRef.current = null;
@@ -5133,8 +5730,8 @@ var floatController = ({
5133
5730
  }
5134
5731
  } else {
5135
5732
  setError(name, {
5136
- type: "validate"
5137
- // message: i18n.t('invalid_number'),
5733
+ type: "validate",
5734
+ message: i18n_default.t("invalid_number")
5138
5735
  });
5139
5736
  setInputValue("");
5140
5737
  lastCommittedValueRef.current = null;
@@ -5161,10 +5758,10 @@ var useFormatFloatNumber = (value) => {
5161
5758
  };
5162
5759
 
5163
5760
  // src/widget/basic/download-file-field/controller.ts
5164
- import { useId, useState as useState9 } from "react";
5761
+ import { useId, useState as useState13 } from "react";
5165
5762
  var downloadFileController = () => {
5166
5763
  const inputId = useId();
5167
- const [file, setFile] = useState9(null);
5764
+ const [file, setFile] = useState13(null);
5168
5765
  const handleFileChange = (e) => {
5169
5766
  setFile(e.target.files[0]);
5170
5767
  };
@@ -5232,8 +5829,8 @@ var dateFieldController = (props) => {
5232
5829
  widget,
5233
5830
  min,
5234
5831
  max,
5235
- formValues,
5236
5832
  viewData,
5833
+ formValues,
5237
5834
  model
5238
5835
  } = props;
5239
5836
  const range = (start, end, step = 1) => {
@@ -5288,18 +5885,30 @@ var dateFieldController = (props) => {
5288
5885
  const compareNow = showTime ? now : now.clone().startOf("day");
5289
5886
  if (minNowValue) {
5290
5887
  if (compareSelected.isBefore(compareNow) && typeof minNowValue === "boolean" && minNowValue === true) {
5888
+ return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
5889
+ "greater_or_equal_now"
5890
+ )}`;
5291
5891
  } else if (import_moment.default.isMoment(minNowValue)) {
5292
5892
  const compareMin = showTime ? minNowValue : minNowValue.clone().startOf("day");
5293
5893
  if (compareSelected.isBefore(compareMin)) {
5294
5894
  const fieldRelationDate = viewData?.models?.[model]?.[min ?? ""];
5895
+ return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
5896
+ "greater_or_equal"
5897
+ )} ${fieldRelationDate?.string}`;
5295
5898
  }
5296
5899
  }
5297
5900
  } else if (maxNowValue) {
5298
5901
  if (compareSelected.isAfter(compareNow) && typeof maxNowValue === "boolean" && maxNowValue === true) {
5902
+ return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
5903
+ "less_or_equal_now"
5904
+ )}`;
5299
5905
  } else if (import_moment.default.isMoment(maxNowValue)) {
5300
5906
  const compareMax = showTime ? maxNowValue : maxNowValue.clone().startOf("day");
5301
5907
  if (compareSelected.isAfter(compareMax)) {
5302
5908
  const fieldRelationDate = viewData?.models?.[model]?.[max ?? ""];
5909
+ return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
5910
+ "less_or_equal"
5911
+ )} ${fieldRelationDate?.string}`;
5303
5912
  }
5304
5913
  }
5305
5914
  }
@@ -5322,11 +5931,11 @@ var dateFieldController = (props) => {
5322
5931
  };
5323
5932
 
5324
5933
  // src/widget/basic/copy-link-button/controller.ts
5325
- import { useState as useState10 } from "react";
5934
+ import { useState as useState14 } from "react";
5326
5935
  import { copyTextToClipboard } from "@fctc/interface-logic";
5327
5936
  var copyLinkButtonController = (props) => {
5328
5937
  const { value, defaultValue } = props;
5329
- const [isCopied, setIsCopied] = useState10(false);
5938
+ const [isCopied, setIsCopied] = useState14(false);
5330
5939
  const handleCopyToClipboard = async (value2) => {
5331
5940
  await copyTextToClipboard(value2);
5332
5941
  setIsCopied(true);
@@ -5340,45 +5949,11 @@ var copyLinkButtonController = (props) => {
5340
5949
  };
5341
5950
  };
5342
5951
 
5343
- // src/widget/basic/color-field/color-wrapper-controller.ts
5344
- import { useEffect as useEffect8, useRef as useRef4, useState as useState11 } from "react";
5345
- var colorWrapperController = (props) => {
5346
- const { savePickColor, defaultColor, colors } = props;
5347
- const [selectedColor, setSelectedColor] = useState11(colors[defaultColor]);
5348
- const [showFullColors, setIsShowFullColor] = useState11(false);
5349
- useEffect8(() => {
5350
- setSelectedColor(colors[defaultColor]);
5351
- }, [defaultColor]);
5352
- const handleShowFullColors = () => {
5353
- setIsShowFullColor(!showFullColors);
5354
- };
5355
- const pickColorsRef = useRef4(null);
5356
- useEffect8(() => {
5357
- const handleClickOutside = (event) => {
5358
- if (pickColorsRef.current && !pickColorsRef.current.contains(event.target)) {
5359
- setIsShowFullColor(false);
5360
- }
5361
- };
5362
- document.addEventListener("mousedown", handleClickOutside);
5363
- return () => {
5364
- document.removeEventListener("mousedown", handleClickOutside);
5365
- };
5366
- }, []);
5367
- return {
5368
- selectedColor,
5369
- showFullColors,
5370
- setSelectedColor,
5371
- handleShowFullColors,
5372
- pickColorsRef,
5373
- savePickColor
5374
- };
5375
- };
5376
-
5377
5952
  // src/widget/basic/color-field/color-controller.ts
5378
- import { evalJSONContext as evalJSONContext6, getEnv as getEnv5, useSave as useSave3 } from "@fctc/interface-logic";
5953
+ import { evalJSONContext as evalJSONContext6, getEnv as getEnv8, useSave as useSave3 } from "@fctc/interface-logic";
5379
5954
  var colorFieldController = (props) => {
5380
5955
  const { value, isForm, name, formValues, idForm, model, actionData } = props;
5381
- const env = getEnv5();
5956
+ const env = getEnv8();
5382
5957
  const _context = { ...evalJSONContext6(actionData?.context) || {} };
5383
5958
  const contextObject = { ...env.context, ..._context };
5384
5959
  const idDefault = isForm ? idForm : formValues?.id;
@@ -5407,16 +5982,16 @@ var colorFieldController = (props) => {
5407
5982
  };
5408
5983
 
5409
5984
  // src/widget/basic/binary-field/controller.ts
5410
- import { useEffect as useEffect9, useId as useId2, useRef as useRef5, useState as useState12 } from "react";
5985
+ import { useEffect as useEffect13, useId as useId2, useRef as useRef6, useState as useState15 } from "react";
5411
5986
  import { isBase64Image } from "@fctc/interface-logic";
5412
5987
  var binaryFieldController = (props) => {
5413
5988
  const { name, methods, readonly = false, value } = props;
5414
5989
  const inputId = useId2();
5415
- const [selectedImage, setSelectedImage] = useState12(null);
5416
- const [initialImage, setInitialImage] = useState12(value || null);
5417
- const [isInsideTable, setIsInsideTable] = useState12(false);
5990
+ const [selectedImage, setSelectedImage] = useState15(null);
5991
+ const [initialImage, setInitialImage] = useState15(value || null);
5992
+ const [isInsideTable, setIsInsideTable] = useState15(false);
5418
5993
  const { setValue } = methods;
5419
- const binaryRef = useRef5(null);
5994
+ const binaryRef = useRef6(null);
5420
5995
  const convertUrlToBase64 = async (url) => {
5421
5996
  try {
5422
5997
  const response = await fetch(url);
@@ -5478,14 +6053,14 @@ var binaryFieldController = (props) => {
5478
6053
  else if (base64.startsWith("UklGR")) mimeType = "image/webp";
5479
6054
  return mimeType ? `data:${mimeType};base64,${base64}` : null;
5480
6055
  };
5481
- useEffect9(() => {
6056
+ useEffect13(() => {
5482
6057
  return () => {
5483
6058
  if (selectedImage) {
5484
6059
  URL.revokeObjectURL(selectedImage);
5485
6060
  }
5486
6061
  };
5487
6062
  }, [selectedImage]);
5488
- useEffect9(() => {
6063
+ useEffect13(() => {
5489
6064
  if (binaryRef.current) {
5490
6065
  const isInsideTable2 = !!binaryRef.current.closest("table");
5491
6066
  setIsInsideTable(isInsideTable2);
@@ -5504,28 +6079,47 @@ var binaryFieldController = (props) => {
5504
6079
  };
5505
6080
  };
5506
6081
  export {
6082
+ API_APP_URL,
6083
+ API_PRESCHOOL_URL,
5507
6084
  CloseIcon,
5508
6085
  EyeIcon,
5509
6086
  LoadingIcon,
6087
+ STORAGES,
5510
6088
  binaryFieldController,
5511
6089
  colorFieldController,
5512
- colorWrapperController,
6090
+ combineContexts,
6091
+ convertFieldsToArray,
5513
6092
  copyLinkButtonController,
6093
+ countSum,
5514
6094
  dateFieldController,
5515
6095
  downLoadBinaryController,
5516
6096
  downloadFileController,
5517
6097
  durationController,
5518
6098
  floatController,
5519
6099
  floatTimeFiledController,
6100
+ getDateRange,
6101
+ languages,
5520
6102
  many2manyFieldController,
5521
6103
  many2manyTagsController,
5522
6104
  many2oneButtonController,
5523
6105
  many2oneFieldController,
6106
+ mergeButtons,
5524
6107
  priorityFieldController,
6108
+ setStorageItemAsync,
5525
6109
  statusDropdownController,
6110
+ useAuth,
6111
+ useCallAction,
5526
6112
  useClickOutside,
6113
+ useConfig,
5527
6114
  useDebounce,
5528
- useTableHandler
6115
+ useDetail,
6116
+ useGetRowIds,
6117
+ useListData,
6118
+ useMenu,
6119
+ useProfile,
6120
+ useStorageState,
6121
+ useUser,
6122
+ useViewV2
5529
6123
  };
5530
6124
  /*! Bundled license information:
5531
6125