forked from ddrilling/asb_cloud_front
111 lines
4.9 KiB
TypeScript
111 lines
4.9 KiB
TypeScript
|
import { Button, Layout, LayoutProps, Menu, SiderProps } from 'antd'
|
|||
|
import { HTMLProps, Key, memo, ReactNode, useEffect, useMemo, useState } from 'react'
|
|||
|
import { ItemType } from 'antd/lib/menu/hooks/useItems'
|
|||
|
import { Link } from 'react-router-dom'
|
|||
|
import {
|
|||
|
ApartmentOutlined,
|
|||
|
CodeOutlined,
|
|||
|
HomeOutlined,
|
|||
|
MenuFoldOutlined,
|
|||
|
MenuUnfoldOutlined,
|
|||
|
UserOutlined,
|
|||
|
} from '@ant-design/icons'
|
|||
|
|
|||
|
import PageHeader from '@components/PageHeader'
|
|||
|
import { UserMenu, UserMenuProps } from '@components/UserMenu'
|
|||
|
import { WellTreeSelector, WellTreeSelectorProps } from '@components/selectors/WellTreeSelector'
|
|||
|
import { isURLAvailable, wrapPrivateComponent } from '@utils'
|
|||
|
|
|||
|
import '@styles/layout.less'
|
|||
|
|
|||
|
const { Content, Sider } = Layout
|
|||
|
|
|||
|
export type LayoutPortalProps = HTMLProps<HTMLDivElement> & {
|
|||
|
title?: ReactNode
|
|||
|
noSheet?: boolean
|
|||
|
showSelector?: boolean
|
|||
|
selectorProps?: WellTreeSelectorProps
|
|||
|
sider?: boolean | JSX.Element
|
|||
|
siderProps?: SiderProps & { userMenuProps?: UserMenuProps }
|
|||
|
isAdmin?: boolean
|
|||
|
}
|
|||
|
|
|||
|
const makeItem = (title: string, key: Key, icon: JSX.Element, label?: ReactNode, onClick?: () => void) => ({ icon, key, title, label: label ?? title, onClick })
|
|||
|
|
|||
|
const _LayoutPortal = memo<LayoutPortalProps>(({ isAdmin, title, noSheet, showSelector, selectorProps, sider, siderProps, ...props }) => {
|
|||
|
const [menuCollapsed, setMenuCollapsed] = useState<boolean>(true)
|
|||
|
const [wellsTreeOpen, setWellsTreeOpen] = useState<boolean>(false)
|
|||
|
const [userMenuOpen, setUserMenuOpen] = useState<boolean>(false)
|
|||
|
const [currentWell, setCurrentWell] = useState<string>('')
|
|||
|
|
|||
|
useEffect(() => {
|
|||
|
if (typeof showSelector === 'boolean')
|
|||
|
setWellsTreeOpen(showSelector)
|
|||
|
}, [showSelector])
|
|||
|
|
|||
|
const menuItems = useMemo(() => [
|
|||
|
!isAdmin && makeItem(currentWell, 'well', <ApartmentOutlined/>, null, () => setWellsTreeOpen((prev) => !prev)),
|
|||
|
isAdmin && makeItem('Вернуться на сайт', 'go_back', <HomeOutlined />, <Link to={'/'}>Домой</Link>),
|
|||
|
!isAdmin && isURLAvailable('/admin') && makeItem('Панель администратора', 'admin_panel', <CodeOutlined />, <Link to={'/admin'}>Панель администратора</Link>),
|
|||
|
makeItem('Профиль', 'profile', <UserOutlined/>, null, () => setUserMenuOpen((prev) => !prev)),
|
|||
|
].filter(Boolean) as ItemType[], [isAdmin, currentWell])
|
|||
|
|
|||
|
return (
|
|||
|
<Layout className={`page-layout ${isAdmin ? 'page-layout-admin' : ''}`}>
|
|||
|
{(sider || siderProps) && (
|
|||
|
<Sider {...siderProps} collapsed={menuCollapsed} trigger={null} collapsible className={`menu-sider ${siderProps?.className || ''}`}>
|
|||
|
<div className={'sider-content'}>
|
|||
|
<button className={'sider-toogle'} onClick={() => setMenuCollapsed((prev) => !prev)}>
|
|||
|
{menuCollapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
|
|||
|
</button>
|
|||
|
<div className={'scrollable hide-slider'}>
|
|||
|
{sider}
|
|||
|
</div>
|
|||
|
<Menu
|
|||
|
mode={'inline'}
|
|||
|
items={menuItems}
|
|||
|
inlineCollapsed
|
|||
|
theme={'dark'}
|
|||
|
selectable={false}
|
|||
|
/>
|
|||
|
<UserMenu
|
|||
|
open={userMenuOpen}
|
|||
|
onClose={() => setUserMenuOpen(false)}
|
|||
|
isAdmin={isAdmin}
|
|||
|
{...siderProps?.userMenuProps}
|
|||
|
/>
|
|||
|
</div>
|
|||
|
</Sider>
|
|||
|
)}
|
|||
|
<Layout className={'page-content'}>
|
|||
|
<PageHeader title={title}>
|
|||
|
{isAdmin ? (
|
|||
|
<Button size={'large'}>
|
|||
|
<Link to={'/'}>Вернуться на сайт</Link>
|
|||
|
</Button>
|
|||
|
) : (
|
|||
|
<>
|
|||
|
<WellTreeSelector
|
|||
|
open={wellsTreeOpen}
|
|||
|
onClose={() => setWellsTreeOpen(false)}
|
|||
|
{...selectorProps}
|
|||
|
onChange={(well) => setCurrentWell(well ?? 'Выберите месторождение')}
|
|||
|
/>
|
|||
|
<Button onClick={() => setWellsTreeOpen((prev) => !prev)}>{currentWell}</Button>
|
|||
|
</>
|
|||
|
)}
|
|||
|
</PageHeader>
|
|||
|
<Content>
|
|||
|
<div {...props} className={`${noSheet ? '' : 'site-layout-background sheet'} ${props.className}`} />
|
|||
|
</Content>
|
|||
|
</Layout>
|
|||
|
</Layout>
|
|||
|
)
|
|||
|
})
|
|||
|
|
|||
|
export const LayoutPortal = wrapPrivateComponent(_LayoutPortal, {
|
|||
|
requirements: ['Deposit.get'],
|
|||
|
})
|
|||
|
|
|||
|
export default LayoutPortal
|