mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
base implementation
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
// prevent set focus on button when closing modal
|
||||
export default function usePreventFocusAfterModalClosing() {
|
||||
return React.useCallback((e: React.SyntheticEvent) => e.stopPropagation(), []);
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import { QueryKeys } from 'types/client/queries';
|
||||
import appConfig from 'configs/app/config';
|
||||
import metamaskIcon from 'icons/metamask.svg';
|
||||
import qrCodeIcon from 'icons/qr_code.svg';
|
||||
import starOutlineIcon from 'icons/star_outline.svg';
|
||||
import walletIcon from 'icons/wallet.svg';
|
||||
import useFetch from 'lib/hooks/useFetch';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
@@ -21,6 +20,8 @@ import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
|
||||
import ExternalLink from 'ui/shared/ExternalLink';
|
||||
import HashStringShorten from 'ui/shared/HashStringShorten';
|
||||
|
||||
import AddressFavoriteButton from './details/AddressFavoriteButton';
|
||||
|
||||
interface Props {
|
||||
addressQuery: UseQueryResult<TAddress>;
|
||||
}
|
||||
@@ -65,9 +66,7 @@ const AddressDetails = ({ addressQuery }: Props) => {
|
||||
</Text>
|
||||
<CopyToClipboard text={ addressQuery.data.hash }/>
|
||||
<Icon as={ metamaskIcon } boxSize={ 6 } ml={ 2 }/>
|
||||
<Button variant="outline" size="sm" ml={ 3 }>
|
||||
<Icon as={ starOutlineIcon } boxSize={ 5 }/>
|
||||
</Button>
|
||||
<AddressFavoriteButton hash={ addressQuery.data.hash } isAdded={ Boolean(addressQuery.data.watchlist_names?.length) } ml={ 3 }/>
|
||||
<Button variant="outline" size="sm" ml={ 2 }>
|
||||
<Icon as={ qrCodeIcon } boxSize={ 5 }/>
|
||||
</Button>
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import { Icon, chakra, Tooltip, IconButton, useDisclosure } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import starFilledIcon from 'icons/star_filled.svg';
|
||||
import starOutlineIcon from 'icons/star_outline.svg';
|
||||
import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing';
|
||||
import WatchlistAddModal from 'ui/watchlist/AddressModal/AddressModal';
|
||||
import DeleteAddressModal from 'ui/watchlist/DeleteAddressModal';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
hash: string;
|
||||
isAdded: boolean;
|
||||
}
|
||||
|
||||
const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => {
|
||||
const addModalProps = useDisclosure();
|
||||
const deleteModalProps = useDisclosure();
|
||||
|
||||
const handleClick = React.useCallback(() => {
|
||||
isAdded ? deleteModalProps.onOpen() : addModalProps.onOpen();
|
||||
}, [ addModalProps, deleteModalProps, isAdded ]);
|
||||
|
||||
const handleAddModalClose = React.useCallback(() => {
|
||||
addModalProps.onClose();
|
||||
}, [ addModalProps ]);
|
||||
|
||||
const handleDeleteModalClose = React.useCallback(() => {
|
||||
deleteModalProps.onClose();
|
||||
}, [ deleteModalProps ]);
|
||||
|
||||
const formData = React.useMemo(() => {
|
||||
return { address_hash: hash, id: '1' };
|
||||
}, [ hash ]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip label={ `${ isAdded ? 'Remove address from Watch list' : 'Add address to Watch list' }` }>
|
||||
<IconButton
|
||||
className={ className }
|
||||
aria-label="edit"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
pl={ 2 }
|
||||
pr={ 2 }
|
||||
onClick={ handleClick }
|
||||
icon={ <Icon as={ isAdded ? starFilledIcon : starOutlineIcon } boxSize={ 5 }/> }
|
||||
onFocusCapture={ usePreventFocusAfterModalClosing() }
|
||||
/>
|
||||
</Tooltip>
|
||||
<WatchlistAddModal { ...addModalProps } onClose={ handleAddModalClose } data={ formData } isAdd/>
|
||||
<DeleteAddressModal { ...deleteModalProps } onClose={ handleDeleteModalClose } data={ formData }/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default chakra(AddressFavoriteButton);
|
||||
@@ -107,7 +107,7 @@ const WatchList: React.FC = () => {
|
||||
Add address
|
||||
</Button>
|
||||
</Box>
|
||||
<AddressModal { ...addressModalProps } onClose={ onAddressModalClose } data={ addressModalData }/>
|
||||
<AddressModal { ...addressModalProps } onClose={ onAddressModalClose } data={ addressModalData } isAdd={ !addressModalData }/>
|
||||
{ deleteModalData && <DeleteAddressModal { ...deleteModalProps } onClose={ onDeleteModalClose } data={ deleteModalData }/> }
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Tooltip, IconButton, Icon, HStack } from '@chakra-ui/react';
|
||||
import React, { useCallback } from 'react';
|
||||
import React from 'react';
|
||||
|
||||
import DeleteIcon from 'icons/delete.svg';
|
||||
import EditIcon from 'icons/edit.svg';
|
||||
import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing';
|
||||
|
||||
type Props = {
|
||||
onEditClick: () => void;
|
||||
@@ -10,8 +11,7 @@ type Props = {
|
||||
}
|
||||
|
||||
const TableItemActionButtons = ({ onEditClick, onDeleteClick }: Props) => {
|
||||
// prevent set focus on button when closing modal
|
||||
const onFocusCapture = useCallback((e: React.SyntheticEvent) => e.stopPropagation(), []);
|
||||
const onFocusCapture = usePreventFocusAfterModalClosing();
|
||||
|
||||
return (
|
||||
<HStack spacing={ 6 } alignSelf="flex-end">
|
||||
|
||||
@@ -29,9 +29,10 @@ const NOTIFICATIONS = [ 'native', 'ERC-20', 'ERC-721' ] as const;
|
||||
const TAG_MAX_LENGTH = 35;
|
||||
|
||||
type Props = {
|
||||
data?: TWatchlistItem;
|
||||
data?: Partial<TWatchlistItem>;
|
||||
onClose: () => void;
|
||||
setAlertVisible: (isAlertVisible: boolean) => void;
|
||||
isAdd: boolean;
|
||||
}
|
||||
|
||||
type Inputs = {
|
||||
@@ -62,12 +63,12 @@ type Checkboxes = 'notification' |
|
||||
'notification_settings.ERC-721.outcoming' |
|
||||
'notification_settings.ERC-721.incoming';
|
||||
|
||||
const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
|
||||
const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible, isAdd }) => {
|
||||
const [ pending, setPending ] = useState(false);
|
||||
const formBackgroundColor = useColorModeValue('white', 'gray.900');
|
||||
|
||||
let notificationsDefault = {} as Inputs['notification_settings'];
|
||||
if (!data) {
|
||||
if (!data?.notification_settings) {
|
||||
NOTIFICATIONS.forEach(n => notificationsDefault[n] = { incoming: true, outcoming: true });
|
||||
} else {
|
||||
notificationsDefault = data.notification_settings;
|
||||
@@ -77,7 +78,7 @@ const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
|
||||
defaultValues: {
|
||||
address: data?.address_hash || '',
|
||||
tag: data?.name || '',
|
||||
notification: data ? data.notification_methods.email : true,
|
||||
notification: data?.notification_methods ? data.notification_methods.email : true,
|
||||
notification_settings: notificationsDefault,
|
||||
},
|
||||
mode: 'onTouched',
|
||||
@@ -95,7 +96,7 @@ const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
|
||||
email: formData.notification,
|
||||
},
|
||||
};
|
||||
if (data) {
|
||||
if (!isAdd && data) {
|
||||
// edit address
|
||||
return fetch<TWatchlistItem, WatchlistErrors>(`/node-api/account/watchlist/${ data.id }`, { method: 'PUT', body });
|
||||
|
||||
@@ -193,7 +194,7 @@ const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
|
||||
isLoading={ pending }
|
||||
disabled={ !isValid || !isDirty }
|
||||
>
|
||||
{ data ? 'Save changes' : 'Add address' }
|
||||
{ !isAdd ? 'Save changes' : 'Add address' }
|
||||
</Button>
|
||||
</Box>
|
||||
</form>
|
||||
|
||||
@@ -7,20 +7,21 @@ import FormModal from 'ui/shared/FormModal';
|
||||
import AddressForm from './AddressForm';
|
||||
|
||||
type Props = {
|
||||
isAdd: boolean;
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
data?: TWatchlistItem;
|
||||
data?: Partial<TWatchlistItem>;
|
||||
}
|
||||
|
||||
const AddressModal: React.FC<Props> = ({ isOpen, onClose, data }) => {
|
||||
const title = data ? 'Edit watch list address' : 'New address to watch list';
|
||||
const text = !data ? 'An email notification can be sent to you when an address on your watch list sends or receives any transactions.' : '';
|
||||
const AddressModal: React.FC<Props> = ({ isOpen, onClose, data, isAdd }) => {
|
||||
const title = !isAdd ? 'Edit watch list address' : 'New address to watch list';
|
||||
const text = isAdd ? 'An email notification can be sent to you when an address on your watch list sends or receives any transactions.' : '';
|
||||
|
||||
const [ isAlertVisible, setAlertVisible ] = useState(false);
|
||||
|
||||
const renderForm = useCallback(() => {
|
||||
return <AddressForm data={ data } onClose={ onClose } setAlertVisible={ setAlertVisible }/>;
|
||||
}, [ data, onClose ]);
|
||||
return <AddressForm data={ data } onClose={ onClose } setAlertVisible={ setAlertVisible } isAdd={ isAdd }/>;
|
||||
}, [ data, isAdd, onClose ]);
|
||||
|
||||
return (
|
||||
<FormModal<TWatchlistItem>
|
||||
|
||||
@@ -12,7 +12,7 @@ import DeleteModal from 'ui/shared/DeleteModal';
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
data: TWatchlistItem;
|
||||
data: Pick<TWatchlistItem, 'address_hash' | 'id'>;
|
||||
}
|
||||
|
||||
const DeleteAddressModal: React.FC<Props> = ({ isOpen, onClose, data }) => {
|
||||
|
||||
Reference in New Issue
Block a user