Skip to content
This repository was archived by the owner on Dec 5, 2025. It is now read-only.

Commit 9c6aacf

Browse files
authored
Merge pull request #11163 from roiLeo/feature/init/swapLanding
✨ swap page landing
2 parents 40fe6f3 + ee70ff5 commit 9c6aacf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1453
-121
lines changed

assets/svg/swap/arrow-down.svg

Lines changed: 19 additions & 0 deletions
Loading

assets/svg/swap/arrow-up.svg

Lines changed: 19 additions & 0 deletions
Loading

assets/svg/swap/arrows.svg

Lines changed: 19 additions & 0 deletions
Loading

components/collection/utils/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ export type CollectionEntityMinimal = {
1818
name: string
1919
currentOwner: string
2020
type: string
21+
ownerCount?: number
2122
}

components/common/ChainDropdown.vue

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
<template #trigger="{ active }">
55
<NeoButton
66
class="chain-dropdown-text"
7+
:variant
78
:label="
89
isMobile || !showNetworkLabel
9-
? selected?.text
10+
? label || selected?.text
1011
: `Network: ${selected?.text}`
1112
"
1213
:icon="active ? 'chevron-up' : 'chevron-down'"
@@ -27,28 +28,32 @@
2728
</template>
2829

2930
<script setup lang="ts">
30-
import { NeoButton, NeoDropdown, NeoDropdownItem } from '@kodadot1/brick'
31+
import { NeoButton, NeoDropdown, NeoDropdownItem, type NeoButtonVariant } from '@kodadot1/brick'
3132
import { type Prefix } from '@kodadot1/static'
3233
3334
const props = withDefaults(
3435
defineProps<{
3536
showNetworkLabel: boolean
3637
position?: 'bottom-auto'
3738
redirect?: boolean
38-
exclude: Prefix[]
39+
exclude?: Prefix[]
40+
variant?: NeoButtonVariant
41+
label?: string
42+
filterByVm?: boolean
3943
}>(),
4044
{
4145
showNetworkLabel: true,
4246
position: undefined,
4347
redirect: true,
4448
mobileModal: false,
4549
exclude: () => [],
50+
filterByVm: false,
4651
},
4752
)
4853
4954
const route = useReactiveRoute()
5055
const { setUrlPrefix, urlPrefix } = usePrefix()
51-
const { availableChains: allChains } = useChain()
56+
const { availableChains: allChains, availableChainsByVm: allChainInVm } = useChain()
5257
const { redirectAfterChainChange } = useChainRedirect()
5358
const { isMobile } = useViewport()
5459
@@ -58,11 +63,10 @@ const selected = computed(() =>
5863
allChains.value.find(chain => chain.value === prefix.value),
5964
)
6065
61-
const availableChains = computed(() =>
62-
allChains.value.filter(
63-
chain => !props.exclude.includes(chain.value as Prefix),
64-
),
65-
)
66+
const availableChains = computed(() => {
67+
return (props.filterByVm ? allChainInVm.value : allChains.value)
68+
.filter(chain => !props.exclude.includes(chain.value as Prefix))
69+
})
6670
6771
function onSwitchChain(chain) {
6872
setUrlPrefix(chain)

components/common/listingCart/shared/ListingCartPriceInput.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
>
77
<input
88
v-model="model"
9+
:disabled="disabled"
910
type="number"
1011
step="0.01"
1112
min="0.001"
1213
pattern="[0-9]+([\.,][0-9]+)?"
1314
class="indent-2.5 border-none outline-none w-20 bg-background-color text-text-color"
14-
:placeholder="$t('price')"
15+
:placeholder="placeholder || $t('price')"
1516
>
1617
<div class="px-3 flex items-center">
1718
{{ chainSymbol }}
@@ -35,6 +36,8 @@ const props = defineProps<{
3536
modelValue?: number | string
3637
check?: boolean
3738
fullWidth?: boolean
39+
disabled?: boolean
40+
placeholder?: string
3841
}>()
3942
const emit = defineEmits(['confirm', 'update:modelValue'])
4043

components/items/ItemsGrid/ItemsGridImage.vue

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
:class="{
1414
'in-cart-border':
1515
shoppingCartStore.isItemInCart(nft.id)
16-
|| listingCartStore.isItemInCart(nft.id),
16+
|| listingCartStore.isItemInCart(nft.id)
17+
|| isAtomicSwapItemSelected
18+
,
1719
}"
1820
:show-action-on-hover="!showActionSection"
1921
:link="NuxtLink"
@@ -26,7 +28,7 @@
2628
#action
2729
>
2830
<div
29-
v-if="!isOwner && Number(nft?.price)"
31+
v-if="!isOwner && Number(nft?.price) && !showAtomicSwapAction"
3032
class="flex"
3133
>
3234
<NeoButton
@@ -56,15 +58,15 @@
5658
</NeoButton>
5759
</div>
5860
<div
59-
v-else-if="isOwner && !hideListing"
61+
v-else-if="showSelect"
6062
class="flex"
6163
>
6264
<NeoButton
63-
:label="listLabel"
65+
:label="selectLabel"
6466
data-testid="item-buy"
6567
no-shadow
6668
class="flex-grow"
67-
@click.prevent="onClickListingCart"
69+
@click.prevent="onSelect"
6870
/>
6971
</div>
7072
</template>
@@ -80,6 +82,7 @@
8082
// PLEASE FIX bind-key href => to
8183
import { resolveComponent } from 'vue'
8284
import { NeoButton, NeoIcon } from '@kodadot1/brick'
85+
import useAtomicSwapAction from './useAtomicSwapAction'
8386
import type { NftCardVariant } from '@/components/shared/nftCard/types'
8487
import type { NFTWithMetadata } from '@/composables/useNft'
8588
import { useShoppingCartStore } from '@/stores/shoppingCart'
@@ -111,6 +114,12 @@ const props = defineProps<{
111114
skeletonVariant: string
112115
}>()
113116
117+
const {
118+
onAtomicSwapSelect,
119+
showAtomicSwapAction,
120+
isItemSelected: isAtomicSwapItemSelected,
121+
} = useAtomicSwapAction(props.nft)
122+
114123
const showActionSection = computed(() => {
115124
return !isLogIn.value && shoppingCartStore.getItemToBuy?.id === props.nft.id
116125
})
@@ -125,8 +134,6 @@ const buyLabel = computed(function () {
125134
)
126135
})
127136
128-
const listLabel = computed(() => listingCartStore.isItemInCart(props.nft.id) ? $i18n.t('remove') : $i18n.t('select'))
129-
130137
const isOwner = computed(() => isCurrentOwner(props.nft?.currentOwner))
131138
132139
const openCompletePurcahseModal = () => {
@@ -155,8 +162,29 @@ const onClickShoppingCart = () => {
155162
shoppingCartStore.setItem(nftToShoppingCartItem(props.nft))
156163
}
157164
}
158-
const onClickListingCart = () => {
159-
listNftByNftWithMetadata(props.nft, { toggle: true })
165+
166+
const onClickListingCart = () => listNftByNftWithMetadata(props.nft, { toggle: true })
167+
168+
const selectLabel = computed(() => {
169+
const selected = showAtomicSwapAction.value ? isAtomicSwapItemSelected.value : listingCartStore.isItemInCart(props.nft.id)
170+
return selected ? $i18n.t('remove') : $i18n.t('select')
171+
})
172+
173+
const showSelect = computed(() => {
174+
if (showAtomicSwapAction.value) {
175+
return true
176+
}
177+
178+
return isOwner.value && !props.hideListing
179+
})
180+
181+
const onSelect = () => {
182+
if (showAtomicSwapAction.value) {
183+
onAtomicSwapSelect()
184+
}
185+
else {
186+
onClickListingCart()
187+
}
160188
}
161189
</script>
162190

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import type { NFTWithMetadata } from '@/composables/useNft'
2+
import { SwapStep } from '@/components/swap/types'
3+
4+
export default (nft: NFTWithMetadata) => {
5+
const route = useRoute()
6+
const swapStore = useAtomicSwapStore()
7+
const { swap, step, stepItems } = storeToRefs(swapStore)
8+
9+
const routeName = computed(() => route.name?.toString() as string)
10+
11+
const showAtomicSwapAction = computed(() => ATOMIC_SWAP_PAGES.includes(routeName.value))
12+
13+
const isItemSelected = computed(() => {
14+
return step.value === SwapStep.REVIEW
15+
? false
16+
: [...swap.value.desired, ...swap.value.offered].flat().some(item => item.id === nft.id)
17+
})
18+
19+
const onAtomicSwapSelect = () => {
20+
if (isItemSelected.value) {
21+
swapStore.removeStepItem(nft.id)
22+
}
23+
else {
24+
swapStore.updateStepItems([
25+
...stepItems.value,
26+
{
27+
id: nft.id,
28+
collectionId: nft.collection.id,
29+
sn: nft.sn,
30+
name: nft.name,
31+
meta: nft.meta,
32+
},
33+
])
34+
}
35+
}
36+
37+
return {
38+
onAtomicSwapSelect,
39+
showAtomicSwapAction,
40+
isItemSelected,
41+
}
42+
}

components/items/ItemsGrid/useItemsGrid.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const EXCLUDED_TOKEN_USE_PAGES = [
2525
'prefix-collection-id',
2626
'prefix-drops-id',
2727
'prefix-u-id',
28+
...ATOMIC_SWAP_PAGES,
2829
]
2930

3031
export function useFetchSearch({

components/items/ItemsGrid/useNftActions.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import nftById from '@/queries/subsquid/general/nftById.graphql'
2-
import listCount from '@/queries/subsquid/general/countOfTokenNftsToList.graphql'
32
import nftListWithSearch from '@/queries/subsquid/ahk/nftListWithSearch.graphql'
43
import type { TokenId } from '@/types'
54

@@ -120,19 +119,15 @@ export const getTokensNfts = async (
120119
}
121120

122121
export const checkIfAnythingToList = async (entities: TokenEntity[]) => {
123-
const { client, urlPrefix } = usePrefix()
124122
const { accountId } = useAuth()
125-
const { data } = await useAsyncQuery<{ count: { totalCount: number } }>({
126-
query: listCount,
127-
variables: {
128-
token: entities.map(({ id }) => id),
129-
owner: accountId.value,
130-
denyList: getDenyList(urlPrefix.value),
131-
},
132-
clientId: client.value,
123+
124+
const count = await getNftCount({
125+
token: { id_in: entities.map(n => n.id) },
126+
currentOwner_eq: accountId.value,
127+
price_eq: 0,
133128
})
134129

135-
return data.value.count.totalCount > 0
130+
return count > 0
136131
}
137132

138133
export function useNftActions(entity: TokenEntity) {

0 commit comments

Comments
 (0)