sevago-sso-fe 1.0.31 → 1.0.33

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.cjs.js CHANGED
@@ -21750,9 +21750,6 @@ const ErrorPage = ({}) => {
21750
21750
  type: LogoutType.THIS_DEVICE,
21751
21751
  refreshToken: account.refreshToken
21752
21752
  })
21753
- ).unwrap(),
21754
- dispatch(
21755
- ACTION_ACCOUNT.unsubscribeTopic({ fcmToken: account.fcmToken })
21756
21753
  ).unwrap()
21757
21754
  ]);
21758
21755
  navigate(PAGE.AUTH.path);
@@ -21786,781 +21783,91 @@ const NotFoundPage = ({}) => {
21786
21783
  /* @__PURE__ */ jsxRuntime.jsx(ButtonElement, { content: "Quay lại trang chủ", fullWidth: false, onClick: () => navigate(PAGE.AUTH.path) })
21787
21784
  ] });
21788
21785
  };
21789
- const ArrowTooltip = emStyled(({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(material.Tooltip, { ...props, arrow: true, classes: { popper: className } }))(() => ({
21790
- [`& .${material.tooltipClasses.arrow}`]: {
21791
- color: "white"
21792
- }
21793
- }));
21794
- const AvatarElement = ({
21795
- url: url2,
21796
- sx = {},
21797
- size = "medium",
21798
- tooltipContent,
21799
- ...rest
21800
- }) => {
21801
- if (tooltipContent) {
21802
- return /* @__PURE__ */ jsxRuntime.jsx(ArrowTooltip, { title: tooltipContent, arrow: true, children: /* @__PURE__ */ jsxRuntime.jsx(
21803
- material.Avatar,
21786
+ const IconLeft = (props) => /* @__PURE__ */ jsxRuntime.jsx(
21787
+ "svg",
21788
+ {
21789
+ width: "20",
21790
+ height: "16",
21791
+ viewBox: "0 0 20 16",
21792
+ fill: "none",
21793
+ xmlns: "http://www.w3.org/2000/svg",
21794
+ ...props,
21795
+ children: /* @__PURE__ */ jsxRuntime.jsx(
21796
+ "path",
21804
21797
  {
21805
- ...rest,
21806
- src: url2 || "",
21807
- sx: { ...MAP_SIZE[size], bgcolor: "primary.main", ...sx, cursor: "pointer" }
21798
+ d: "M8 15L1 8M1 8L8 1M1 8L19 8",
21799
+ stroke: "currentColor",
21800
+ "stroke-width": "2",
21801
+ "stroke-linecap": "round",
21802
+ "stroke-linejoin": "round"
21808
21803
  }
21809
- ) });
21804
+ )
21810
21805
  }
21811
- return /* @__PURE__ */ jsxRuntime.jsx(material.Avatar, { ...rest, src: url2 || "", sx: { ...MAP_SIZE[size], bgcolor: "primary.main", ...sx, cursor: "pointer" } });
21812
- };
21813
- const TimeAgoComponent = ({
21814
- time: time2,
21815
- hasText
21816
- }) => {
21817
- return /* @__PURE__ */ jsxRuntime.jsx(
21818
- material.Typography,
21819
- {
21820
- variant: "caption",
21821
- sx: { ...getLimitLineCss(1), color: "text.disabled", lineHeight: 1.2 },
21822
- children: (hasText ? "Cập nhật lúc " : "") + timeUtils.getTimeAgo(time2)
21823
- }
21824
- );
21825
- };
21826
- const TimeAgoContentComponent = ({ time: time2, content, height: height2 = HEIGHT_IMAGE_DEFAULT }) => {
21827
- return /* @__PURE__ */ jsxRuntime.jsxs(
21828
- system.Stack,
21829
- {
21830
- sx: {
21831
- height: height2,
21832
- gap: 0,
21833
- justifyContent: "space-between",
21834
- alignItems: "flex-start"
21835
- },
21836
- children: [
21837
- /* @__PURE__ */ jsxRuntime.jsx(
21838
- material.Typography,
21839
- {
21840
- sx: {
21841
- ...getLimitLineCss(1)
21842
- },
21843
- children: content
21844
- }
21845
- ),
21846
- /* @__PURE__ */ jsxRuntime.jsx(TimeAgoComponent, { time: time2 })
21847
- ]
21848
- }
21849
- );
21850
- };
21851
- const ImageContentTimeComponent = ({
21852
- url: url2,
21853
- content,
21854
- time: time2,
21855
- sizeType = "medium"
21856
- }) => {
21857
- return /* @__PURE__ */ jsxRuntime.jsxs(StackRow, { alignItems: "center", children: [
21858
- /* @__PURE__ */ jsxRuntime.jsx(AvatarElement, { url: url2, size: sizeType }),
21859
- /* @__PURE__ */ jsxRuntime.jsx(TimeAgoContentComponent, { content, time: time2 })
21860
- ] });
21861
- };
21862
- const TooltipOnClickElement = ({
21863
- open,
21864
- placement = "top",
21865
- content,
21866
- children,
21867
- onOpen,
21868
- onClose,
21869
- onClickAway,
21870
- ...rest
21871
- }) => {
21872
- return (
21873
- // Chỗ này có thể là bug, onClickAway apply ngay cả khi component chưa được render
21874
- /* @__PURE__ */ jsxRuntime.jsx(material.ClickAwayListener, { onClickAway, children: /* @__PURE__ */ jsxRuntime.jsx(
21875
- material.Tooltip,
21806
+ );
21807
+ const IconRight = (props) => /* @__PURE__ */ jsxRuntime.jsx(
21808
+ "svg",
21809
+ {
21810
+ width: "20",
21811
+ height: "16",
21812
+ viewBox: "0 0 20 16",
21813
+ fill: "none",
21814
+ xmlns: "http://www.w3.org/2000/svg",
21815
+ ...props,
21816
+ children: /* @__PURE__ */ jsxRuntime.jsx(
21817
+ "path",
21876
21818
  {
21877
- PopperProps: { disablePortal: true },
21878
- open,
21879
- onOpen,
21880
- onClose,
21881
- disableFocusListener: true,
21882
- disableHoverListener: true,
21883
- disableTouchListener: true,
21884
- placement,
21885
- title: content,
21886
- ...rest,
21887
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { children })
21819
+ d: "M12 1L19 8M19 8L12 15M19 8L1 8",
21820
+ stroke: "currentColor",
21821
+ "stroke-width": "2",
21822
+ "stroke-linecap": "round",
21823
+ "stroke-linejoin": "round"
21888
21824
  }
21889
- ) })
21890
- );
21825
+ )
21826
+ }
21827
+ );
21828
+ const LayoutGroupContext = React.createContext({});
21829
+ function useConstant(init) {
21830
+ const ref = React.useRef(null);
21831
+ if (ref.current === null) {
21832
+ ref.current = init();
21833
+ }
21834
+ return ref.current;
21835
+ }
21836
+ const isBrowser = typeof window !== "undefined";
21837
+ const useIsomorphicLayoutEffect = isBrowser ? React.useLayoutEffect : React.useEffect;
21838
+ const PresenceContext = /* @__PURE__ */ React.createContext(null);
21839
+ function addUniqueItem(arr, item) {
21840
+ if (arr.indexOf(item) === -1)
21841
+ arr.push(item);
21842
+ }
21843
+ function removeItem(arr, item) {
21844
+ const index = arr.indexOf(item);
21845
+ if (index > -1)
21846
+ arr.splice(index, 1);
21847
+ }
21848
+ const clamp = (min, max, v) => {
21849
+ if (v > max)
21850
+ return max;
21851
+ if (v < min)
21852
+ return min;
21853
+ return v;
21891
21854
  };
21892
- const EmptyComponent = ({}) => {
21893
- return /* @__PURE__ */ jsxRuntime.jsx(material.Fade, { in: true, timeout: ANIMATION_TIME, children: /* @__PURE__ */ jsxRuntime.jsx(
21894
- material.Stack,
21895
- {
21896
- direction: "column",
21897
- sx: {
21898
- flex: 1,
21899
- height: "100%",
21900
- alignItems: "center",
21901
- justifyContent: "center",
21902
- padding: PADDING_GAP_ITEM
21903
- },
21904
- children: /* @__PURE__ */ jsxRuntime.jsx(material.Box, { component: "img", sx: { width: 70 }, src: "/images/empty.svg" })
21905
- }
21906
- ) });
21855
+ function formatErrorMessage(message, errorCode) {
21856
+ return errorCode ? `${message}. For more information and steps for solving, visit https://motion.dev/troubleshooting/${errorCode}` : message;
21857
+ }
21858
+ let warning = () => {
21907
21859
  };
21908
- const BellComponent = ({}) => {
21909
- const isSystemMonitor = useIsSystemMonitor();
21910
- const { notificationCount } = reactRedux.useSelector(
21911
- (state) => state.account
21912
- );
21913
- const account = reactRedux.useSelector((state) => state.account);
21914
- const dispatch = useAppDispatch();
21915
- const navigate = reactRouterDom.useNavigate();
21916
- const { palette } = material.useTheme();
21917
- const { showSnackbar } = useSnackbar();
21918
- const [open, setOpen] = React.useState(false);
21919
- const [list, setList] = React.useState([]);
21920
- const [loading, setLoading] = React.useState(false);
21921
- const handleGetListNotification = async () => {
21922
- setLoading(true);
21923
- try {
21924
- const res = await notificationApi.getListNotification({
21925
- status: NotificationStatus.NOT_VIEWED,
21926
- page: 0,
21927
- take: 0
21928
- });
21929
- setList(res.list);
21930
- dispatch(ACTION_ACCOUNT.changeNotificationCount(res.total));
21931
- } catch (error) {
21932
- showSnackbar({
21933
- message: getErrorMessage(error),
21934
- type: SnackbarType.ERROR
21935
- });
21936
- } finally {
21937
- setLoading(false);
21860
+ let invariant = () => {
21861
+ };
21862
+ if (process.env.NODE_ENV !== "production") {
21863
+ warning = (check, message, errorCode) => {
21864
+ if (!check && typeof console !== "undefined") {
21865
+ console.warn(formatErrorMessage(message, errorCode));
21938
21866
  }
21939
21867
  };
21940
- React.useEffect(() => {
21941
- (async () => await handleGetListNotification())();
21942
- }, []);
21943
- const clickNotification = async (notification) => {
21944
- setOpen(false);
21945
- const isMyProposal = notification?.createdById === account.user.id;
21946
- try {
21947
- await notificationApi.updateNotification({
21948
- updateNotificationAction: UpdateNotificationAction.VIEW_ONE,
21949
- id: notification.id
21950
- });
21951
- dispatch(ACTION_ACCOUNT.changeNotificationCount(notificationCount - 1));
21952
- navigate(notification.path || PAGE.DASHBOARD.path, {
21953
- state: {
21954
- searchType: isMyProposal ? UserMovementSearchType.MY_PROPOSAL : UserMovementSearchType.NEED_APPROVE
21955
- }
21956
- });
21957
- } catch (error) {
21958
- showSnackbar({
21959
- message: getErrorMessage(error),
21960
- type: SnackbarType.ERROR
21961
- });
21962
- }
21963
- };
21964
- return /* @__PURE__ */ jsxRuntime.jsx(
21965
- TooltipOnClickElement,
21966
- {
21967
- open,
21968
- onClickAway: () => setOpen(false),
21969
- placement: "bottom-end",
21970
- content: /* @__PURE__ */ jsxRuntime.jsxs(
21971
- material.List,
21972
- {
21973
- sx: {
21974
- display: "flex",
21975
- flexDirection: "column",
21976
- padding: 0,
21977
- maxHeight: 500,
21978
- overflowY: "auto",
21979
- flex: 1,
21980
- width: "300px"
21981
- },
21982
- children: [
21983
- /* @__PURE__ */ jsxRuntime.jsxs(
21984
- material.ListItem,
21985
- {
21986
- sx: {
21987
- padding: PADDING_GAP_ITEM,
21988
- display: "flex",
21989
- flexDirection: "row",
21990
- justifyContent: "space-between",
21991
- alignItems: "center",
21992
- position: "sticky",
21993
- top: 0,
21994
- backgroundColor: palette.background.paper,
21995
- zIndex: 1
21996
- },
21997
- children: [
21998
- /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { variant: "subtitle1", children: "Thông báo" }),
21999
- /* @__PURE__ */ jsxRuntime.jsxs(StackRow, { children: [
22000
- /* @__PURE__ */ jsxRuntime.jsx(
22001
- IconElement,
22002
- {
22003
- sx: { cursor: "pointer" },
22004
- icon: "mark_email_read",
22005
- onClick: async (e) => {
22006
- e.stopPropagation();
22007
- try {
22008
- await notificationApi.updateNotification({
22009
- updateNotificationAction: UpdateNotificationAction.VIEW_ALL
22010
- });
22011
- dispatch(ACTION_ACCOUNT.changeNotificationCount(0));
22012
- } catch (error) {
22013
- showSnackbar({
22014
- message: getErrorMessage(error),
22015
- type: SnackbarType.ERROR
22016
- });
22017
- }
22018
- }
22019
- }
22020
- ),
22021
- /* @__PURE__ */ jsxRuntime.jsx(
22022
- IconElement,
22023
- {
22024
- icon: "settings",
22025
- onClick: (e) => {
22026
- e.stopPropagation();
22027
- }
22028
- }
22029
- )
22030
- ] })
22031
- ]
22032
- }
22033
- ),
22034
- loading ? /* @__PURE__ */ jsxRuntime.jsx(StackRowAlignCenter, { sx: { height: 50 }, children: /* @__PURE__ */ jsxRuntime.jsx(LoadingComponent, {}) }) : list.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(EmptyComponent, {}) : list.map((notification) => /* @__PURE__ */ jsxRuntime.jsx(
22035
- material.ListItem,
22036
- {
22037
- onClick: () => clickNotification(notification),
22038
- id: notification.id,
22039
- sx: {
22040
- borderRadius: BORDER_RADIUS_ELEMENT,
22041
- padding: PADDING_GAP_ITEM,
22042
- display: "flex",
22043
- flexDirection: "row",
22044
- alignItems: "center",
22045
- cursor: "pointer",
22046
- transition: TRANSITION_TIME,
22047
- "&:hover": {
22048
- backgroundColor: palette.action.hover,
22049
- color: palette.primary.main
22050
- }
22051
- },
22052
- children: /* @__PURE__ */ jsxRuntime.jsxs(material.Stack, { gap: 1, children: [
22053
- /* @__PURE__ */ jsxRuntime.jsx(
22054
- ImageContentTimeComponent,
22055
- {
22056
- url: notification.createdBy?.url || "",
22057
- content: notification.title,
22058
- time: notification.createdAt
22059
- }
22060
- ),
22061
- /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { variant: "caption", sx: { ...getLimitLineCss(2) }, children: notification.content })
22062
- ] })
22063
- },
22064
- notification.id
22065
- ))
22066
- ]
22067
- }
22068
- ),
22069
- children: /* @__PURE__ */ jsxRuntime.jsx(
22070
- material.Badge,
22071
- {
22072
- onClick: async () => {
22073
- setOpen(!open);
22074
- await handleGetListNotification();
22075
- },
22076
- badgeContent: notificationCount,
22077
- color: "error",
22078
- sx: { cursor: "pointer" },
22079
- children: /* @__PURE__ */ jsxRuntime.jsx(
22080
- IconElement,
22081
- {
22082
- icon: "notifications",
22083
- onClick: () => setOpen(!open),
22084
- size: "large",
22085
- sx: {
22086
- color: isSystemMonitor ? palette.background.default : palette.primary.main,
22087
- "&:hover": {
22088
- color: isSystemMonitor ? palette.background.default : palette.primary.main
22089
- }
22090
- }
22091
- }
22092
- )
22093
- }
22094
- )
22095
- }
22096
- );
22097
- };
22098
- const AvatarUserInfo = ({
22099
- name,
22100
- url: url2,
22101
- positions = [],
22102
- maxWidth: maxWidth2 = "440px",
22103
- isTag = false,
22104
- sxName,
22105
- sxPosition,
22106
- sizeAvatar = "large"
22107
- }) => {
22108
- const { palette } = material.useTheme();
22109
- const isSystemMonitor = useIsSystemMonitor();
22110
- return /* @__PURE__ */ jsxRuntime.jsxs(StackRow, { sx: { alignItems: "center", gap: PADDING_GAP_ITEM }, children: [
22111
- /* @__PURE__ */ jsxRuntime.jsx(AvatarElement, { url: url2, size: sizeAvatar }),
22112
- positions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(material.Stack, { sx: { gap: 0 }, children: [
22113
- /* @__PURE__ */ jsxRuntime.jsx(
22114
- material.Typography,
22115
- {
22116
- sx: {
22117
- color: isSystemMonitor ? palette.primary.contrastText : palette.text.secondary,
22118
- fontWeight: "600",
22119
- fontSize: "14px",
22120
- lineHeight: "20px",
22121
- ...getLimitLineCss(1),
22122
- ...sxName
22123
- },
22124
- children: name
22125
- }
22126
- ),
22127
- /* @__PURE__ */ jsxRuntime.jsx(
22128
- material.Typography,
22129
- {
22130
- variant: "caption",
22131
- sx: {
22132
- ...getLimitLineCss(1),
22133
- color: palette.text.disabled,
22134
- maxWidth: maxWidth2,
22135
- ...isTag && {
22136
- display: "flex",
22137
- padding: "2px 4px",
22138
- justifyContent: "center",
22139
- alignItems: "center",
22140
- gap: "10px",
22141
- borderRadius: "4px",
22142
- background: " #EFF8FF",
22143
- color: " #035388",
22144
- width: "fit-content",
22145
- ...sxPosition
22146
- }
22147
- },
22148
- children: positions.join(" / ")
22149
- }
22150
- )
22151
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(
22152
- material.Typography,
22153
- {
22154
- sx: {
22155
- ...TYPOGRAPHY_STYLES.textSm.semiBold,
22156
- ...getLimitLineCss(1),
22157
- ...sxName
22158
- },
22159
- children: name
22160
- }
22161
- )
22162
- ] });
22163
- };
22164
- const RadioGroupElement = ({
22165
- name,
22166
- direction = "row",
22167
- label,
22168
- disabled,
22169
- iconLabel = "event_list",
22170
- defaultValue,
22171
- value: value2,
22172
- onChange,
22173
- children,
22174
- required = false,
22175
- sx = {}
22176
- }) => {
22177
- const change = (event) => {
22178
- onChange && onChange({ target: { name, value: event.target.value || void 0 } });
22179
- };
22180
- return /* @__PURE__ */ jsxRuntime.jsxs(material.FormControl, { disabled, sx: { gap: PADDING_GAP_ITEM }, onChange: change, children: [
22181
- label && /* @__PURE__ */ jsxRuntime.jsx(
22182
- material.InputLabel,
22183
- {
22184
- shrink: true,
22185
- required,
22186
- sx: {
22187
- transform: "translate(0px , -9px) scale(0.75)",
22188
- zIndex: 2,
22189
- display: "flex"
22190
- },
22191
- children: /* @__PURE__ */ jsxRuntime.jsxs(StackLabel, { children: [
22192
- /* @__PURE__ */ jsxRuntime.jsx(IconElement, { icon: iconLabel, sx: { fontSize: TEXT_FIELD.FONT_SIZE_LABEL } }),
22193
- label
22194
- ] })
22195
- }
22196
- ),
22197
- /* @__PURE__ */ jsxRuntime.jsx(
22198
- material.RadioGroup,
22199
- {
22200
- name,
22201
- defaultValue,
22202
- value: value2,
22203
- sx: {
22204
- flexDirection: direction,
22205
- paddingTop: label ? "calc(8.5px + 1.5px)" : 0,
22206
- // 8.5 lấy từ default theme không phải tự nhiên mà có
22207
- gap: PADDING_GAP_LAYOUT,
22208
- ...sx
22209
- },
22210
- children
22211
- }
22212
- )
22213
- ] });
22214
- };
22215
- const RadioElement = ({ name, label, ...rest }) => {
22216
- return /* @__PURE__ */ jsxRuntime.jsx(
22217
- material.FormControlLabel,
22218
- {
22219
- name,
22220
- label,
22221
- sx: { alignItems: "center", mr: 0 },
22222
- control: /* @__PURE__ */ jsxRuntime.jsx(
22223
- material.Radio,
22224
- {
22225
- ...rest,
22226
- sx: {
22227
- paddingTop: 0,
22228
- paddingBottom: 0,
22229
- paddingRight: PADDING_GAP_ITEM,
22230
- marginLeft: "2px",
22231
- "&:hover": { backgroundColor: "unset" },
22232
- "& .MuiSvgIcon-root": { fontSize: "18px" }
22233
- }
22234
- }
22235
- )
22236
- }
22237
- );
22238
- };
22239
- const AvatarUserComponent = ({}) => {
22240
- const account = reactRedux.useSelector((state) => state.account);
22241
- const { showSnackbar } = useSnackbar();
22242
- const dispatch = useAppDispatch();
22243
- const navigate = reactRouterDom.useNavigate();
22244
- const [anchorEl, setAnchorEl] = React.useState(null);
22245
- const positions = account?.user?.managedOrgUnits?.map((e) => e.name) || [];
22246
- const menu = [
22247
- {
22248
- content: "Đăng xuất khỏi thiết bị",
22249
- icon: "logout",
22250
- onClick: async () => {
22251
- try {
22252
- await Promise.all([
22253
- dispatch(
22254
- ACTION_ACCOUNT.logout({
22255
- type: LogoutType.THIS_DEVICE,
22256
- refreshToken: account.refreshToken
22257
- })
22258
- ).unwrap()
22259
- ]);
22260
- navigate(PAGE.AUTH.path);
22261
- } catch (error) {
22262
- showSnackbar({
22263
- message: getErrorMessage(error),
22264
- type: SnackbarType.ERROR
22265
- });
22266
- }
22267
- }
22268
- },
22269
- {
22270
- content: "Đăng xuất khỏi tất cả thiết bị",
22271
- icon: "exit_to_app",
22272
- onClick: async () => {
22273
- if ("serviceWorker" in navigator) {
22274
- navigator.serviceWorker.getRegistrations().then((registrations) => {
22275
- registrations.forEach((registration) => {
22276
- registration.unregister();
22277
- });
22278
- }).catch((error) => {
22279
- console.error("Error unregistering Service Workers: ", error);
22280
- });
22281
- } else {
22282
- console.warn("Service Worker is not supported in this browser.");
22283
- }
22284
- await dispatch(
22285
- ACTION_ACCOUNT.logout({
22286
- type: LogoutType.THIS_DEVICE,
22287
- refreshToken: account.refreshToken
22288
- })
22289
- ).unwrap();
22290
- navigate(PAGE.AUTH.path);
22291
- }
22292
- }
22293
- ];
22294
- const handleClick = (event) => {
22295
- setAnchorEl(event.currentTarget);
22296
- };
22297
- const handleClose = () => {
22298
- setAnchorEl(null);
22299
- };
22300
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
22301
- /* @__PURE__ */ jsxRuntime.jsxs(
22302
- material.Box,
22303
- {
22304
- onClick: handleClick,
22305
- sx: {
22306
- cursor: "pointer",
22307
- display: "flex",
22308
- alignItems: "center",
22309
- gap: 1
22310
- },
22311
- children: [
22312
- /* @__PURE__ */ jsxRuntime.jsx(
22313
- AvatarUserInfo,
22314
- {
22315
- url: account.user?.url,
22316
- name: account.user?.name ?? "",
22317
- positions,
22318
- isTag: true
22319
- }
22320
- ),
22321
- /* @__PURE__ */ jsxRuntime.jsx(
22322
- IconElement,
22323
- {
22324
- icon: "arrow_drop_down",
22325
- size: "medium",
22326
- sx: {
22327
- color: "text.secondary",
22328
- transition: "transform 0.2s ease-in-out",
22329
- transform: anchorEl ? "rotate(180deg)" : "rotate(0deg)",
22330
- fontVariationSettings: "'wght' 600, 'FILL' 0",
22331
- willChange: "transform",
22332
- backfaceVisibility: "hidden"
22333
- }
22334
- }
22335
- )
22336
- ]
22337
- }
22338
- ),
22339
- /* @__PURE__ */ jsxRuntime.jsxs(
22340
- material.Menu,
22341
- {
22342
- anchorEl,
22343
- open: Boolean(anchorEl),
22344
- onClose: handleClose,
22345
- onClick: handleClose,
22346
- disableScrollLock: true,
22347
- PaperProps: {
22348
- elevation: 0,
22349
- sx: {
22350
- overflow: "visible",
22351
- filter: "drop-shadow(0px 2px 8px rgba(0,0,0,0.32))",
22352
- mt: 1.5,
22353
- transform: "translate3d(0, 0, 0)",
22354
- willChange: "transform",
22355
- "& .MuiAvatar-root": {
22356
- width: 32,
22357
- height: 32,
22358
- ml: -0.5,
22359
- mr: 1
22360
- },
22361
- "&:before": {
22362
- content: '""',
22363
- display: "block",
22364
- position: "absolute",
22365
- top: 0,
22366
- right: 14,
22367
- width: 10,
22368
- height: 10,
22369
- bgcolor: "background.paper",
22370
- transform: "translateY(-50%) rotate(45deg)",
22371
- zIndex: 0
22372
- }
22373
- }
22374
- },
22375
- transformOrigin: { horizontal: "right", vertical: "top" },
22376
- anchorOrigin: { horizontal: "right", vertical: "bottom" },
22377
- children: [
22378
- /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { sx: { p: 2 }, children: [
22379
- /* @__PURE__ */ jsxRuntime.jsxs(StackRowAlignStartJustBetween, { children: [
22380
- /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { variant: "subtitle1", sx: { lineHeight: 1 }, children: account.user?.name }),
22381
- /* @__PURE__ */ jsxRuntime.jsx(
22382
- IconElement,
22383
- {
22384
- icon: "settings",
22385
- onClick: () => navigate(PAGE.DASHBOARD.path + DASHBOARD_SCREEN.ACCOUNT.path)
22386
- }
22387
- )
22388
- ] }),
22389
- account.user?.userOrgUnitPositions && account.user.userOrgUnitPositions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
22390
- /* @__PURE__ */ jsxRuntime.jsx(
22391
- IconContentElement,
22392
- {
22393
- icon: "admin_panel_settings",
22394
- content: "Vai trò"
22395
- }
22396
- ),
22397
- /* @__PURE__ */ jsxRuntime.jsx(
22398
- RadioGroupElement,
22399
- {
22400
- direction: "column",
22401
- sx: { paddingLeft: "20px" },
22402
- value: account.userUnitPositionId,
22403
- onChange: (event) => {
22404
- dispatch(
22405
- ACTION_ACCOUNT.updatePositionOrgUnit(event.target.value)
22406
- );
22407
- window.location.reload();
22408
- },
22409
- children: account.user.userOrgUnitPositions.map((e) => /* @__PURE__ */ jsxRuntime.jsx(
22410
- RadioElement,
22411
- {
22412
- value: e.id,
22413
- size: "small",
22414
- label: /* @__PURE__ */ jsxRuntime.jsxs(system.Stack, { gap: 0, children: [
22415
- /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { children: e.orgUnit.name }),
22416
- /* @__PURE__ */ jsxRuntime.jsx(
22417
- material.Typography,
22418
- {
22419
- variant: "caption",
22420
- sx: {
22421
- ...getLimitLineCss(1),
22422
- color: "text.disabled"
22423
- },
22424
- children: e.position.name
22425
- }
22426
- )
22427
- ] })
22428
- },
22429
- e.id
22430
- ))
22431
- }
22432
- )
22433
- ] })
22434
- ] }),
22435
- /* @__PURE__ */ jsxRuntime.jsx(material.Divider, {}),
22436
- menu.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(material.MenuItem, { onClick: item.onClick, children: [
22437
- /* @__PURE__ */ jsxRuntime.jsx(IconElement, { icon: item.icon, size: "small", sx: { mr: 1 } }),
22438
- /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { children: item.content })
22439
- ] }, index))
22440
- ]
22441
- }
22442
- )
22443
- ] });
22444
- };
22445
- const MonitorPart = ({
22446
- children
22447
- }) => {
22448
- return /* @__PURE__ */ jsxRuntime.jsx(
22449
- system.Stack,
22450
- {
22451
- sx: {
22452
- minHeight: "100vh",
22453
- width: "100%",
22454
- overflowY: "auto",
22455
- backgroundImage: "url('/images/image-dashboard.jpg')",
22456
- backgroundSize: "cover",
22457
- backgroundPosition: "top",
22458
- backgroundRepeat: "no-repeat"
22459
- },
22460
- children: /* @__PURE__ */ jsxRuntime.jsxs(system.Stack, { p: { padding: PADDING_GAP_LAYOUT }, children: [
22461
- /* @__PURE__ */ jsxRuntime.jsxs(StackRowJustBetween, { children: [
22462
- /* @__PURE__ */ jsxRuntime.jsx(StackRowAlignCenter, { children: /* @__PURE__ */ jsxRuntime.jsx(
22463
- LogoComponent,
22464
- {
22465
- url: "/images/logo/logo-sub-3.svg",
22466
- fillColor: "white"
22467
- }
22468
- ) }),
22469
- /* @__PURE__ */ jsxRuntime.jsxs(StackRowAlignCenter, { children: [
22470
- /* @__PURE__ */ jsxRuntime.jsx(BellComponent, {}),
22471
- /* @__PURE__ */ jsxRuntime.jsx(AvatarUserComponent, {})
22472
- ] })
22473
- ] }),
22474
- children
22475
- ] })
22476
- }
22477
- );
22478
- };
22479
- const IconLeft = (props) => /* @__PURE__ */ jsxRuntime.jsx(
22480
- "svg",
22481
- {
22482
- width: "20",
22483
- height: "16",
22484
- viewBox: "0 0 20 16",
22485
- fill: "none",
22486
- xmlns: "http://www.w3.org/2000/svg",
22487
- ...props,
22488
- children: /* @__PURE__ */ jsxRuntime.jsx(
22489
- "path",
22490
- {
22491
- d: "M8 15L1 8M1 8L8 1M1 8L19 8",
22492
- stroke: "currentColor",
22493
- "stroke-width": "2",
22494
- "stroke-linecap": "round",
22495
- "stroke-linejoin": "round"
22496
- }
22497
- )
22498
- }
22499
- );
22500
- const IconRight = (props) => /* @__PURE__ */ jsxRuntime.jsx(
22501
- "svg",
22502
- {
22503
- width: "20",
22504
- height: "16",
22505
- viewBox: "0 0 20 16",
22506
- fill: "none",
22507
- xmlns: "http://www.w3.org/2000/svg",
22508
- ...props,
22509
- children: /* @__PURE__ */ jsxRuntime.jsx(
22510
- "path",
22511
- {
22512
- d: "M12 1L19 8M19 8L12 15M19 8L1 8",
22513
- stroke: "currentColor",
22514
- "stroke-width": "2",
22515
- "stroke-linecap": "round",
22516
- "stroke-linejoin": "round"
22517
- }
22518
- )
22519
- }
22520
- );
22521
- const LayoutGroupContext = React.createContext({});
22522
- function useConstant(init) {
22523
- const ref = React.useRef(null);
22524
- if (ref.current === null) {
22525
- ref.current = init();
22526
- }
22527
- return ref.current;
22528
- }
22529
- const isBrowser = typeof window !== "undefined";
22530
- const useIsomorphicLayoutEffect = isBrowser ? React.useLayoutEffect : React.useEffect;
22531
- const PresenceContext = /* @__PURE__ */ React.createContext(null);
22532
- function addUniqueItem(arr, item) {
22533
- if (arr.indexOf(item) === -1)
22534
- arr.push(item);
22535
- }
22536
- function removeItem(arr, item) {
22537
- const index = arr.indexOf(item);
22538
- if (index > -1)
22539
- arr.splice(index, 1);
22540
- }
22541
- const clamp = (min, max, v) => {
22542
- if (v > max)
22543
- return max;
22544
- if (v < min)
22545
- return min;
22546
- return v;
22547
- };
22548
- function formatErrorMessage(message, errorCode) {
22549
- return errorCode ? `${message}. For more information and steps for solving, visit https://motion.dev/troubleshooting/${errorCode}` : message;
22550
- }
22551
- let warning = () => {
22552
- };
22553
- let invariant = () => {
22554
- };
22555
- if (process.env.NODE_ENV !== "production") {
22556
- warning = (check, message, errorCode) => {
22557
- if (!check && typeof console !== "undefined") {
22558
- console.warn(formatErrorMessage(message, errorCode));
22559
- }
22560
- };
22561
- invariant = (check, message, errorCode) => {
22562
- if (!check) {
22563
- throw new Error(formatErrorMessage(message, errorCode));
21868
+ invariant = (check, message, errorCode) => {
21869
+ if (!check) {
21870
+ throw new Error(formatErrorMessage(message, errorCode));
22564
21871
  }
22565
21872
  };
22566
21873
  }
@@ -29678,337 +28985,762 @@ const gestureAnimations = {
29678
28985
  inView: {
29679
28986
  Feature: InViewFeature
29680
28987
  },
29681
- tap: {
29682
- Feature: PressGesture
28988
+ tap: {
28989
+ Feature: PressGesture
28990
+ },
28991
+ focus: {
28992
+ Feature: FocusGesture
28993
+ },
28994
+ hover: {
28995
+ Feature: HoverGesture
28996
+ }
28997
+ };
28998
+ const layout = {
28999
+ layout: {
29000
+ ProjectionNode: HTMLProjectionNode,
29001
+ MeasureLayout
29002
+ }
29003
+ };
29004
+ const featureBundle = {
29005
+ ...animations,
29006
+ ...gestureAnimations,
29007
+ ...drag,
29008
+ ...layout
29009
+ };
29010
+ const motion = /* @__PURE__ */ createMotionProxy(featureBundle, createDomVisualElement);
29011
+ const animationPresets = {
29012
+ fadeInUp: {
29013
+ initial: { opacity: 0, y: 50 },
29014
+ animate: { opacity: 1, y: 0 },
29015
+ transition: { duration: 0.2, ease: "easeOut" }
29016
+ },
29017
+ fadeInDown: {
29018
+ initial: { opacity: 0, y: -50 },
29019
+ animate: { opacity: 1, y: 0 },
29020
+ transition: { duration: 0.3, ease: "easeOut" }
29683
29021
  },
29684
- focus: {
29685
- Feature: FocusGesture
29022
+ fadeInLeft: {
29023
+ initial: { opacity: 0, x: -50 },
29024
+ animate: { opacity: 1, x: 0 },
29025
+ transition: { duration: 0.3, ease: "easeOut" }
29686
29026
  },
29687
- hover: {
29688
- Feature: HoverGesture
29027
+ fadeInRight: {
29028
+ initial: { opacity: 0, x: 50 },
29029
+ animate: { opacity: 1, x: 0 },
29030
+ transition: { duration: 0.3, ease: "easeOut" }
29031
+ },
29032
+ scaleIn: {
29033
+ initial: { opacity: 0, scale: 0.9 },
29034
+ animate: { opacity: 1, scale: 1 },
29035
+ transition: { duration: 0.3, ease: "easeOut" }
29036
+ },
29037
+ slideInUp: {
29038
+ initial: { opacity: 0, y: 20 },
29039
+ animate: { opacity: 1, y: 0 },
29040
+ transition: { duration: 0.4, ease: "easeOut" }
29041
+ },
29042
+ staggerItem: {
29043
+ initial: { opacity: 0, y: 30, scale: 0.9 },
29044
+ animate: { opacity: 1, y: 0, scale: 1 },
29045
+ transition: { duration: 0.4, delay: 0, ease: "easeOut" }
29046
+ },
29047
+ tabContent: {
29048
+ initial: { opacity: 0, y: 20 },
29049
+ animate: { opacity: 1, y: 0 },
29050
+ transition: { duration: 0.4, ease: "easeOut" }
29051
+ },
29052
+ tabUnderline: {
29053
+ initial: { scaleX: 0, opacity: 0 },
29054
+ animate: { scaleX: 1, opacity: 1 },
29055
+ exit: { scaleX: 0, opacity: 0 },
29056
+ transition: { duration: 0.3, ease: "easeInOut" }
29689
29057
  }
29690
29058
  };
29691
- const layout = {
29692
- layout: {
29693
- ProjectionNode: HTMLProjectionNode,
29694
- MeasureLayout
29059
+ const MotionBox = ({
29060
+ children,
29061
+ sx,
29062
+ onClick,
29063
+ preset = "fadeInUp",
29064
+ delay: delay2,
29065
+ index,
29066
+ hover: hover2 = false,
29067
+ ...motionProps
29068
+ }) => {
29069
+ const getAnimationProps = () => {
29070
+ if (preset) {
29071
+ const presetConfig = animationPresets[preset];
29072
+ if (preset === "staggerItem" && index !== void 0) {
29073
+ return {
29074
+ ...presetConfig,
29075
+ transition: {
29076
+ ...presetConfig.transition,
29077
+ delay: index * 0.05 + (delay2 || 0)
29078
+ }
29079
+ };
29080
+ }
29081
+ if (delay2 !== void 0) {
29082
+ return {
29083
+ ...presetConfig,
29084
+ transition: {
29085
+ ...presetConfig.transition,
29086
+ delay: delay2
29087
+ }
29088
+ };
29089
+ }
29090
+ return presetConfig;
29091
+ }
29092
+ return {};
29093
+ };
29094
+ const hoverProps = hover2 ? {
29095
+ whileHover: {
29096
+ y: -4,
29097
+ scale: 1.05,
29098
+ transition: { duration: 0.2 }
29099
+ }
29100
+ } : {};
29101
+ return /* @__PURE__ */ jsxRuntime.jsx(motion.div, { ...motionProps, ...getAnimationProps(), ...hoverProps, onClick, style: { ...sx }, children });
29102
+ };
29103
+ const AppGrid = ({
29104
+ apps,
29105
+ onClickItem,
29106
+ columns = 5,
29107
+ rows = 3,
29108
+ iconSize = 80,
29109
+ iconRadius = 7,
29110
+ iconShadow = `0 ${PADDING_GAP_ITEM_SMALL} ${PADDING_GAP_LAYOUT} ${BORDER_COLOR_CARD}`,
29111
+ gap: gap2 = PADDING_GAP_ITEM,
29112
+ titleVariant = "subtitle1",
29113
+ captionVariant = "caption",
29114
+ titleColor,
29115
+ captionColor,
29116
+ selectedAppId,
29117
+ showPagination = true
29118
+ }) => {
29119
+ const theme = useTheme();
29120
+ const pageSize = Math.max(1, columns * Math.max(1, rows));
29121
+ const totalPages = Math.max(1, Math.ceil(apps.length / pageSize));
29122
+ const [page, setPage] = React.useState(0);
29123
+ const { user } = reactRedux.useSelector((state) => state.account);
29124
+ React.useEffect(() => {
29125
+ setPage((prev) => prev >= totalPages ? totalPages - 1 : prev);
29126
+ }, [totalPages, columns, rows, apps.length]);
29127
+ const start = page * pageSize;
29128
+ const end = start + pageSize;
29129
+ const visibleApps = totalPages > 1 ? apps.slice(start, end) : apps;
29130
+ const findLink = (app) => {
29131
+ if (!app.children?.length) {
29132
+ return app.path;
29133
+ }
29134
+ for (const i of app.children || []) {
29135
+ if (user?.type && i.allowUserTypes.includes(user?.type)) {
29136
+ if (i.path) {
29137
+ return `${i.path}`;
29138
+ }
29139
+ }
29140
+ }
29141
+ };
29142
+ return /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { sx: { position: "relative" }, children: [
29143
+ /* @__PURE__ */ jsxRuntime.jsx(
29144
+ material.Box,
29145
+ {
29146
+ sx: {
29147
+ display: "grid",
29148
+ gridTemplateColumns: `repeat(${columns}, 1fr)`,
29149
+ gap: gap2
29150
+ },
29151
+ children: visibleApps.map((app, index) => {
29152
+ const isSelected = selectedAppId === app.key;
29153
+ return /* @__PURE__ */ jsxRuntime.jsx(
29154
+ "a",
29155
+ {
29156
+ href: findLink(app) || "#",
29157
+ target: "_blank",
29158
+ rel: "noopener noreferrer",
29159
+ style: {
29160
+ textDecoration: "none",
29161
+ color: "inherit",
29162
+ width: "100%",
29163
+ display: "block"
29164
+ },
29165
+ onClick: (e) => {
29166
+ const url2 = findLink(app);
29167
+ e.preventDefault();
29168
+ onClickItem?.(app);
29169
+ if (url2 && url2 !== "#") {
29170
+ try {
29171
+ window.open(url2, "_blank", "noopener");
29172
+ } catch (err) {
29173
+ const newWindow = window.open("about:blank");
29174
+ if (newWindow) newWindow.location.href = url2;
29175
+ }
29176
+ }
29177
+ },
29178
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
29179
+ MotionBox,
29180
+ {
29181
+ preset: "staggerItem",
29182
+ index,
29183
+ hover: true,
29184
+ sx: {
29185
+ cursor: "pointer",
29186
+ display: "flex",
29187
+ flex: 1,
29188
+ alignItems: "center",
29189
+ flexDirection: "column"
29190
+ },
29191
+ onClick: () => {
29192
+ },
29193
+ children: [
29194
+ /* @__PURE__ */ jsxRuntime.jsx(
29195
+ material.Box,
29196
+ {
29197
+ sx: {
29198
+ width: iconSize,
29199
+ height: iconSize,
29200
+ borderRadius: iconRadius,
29201
+ mb: 1.5,
29202
+ display: "flex",
29203
+ alignItems: "center",
29204
+ justifyContent: "center",
29205
+ background: getAppColor(app.category),
29206
+ boxShadow: isSelected ? `0 0 0 1px ${theme.palette.primary.main}, ${iconShadow}` : iconShadow
29207
+ },
29208
+ children: typeof app.icon === "string" && app.icon && /* @__PURE__ */ jsxRuntime.jsx(
29209
+ ImageElement,
29210
+ {
29211
+ sx: { width: iconSize * 0.56, height: iconSize * 0.56 },
29212
+ url: app.icon,
29213
+ sizeType: ImageSizeType.SQUARE
29214
+ }
29215
+ )
29216
+ }
29217
+ ),
29218
+ /* @__PURE__ */ jsxRuntime.jsx(
29219
+ material.Typography,
29220
+ {
29221
+ variant: titleVariant,
29222
+ sx: { color: titleColor ?? theme.palette.common.white },
29223
+ children: app.title
29224
+ }
29225
+ ),
29226
+ /* @__PURE__ */ jsxRuntime.jsx(
29227
+ material.Typography,
29228
+ {
29229
+ variant: captionVariant,
29230
+ sx: { color: captionColor ?? theme.palette.common.white },
29231
+ children: app.caption
29232
+ }
29233
+ )
29234
+ ]
29235
+ }
29236
+ )
29237
+ },
29238
+ app.key
29239
+ );
29240
+ })
29241
+ }
29242
+ ),
29243
+ showPagination && totalPages > 1 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
29244
+ page === totalPages - 1 && /* @__PURE__ */ jsxRuntime.jsx(
29245
+ material.IconButton,
29246
+ {
29247
+ size: "small",
29248
+ onClick: () => setPage((p) => Math.max(0, p - 1)),
29249
+ disabled: page === 0,
29250
+ sx: {
29251
+ position: "absolute",
29252
+ top: "50%",
29253
+ left: -30,
29254
+ transform: "translateY(-120%)",
29255
+ color: theme.palette.divider
29256
+ },
29257
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconLeft, {})
29258
+ }
29259
+ ),
29260
+ page !== totalPages - 1 && /* @__PURE__ */ jsxRuntime.jsx(
29261
+ material.IconButton,
29262
+ {
29263
+ size: "small",
29264
+ onClick: () => setPage((p) => Math.min(totalPages - 1, p + 1)),
29265
+ disabled: page === totalPages - 1,
29266
+ sx: {
29267
+ position: "absolute",
29268
+ top: "50%",
29269
+ right: -30,
29270
+ transform: "translateY(-120%)",
29271
+ color: theme.palette.divider
29272
+ },
29273
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconRight, {})
29274
+ }
29275
+ ),
29276
+ /* @__PURE__ */ jsxRuntime.jsx(
29277
+ material.Box,
29278
+ {
29279
+ sx: {
29280
+ mt: 2,
29281
+ display: "flex",
29282
+ alignItems: "center",
29283
+ justifyContent: "center"
29284
+ },
29285
+ children: /* @__PURE__ */ jsxRuntime.jsx(
29286
+ material.Box,
29287
+ {
29288
+ sx: {
29289
+ display: "flex",
29290
+ alignItems: "center",
29291
+ gap: PADDING_GAP_BUTTON,
29292
+ px: PADDING_GAP_BUTTON,
29293
+ py: PADDING_GAP_ITEM_SMALL,
29294
+ borderRadius: BORDER_RADIUS_ELEMENT_WRAPPER,
29295
+ backgroundColor: "rgba(255,255,255,0.15)"
29296
+ },
29297
+ children: Array.from({ length: totalPages }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
29298
+ material.Box,
29299
+ {
29300
+ onClick: () => setPage(i),
29301
+ sx: {
29302
+ height: 10,
29303
+ borderRadius: BORDER_RADIUS_ELEMENT_WRAPPER,
29304
+ cursor: "pointer",
29305
+ transition: "width 0.3s ease",
29306
+ width: i === page ? "40px" : "10px",
29307
+ backgroundColor: i === page ? theme.palette.common.white : "rgba(255,255,255,0.35)"
29308
+ }
29309
+ },
29310
+ i
29311
+ ))
29312
+ }
29313
+ )
29314
+ }
29315
+ )
29316
+ ] })
29317
+ ] });
29318
+ };
29319
+ const ArrowTooltip = emStyled(({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(material.Tooltip, { ...props, arrow: true, classes: { popper: className } }))(() => ({
29320
+ [`& .${material.tooltipClasses.arrow}`]: {
29321
+ color: "white"
29695
29322
  }
29696
- };
29697
- const featureBundle = {
29698
- ...animations,
29699
- ...gestureAnimations,
29700
- ...drag,
29701
- ...layout
29702
- };
29703
- const motion = /* @__PURE__ */ createMotionProxy(featureBundle, createDomVisualElement);
29704
- const animationPresets = {
29705
- fadeInUp: {
29706
- initial: { opacity: 0, y: 50 },
29707
- animate: { opacity: 1, y: 0 },
29708
- transition: { duration: 0.2, ease: "easeOut" }
29709
- },
29710
- fadeInDown: {
29711
- initial: { opacity: 0, y: -50 },
29712
- animate: { opacity: 1, y: 0 },
29713
- transition: { duration: 0.3, ease: "easeOut" }
29714
- },
29715
- fadeInLeft: {
29716
- initial: { opacity: 0, x: -50 },
29717
- animate: { opacity: 1, x: 0 },
29718
- transition: { duration: 0.3, ease: "easeOut" }
29719
- },
29720
- fadeInRight: {
29721
- initial: { opacity: 0, x: 50 },
29722
- animate: { opacity: 1, x: 0 },
29723
- transition: { duration: 0.3, ease: "easeOut" }
29724
- },
29725
- scaleIn: {
29726
- initial: { opacity: 0, scale: 0.9 },
29727
- animate: { opacity: 1, scale: 1 },
29728
- transition: { duration: 0.3, ease: "easeOut" }
29729
- },
29730
- slideInUp: {
29731
- initial: { opacity: 0, y: 20 },
29732
- animate: { opacity: 1, y: 0 },
29733
- transition: { duration: 0.4, ease: "easeOut" }
29734
- },
29735
- staggerItem: {
29736
- initial: { opacity: 0, y: 30, scale: 0.9 },
29737
- animate: { opacity: 1, y: 0, scale: 1 },
29738
- transition: { duration: 0.4, delay: 0, ease: "easeOut" }
29739
- },
29740
- tabContent: {
29741
- initial: { opacity: 0, y: 20 },
29742
- animate: { opacity: 1, y: 0 },
29743
- transition: { duration: 0.4, ease: "easeOut" }
29744
- },
29745
- tabUnderline: {
29746
- initial: { scaleX: 0, opacity: 0 },
29747
- animate: { scaleX: 1, opacity: 1 },
29748
- exit: { scaleX: 0, opacity: 0 },
29749
- transition: { duration: 0.3, ease: "easeInOut" }
29323
+ }));
29324
+ const AvatarElement = ({
29325
+ url: url2,
29326
+ sx = {},
29327
+ size = "medium",
29328
+ tooltipContent,
29329
+ ...rest
29330
+ }) => {
29331
+ if (tooltipContent) {
29332
+ return /* @__PURE__ */ jsxRuntime.jsx(ArrowTooltip, { title: tooltipContent, arrow: true, children: /* @__PURE__ */ jsxRuntime.jsx(
29333
+ material.Avatar,
29334
+ {
29335
+ ...rest,
29336
+ src: url2 || "",
29337
+ sx: { ...MAP_SIZE[size], bgcolor: "primary.main", ...sx, cursor: "pointer" }
29338
+ }
29339
+ ) });
29750
29340
  }
29341
+ return /* @__PURE__ */ jsxRuntime.jsx(material.Avatar, { ...rest, src: url2 || "", sx: { ...MAP_SIZE[size], bgcolor: "primary.main", ...sx, cursor: "pointer" } });
29751
29342
  };
29752
- const MotionBox = ({
29343
+ const AvatarUserInfo = ({
29344
+ name,
29345
+ url: url2,
29346
+ positions = [],
29347
+ maxWidth: maxWidth2 = "440px",
29348
+ isTag = false,
29349
+ sxName,
29350
+ sxPosition,
29351
+ sizeAvatar = "large"
29352
+ }) => {
29353
+ const { palette } = material.useTheme();
29354
+ const isSystemMonitor = useIsSystemMonitor();
29355
+ return /* @__PURE__ */ jsxRuntime.jsxs(StackRow, { sx: { alignItems: "center", gap: PADDING_GAP_ITEM }, children: [
29356
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarElement, { url: url2, size: sizeAvatar }),
29357
+ positions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(material.Stack, { sx: { gap: 0 }, children: [
29358
+ /* @__PURE__ */ jsxRuntime.jsx(
29359
+ material.Typography,
29360
+ {
29361
+ sx: {
29362
+ color: isSystemMonitor ? palette.primary.contrastText : palette.text.secondary,
29363
+ fontWeight: "600",
29364
+ fontSize: "14px",
29365
+ lineHeight: "20px",
29366
+ ...getLimitLineCss(1),
29367
+ ...sxName
29368
+ },
29369
+ children: name
29370
+ }
29371
+ ),
29372
+ /* @__PURE__ */ jsxRuntime.jsx(
29373
+ material.Typography,
29374
+ {
29375
+ variant: "caption",
29376
+ sx: {
29377
+ ...getLimitLineCss(1),
29378
+ color: palette.text.disabled,
29379
+ maxWidth: maxWidth2,
29380
+ ...isTag && {
29381
+ display: "flex",
29382
+ padding: "2px 4px",
29383
+ justifyContent: "center",
29384
+ alignItems: "center",
29385
+ gap: "10px",
29386
+ borderRadius: "4px",
29387
+ background: " #EFF8FF",
29388
+ color: " #035388",
29389
+ width: "fit-content",
29390
+ ...sxPosition
29391
+ }
29392
+ },
29393
+ children: positions.join(" / ")
29394
+ }
29395
+ )
29396
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
29397
+ material.Typography,
29398
+ {
29399
+ sx: {
29400
+ ...TYPOGRAPHY_STYLES.textSm.semiBold,
29401
+ ...getLimitLineCss(1),
29402
+ ...sxName
29403
+ },
29404
+ children: name
29405
+ }
29406
+ )
29407
+ ] });
29408
+ };
29409
+ const RadioGroupElement = ({
29410
+ name,
29411
+ direction = "row",
29412
+ label,
29413
+ disabled,
29414
+ iconLabel = "event_list",
29415
+ defaultValue,
29416
+ value: value2,
29417
+ onChange,
29753
29418
  children,
29754
- sx,
29755
- onClick,
29756
- preset = "fadeInUp",
29757
- delay: delay2,
29758
- index,
29759
- hover: hover2 = false,
29760
- ...motionProps
29419
+ required = false,
29420
+ sx = {}
29761
29421
  }) => {
29762
- const getAnimationProps = () => {
29763
- if (preset) {
29764
- const presetConfig = animationPresets[preset];
29765
- if (preset === "staggerItem" && index !== void 0) {
29766
- return {
29767
- ...presetConfig,
29768
- transition: {
29769
- ...presetConfig.transition,
29770
- delay: index * 0.05 + (delay2 || 0)
29771
- }
29772
- };
29422
+ const change = (event) => {
29423
+ onChange && onChange({ target: { name, value: event.target.value || void 0 } });
29424
+ };
29425
+ return /* @__PURE__ */ jsxRuntime.jsxs(material.FormControl, { disabled, sx: { gap: PADDING_GAP_ITEM }, onChange: change, children: [
29426
+ label && /* @__PURE__ */ jsxRuntime.jsx(
29427
+ material.InputLabel,
29428
+ {
29429
+ shrink: true,
29430
+ required,
29431
+ sx: {
29432
+ transform: "translate(0px , -9px) scale(0.75)",
29433
+ zIndex: 2,
29434
+ display: "flex"
29435
+ },
29436
+ children: /* @__PURE__ */ jsxRuntime.jsxs(StackLabel, { children: [
29437
+ /* @__PURE__ */ jsxRuntime.jsx(IconElement, { icon: iconLabel, sx: { fontSize: TEXT_FIELD.FONT_SIZE_LABEL } }),
29438
+ label
29439
+ ] })
29440
+ }
29441
+ ),
29442
+ /* @__PURE__ */ jsxRuntime.jsx(
29443
+ material.RadioGroup,
29444
+ {
29445
+ name,
29446
+ defaultValue,
29447
+ value: value2,
29448
+ sx: {
29449
+ flexDirection: direction,
29450
+ paddingTop: label ? "calc(8.5px + 1.5px)" : 0,
29451
+ // 8.5 lấy từ default theme không phải tự nhiên mà có
29452
+ gap: PADDING_GAP_LAYOUT,
29453
+ ...sx
29454
+ },
29455
+ children
29773
29456
  }
29774
- if (delay2 !== void 0) {
29775
- return {
29776
- ...presetConfig,
29777
- transition: {
29778
- ...presetConfig.transition,
29779
- delay: delay2
29457
+ )
29458
+ ] });
29459
+ };
29460
+ const RadioElement = ({ name, label, ...rest }) => {
29461
+ return /* @__PURE__ */ jsxRuntime.jsx(
29462
+ material.FormControlLabel,
29463
+ {
29464
+ name,
29465
+ label,
29466
+ sx: { alignItems: "center", mr: 0 },
29467
+ control: /* @__PURE__ */ jsxRuntime.jsx(
29468
+ material.Radio,
29469
+ {
29470
+ ...rest,
29471
+ sx: {
29472
+ paddingTop: 0,
29473
+ paddingBottom: 0,
29474
+ paddingRight: PADDING_GAP_ITEM,
29475
+ marginLeft: "2px",
29476
+ "&:hover": { backgroundColor: "unset" },
29477
+ "& .MuiSvgIcon-root": { fontSize: "18px" }
29780
29478
  }
29781
- };
29782
- }
29783
- return presetConfig;
29784
- }
29785
- return {};
29786
- };
29787
- const hoverProps = hover2 ? {
29788
- whileHover: {
29789
- y: -4,
29790
- scale: 1.05,
29791
- transition: { duration: 0.2 }
29479
+ }
29480
+ )
29792
29481
  }
29793
- } : {};
29794
- return /* @__PURE__ */ jsxRuntime.jsx(motion.div, { ...motionProps, ...getAnimationProps(), ...hoverProps, onClick, style: { ...sx }, children });
29482
+ );
29795
29483
  };
29796
- const AppGrid = ({
29797
- apps,
29798
- onClickItem,
29799
- columns = 5,
29800
- rows = 3,
29801
- iconSize = 80,
29802
- iconRadius = 7,
29803
- iconShadow = `0 ${PADDING_GAP_ITEM_SMALL} ${PADDING_GAP_LAYOUT} ${BORDER_COLOR_CARD}`,
29804
- gap: gap2 = PADDING_GAP_ITEM,
29805
- titleVariant = "subtitle1",
29806
- captionVariant = "caption",
29807
- titleColor,
29808
- captionColor,
29809
- selectedAppId,
29810
- showPagination = true
29811
- }) => {
29812
- const theme = useTheme();
29813
- const pageSize = Math.max(1, columns * Math.max(1, rows));
29814
- const totalPages = Math.max(1, Math.ceil(apps.length / pageSize));
29815
- const [page, setPage] = React.useState(0);
29816
- const { user } = reactRedux.useSelector((state) => state.account);
29817
- React.useEffect(() => {
29818
- setPage((prev) => prev >= totalPages ? totalPages - 1 : prev);
29819
- }, [totalPages, columns, rows, apps.length]);
29820
- const start = page * pageSize;
29821
- const end = start + pageSize;
29822
- const visibleApps = totalPages > 1 ? apps.slice(start, end) : apps;
29823
- const findLink = (app) => {
29824
- if (!app.children?.length) {
29825
- return app.path;
29826
- }
29827
- for (const i of app.children || []) {
29828
- if (user?.type && i.allowUserTypes.includes(user?.type)) {
29829
- if (i.path) {
29830
- return `${i.path}`;
29484
+ const AvatarUserComponent = ({}) => {
29485
+ const account = reactRedux.useSelector((state) => state.account);
29486
+ const { showSnackbar } = useSnackbar();
29487
+ const dispatch = useAppDispatch();
29488
+ const navigate = reactRouterDom.useNavigate();
29489
+ const [anchorEl, setAnchorEl] = React.useState(null);
29490
+ const positions = account?.user?.managedOrgUnits?.map((e) => e.name) || [];
29491
+ const menu = [
29492
+ {
29493
+ content: "Đăng xuất khỏi thiết bị",
29494
+ icon: "logout",
29495
+ onClick: async () => {
29496
+ try {
29497
+ await Promise.all([
29498
+ dispatch(
29499
+ ACTION_ACCOUNT.logout({
29500
+ type: LogoutType.THIS_DEVICE,
29501
+ refreshToken: account.refreshToken
29502
+ })
29503
+ ).unwrap()
29504
+ ]);
29505
+ navigate(PAGE.AUTH.path);
29506
+ } catch (error) {
29507
+ showSnackbar({
29508
+ message: getErrorMessage(error),
29509
+ type: SnackbarType.ERROR
29510
+ });
29511
+ }
29512
+ }
29513
+ },
29514
+ {
29515
+ content: "Đăng xuất khỏi tất cả thiết bị",
29516
+ icon: "exit_to_app",
29517
+ onClick: async () => {
29518
+ if ("serviceWorker" in navigator) {
29519
+ navigator.serviceWorker.getRegistrations().then((registrations) => {
29520
+ registrations.forEach((registration) => {
29521
+ registration.unregister();
29522
+ });
29523
+ }).catch((error) => {
29524
+ console.error("Error unregistering Service Workers: ", error);
29525
+ });
29526
+ } else {
29527
+ console.warn("Service Worker is not supported in this browser.");
29831
29528
  }
29529
+ await dispatch(
29530
+ ACTION_ACCOUNT.logout({
29531
+ type: LogoutType.THIS_DEVICE,
29532
+ refreshToken: account.refreshToken
29533
+ })
29534
+ ).unwrap();
29535
+ navigate(PAGE.AUTH.path);
29832
29536
  }
29833
29537
  }
29538
+ ];
29539
+ const handleClick = (event) => {
29540
+ setAnchorEl(event.currentTarget);
29834
29541
  };
29835
- return /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { sx: { position: "relative" }, children: [
29836
- /* @__PURE__ */ jsxRuntime.jsx(
29542
+ const handleClose = () => {
29543
+ setAnchorEl(null);
29544
+ };
29545
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
29546
+ /* @__PURE__ */ jsxRuntime.jsxs(
29837
29547
  material.Box,
29838
29548
  {
29549
+ onClick: handleClick,
29839
29550
  sx: {
29840
- display: "grid",
29841
- gridTemplateColumns: `repeat(${columns}, 1fr)`,
29842
- gap: gap2
29551
+ cursor: "pointer",
29552
+ display: "flex",
29553
+ alignItems: "center",
29554
+ gap: 1
29843
29555
  },
29844
- children: visibleApps.map((app, index) => {
29845
- const isSelected = selectedAppId === app.key;
29846
- return /* @__PURE__ */ jsxRuntime.jsx(
29847
- "a",
29556
+ children: [
29557
+ /* @__PURE__ */ jsxRuntime.jsx(
29558
+ AvatarUserInfo,
29848
29559
  {
29849
- href: findLink(app) || "#",
29850
- target: "_blank",
29851
- rel: "noopener noreferrer",
29852
- style: {
29853
- textDecoration: "none",
29854
- color: "inherit",
29855
- width: "100%",
29856
- display: "block"
29857
- },
29858
- onClick: (e) => {
29859
- const url2 = findLink(app);
29860
- e.preventDefault();
29861
- onClickItem?.(app);
29862
- if (url2 && url2 !== "#") {
29863
- try {
29864
- window.open(url2, "_blank", "noopener");
29865
- } catch (err) {
29866
- const newWindow = window.open("about:blank");
29867
- if (newWindow) newWindow.location.href = url2;
29868
- }
29560
+ url: account.user?.url,
29561
+ name: account.user?.name ?? "",
29562
+ positions,
29563
+ isTag: true
29564
+ }
29565
+ ),
29566
+ /* @__PURE__ */ jsxRuntime.jsx(
29567
+ IconElement,
29568
+ {
29569
+ icon: "arrow_drop_down",
29570
+ size: "medium",
29571
+ sx: {
29572
+ color: "text.secondary",
29573
+ transition: "transform 0.2s ease-in-out",
29574
+ transform: anchorEl ? "rotate(180deg)" : "rotate(0deg)",
29575
+ fontVariationSettings: "'wght' 600, 'FILL' 0",
29576
+ willChange: "transform",
29577
+ backfaceVisibility: "hidden"
29578
+ }
29579
+ }
29580
+ )
29581
+ ]
29582
+ }
29583
+ ),
29584
+ /* @__PURE__ */ jsxRuntime.jsxs(
29585
+ material.Menu,
29586
+ {
29587
+ anchorEl,
29588
+ open: Boolean(anchorEl),
29589
+ onClose: handleClose,
29590
+ onClick: handleClose,
29591
+ disableScrollLock: true,
29592
+ PaperProps: {
29593
+ elevation: 0,
29594
+ sx: {
29595
+ overflow: "visible",
29596
+ filter: "drop-shadow(0px 2px 8px rgba(0,0,0,0.32))",
29597
+ mt: 1.5,
29598
+ transform: "translate3d(0, 0, 0)",
29599
+ willChange: "transform",
29600
+ "& .MuiAvatar-root": {
29601
+ width: 32,
29602
+ height: 32,
29603
+ ml: -0.5,
29604
+ mr: 1
29605
+ },
29606
+ "&:before": {
29607
+ content: '""',
29608
+ display: "block",
29609
+ position: "absolute",
29610
+ top: 0,
29611
+ right: 14,
29612
+ width: 10,
29613
+ height: 10,
29614
+ bgcolor: "background.paper",
29615
+ transform: "translateY(-50%) rotate(45deg)",
29616
+ zIndex: 0
29617
+ }
29618
+ }
29619
+ },
29620
+ transformOrigin: { horizontal: "right", vertical: "top" },
29621
+ anchorOrigin: { horizontal: "right", vertical: "bottom" },
29622
+ children: [
29623
+ /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { sx: { p: 2 }, children: [
29624
+ /* @__PURE__ */ jsxRuntime.jsxs(StackRowAlignStartJustBetween, { children: [
29625
+ /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { variant: "subtitle1", sx: { lineHeight: 1 }, children: account.user?.name }),
29626
+ /* @__PURE__ */ jsxRuntime.jsx(
29627
+ IconElement,
29628
+ {
29629
+ icon: "settings",
29630
+ onClick: () => navigate(PAGE.DASHBOARD.path + DASHBOARD_SCREEN.ACCOUNT.path)
29631
+ }
29632
+ )
29633
+ ] }),
29634
+ account.user?.userOrgUnitPositions && account.user.userOrgUnitPositions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
29635
+ /* @__PURE__ */ jsxRuntime.jsx(
29636
+ IconContentElement,
29637
+ {
29638
+ icon: "admin_panel_settings",
29639
+ content: "Vai trò"
29869
29640
  }
29870
- },
29871
- children: /* @__PURE__ */ jsxRuntime.jsxs(
29872
- MotionBox,
29641
+ ),
29642
+ /* @__PURE__ */ jsxRuntime.jsx(
29643
+ RadioGroupElement,
29873
29644
  {
29874
- preset: "staggerItem",
29875
- index,
29876
- hover: true,
29877
- sx: {
29878
- cursor: "pointer",
29879
- display: "flex",
29880
- flex: 1,
29881
- alignItems: "center",
29882
- flexDirection: "column"
29883
- },
29884
- onClick: () => {
29645
+ direction: "column",
29646
+ sx: { paddingLeft: "20px" },
29647
+ value: account.userUnitPositionId,
29648
+ onChange: (event) => {
29649
+ dispatch(
29650
+ ACTION_ACCOUNT.updatePositionOrgUnit(event.target.value)
29651
+ );
29652
+ window.location.reload();
29885
29653
  },
29886
- children: [
29887
- /* @__PURE__ */ jsxRuntime.jsx(
29888
- material.Box,
29889
- {
29890
- sx: {
29891
- width: iconSize,
29892
- height: iconSize,
29893
- borderRadius: iconRadius,
29894
- mb: 1.5,
29895
- display: "flex",
29896
- alignItems: "center",
29897
- justifyContent: "center",
29898
- background: getAppColor(app.category),
29899
- boxShadow: isSelected ? `0 0 0 1px ${theme.palette.primary.main}, ${iconShadow}` : iconShadow
29900
- },
29901
- children: typeof app.icon === "string" && app.icon && /* @__PURE__ */ jsxRuntime.jsx(
29902
- ImageElement,
29654
+ children: account.user.userOrgUnitPositions.map((e) => /* @__PURE__ */ jsxRuntime.jsx(
29655
+ RadioElement,
29656
+ {
29657
+ value: e.id,
29658
+ size: "small",
29659
+ label: /* @__PURE__ */ jsxRuntime.jsxs(system.Stack, { gap: 0, children: [
29660
+ /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { children: e.orgUnit.name }),
29661
+ /* @__PURE__ */ jsxRuntime.jsx(
29662
+ material.Typography,
29903
29663
  {
29904
- sx: { width: iconSize * 0.56, height: iconSize * 0.56 },
29905
- url: app.icon,
29906
- sizeType: ImageSizeType.SQUARE
29664
+ variant: "caption",
29665
+ sx: {
29666
+ ...getLimitLineCss(1),
29667
+ color: "text.disabled"
29668
+ },
29669
+ children: e.position.name
29907
29670
  }
29908
29671
  )
29909
- }
29910
- ),
29911
- /* @__PURE__ */ jsxRuntime.jsx(
29912
- material.Typography,
29913
- {
29914
- variant: titleVariant,
29915
- sx: { color: titleColor ?? theme.palette.common.white },
29916
- children: app.title
29917
- }
29918
- ),
29919
- /* @__PURE__ */ jsxRuntime.jsx(
29920
- material.Typography,
29921
- {
29922
- variant: captionVariant,
29923
- sx: { color: captionColor ?? theme.palette.common.white },
29924
- children: app.caption
29925
- }
29926
- )
29927
- ]
29672
+ ] })
29673
+ },
29674
+ e.id
29675
+ ))
29928
29676
  }
29929
29677
  )
29930
- },
29931
- app.key
29932
- );
29933
- })
29678
+ ] })
29679
+ ] }),
29680
+ /* @__PURE__ */ jsxRuntime.jsx(material.Divider, {}),
29681
+ menu.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(material.MenuItem, { onClick: item.onClick, children: [
29682
+ /* @__PURE__ */ jsxRuntime.jsx(IconElement, { icon: item.icon, size: "small", sx: { mr: 1 } }),
29683
+ /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { children: item.content })
29684
+ ] }, index))
29685
+ ]
29934
29686
  }
29935
- ),
29936
- showPagination && totalPages > 1 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
29937
- page === totalPages - 1 && /* @__PURE__ */ jsxRuntime.jsx(
29938
- material.IconButton,
29939
- {
29940
- size: "small",
29941
- onClick: () => setPage((p) => Math.max(0, p - 1)),
29942
- disabled: page === 0,
29943
- sx: {
29944
- position: "absolute",
29945
- top: "50%",
29946
- left: -30,
29947
- transform: "translateY(-120%)",
29948
- color: theme.palette.divider
29949
- },
29950
- children: /* @__PURE__ */ jsxRuntime.jsx(IconLeft, {})
29951
- }
29952
- ),
29953
- page !== totalPages - 1 && /* @__PURE__ */ jsxRuntime.jsx(
29954
- material.IconButton,
29955
- {
29956
- size: "small",
29957
- onClick: () => setPage((p) => Math.min(totalPages - 1, p + 1)),
29958
- disabled: page === totalPages - 1,
29959
- sx: {
29960
- position: "absolute",
29961
- top: "50%",
29962
- right: -30,
29963
- transform: "translateY(-120%)",
29964
- color: theme.palette.divider
29965
- },
29966
- children: /* @__PURE__ */ jsxRuntime.jsx(IconRight, {})
29967
- }
29968
- ),
29969
- /* @__PURE__ */ jsxRuntime.jsx(
29970
- material.Box,
29971
- {
29972
- sx: {
29973
- mt: 2,
29974
- display: "flex",
29975
- alignItems: "center",
29976
- justifyContent: "center"
29977
- },
29978
- children: /* @__PURE__ */ jsxRuntime.jsx(
29979
- material.Box,
29980
- {
29981
- sx: {
29982
- display: "flex",
29983
- alignItems: "center",
29984
- gap: PADDING_GAP_BUTTON,
29985
- px: PADDING_GAP_BUTTON,
29986
- py: PADDING_GAP_ITEM_SMALL,
29987
- borderRadius: BORDER_RADIUS_ELEMENT_WRAPPER,
29988
- backgroundColor: "rgba(255,255,255,0.15)"
29989
- },
29990
- children: Array.from({ length: totalPages }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
29991
- material.Box,
29992
- {
29993
- onClick: () => setPage(i),
29994
- sx: {
29995
- height: 10,
29996
- borderRadius: BORDER_RADIUS_ELEMENT_WRAPPER,
29997
- cursor: "pointer",
29998
- transition: "width 0.3s ease",
29999
- width: i === page ? "40px" : "10px",
30000
- backgroundColor: i === page ? theme.palette.common.white : "rgba(255,255,255,0.35)"
30001
- }
30002
- },
30003
- i
30004
- ))
30005
- }
30006
- )
30007
- }
30008
- )
30009
- ] })
29687
+ )
30010
29688
  ] });
30011
29689
  };
29690
+ const EmptyComponent = ({}) => {
29691
+ return /* @__PURE__ */ jsxRuntime.jsx(material.Fade, { in: true, timeout: ANIMATION_TIME, children: /* @__PURE__ */ jsxRuntime.jsx(
29692
+ material.Stack,
29693
+ {
29694
+ direction: "column",
29695
+ sx: {
29696
+ flex: 1,
29697
+ height: "100%",
29698
+ alignItems: "center",
29699
+ justifyContent: "center",
29700
+ padding: PADDING_GAP_ITEM
29701
+ },
29702
+ children: /* @__PURE__ */ jsxRuntime.jsx(material.Box, { component: "img", sx: { width: 70 }, src: "/images/empty.svg" })
29703
+ }
29704
+ ) });
29705
+ };
29706
+ const TimeAgoComponent = ({
29707
+ time: time2,
29708
+ hasText
29709
+ }) => {
29710
+ return /* @__PURE__ */ jsxRuntime.jsx(
29711
+ material.Typography,
29712
+ {
29713
+ variant: "caption",
29714
+ sx: { ...getLimitLineCss(1), color: "text.disabled", lineHeight: 1.2 },
29715
+ children: (hasText ? "Cập nhật lúc " : "") + timeUtils.getTimeAgo(time2)
29716
+ }
29717
+ );
29718
+ };
29719
+ const TimeAgoContentComponent = ({ time: time2, content, height: height2 = HEIGHT_IMAGE_DEFAULT }) => {
29720
+ return /* @__PURE__ */ jsxRuntime.jsxs(
29721
+ system.Stack,
29722
+ {
29723
+ sx: {
29724
+ height: height2,
29725
+ gap: 0,
29726
+ justifyContent: "space-between",
29727
+ alignItems: "flex-start"
29728
+ },
29729
+ children: [
29730
+ /* @__PURE__ */ jsxRuntime.jsx(
29731
+ material.Typography,
29732
+ {
29733
+ sx: {
29734
+ ...getLimitLineCss(1)
29735
+ },
29736
+ children: content
29737
+ }
29738
+ ),
29739
+ /* @__PURE__ */ jsxRuntime.jsx(TimeAgoComponent, { time: time2 })
29740
+ ]
29741
+ }
29742
+ );
29743
+ };
30012
29744
  const AppsSidebar = ({
30013
29745
  isOpen,
30014
29746
  onClose,
@@ -30243,6 +29975,36 @@ const TypographyContentCaption = ({
30243
29975
  )
30244
29976
  ] });
30245
29977
  };
29978
+ const TooltipOnClickElement = ({
29979
+ open,
29980
+ placement = "top",
29981
+ content,
29982
+ children,
29983
+ onOpen,
29984
+ onClose,
29985
+ onClickAway,
29986
+ ...rest
29987
+ }) => {
29988
+ return (
29989
+ // Chỗ này có thể là bug, onClickAway apply ngay cả khi component chưa được render
29990
+ /* @__PURE__ */ jsxRuntime.jsx(material.ClickAwayListener, { onClickAway, children: /* @__PURE__ */ jsxRuntime.jsx(
29991
+ material.Tooltip,
29992
+ {
29993
+ PopperProps: { disablePortal: true },
29994
+ open,
29995
+ onOpen,
29996
+ onClose,
29997
+ disableFocusListener: true,
29998
+ disableHoverListener: true,
29999
+ disableTouchListener: true,
30000
+ placement,
30001
+ title: content,
30002
+ ...rest,
30003
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { children })
30004
+ }
30005
+ ) })
30006
+ );
30007
+ };
30246
30008
  const TypographyFilter = material.styled(material.Typography)(({ theme }) => ({
30247
30009
  height: HEIGHT_ELEMENT_OTHER,
30248
30010
  border: `1px solid ${theme.palette.divider}`,
@@ -30527,7 +30289,6 @@ exports.AvatarUserComponent = AvatarUserComponent;
30527
30289
  exports.AvatarUserInfo = AvatarUserInfo;
30528
30290
  exports.BOOKING_SCREEN = BOOKING_SCREEN;
30529
30291
  exports.BUTTON_BACK_ICON_CONTENT = BUTTON_BACK_ICON_CONTENT;
30530
- exports.BellComponent = BellComponent;
30531
30292
  exports.BorderLinearProgress = BorderLinearProgress;
30532
30293
  exports.ButtonElement = ButtonElement;
30533
30294
  exports.DASHBOARD_BASE = DASHBOARD_BASE;
@@ -30548,7 +30309,6 @@ exports.LogoutType = LogoutType;
30548
30309
  exports.MAP_SIZE = MAP_SIZE;
30549
30310
  exports.MODE = MODE;
30550
30311
  exports.Mode = Mode;
30551
- exports.MonitorPart = MonitorPart;
30552
30312
  exports.MotionBox = MotionBox;
30553
30313
  exports.NotFoundPage = NotFoundPage;
30554
30314
  exports.NotificationStatus = NotificationStatus;