- Consolidated JavaScript completion sources into a new module, improving organization and maintainability. - Updated the `fcTemplateLang` to utilize the new `javascriptCompletionSources` for enhanced autocomplete capabilities. - Removed redundant imports and streamlined the code in various components, including Invoices, Payments, TaxRecords, and Inventory sections, by replacing dropdown actions with a unified `ObjectActions` component. - Improved the handling of object actions across multiple inventory and finance components, enhancing user experience and code consistency.
164 lines
4.8 KiB
JavaScript
164 lines
4.8 KiB
JavaScript
import PropTypes from 'prop-types'
|
|
import { createElement, useContext, useEffect } from 'react'
|
|
import { Flex, Typography, Button, Space, Divider, Card } from 'antd'
|
|
import { UserOutlined } from '@ant-design/icons'
|
|
import { useNavigate, useLocation } from 'react-router-dom'
|
|
import LogoutIcon from '../../Icons/LogoutIcon'
|
|
import { User } from '../../../database/models/User'
|
|
import { buildActionUrl } from '../../../utils/modelActions'
|
|
import { AuthContext } from '../context/AuthContext'
|
|
import ObjectActions from './ObjectActions'
|
|
import ElipsisText from './ElipsisText'
|
|
|
|
const { Text } = Typography
|
|
|
|
const ICON_ACTION_NAMES = ['info', 'edit']
|
|
|
|
const UserProfilePopover = ({ onClose }) => {
|
|
const { userProfile, profileImageUrl, logout } = useContext(AuthContext)
|
|
const navigate = useNavigate()
|
|
const location = useLocation()
|
|
|
|
const modelActions = User.actions || []
|
|
const iconActions = modelActions.filter((a) =>
|
|
ICON_ACTION_NAMES.includes(a.name)
|
|
)
|
|
|
|
const objectData = { ...userProfile, _user: userProfile }
|
|
|
|
useEffect(() => {
|
|
onClose?.()
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [location.pathname, location.search])
|
|
|
|
const runAction = (action) => {
|
|
if (action.name === 'logout') {
|
|
logout()
|
|
} else if (userProfile?._id) {
|
|
const url = buildActionUrl(User, action, userProfile._id, '', '')
|
|
navigate(url)
|
|
}
|
|
onClose?.()
|
|
}
|
|
|
|
const isActionDisabled = (action) => {
|
|
if (action.disabled && typeof action.disabled === 'function') {
|
|
return action.disabled(objectData)
|
|
}
|
|
return false
|
|
}
|
|
|
|
const username = userProfile?.username
|
|
const fullName = [userProfile?.firstName, userProfile?.lastName]
|
|
.filter(Boolean)
|
|
.join(' ')
|
|
const email = userProfile?.email
|
|
|
|
return (
|
|
<Flex
|
|
align='center'
|
|
gap='middle'
|
|
style={{ minWidth: 240, padding: '0 1px' }}
|
|
>
|
|
<Flex align='center' gap='12px' style={{ flex: 1, minWidth: 0 }}>
|
|
{profileImageUrl ? (
|
|
<img
|
|
src={profileImageUrl}
|
|
alt=''
|
|
style={{
|
|
width: 76,
|
|
height: 76,
|
|
borderRadius: '5px',
|
|
objectFit: 'cover'
|
|
}}
|
|
/>
|
|
) : (
|
|
<Card
|
|
style={{ borderRadius: '5px', width: 76, height: 76 }}
|
|
styles={{ body: { padding: 0, height: '100%' } }}
|
|
>
|
|
<Flex justify='center' align='center' style={{ height: '100%' }}>
|
|
<UserOutlined
|
|
style={{
|
|
fontSize: 32,
|
|
color: 'var(--color-text-secondary)',
|
|
marginBottom: 2
|
|
}}
|
|
/>
|
|
</Flex>
|
|
</Card>
|
|
)}
|
|
<Flex vertical style={{ minWidth: 0 }}>
|
|
{fullName && (
|
|
<ElipsisText
|
|
strong
|
|
style={{ fontSize: 18, lineHeight: 1, marginTop: 1 }}
|
|
>
|
|
{fullName}
|
|
</ElipsisText>
|
|
)}
|
|
{email && (
|
|
<Space>
|
|
<Text
|
|
type='secondary'
|
|
strong
|
|
style={{ fontSize: 12, lineHeight: 1 }}
|
|
>
|
|
@{username}
|
|
</Text>
|
|
<ElipsisText
|
|
type='secondary'
|
|
style={{ fontSize: 12, lineHeight: 1 }}
|
|
>
|
|
{email}
|
|
</ElipsisText>
|
|
</Space>
|
|
)}
|
|
{!username && !fullName && !email && (
|
|
<Text type='secondary'>Unknown user</Text>
|
|
)}
|
|
<Divider style={{ margin: '5px 0' }} />
|
|
<Flex gap={'1px'}>
|
|
{iconActions.map((action) => (
|
|
<Button
|
|
key={action.name}
|
|
type='text'
|
|
size='small'
|
|
icon={action.icon ? createElement(action.icon) : undefined}
|
|
onClick={() => runAction(action)}
|
|
disabled={isActionDisabled(action)}
|
|
aria-label={action.label}
|
|
/>
|
|
))}
|
|
<Button
|
|
type='text'
|
|
size='small'
|
|
icon={createElement(LogoutIcon)}
|
|
onClick={() => runAction({ name: 'logout' })}
|
|
aria-label='Logout'
|
|
/>
|
|
{userProfile?._id && (
|
|
<ObjectActions
|
|
type='user'
|
|
pageName='info'
|
|
id={userProfile._id}
|
|
objectData={objectData}
|
|
visibleActions={{ info: false, edit: false }}
|
|
buttonProps={{ type: 'text', size: 'small' }}
|
|
trigger={['hover']}
|
|
placement='bottomLeft'
|
|
/>
|
|
)}
|
|
</Flex>
|
|
</Flex>
|
|
</Flex>
|
|
</Flex>
|
|
)
|
|
}
|
|
|
|
UserProfilePopover.propTypes = {
|
|
onClose: PropTypes.func
|
|
}
|
|
|
|
export default UserProfilePopover
|