Skip to content

Commit

Permalink
feat(bridge-ui-v2): review step (#14940)
Browse files Browse the repository at this point in the history
  • Loading branch information
KorbinianK authored Oct 12, 2023
1 parent 99b200b commit c079223
Show file tree
Hide file tree
Showing 22 changed files with 636 additions and 242 deletions.
1 change: 1 addition & 0 deletions packages/bridge-ui-v2/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
node_modules
/build
/.svelte-kit
.svelte-kit/
/package
.env
.env.*
Expand Down
167 changes: 136 additions & 31 deletions packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
import { Button } from '$components/Button';
import { Card } from '$components/Card';
import { ChainSelectorWrapper } from '$components/ChainSelector';
import ChainSelector from '$components/ChainSelector/ChainSelector.svelte';
import { Icon } from '$components/Icon';
import IconFlipper from '$components/Icon/IconFlipper.svelte';
import { NFTCard } from '$components/NFTCard';
import { NFTList } from '$components/NFTList';
import { successToast, warningToast } from '$components/NotificationToast';
import { errorToast, infoToast } from '$components/NotificationToast/NotificationToast.svelte';
Expand Down Expand Up @@ -40,6 +44,7 @@
import { getTokenWithInfoFromAddress } from '$libs/token/getTokenWithInfoFromAddress';
import { refreshUserBalance } from '$libs/util/balance';
import { getConnectedWallet } from '$libs/util/getConnectedWallet';
import { shortenAddress } from '$libs/util/shortenAddress';
import { type Account, account } from '$stores/account';
import { type Network, network } from '$stores/network';
import { pendingTransactions } from '$stores/pendingTransactions';
Expand Down Expand Up @@ -364,6 +369,7 @@
let nftStepTitle: string;
let nftStepDescription: string;
let nextStepButtonText: string;
let nftIdArray: number[];
let enteredIds: string = '';
let contractAddress: Address | '';
Expand All @@ -381,6 +387,12 @@
let foundNFTs: NFT[] = [];
let selectedNFT: NFT[] = [];
enum NFTView {
CARDS,
LIST,
}
let nftView: NFTView = NFTView.CARDS;
function onAddressValidation(event: CustomEvent<{ isValidEthereumAddress: boolean; addr: Address }>) {
const { isValidEthereumAddress, addr } = event.detail;
addressInputState = AddressInputState.Validating;
Expand All @@ -406,6 +418,7 @@
addressInputState = AddressInputState.Invalid;
}
}
const scanForNFTs = async () => {
scanning = true;
const accountAddress = $account?.address;
Expand All @@ -417,8 +430,27 @@
scanned = true;
};
const changeNFTView = () => {
if (nftView === NFTView.CARDS) {
nftView = NFTView.LIST;
} else {
nftView = NFTView.CARDS;
}
};
const searchNFTs = () => {
// TODO: implement
};
// Whenever the user switches bridge types, we should reset the forms
$: $activeBridge && resetForm();
$: $activeBridge && (resetForm(), (activeStep = NFTSteps.IMPORT));
$: {
const stepKey = NFTSteps[activeStep].toLowerCase();
nftStepTitle = $t(`bridge.title.nft.${stepKey}`);
nftStepDescription = $t(`bridge.description.nft.${stepKey}`);
nextStepButtonText = activeStep === NFTSteps.CONFIRM ? $t('common.confirm') : $t('common.continue');
}
$: {
const stepKey = NFTSteps[activeStep].toLowerCase();
Expand Down Expand Up @@ -545,54 +577,126 @@
Automatic NFT Input
-->
<div class="f-between-center w-full gap-4">
<Button
disabled={!canScan}
loading={scanning}
type="primary"
class="px-[28px] py-[14px] rounded-full flex-1 text-white"
on:click={scanForNFTs}>Scan for NFTs</Button>
{#if !scanned}
<Button
disabled={!canScan}
loading={scanning}
type="primary"
class="px-[28px] py-[14px] rounded-full flex-1 text-white"
on:click={scanForNFTs}>{$t('bridge.actions.nft_scan')}</Button>
{:else}
<Button
disabled={!canScan}
loading={scanning}
type="neutral"
class="px-[28px] py-[14px] rounded-full flex-1 bg-transparent !border border-primary-brand hover:border-primary-interactive-hover"
on:click={scanForNFTs}>{$t('bridge.actions.nft_scan_again')}</Button>
{/if}
</div>

<!--
Automatic NFT Input
-->
<div class="f-col w-full gap-4">
{#if scanned}
<h2>Your NFTs:</h2>
<h2>{$t('bridge.nft.step.import.scan_screen.title')}</h2>
<!-- Todo: also enable card view here? -->
<NFTList bind:nfts={foundNFTs} chainId={$network?.id} bind:selectedNFT />

<div class="flex items-center justify-between space-x-2">
<span class="text-sm">Don't see your NFTs?<br /> Try adding them manually!</span>
<FlatAlert type="warning" message={$t('bridge.nft.step.import.scan_screen.description')} />
<Button
type="neutral"
class="bg-transparent !border border-primary-brand hover:border-primary-interactive-hover py-[14px]"
class="bg-transparent !border border-primary-brand hover:border-primary-interactive-hover "
on:click={() => (manualNFTInput = !manualNFTInput)}>
Add manually
{$t('bridge.actions.nft_manual')}
</Button>
</div>
{/if}

<NFTList bind:nfts={foundNFTs} chainId={$network?.id} bind:selectedNFT />
</div>
{/if}

<!-- REVIEW STEP -->
{:else if activeStep === NFTSteps.REVIEW}
<div class="container mx-auto inline-block align-middle space-y-[25px]">
<div class="flex justify-between mb-2 items-center">
<div class="font-bold">{$t('common.destination')}</div>
<div><ChainSelector small value={$destinationChain} readOnly /></div>
</div>

<div class="flex justify-between mb-2">
<div class="font-bold">{$t('common.contract_address')}</div>
<div class="text-secondary-content">
<ul>
{#each selectedNFT as nft}
{@const currentChain = $network?.id}
{#if currentChain && $destinationChain?.id}
<li>
<a
class="flex justify-start link"
href={`${chainConfig[$destinationChain?.id].urls.explorer}`}
target="_blank">
{shortenAddress(nft.addresses[currentChain], 8, 12)}
<Icon type="arrow-top-right" fillClass="fill-primary-link" />
</a>
</li>
{/if}
{/each}
</ul>
</div>
</div>

<div class="flex justify-between">
<div class="font-bold">{$t('bridge.nft.step.review.token_id')}</div>
<div class="break-words text-right text-secondary-content">
<ul>
{#each selectedNFT as nft}
<li>{nft.tokenId}</li>
{/each}
</ul>
</div>
</div>
</div>
<div class="h-sep" />
<!--
Recipient & Processing Fee
-->
<div class="space-y-[16px]">
<Recipient bind:this={recipientComponent} />
<ProcessingFee bind:this={processingFeeComponent} />
</div>
<!-- REVIEW STEP -->
{:else if activeStep === NFTSteps.REVIEW}
<div class="f-between-center gap-4">
<div class="f-col">
<p>Contract: {contractAddress}</p>
<div class="h-sep" />
<div class="flex justify-between items-center w-full">
<div class="flex items-center gap-2">
<span>{$t('bridge.nft.step.review.your_tokens')}</span>
<ChainSelector small value={$network} readOnly />
</div>
<div class="flex gap-2">
<Button
disabled={true}
shape="circle"
type="neutral"
class="!w-9 !h-9 rounded-full"
on:click={searchNFTs}>
<Icon type="magnifier" fillClass="fill-primary-icon" size={24} vWidth={24} vHeight={24} />
</Button>
<IconFlipper
iconType1="list"
iconType2="cards"
selectedDefault="list"
class="bg-neutral w-9 h-9 rounded-full"
on:labelclick={changeNFTView} />
<!-- <Icon type="list" fillClass="fill-primary-icon" size={24} vWidth={24} vHeight={24} /> -->
</div>
</div>
{#if nftView === NFTView.LIST}
<NFTList bind:nfts={selectedNFT} chainId={$network?.id} viewOnly />
{:else if nftView === NFTView.CARDS}
<div class="rounded-[20px] bg-neutral min-h-[200px] w-full p-2 f-center">
{#each selectedNFT as nft}
<p>Name: {nft.name}</p>
<p>Type: {nft.type}</p>
<p>ID: {nft.tokenId}</p>
<p>URI: {nft.uri}</p>
<p>Balance: {nft.balance}</p>
<NFTCard {nft} />
{/each}

<!-- <p>IDs: {nftIdArray.join(', ')}</p> -->
</div>
</div>
{/if}
<!-- CONFIRM STEP -->
{:else if activeStep === NFTSteps.CONFIRM}
<div class="f-between-center gap-4">
Expand All @@ -607,15 +711,16 @@
<div class="f-between-center w-full gap-4">
{#if activeStep !== NFTSteps.IMPORT}
<Button
type="secondary"
class="px-[28px] py-[14px] rounded-full flex-1 text-secondary-content"
on:click={previousStep}>Previous Step</Button>
type="neutral"
class="px-[28px] py-[14px] rounded-full w-auto flex-1 bg-transparent !border border-primary-brand hover:border-primary-interactive-hover"
on:click={previousStep}>
<span class="body-bold">{$t('common.edit')}</span></Button>
{/if}
<Button
disabled={!canProceed}
type="primary"
class="px-[28px] py-[14px] rounded-full flex-1 text-white"
on:click={nextStep}>Next Step</Button>
on:click={nextStep}><span class="body-bold">{nextStepButtonText}</span></Button>
</div>
</div></Card>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
'flex justify-start content-center',
);
let iconSize = small ? 'w-5 h-5' : 'w-7 h-7';
let switchingNetwork = false;
let buttonId = `button-${uid()}`;
let dialogId = `dialog-${uid()}`;
Expand Down Expand Up @@ -134,7 +136,7 @@
{#if value}
{@const icon = chainConfig[Number(value.id)]?.icon || 'Unknown Chain'}
<i role="img" aria-label={value.name}>
<img src={icon} alt="chain-logo" class="rounded-full w-6 h-6" />
<img src={icon} alt="chain-logo" class="rounded-full {iconSize}" />
</i>
<span>{truncateString(value.name, 8)}</span>
{/if}
Expand Down
28 changes: 25 additions & 3 deletions packages/bridge-ui-v2/src/components/Icon/Icon.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
| 'trash'
| 'adjustments'
| 'sun'
| 'moon';
| 'moon'
| 'list'
| 'magnifier'
| 'cards';
</script>

<script lang="ts">
Expand Down Expand Up @@ -226,6 +229,25 @@
class={fillClass}
fill="none"
d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"
></path
>{/if}
></path>
{:else if type === 'list'}
<path
class={fillClass}
fill-rule="evenodd"
clip-rule="evenodd"
d="M3.375 6.75C3.375 6.12868 3.87868 5.625 4.5 5.625C5.12132 5.625 5.625 6.12868 5.625 6.75C5.625 7.37132 5.12132 7.875 4.5 7.875C3.87868 7.875 3.375 7.37132 3.375 6.75ZM8.25 6.75C8.25 6.33579 8.58579 6 9 6H21C21.4142 6 21.75 6.33579 21.75 6.75C21.75 7.16421 21.4142 7.5 21 7.5H9C8.58579 7.5 8.25 7.16421 8.25 6.75ZM3.375 12C3.375 11.3787 3.87868 10.875 4.5 10.875C5.12132 10.875 5.625 11.3787 5.625 12C5.625 12.6213 5.12132 13.125 4.5 13.125C3.87868 13.125 3.375 12.6213 3.375 12ZM8.25 12C8.25 11.5858 8.58579 11.25 9 11.25H21C21.4142 11.25 21.75 11.5858 21.75 12C21.75 12.4142 21.4142 12.75 21 12.75H9C8.58579 12.75 8.25 12.4142 8.25 12ZM3.375 17.25C3.375 16.6287 3.87868 16.125 4.5 16.125C5.12132 16.125 5.625 16.6287 5.625 17.25C5.625 17.8713 5.12132 18.375 4.5 18.375C3.87868 18.375 3.375 17.8713 3.375 17.25ZM8.25 17.25C8.25 16.8358 8.58579 16.5 9 16.5H21C21.4142 16.5 21.75 16.8358 21.75 17.25C21.75 17.6642 21.4142 18 21 18H9C8.58579 18 8.25 17.6642 8.25 17.25Z"
fill="none" />
{:else if type === 'cards'}
<rect class={fillClass} fill-rule="evenodd" clip-rule="evenodd" x="2" y="2" width="12" height="12" />
<rect class={fillClass} fill-rule="evenodd" clip-rule="evenodd" x="18" y="2" width="12" height="12" />
<rect class={fillClass} fill-rule="evenodd" clip-rule="evenodd" x="2" y="18" width="12" height="12" />
<rect class={fillClass} fill-rule="evenodd" clip-rule="evenodd" x="18" y="18" width="12" height="12" />
{:else if type === 'magnifier'}
<path
class={fillClass}
fill-rule="evenodd"
clip-rule="evenodd"
d="M19.5151 9.54126C19.5151 6.05828 16.6915 3.23477 13.2086 3.23477C9.72559 3.23477 6.90208 6.05828 6.90208 9.54126C6.90208 11.2829 7.60719 12.8586 8.74921 14.0006C9.89123 15.1426 11.4669 15.8478 13.2086 15.8478C16.6915 15.8478 19.5151 13.0242 19.5151 9.54126ZM13.2086 1.83333C17.4655 1.83333 20.9165 5.28429 20.9165 9.54126C20.9165 13.7982 17.4655 17.2492 13.2086 17.2492C11.3327 17.2492 9.61242 16.5783 8.27618 15.4646L3.89396 19.8468C3.62031 20.1205 3.17664 20.1205 2.90299 19.8468C2.62934 19.5732 2.62934 19.1295 2.90299 18.8559L7.28521 14.4737C6.17148 13.1374 5.50064 11.4172 5.50064 9.54126C5.50064 5.28429 8.9516 1.83333 13.2086 1.83333Z"
fill="none" />
{/if}
</svg>
28 changes: 28 additions & 0 deletions packages/bridge-ui-v2/src/components/Icon/IconFlipper.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
import { Icon, type IconType } from '$components/Icon';
import { classNames } from '$libs/util/classNames';
export let iconType1: IconType;
export let iconType2: IconType;
export let selectedDefault: IconType = iconType1;
const dispatch = createEventDispatcher();
function handleLabelClick() {
selectedDefault = selectedDefault === iconType1 ? iconType2 : iconType1;
dispatch('labelclick');
}
$: isDefault = selectedDefault === iconType1;
$: classes = classNames('swap swap-rotate', $$props.class);
</script>

<div role="button" tabindex="0" class={classes} on:click={handleLabelClick} on:keypress={handleLabelClick}>
<input type="checkbox" class="border-none" bind:checked={isDefault} />
<Icon type={iconType1} class="fill-primary-icon swap-on" width={25} height={25} vHeight={25} vWidth={25} />
<Icon type={iconType2} class="fill-primary-icon swap-off" width={25} height={25} vHeight={25} vWidth={25} />
</div>
1 change: 1 addition & 0 deletions packages/bridge-ui-v2/src/components/Icon/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export { default as BllIcon } from './BLL.svelte';
export { default as EthIcon } from './ETH.svelte';
export { default as HorseIcon } from './HORSE.svelte';
export { default as Icon, type IconType } from './Icon.svelte';
export { default as IconFlipper } from './IconFlipper.svelte';
export { default as TTKOIcon } from './TTKO.svelte';
Loading

1 comment on commit c079223

@vercel
Copy link

@vercel vercel bot commented on c079223 Oct 12, 2023

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

bridge-ui-v2-internal – ./packages/bridge-ui-v2

bridge-ui-v2-internal-taikoxyz.vercel.app
bridge-ui-v2-internal-git-main-taikoxyz.vercel.app
bridge-ui-v2-internal.vercel.app

Please sign in to comment.