Commit d08346f0 authored by tom's avatar tom

delete funtionality

parent 146e347f
import type { AddressParam } from './addressParams';
export interface AddressTag { export interface AddressTag {
address_hash: string; address_hash: string;
name: string; name: string;
...@@ -63,6 +64,7 @@ export interface WatchlistAddress { ...@@ -63,6 +64,7 @@ export interface WatchlistAddress {
notification_settings: NotificationSettings; notification_settings: NotificationSettings;
notification_methods: NotificationMethods; notification_methods: NotificationMethods;
id: string; id: string;
address?: AddressParam;
} }
export interface WatchlistAddressNew { export interface WatchlistAddressNew {
......
import { Icon, chakra, Tooltip, IconButton, useDisclosure } from '@chakra-ui/react'; import { Icon, chakra, Tooltip, IconButton, useDisclosure } from '@chakra-ui/react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { TWatchlist } from 'types/client/account';
import { QueryKeys as AccountQueryKeys } from 'types/client/accountQueries';
import { QueryKeys } from 'types/client/queries';
import starFilledIcon from 'icons/star_filled.svg'; import starFilledIcon from 'icons/star_filled.svg';
import starOutlineIcon from 'icons/star_outline.svg'; import starOutlineIcon from 'icons/star_outline.svg';
import useFetch from 'lib/hooks/useFetch';
import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing'; import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing';
import WatchlistAddModal from 'ui/watchlist/AddressModal/AddressModal'; import WatchlistAddModal from 'ui/watchlist/AddressModal/AddressModal';
import DeleteAddressModal from 'ui/watchlist/DeleteAddressModal'; import DeleteAddressModal from 'ui/watchlist/DeleteAddressModal';
...@@ -16,11 +23,27 @@ interface Props { ...@@ -16,11 +23,27 @@ interface Props {
const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => { const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => {
const addModalProps = useDisclosure(); const addModalProps = useDisclosure();
const deleteModalProps = useDisclosure(); const deleteModalProps = useDisclosure();
const queryClient = useQueryClient();
const router = useRouter();
const fetch = useFetch();
const watchListQuery = useQuery<unknown, unknown, TWatchlist>(
[ AccountQueryKeys.watchlist ],
async() => fetch('/node-api/account/watchlist'),
{
enabled: isAdded,
},
);
const handleClick = React.useCallback(() => { const handleClick = React.useCallback(() => {
isAdded ? deleteModalProps.onOpen() : addModalProps.onOpen(); isAdded ? deleteModalProps.onOpen() : addModalProps.onOpen();
}, [ addModalProps, deleteModalProps, isAdded ]); }, [ addModalProps, deleteModalProps, isAdded ]);
const handleAddOrDeleteSuccess = React.useCallback(async() => {
await queryClient.refetchQueries({ queryKey: [ QueryKeys.address, router.query.id ] });
addModalProps.onClose();
}, [ addModalProps, queryClient, router.query.id ]);
const handleAddModalClose = React.useCallback(() => { const handleAddModalClose = React.useCallback(() => {
addModalProps.onClose(); addModalProps.onClose();
}, [ addModalProps ]); }, [ addModalProps ]);
...@@ -30,13 +53,20 @@ const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => { ...@@ -30,13 +53,20 @@ const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => {
}, [ deleteModalProps ]); }, [ deleteModalProps ]);
const formData = React.useMemo(() => { const formData = React.useMemo(() => {
return { address_hash: hash, id: '1' }; return {
}, [ hash ]); address_hash: hash,
// FIXME temporary solution
// there is no endpoint in api what can return watchlist address info by its hash
// so we look up in the whole watchlist and hope we can find a necessary item
id: watchListQuery.data?.find((address) => address.address?.hash === hash)?.id || '',
};
}, [ hash, watchListQuery.data ]);
return ( return (
<> <>
<Tooltip label={ `${ isAdded ? 'Remove address from Watch list' : 'Add address to Watch list' }` }> <Tooltip label={ `${ isAdded ? 'Remove address from Watch list' : 'Add address to Watch list' }` }>
<IconButton <IconButton
isActive={ isAdded }
className={ className } className={ className }
aria-label="edit" aria-label="edit"
variant="outline" variant="outline"
...@@ -48,8 +78,19 @@ const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => { ...@@ -48,8 +78,19 @@ const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => {
onFocusCapture={ usePreventFocusAfterModalClosing() } onFocusCapture={ usePreventFocusAfterModalClosing() }
/> />
</Tooltip> </Tooltip>
<WatchlistAddModal { ...addModalProps } onClose={ handleAddModalClose } data={ formData } isAdd/> <WatchlistAddModal
<DeleteAddressModal { ...deleteModalProps } onClose={ handleDeleteModalClose } data={ formData }/> { ...addModalProps }
isAdd
onClose={ handleAddModalClose }
onSuccess={ handleAddOrDeleteSuccess }
data={ formData }
/>
<DeleteAddressModal
{ ...deleteModalProps }
onClose={ handleDeleteModalClose }
data={ formData }
onSuccess={ handleAddOrDeleteSuccess }
/>
</> </>
); );
}; };
......
import { Box, Button, Skeleton, useDisclosure } from '@chakra-ui/react'; import { Box, Button, Skeleton, useDisclosure } from '@chakra-ui/react';
import { useQuery } from '@tanstack/react-query'; import { useQuery, useQueryClient } from '@tanstack/react-query';
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import type { TWatchlist, TWatchlistItem } from 'types/client/account'; import type { TWatchlist, TWatchlistItem } from 'types/client/account';
...@@ -22,6 +22,7 @@ import WatchlistTable from 'ui/watchlist/WatchlistTable/WatchlistTable'; ...@@ -22,6 +22,7 @@ import WatchlistTable from 'ui/watchlist/WatchlistTable/WatchlistTable';
const WatchList: React.FC = () => { const WatchList: React.FC = () => {
const { data, isLoading, isError } = const { data, isLoading, isError } =
useQuery<unknown, unknown, TWatchlist>([ QueryKeys.watchlist ], async() => fetch('/node-api/account/watchlist/get-with-tokens')); useQuery<unknown, unknown, TWatchlist>([ QueryKeys.watchlist ], async() => fetch('/node-api/account/watchlist/get-with-tokens'));
const queryClient = useQueryClient();
const addressModalProps = useDisclosure(); const addressModalProps = useDisclosure();
const deleteModalProps = useDisclosure(); const deleteModalProps = useDisclosure();
...@@ -42,6 +43,12 @@ const WatchList: React.FC = () => { ...@@ -42,6 +43,12 @@ const WatchList: React.FC = () => {
addressModalProps.onClose(); addressModalProps.onClose();
}, [ addressModalProps ]); }, [ addressModalProps ]);
const onAddOrEditSuccess = useCallback(async() => {
await queryClient.refetchQueries([ QueryKeys.watchlist ]);
setAddressModalData(undefined);
addressModalProps.onClose();
}, [ addressModalProps, queryClient ]);
const onDeleteClick = useCallback((data: TWatchlistItem) => { const onDeleteClick = useCallback((data: TWatchlistItem) => {
setDeleteModalData(data); setDeleteModalData(data);
deleteModalProps.onOpen(); deleteModalProps.onOpen();
...@@ -52,6 +59,12 @@ const WatchList: React.FC = () => { ...@@ -52,6 +59,12 @@ const WatchList: React.FC = () => {
deleteModalProps.onClose(); deleteModalProps.onClose();
}, [ deleteModalProps ]); }, [ deleteModalProps ]);
const onDeleteSuccess = useCallback(async() => {
queryClient.setQueryData([ QueryKeys.watchlist ], (prevData: TWatchlist | undefined) => {
return prevData?.filter((item) => item.id !== deleteModalData?.id);
});
}, [ deleteModalData?.id, queryClient ]);
const description = ( const description = (
<AccountPageDescription> <AccountPageDescription>
An email notification can be sent to you when an address on your watch list sends or receives any transactions. An email notification can be sent to you when an address on your watch list sends or receives any transactions.
...@@ -107,8 +120,21 @@ const WatchList: React.FC = () => { ...@@ -107,8 +120,21 @@ const WatchList: React.FC = () => {
Add address Add address
</Button> </Button>
</Box> </Box>
<AddressModal { ...addressModalProps } onClose={ onAddressModalClose } data={ addressModalData } isAdd={ !addressModalData }/> <AddressModal
{ deleteModalData && <DeleteAddressModal { ...deleteModalProps } onClose={ onDeleteModalClose } data={ deleteModalData }/> } { ...addressModalProps }
onClose={ onAddressModalClose }
onSuccess={ onAddOrEditSuccess }
data={ addressModalData }
isAdd={ !addressModalData }
/>
{ deleteModalData && (
<DeleteAddressModal
{ ...deleteModalProps }
onClose={ onDeleteModalClose }
onSuccess={ onDeleteSuccess }
data={ deleteModalData }
/>
) }
</> </>
); );
} }
......
...@@ -4,14 +4,13 @@ import { ...@@ -4,14 +4,13 @@ import {
Text, Text,
useColorModeValue, useColorModeValue,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useMutation } from '@tanstack/react-query';
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import type { SubmitHandler, ControllerRenderProps } from 'react-hook-form'; import type { SubmitHandler, ControllerRenderProps } from 'react-hook-form';
import { useForm, Controller } from 'react-hook-form'; import { useForm, Controller } from 'react-hook-form';
import type { WatchlistErrors } from 'types/api/account'; import type { WatchlistErrors } from 'types/api/account';
import type { TWatchlistItem } from 'types/client/account'; import type { TWatchlistItem } from 'types/client/account';
import { QueryKeys } from 'types/client/accountQueries';
import getErrorMessage from 'lib/getErrorMessage'; import getErrorMessage from 'lib/getErrorMessage';
import type { ErrorType } from 'lib/hooks/useFetch'; import type { ErrorType } from 'lib/hooks/useFetch';
...@@ -30,7 +29,7 @@ const TAG_MAX_LENGTH = 35; ...@@ -30,7 +29,7 @@ const TAG_MAX_LENGTH = 35;
type Props = { type Props = {
data?: Partial<TWatchlistItem>; data?: Partial<TWatchlistItem>;
onClose: () => void; onSuccess: () => Promise<void>;
setAlertVisible: (isAlertVisible: boolean) => void; setAlertVisible: (isAlertVisible: boolean) => void;
isAdd: boolean; isAdd: boolean;
} }
...@@ -63,7 +62,7 @@ type Checkboxes = 'notification' | ...@@ -63,7 +62,7 @@ type Checkboxes = 'notification' |
'notification_settings.ERC-721.outcoming' | 'notification_settings.ERC-721.outcoming' |
'notification_settings.ERC-721.incoming'; 'notification_settings.ERC-721.incoming';
const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible, isAdd }) => { const AddressForm: React.FC<Props> = ({ data, onSuccess, setAlertVisible, isAdd }) => {
const [ pending, setPending ] = useState(false); const [ pending, setPending ] = useState(false);
const formBackgroundColor = useColorModeValue('white', 'gray.900'); const formBackgroundColor = useColorModeValue('white', 'gray.900');
...@@ -84,7 +83,6 @@ const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible, isAdd }) ...@@ -84,7 +83,6 @@ const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible, isAdd })
mode: 'onTouched', mode: 'onTouched',
}); });
const queryClient = useQueryClient();
const fetch = useFetch(); const fetch = useFetch();
function updateWatchlist(formData: Inputs) { function updateWatchlist(formData: Inputs) {
...@@ -107,11 +105,9 @@ const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible, isAdd }) ...@@ -107,11 +105,9 @@ const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible, isAdd })
} }
const { mutate } = useMutation(updateWatchlist, { const { mutate } = useMutation(updateWatchlist, {
onSuccess: () => { onSuccess: async() => {
queryClient.refetchQueries([ QueryKeys.watchlist ]).then(() => { await onSuccess();
onClose();
setPending(false); setPending(false);
});
}, },
onError: (e: ErrorType<WatchlistErrors>) => { onError: (e: ErrorType<WatchlistErrors>) => {
setPending(false); setPending(false);
......
...@@ -10,18 +10,19 @@ type Props = { ...@@ -10,18 +10,19 @@ type Props = {
isAdd: boolean; isAdd: boolean;
isOpen: boolean; isOpen: boolean;
onClose: () => void; onClose: () => void;
onSuccess: () => Promise<void>;
data?: Partial<TWatchlistItem>; data?: Partial<TWatchlistItem>;
} }
const AddressModal: React.FC<Props> = ({ isOpen, onClose, data, isAdd }) => { const AddressModal: React.FC<Props> = ({ isOpen, onClose, onSuccess, data, isAdd }) => {
const title = !isAdd ? 'Edit watch list address' : 'New address to watch list'; 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 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 [ isAlertVisible, setAlertVisible ] = useState(false);
const renderForm = useCallback(() => { const renderForm = useCallback(() => {
return <AddressForm data={ data } onClose={ onClose } setAlertVisible={ setAlertVisible } isAdd={ isAdd }/>; return <AddressForm data={ data } onSuccess={ onSuccess } setAlertVisible={ setAlertVisible } isAdd={ isAdd }/>;
}, [ data, isAdd, onClose ]); }, [ data, isAdd, onSuccess ]);
return ( return (
<FormModal<TWatchlistItem> <FormModal<TWatchlistItem>
......
import { Text } from '@chakra-ui/react'; import { Text } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import type { TWatchlistItem, TWatchlist } from 'types/client/account'; import type { TWatchlistItem } from 'types/client/account';
import { QueryKeys } from 'types/client/accountQueries';
import useFetch from 'lib/hooks/useFetch'; import useFetch from 'lib/hooks/useFetch';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
...@@ -12,11 +10,11 @@ import DeleteModal from 'ui/shared/DeleteModal'; ...@@ -12,11 +10,11 @@ import DeleteModal from 'ui/shared/DeleteModal';
type Props = { type Props = {
isOpen: boolean; isOpen: boolean;
onClose: () => void; onClose: () => void;
onSuccess: () => Promise<void>;
data: Pick<TWatchlistItem, 'address_hash' | 'id'>; data: Pick<TWatchlistItem, 'address_hash' | 'id'>;
} }
const DeleteAddressModal: React.FC<Props> = ({ isOpen, onClose, data }) => { const DeleteAddressModal: React.FC<Props> = ({ isOpen, onClose, onSuccess, data }) => {
const queryClient = useQueryClient();
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const fetch = useFetch(); const fetch = useFetch();
...@@ -24,12 +22,6 @@ const DeleteAddressModal: React.FC<Props> = ({ isOpen, onClose, data }) => { ...@@ -24,12 +22,6 @@ const DeleteAddressModal: React.FC<Props> = ({ isOpen, onClose, data }) => {
return fetch(`/node-api/account/watchlist/${ data?.id }`, { method: 'DELETE' }); return fetch(`/node-api/account/watchlist/${ data?.id }`, { method: 'DELETE' });
}, [ data?.id, fetch ]); }, [ data?.id, fetch ]);
const onSuccess = useCallback(async() => {
queryClient.setQueryData([ QueryKeys.watchlist ], (prevData: TWatchlist | undefined) => {
return prevData?.filter((item) => item.id !== data.id);
});
}, [ data, queryClient ]);
const address = data?.address_hash; const address = data?.address_hash;
const renderModalContent = useCallback(() => { const renderModalContent = useCallback(() => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment