Use of ClickAwayListener instead of IconButton for closing

This commit is contained in:
Nicola Benaglia 2025-06-12 20:24:23 +02:00
parent 1d50a96d25
commit 94ad99d7e4

View File

@ -18,6 +18,8 @@ import {
CircularProgress, CircularProgress,
useTheme, useTheme,
Autocomplete, Autocomplete,
IconButton,
ClickAwayListener,
} from '@mui/material'; } from '@mui/material';
import { import {
getAddressInfo, getAddressInfo,
@ -28,7 +30,7 @@ import { getNameInfo } from '../Group/Group';
import AccountCircleIcon from '@mui/icons-material/AccountCircle'; import AccountCircleIcon from '@mui/icons-material/AccountCircle';
import { Spacer } from '../../common/Spacer'; import { Spacer } from '../../common/Spacer';
import { formatTimestamp } from '../../utils/time'; import { formatTimestamp } from '../../utils/time';
import CloseFullscreenIcon from '@mui/icons-material/CloseFullscreen'; import CloseIcon from '@mui/icons-material/Close';
import { import {
executeEvent, executeEvent,
subscribeToEvent, subscribeToEvent,
@ -160,489 +162,481 @@ export const UserLookup = ({ isOpenDrawerLookup, setIsOpenDrawerLookup }) => {
return ( return (
<DrawerUserLookup open={isOpenDrawerLookup} setOpen={setIsOpenDrawerLookup}> <DrawerUserLookup open={isOpenDrawerLookup} setOpen={setIsOpenDrawerLookup}>
<Box <ClickAwayListener onClickAway={onClose}>
sx={{
display: 'flex',
flexDirection: 'column',
height: '100vh',
overflow: 'hidden',
padding: '15px',
}}
>
<Box
sx={{
alignItems: 'center',
display: 'flex',
flexShrink: 0,
gap: '5px',
}}
>
<Autocomplete
value={nameOrAddress}
onChange={(event: any, newValue: string | null) => {
if (!newValue) {
setNameOrAddress('');
return;
}
setNameOrAddress(newValue);
lookupFunc(newValue);
}}
inputValue={inputValue}
onInputChange={(event, newInputValue) => {
setInputValue(newInputValue);
}}
id="controllable-states-demo"
loading={isLoading}
noOptionsText={t('core:option_no', {
postProcess: 'capitalizeFirstChar',
})}
options={options}
sx={{ width: 300 }}
renderInput={(params) => (
<TextField
autoFocus
autoComplete="off"
{...params}
label={t('auth:address_name', {
postProcess: 'capitalizeFirstChar',
})}
onKeyDown={(e) => {
if (e.key === 'Enter' && nameOrAddress) {
lookupFunc(inputValue);
}
}}
/>
)}
/>
<ButtonBase
sx={{
marginLeft: 'auto',
}}
onClick={() => {
onClose();
}}
>
<CloseFullscreenIcon
sx={{
color: theme.palette.text.primary,
}}
/>
</ButtonBase>
</Box>
<Box <Box
sx={{ sx={{
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
flexGrow: 1, height: '100vh',
overflow: 'auto', overflow: 'hidden',
padding: '15px',
}} }}
> >
{!isLoadingUser && errorMessage && ( <Box
<Box sx={{
sx={{ alignItems: 'center',
display: 'flex', display: 'flex',
justifyContent: 'center', gap: '5px',
marginTop: '40px', }}
width: '100%', >
<Autocomplete
value={nameOrAddress}
onChange={(event: any, newValue: string | null) => {
if (!newValue) {
setNameOrAddress('');
return;
}
setNameOrAddress(newValue);
lookupFunc(newValue);
}} }}
> inputValue={inputValue}
<Typography>{errorMessage}</Typography> onInputChange={(event, newInputValue) => {
</Box> setInputValue(newInputValue);
)}
{isLoadingUser && (
<Box
sx={{
display: 'flex',
justifyContent: 'center',
marginTop: '40px',
width: '100%',
}} }}
> id="controllable-states-demo"
<CircularProgress loading={isLoading}
sx={{ noOptionsText={t('core:option_no', {
color: theme.palette.text.primary, postProcess: 'capitalizeFirstChar',
}} })}
/> options={options}
</Box> sx={{ flexGrow: 1 }}
)} renderInput={(params) => (
<TextField
autoFocus
autoComplete="off"
{...params}
label={t('auth:address_name', {
postProcess: 'capitalizeFirstChar',
})}
onKeyDown={(e) => {
if (e.key === 'Enter' && nameOrAddress) {
lookupFunc(inputValue);
}
}}
/>
)}
/>
</Box>
{!isLoadingUser && addressInfo && ( <Box
<> sx={{
<Spacer height="30px" /> display: 'flex',
flexDirection: 'column',
flexGrow: 1,
overflow: 'auto',
}}
>
{!isLoadingUser && errorMessage && (
<Box <Box
sx={{ sx={{
display: 'flex', display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
gap: '20px',
justifyContent: 'center', justifyContent: 'center',
marginTop: '40px',
width: '100%', width: '100%',
}} }}
> >
<Card <Typography>{errorMessage}</Typography>
</Box>
)}
{isLoadingUser && (
<Box
sx={{
display: 'flex',
justifyContent: 'center',
marginTop: '40px',
width: '100%',
}}
>
<CircularProgress
sx={{
color: theme.palette.text.primary,
}}
/>
</Box>
)}
{!isLoadingUser && addressInfo && (
<>
<Spacer height="30px" />
<Box
sx={{ sx={{
alignItems: 'center',
background: theme.palette.background.default,
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'row',
minHeight: '200px', flexWrap: 'wrap',
minWidth: '320px', gap: '20px',
padding: '15px', justifyContent: 'center',
width: '100%',
}} }}
> >
<Typography <Card
sx={{ sx={{
textAlign: 'center', alignItems: 'center',
background: theme.palette.background.default,
display: 'flex',
flexDirection: 'column',
minHeight: '200px',
minWidth: '320px',
padding: '15px',
}} }}
> >
{addressInfo?.name ?? <Typography
t('auth:message.error.name_not_registered', { sx={{
postProcess: 'capitalizeFirstChar', textAlign: 'center',
})} }}
</Typography> >
{addressInfo?.name ??
t('auth:message.error.name_not_registered', {
postProcess: 'capitalizeFirstChar',
})}
</Typography>
<Spacer height="20px" /> <Spacer height="20px" />
<Divider> <Divider>
{addressInfo?.name ? ( {addressInfo?.name ? (
<Avatar <Avatar
sx={{ sx={{
height: '50px', height: '50px',
width: '50px', width: '50px',
'& img': { '& img': {
objectFit: 'fill', objectFit: 'fill',
}, },
}} }}
alt={addressInfo?.name} alt={addressInfo?.name}
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${ src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${
addressInfo?.name addressInfo?.name
}/qortal_avatar?async=true`} }/qortal_avatar?async=true`}
> >
<AccountCircleIcon
sx={{
fontSize: '50px',
}}
/>
</Avatar>
) : (
<AccountCircleIcon <AccountCircleIcon
sx={{ sx={{
fontSize: '50px', fontSize: '50px',
}} }}
/> />
</Avatar> )}
) : ( </Divider>
<AccountCircleIcon
sx={{
fontSize: '50px',
}}
/>
)}
</Divider>
<Spacer height="20px" /> <Spacer height="20px" />
<Typography <Typography
sx={{ sx={{
textAlign: 'center', textAlign: 'center',
}} }}
> >
{t('core:level', { postProcess: 'capitalizeFirstChar' })}{' '} {t('core:level', { postProcess: 'capitalizeFirstChar' })}{' '}
{addressInfo?.level} {addressInfo?.level}
</Typography> </Typography>
</Card> </Card>
<Card <Card
sx={{
background: theme.palette.background.default,
display: 'flex',
flexDirection: 'column',
gap: '20px',
minHeight: '200px',
minWidth: '320px',
padding: '15px',
}}
>
<Box
sx={{ sx={{
background: theme.palette.background.default,
display: 'flex', display: 'flex',
flexDirection: 'column',
gap: '20px', gap: '20px',
justifyContent: 'space-between', minHeight: '200px',
width: '100%', minWidth: '320px',
padding: '15px',
}} }}
> >
<Box <Box
sx={{ sx={{
display: 'flex', display: 'flex',
flexShrink: 0, gap: '20px',
justifyContent: 'space-between',
width: '100%',
}}
>
<Box
sx={{
display: 'flex',
flexShrink: 0,
}}
>
<Typography>
{t('auth:address', {
postProcess: 'capitalizeFirstChar',
})}
</Typography>
</Box>
<Tooltip
title={
<span
style={{
color: theme.palette.text.primary,
fontSize: '14px',
fontWeight: 700,
}}
>
{t('auth:action.copy_address', {
postProcess: 'capitalizeFirstChar',
})}
</span>
}
placement="bottom"
arrow
sx={{ fontSize: '24' }}
slotProps={{
tooltip: {
sx: {
color: theme.palette.text.primary,
backgroundColor: theme.palette.background.default,
},
},
arrow: {
sx: {
color: theme.palette.text.primary,
},
},
}}
>
<ButtonBase
onClick={() => {
navigator.clipboard.writeText(addressInfo?.address);
}}
>
<Typography
sx={{
textAlign: 'end',
}}
>
{addressInfo?.address}
</Typography>
</ButtonBase>
</Tooltip>
</Box>
<Box
sx={{
display: 'flex',
gap: '20px',
justifyContent: 'space-between',
width: '100%',
}} }}
> >
<Typography> <Typography>
{t('auth:address', { {t('core:balance', {
postProcess: 'capitalizeFirstChar', postProcess: 'capitalizeFirstChar',
})} })}
</Typography> </Typography>
<Typography>{addressInfo?.balance}</Typography>
</Box> </Box>
<Tooltip <Spacer height="20px" />
title={
<span <Button
style={{ variant="contained"
color: theme.palette.text.primary, onClick={() => {
fontSize: '14px', executeEvent('openPaymentInternal', {
fontWeight: 700, address: addressInfo?.address,
}} name: addressInfo?.name,
> });
{t('auth:action.copy_address', {
postProcess: 'capitalizeFirstChar',
})}
</span>
}
placement="bottom"
arrow
sx={{ fontSize: '24' }}
slotProps={{
tooltip: {
sx: {
color: theme.palette.text.primary,
backgroundColor: theme.palette.background.default,
},
},
arrow: {
sx: {
color: theme.palette.text.primary,
},
},
}} }}
> >
<ButtonBase {t('core:action.send_qort', {
onClick={() => { postProcess: 'capitalizeFirstChar',
navigator.clipboard.writeText(addressInfo?.address); })}
}} </Button>
> </Card>
<Typography </Box>
sx={{ </>
textAlign: 'end', )}
}}
>
{addressInfo?.address}
</Typography>
</ButtonBase>
</Tooltip>
</Box>
<Spacer height="40px" />
{isLoadingPayments && (
<Box
sx={{
display: 'flex',
justifyContent: 'center',
width: '100%',
}}
>
<CircularProgress
sx={{
color: theme.palette.text.primary,
}}
/>
</Box>
)}
{!isLoadingPayments && addressInfo && (
<Card
sx={{
background: theme.palette.background.default,
display: 'flex',
flexDirection: 'column',
overflow: 'auto',
padding: '15px',
}}
>
<Typography>
{t('core:message.generic.most_recent_payment', {
count: 20,
postProcess: 'capitalizeFirstChar',
})}
</Typography>
<Spacer height="20px" />
{!isLoadingPayments && payments?.length === 0 && (
<Box <Box
sx={{ sx={{
display: 'flex', display: 'flex',
gap: '20px', justifyContent: 'center',
justifyContent: 'space-between',
width: '100%', width: '100%',
}} }}
> >
<Typography> <Typography>
{t('core:balance', { {t('core:message.generic.no_payments', {
postProcess: 'capitalizeFirstChar', postProcess: 'capitalizeFirstChar',
})} })}
</Typography> </Typography>
<Typography>{addressInfo?.balance}</Typography>
</Box> </Box>
)}
<Spacer height="20px" /> <Table>
<TableHead>
<Button <TableRow>
variant="contained"
onClick={() => {
executeEvent('openPaymentInternal', {
address: addressInfo?.address,
name: addressInfo?.name,
});
}}
>
{t('core:action.send_qort', {
postProcess: 'capitalizeFirstChar',
})}
</Button>
</Card>
</Box>
</>
)}
<Spacer height="40px" />
{isLoadingPayments && (
<Box
sx={{
display: 'flex',
justifyContent: 'center',
width: '100%',
}}
>
<CircularProgress
sx={{
color: theme.palette.text.primary,
}}
/>
</Box>
)}
{!isLoadingPayments && addressInfo && (
<Card
sx={{
background: theme.palette.background.default,
display: 'flex',
flexDirection: 'column',
overflow: 'auto',
padding: '15px',
}}
>
<Typography>
{t('core:message.generic.most_recent_payment', {
count: 20,
postProcess: 'capitalizeFirstChar',
})}
</Typography>
<Spacer height="20px" />
{!isLoadingPayments && payments?.length === 0 && (
<Box
sx={{
display: 'flex',
justifyContent: 'center',
width: '100%',
}}
>
<Typography>
{t('core:message.generic.no_payments', {
postProcess: 'capitalizeFirstChar',
})}
</Typography>
</Box>
)}
<Table>
<TableHead>
<TableRow>
<TableCell>
{t('core:sender', { postProcess: 'capitalizeFirstChar' })}
</TableCell>
<TableCell>
{t('core:receiver', {
postProcess: 'capitalizeFirstChar',
})}
</TableCell>
<TableCell>
{t('core:amount', { postProcess: 'capitalizeFirstChar' })}
</TableCell>
<TableCell>
{t('core:time.time', {
postProcess: 'capitalizeFirstChar',
})}
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{payments.map((payment, index) => (
<TableRow key={payment?.signature}>
<TableCell> <TableCell>
<Tooltip {t('core:sender', {
title={ postProcess: 'capitalizeFirstChar',
<span })}
style={{
color: theme.palette.text.primary,
fontSize: '14px',
fontWeight: 700,
}}
>
{t('auth:action.copy_address', {
postProcess: 'capitalizeFirstChar',
})}
</span>
}
placement="bottom"
arrow
sx={{ fontSize: '24' }}
slotProps={{
tooltip: {
sx: {
color: theme.palette.text.primary,
backgroundColor:
theme.palette.background.default,
},
},
arrow: {
sx: {
color: theme.palette.text.primary,
},
},
}}
>
<ButtonBase
onClick={() => {
navigator.clipboard.writeText(
payment?.creatorAddress
);
}}
>
{formatAddress(payment?.creatorAddress)}
</ButtonBase>
</Tooltip>
</TableCell> </TableCell>
<TableCell> <TableCell>
<Tooltip {t('core:receiver', {
title={ postProcess: 'capitalizeFirstChar',
<span })}
style={{
color: theme.palette.text.primary,
fontSize: '14px',
fontWeight: 700,
}}
>
{t('auth:action.copy_address', {
postProcess: 'capitalizeFirstChar',
})}
</span>
}
placement="bottom"
arrow
sx={{ fontSize: '24' }}
slotProps={{
tooltip: {
sx: {
color: theme.palette.text.primary,
backgroundColor:
theme.palette.background.default,
},
},
arrow: {
sx: {
color: theme.palette.text.primary,
},
},
}}
>
<ButtonBase
onClick={() => {
navigator.clipboard.writeText(payment?.recipient);
}}
>
{formatAddress(payment?.recipient)}
</ButtonBase>
</Tooltip>
</TableCell> </TableCell>
<TableCell>{payment?.amount}</TableCell>
<TableCell> <TableCell>
{formatTimestamp(payment?.timestamp)} {t('core:amount', {
postProcess: 'capitalizeFirstChar',
})}
</TableCell>
<TableCell>
{t('core:time.time', {
postProcess: 'capitalizeFirstChar',
})}
</TableCell> </TableCell>
</TableRow> </TableRow>
))} </TableHead>
</TableBody>
</Table> <TableBody>
</Card> {payments.map((payment, index) => (
)} <TableRow key={payment?.signature}>
<TableCell>
<Tooltip
title={
<span
style={{
color: theme.palette.text.primary,
fontSize: '14px',
fontWeight: 700,
}}
>
{t('auth:action.copy_address', {
postProcess: 'capitalizeFirstChar',
})}
</span>
}
placement="bottom"
arrow
sx={{ fontSize: '24' }}
slotProps={{
tooltip: {
sx: {
color: theme.palette.text.primary,
backgroundColor:
theme.palette.background.default,
},
},
arrow: {
sx: {
color: theme.palette.text.primary,
},
},
}}
>
<ButtonBase
onClick={() => {
navigator.clipboard.writeText(
payment?.creatorAddress
);
}}
>
{formatAddress(payment?.creatorAddress)}
</ButtonBase>
</Tooltip>
</TableCell>
<TableCell>
<Tooltip
title={
<span
style={{
color: theme.palette.text.primary,
fontSize: '14px',
fontWeight: 700,
}}
>
{t('auth:action.copy_address', {
postProcess: 'capitalizeFirstChar',
})}
</span>
}
placement="bottom"
arrow
sx={{ fontSize: '24' }}
slotProps={{
tooltip: {
sx: {
color: theme.palette.text.primary,
backgroundColor:
theme.palette.background.default,
},
},
arrow: {
sx: {
color: theme.palette.text.primary,
},
},
}}
>
<ButtonBase
onClick={() => {
navigator.clipboard.writeText(
payment?.recipient
);
}}
>
{formatAddress(payment?.recipient)}
</ButtonBase>
</Tooltip>
</TableCell>
<TableCell>{payment?.amount}</TableCell>
<TableCell>
{formatTimestamp(payment?.timestamp)}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Card>
)}
</Box>
</Box> </Box>
</Box> </ClickAwayListener>
</DrawerUserLookup> </DrawerUserLookup>
); );
}; };