Skip to content

Commit

Permalink
basic layout
Browse files Browse the repository at this point in the history
  • Loading branch information
KorbinianK committed Sep 27, 2023
1 parent e56a890 commit 02fac48
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
import { Icon } from '$components/Icon';
import { uid } from '$libs/util/uid';
export let ethereumAddress: Address | string = '';
export let labelText = $t('inputs.address_input.label');
enum State {
Valid = 'valid',
Invalid = 'invalid',
Expand All @@ -18,8 +21,6 @@
let inputId = `input-${uid()}`;
let state: State;
export let ethereumAddress: Address | string = '';
const dispatch = createEventDispatcher();
const validateEthereumAddress = (address: string | EventTarget | null) => {
Expand Down Expand Up @@ -60,7 +61,7 @@

<div class="f-col space-y-2">
<div class="f-between-center text-secondary-content">
<label class="body-regular" for={inputId}>{$t('inputs.address_input.label')}</label>
<label class="body-regular" for={inputId}>{labelText}</label>
</div>
<div class="relative f-items-center">
<input
Expand Down
97 changes: 77 additions & 20 deletions packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { onDestroy } from 'svelte';
import { t } from 'svelte-i18n';
import { TransactionExecutionError, UserRejectedRequestError } from 'viem';
import { type Address, TransactionExecutionError, UserRejectedRequestError } from 'viem';
import { routingContractsMap } from '$bridgeConfig';
import { chainConfig } from '$chainConfig';
Expand Down Expand Up @@ -40,7 +41,9 @@
import { pendingTransactions } from '$stores/pendingTransactions';
import Actions from './Actions.svelte';
import AddressInput from './AddressInput.svelte';
import Amount from './Amount.svelte';
import IdInput from './IDInput.svelte';
import { ProcessingFee } from './ProcessingFee';
import Recipient from './Recipient.svelte';
import {
Expand All @@ -54,7 +57,6 @@
} from './state';
import { BridgeTypes, NFTSteps } from './types';
let activeStep: NFTSteps = NFTSteps.IMPORT;
let amountComponent: Amount;
let recipientComponent: Recipient;
let processingFeeComponent: ProcessingFee;
Expand Down Expand Up @@ -270,13 +272,8 @@
bridgeTxService.addTxByAddress($account.address, bridgeTx);
// Reset the form (we check if these are still mounted, as the user might have left the page)
if (amountComponent) amountComponent.clearAmount();
if (recipientComponent) recipientComponent.clearRecipient();
if (processingFeeComponent) processingFeeComponent.resetProcessingFee();
// Update balance after bridging
if (amountComponent) amountComponent.updateBalance();
// Reset the form
resetForm();
// Refresh user's balance
refreshUserBalance();
Expand Down Expand Up @@ -309,21 +306,54 @@
}
}
$: if ($selectedToken && amountComponent) {
amountComponent.validateAmount();
}
const resetForm = () => {
//we check if these are still mounted, as the user might have left the page
if (amountComponent) amountComponent.clearAmount();
if (recipientComponent) recipientComponent.clearRecipient();
if (processingFeeComponent) processingFeeComponent.resetProcessingFee();
if (addressInputComponent) addressInputComponent.clear();
// Update balance after bridging
if (amountComponent) amountComponent.updateBalance();
};
// NFT Bridge logic
let activeStep: NFTSteps = NFTSteps.IMPORT;
const nextStep = () => (activeStep = Math.min(activeStep + 1, NFTSteps.CONFIRM));
const back = () => (activeStep = Math.max(activeStep - 1, NFTSteps.IMPORT));
const previousStep = () => (activeStep = Math.max(activeStep - 1, NFTSteps.IMPORT));
let nftStepTitle: string;
let nftStepDescription: string;
let nftIdArray: number[] = [];
let invalidAddress = false;
let addressInputComponent: AddressInput;
function onAddressValidation(event: CustomEvent<{ isValidEthereumAddress: boolean; addr: Address }>) {
const { isValidEthereumAddress, addr } = event.detail;
if (isValidEthereumAddress) {
$recipientAddress = addr;
invalidAddress = false;
} else {
invalidAddress = true;
}
}
$: {
const stepKey = NFTSteps[activeStep].toLowerCase(); // Convert enum to string and to lowercase
nftStepTitle = $t(`bridge.title.nft.${stepKey}`);
nftStepDescription = $t(`bridge.description.nft.${stepKey}`);
}
$: if ($selectedToken && amountComponent) {
amountComponent.validateAmount();
}
$: ethereumAddressBinding = $recipientAddress || undefined;
onDestroy(() => {
resetForm();
});
</script>

