Commit 3d4d8575 authored by tom's avatar tom

skeletons public tags

parent 54951e67
......@@ -13,3 +13,17 @@ export const PRIVATE_TAG_TX = {
name: 'placeholder',
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';
import type { AddressTag } from 'types/api/account';
import useApiQuery from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile';
import { PRIVATE_TAG_ADDRESS } from 'stubs/account';
import AccountPageDescription from 'ui/shared/AccountPageDescription';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
......@@ -24,7 +23,6 @@ const PrivateAddressTags = () => {
const addressModalProps = useDisclosure();
const deleteModalProps = useDisclosure();
const isMobile = useIsMobile();
const [ addressModalData, setAddressModalData ] = useState<AddressTag>();
const [ deleteModalData, setDeleteModalData ] = useState<AddressTag>();
......@@ -56,8 +54,9 @@ const PrivateAddressTags = () => {
return <DataFetchAlert/>;
}
const list = isMobile ? (
<Box>
const list = (
<>
<Box display={{ base: 'block', lg: 'none' }}>
{ addressTagsData?.map((item: AddressTag, index: number) => (
<AddressTagListItem
item={ item }
......@@ -68,13 +67,15 @@ const PrivateAddressTags = () => {
/>
)) }
</Box>
) : (
<Box display={{ base: 'none', lg: 'block' }}>
<AddressTagTable
isLoading={ isPlaceholderData }
data={ addressTagsData }
onDeleteClick={ onDeleteClick }
onEditClick={ onEditClick }
/>
</Box>
</>
);
return (
......
......@@ -4,7 +4,6 @@ import React, { useCallback, useState } from 'react';
import type { TransactionTag } from 'types/api/account';
import useApiQuery from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile';
import { PRIVATE_TAG_TX } from 'stubs/account';
import AccountPageDescription from 'ui/shared/AccountPageDescription';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
......@@ -24,7 +23,6 @@ const PrivateTransactionTags = () => {
const transactionModalProps = useDisclosure();
const deleteModalProps = useDisclosure();
const isMobile = useIsMobile();
const [ transactionModalData, setTransactionModalData ] = useState<TransactionTag>();
const [ deleteModalData, setDeleteModalData ] = useState<TransactionTag>();
......@@ -63,8 +61,9 @@ const PrivateTransactionTags = () => {
return <DataFetchAlert/>;
}
const list = isMobile ? (
<Box>
const list = (
<>
<Box display={{ base: 'block', lg: 'none' }}>
{ transactionTagsData?.map((item, index) => (
<TransactionTagListItem
key={ item.id + (isPlaceholderData ? index : '') }
......@@ -75,13 +74,15 @@ const PrivateTransactionTags = () => {
/>
)) }
</Box>
) : (
<Box display={{ base: 'none', lg: 'block' }}>
<TransactionTagTable
data={ transactionTagsData }
isLoading={ isPlaceholderData }
onDeleteClick={ onDeleteClick }
onEditClick={ onEditClick }
/>
</Box>
</>
);
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 type { PublicTag } from 'types/api/account';
import AddressSnippet from 'ui/shared/AddressSnippet';
import Tag from 'ui/shared/chakra/Tag';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import TableItemActionButtons from 'ui/shared/TableItemActionButtons';
import TruncatedTextTooltip from 'ui/shared/TruncatedTextTooltip';
interface Props {
item: PublicTag;
isLoading?: boolean;
onEditClick: (data: PublicTag) => void;
onDeleteClick: (data: PublicTag) => void;
}
const PublicTagListItem = ({ item, onEditClick, onDeleteClick }: Props) => {
const PublicTagListItem = ({ item, isLoading, onEditClick, onDeleteClick }: Props) => {
const onItemEditClick = useCallback(() => {
return onEditClick(item);
}, [ item, onEditClick ]);
......@@ -27,28 +28,22 @@ const PublicTagListItem = ({ item, onEditClick, onDeleteClick }: Props) => {
<ListItemMobile>
<VStack spacing={ 3 } alignItems="flex-start" 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>
<HStack spacing={ 3 }>
<Text fontSize="sm" fontWeight={ 500 }>Public tags</Text>
<HStack spacing={ 2 } alignItems="baseline">
{ item.tags.split(';').map((tag) => {
return (
<TruncatedTextTooltip label={ tag } key={ tag }>
<Tag>
{ tag }
</Tag>
</TruncatedTextTooltip>
);
}) }
{ item.tags.split(';').map((tag) => <Tag key={ tag } isLoading={ isLoading } isTruncated>{ tag }</Tag>) }
</HStack>
</HStack>
<HStack spacing={ 3 }>
<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>
</VStack>
<TableItemActionButtons onDeleteClick={ onItemDeleteClick } onEditClick={ onItemEditClick }/>
<TableItemActionButtons onDeleteClick={ onItemDeleteClick } onEditClick={ onItemEditClick } isLoading={ isLoading }/>
</ListItemMobile>
);
};
......
......@@ -12,12 +12,13 @@ import type { PublicTags, PublicTag } from 'types/api/account';
import PublicTagTableItem from './PublicTagTableItem';
interface Props {
data: PublicTags;
data?: PublicTags;
isLoading?: boolean;
onEditClick: (data: PublicTag) => void;
onDeleteClick: (data: PublicTag) => void;
}
const PublicTagTable = ({ data, onEditClick, onDeleteClick }: Props) => {
const PublicTagTable = ({ data, isLoading, onEditClick, onDeleteClick }: Props) => {
return (
<Table variant="simple" minWidth="600px">
<Thead>
......@@ -29,10 +30,11 @@ const PublicTagTable = ({ data, onEditClick, onDeleteClick }: Props) => {
</Tr>
</Thead>
<Tbody>
{ data.map((item) => (
{ data?.map((item, index) => (
<PublicTagTableItem
key={ item.id + (isLoading ? String(index) : '') }
item={ item }
key={ item.id }
isLoading={ isLoading }
onDeleteClick={ onDeleteClick }
onEditClick={ onEditClick }
/>
......
import {
Tag,
Tr,
Td,
VStack,
Text,
Box,
Skeleton,
} from '@chakra-ui/react';
import React, { useCallback } from 'react';
import type { PublicTag } from 'types/api/account';
import AddressSnippet from 'ui/shared/AddressSnippet';
import Tag from 'ui/shared/chakra/Tag';
import TableItemActionButtons from 'ui/shared/TableItemActionButtons';
import TruncatedTextTooltip from 'ui/shared/TruncatedTextTooltip';
interface Props {
item: PublicTag;
isLoading?: boolean;
onEditClick: (data: PublicTag) => void;
onDeleteClick: (data: PublicTag) => void;
}
const PublicTagTableItem = ({ item, onEditClick, onDeleteClick }: Props) => {
const PublicTagTableItem = ({ item, isLoading, onEditClick, onDeleteClick }: Props) => {
const onItemEditClick = useCallback(() => {
return onEditClick(item);
}, [ item, onEditClick ]);
......@@ -32,29 +33,23 @@ const PublicTagTableItem = ({ item, onEditClick, onDeleteClick }: Props) => {
<Tr alignItems="top" key={ item.id }>
<Td>
<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>
</Td>
<Td>
<VStack spacing={ 2 } alignItems="baseline">
{ item.tags.split(';').map((tag) => {
return (
<TruncatedTextTooltip label={ tag } key={ tag }>
<Tag>
{ tag }
</Tag>
</TruncatedTextTooltip>
);
}) }
{ item.tags.split(';').map((tag) => <Tag key={ tag } isLoading={ isLoading } isTruncated>{ tag }</Tag>) }
</VStack>
</Td>
<Td>
<VStack alignItems="flex-start">
<Text fontSize="sm" fontWeight="500">Submitted</Text>
</VStack>
<Skeleton fontSize="sm" fontWeight="500" py="2px" isLoaded={ !isLoading } display="inline-block">
Submitted
</Skeleton>
</Td>
<Td>
<TableItemActionButtons onDeleteClick={ onItemDeleteClick } onEditClick={ onItemEditClick }/>
<Box py="2px">
<TableItemActionButtons onDeleteClick={ onItemDeleteClick } onEditClick={ onItemEditClick } isLoading={ isLoading }/>
</Box>
</Td>
</Tr>
);
......
......@@ -4,12 +4,10 @@ import React, { useCallback, useState } from 'react';
import type { PublicTag } from 'types/api/account';
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 AccountPageDescription from 'ui/shared/AccountPageDescription';
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 PublicTagTable from './PublicTagTable/PublicTagTable';
......@@ -22,9 +20,12 @@ type Props = {
const PublicTagsData = ({ changeToFormScreen, onTagDelete }: Props) => {
const deleteModalProps = useDisclosure();
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(() => {
setDeleteModalData(undefined);
......@@ -53,22 +54,6 @@ const PublicTagsData = ({ changeToFormScreen, onTagDelete }: Props) => {
</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 (error.status === 403) {
throw new Error('Unverified email error', { cause: error });
......@@ -76,33 +61,37 @@ const PublicTagsData = ({ changeToFormScreen, onTagDelete }: Props) => {
return <DataFetchAlert/>;
}
const list = isMobile ? (
<Box>
{ data.map((item) => (
const list = (
<>
<Box display={{ base: 'block', lg: 'none' }}>
{ data?.map((item, index) => (
<PublicTagListItem
key={ item.id + (isPlaceholderData ? String(index) : '') }
item={ item }
key={ item.id }
isLoading={ isPlaceholderData }
onDeleteClick={ onItemDeleteClick }
onEditClick={ onItemEditClick }
/>
)) }
</Box>
) : (
<PublicTagTable data={ data } onEditClick={ onItemEditClick } onDeleteClick={ onItemDeleteClick }/>
<Box display={{ base: 'none', lg: 'block' }}>
<PublicTagTable data={ data } isLoading={ isPlaceholderData } onEditClick={ onItemEditClick } onDeleteClick={ onItemDeleteClick }/>
</Box>
</>
);
return (
<>
{ description }
{ data.length > 0 && list }
<Box marginTop={ 8 }>
{ Boolean(data?.length) && list }
<Skeleton mt={ 8 } isLoaded={ !isPlaceholderData } display="inline-block">
<Button
size="lg"
onClick={ changeToForm }
>
Request to add public tag
</Button>
</Box>
</Skeleton>
{ deleteModalData && (
<DeletePublicTagModal
{ ...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