Skip to content

Commit

Permalink
Merge pull request #10 from AstarNetwork/feat/parent-page
Browse files Browse the repository at this point in the history
feat: display Parent NFT data on the Parent page
  • Loading branch information
impelcrypto authored Mar 6, 2023
2 parents 3cb6cda + fc2e9cf commit d5c01ee
Show file tree
Hide file tree
Showing 13 changed files with 250 additions and 110 deletions.
12 changes: 3 additions & 9 deletions src/components/assets/AssetList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,7 @@
</div>
</template>
<script lang="ts">
import {
useAccount,
useBreakpoints,
useNft,
chunkyAddress,
partsAddress,
useNetworkInfo,
} from 'src/hooks';
import { useAccount, useBreakpoints, useNft, useNetworkInfo } from 'src/hooks';
import { defineComponent, computed, watchEffect } from 'vue';
import { getShortenAddress } from '@astar-network/astar-sdk-core';
import { IBasePart, ParentInventory } from 'src/modules/nft';
Expand Down Expand Up @@ -115,7 +108,8 @@ export default defineComponent({
// Todo: get from url
const tokenId = 1;
const { parts, unequip, equip, getChildrenToEquipPreview } = useNft(tokenId);
const { parts, unequip, equip, getChildrenToEquipPreview, chunkyAddress, partsAddress } =
useNft(tokenId);
const isSlotEquipped = (part: IBasePart): boolean =>
!!part.metadataUri && !!part.equippable && part.equippable.length > 0;
Expand Down
125 changes: 94 additions & 31 deletions src/components/parent/Inventory.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,45 @@
</div>

<div v-if="selectedTab === InventoryTab.inventory" class="wrapper--items">
<div v-for="(item, index) in dummyList" :key="index" class="card--item">
<div
v-for="[k, v] in acceptableEquipments"
:key="Number(k.u64)"
class="card--item"
@click="navigateToChildFromInventory(Number(k.u64), String(v[0]?.partsAddress))"
>
<div class="box--nft-img">
<img :src="item.img" :alt="item.name" class="img--item" />
</div>
<span class="text--name">{{ item.name }}</span>
</div>
<div class="card--item">
<div class="box--nft-add">
<span class="text--lg">+</span>
<span class="text--name">{{ $t('add') }}</span>
<img :src="v[0]?.gatewayUrl" :alt="String(v[0]?.id)" class="img--item" />
</div>
<span class="text--name">{{ v[0]?.id }}</span>
</div>
</div>
<div v-else class="wrapper--items">
<div v-for="(item, index) in dummyEquippedList" :key="index" class="card--item">
<div class="box--nft-img">
<img :src="item.img" :alt="item.name" class="img--item" />
<div
v-for="(item, index) in equipped"
:key="index"
@click="navigateToChildFromEquipped(Number(item.id))"
>
<div v-if="!isSlot(item) || isSlotEquipped(item)" class="card--item">
<div class="box--nft-img">
<img :src="item.metadataUri" :alt="String(item.id)" class="img--item" />
</div>
<span class="text--name">{{ item.id }}</span>
</div>
<span class="text--name">{{ item.name }}</span>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { defineComponent, ref, PropType, computed, watchEffect } from 'vue';
import ModeTabs from 'src/components/common/ModeTabs.vue';
import { getShortenAddress } from '@astar-network/astar-sdk-core';
import { ExtendedAsset, IBasePart, Id } from 'src/modules/nft';
import { networkParam, Path } from 'src/router/routes';
import { useAccount, useNetworkInfo } from 'src/hooks';
import { providerEndpoints } from 'src/config/chainEndpoints';
import { useRouter, useRoute } from 'vue-router';
import { getContract, getGasLimit } from 'src/modules/nft/common-api';
import { $api } from 'src/boot/api';
enum InventoryTab {
inventory = 'Inventory',
Expand All @@ -45,8 +57,33 @@ enum InventoryTab {
export default defineComponent({
components: { ModeTabs },
props: {
parts: {
type: Object as PropType<IBasePart[]>,
required: true,
},
getChildren: {
type: Function,
required: true,
},
tokenId: {
type: Number,
required: true,
},
},
setup(props) {
const selectedTab = ref<InventoryTab>(InventoryTab.inventory);
const acceptableEquipments = ref<Map<Id, (ExtendedAsset | null)[]>>();
const { currentAccount } = useAccount();
const { currentNetworkIdx } = useNetworkInfo();
const router = useRouter();
const route = useRoute();
const tokenId = route.query.tokenId?.toString() ?? '';
const setAcceptableEquipments = async (): Promise<void> => {
acceptableEquipments.value = await props.getChildren(props.tokenId);
};
const setSelectedTab = (isAttribute: boolean): void => {
if (isAttribute) {
selectedTab.value = InventoryTab.inventory;
Expand All @@ -55,33 +92,59 @@ export default defineComponent({
}
};
const dummyItemA = {
id: 1,
name: 'The Reborn Nebula',
description: 'description',
img: 'https://astar.network/_nuxt/reading-astar.87a786d8.svg',
isValid: true,
};
const isSlotEquipped = (part: IBasePart): boolean =>
!!part.metadataUri && !!part.equippable && part.equippable.length > 0;
const isSlot = (part: IBasePart): boolean => part.partType === 'Slot';
const equipped = computed<IBasePart[]>(() => props.parts.filter((it) => isSlotEquipped(it)));
const dummyItemB = {
id: 555,
name: 'Starmap',
description: 'description',
img: require('../../assets/img/parent-example.svg'),
isValid: true,
const navigateToChildFromEquipped = async (id: number): Promise<void> => {
try {
const mainContractAddress =
String(providerEndpoints[Number(currentNetworkIdx.value)].baseContractAddress![0]) || '';
const contract = await getContract({ api: $api!, address: mainContractAddress });
const { output: equipment } = await contract.query['equippable::getEquipment'](
currentAccount.value,
{
gasLimit: getGasLimit(contract.api),
storageDepositLimit: null,
},
{ u64: tokenId },
id
);
const equipmentString = equipment?.toString() as string;
const childId = Number(JSON.parse(equipmentString).childNft[1].u64);
const childTokenAddress = String(JSON.parse(equipmentString).childNft[0]);
const base = networkParam + Path.Child;
const url = `${base}?tokenId=${childId}&contractAddress=${childTokenAddress}`;
router.push(url);
} catch (error) {
console.error(error);
const fallback = networkParam + Path.Assets;
router.push(fallback);
}
};
const dummyList = [dummyItemA, dummyItemB, dummyItemA, dummyItemB];
const navigateToChildFromInventory = (childId: number, partsAddress: string): void => {
const base = networkParam + Path.Child;
const url = `${base}?tokenId=${childId}&contractAddress=${partsAddress}`;
router.push(url);
};
const dummyEquippedList = [dummyItemB, dummyItemA];
watchEffect(setAcceptableEquipments);
return {
selectedTab,
InventoryTab,
equipped,
acceptableEquipments,
setSelectedTab,
getShortenAddress,
dummyList,
dummyEquippedList,
isSlot,
isSlotEquipped,
navigateToChildFromInventory,
navigateToChildFromEquipped,
};
},
});
Expand Down
53 changes: 40 additions & 13 deletions src/components/parent/Parent.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
<template>
<div class="wrapper--parent">
<div v-if="!isLoading" class="wrapper--parent">
<div class="container--parent">
<img :src="dummyNft.img" alt="nft-logo" class="img--nft-big" />
<div class="image-container--parent">
<img
v-for="(part, index) in p"
:key="`part-${index}`"
class="image--parent"
:src="part.metadataUri"
/>
<div v-if="p.length === 0" class="row--no-images">
<span class="text--lg">No images for token ID: {{ tokenId }}</span>
</div>
</div>

<div class="buttons">
<astar-button :width="130" :height="48">
Expand All @@ -20,7 +30,7 @@

<div class="wrapper-nft-introduction">
<nft-introduction
:id="dummyNft.id"
:id="tokenId"
:collection="dummyNft.collection"
:description="dummyNft.description"
:img="dummyNft.img"
Expand All @@ -35,27 +45,31 @@
:dummy-items="dummyItems"
:dummy-specifics="dummySpecifics"
/>
<inventory />
<inventory
:token-id="Number(tokenId)"
:parts="p"
:get-children="getChildrenToEquipPreview"
/>
</div>
</div>
</div>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue';
// import { useRoute } from 'vue-router';
import { computed, defineComponent, watchEffect } from 'vue';
import { useRoute } from 'vue-router';
import NftIntroduction from 'src/components/common/NftIntroduction.vue';
import Attributes from 'src/components/common/Attributes.vue';
import Inventory from 'src/components/parent/Inventory.vue';
import { useNft } from 'src/hooks';
import { IBasePart } from 'src/modules/nft';
export default defineComponent({
components: { NftIntroduction, Attributes, Inventory },
setup() {
// const route = useRoute();
// const id = computed<string>(() => route.query.id as string);
// watchEffect(() => {
// console.log('id', id);
// });
const route = useRoute();
const tokenId = computed<string>(() => route.query.tokenId as string);
const { parts, isLoading, getChildrenToEquipPreview } = useNft(Number(tokenId.value));
const p = computed<IBasePart[]>(() => parts.value as IBasePart[]);
const reload = (): void => {
window.location.reload();
Expand Down Expand Up @@ -84,7 +98,20 @@ export default defineComponent({
chain: 'ASTAR',
};
return { dummyNft, reload, dummyItems, dummySpecifics };
watchEffect(() => {
console.log('parts', parts.value);
});
return {
dummyNft,
reload,
dummyItems,
dummySpecifics,
isLoading,
p,
tokenId,
getChildrenToEquipPreview,
};
},
});
</script>
Expand Down
10 changes: 10 additions & 0 deletions src/components/parent/styles/inventory.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,19 @@
@media (min-width: $xl) {
column-gap: 20px;
}
:hover {
.img--item {
transition: all 0.3s ease 0s;
border: 2px solid $astar-blue;
box-shadow: 0px 0px 6px #1cb8d2;
}
}
}

.card--item {
display: flex;
flex-direction: column;
justify-content: center;
row-gap: 8px;
width: 120px;
cursor: pointer;
Expand All @@ -50,6 +58,8 @@
max-height: 100px;
border-radius: 8px;
background: $img-background;
transition: all 0.3s ease 0s;
border: 2px solid black;
}

.text--name {
Expand Down
23 changes: 23 additions & 0 deletions src/components/parent/styles/parent.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,29 @@
background: $img-background;
}

.image-container--parent {
position: relative;
height: auto;
width: 358px;
height: 350px;
display: flex;
justify-content: center;
align-items: center;
background: $img-background;
border-radius: 16px;
padding-left: 56px;
}

.row--no-images {
padding-right: 56px;
}

.image--parent {
position: absolute;
max-height: 350px;
width: 100%;
}

.buttons {
display: flex;
column-gap: 16px;
Expand Down
9 changes: 4 additions & 5 deletions src/config/chainEndpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ export interface ChainProvider {
faucetEndpoint: string;
// Memo: using `require` occurs error in `yarn test`
defaultLogo: string;
// Memo: XVM transfer contracts address
xvmErcTransferContract?: string;
baseContractAddress?: string[];
partsAddress?: string;
}

export enum endpointKey {
Expand Down Expand Up @@ -101,7 +101,8 @@ export const providerEndpoints: ChainProvider[] = [
faucetEndpoint: 'https://us-central1-facuet-bot.cloudfunctions.net/app/shibuya',
defaultLogo:
'https://github.com/AstarNetwork/astar-apps/blob/main/src/assets/img/chain/shibuya.png?raw=true',
xvmErcTransferContract: 'ZdNJsZUK96jGxr8iRfT8xHXUi5iQ7XwL9qbyJkADPdH7C1U',
baseContractAddress: ['aEa8Jx4noRvq1gs79yd5THenLuBiqbNFnvWXkNRPj7ADdqp'],
partsAddress: 'XxLjz535ZFcWDb2kn3gBYvNAyiTZvaBrJBmkP5hUnRPSAcE',
},
{
networkAlias: 'development',
Expand All @@ -118,8 +119,6 @@ export const providerEndpoints: ChainProvider[] = [
faucetEndpoint: '',
defaultLogo:
'https://github.com/AstarNetwork/astar-apps/blob/main/src/assets/img/chain/shibuya.png?raw=true',
// Memo: paste the contract addresses after deployed the contracts on the local network
// xvmErcTransferContract: '',
},
{
networkAlias: 'custom-node',
Expand Down
1 change: 1 addition & 0 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export * from './useChainInfo';
export * from './useConnectWallet';
export * from './ui/useBreakpoints';
export * from './ui/useTooltip';
export * from './ui/usePageReady';
export * from './useGasPrice';
export * from './useNetworkInfo';
export * from './useAppRouter';
Expand Down
Loading

0 comments on commit d5c01ee

Please sign in to comment.