Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TW-830: Collectibles Manage dropdown #925

Merged
merged 27 commits into from
Jul 12, 2023
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
af8ba2b
TW-826: Collectibles re-design
alex-tsx Jun 23, 2023
8bc0474
TW-828: Collectibles grid layout
alex-tsx Jun 24, 2023
3430d15
TW-828: Collectibles grid layout. + Scroll tabsbar into view
alex-tsx Jun 26, 2023
65183c2
TW-828: Collectibles grid layout. ++ Images
alex-tsx Jun 26, 2023
079102d
TW-864: Collectibles hover effect
alex-tsx Jun 26, 2023
8898d8d
TW-828: Collectibles grid layout. Refactor
alex-tsx Jun 26, 2023
a7e1dca
Merge branch 'development' into TW-828-collectibles-grid
alex-tsx Jun 26, 2023
91b219a
TW-828: Collectibles grid layout. Refactor
alex-tsx Jun 29, 2023
fd976af
TW-830: Collectibles Manage dropdown. + Detailed grid
alex-tsx Jun 29, 2023
b47a127
TW-830: Collectibles Manage dropdown. + Detailes toggle
alex-tsx Jul 3, 2023
6672f10
TW-830: Collectibles Manage dropdown. + Floor prices
alex-tsx Jul 3, 2023
531ab18
Merge branch 'development' into TW-830-collectibles-manage-dropdown
alex-tsx Jul 4, 2023
c19133b
Merge branch 'development' into TW-828-collectibles-grid
alex-tsx Jul 4, 2023
1583a18
TW-828: Collectibles grid layout. Fix after QA
alex-tsx Jul 4, 2023
3c5b1e4
Merge branch 'TW-828-collectibles-grid' into TW-830-collectibles-mana…
alex-tsx Jul 4, 2023
0757ded
TW-830: Collectibles Manage dropdown. Fix floor price currency
alex-tsx Jul 4, 2023
76f3d2f
TW-830: Collectibles Manage dropdown. Refactor
alex-tsx Jul 5, 2023
e14d147
TW-830: Collectibles Manage dropdown. Refactor
alex-tsx Jul 5, 2023
ea9ab54
TW-830: Collectibles Manage dropdown. Refactor
alex-tsx Jul 5, 2023
b4b43fb
Merge branch 'development' into TW-830-collectibles-manage-dropdown
alex-tsx Jul 5, 2023
5d6a994
TW-830: Collectibles Manage dropdown. Fix QA. Loading details by slugs
alex-tsx Jul 6, 2023
be31160
TW-830: Collectibles Manage dropdown. Fix QA. By design
alex-tsx Jul 6, 2023
de83dd4
TW-830: Collectibles Manage dropdown. Fix QA. Scroll to the tabs bar
alex-tsx Jul 6, 2023
119bff1
TW-830: Collectibles Manage dropdown. Fix QA. Refactor
alex-tsx Jul 6, 2023
4b72ec6
Merge branch 'development' into TW-830-collectibles-manage-dropdown
alex-tsx Jul 10, 2023
9c7b2f7
TW-830: Collectibles Manage dropdown. Fix QA. 2 decimals for unletter…
alex-tsx Jul 10, 2023
5c0f445
TW-830: Collectibles Manage dropdown. Refactor
alex-tsx Jul 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions public/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2358,6 +2358,9 @@
"message": "less",
"description": "Show less"
},
"showInfo": {
"message": "Show info"
},
"recentDestinations": {
"message": "Recent destinations"
},
Expand Down
3 changes: 3 additions & 0 deletions public/_locales/uk/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1855,5 +1855,8 @@
"content": "$1"
}
}
},
"showInfo": {
"message": "Деталі"
}
}
2 changes: 2 additions & 0 deletions src/app/WithDataLoading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, { FC, useEffect } from 'react';
import { useDispatch } from 'react-redux';

