Commit 910e86d6 authored by Charles Bachmeier's avatar Charles Bachmeier Committed by GitHub

feat: Add loading skeleton for profile page (#4823)

* Add loading skeleton for profile page

* add consts for sidebar width and padding
Co-authored-by: default avatarCharles Bachmeier <charlie@genie.xyz>
parent 537fea10
...@@ -26,6 +26,7 @@ import styled from 'styled-components/macro' ...@@ -26,6 +26,7 @@ import styled from 'styled-components/macro'
import { EmptyWalletContent } from './EmptyWalletContent' import { EmptyWalletContent } from './EmptyWalletContent'
import { ProfileAccountDetails } from './ProfileAccountDetails' import { ProfileAccountDetails } from './ProfileAccountDetails'
import * as styles from './ProfilePage.css' import * as styles from './ProfilePage.css'
import { ProfilePageLoadingSkeleton } from './ProfilePageLoadingSkeleton'
import { WalletAssetDisplay } from './WalletAssetDisplay' import { WalletAssetDisplay } from './WalletAssetDisplay'
const SellModeButton = styled.button<{ active: boolean }>` const SellModeButton = styled.button<{ active: boolean }>`
...@@ -46,6 +47,9 @@ const SellModeButton = styled.button<{ active: boolean }>` ...@@ -46,6 +47,9 @@ const SellModeButton = styled.button<{ active: boolean }>`
} }
` `
const FILTER_SIDEBAR_WIDTH = 300
const PADDING = 16
function roundFloorPrice(price?: number, n?: number) { function roundFloorPrice(price?: number, n?: number) {
return price ? Math.round(price * Math.pow(10, n ?? 3) + Number.EPSILON) / Math.pow(10, n ?? 3) : 0 return price ? Math.round(price * Math.pow(10, n ?? 3) + Number.EPSILON) / Math.pow(10, n ?? 3) : 0
} }
...@@ -76,7 +80,7 @@ export const ProfilePage = () => { ...@@ -76,7 +80,7 @@ export const ProfilePage = () => {
toggleSellMode() toggleSellMode()
} }
const { data: ownerCollections } = useQuery( const { data: ownerCollections, isLoading: collectionsAreLoading } = useQuery(
['ownerCollections', address], ['ownerCollections', address],
() => OSCollectionsFetcher({ params: { asset_owner: address, offset: '0', limit: '300' } }), () => OSCollectionsFetcher({ params: { asset_owner: address, offset: '0', limit: '300' } }),
{ {
...@@ -85,7 +89,7 @@ export const ProfilePage = () => { ...@@ -85,7 +89,7 @@ export const ProfilePage = () => {
) )
const ownerCollectionsAddresses = useMemo(() => ownerCollections?.map(({ address }) => address), [ownerCollections]) const ownerCollectionsAddresses = useMemo(() => ownerCollections?.map(({ address }) => address), [ownerCollections])
const { data: collectionStats } = useQuery( const { data: collectionStats, isLoading: collectionStatsAreLoading } = useQuery(
['ownerCollectionStats', ownerCollectionsAddresses], ['ownerCollectionStats', ownerCollectionsAddresses],
() => fetchMultipleCollectionStats({ addresses: ownerCollectionsAddresses ?? [] }), () => fetchMultipleCollectionStats({ addresses: ownerCollectionsAddresses ?? [] }),
{ {
...@@ -98,6 +102,7 @@ export const ProfilePage = () => { ...@@ -98,6 +102,7 @@ export const ProfilePage = () => {
fetchNextPage, fetchNextPage,
hasNextPage, hasNextPage,
isSuccess, isSuccess,
isLoading: assetsAreLoading,
} = useInfiniteQuery( } = useInfiniteQuery(
['ownerAssets', address, collectionFilters], ['ownerAssets', address, collectionFilters],
async ({ pageParam = 0 }) => { async ({ pageParam = 0 }) => {
...@@ -116,6 +121,8 @@ export const ProfilePage = () => { ...@@ -116,6 +121,8 @@ export const ProfilePage = () => {
} }
) )
const anyQueryIsLoading = collectionsAreLoading || collectionStatsAreLoading || assetsAreLoading
const ownerAssets = useMemo(() => (isSuccess ? ownerAssetsData?.pages.flat() : null), [isSuccess, ownerAssetsData]) const ownerAssets = useMemo(() => (isSuccess ? ownerAssetsData?.pages.flat() : null), [isSuccess, ownerAssetsData])
useEffect(() => { useEffect(() => {
...@@ -153,17 +160,19 @@ export const ProfilePage = () => { ...@@ -153,17 +160,19 @@ export const ProfilePage = () => {
}, [collectionStats, ownerCollections, setWalletCollections]) }, [collectionStats, ownerCollections, setWalletCollections])
const { gridX } = useSpring({ const { gridX } = useSpring({
gridX: isFiltersExpanded ? 300 : -16, gridX: isFiltersExpanded ? FILTER_SIDEBAR_WIDTH : -PADDING,
}) })
return ( return (
<Column <Column
width="full" width="full"
paddingLeft={{ sm: '16', md: '52' }} paddingLeft={{ sm: `${PADDING}`, md: '52' }}
paddingRight={{ sm: '0', md: isBagExpanded ? '0' : '72' }} paddingRight={{ sm: `${PADDING}`, md: isBagExpanded ? '0' : '72' }}
paddingTop={{ sm: '16', md: '40' }} paddingTop={{ sm: `${PADDING}`, md: '40' }}
> >
{walletAssets.length === 0 ? ( {anyQueryIsLoading ? (
<ProfilePageLoadingSkeleton />
) : walletAssets.length === 0 ? (
<EmptyWalletContent /> <EmptyWalletContent />
) : ( ) : (
<Row alignItems="flex-start" position="relative"> <Row alignItems="flex-start" position="relative">
...@@ -173,10 +182,12 @@ export const ProfilePage = () => { ...@@ -173,10 +182,12 @@ export const ProfilePage = () => {
<Column width="full"> <Column width="full">
<ProfileAccountDetails /> <ProfileAccountDetails />
<AnimatedBox <AnimatedBox
paddingLeft={isFiltersExpanded ? '24' : '16'}
flexShrink="0" flexShrink="0"
style={{ style={{
transform: gridX.to((x) => `translate(${Number(x) - (!isMobile && isFiltersExpanded ? 300 : 0)}px)`), transform: gridX.to(
(x) =>
`translate(${Number(x) - (!isMobile && isFiltersExpanded ? FILTER_SIDEBAR_WIDTH : -PADDING)}px)`
),
}} }}
> >
<Row gap="8" flexWrap="nowrap" justifyContent="space-between"> <Row gap="8" flexWrap="nowrap" justifyContent="space-between">
......
import { assetList } from 'nft/components/collection/CollectionNfts.css'
import styled from 'styled-components/macro'
const SkeletonPageWrapper = styled.div`
display: flex;
flex-direction: column;
width: 100%;
gap: 18px;
`
const SkeletonRowWrapper = styled.div`
display: flex;
flex-direct: row;
width: 100%;
`
const AccountDetailsSkeletonWrapper = styled(SkeletonRowWrapper)`
gap: 12px;
margin-bottom: 30px;
`
const ProfilePictureSkeleton = styled.div`
height: 44px;
width: 44px;
background: ${({ theme }) => theme.backgroundModule};
border-radius: 100px;
`
const ProfileDetailsSkeleton = styled.div`
width: 180px;
height: 36px;
background: ${({ theme }) => theme.backgroundModule};
border-radius: 12px;
`
const FilterBarSkeletonWrapper = styled(SkeletonRowWrapper)`
justify-content: space-between;
`
const FilterButtonSkeleton = styled.div`
width: 92px;
height: 44px;
background: ${({ theme }) => theme.backgroundModule};
border-radius: 12px;
`
const SellButtonSkeleton = styled.div`
width: 80px;
height: 44px;
background: ${({ theme }) => theme.backgroundModule};
border-radius: 12px;
`
export const ProfileAssetsWrapperSkeleton = styled(SkeletonRowWrapper)`
flex-wrap: wrap;
gap: 26px;
margin-bottom: 20px;
`
export const ProfileAssetCardSkeleton = styled.div`
width: 100%;
height: 330px;
background: ${({ theme }) => theme.backgroundModule};
border-radius: 20px;
`
export const ProfilePageLoadingSkeleton = () => {
return (
<SkeletonPageWrapper>
<AccountDetailsSkeletonWrapper>
<ProfilePictureSkeleton />
<ProfileDetailsSkeleton />
</AccountDetailsSkeletonWrapper>
<FilterBarSkeletonWrapper>
<FilterButtonSkeleton />
<SellButtonSkeleton />
</FilterBarSkeletonWrapper>
<div className={assetList}>{new Array(25).fill(<ProfileAssetCardSkeleton />)}</div>
</SkeletonPageWrapper>
)
}
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