@fctc/widget-logic 1.1.3 → 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.js CHANGED
@@ -4034,38 +4034,644 @@ var require_moment = __commonJS({
4034
4034
  // src/index.ts
4035
4035
  var index_exports = {};
4036
4036
  __export(index_exports, {
4037
+ API_APP_URL: () => API_APP_URL,
4038
+ API_PRESCHOOL_URL: () => API_PRESCHOOL_URL,
4037
4039
  CloseIcon: () => CloseIcon,
4038
4040
  EyeIcon: () => EyeIcon,
4039
- LayerLoading: () => LayerLoading,
4040
4041
  LoadingIcon: () => LoadingIcon,
4041
- LoadingSmall: () => LoadingSmall,
4042
- ModalConfirm: () => ModalConfirm,
4043
- ModalDetail: () => ModalDetail,
4044
- ModalLayer: () => ModalLayer,
4042
+ STORAGES: () => STORAGES,
4045
4043
  binaryFieldController: () => binaryFieldController,
4046
4044
  colorFieldController: () => colorFieldController,
4047
- colorWrapperController: () => colorWrapperController,
4045
+ combineContexts: () => combineContexts,
4046
+ convertFieldsToArray: () => convertFieldsToArray,
4048
4047
  copyLinkButtonController: () => copyLinkButtonController,
4048
+ countSum: () => countSum,
4049
4049
  dateFieldController: () => dateFieldController,
4050
4050
  downLoadBinaryController: () => downLoadBinaryController,
4051
4051
  downloadFileController: () => downloadFileController,
4052
4052
  durationController: () => durationController,
4053
4053
  floatController: () => floatController,
4054
4054
  floatTimeFiledController: () => floatTimeFiledController,
4055
+ getDateRange: () => getDateRange,
4056
+ languages: () => languages,
4055
4057
  many2manyFieldController: () => many2manyFieldController,
4056
4058
  many2manyTagsController: () => many2manyTagsController,
4057
4059
  many2oneButtonController: () => many2oneButtonController,
4058
4060
  many2oneFieldController: () => many2oneFieldController,
4061
+ mergeButtons: () => mergeButtons,
4059
4062
  priorityFieldController: () => priorityFieldController,
4063
+ setStorageItemAsync: () => setStorageItemAsync,
4060
4064
  statusDropdownController: () => statusDropdownController,
4065
+ useAuth: () => useAuth,
4066
+ useCallAction: () => useCallAction,
4061
4067
  useClickOutside: () => useClickOutside,
4068
+ useConfig: () => useConfig,
4062
4069
  useDebounce: () => useDebounce,
4063
- useTableHandler: () => useTableHandler
4070
+ useDetail: () => useDetail,
4071
+ useGetRowIds: () => useGetRowIds,
4072
+ useListData: () => useListData,
4073
+ useMenu: () => useMenu,
4074
+ useProfile: () => useProfile,
4075
+ useStorageState: () => useStorageState,
4076
+ useUser: () => useUser,
4077
+ useViewV2: () => useViewV2
4064
4078
  });
4065
4079
  module.exports = __toCommonJS(index_exports);
4066
4080
 
4067
- // src/hooks/use-click-outside.ts
4081
+ // src/hooks/core/use-call-action.ts
4082
+ var import_interface_logic = require("@fctc/interface-logic");
4068
4083
  var import_react = require("react");
4084
+ var useCallAction = () => {
4085
+ const queryLoadAction = (0, import_interface_logic.useLoadAction)();
4086
+ const queryRunAction = (0, import_interface_logic.useRunAction)();
4087
+ const [data, setData] = (0, import_react.useState)(void 0);
4088
+ const callAction = async ({
4089
+ aid,
4090
+ actionType = "ir.actions.act_window"
4091
+ }) => {
4092
+ const context = (0, import_interface_logic.getEnv)().context;
4093
+ let res = void 0;
4094
+ if (actionType === "ir.actions.act_window") {
4095
+ res = await queryLoadAction.mutateAsync({
4096
+ idAction: aid,
4097
+ context
4098
+ });
4099
+ } else if (actionType === "ir.actions.server") {
4100
+ res = await queryRunAction.mutateAsync({
4101
+ idAction: aid,
4102
+ context
4103
+ });
4104
+ }
4105
+ setData(res);
4106
+ return res;
4107
+ };
4108
+ return [data, callAction];
4109
+ };
4110
+
4111
+ // src/hooks/core/use-config.ts
4112
+ var import_interface_logic2 = require("@fctc/interface-logic");
4113
+ var import_react2 = require("react");
4114
+ var useConfig = ({ localStorageUtils, sessionStorageUtils }) => {
4115
+ const dispatch = (0, import_interface_logic2.useAppDispatch)();
4116
+ const envConfig = (0, import_react2.useMemo)(() => {
4117
+ return {
4118
+ mode: "development",
4119
+ baseUrl: "https://api.vitrust.app/c2/api/v2",
4120
+ config: {
4121
+ grantType: "password",
4122
+ clientId: "C52foVQSMpnNOcAP2CBIIkupOSfxUarF8nlOPfXM",
4123
+ clientSecret: "rColINr4a9QBFQPqQB8YU1XfBjqzwerDMJGBxsFK"
4124
+ }
4125
+ };
4126
+ }, []);
4127
+ const config = (0, import_react2.useMemo)(() => {
4128
+ return {
4129
+ VITE_SIDEBAR_TYPE: "grid/sidebar",
4130
+ VITE_APP_DOMAIN: "https://api.vitrust.app/c2/",
4131
+ VITE_IS_EDU: true,
4132
+ VITE_LOGO_WHITE_LOGIN: "https://static.vitrust.app/vitrust/3a/3a1301f614dea6ee19ebf99b68f57e3fd46011d2.png",
4133
+ VITE_LOGO_BLACK_LOGIN: "https://static.vitrust.app/vitrust/32/3223918780da7a439f916faac9abf0bfe98dfa07.png",
4134
+ VITE_BACKGROUND_SIDEBAR: "linear-gradient(178deg, rgb(1, 106, 13) -0.89%, rgb(4, 179, 66) 99.46%",
4135
+ VITE_BANNER: "https://static.vitrust.app/vitrust/5d/5d20cab0627182b4ed5cba4ee42c58b98b663e5b.svg",
4136
+ VITE_BG_BUTTON: "#008F3C",
4137
+ VITE_BACKGROUND_PAGE: "#F9FAFB"
4138
+ };
4139
+ }, []);
4140
+ (0, import_react2.useEffect)(() => {
4141
+ try {
4142
+ const env = (0, import_interface_logic2.getEnv)();
4143
+ env.setupEnv({
4144
+ baseUrl: envConfig.baseUrl,
4145
+ port: 3e3,
4146
+ config: {
4147
+ grantType: envConfig.config.grantType,
4148
+ clientId: envConfig.config.clientId,
4149
+ clientSecret: envConfig.config.clientSecret
4150
+ },
4151
+ db: "preschool",
4152
+ localStorageUtils: localStorageUtils(),
4153
+ sessionStorageUtils: sessionStorageUtils()
4154
+ });
4155
+ dispatch((0, import_interface_logic2.setEnvFile)(config));
4156
+ } catch (error) {
4157
+ console.error("Error loading env or config:", error);
4158
+ }
4159
+ }, [dispatch, envConfig, config]);
4160
+ return { envConfig, config };
4161
+ };
4162
+
4163
+ // src/hooks/core/use-detail.ts
4164
+ var import_interface_logic3 = require("@fctc/interface-logic");
4165
+ var import_react_query = require("@tanstack/react-query");
4166
+ var import_react3 = require("react");
4167
+ var useDetail = (accessToken, sub) => {
4168
+ const dispatch = (0, import_interface_logic3.useAppDispatch)();
4169
+ const fetchGetDetail = (0, import_interface_logic3.useGetDetail)();
4170
+ const userDetailQuery = (0, import_react_query.useQuery)({
4171
+ queryKey: ["userDetailQuery", sub && accessToken],
4172
+ queryFn: () => {
4173
+ return fetchGetDetail.mutateAsync({
4174
+ model: "res.users",
4175
+ ids: [sub],
4176
+ specification: { image_256: {} }
4177
+ });
4178
+ },
4179
+ enabled: !!sub && !!accessToken
4180
+ });
4181
+ (0, import_react3.useEffect)(() => {
4182
+ if (userDetailQuery.data) {
4183
+ const userPicture = userDetailQuery.data;
4184
+ dispatch(
4185
+ (0, import_interface_logic3.setProfile)({ ...userPicture, image: userPicture?.[0]?.image_256 })
4186
+ );
4187
+ }
4188
+ }, [userDetailQuery.data, dispatch]);
4189
+ return userDetailQuery;
4190
+ };
4191
+
4192
+ // src/hooks/core/use-list-data.ts
4193
+ var import_react5 = require("react");
4194
+ var import_interface_logic4 = require("@fctc/interface-logic");
4195
+
4196
+ // src/utils/function.ts
4197
+ var import_react4 = require("react");
4198
+ var countSum = (data, field) => {
4199
+ if (!data || !field) return 0;
4200
+ return data.reduce(
4201
+ (total, item) => total + (item?.[`${field}_count`] || 0),
4202
+ 0
4203
+ );
4204
+ };
4205
+ function mergeButtons(fields) {
4206
+ const buttons = fields?.filter((f) => f.type_co === "button");
4207
+ const others = fields?.filter((f) => f.type_co !== "button");
4208
+ if (buttons?.length) {
4209
+ others.push({
4210
+ type_co: "buttons",
4211
+ buttons
4212
+ });
4213
+ }
4214
+ return others;
4215
+ }
4216
+ function isElementVisible(el) {
4217
+ const style = window.getComputedStyle(el);
4218
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0";
4219
+ }
4220
+ function arraysAreEqual(a, b) {
4221
+ if (a.length !== b.length) return false;
4222
+ const setA = new Set(a);
4223
+ const setB = new Set(b);
4224
+ if (setA.size !== setB.size) return false;
4225
+ for (const val of setA) {
4226
+ if (!setB.has(val)) return false;
4227
+ }
4228
+ return true;
4229
+ }
4230
+ function useGetRowIds(tableRef) {
4231
+ const [rowIds, setRowIds] = (0, import_react4.useState)([]);
4232
+ const lastRowIdsRef = (0, import_react4.useRef)([]);
4233
+ const updateVisibleRowIds = (0, import_react4.useCallback)(() => {
4234
+ const table = tableRef?.current;
4235
+ if (!table) return;
4236
+ const rows = table.querySelectorAll("tr[data-row-id]");
4237
+ const ids = [];
4238
+ rows.forEach((row) => {
4239
+ const el = row;
4240
+ if (isElementVisible(el)) {
4241
+ const id = el.getAttribute("data-row-id");
4242
+ if (id) ids.push(id);
4243
+ }
4244
+ });
4245
+ const uniqueIds = Array.from(new Set(ids));
4246
+ if (!arraysAreEqual(lastRowIdsRef.current, uniqueIds)) {
4247
+ lastRowIdsRef.current = uniqueIds;
4248
+ setRowIds(uniqueIds);
4249
+ }
4250
+ }, [tableRef]);
4251
+ (0, import_react4.useEffect)(() => {
4252
+ const table = tableRef?.current;
4253
+ if (!table) return;
4254
+ const observer = new MutationObserver(() => {
4255
+ updateVisibleRowIds();
4256
+ });
4257
+ observer.observe(table, {
4258
+ childList: true,
4259
+ subtree: true,
4260
+ attributes: true,
4261
+ attributeFilter: ["style", "class"]
4262
+ });
4263
+ updateVisibleRowIds();
4264
+ return () => {
4265
+ observer.disconnect();
4266
+ };
4267
+ }, [updateVisibleRowIds, tableRef]);
4268
+ return { rowIds, refresh: updateVisibleRowIds };
4269
+ }
4270
+ var getDateRange = (currentDate, unit) => {
4271
+ const date = new Date(currentDate);
4272
+ let dateStart, dateEnd;
4273
+ function formatDate(d) {
4274
+ 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");
4275
+ }
4276
+ switch (unit) {
4277
+ case "month":
4278
+ dateStart = new Date(
4279
+ date.getFullYear(),
4280
+ date.getMonth() + 1,
4281
+ date.getDate(),
4282
+ 23,
4283
+ 59,
4284
+ 59
4285
+ );
4286
+ dateStart.setHours(dateStart.getHours() - 7);
4287
+ dateEnd = new Date(date.getFullYear(), date.getMonth(), 0, 0, 0, 0);
4288
+ dateEnd.setHours(dateEnd.getHours() - 7);
4289
+ break;
4290
+ case "day":
4291
+ dateStart = new Date(
4292
+ date.getFullYear(),
4293
+ date.getMonth(),
4294
+ date.getDate(),
4295
+ 23,
4296
+ 59,
4297
+ 59
4298
+ );
4299
+ dateStart.setHours(dateStart.getHours() - 7);
4300
+ dateEnd = new Date(
4301
+ date.getFullYear(),
4302
+ date.getMonth(),
4303
+ date.getDate(),
4304
+ 0,
4305
+ 0,
4306
+ 0
4307
+ );
4308
+ dateEnd.setHours(dateEnd.getHours() - 7);
4309
+ break;
4310
+ case "week":
4311
+ const dayOfWeek = date.getDay();
4312
+ const daysToMonday = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
4313
+ const daysToSunday = dayOfWeek === 0 ? 0 : 7 - dayOfWeek;
4314
+ dateStart = new Date(
4315
+ date.getFullYear(),
4316
+ date.getMonth(),
4317
+ date.getDate() + daysToSunday,
4318
+ 23,
4319
+ 59,
4320
+ 59
4321
+ );
4322
+ dateStart.setHours(dateStart.getHours() - 7);
4323
+ dateEnd = new Date(
4324
+ date.getFullYear(),
4325
+ date.getMonth(),
4326
+ date.getDate() + daysToMonday,
4327
+ 0,
4328
+ 0,
4329
+ 0
4330
+ );
4331
+ dateEnd.setHours(dateEnd.getHours() - 7);
4332
+ break;
4333
+ case "year":
4334
+ dateStart = new Date(date.getFullYear(), 11, 31, 23, 59, 59);
4335
+ dateStart.setHours(dateStart.getHours() - 7);
4336
+ dateEnd = new Date(date.getFullYear() - 1, 11, 31, 0, 0, 0);
4337
+ dateEnd.setHours(dateEnd.getHours() - 7);
4338
+ break;
4339
+ default:
4340
+ throw new Error(
4341
+ "\u0110\u01A1n v\u1ECB kh\xF4ng h\u1EE3p l\u1EC7. Ch\u1EC9 ch\u1EA5p nh\u1EADn: week, day, month, year"
4342
+ );
4343
+ }
4344
+ return [
4345
+ ["date_start", "<=", formatDate(dateStart)],
4346
+ ["date_end", ">=", formatDate(dateEnd)]
4347
+ ];
4348
+ };
4349
+ var convertFieldsToArray = (fields) => {
4350
+ const defaultFields = ["display_name", "date_start", "date_end"];
4351
+ if (!fields || !Array.isArray(fields)) {
4352
+ return defaultFields;
4353
+ }
4354
+ const inputFields = fields.filter((field) => field && field.type_co === "field").map((field) => field.name);
4355
+ return [...defaultFields, ...inputFields];
4356
+ };
4357
+ function combineContexts(contexts) {
4358
+ if (contexts.some((context) => !context)) {
4359
+ return void 0;
4360
+ } else {
4361
+ const res = contexts.reduce((acc, context) => {
4362
+ return { ...acc, ...context };
4363
+ }, {});
4364
+ return res;
4365
+ }
4366
+ }
4367
+ var STORAGES = {
4368
+ TOKEN: "accessToken",
4369
+ USER_INFO: "USER_INFO"
4370
+ };
4371
+ function useAsyncState(initialValue = [true, null]) {
4372
+ return (0, import_react4.useReducer)(
4373
+ (_state, action = null) => [false, action],
4374
+ initialValue
4375
+ );
4376
+ }
4377
+ async function setStorageItemAsync(key, value) {
4378
+ try {
4379
+ if (value === null) {
4380
+ localStorage.removeItem(key);
4381
+ } else {
4382
+ localStorage.setItem(key, value);
4383
+ }
4384
+ } catch (e) {
4385
+ console.error("Local storage is unavailable:", e);
4386
+ }
4387
+ }
4388
+ function useStorageState(key) {
4389
+ const [state, setState] = useAsyncState();
4390
+ (0, import_react4.useEffect)(() => {
4391
+ try {
4392
+ const storedValue = localStorage.getItem(key);
4393
+ setState(storedValue);
4394
+ } catch (e) {
4395
+ console.error("Local storage is unavailable:", e);
4396
+ }
4397
+ }, [key]);
4398
+ const setValue = (0, import_react4.useCallback)(
4399
+ (value) => {
4400
+ setState(value);
4401
+ setStorageItemAsync(key, value);
4402
+ },
4403
+ [key]
4404
+ );
4405
+ return [state, setValue];
4406
+ }
4407
+
4408
+ // src/hooks/core/use-list-data.ts
4409
+ var useListData = ({
4410
+ action,
4411
+ context,
4412
+ viewResponse
4413
+ }) => {
4414
+ const { groupByDomain } = (0, import_interface_logic4.useAppSelector)(import_interface_logic4.selectSearch);
4415
+ const initModel = (0, import_interface_logic4.useModel)();
4416
+ const [type, setType] = (0, import_react5.useState)("list");
4417
+ const [mode, setMode] = (0, import_react5.useState)("month");
4418
+ const [currentDate, setCurrentDate] = (0, import_react5.useState)(/* @__PURE__ */ new Date());
4419
+ const { pageLimit, page, order } = (0, import_interface_logic4.useAppSelector)(import_interface_logic4.selectList);
4420
+ const listDataProps = (0, import_react5.useMemo)(() => {
4421
+ const actData = action?.result;
4422
+ if (!viewResponse || !actData || !context) {
4423
+ return null;
4424
+ }
4425
+ const specification = initModel.initModel({
4426
+ name: String(actData.res_model),
4427
+ view: viewResponse || {},
4428
+ actContext: context,
4429
+ fields: type === "kanban" ? viewResponse?.views?.kanban?.fields : type === "calendar" ? viewResponse?.views?.calendar?.fields : viewResponse?.views?.list?.fields
4430
+ }).getSpecification();
4431
+ const domain = type === "calendar" ? getDateRange(currentDate, mode) : actData?.domain ? Array.isArray(actData?.domain) ? [...actData?.domain] : (0, import_interface_logic4.evalJSONDomain)(actData?.domain, context) : [];
4432
+ const limit = type === "calendar" ? 2500 : pageLimit;
4433
+ const offset = page * pageLimit;
4434
+ const fields = type === "calendar" ? convertFieldsToArray(viewResponse?.views?.calendar?.fields) || [] : typeof groupByDomain === "object" ? groupByDomain?.fields : void 0;
4435
+ const groupby = typeof groupByDomain === "object" ? [groupByDomain?.contexts?.[0]?.group_by] : [];
4436
+ const sort = order ? order : viewResponse?.views?.list?.default_order ? (0, import_interface_logic4.formatSortingString)(viewResponse?.views?.list?.default_order) : "";
4437
+ return {
4438
+ model: actData.res_model,
4439
+ specification,
4440
+ domain,
4441
+ limit,
4442
+ offset,
4443
+ fields,
4444
+ groupby,
4445
+ context,
4446
+ sort,
4447
+ type
4448
+ };
4449
+ }, [
4450
+ action?.result,
4451
+ context,
4452
+ currentDate,
4453
+ groupByDomain,
4454
+ initModel,
4455
+ mode,
4456
+ order,
4457
+ page,
4458
+ pageLimit,
4459
+ type,
4460
+ viewResponse
4461
+ ]);
4462
+ const list = (0, import_interface_logic4.useGetListData)(
4463
+ listDataProps,
4464
+ [listDataProps],
4465
+ !!listDataProps
4466
+ );
4467
+ return {
4468
+ ...list,
4469
+ state: {
4470
+ type,
4471
+ setType,
4472
+ mode,
4473
+ setMode,
4474
+ currentDate,
4475
+ setCurrentDate
4476
+ }
4477
+ };
4478
+ };
4479
+
4480
+ // src/hooks/core/use-menu.ts
4481
+ var import_react6 = require("react");
4482
+ var import_interface_logic5 = require("@fctc/interface-logic");
4483
+
4484
+ // src/utils/constants.ts
4485
+ var languages = [
4486
+ { id: "vi_VN", name: "VIE" },
4487
+ { id: "en_US", name: "ENG" }
4488
+ ];
4489
+ var API_PRESCHOOL_URL = {
4490
+ baseURL: "https://preschool.vitrust.app"
4491
+ };
4492
+ var API_APP_URL = {
4493
+ baseUrl: "https://api.vitrust.app",
4494
+ c2: "https://api.vitrust.app/c2",
4495
+ apiV2: "https://api.vitrust.app/c2/api/v2"
4496
+ };
4497
+
4498
+ // src/hooks/core/use-menu.ts
4499
+ var useMenu = ({ context }) => {
4500
+ const menuData = (0, import_interface_logic5.useGetMenu)(context, !!context);
4501
+ const [menuid, setMenuId] = (0, import_react6.useState)(void 0);
4502
+ const [action, setAction] = useCallAction();
4503
+ const configedIconData = (0, import_react6.useMemo)(() => {
4504
+ const data = menuData.data;
4505
+ return data?.map((item) => {
4506
+ return {
4507
+ ...item,
4508
+ child_id: item?.child_id?.map((child) => {
4509
+ return {
4510
+ ...child,
4511
+ url_icon: API_APP_URL.c2 + "/" + child.url_icon
4512
+ };
4513
+ }) ?? [],
4514
+ url_icon: API_APP_URL.c2 + "/" + item.url_icon
4515
+ };
4516
+ });
4517
+ }, [menuData.data]);
4518
+ const handleChangeMenu = async ({
4519
+ menu,
4520
+ subMenu
4521
+ }) => {
4522
+ const aid = subMenu?.action?.id?.id;
4523
+ const actionType = subMenu?.action?.type;
4524
+ await setAction({
4525
+ aid: Number(aid),
4526
+ actionType
4527
+ });
4528
+ if (menu) {
4529
+ setMenuId(menu.id?.toString() ?? "");
4530
+ }
4531
+ };
4532
+ (0, import_react6.useEffect)(() => {
4533
+ const firstRecord = configedIconData?.[0];
4534
+ const firstChild = firstRecord?.child_id?.[0];
4535
+ if (firstChild && firstRecord) {
4536
+ handleChangeMenu({ menu: firstRecord, subMenu: firstChild });
4537
+ }
4538
+ }, [configedIconData]);
4539
+ return {
4540
+ ...menuData,
4541
+ data: configedIconData,
4542
+ action: { handleChangeMenu },
4543
+ state: { menuid, action },
4544
+ context
4545
+ };
4546
+ };
4547
+
4548
+ // src/hooks/core/use-profile.ts
4549
+ var import_react_query2 = require("@tanstack/react-query");
4550
+ var import_react7 = require("react");
4551
+ var import_react_i18next = require("react-i18next");
4552
+ var import_interface_logic6 = require("@fctc/interface-logic");
4553
+ var useProfile = (accessToken) => {
4554
+ const getProfile = (0, import_interface_logic6.useGetProfile)();
4555
+ const dispatch = (0, import_interface_logic6.useAppDispatch)();
4556
+ const { i18n: i18n2 } = (0, import_react_i18next.useTranslation)();
4557
+ const fetchUserProfile = async () => {
4558
+ return await getProfile.mutateAsync();
4559
+ };
4560
+ const userInfoQuery = (0, import_react_query2.useQuery)({
4561
+ queryKey: ["userInfo", accessToken],
4562
+ queryFn: fetchUserProfile,
4563
+ enabled: !!accessToken
4564
+ });
4565
+ (0, import_react7.useEffect)(() => {
4566
+ if (userInfoQuery.data) {
4567
+ const userInfo = userInfoQuery.data;
4568
+ const env = (0, import_interface_logic6.getEnv)();
4569
+ env.setUid(userInfo?.sub);
4570
+ dispatch((0, import_interface_logic6.setDataUser)(userInfo));
4571
+ const userLocale = languages.find((lang) => lang?.id === userInfo?.locale);
4572
+ env.setLang(userLocale?.id);
4573
+ i18n2.changeLanguage(userLocale?.id.split("_")[0]);
4574
+ }
4575
+ }, [dispatch, userInfoQuery.data]);
4576
+ const context = (0, import_react7.useMemo)(() => {
4577
+ if (userInfoQuery.data?.sub && userInfoQuery.data?.locale) {
4578
+ return {
4579
+ uid: Number(userInfoQuery.data.sub),
4580
+ allowed_company_ids: [],
4581
+ lang: String(userInfoQuery.data.locale),
4582
+ tz: "Asia/Saigon"
4583
+ };
4584
+ }
4585
+ return void 0;
4586
+ }, [userInfoQuery.data]);
4587
+ return { ...userInfoQuery, context };
4588
+ };
4589
+
4590
+ // src/hooks/core/use-user.ts
4591
+ var useUser = (accessToken) => {
4592
+ const userProfile = useProfile(accessToken);
4593
+ const userDetail = useDetail(accessToken, userProfile.data?.sub);
4594
+ return { userProfile, userDetail, context: userProfile.context };
4595
+ };
4596
+
4597
+ // src/hooks/core/use-view-v2.ts
4598
+ var import_react8 = require("react");
4599
+ var import_interface_logic7 = require("@fctc/interface-logic");
4600
+ var useViewV2 = ({
4601
+ action,
4602
+ context
4603
+ }) => {
4604
+ const viewParams = (0, import_react8.useMemo)(() => {
4605
+ if (!action?.result) {
4606
+ return void 0;
4607
+ }
4608
+ const actionResult = action?.result;
4609
+ return {
4610
+ model: String(actionResult?.res_model),
4611
+ views: [
4612
+ ...Array.isArray(actionResult?.views) ? actionResult?.views.map(
4613
+ (view2) => view2[1] === "list" ? [view2[0], "list"] : view2
4614
+ ) : [],
4615
+ [
4616
+ Array.isArray(actionResult?.search_view_id) ? actionResult?.search_view_id[0] : actionResult?.search_view_id,
4617
+ "search"
4618
+ ]
4619
+ ],
4620
+ context
4621
+ };
4622
+ }, [action, context]);
4623
+ const view = (0, import_interface_logic7.useGetView)(
4624
+ viewParams || {},
4625
+ !!viewParams
4626
+ );
4627
+ return {
4628
+ ...view,
4629
+ context
4630
+ };
4631
+ };
4632
+
4633
+ // src/hooks/core/use-auth.ts
4634
+ var import_interface_logic8 = require("@fctc/interface-logic");
4635
+ var useAuth = () => {
4636
+ const [[isLoading, accessToken], setAccessToken] = useStorageState("TOKEN");
4637
+ const loginMutate = (0, import_interface_logic8.useLoginCredential)();
4638
+ const dispatch = (0, import_interface_logic8.useAppDispatch)();
4639
+ const signIn = async (email, password) => {
4640
+ try {
4641
+ loginMutate.mutate(
4642
+ {
4643
+ email,
4644
+ password,
4645
+ path: "/authentication/oauth2/token"
4646
+ },
4647
+ {
4648
+ onSuccess: (res) => {
4649
+ setAccessToken(res.access_token);
4650
+ },
4651
+ onError: (err) => {
4652
+ }
4653
+ }
4654
+ );
4655
+ } catch (error) {
4656
+ throw new Error("Login failed");
4657
+ }
4658
+ };
4659
+ const signOut = async () => {
4660
+ dispatch((0, import_interface_logic8.setMenuList)([]));
4661
+ dispatch((0, import_interface_logic8.setDataUser)({}));
4662
+ dispatch((0, import_interface_logic8.setProfile)({}));
4663
+ setAccessToken(null);
4664
+ };
4665
+ return {
4666
+ signIn,
4667
+ signOut,
4668
+ accessToken,
4669
+ isLoading
4670
+ };
4671
+ };
4672
+
4673
+ // src/hooks/utils/use-click-outside.ts
4674
+ var import_react9 = require("react");
4069
4675
  var DEFAULT_EVENTS = ["mousedown", "touchstart"];
4070
4676
  var useClickOutside = ({
4071
4677
  handler,
@@ -4073,8 +4679,8 @@ var useClickOutside = ({
4073
4679
  nodes = [],
4074
4680
  refs
4075
4681
  }) => {
4076
- const ref = (0, import_react.useRef)(null);
4077
- (0, import_react.useEffect)(() => {
4682
+ const ref = (0, import_react9.useRef)(null);
4683
+ (0, import_react9.useEffect)(() => {
4078
4684
  const listener = (event) => {
4079
4685
  const { target } = event;
4080
4686
  if (refs && refs?.length > 0 && refs?.some((r) => r.current?.contains(target))) {
@@ -4095,11 +4701,11 @@ var useClickOutside = ({
4095
4701
  return ref;
4096
4702
  };
4097
4703
 
4098
- // src/hooks/use-debounce.ts
4099
- var import_react2 = require("react");
4704
+ // src/hooks/utils/use-debounce.ts
4705
+ var import_react10 = require("react");
4100
4706
  function useDebounce(value, delay) {
4101
- const [debouncedValue, setDebouncedValue] = (0, import_react2.useState)(value);
4102
- (0, import_react2.useEffect)(() => {
4707
+ const [debouncedValue, setDebouncedValue] = (0, import_react10.useState)(value);
4708
+ (0, import_react10.useEffect)(() => {
4103
4709
  const handler = setTimeout(() => {
4104
4710
  setDebouncedValue(value);
4105
4711
  }, delay);
@@ -4217,19 +4823,19 @@ var CloseIcon = ({ className = "" }) => {
4217
4823
  };
4218
4824
 
4219
4825
  // src/widget/basic/status-dropdown-field/controller.ts
4220
- var import_react3 = require("react");
4221
- var import_interface_logic = require("@fctc/interface-logic");
4826
+ var import_react11 = require("react");
4827
+ var import_interface_logic9 = require("@fctc/interface-logic");
4222
4828
  var statusDropdownController = (props) => {
4223
4829
  const { selection, isForm, id, model, name, state, onRefetch } = props;
4224
- const env = (0, import_interface_logic.getEnv)();
4830
+ const env = (0, import_interface_logic9.getEnv)();
4225
4831
  const colors = {
4226
4832
  normal: "bg-[#e9ecef]",
4227
4833
  done: "bg-primary",
4228
4834
  blocked: "bg-red-500"
4229
4835
  };
4230
- const [isOpen, setIsOpen] = (0, import_react3.useState)(false);
4231
- const buttonRef = (0, import_react3.useRef)(null);
4232
- (0, import_react3.useEffect)(() => {
4836
+ const [isOpen, setIsOpen] = (0, import_react11.useState)(false);
4837
+ const buttonRef = (0, import_react11.useRef)(null);
4838
+ (0, import_react11.useEffect)(() => {
4233
4839
  const handleClickOutside = (event) => {
4234
4840
  if (buttonRef.current && !buttonRef.current.contains(event.target)) {
4235
4841
  setIsOpen(false);
@@ -4240,7 +4846,7 @@ var statusDropdownController = (props) => {
4240
4846
  document.removeEventListener("mousedown", handleClickOutside);
4241
4847
  };
4242
4848
  }, []);
4243
- const { mutate: onSave } = (0, import_interface_logic.useSave)();
4849
+ const { mutate: onSave } = (0, import_interface_logic9.useSave)();
4244
4850
  const handleClick = async (status) => {
4245
4851
  setIsOpen(!isOpen);
4246
4852
  onSave(
@@ -4270,8 +4876,8 @@ var statusDropdownController = (props) => {
4270
4876
  };
4271
4877
 
4272
4878
  // src/widget/basic/many2one-field/controller.ts
4273
- var import_react4 = require("react");
4274
- var import_interface_logic2 = require("@fctc/interface-logic");
4879
+ var import_react12 = require("react");
4880
+ var import_interface_logic10 = require("@fctc/interface-logic");
4275
4881
  var many2oneFieldController = (props) => {
4276
4882
  const {
4277
4883
  name,
@@ -4286,24 +4892,24 @@ var many2oneFieldController = (props) => {
4286
4892
  showDetail = true,
4287
4893
  actionData
4288
4894
  } = props;
4289
- const [options, setOptions] = (0, import_react4.useState)([]);
4290
- const [isShowModalMany2Many, setIsShowModalMany2Many] = (0, import_react4.useState)(false);
4291
- const [tempSelectedOption, setTempSelectedOption] = (0, import_react4.useState)(null);
4292
- const { menuList } = (0, import_interface_logic2.useAppSelector)(import_interface_logic2.selectNavbar);
4293
- const { context } = (0, import_interface_logic2.useAppSelector)(import_interface_logic2.selectEnv);
4294
- const [domainModal, setDomainModal] = (0, import_react4.useState)(null);
4895
+ const [options, setOptions] = (0, import_react12.useState)([]);
4896
+ const [isShowModalMany2Many, setIsShowModalMany2Many] = (0, import_react12.useState)(false);
4897
+ const [tempSelectedOption, setTempSelectedOption] = (0, import_react12.useState)(null);
4898
+ const { menuList } = (0, import_interface_logic10.useAppSelector)(import_interface_logic10.selectNavbar);
4899
+ const { context } = (0, import_interface_logic10.useAppSelector)(import_interface_logic10.selectEnv);
4900
+ const [domainModal, setDomainModal] = (0, import_react12.useState)(null);
4295
4901
  const initValue = methods?.getValues(name);
4296
- const domainObject = (0, import_react4.useMemo)(
4297
- () => (0, import_interface_logic2.evalJSONDomain)(domain, JSON.parse(JSON.stringify(formValues)) ?? {}),
4902
+ const domainObject = (0, import_react12.useMemo)(
4903
+ () => (0, import_interface_logic10.evalJSONDomain)(domain, JSON.parse(JSON.stringify(formValues)) ?? {}),
4298
4904
  [domain, formValues]
4299
4905
  );
4300
- const optionsObject = (0, import_interface_logic2.evalJSONContext)(fieldOptions) || {};
4906
+ const optionsObject = (0, import_interface_logic10.evalJSONContext)(fieldOptions) || {};
4301
4907
  const contextObject = {
4302
- ...(0, import_interface_logic2.evalJSONContext)(actionData?.context) || {},
4908
+ ...(0, import_interface_logic10.evalJSONContext)(actionData?.context) || {},
4303
4909
  ...fieldContext,
4304
4910
  ...context
4305
4911
  };
4306
- const actionId = (0, import_react4.useMemo)(
4912
+ const actionId = (0, import_react12.useMemo)(
4307
4913
  () => menuList?.flatMap(
4308
4914
  (item) => item?.child_id.filter(
4309
4915
  (childItem) => childItem?.is_display && childItem?.action?.res_model === relation
@@ -4326,23 +4932,23 @@ var many2oneFieldController = (props) => {
4326
4932
  data: dataOfSelection,
4327
4933
  refetch,
4328
4934
  isFetching
4329
- } = (0, import_interface_logic2.useGetSelection)({
4935
+ } = (0, import_interface_logic10.useGetSelection)({
4330
4936
  data,
4331
4937
  queryKey,
4332
4938
  enabled: false
4333
4939
  });
4334
- const selectOptions = (0, import_react4.useMemo)(() => {
4940
+ const selectOptions = (0, import_react12.useMemo)(() => {
4335
4941
  return dataOfSelection?.records?.map((val) => ({
4336
4942
  value: val?.id,
4337
4943
  label: val?.display_name || val?.name
4338
4944
  })) || [];
4339
4945
  }, [dataOfSelection]);
4340
- (0, import_react4.useEffect)(() => {
4946
+ (0, import_react12.useEffect)(() => {
4341
4947
  setOptions(selectOptions);
4342
4948
  setDomainModal(domainObject);
4343
- if (relation === "student.subject") (0, import_interface_logic2.setListSubject)(selectOptions);
4949
+ if (relation === "student.subject") (0, import_interface_logic10.setListSubject)(selectOptions);
4344
4950
  }, [selectOptions]);
4345
- (0, import_react4.useEffect)(() => {
4951
+ (0, import_react12.useEffect)(() => {
4346
4952
  if (!propValue && tempSelectedOption) {
4347
4953
  methods.setValue(name, null);
4348
4954
  setTempSelectedOption(null);
@@ -4353,15 +4959,15 @@ var many2oneFieldController = (props) => {
4353
4959
  });
4354
4960
  }
4355
4961
  }, [propValue]);
4356
- const fetchMoreOptions = (0, import_react4.useCallback)(() => {
4962
+ const fetchMoreOptions = (0, import_react12.useCallback)(() => {
4357
4963
  refetch();
4358
4964
  }, [refetch]);
4359
- (0, import_react4.useEffect)(() => {
4965
+ (0, import_react12.useEffect)(() => {
4360
4966
  if (actionId) {
4361
4967
  localStorage.setItem("aid", actionId);
4362
4968
  }
4363
4969
  }, [actionId]);
4364
- const handleChooseRecord = (0, import_react4.useCallback)(
4970
+ const handleChooseRecord = (0, import_react12.useCallback)(
4365
4971
  (idRecord) => {
4366
4972
  const newOption = options.find(
4367
4973
  (option) => option.value === idRecord
@@ -4386,8 +4992,8 @@ var many2oneFieldController = (props) => {
4386
4992
  },
4387
4993
  [options, methods, name, onChange]
4388
4994
  );
4389
- const handleClose = (0, import_react4.useCallback)(() => setIsShowModalMany2Many(false), []);
4390
- const handleSelectChange = (0, import_react4.useCallback)(
4995
+ const handleClose = (0, import_react12.useCallback)(() => setIsShowModalMany2Many(false), []);
4996
+ const handleSelectChange = (0, import_react12.useCallback)(
4391
4997
  (selectedOption) => {
4392
4998
  if (!selectedOption) {
4393
4999
  methods.setValue(name, null, { shouldDirty: true });
@@ -4437,21 +5043,18 @@ var many2oneFieldController = (props) => {
4437
5043
  };
4438
5044
 
4439
5045
  // src/widget/basic/many2one-button-field/controller.ts
4440
- var import_interface_logic3 = require("@fctc/interface-logic");
4441
- var many2oneButtonController = ({
4442
- relation,
4443
- methods,
4444
- domain
4445
- }) => {
5046
+ var import_interface_logic11 = require("@fctc/interface-logic");
5047
+ var many2oneButtonController = (props) => {
5048
+ const { domain, methods, relation } = props;
4446
5049
  const actionDataString = sessionStorage.getItem("actionData");
4447
- const env = (0, import_interface_logic3.getEnv)();
4448
- const domainObject = (0, import_interface_logic3.evalJSONDomain)(domain, methods?.getValues() || {});
5050
+ const env = (0, import_interface_logic11.getEnv)();
5051
+ const domainObject = (0, import_interface_logic11.evalJSONDomain)(domain, methods?.getValues() || {});
4449
5052
  const actionData = actionDataString && actionDataString !== "undefined" ? JSON.parse(actionDataString) : {};
4450
- const { data: dataOfSelection } = (0, import_interface_logic3.useGetSelection)({
5053
+ const { data: dataOfSelection } = (0, import_interface_logic11.useGetSelection)({
4451
5054
  data: {
4452
5055
  model: relation ?? "",
4453
5056
  domain: domainObject,
4454
- context: { ...env.context, ...(0, import_interface_logic3.evalJSONContext)(actionData?.context) }
5057
+ context: { ...env.context, ...(0, import_interface_logic11.evalJSONContext)(actionData?.context) }
4455
5058
  },
4456
5059
  queryKey: [`data_${relation}`, domainObject]
4457
5060
  });
@@ -4465,26 +5068,15 @@ var many2oneButtonController = ({
4465
5068
  };
4466
5069
 
4467
5070
  // src/widget/basic/many2many-field/controller.ts
4468
- var import_react6 = require("react");
4469
- var import_interface_logic5 = require("@fctc/interface-logic");
5071
+ var import_react14 = require("react");
5072
+ var import_interface_logic13 = require("@fctc/interface-logic");
4470
5073
 
4471
- // src/widget/table/use-table.ts
4472
- var import_interface_logic4 = require("@fctc/interface-logic");
4473
- var import_react5 = require("react");
4474
- function mergeButtons(fields) {
4475
- const buttons = fields?.filter((f) => f.type_co === "button");
4476
- const others = fields?.filter((f) => f.type_co !== "button");
4477
- if (buttons?.length) {
4478
- others.push({
4479
- type_co: "buttons",
4480
- buttons
4481
- });
4482
- }
4483
- return others;
4484
- }
4485
- var useTableHandler = ({ data }) => {
4486
- const [rows, setRows] = (0, import_react5.useState)(data.records || []);
4487
- const [columns, setColumns] = (0, import_react5.useState)([]);
5074
+ // src/widget/advance/table/table-view/controller.ts
5075
+ var import_interface_logic12 = require("@fctc/interface-logic");
5076
+ var import_react13 = require("react");
5077
+ var tableController = ({ data }) => {
5078
+ const [rows, setRows] = (0, import_react13.useState)(data.records || []);
5079
+ const [columns, setColumns] = (0, import_react13.useState)([]);
4488
5080
  const dataModelFields = data.fields?.map((field) => {
4489
5081
  return {
4490
5082
  ...data.dataModel?.[field?.name],
@@ -4512,14 +5104,14 @@ var useTableHandler = ({ data }) => {
4512
5104
  return item.display_name ? { ...transformedItem, item: item.display_name } : transformedItem;
4513
5105
  });
4514
5106
  };
4515
- (0, import_react5.useEffect)(() => {
5107
+ (0, import_react13.useEffect)(() => {
4516
5108
  setRows(transformData(data.records || null));
4517
5109
  }, [data.records]);
4518
5110
  const handleGetColumns = () => {
4519
5111
  let cols = [];
4520
5112
  try {
4521
5113
  cols = mergeFields?.filter((item) => {
4522
- return item?.widget !== "details_Receive_money" && !(item?.column_invisible ? import_interface_logic4.domainHelper.matchDomains(data.context, item?.column_invisible) : item?.invisible ? import_interface_logic4.domainHelper.matchDomains(data.context, item?.invisible) : false);
5114
+ return item?.widget !== "details_Receive_money" && !(item?.column_invisible ? import_interface_logic12.domainHelper.matchDomains(data.context, item?.column_invisible) : item?.invisible ? import_interface_logic12.domainHelper.matchDomains(data.context, item?.invisible) : false);
4523
5115
  })?.map((field) => {
4524
5116
  return {
4525
5117
  name: field?.name,
@@ -4533,7 +5125,7 @@ var useTableHandler = ({ data }) => {
4533
5125
  }
4534
5126
  return cols;
4535
5127
  };
4536
- (0, import_react5.useEffect)(() => {
5128
+ (0, import_react13.useEffect)(() => {
4537
5129
  const columns2 = handleGetColumns();
4538
5130
  setColumns(columns2);
4539
5131
  }, [data.records]);
@@ -4574,17 +5166,14 @@ var many2manyFieldController = (props) => {
4574
5166
  options,
4575
5167
  sessionStorageUtils
4576
5168
  } = props;
4577
- const appDispatch = (0, import_interface_logic5.useAppDispatch)();
5169
+ const appDispatch = (0, import_interface_logic13.useAppDispatch)();
4578
5170
  const actionData = sessionStorageUtils.getActionData();
4579
5171
  const [debouncedPage] = useDebounce(page, 500);
4580
- const [order, setOrder] = (0, import_react6.useState)();
4581
- const [isLoadedData, setIsLoadedData] = (0, import_react6.useState)(false);
4582
- const [domainMany2Many, setDomainMany2Many] = (0, import_react6.useState)(domain);
4583
- const env = (0, import_interface_logic5.getEnv)();
4584
- const {
4585
- // tableHead,
4586
- selectedTags
4587
- } = (0, import_interface_logic5.useAppSelector)(import_interface_logic5.selectSearch);
5172
+ const [order, setOrder] = (0, import_react14.useState)();
5173
+ const [isLoadedData, setIsLoadedData] = (0, import_react14.useState)(false);
5174
+ const [domainMany2Many, setDomainMany2Many] = (0, import_react14.useState)(domain);
5175
+ const env = (0, import_interface_logic13.getEnv)();
5176
+ const { selectedTags } = (0, import_interface_logic13.useAppSelector)(import_interface_logic13.selectSearch);
4588
5177
  const viewParams = {
4589
5178
  model: relation,
4590
5179
  views: [
@@ -4593,11 +5182,11 @@ var many2manyFieldController = (props) => {
4593
5182
  ],
4594
5183
  context
4595
5184
  };
4596
- const { data: viewResponse, isFetched: isViewReponseFetched } = (0, import_interface_logic5.useGetView)(
5185
+ const { data: viewResponse, isFetched: isViewReponseFetched } = (0, import_interface_logic13.useGetView)(
4597
5186
  viewParams,
4598
5187
  actionData
4599
5188
  );
4600
- const baseModel = (0, import_react6.useMemo)(
5189
+ const baseModel = (0, import_react14.useMemo)(
4601
5190
  () => ({
4602
5191
  name: String(relation),
4603
5192
  view: viewResponse || {},
@@ -4609,26 +5198,26 @@ var many2manyFieldController = (props) => {
4609
5198
  }),
4610
5199
  [model, viewResponse]
4611
5200
  );
4612
- const initModel = (0, import_interface_logic5.useModel)();
4613
- const modelInstance = (0, import_react6.useMemo)(() => {
5201
+ const initModel = (0, import_interface_logic13.useModel)();
5202
+ const modelInstance = (0, import_react14.useMemo)(() => {
4614
5203
  if (viewResponse) {
4615
5204
  return initModel.initModel(baseModel);
4616
5205
  }
4617
5206
  return null;
4618
5207
  }, [baseModel, viewResponse]);
4619
- const specification = (0, import_react6.useMemo)(() => {
5208
+ const specification = (0, import_react14.useMemo)(() => {
4620
5209
  if (modelInstance) {
4621
5210
  return modelInstance.getSpecification();
4622
5211
  }
4623
5212
  return null;
4624
5213
  }, [modelInstance]);
4625
5214
  const default_order = viewResponse && viewResponse?.views?.list?.default_order;
4626
- const optionsObject = tab?.options ? (0, import_interface_logic5.evalJSONContext)(tab?.options) : (options ? (0, import_interface_logic5.evalJSONContext)(options) : {}) || {};
5215
+ const optionsObject = tab?.options ? (0, import_interface_logic13.evalJSONContext)(tab?.options) : (options ? (0, import_interface_logic13.evalJSONContext)(options) : {}) || {};
4627
5216
  const fetchData = async () => {
4628
5217
  try {
4629
5218
  setDomainMany2Many(domain);
4630
- appDispatch((0, import_interface_logic5.setFirstDomain)(domain));
4631
- appDispatch((0, import_interface_logic5.setViewDataStore)(viewResponse));
5219
+ appDispatch((0, import_interface_logic13.setFirstDomain)(domain));
5220
+ appDispatch((0, import_interface_logic13.setViewDataStore)(viewResponse));
4632
5221
  const modalData = viewResponse?.views?.list?.fields.map((field) => ({
4633
5222
  ...viewResponse?.models?.[String(model)]?.[field?.name],
4634
5223
  ...field
@@ -4639,7 +5228,7 @@ var many2manyFieldController = (props) => {
4639
5228
  [`${aid}_${relation}_popupmany2many`]: modalData
4640
5229
  });
4641
5230
  }
4642
- appDispatch((0, import_interface_logic5.setPage)(0));
5231
+ appDispatch((0, import_interface_logic13.setPage)(0));
4643
5232
  } catch (err) {
4644
5233
  console.log(err);
4645
5234
  }
@@ -4661,7 +5250,7 @@ var many2manyFieldController = (props) => {
4661
5250
  context,
4662
5251
  fields: groupByDomain?.fields,
4663
5252
  groupby: [groupByDomain?.contexts[0]?.group_by],
4664
- sort: order ? order : default_order ? (0, import_interface_logic5.formatSortingString)(default_order) : ""
5253
+ sort: order ? order : default_order ? (0, import_interface_logic13.formatSortingString)(default_order) : ""
4665
5254
  };
4666
5255
  const enabled = isLoadedData && !!specification && !!relation && !!domainMany2Many && !!viewResponse;
4667
5256
  const {
@@ -4669,24 +5258,24 @@ var many2manyFieldController = (props) => {
4669
5258
  isLoading: isDataLoading,
4670
5259
  isFetched: isDataResponseFetched,
4671
5260
  isPlaceholderData
4672
- } = (0, import_interface_logic5.useGetListData)(data, queryKey, enabled);
4673
- (0, import_react6.useEffect)(() => {
5261
+ } = (0, import_interface_logic13.useGetListData)(data, queryKey, enabled);
5262
+ (0, import_react14.useEffect)(() => {
4674
5263
  if (viewResponse) {
4675
5264
  fetchData();
4676
5265
  }
4677
5266
  return () => {
4678
- appDispatch((0, import_interface_logic5.setGroupByDomain)(null));
5267
+ appDispatch((0, import_interface_logic13.setGroupByDomain)(null));
4679
5268
  setFields((prevFields) => ({
4680
5269
  ...prevFields,
4681
5270
  [`${aid}_${relation}_popupmany2many`]: null
4682
5271
  }));
4683
- appDispatch((0, import_interface_logic5.setPage)(0));
5272
+ appDispatch((0, import_interface_logic13.setPage)(0));
4684
5273
  setSelectedRowKeys([]);
4685
5274
  setDomainMany2Many(null);
4686
5275
  setIsLoadedData(false);
4687
5276
  };
4688
5277
  }, [viewResponse]);
4689
- const { rows, columns, typeTable } = useTableHandler({
5278
+ const { rows, columns, typeTable } = tableController({
4690
5279
  data: {
4691
5280
  fields: fields?.[`${aid}_${relation}_popupmany2many`] || viewResponse?.views?.list?.fields,
4692
5281
  records: dataResponse?.records ?? dataResponse?.groups,
@@ -4704,18 +5293,18 @@ var many2manyFieldController = (props) => {
4704
5293
  refetch,
4705
5294
  data: dataFormViewResponse,
4706
5295
  isSuccess
4707
- } = (0, import_interface_logic5.useGetFormView)({
5296
+ } = (0, import_interface_logic13.useGetFormView)({
4708
5297
  data: dataFormView,
4709
5298
  queryKey: [`form-view-action-${relation}`],
4710
5299
  enabled: false
4711
5300
  });
4712
- (0, import_react6.useEffect)(() => {
5301
+ (0, import_react14.useEffect)(() => {
4713
5302
  if (isSuccess && dataFormViewResponse) {
4714
5303
  sessionStorage.setItem("actionData", JSON.stringify(dataFormViewResponse));
4715
5304
  window.location.href = `/form/menu?model=${relation}`;
4716
5305
  }
4717
5306
  }, [isSuccess]);
4718
- (0, import_react6.useEffect)(() => {
5307
+ (0, import_react14.useEffect)(() => {
4719
5308
  if (domainMany2Many && !isLoadedData) {
4720
5309
  setIsLoadedData(true);
4721
5310
  }
@@ -4727,42 +5316,12 @@ var many2manyFieldController = (props) => {
4727
5316
  console.log(error);
4728
5317
  }
4729
5318
  };
4730
- return {
4731
- rows,
4732
- columns,
4733
- typeTable,
4734
- handleCreateNewOnPage,
4735
- isLoadedData,
4736
- domainMany2Many,
4737
- isDataLoading,
4738
- isDataResponseFetched,
4739
- isPlaceholderData,
4740
- queryKey,
4741
- data,
4742
- specification,
4743
- enabled,
4744
- isViewReponseFetched,
4745
- actionData,
4746
- viewResponse,
4747
- debouncedPage,
4748
- order,
4749
- default_order,
4750
- optionsObject,
4751
- setDomainMany2Many,
4752
- // tableHead,
4753
- selectedTags,
4754
- initModel,
4755
- modelInstance,
4756
- baseModel,
4757
- dataResponse,
4758
- isLoading: isDataLoading,
4759
- setOrder
4760
- };
5319
+ return {};
4761
5320
  };
4762
5321
 
4763
5322
  // src/widget/basic/many2many-tags-field/controller.ts
4764
- var import_react7 = require("react");
4765
- var import_interface_logic6 = require("@fctc/interface-logic");
5323
+ var import_react15 = require("react");
5324
+ var import_interface_logic14 = require("@fctc/interface-logic");
4766
5325
  var many2manyTagsController = (props) => {
4767
5326
  const {
4768
5327
  relation,
@@ -4773,10 +5332,10 @@ var many2manyTagsController = (props) => {
4773
5332
  placeholderNoOption
4774
5333
  } = props;
4775
5334
  const isUser = relation === "res.users" || relation === "res.partner";
4776
- const env = (0, import_interface_logic6.getEnv)();
4777
- const addtionalFields = optionsFields ? (0, import_interface_logic6.evalJSONContext)(optionsFields) : null;
4778
- const domainObject = (0, import_react7.useMemo)(
4779
- () => (0, import_interface_logic6.evalJSONDomain)(domain, JSON.parse(JSON.stringify(formValues || {}))),
5335
+ const env = (0, import_interface_logic14.getEnv)();
5336
+ const addtionalFields = optionsFields ? (0, import_interface_logic14.evalJSONContext)(optionsFields) : null;
5337
+ const domainObject = (0, import_react15.useMemo)(
5338
+ () => (0, import_interface_logic14.evalJSONDomain)(domain, JSON.parse(JSON.stringify(formValues || {}))),
4780
5339
  [domain, formValues]
4781
5340
  );
4782
5341
  const data = {
@@ -4786,13 +5345,13 @@ var many2manyTagsController = (props) => {
4786
5345
  id: {},
4787
5346
  name: {},
4788
5347
  display_name: {},
4789
- ...widget && import_interface_logic6.WIDGETAVATAR[widget] ? { image_256: {} } : {},
4790
- ...widget && import_interface_logic6.WIDGETCOLOR[widget] && addtionalFields?.color_field ? { color: {} } : {}
5348
+ ...widget && import_interface_logic14.WIDGETAVATAR[widget] ? { image_256: {} } : {},
5349
+ ...widget && import_interface_logic14.WIDGETCOLOR[widget] && addtionalFields?.color_field ? { color: {} } : {}
4791
5350
  },
4792
5351
  enabled: true,
4793
5352
  context: env.context
4794
5353
  };
4795
- const { data: dataOfSelection } = (0, import_interface_logic6.useGetSelection)({
5354
+ const { data: dataOfSelection } = (0, import_interface_logic14.useGetSelection)({
4796
5355
  data,
4797
5356
  queryKey: [`data_${relation}`, domainObject]
4798
5357
  });
@@ -4818,8 +5377,8 @@ var many2manyTagsController = (props) => {
4818
5377
  };
4819
5378
 
4820
5379
  // src/widget/basic/status-bar-field/controller.ts
4821
- var import_react8 = require("react");
4822
- var import_interface_logic7 = require("@fctc/interface-logic");
5380
+ var import_react16 = require("react");
5381
+ var import_interface_logic15 = require("@fctc/interface-logic");
4823
5382
  var durationController = (props) => {
4824
5383
  const {
4825
5384
  relation,
@@ -4836,14 +5395,14 @@ var durationController = (props) => {
4836
5395
  name: "",
4837
5396
  fold: ""
4838
5397
  };
4839
- const [disabled, setDisabled] = (0, import_react8.useState)(false);
4840
- const [modelStatus, setModalStatus] = (0, import_react8.useState)(false);
4841
- const { context } = (0, import_interface_logic7.useAppSelector)(import_interface_logic7.selectEnv);
5398
+ const [disabled, setDisabled] = (0, import_react16.useState)(false);
5399
+ const [modelStatus, setModalStatus] = (0, import_react16.useState)(false);
5400
+ const { context } = (0, import_interface_logic15.useAppSelector)(import_interface_logic15.selectEnv);
4842
5401
  const queryKey = [`data-status-duration`, specification];
4843
5402
  const listDataProps = {
4844
5403
  model: relation,
4845
5404
  specification,
4846
- domain: (0, import_interface_logic7.evalJSONDomain)(domain, JSON.parse(JSON.stringify(formValues))),
5405
+ domain: (0, import_interface_logic15.evalJSONDomain)(domain, JSON.parse(JSON.stringify(formValues))),
4847
5406
  limit: 10,
4848
5407
  offset: 0,
4849
5408
  fields: "",
@@ -4853,8 +5412,8 @@ var durationController = (props) => {
4853
5412
  },
4854
5413
  sort: ""
4855
5414
  };
4856
- const { data: dataResponse } = (0, import_interface_logic7.useGetListData)(listDataProps, queryKey);
4857
- const { mutate: fetchChangeStatus } = (0, import_interface_logic7.useChangeStatus)();
5415
+ const { data: dataResponse } = (0, import_interface_logic15.useGetListData)(listDataProps, queryKey);
5416
+ const { mutate: fetchChangeStatus } = (0, import_interface_logic15.useChangeStatus)();
4858
5417
  const handleClick = async (stage_id) => {
4859
5418
  setDisabled(true);
4860
5419
  if (stage_id) {
@@ -4890,26 +5449,26 @@ var durationController = (props) => {
4890
5449
  };
4891
5450
 
4892
5451
  // src/widget/basic/priority-field/controller.ts
4893
- var import_interface_logic8 = require("@fctc/interface-logic");
5452
+ var import_interface_logic16 = require("@fctc/interface-logic");
4894
5453
  var priorityFieldController = (props) => {
4895
5454
  const {
4896
5455
  value,
4897
- selection,
4898
5456
  isForm,
4899
5457
  name,
4900
5458
  methods,
4901
- id,
4902
5459
  onChange,
4903
5460
  model,
5461
+ selection,
5462
+ id,
4904
5463
  actionData,
4905
5464
  viewData,
4906
5465
  context
4907
5466
  } = props;
4908
- const _context = { ...(0, import_interface_logic8.evalJSONContext)(actionData?.context) };
5467
+ const _context = { ...(0, import_interface_logic16.evalJSONContext)(actionData?.context) };
4909
5468
  const contextObject = { ...context, ..._context };
4910
5469
  const defaultPriority = parseInt(value) + 1;
4911
5470
  const label = viewData?.models?.[model]?.[name ?? ""]?.string ?? name;
4912
- const { mutateAsync: fetchSave } = (0, import_interface_logic8.useSave)();
5471
+ const { mutateAsync: fetchSave } = (0, import_interface_logic16.useSave)();
4913
5472
  const savePriorities = async ({
4914
5473
  value: value2,
4915
5474
  resetPriority
@@ -4944,8 +5503,8 @@ var priorityFieldController = (props) => {
4944
5503
  };
4945
5504
 
4946
5505
  // src/widget/basic/float-time-field/controller.ts
4947
- var import_react9 = require("react");
4948
- var import_interface_logic9 = require("@fctc/interface-logic");
5506
+ var import_react17 = require("react");
5507
+ var import_interface_logic17 = require("@fctc/interface-logic");
4949
5508
  var floatTimeFiledController = ({
4950
5509
  onChange: fieldOnChange,
4951
5510
  onBlur,
@@ -4954,11 +5513,11 @@ var floatTimeFiledController = ({
4954
5513
  props
4955
5514
  }) => {
4956
5515
  const { name, defaultValue = 0, onChange } = props;
4957
- const [input, setInput] = (0, import_react9.useState)(
4958
- (0, import_interface_logic9.convertFloatToTime)(value ?? defaultValue)
5516
+ const [input, setInput] = (0, import_react17.useState)(
5517
+ (0, import_interface_logic17.convertFloatToTime)(value ?? defaultValue)
4959
5518
  );
4960
- const [formattedTime, setFormattedTime] = (0, import_react9.useState)("");
4961
- const [errors, setErrors] = (0, import_react9.useState)("");
5519
+ const [formattedTime, setFormattedTime] = (0, import_react17.useState)("");
5520
+ const [errors, setErrors] = (0, import_react17.useState)("");
4962
5521
  const handleInputChange = (e) => {
4963
5522
  const raw = e.target.value.replace(/[^\d:]/g, "");
4964
5523
  setInput(raw);
@@ -4988,7 +5547,7 @@ var floatTimeFiledController = ({
4988
5547
  if (!isDirty) return;
4989
5548
  if (formattedTime) {
4990
5549
  setInput(formattedTime);
4991
- const floatVal = (0, import_interface_logic9.convertTimeToFloat)(formattedTime);
5550
+ const floatVal = (0, import_interface_logic17.convertTimeToFloat)(formattedTime);
4992
5551
  fieldOnChange(floatVal);
4993
5552
  if (onChange) {
4994
5553
  onChange(name ?? "", floatVal);
@@ -5031,7 +5590,31 @@ var floatTimeFiledController = ({
5031
5590
  };
5032
5591
 
5033
5592
  // src/widget/basic/float-field/controller.ts
5034
- var import_react10 = require("react");
5593
+ var import_react18 = require("react");
5594
+
5595
+ // src/utils/i18n.ts
5596
+ var import_react_i18next2 = require("react-i18next");
5597
+ var import_i18next = __toESM(require("i18next"));
5598
+ var import_i18next_browser_languagedetector = __toESM(require("i18next-browser-languagedetector"));
5599
+ import_i18next.default.use(import_i18next_browser_languagedetector.default).use(import_react_i18next2.initReactI18next).init({
5600
+ resources: {
5601
+ vi: { translation: vi },
5602
+ en: { translation: en }
5603
+ },
5604
+ fallbackLng: "vi",
5605
+ lng: "vi_VN",
5606
+ debug: false,
5607
+ nonExplicitSupportedLngs: true,
5608
+ interpolation: {
5609
+ escapeValue: false
5610
+ },
5611
+ detection: {
5612
+ caches: ["cookie"]
5613
+ }
5614
+ });
5615
+ var i18n_default = import_i18next.default;
5616
+
5617
+ // src/widget/basic/float-field/controller.ts
5035
5618
  var floatController = ({
5036
5619
  onChange,
5037
5620
  value,
@@ -5039,10 +5622,10 @@ var floatController = ({
5039
5622
  }) => {
5040
5623
  const { name, required, methods, onChange: handleOnchange, string } = props;
5041
5624
  const { setError, clearErrors } = methods;
5042
- const [inputValue, setInputValue] = (0, import_react10.useState)(
5625
+ const [inputValue, setInputValue] = (0, import_react18.useState)(
5043
5626
  value !== void 0 && value !== null ? useFormatFloatNumber(value) : ""
5044
5627
  );
5045
- (0, import_react10.useEffect)(() => {
5628
+ (0, import_react18.useEffect)(() => {
5046
5629
  if (value !== void 0 && value !== null && value !== parseFloat(inputValue?.replace(/,/g, ""))) {
5047
5630
  setInputValue(useFormatFloatNumber(value));
5048
5631
  clearErrors(name);
@@ -5050,9 +5633,9 @@ var floatController = ({
5050
5633
  setInputValue("");
5051
5634
  }
5052
5635
  }, [value, name, clearErrors]);
5053
- const isDirtyRef = (0, import_react10.useRef)(false);
5054
- const inputRef = (0, import_react10.useRef)(null);
5055
- const lastCommittedValueRef = (0, import_react10.useRef)(null);
5636
+ const isDirtyRef = (0, import_react18.useRef)(false);
5637
+ const inputRef = (0, import_react18.useRef)(null);
5638
+ const lastCommittedValueRef = (0, import_react18.useRef)(null);
5056
5639
  const handleInputChange = (e) => {
5057
5640
  const newValue = e.target.value;
5058
5641
  const valueWithoutCommas = newValue.replace(/,/g, "");
@@ -5070,8 +5653,8 @@ var floatController = ({
5070
5653
  if (!isNaN(parsedValue)) {
5071
5654
  if (parsedValue < 0) {
5072
5655
  setError(name, {
5073
- type: "validate"
5074
- // message: i18n.t('invalid_number'),
5656
+ type: "validate",
5657
+ message: i18n_default.t("invalid_number")
5075
5658
  });
5076
5659
  } else {
5077
5660
  onChange(parsedValue);
@@ -5094,8 +5677,8 @@ var floatController = ({
5094
5677
  if (rawValue === "" || rawValue === ".") {
5095
5678
  if (required) {
5096
5679
  setError(name, {
5097
- type: "required"
5098
- // message: `${string} ${t('must_required')}`,
5680
+ type: "required",
5681
+ message: `${string} ${i18n_default.t("must_required")}`
5099
5682
  });
5100
5683
  }
5101
5684
  onChange(null);
@@ -5104,8 +5687,8 @@ var floatController = ({
5104
5687
  } else if (!isNaN(parsedValue)) {
5105
5688
  if (parsedValue < 0) {
5106
5689
  setError(name, {
5107
- type: "validate"
5108
- // message: i18n.t('invalid_number'),
5690
+ type: "validate",
5691
+ message: i18n_default.t("invalid_number")
5109
5692
  });
5110
5693
  setInputValue("");
5111
5694
  lastCommittedValueRef.current = null;
@@ -5125,8 +5708,8 @@ var floatController = ({
5125
5708
  }
5126
5709
  } else {
5127
5710
  setError(name, {
5128
- type: "validate"
5129
- // message: i18n.t('invalid_number'),
5711
+ type: "validate",
5712
+ message: i18n_default.t("invalid_number")
5130
5713
  });
5131
5714
  setInputValue("");
5132
5715
  lastCommittedValueRef.current = null;
@@ -5153,10 +5736,10 @@ var useFormatFloatNumber = (value) => {
5153
5736
  };
5154
5737
 
5155
5738
  // src/widget/basic/download-file-field/controller.ts
5156
- var import_react11 = require("react");
5739
+ var import_react19 = require("react");
5157
5740
  var downloadFileController = () => {
5158
- const inputId = (0, import_react11.useId)();
5159
- const [file, setFile] = (0, import_react11.useState)(null);
5741
+ const inputId = (0, import_react19.useId)();
5742
+ const [file, setFile] = (0, import_react19.useState)(null);
5160
5743
  const handleFileChange = (e) => {
5161
5744
  setFile(e.target.files[0]);
5162
5745
  };
@@ -5224,8 +5807,8 @@ var dateFieldController = (props) => {
5224
5807
  widget,
5225
5808
  min,
5226
5809
  max,
5227
- formValues,
5228
5810
  viewData,
5811
+ formValues,
5229
5812
  model
5230
5813
  } = props;
5231
5814
  const range = (start, end, step = 1) => {
@@ -5280,18 +5863,30 @@ var dateFieldController = (props) => {
5280
5863
  const compareNow = showTime ? now : now.clone().startOf("day");
5281
5864
  if (minNowValue) {
5282
5865
  if (compareSelected.isBefore(compareNow) && typeof minNowValue === "boolean" && minNowValue === true) {
5866
+ return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
5867
+ "greater_or_equal_now"
5868
+ )}`;
5283
5869
  } else if (import_moment.default.isMoment(minNowValue)) {
5284
5870
  const compareMin = showTime ? minNowValue : minNowValue.clone().startOf("day");
5285
5871
  if (compareSelected.isBefore(compareMin)) {
5286
5872
  const fieldRelationDate = viewData?.models?.[model]?.[min ?? ""];
5873
+ return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
5874
+ "greater_or_equal"
5875
+ )} ${fieldRelationDate?.string}`;
5287
5876
  }
5288
5877
  }
5289
5878
  } else if (maxNowValue) {
5290
5879
  if (compareSelected.isAfter(compareNow) && typeof maxNowValue === "boolean" && maxNowValue === true) {
5880
+ return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
5881
+ "less_or_equal_now"
5882
+ )}`;
5291
5883
  } else if (import_moment.default.isMoment(maxNowValue)) {
5292
5884
  const compareMax = showTime ? maxNowValue : maxNowValue.clone().startOf("day");
5293
5885
  if (compareSelected.isAfter(compareMax)) {
5294
5886
  const fieldRelationDate = viewData?.models?.[model]?.[max ?? ""];
5887
+ return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
5888
+ "less_or_equal"
5889
+ )} ${fieldRelationDate?.string}`;
5295
5890
  }
5296
5891
  }
5297
5892
  }
@@ -5313,14 +5908,14 @@ var dateFieldController = (props) => {
5313
5908
  };
5314
5909
  };
5315
5910
 
5316
- // src/widget/basic/copy-link-buttton/controller.ts
5317
- var import_react12 = require("react");
5318
- var import_interface_logic10 = require("@fctc/interface-logic");
5911
+ // src/widget/basic/copy-link-button/controller.ts
5912
+ var import_react20 = require("react");
5913
+ var import_interface_logic18 = require("@fctc/interface-logic");
5319
5914
  var copyLinkButtonController = (props) => {
5320
5915
  const { value, defaultValue } = props;
5321
- const [isCopied, setIsCopied] = (0, import_react12.useState)(false);
5916
+ const [isCopied, setIsCopied] = (0, import_react20.useState)(false);
5322
5917
  const handleCopyToClipboard = async (value2) => {
5323
- await (0, import_interface_logic10.copyTextToClipboard)(value2);
5918
+ await (0, import_interface_logic18.copyTextToClipboard)(value2);
5324
5919
  setIsCopied(true);
5325
5920
  setTimeout(() => setIsCopied(false), 2e3);
5326
5921
  };
@@ -5332,49 +5927,15 @@ var copyLinkButtonController = (props) => {
5332
5927
  };
5333
5928
  };
5334
5929
 
5335
- // src/widget/basic/color-field/color-wrapper-controller.ts
5336
- var import_react13 = require("react");
5337
- var colorWrapperController = (props) => {
5338
- const { savePickColor, defaultColor, colors } = props;
5339
- const [selectedColor, setSelectedColor] = (0, import_react13.useState)(colors[defaultColor]);
5340
- const [showFullColors, setIsShowFullColor] = (0, import_react13.useState)(false);
5341
- (0, import_react13.useEffect)(() => {
5342
- setSelectedColor(colors[defaultColor]);
5343
- }, [defaultColor]);
5344
- const handleShowFullColors = () => {
5345
- setIsShowFullColor(!showFullColors);
5346
- };
5347
- const pickColorsRef = (0, import_react13.useRef)(null);
5348
- (0, import_react13.useEffect)(() => {
5349
- const handleClickOutside = (event) => {
5350
- if (pickColorsRef.current && !pickColorsRef.current.contains(event.target)) {
5351
- setIsShowFullColor(false);
5352
- }
5353
- };
5354
- document.addEventListener("mousedown", handleClickOutside);
5355
- return () => {
5356
- document.removeEventListener("mousedown", handleClickOutside);
5357
- };
5358
- }, []);
5359
- return {
5360
- selectedColor,
5361
- showFullColors,
5362
- setSelectedColor,
5363
- handleShowFullColors,
5364
- pickColorsRef,
5365
- savePickColor
5366
- };
5367
- };
5368
-
5369
5930
  // src/widget/basic/color-field/color-controller.ts
5370
- var import_interface_logic11 = require("@fctc/interface-logic");
5931
+ var import_interface_logic19 = require("@fctc/interface-logic");
5371
5932
  var colorFieldController = (props) => {
5372
5933
  const { value, isForm, name, formValues, idForm, model, actionData } = props;
5373
- const env = (0, import_interface_logic11.getEnv)();
5374
- const _context = { ...(0, import_interface_logic11.evalJSONContext)(actionData?.context) || {} };
5934
+ const env = (0, import_interface_logic19.getEnv)();
5935
+ const _context = { ...(0, import_interface_logic19.evalJSONContext)(actionData?.context) || {} };
5375
5936
  const contextObject = { ...env.context, ..._context };
5376
5937
  const idDefault = isForm ? idForm : formValues?.id;
5377
- const { mutate: onSave } = (0, import_interface_logic11.useSave)();
5938
+ const { mutate: onSave } = (0, import_interface_logic19.useSave)();
5378
5939
  const savePickColor = async (colorObject) => {
5379
5940
  const { id } = colorObject;
5380
5941
  if (value === id) return;
@@ -5399,16 +5960,16 @@ var colorFieldController = (props) => {
5399
5960
  };
5400
5961
 
5401
5962
  // src/widget/basic/binary-field/controller.ts
5402
- var import_react14 = require("react");
5403
- var import_interface_logic12 = require("@fctc/interface-logic");
5963
+ var import_react21 = require("react");
5964
+ var import_interface_logic20 = require("@fctc/interface-logic");
5404
5965
  var binaryFieldController = (props) => {
5405
5966
  const { name, methods, readonly = false, value } = props;
5406
- const inputId = (0, import_react14.useId)();
5407
- const [selectedImage, setSelectedImage] = (0, import_react14.useState)(null);
5408
- const [initialImage, setInitialImage] = (0, import_react14.useState)(value || null);
5409
- const [isInsideTable, setIsInsideTable] = (0, import_react14.useState)(false);
5967
+ const inputId = (0, import_react21.useId)();
5968
+ const [selectedImage, setSelectedImage] = (0, import_react21.useState)(null);
5969
+ const [initialImage, setInitialImage] = (0, import_react21.useState)(value || null);
5970
+ const [isInsideTable, setIsInsideTable] = (0, import_react21.useState)(false);
5410
5971
  const { setValue } = methods;
5411
- const binaryRef = (0, import_react14.useRef)(null);
5972
+ const binaryRef = (0, import_react21.useRef)(null);
5412
5973
  const convertUrlToBase64 = async (url) => {
5413
5974
  try {
5414
5975
  const response = await fetch(url);
@@ -5457,11 +6018,11 @@ var binaryFieldController = (props) => {
5457
6018
  };
5458
6019
  const checkIsImageLink = (url) => {
5459
6020
  const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|ico)$/i;
5460
- return imageExtensions.test(url) || (0, import_interface_logic12.isBase64Image)(url) || isBlobUrl(url);
6021
+ return imageExtensions.test(url) || (0, import_interface_logic20.isBase64Image)(url) || isBlobUrl(url);
5461
6022
  };
5462
6023
  const getImageBase64WithMimeType = (base64) => {
5463
6024
  if (typeof base64 !== "string" || base64.length < 10) return null;
5464
- if ((0, import_interface_logic12.isBase64Image)(base64)) return base64;
6025
+ if ((0, import_interface_logic20.isBase64Image)(base64)) return base64;
5465
6026
  let mimeType = null;
5466
6027
  if (base64.startsWith("iVBORw0KGgo")) mimeType = "image/png";
5467
6028
  else if (base64.startsWith("/9j/")) mimeType = "image/jpeg";
@@ -5470,14 +6031,14 @@ var binaryFieldController = (props) => {
5470
6031
  else if (base64.startsWith("UklGR")) mimeType = "image/webp";
5471
6032
  return mimeType ? `data:${mimeType};base64,${base64}` : null;
5472
6033
  };
5473
- (0, import_react14.useEffect)(() => {
6034
+ (0, import_react21.useEffect)(() => {
5474
6035
  return () => {
5475
6036
  if (selectedImage) {
5476
6037
  URL.revokeObjectURL(selectedImage);
5477
6038
  }
5478
6039
  };
5479
6040
  }, [selectedImage]);
5480
- (0, import_react14.useEffect)(() => {
6041
+ (0, import_react21.useEffect)(() => {
5481
6042
  if (binaryRef.current) {
5482
6043
  const isInsideTable2 = !!binaryRef.current.closest("table");
5483
6044
  setIsInsideTable(isInsideTable2);
@@ -5495,296 +6056,49 @@ var binaryFieldController = (props) => {
5495
6056
  getImageBase64WithMimeType
5496
6057
  };
5497
6058
  };
5498
-
5499
- // src/widget/common/modal-layer.tsx
5500
- var import_react15 = require("react");
5501
- var import_react16 = require("@headlessui/react");
5502
- var import_jsx_runtime4 = require("react/jsx-runtime");
5503
- var ModalLayer = ({
5504
- isOpen,
5505
- onClose,
5506
- title,
5507
- children
5508
- }) => {
5509
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
5510
- import_react16.Transition,
5511
- {
5512
- show: isOpen,
5513
- enter: "transition duration-100 ease-out",
5514
- enterFrom: "transform scale-95 opacity-0",
5515
- enterTo: "transform scale-100 opacity-100",
5516
- leave: "transition duration-75 ease-out",
5517
- leaveFrom: "transform scale-100 opacity-100",
5518
- leaveTo: "transform scale-95 opacity-0",
5519
- as: import_react15.Fragment,
5520
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react16.Dialog, { onClose, "aria-labelledby": "modal-title", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react16.DialogPanel, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "fixed bottom-0 left-0 right-0 top-0 z-[500]", children: [
5521
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "absolute inset-0 bg-[rgba(27,27,27,0.48)]" }),
5522
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex items-center justify-center mx-4 absolute inset-0 overflow-auto", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: " relative z-[1] mx-auto my-[88px] p-4 flex flex-col gap-2 max-w-[1000px] transform rounded-xl bg-[#FFF]", children: [
5523
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
5524
- "div",
5525
- {
5526
- className: `flex justify-between items-center border-[rgba(0,0,0,0.1)] pb-2`,
5527
- children: [
5528
- title && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { id: "modal-title", className: "text-[20px] font-semibold", children: title }),
5529
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
5530
- "button",
5531
- {
5532
- onClick: onClose,
5533
- "aria-label": "Close",
5534
- className: "ml-auto absolute top-[16px] right-[16px] !cursor-pointer",
5535
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CloseIcon, {})
5536
- }
5537
- )
5538
- ]
5539
- }
5540
- ),
5541
- children
5542
- ] }) })
5543
- ] }) }) })
5544
- }
5545
- );
5546
- };
5547
-
5548
- // src/widget/common/modal-confirm.tsx
5549
- var import_jsx_runtime5 = require("react/jsx-runtime");
5550
- var ModalConfirm = ({
5551
- name,
5552
- isShowModal,
5553
- onClick,
5554
- onClose,
5555
- title,
5556
- content,
5557
- isLoading
5558
- }) => {
5559
- const renderButtonAction = (name2) => {
5560
- switch (name2) {
5561
- case "duplicate":
5562
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5563
- "button",
5564
- {
5565
- type: "button",
5566
- onClick,
5567
- className: "button-primary flex-1 cursor-pointer flex items-center justify-center gap-2",
5568
- disabled: isLoading,
5569
- children: isLoading && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(LoadingIcon, {})
5570
- }
5571
- );
5572
- case "archive":
5573
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5574
- "button",
5575
- {
5576
- type: "button",
5577
- onClick,
5578
- className: "button-primary flex-1 cursor-pointer flex items-center justify-center gap-2",
5579
- disabled: isLoading,
5580
- children: isLoading && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(LoadingIcon, {})
5581
- }
5582
- );
5583
- case "unarchive":
5584
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5585
- "button",
5586
- {
5587
- type: "button",
5588
- onClick,
5589
- className: "button-primary flex-1 cursor-pointer flex items-center justify-center gap-2",
5590
- disabled: isLoading,
5591
- children: isLoading && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(LoadingIcon, {})
5592
- }
5593
- );
5594
- case "delete":
5595
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5596
- "button",
5597
- {
5598
- type: "button",
5599
- onClick,
5600
- className: "button-primary flex-1 flex items-center justify-center gap-2",
5601
- disabled: isLoading,
5602
- children: isLoading && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(LoadingIcon, {})
5603
- }
5604
- );
5605
- default:
5606
- break;
5607
- }
5608
- };
5609
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ModalLayer, { isOpen: isShowModal, onClose, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-auto flex flex-col items-center justify-center gap-4", children: [
5610
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col gap-[4px] items-center", children: [
5611
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-[18px] font-bold", children: title }),
5612
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[16px]", children: content })
5613
- ] }),
5614
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex justify-center items-center gap-2 w-full", children: [
5615
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5616
- "button",
5617
- {
5618
- type: "button",
5619
- onClick: onClose,
5620
- className: "button-secondary flex-1 cursor-pointer"
5621
- }
5622
- ),
5623
- renderButtonAction(name)
5624
- ] })
5625
- ] }) });
5626
- };
5627
-
5628
- // src/widget/common/modal-detail.tsx
5629
- var import_react17 = require("react");
5630
- var import_react_dom = require("react-dom");
5631
- var import_react_tooltip = require("react-tooltip");
5632
- var import_interface_logic13 = require("@fctc/interface-logic");
5633
- var import_jsx_runtime6 = require("react/jsx-runtime");
5634
- var ModalDetail = ({
5635
- idToolTip,
5636
- title,
5637
- model,
5638
- idForm,
5639
- aid,
5640
- place,
5641
- renderDetail,
5642
- context
5643
- }) => {
5644
- const [showModalDetail, setShowModalDetail] = (0, import_react17.useState)(false);
5645
- const [actionData, setActionData] = (0, import_react17.useState)();
5646
- const { isShowingModalDetail } = (0, import_interface_logic13.useAppSelector)(import_interface_logic13.selectForm);
5647
- const appDispatch = (0, import_interface_logic13.useAppDispatch)();
5648
- const handleToggleModal = (e) => {
5649
- e.stopPropagation();
5650
- setShowModalDetail(!showModalDetail);
5651
- appDispatch((0, import_interface_logic13.setIsShowingModalDetail)(!isShowingModalDetail));
5652
- };
5653
- const handleNavigateDetail = () => {
5654
- sessionStorage.setItem("actionData", JSON.stringify(actionData));
5655
- (0, import_interface_logic13.setIsShowingModalDetail)(!isShowingModalDetail);
5656
- window.location.href = `/form/menu?model=${model}&id=${idForm}`;
5657
- };
5658
- return (0, import_react_dom.createPortal)(
5659
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
5660
- !isShowingModalDetail && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5661
- import_react_tooltip.Tooltip,
5662
- {
5663
- opacity: 1,
5664
- className: "z-[99999] ",
5665
- place,
5666
- id: idToolTip,
5667
- clickable: true,
5668
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
5669
- "button",
5670
- {
5671
- className: "flex gap-2 cursor-pointer items-center justify-center rounded-lg",
5672
- type: "button",
5673
- onClick: handleToggleModal,
5674
- children: [
5675
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(EyeIcon, {}),
5676
- title
5677
- ]
5678
- }
5679
- )
5680
- }
5681
- ),
5682
- showModalDetail && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "fixed bottom-0 left-0 right-0 top-0 z-[100]", children: [
5683
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "absolute inset-0 bg-[rgba(27,27,27,0.48)]" }),
5684
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "absolute inset-0 overflow-auto flex flex-col justify-center items-center px-5", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "relative z-[1] max-w-full p-4 flex flex-col gap-4 w-[1000px] transform rounded-3xl bg-[#FFF] h-[90%]", children: [
5685
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex justify-between items-center border-b border-[rgba(0,0,0,0.1)] pb-2", children: [
5686
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5687
- "div",
5688
- {
5689
- id: "modal-detail",
5690
- className: "text-[20px] cursor-pointer font-semibold flex items-stretch gap-2",
5691
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5692
- "button",
5693
- {
5694
- onClick: handleNavigateDetail,
5695
- className: "text-sm italic text-primary underline cursor-pointer",
5696
- children: title
5697
- }
5698
- )
5699
- }
5700
- ),
5701
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: handleToggleModal, className: "cursor-pointer", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CloseIcon, { className: "h-5 w-5" }) })
5702
- ] }),
5703
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex-1 overflow-auto", children: typeof renderDetail === "function" && renderDetail({
5704
- id: idForm,
5705
- aid,
5706
- model,
5707
- setActionData,
5708
- context
5709
- }) })
5710
- ] }) })
5711
- ] })
5712
- ] }),
5713
- document.body
5714
- );
5715
- };
5716
-
5717
- // src/widget/common/loading-normal.tsx
5718
- var import_react18 = require("react");
5719
- var import_jsx_runtime7 = require("react/jsx-runtime");
5720
- var LayerLoading = () => {
5721
- const [activeIndex, setActiveIndex] = (0, import_react18.useState)(0);
5722
- (0, import_react18.useEffect)(() => {
5723
- const interval = setInterval(() => {
5724
- setActiveIndex((prevIndex) => (prevIndex + 1) % 6);
5725
- }, 200);
5726
- return () => clearInterval(interval);
5727
- }, []);
5728
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "my-auto flex-1 h-full flex justify-center items-center", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex justify-center items-center", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex justify-center flex-col items-center gap-12", children: [
5729
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "loading-container", children: [...Array(6)].map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5730
- "div",
5731
- {
5732
- className: `loading-item ${index === activeIndex ? "active" : ""}`
5733
- },
5734
- index
5735
- )) }),
5736
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-[rgba(45,45,45,1)] text-xl font-semibold tracking-[-1%]" })
5737
- ] }) }) });
5738
- };
5739
-
5740
- // src/widget/common/loading-small.tsx
5741
- var import_react19 = require("react");
5742
- var import_jsx_runtime8 = require("react/jsx-runtime");
5743
- var LoadingSmall = () => {
5744
- const [activeIndex, setActiveIndex] = (0, import_react19.useState)(0);
5745
- (0, import_react19.useEffect)(() => {
5746
- const interval = setInterval(() => {
5747
- setActiveIndex((prevIndex) => (prevIndex + 1) % 6);
5748
- }, 200);
5749
- return () => clearInterval(interval);
5750
- }, []);
5751
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "my-auto flex-1 h-full flex justify-center items-center", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex justify-center items-center", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex justify-center flex-col items-center gap-12", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "loading-container-small", children: [...Array(4)].map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5752
- "div",
5753
- {
5754
- className: `loading-item-small ${index === activeIndex ? "active" : ""}`
5755
- },
5756
- index
5757
- )) }) }) }) });
5758
- };
5759
6059
  // Annotate the CommonJS export names for ESM import in node:
5760
6060
  0 && (module.exports = {
6061
+ API_APP_URL,
6062
+ API_PRESCHOOL_URL,
5761
6063
  CloseIcon,
5762
6064
  EyeIcon,
5763
- LayerLoading,
5764
6065
  LoadingIcon,
5765
- LoadingSmall,
5766
- ModalConfirm,
5767
- ModalDetail,
5768
- ModalLayer,
6066
+ STORAGES,
5769
6067
  binaryFieldController,
5770
6068
  colorFieldController,
5771
- colorWrapperController,
6069
+ combineContexts,
6070
+ convertFieldsToArray,
5772
6071
  copyLinkButtonController,
6072
+ countSum,
5773
6073
  dateFieldController,
5774
6074
  downLoadBinaryController,
5775
6075
  downloadFileController,
5776
6076
  durationController,
5777
6077
  floatController,
5778
6078
  floatTimeFiledController,
6079
+ getDateRange,
6080
+ languages,
5779
6081
  many2manyFieldController,
5780
6082
  many2manyTagsController,
5781
6083
  many2oneButtonController,
5782
6084
  many2oneFieldController,
6085
+ mergeButtons,
5783
6086
  priorityFieldController,
6087
+ setStorageItemAsync,
5784
6088
  statusDropdownController,
6089
+ useAuth,
6090
+ useCallAction,
5785
6091
  useClickOutside,
6092
+ useConfig,
5786
6093
  useDebounce,
5787
- useTableHandler
6094
+ useDetail,
6095
+ useGetRowIds,
6096
+ useListData,
6097
+ useMenu,
6098
+ useProfile,
6099
+ useStorageState,
6100
+ useUser,
6101
+ useViewV2
5788
6102
  });
5789
6103
  /*! Bundled license information:
5790
6104