farmcontrol-ui/src/components/Dashboard/common/UserProfilePopover.jsx
Tom Butcher 24c06c25d3 Refactor JavaScript Language Support and Enhance Autocomplete Functionality
- 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.
2026-08-20 19:35:09 +01:00

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