Commit 3d4d8575 authored by tom's avatar tom

skeletons public tags

parent 54951e67
...@@ -13,3 +13,17 @@ export const PRIVATE_TAG_TX = { ...@@ -13,3 +13,17 @@ export const PRIVATE_TAG_TX = {
name: 'placeholder', name: 'placeholder',
transaction_hash: TX_HASH, transaction_hash: TX_HASH,
}; };
export const PUBLIC_TAG = {
additional_comment: 'my comment',
addresses: [ ADDRESS_HASH ],
addresses_with_info: [ ADDRESS_PARAMS ],
company: null,
email: 'john.doe@example.com',
full_name: 'name',
id: 1,
is_owner: true,
submission_date: '2022-11-11T11:11:11.000000Z',
tags: 'placeholder',
website: null,
};
...@@ -4,7 +4,6 @@ import React, { useCallback, useState } from 'react'; ...@@ -4,7 +4,6 @@ import React, { useCallback, useState } from 'react';
import type { AddressTag } from 'types/api/account'; import type { AddressTag } from 'types/api/account';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile';
import { PRIVATE_TAG_ADDRESS } from 'stubs/account'; import { PRIVATE_TAG_ADDRESS } from 'stubs/account';
import AccountPageDescription from 'ui/shared/AccountPageDescription'; import AccountPageDescription from 'ui/shared/AccountPageDescription';
import DataFetchAlert from 'ui/shared/DataFetchAlert'; import DataFetchAlert from 'ui/shared/DataFetchAlert';
...@@ -24,7 +23,6 @@ const PrivateAddressTags = () => { ...@@ -24,7 +23,6 @@ const PrivateAddressTags = () => {
const addressModalProps = useDisclosure(); const addressModalProps = useDisclosure();
const deleteModalProps = useDisclosure(); const deleteModalProps = useDisclosure();
const isMobile = useIsMobile();
const [ addressModalData, setAddressModalData ] = useState<AddressTag>(); const [ addressModalData, setAddressModalData ] = useState<AddressTag>();
const [ deleteModalData, setDeleteModalData ] = useState<AddressTag>(); const [ deleteModalData, setDeleteModalData ] = useState<AddressTag>();
...@@ -56,25 +54,28 @@ const PrivateAddressTags = () => { ...@@ -56,25 +54,28 @@ const PrivateAddressTags = () => {
return <DataFetchAlert/>; return <DataFetchAlert/>;
} }
const list = isMobile ? ( const list = (
<Box> <>
{ addressTagsData?.map((item: AddressTag, index: number) => ( <Box display={{ base: 'block', lg: 'none' }}>
<AddressTagListItem { addressTagsData?.map((item: AddressTag, index: number) => (
item={ item } <AddressTagListItem
key={ item.id + (isPlaceholderData ? index : '') } item={ item }
key={ item.id + (isPlaceholderData ? index : '') }
onDeleteClick={ onDeleteClick }
onEditClick={ onEditClick }
isLoading={ isPlaceholderData }
/>
)) }
</Box>
<Box display={{ base: 'none', lg: 'block' }}>
<AddressTagTable
isLoading={ isPlaceholderData }
data={ addressTagsData }
onDeleteClick={ onDeleteClick } onDeleteClick={ onDeleteClick }
onEditClick={ onEditClick } onEditClick={ onEditClick }
isLoading={ isPlaceholderData }
/> />
)) } </Box>
</Box> </>
) : (
<AddressTagTable
isLoading={ isPlaceholderData }
data={ addressTagsData }
onDeleteClick={ onDeleteClick }
onEditClick={ onEditClick }
/>
); );
return ( return (
......
...@@ -4,7 +4,6 @@ import React, { useCallback, useState } from 'react'; ...@@ -4,7 +4,6 @@ import React, { useCallback, useState } from 'react';
import type { TransactionTag } from 'types/api/account'; import type { TransactionTag } from 'types/api/account';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile';
import { PRIVATE_TAG_TX } from 'stubs/account'; import { PRIVATE_TAG_TX } from 'stubs/account';
import AccountPageDescription from 'ui/shared/AccountPageDescription'; import AccountPageDescription from 'ui/shared/AccountPageDescription';
import DataFetchAlert from 'ui/shared/DataFetchAlert'; import DataFetchAlert from 'ui/shared/DataFetchAlert';
...@@ -24,7 +23,6 @@ const PrivateTransactionTags = () => { ...@@ -24,7 +23,6 @@ const PrivateTransactionTags = () => {
const transactionModalProps = useDisclosure(); const transactionModalProps = useDisclosure();
const deleteModalProps = useDisclosure(); const deleteModalProps = useDisclosure();
const isMobile = useIsMobile();
const [ transactionModalData, setTransactionModalData ] = useState<TransactionTag>(); const [ transactionModalData, setTransactionModalData ] = useState<TransactionTag>();
const [ deleteModalData, setDeleteModalData ] = useState<TransactionTag>(); const [ deleteModalData, setDeleteModalData ] = useState<TransactionTag>();
...@@ -63,25 +61,28 @@ const PrivateTransactionTags = () => { ...@@ -63,25 +61,28 @@ const PrivateTransactionTags = () => {
return <DataFetchAlert/>; return <DataFetchAlert/>;
} }
const list = isMobile ? ( const list = (
<Box> <>
{ transactionTagsData?.map((item, index) => ( <Box display={{ base: 'block', lg: 'none' }}>
<TransactionTagListItem { transactionTagsData?.map((item, index) => (
key={ item.id + (isPlaceholderData ? index : '') } <TransactionTagListItem
item={ item } key={ item.id + (isPlaceholderData ? index : '') }
item={ item }
isLoading={ isPlaceholderData }
onDeleteClick={ onDeleteClick }
onEditClick={ onEditClick }
/>
)) }
</Box>
<Box display={{ base: 'none', lg: 'block' }}>
<TransactionTagTable
data={ transactionTagsData }
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
onDeleteClick={ onDeleteClick } onDeleteClick={ onDeleteClick }
onEditClick={ onEditClick } onEditClick={ onEditClick }
/> />
)) } </Box>
</Box> </>
) : (
<TransactionTagTable
data={ transactionTagsData }
isLoading={ isPlaceholderData }
onDeleteClick={ onDeleteClick }
onEditClick={ onEditClick }
/>
); );
return ( return (
......
import { Tag, VStack, Text, HStack } from '@chakra-ui/react'; import { VStack, Text, HStack, Skeleton } from '@chakra-ui/react';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import type { PublicTag } from 'types/api/account'; import type { PublicTag } from 'types/api/account';
import AddressSnippet from 'ui/shared/AddressSnippet'; import AddressSnippet from 'ui/shared/AddressSnippet';
import Tag from 'ui/shared/chakra/Tag';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile'; import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import TableItemActionButtons from 'ui/shared/TableItemActionButtons'; import TableItemActionButtons from 'ui/shared/TableItemActionButtons';
import TruncatedTextTooltip from 'ui/shared/TruncatedTextTooltip';
interface Props { interface Props {
item: PublicTag; item: PublicTag;
isLoading?: boolean;
onEditClick: (data: PublicTag) => void; onEditClick: (data: PublicTag) => void;
onDeleteClick: (data: PublicTag) => void; onDeleteClick: (data: PublicTag) => void;
} }
const PublicTagListItem = ({ item, onEditClick, onDeleteClick }: Props) => { const PublicTagListItem = ({ item, isLoading, onEditClick, onDeleteClick }: Props) => {
const onItemEditClick = useCallback(() => { const onItemEditClick = useCallback(() => {
return onEditClick(item); return onEditClick(item);
}, [ item, onEditClick ]); }, [ item, onEditClick ]);
...@@ -27,28 +28,22 @@ const PublicTagListItem = ({ item, onEditClick, onDeleteClick }: Props) => { ...@@ -27,28 +28,22 @@ const PublicTagListItem = ({ item, onEditClick, onDeleteClick }: Props) => {
<ListItemMobile> <ListItemMobile>
<VStack spacing={ 3 } alignItems="flex-start" maxW="100%"> <VStack spacing={ 3 } alignItems="flex-start" maxW="100%">
<VStack spacing={ 4 } alignItems="unset" maxW="100%"> <VStack spacing={ 4 } alignItems="unset" maxW="100%">
{ item.addresses_with_info.map((address) => <AddressSnippet key={ address.hash } address={ address }/>) } { item.addresses_with_info.map((address) => <AddressSnippet key={ address.hash } address={ address } isLoading={ isLoading }/>) }
</VStack> </VStack>
<HStack spacing={ 3 }> <HStack spacing={ 3 }>
<Text fontSize="sm" fontWeight={ 500 }>Public tags</Text> <Text fontSize="sm" fontWeight={ 500 }>Public tags</Text>
<HStack spacing={ 2 } alignItems="baseline"> <HStack spacing={ 2 } alignItems="baseline">
{ item.tags.split(';').map((tag) => { { item.tags.split(';').map((tag) => <Tag key={ tag } isLoading={ isLoading } isTruncated>{ tag }</Tag>) }
return (
<TruncatedTextTooltip label={ tag } key={ tag }>
<Tag>
{ tag }
</Tag>
</TruncatedTextTooltip>
);
}) }
</HStack> </HStack>
</HStack> </HStack>
<HStack spacing={ 3 }> <HStack spacing={ 3 }>
<Text fontSize="sm" fontWeight={ 500 }>Status</Text> <Text fontSize="sm" fontWeight={ 500 }>Status</Text>
<Text fontSize="sm" variant="secondary">Submitted</Text> <Skeleton fontSize="sm" color="text_secondary" isLoaded={ !isLoading } display="inline-block">
<span>Submitted</span>
</Skeleton>
</HStack> </HStack>
</VStack> </VStack>
<TableItemActionButtons onDeleteClick={ onItemDeleteClick } onEditClick={ onItemEditClick }/> <TableItemActionButtons onDeleteClick={ onItemDeleteClick } onEditClick={ onItemEditClick } isLoading={ isLoading }/>
</ListItemMobile> </ListItemMobile>
); );
}; };
......
...@@ -12,12 +12,13 @@ import type { PublicTags, PublicTag } from 'types/api/account'; ...@@ -12,12 +12,13 @@ import type { PublicTags, PublicTag } from 'types/api/account';
import PublicTagTableItem from './PublicTagTableItem'; import PublicTagTableItem from './PublicTagTableItem';
interface Props { interface Props {
data: PublicTags; data?: PublicTags;
isLoading?: boolean;
onEditClick: (data: PublicTag) => void; onEditClick: (data: PublicTag) => void;
onDeleteClick: (data: PublicTag) => void; onDeleteClick: (data: PublicTag) => void;
} }
const PublicTagTable = ({ data, onEditClick, onDeleteClick }: Props) => { const PublicTagTable = ({ data, isLoading, onEditClick, onDeleteClick }: Props) => {
return ( return (
<Table variant="simple" minWidth="600px"> <Table variant="simple" minWidth="600px">
<Thead> <Thead>
...@@ -29,10 +30,11 @@ const PublicTagTable = ({ data, onEditClick, onDeleteClick }: Props) => { ...@@ -29,10 +30,11 @@ const PublicTagTable = ({ data, onEditClick, onDeleteClick }: Props) => {
</Tr> </Tr>
</Thead> </Thead>
<Tbody> <Tbody>
{ data.map((item) => ( { data?.map((item, index) => (
<PublicTagTableItem <PublicTagTableItem
key={ item.id + (isLoading ? String(index) : '') }
item={ item } item={ item }
key={ item.id } isLoading={ isLoading }
onDeleteClick={ onDeleteClick } onDeleteClick={ onDeleteClick }
onEditClick={ onEditClick } onEditClick={ onEditClick }
/> />
......
import { import {
Tag,
Tr, Tr,
Td, Td,
VStack, VStack,
Text, Box,
Skeleton,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import type { PublicTag } from 'types/api/account'; import type { PublicTag } from 'types/api/account';
import AddressSnippet from 'ui/shared/AddressSnippet'; import AddressSnippet from 'ui/shared/AddressSnippet';
import Tag from 'ui/shared/chakra/Tag';
import TableItemActionButtons from 'ui/shared/TableItemActionButtons'; import TableItemActionButtons from 'ui/shared/TableItemActionButtons';
import TruncatedTextTooltip from 'ui/shared/TruncatedTextTooltip';
interface Props { interface Props {
item: PublicTag; item: PublicTag;
isLoading?: boolean;
onEditClick: (data: PublicTag) => void; onEditClick: (data: PublicTag) => void;
onDeleteClick: (data: PublicTag) => void; onDeleteClick: (data: PublicTag) => void;
} }
const PublicTagTableItem = ({ item, onEditClick, onDeleteClick }: Props) => { const PublicTagTableItem = ({ item, isLoading, onEditClick, onDeleteClick }: Props) => {
const onItemEditClick = useCallback(() => { const onItemEditClick = useCallback(() => {
return onEditClick(item); return onEditClick(item);
}, [ item, onEditClick ]); }, [ item, onEditClick ]);
...@@ -32,29 +33,23 @@ const PublicTagTableItem = ({ item, onEditClick, onDeleteClick }: Props) => { ...@@ -32,29 +33,23 @@ const PublicTagTableItem = ({ item, onEditClick, onDeleteClick }: Props) => {
<Tr alignItems="top" key={ item.id }> <Tr alignItems="top" key={ item.id }>
<Td> <Td>
<VStack spacing={ 4 } alignItems="unset"> <VStack spacing={ 4 } alignItems="unset">
{ item.addresses_with_info.map((address) => <AddressSnippet key={ address.hash } address={ address }/>) } { item.addresses_with_info.map((address) => <AddressSnippet key={ address.hash } address={ address } isLoading={ isLoading }/>) }
</VStack> </VStack>
</Td> </Td>
<Td> <Td>
<VStack spacing={ 2 } alignItems="baseline"> <VStack spacing={ 2 } alignItems="baseline">
{ item.tags.split(';').map((tag) => { { item.tags.split(';').map((tag) => <Tag key={ tag } isLoading={ isLoading } isTruncated>{ tag }</Tag>) }
return (
<TruncatedTextTooltip label={ tag } key={ tag }>
<Tag>
{ tag }
</Tag>
</TruncatedTextTooltip>
);
}) }
</VStack> </VStack>
</Td> </Td>
<Td> <Td>
<VStack alignItems="flex-start"> <Skeleton fontSize="sm" fontWeight="500" py="2px" isLoaded={ !isLoading } display="inline-block">
<Text fontSize="sm" fontWeight="500">Submitted</Text> Submitted
</VStack> </Skeleton>
</Td> </Td>
<Td> <Td>
<TableItemActionButtons onDeleteClick={ onItemDeleteClick } onEditClick={ onItemEditClick }/> <Box py="2px">
<TableItemActionButtons onDeleteClick={ onItemDeleteClick } onEditClick={ onItemEditClick } isLoading={ isLoading }/>
</Box>
</Td> </Td>
</Tr> </Tr>
); );
......
...@@ -4,12 +4,10 @@ import React, { useCallback, useState } from 'react'; ...@@ -4,12 +4,10 @@ import React, { useCallback, useState } from 'react';
import type { PublicTag } from 'types/api/account'; import type { PublicTag } from 'types/api/account';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile'; import { PUBLIC_TAG } from 'stubs/account';
import PublicTagListItem from 'ui/publicTags/PublicTagTable/PublicTagListItem'; import PublicTagListItem from 'ui/publicTags/PublicTagTable/PublicTagListItem';
import AccountPageDescription from 'ui/shared/AccountPageDescription'; import AccountPageDescription from 'ui/shared/AccountPageDescription';
import DataFetchAlert from 'ui/shared/DataFetchAlert'; import DataFetchAlert from 'ui/shared/DataFetchAlert';
import SkeletonListAccount from 'ui/shared/skeletons/SkeletonListAccount';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
import DeletePublicTagModal from './DeletePublicTagModal'; import DeletePublicTagModal from './DeletePublicTagModal';
import PublicTagTable from './PublicTagTable/PublicTagTable'; import PublicTagTable from './PublicTagTable/PublicTagTable';
...@@ -22,9 +20,12 @@ type Props = { ...@@ -22,9 +20,12 @@ type Props = {
const PublicTagsData = ({ changeToFormScreen, onTagDelete }: Props) => { const PublicTagsData = ({ changeToFormScreen, onTagDelete }: Props) => {
const deleteModalProps = useDisclosure(); const deleteModalProps = useDisclosure();
const [ deleteModalData, setDeleteModalData ] = useState<PublicTag>(); const [ deleteModalData, setDeleteModalData ] = useState<PublicTag>();
const isMobile = useIsMobile();
const { data, isLoading, isError, error } = useApiQuery('public_tags'); const { data, isPlaceholderData, isError, error } = useApiQuery('public_tags', {
queryOptions: {
placeholderData: Array(3).fill(PUBLIC_TAG),
},
});
const onDeleteModalClose = useCallback(() => { const onDeleteModalClose = useCallback(() => {
setDeleteModalData(undefined); setDeleteModalData(undefined);
...@@ -53,22 +54,6 @@ const PublicTagsData = ({ changeToFormScreen, onTagDelete }: Props) => { ...@@ -53,22 +54,6 @@ const PublicTagsData = ({ changeToFormScreen, onTagDelete }: Props) => {
</AccountPageDescription> </AccountPageDescription>
); );
if (isLoading) {
const loader = isMobile ? <SkeletonListAccount/> : (
<>
<SkeletonTable columns={ [ '50%', '25%', '25%', '108px' ] }/>
<Skeleton height="48px" width="270px" marginTop={ 8 }/>
</>
);
return (
<>
{ description }
{ loader }
</>
);
}
if (isError) { if (isError) {
if (error.status === 403) { if (error.status === 403) {
throw new Error('Unverified email error', { cause: error }); throw new Error('Unverified email error', { cause: error });
...@@ -76,33 +61,37 @@ const PublicTagsData = ({ changeToFormScreen, onTagDelete }: Props) => { ...@@ -76,33 +61,37 @@ const PublicTagsData = ({ changeToFormScreen, onTagDelete }: Props) => {
return <DataFetchAlert/>; return <DataFetchAlert/>;
} }
const list = isMobile ? ( const list = (
<Box> <>
{ data.map((item) => ( <Box display={{ base: 'block', lg: 'none' }}>
<PublicTagListItem { data?.map((item, index) => (
item={ item } <PublicTagListItem
key={ item.id } key={ item.id + (isPlaceholderData ? String(index) : '') }
onDeleteClick={ onItemDeleteClick } item={ item }
onEditClick={ onItemEditClick } isLoading={ isPlaceholderData }
/> onDeleteClick={ onItemDeleteClick }
)) } onEditClick={ onItemEditClick }
</Box> />
) : ( )) }
<PublicTagTable data={ data } onEditClick={ onItemEditClick } onDeleteClick={ onItemDeleteClick }/> </Box>
<Box display={{ base: 'none', lg: 'block' }}>
<PublicTagTable data={ data } isLoading={ isPlaceholderData } onEditClick={ onItemEditClick } onDeleteClick={ onItemDeleteClick }/>
</Box>
</>
); );
return ( return (
<> <>
{ description } { description }
{ data.length > 0 && list } { Boolean(data?.length) && list }
<Box marginTop={ 8 }> <Skeleton mt={ 8 } isLoaded={ !isPlaceholderData } display="inline-block">
<Button <Button
size="lg" size="lg"
onClick={ changeToForm } onClick={ changeToForm }
> >
Request to add public tag Request to add public tag
</Button> </Button>
</Box> </Skeleton>
{ deleteModalData && ( { deleteModalData && (
<DeletePublicTagModal <DeletePublicTagModal
{ ...deleteModalProps } { ...deleteModalProps }
......
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