{#if $activeBridge === BridgeTypes.FUNGIBLE}
Expand Down Expand Up @@ -361,13 +391,40 @@
</Stepper>

<Card class="mt-[32px] w-full md:w-[524px]" title={nftStepTitle} text={nftStepDescription}>
<div class="f-between-center w-full gap-4">
<Button type="primary" class="px-[28px] py-[14px] rounded-full flex-1 text-white" on:click={back}
>Previous Step</Button>
<Button type="primary" class="px-[28px] py-[14px] rounded-full flex-1 text-white" on:click={nextStep}
>Next Step</Button>
</div>
</Card>
<div class="space-y-[30px]">
{#if activeStep === NFTSteps.IMPORT}
<div class="f-between-center gap-4">
<ChainSelectorWrapper />
</div>

<AddressInput
bind:this={addressInputComponent}
bind:ethereumAddress={ethereumAddressBinding}
on:addressvalidation={onAddressValidation}
labelText={$t('bridge.title.nft.address')} />

<IdInput bind:numbersArray={nftIdArray} />
{:else if activeStep === NFTSteps.REVIEW}
<div class="f-between-center gap-4">
<ChainSelectorWrapper />
</div>
{:else if activeStep === NFTSteps.CONFIRM}
<div class="f-between-center gap-4">
<ChainSelectorWrapper />
</div>
{/if}
{nftIdArray}
<div class="h-sep" />
<div class="f-between-center w-full gap-4">
<Button type="primary" class="px-[28px] py-[14px] rounded-full flex-1 text-white" on:click={previousStep}
>Previous Step</Button>
<Button
disabled={invalidAddress}
type="primary"
class="px-[28px] py-[14px] rounded-full flex-1 text-white"
on:click={nextStep}>Next Step</Button>
</div>
</div></Card>
</div>
{/if}

Expand Down
8 changes: 6 additions & 2 deletions packages/bridge-ui-v2/src/components/Bridge/BridgeTabs.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,17 @@
{#if PUBLIC_NFT_BRIDGE_ENABLED === 'true'}
<div class={classes}>
<button
class="{isERC20Bridge ? 'btn-primary' : 'btn-ghost'} px-[28px] py-[14px] rounded-full text-white"
class="{isERC20Bridge
? 'btn-primary text-white'
: 'btn-ghost light:text-black dark:text-white'} h-[44px] px-[28px] py-[14px] rounded-full"
on:click={() => onBridgeClick(BridgeTypes.FUNGIBLE)}>
<span> {$t('nav.token')}</span>
</button>

<button
class="{isNFTBridge ? 'btn-primary' : 'btn-ghost'} h-[44px] px-[28px] py-[14px] rounded-full text-white"
class="{isNFTBridge
? 'btn-primary text-white'
: 'btn-ghost light:text-black dark:text-white'} h-[44px] px-[28px] py-[14px] rounded-full"
on:click={() => onBridgeClick(BridgeTypes.NFT)}>
<span> {$t('nav.nft')}</span>
</button>
Expand Down
73 changes: 73 additions & 0 deletions packages/bridge-ui-v2/src/components/Bridge/IDInput.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
import { t } from 'svelte-i18n';
import { FlatAlert } from '$components/Alert';
import { Icon } from '$components/Icon';
export let numbersArray: number[] = [];
enum State {
Valid,
Invalid,
Neutral,
}
const dispatch = createEventDispatcher();
let inputId = 'numberInput';
let state = State.Neutral;
let value: string = '';
$: {
value = value.replace(/\s+/g, '');
if (value === '' || value.endsWith(',')) {
state = State.Neutral;
numbersArray = [];
} else {
const inputArray = value.split(',');
const isValid = inputArray.every((item) => /^[0-9]+$/.test(item));
state = isValid ? State.Valid : State.Invalid;
numbersArray = isValid ? inputArray.map((num) => parseInt(num)).filter(Boolean) : [];
}
}
function validateInput(e: Event) {
const target = e.target as HTMLInputElement;
value = target.value.replace(/\s+/g, '');
dispatch('input', { value, numbersArray });
}
function clear() {
value = '';
numbersArray = [];
state = State.Neutral;
dispatch('input', { value, numbersArray });
}
</script>

<div class="f-col space-y-2">
<div class="f-between-center text-secondary-content">
<label class="body-regular" for={inputId}>{$t('inputs.nft.token_id.label')}</label>
</div>
<div class="relative f-items-center">
<input
id={inputId}
type="text"
placeholder={$t('inputs.nft.token_id.placeholder')}
bind:value
on:input={validateInput}
class="w-full input-box withValdiation py-6 pr-16 px-[26px] title-subsection-bold placeholder:text-tertiary-content
{state === State.Valid ? 'success' : state === State.Invalid ? 'error' : ''}" />
<button class="absolute right-6 uppercase body-bold text-secondary-content" on:click={clear}>
<Icon type="x-close-circle" fillClass="fill-primary-icon" size={24} />
</button>
</div>
</div>

<div class="mt-5 min-h-[20px]">
{#if state === State.Invalid && value !== ''}
<FlatAlert type="error" forceColumnFlow message={$t('inputs.address_input.errors.invalid')} />
{:else if state === State.Valid}
<FlatAlert type="success" forceColumnFlow message={$t('inputs.address_input.success')} />
{/if}
</div>

0 comments on commit 02fac48

Please sign in to comment.