146 lines
4.5 KiB
TypeScript
146 lines
4.5 KiB
TypeScript
import { useShallow } from 'zustand/react/shallow';
|
|
import { useLayoutStore } from './store';
|
|
import clsx from 'clsx';
|
|
import { Menu, MenuItem, Tooltip } from '@mui/material';
|
|
import { Button } from '@mui/material';
|
|
import { message } from '@/modules/message';
|
|
import SmileOutlined from '@ant-design/icons/SmileOutlined';
|
|
import SwitcherOutlined from '@ant-design/icons/SwitcherOutlined';
|
|
import { useMemo } from 'react';
|
|
import { query, queryLogin } from '../query';
|
|
import { useNewNavigate } from '../navicate';
|
|
import { LogOut, Map, SquareUser, Users, X } from 'lucide-react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import React from 'react';
|
|
|
|
export const LayoutUser = () => {
|
|
const { open, setOpen, ...store } = useLayoutStore(
|
|
useShallow((state) => ({
|
|
open: state.openUser, //
|
|
setOpen: state.setOpenUser,
|
|
me: state.me,
|
|
switchOrg: state.switchOrg,
|
|
})),
|
|
);
|
|
const navigate = useNewNavigate();
|
|
const { t } = useTranslation();
|
|
const meun = [
|
|
{
|
|
title: t('Your profile'),
|
|
icon: <SquareUser size={16} />,
|
|
link: '/user/profile',
|
|
},
|
|
{
|
|
title: t('Your orgs'),
|
|
icon: <SwitcherOutlined />,
|
|
link: '/org/edit/list',
|
|
},
|
|
{
|
|
title: t('Site Map'),
|
|
icon: <Map size={16} />,
|
|
link: '/map',
|
|
},
|
|
];
|
|
const items = useMemo(() => {
|
|
const orgs = store.me?.orgs || [];
|
|
return orgs.map((item) => {
|
|
return {
|
|
label: item,
|
|
key: item,
|
|
icon: <SmileOutlined />,
|
|
};
|
|
});
|
|
}, [store.me]);
|
|
|
|
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
|
|
|
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
|
|
setAnchorEl(event.currentTarget);
|
|
};
|
|
|
|
const handleClose = () => {
|
|
setAnchorEl(null);
|
|
};
|
|
|
|
return (
|
|
<div className={clsx('w-full h-full absolute z-20 no-drag ', !open && 'hidden')}>
|
|
<div
|
|
className='w-full absolute h-full opacity-60 z-0'
|
|
onClick={() => {
|
|
setOpen(false);
|
|
}}></div>
|
|
<div className='w-[400px] bg-amber-900 text-primary transition-all duration-300 h-full absolute top-0 right-0 rounded-l-lg'>
|
|
<div className='flex justify-between p-6 mt-4 font-bold items-center border-b'>
|
|
<div className='flex items-center gap-2'>
|
|
{t('User')}: <span className='text-primary'>{store.me?.username}</span>
|
|
</div>
|
|
<div className='flex gap-4'>
|
|
{items.length > 0 && (
|
|
<Tooltip title={t('Switch Org')}>
|
|
<Button aria-controls='switch-org-menu' aria-haspopup='true' onClick={handleClick}>
|
|
<Users />
|
|
</Button>
|
|
</Tooltip>
|
|
)}
|
|
|
|
<Button onClick={() => setOpen(false)}>
|
|
<X />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
<div className='mt-3 font-medium'>
|
|
{meun.map((item, index) => {
|
|
return (
|
|
<div
|
|
key={index}
|
|
className='flex items-center p-4 hover:bg-secondary hover:text-white cursor-pointer'
|
|
onClick={() => {
|
|
if (item.link) {
|
|
navigate(item.link);
|
|
setOpen(false);
|
|
} else {
|
|
message.info('Coming soon');
|
|
}
|
|
}}>
|
|
<div className='mr-4'>{item.icon}</div>
|
|
<div>{item.title}</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
<div
|
|
className='flex items-center p-4 hover:bg-secondary hover:text-white cursor-pointer'
|
|
onClick={async () => {
|
|
const res = await queryLogin.logout();
|
|
// console.log(res);
|
|
if (res.success) {
|
|
window.open('/user/login', '_self');
|
|
} else {
|
|
message.error(res.message || 'Logout failed');
|
|
}
|
|
}}>
|
|
<div className='mr-4'>
|
|
<LogOut size={16} />
|
|
</div>
|
|
<div>{t('Login Out')}</div>
|
|
</div>
|
|
</div>
|
|
<Menu id='simple-menu' anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={handleClose}>
|
|
{items.map((item, index) => {
|
|
return (
|
|
<MenuItem
|
|
key={index}
|
|
onClick={() => {
|
|
store.switchOrg(item.key, 'org');
|
|
handleClose();
|
|
}}>
|
|
<div className='mr-4'>{item.icon}</div>
|
|
<div>{item.label}</div>
|
|
</MenuItem>
|
|
);
|
|
})}
|
|
</Menu>
|
|
</div>
|
|
);
|
|
};
|