import { useAdvertisingLoading } from 'app/hooks/use-advertising.hook';
import { useCollectiblesDetailsLoading } from 'app/hooks/use-collectibles-details-loading';
import { useLongRefreshLoading } from 'app/hooks/use-long-refresh-loading.hook';
import { useMetadataLoading } from 'app/hooks/use-metadata-loading';
import { useTokensLoading } from 'app/hooks/use-tokens-loading';
Expand All @@ -15,6 +16,7 @@ export const WithDataLoading: FC<PropsWithChildren> = ({ children }) => {
useMetadataLoading();
useTokensLoading();
useBalancesLoading();
useCollectiblesDetailsLoading();

useLongRefreshLoading();
useAdvertisingLoading();
Expand Down
4 changes: 2 additions & 2 deletions src/app/atoms/Banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ export const Banner: FC<Props> = ({
<p className="text-xs font-normal text-gray-700 mb-4">{description}</p>

<div className="flex justify-between">
<FormSecondaryButton small className="flex-1 mr-4 h-2.25 rounded-md" type="button" onClick={onDisable}>
<FormSecondaryButton small className="flex-1 mr-4 h-9 rounded-md" type="button" onClick={onDisable}>
<span className="capitalize text-base text-center w-full">{t(disableButtonText)}</span>
</FormSecondaryButton>

<FormSubmitButton small className="flex-1 h-2.25 rounded-md" onClick={onEnable}>
<FormSubmitButton small className="flex-1 h-9 rounded-md" onClick={onEnable}>
<span className="capitalize text-base text-center w-full whitespace-nowrap">{t(enableButtonText)}</span>
</FormSubmitButton>
</div>
Expand Down
27 changes: 14 additions & 13 deletions src/app/atoms/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ import { ReactComponent as OkIcon } from 'app/icons/ok.svg';
import { TestIDProps, setTestID, useAnalytics, AnalyticsEventCategory } from 'lib/analytics';
import { blurHandler, checkedHandler, focusHandler } from 'lib/ui/inputHandlers';

export type CheckboxProps = TestIDProps &
Pick<InputHTMLAttributes<HTMLInputElement>, 'name' | 'checked' | 'className' | 'onFocus' | 'onBlur' | 'onClick'> & {
containerClassName?: string;
errored?: boolean;
onChange?: (checked: boolean, event: React.ChangeEvent<HTMLInputElement>) => void;
};
export interface CheckboxProps
extends TestIDProps,
Pick<InputHTMLAttributes<HTMLInputElement>, 'name' | 'checked' | 'className' | 'onFocus' | 'onBlur' | 'onClick'> {
overrideClassNames?: string;
errored?: boolean;
onChange?: (checked: boolean, event: React.ChangeEvent<HTMLInputElement>) => void;
}

const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
(
{
containerClassName,
overrideClassNames,
errored = false,
className,
checked,
Expand Down Expand Up @@ -64,8 +65,8 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
const classNameMemo = useMemo(
() =>
classNames(
'flex justify-center items-center h-6 w-6 flex-shrink-0',
'text-white border rounded-md overflow-hidden',
'flex justify-center items-center flex-shrink-0',
'text-white border overflow-hidden',
'transition ease-in-out duration-200 disable-outline-for-click',
localChecked ? 'bg-primary-orange' : 'bg-black-40',
localFocused && 'shadow-outline',
Expand All @@ -81,9 +82,9 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
return 'border-gray-400';
}
})(),
containerClassName
overrideClassNames || 'h-6 w-6 rounded-md'
),
[localChecked, localFocused, errored, containerClassName]
[localChecked, localFocused, errored]
);

return (
Expand All @@ -101,8 +102,8 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
/>

<OkIcon
className={classNames(localChecked ? 'block' : 'hidden', 'h-4 w-4 pointer-events-none stroke-current')}
style={{ strokeWidth: 2 }}
className={classNames(localChecked ? 'block' : 'hidden', 'pointer-events-none stroke-current')}
style={{ strokeWidth: 2, height: '67%', width: '67%' }}
/>
</div>
);
Expand Down
6 changes: 3 additions & 3 deletions src/app/atoms/Divider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React, { FC } from 'react';

import clsx from 'clsx';
keshan3262 marked this conversation as resolved.
Show resolved Hide resolved

interface DividerProps {
style?: React.CSSProperties;
className?: string;
Expand All @@ -8,12 +10,10 @@ interface DividerProps {
const Divider: FC<DividerProps> = ({ style, className }) => (
<div
style={{
width: '100%',
height: '1px',
backgroundColor: '#E2E8F0',
...style
}}
className={className}
className={clsx('w-full bg-gray-300', className)}
/>
);

Expand Down
2 changes: 1 addition & 1 deletion src/app/atoms/DonationBanner/DonationBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const DONATE_MAD_FISH_URL = 'https://donate.mad.fish';

export const DonationBanner: FC = () => (
<Anchor
className="flex flex-col items-center justify-center rounded h-7 bg-blue-150 max-w-100"
className="flex flex-col items-center justify-center rounded h-7 bg-blue-150 max-w-25"
href={DONATE_MAD_FISH_URL}
testID={DonationBannerSelectors.ukraineDonationBanner}
>
Expand Down
16 changes: 11 additions & 5 deletions src/app/atoms/DropdownWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,21 @@ import CSSTransition from 'react-transition-group/CSSTransition';

type DropdownWrapperProps = HTMLAttributes<HTMLDivElement> & {
opened: boolean;
design?: Design;
hiddenOverflow?: boolean;
scaleAnimation?: boolean;
};

const DESIGN_CLASS_NAMES = {
light: 'bg-white border-gray-300',
dark: 'bg-gray-910 border-gray-850'
};

type Design = keyof typeof DESIGN_CLASS_NAMES;

const DropdownWrapper: FC<DropdownWrapperProps> = ({
opened,
design = 'light',
hiddenOverflow = true,
scaleAnimation = true,
className,
Expand All @@ -36,13 +45,10 @@ const DropdownWrapper: FC<DropdownWrapperProps> = ({
'mt-2 border rounded-md shadow-xl',
hiddenOverflow && 'overflow-hidden',
process.env.TARGET_BROWSER === 'firefox' && 'grayscale-firefox-fix',
DESIGN_CLASS_NAMES[design],
className
)}
style={{
backgroundColor: '#1b262c',
borderColor: '#212e36',
...style
}}
style={style}
{...rest}
/>
</CSSTransition>
Expand Down
4 changes: 2 additions & 2 deletions src/app/atoms/FormCheckbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import classNames from 'clsx';
import Checkbox, { CheckboxProps } from 'app/atoms/Checkbox';
import { AnalyticsEventCategory, setTestID, useAnalytics } from 'lib/analytics';

export type FormCheckboxProps = CheckboxProps & {
export interface FormCheckboxProps extends CheckboxProps {
label?: ReactNode;
labelDescription?: ReactNode;
errorCaption?: ReactNode;
containerClassName?: string;
labelClassName?: string;
};
}

export const FormCheckbox = forwardRef<HTMLInputElement, FormCheckboxProps>(
(
Expand Down
33 changes: 33 additions & 0 deletions src/app/hooks/use-collectibles-details-loading.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useMemo } from 'react';

import { useDispatch } from 'react-redux';

import { loadCollectiblesDetailsActions } from 'app/store/collectibles/actions';
import { COLLECTIBLES_DETAILS_SYNC_INTERVAL } from 'lib/fixed-times';
import { useAccount, useChainId, useCollectibleTokens } from 'lib/temple/front';
import { useInterval } from 'lib/ui/hooks';

export const useCollectiblesDetailsLoading = () => {
const chainId = useChainId()!;
const { publicKeyHash } = useAccount();
const { data: collectibles } = useCollectibleTokens(chainId, publicKeyHash);
const dispatch = useDispatch();

const { slugs, checksum } = useMemo(() => {
const slugs = collectibles.map(({ tokenSlug }) => tokenSlug);

const checksum = slugs.sort().join('+');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can add in deps slugs.length and remove checksum

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are not the same

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then what is the checksum ?

Copy link
Collaborator Author

@alex-tsx alex-tsx Jul 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The kind of dependency, that will only change, when slugs' values change. Not a link to the slugs array, but actual values. That's why I sort them first and then put together in one string.

collectibles (link to object) may change, then slugs (link to object) may change, while checksum will stay the same.


return { slugs, checksum };
}, [collectibles]);

useInterval(
() => {
if (slugs.length < 1) return;

dispatch(loadCollectiblesDetailsActions.submit(slugs));
},
COLLECTIBLES_DETAILS_SYNC_INTERVAL,
[checksum, dispatch]
keshan3262 marked this conversation as resolved.
Show resolved Hide resolved
);
};
6 changes: 6 additions & 0 deletions src/app/icons/editing.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 5 additions & 2 deletions src/app/icons/manage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/app/layouts/PageLayout/Header/AccountDropdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ const AccountDropdown: FC<AccountDropdownProps> = ({ opened, setOpened }) => {
return (
<DropdownWrapper
opened={opened}
className="origin-top-right p-2"
design="dark"
className="origin-top-right p-2 min-w-64"
style={{
minWidth: '16rem',
transform: 'translate(3.25rem, 3.25rem)',
pointerEvents: 'all'
}}
Expand Down
2 changes: 1 addition & 1 deletion src/app/layouts/PageLayout/Header/NetworkSelect/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const NetworkSelect: FC<NetworkSelectProps> = () => {
placement="bottom-end"
strategy="fixed"
popup={({ opened, setOpened }) => (
<DropdownWrapper opened={opened} className="origin-top-right p-2">
<DropdownWrapper opened={opened} design="dark" className="origin-top-right p-2">
<div className={styles.scroll}>
<h2
className={classNames(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ export const NewsletterOverlay: FC = () => {
<div
className={classNames(
'flex flex-col justify-center text-center bg-orange-100 shadow-lg bg-no-repeat rounded-md',
popup ? 'h-full' : 'h-700',
popup ? 'p-4' : 'px-3.5 py-4.5'
popup ? 'p-4' : 'px-13 py-18'
)}
style={{ height: popup ? '100%' : '700px' }}
>
<Button
className={classNames(
Expand Down Expand Up @@ -134,7 +134,7 @@ export const NewsletterOverlay: FC = () => {
<input
ref={register()}
name="email"
className="w-full max-h-3/25 p-4 rounded-md border text-sm text-gray-910"
className="w-full max-h-13 p-4 rounded-md border text-sm text-gray-910"
placeholder="example@mail.com"
{...setTestID(NewsletterOverlaySelectors.emailInput)}
/>
Expand Down
67 changes: 56 additions & 11 deletions src/app/pages/Collectibles/CollectibleItem.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,89 @@
import React, { FC, useCallback, useRef, useState } from 'react';
import React, { FC, useCallback, useRef, useState, useMemo } from 'react';

import { isDefined } from '@rnw-community/shared';
import clsx from 'clsx';

import Money from 'app/atoms/Money';
import { useAppEnv } from 'app/env';
import { useAssetMetadata, getAssetName } from 'lib/metadata';
import { useCollectibleDetailsSelector } from 'app/store/collectibles/selectors';
import { objktCurrencies } from 'lib/apis/objkt';
import { useAssetMetadata, getAssetName, TEZOS_METADATA } from 'lib/metadata';
import { useBalance } from 'lib/temple/front';
import { atomsToTokens } from 'lib/temple/helpers';
import { useIntersectionDetection } from 'lib/ui/use-intersection-detection';
import { Link } from 'lib/woozie';

import { CollectibleItemImage } from './CollectibleItemImage';

interface Props {
assetSlug: string;
index: number;
itemsLength: number;
detailsShown?: boolean;
accountPkh: string;
areDetailsShown: boolean;
}

export const CollectibleItem: FC<Props> = ({ assetSlug, detailsShown }) => {
export const CollectibleItem: FC<Props> = ({ assetSlug, accountPkh, areDetailsShown }) => {
const { popup } = useAppEnv();
const metadata = useAssetMetadata(assetSlug);
const toDisplayRef = useRef<HTMLDivElement>(null);
const [displayed, setDisplayed] = useState(true);
const { data: balance } = useBalance(assetSlug, accountPkh, { displayed });
const details = useCollectibleDetailsSelector(assetSlug);

const listing = useMemo(() => {
if (!isDefined(details)) return null;

const { floorPrice, currencyId } = details.listing;
const currency = objktCurrencies[currencyId];

if (!isDefined(currency)) return null;

return { floorPrice, decimals: currency.decimals, symbol: currency.symbol };
}, [details]);

const handleIntersection = useCallback(() => {
setDisplayed(true);
}, [setDisplayed]);

useIntersectionDetection(toDisplayRef, handleIntersection, !displayed);

const assetName = getAssetName(metadata);

return (
<Link to={`/collectible/${assetSlug}`} className="flex flex-col border border-gray-300 rounded-lg">
<div
ref={toDisplayRef}
className="flex items-center justify-center bg-blue-50 rounded-lg overflow-hidden hover:opacity-70"
style={{ height: popup ? 106 : 125 }}
className={clsx(
'relative flex items-center justify-center bg-blue-50 rounded-lg overflow-hidden hover:opacity-70',
areDetailsShown && 'border-b border-gray-300',
popup ? 'h-26.5' : 'h-31.25'
)}
title={assetName}
>
{displayed && <CollectibleItemImage metadata={metadata} assetSlug={assetSlug} />}

{areDetailsShown && balance ? (
<div className="absolute bottom-1.5 left-1.5 text-2xs text-white leading-none p-1 bg-black bg-opacity-60 rounded">
{balance.toFixed()}×
</div>
) : null}
</div>

{detailsShown && (
<div className="mt-2">
<p className="text-sm text-gray-910">{getAssetName(metadata)}</p>
{areDetailsShown && (
<div className="mt-1 mb-2 mx-1.5">
<h5 className="text-sm leading-5 text-gray-910 truncate">{assetName}</h5>
<div className="text-2xs leading-3 text-gray-600">
<span>Floor: </span>
{isDefined(listing) ? (
<>
<Money shortened smallFractionFont={false} tooltip={true} cryptoDecimals={TEZOS_METADATA.decimals}>
{atomsToTokens(listing.floorPrice, listing.decimals)}
</Money>
<span> {listing.symbol}</span>
</>
) : (
'-'
)}
</div>
</div>
)}
</Link>
Expand Down
Loading
Loading