diff --git a/pages/ad-marketplace/index.tsx b/pages/ad-marketplace/index.tsx index 42dd3b58..9f31d653 100644 --- a/pages/ad-marketplace/index.tsx +++ b/pages/ad-marketplace/index.tsx @@ -1,14 +1,17 @@ +import React, { useCallback, useEffect, useState } from "react"; + import Header from "../../src/components/Header/header"; import { useConnectModal } from "@rainbow-me/rainbowkit"; // antd imports import { DownOutlined } from "@ant-design/icons"; import { Dropdown, Menu, Space, Radio, Typography } from "antd"; +const {Title} = Typography; import type { RadioChangeEvent } from "antd"; import { useQuery } from "@apollo/client"; import { AdvNFTAddr, MarketPlaceAddr } from "../../src/env"; -import React, { useState } from "react"; import { AdvNftMetaData } from "../../src/types/AdvNFTData"; + // custom-component imports import AdModal from "../../src/components/AdModal/AdModal"; import { useSigner } from "wagmi"; @@ -29,14 +32,16 @@ import { MusicPlayerSub } from "../../src/subs/MusicPlayerSub"; const client = new NFTStorage({ token: process.env.NEXT_PUBLIC_NFT_STORAGE_TOKEN ?? "", }); -const { Title } = Typography; + const AdMarketPlace: React.FC = () => { + const { data: signer } = useSigner(); const [selectedAdv, setSelectedAdv] = useState(); const [showModal, setShowModal] = useState(false); const [isCreatingAd, setIsCreatingAd] = useState(false); + const handleAdModal = () => { setShowModal(!showModal); }; @@ -73,7 +78,6 @@ const AdMarketPlace: React.FC = () => { if (!selectedAdv?.token.id) { throw new Error("Failed to get selected adv id"); - return; } console.log("handleAdForm: Creating Market Sale"); @@ -106,9 +110,9 @@ const AdMarketPlace: React.FC = () => { const handleRentClick = (advNft: GetUnsold_marketItems) => { setSelectedAdv(advNft); - setShowModal(true); }; + return ( <>
@@ -127,6 +131,7 @@ const AdMarketPlace: React.FC = () => { ); }; + interface AdlistProp { onHandleModal: () => void; onRentClick: (advNft: GetUnsold_marketItems) => void; diff --git a/pages/profile.tsx b/pages/profile.tsx new file mode 100644 index 00000000..3608bb34 --- /dev/null +++ b/pages/profile.tsx @@ -0,0 +1,46 @@ + +import type { NextPage } from "next"; +import Header from "../src/components/Header/header"; +import {Tabs} from 'antd' + +// component imports +import MusicTab from "../src/components/ProfilePage/MusicTab/MusicTab"; +import AdvertisementTab from "../src/components/ProfilePage/AdvertisementTab/AdvertismentTab"; + + + +const Profile: NextPage = () => { + + + return ( +
+
+
+ + + + + + + + + Subscription + + +
+
+ ); +}; + +export default Profile; + + +const Advertisment: React.FC = () =>{ + console.log('render advertisement') + return( +
+ Advertisement Content tab +
+ ) +} + diff --git a/src/components/AdModal/AdModalForm/AdModalForm.types.ts b/src/components/AdModal/AdModalForm/AdModalForm.types.ts index a5a0b7b3..406a1890 100644 --- a/src/components/AdModal/AdModalForm/AdModalForm.types.ts +++ b/src/components/AdModal/AdModalForm/AdModalForm.types.ts @@ -1,12 +1,18 @@ +<<<<<<< HEAD +type AdModalFormValues = { + bannerImage: File[]; +======= import { UploadFile } from "antd"; export type AdModalFormValues = { bannerImage: UploadFile[]; adUrl: string; +>>>>>>> main }; + interface AdModalFormProps { onHandleAdForm: (values: AdModalFormValues) => void; isCreatingAd: boolean; } -export type { AdModalFormProps } \ No newline at end of file +export type { AdModalFormProps, AdModalFormValues} \ No newline at end of file diff --git a/src/components/Header/header.tsx b/src/components/Header/header.tsx index 56d79821..a90c4447 100644 --- a/src/components/Header/header.tsx +++ b/src/components/Header/header.tsx @@ -20,6 +20,10 @@ function Header() { router.push("/"); }; + const navigateProfilePage = () => { + router.push("/profile"); + }; + let correctNetwork; if (chain?.network === "tevmos" || !isConnected) { @@ -63,6 +67,15 @@ function Header() { Ad Marketplace + + + diff --git a/src/components/MarketPlacePage/Adlist/Adlist.tsx b/src/components/MarketPlacePage/Adlist/Adlist.tsx new file mode 100644 index 00000000..74d1c1c4 --- /dev/null +++ b/src/components/MarketPlacePage/Adlist/Adlist.tsx @@ -0,0 +1,115 @@ +import {useEffect,useState} from 'react' + +// proptype imports +import {AdlistProp} from './Adlist.types' + +// wagmi & rainbowkit imports +import { useConnectModal } from '@rainbow-me/rainbowkit'; +import { useAccount } from 'wagmi'; + +// antd imports +import {Button, List, Typography} from 'antd' +const {Title, Text} = Typography; + +// utility imports +import { fetchIpfs } from '../../../services/ipfs/fetchIpfs'; + +// graphql imports +import { useQuery } from '@apollo/client'; +import { GetAllAsks, GetAllAsks_asks } from '../../../graph-ql/queries/GET_ALL_ASKS/__generated__/GetAllAsks'; +import { AdvNFTAddr } from '../../../env'; +import { GET_ALL_ASKS } from '../../../graph-ql/queries/GET_ALL_ASKS/getAllAsks'; + +// types imports +import { AdvNftMetaData } from '../../../types/AdvNFTData'; + + +const Adlist: React.FC = ({ onRentClick }) => { + + const { openConnectModal } = useConnectModal(); + const { isConnected } = useAccount() + + const { + loading: isLoadingAllAsks, + data: allAsksConnection, + error: allAskError, + } = useQuery(GET_ALL_ASKS, { + variables: { + nftContractAddr: AdvNFTAddr.toLowerCase(), + }, + }); + + return ( + <> + + { + return ( + onRentClick(item) : openConnectModal}>Rent Ad Space + } + > + } + description="TODO: fetch desc from ipfs" + /> + + ); + }} + /> + + ); + }; + + interface TitleProps { + item: GetAllAsks_asks; + } + + const TitleNode: React.FC = ({ item }) => { + const [metaData, setMetaData] = useState(); + + console.log(metaData) + + const fetchMetaData = async () => { + const advMetaData = await fetchIpfs( + item.token.metaDataHash + ); + console.log(advMetaData) + setMetaData(advMetaData); + }; + + useEffect(() => { + fetchMetaData(); + }, [item]); + + return ( +
+ + {metaData?.name} + + + {item.token.id} + +
+ ); + }; + + + export default Adlist \ No newline at end of file diff --git a/src/components/MarketPlacePage/Adlist/Adlist.types.ts b/src/components/MarketPlacePage/Adlist/Adlist.types.ts new file mode 100644 index 00000000..71f153d3 --- /dev/null +++ b/src/components/MarketPlacePage/Adlist/Adlist.types.ts @@ -0,0 +1,10 @@ +import { + GetAllAsks_asks, +} from "../../../graph-ql/queries/GET_ALL_ASKS/__generated__/GetAllAsks"; + +interface AdlistProp { + onHandleModal: () => void; + onRentClick: (advNft: GetAllAsks_asks) => void; +} + +export type {AdlistProp} \ No newline at end of file diff --git a/src/components/MintSong/MintSongModal/MintForm/MintForm.types.ts b/src/components/MintSong/MintSongModal/MintForm/MintForm.types.ts index 520b6289..c6631b78 100644 --- a/src/components/MintSong/MintSongModal/MintForm/MintForm.types.ts +++ b/src/components/MintSong/MintSongModal/MintForm/MintForm.types.ts @@ -1,5 +1,5 @@ import { UploadFile } from "antd" -export type MintMusicWAdFormValues = { +type MintMusicWAdFormValues = { songName: string; artistName: string; adDurationDays: number; @@ -13,4 +13,4 @@ interface FormProps { isMinting: boolean; } -export type { FormProps } \ No newline at end of file +export type { FormProps, MintMusicWAdFormValues } \ No newline at end of file diff --git a/src/components/MintSong/MintSongModal/MintSongModal.types.ts b/src/components/MintSong/MintSongModal/MintSongModal.types.ts index 8d0d3306..f2d69890 100644 --- a/src/components/MintSong/MintSongModal/MintSongModal.types.ts +++ b/src/components/MintSong/MintSongModal/MintSongModal.types.ts @@ -1,8 +1,8 @@ -import { MintMusicWAdFormValues } from "./MintForm/MintForm.types"; +import { MintMusicAdFormValues } from "./MintForm/MintForm.types"; interface ModalProps { onHandleModal: () => void; - onHandleMintForm: (value: MintMusicWAdFormValues) => void; + onHandleMintForm: (value: MintMusicAdFormValues) => void; isVisible: boolean; isMinting: boolean; } diff --git a/src/components/ProfilePage/AdvertisementTab/AdvertismentTab.tsx b/src/components/ProfilePage/AdvertisementTab/AdvertismentTab.tsx new file mode 100644 index 00000000..bb07b668 --- /dev/null +++ b/src/components/ProfilePage/AdvertisementTab/AdvertismentTab.tsx @@ -0,0 +1,142 @@ +import {useState} from 'react'; + +// antd imports +import {List,Typography,Button} from 'antd' +const {Title} = Typography; + +import {useQuery} from '@apollo/client' + +// wagmi imports +import { useAccount, useSigner } from 'wagmi'; + +// contract imports +import { AdvNFT__factory, MarketPlace__factory } from '../../../contracts'; +import { AdvNFTAddr, MarketPlaceAddr } from '../../../env'; + +// custom-components imports +import ListItem from '../../Shared/ListItem/ListItem'; +// import MusicListItem from './MusicListItem'; + + +import { GET_ADVERTISER_ADS } from '../../../graph-ql/queries/GET_ALL_ADS/getAllAds'; +import { GetAdvertiserAds } from '../../../graph-ql/queries/GET_ALL_ADS/__generated__/GetAdvertiserAds'; +import { asyncStore } from '../../../services/ipfs/nftstorage'; +import { NFTStorage } from 'nft.storage'; +import { AdvNftMetaData } from '../../../types/AdvNFTData'; + + +// create client instance for nft.storage +const client = new NFTStorage({ + token: process.env.NEXT_PUBLIC_NFT_STORAGE_TOKEN ?? "", +}); + +const AdvertisementTab: React.FC = () =>{ + +// query for data +// pass data to components +// fetchMetadata uri's for ad music +// replace image with new + + +const {address} = useAccount() +const {data:signer} = useSigner() +const [isBurningAd,setIsBurningAd] = useState(false) +const [isReplacingAd,setIsReplacingAd] = useState(false) +const [selectedAd, setSelectedAd] = useState({}) + +const { + loading: isLoading, + data: allAds, + error: error, + } = useQuery(GET_ADVERTISER_ADS,{ + variables: { + advertiserAddress: address?.toLowerCase(), + }, + }); + + const burnAdHandler = async() =>{ + const adNftContract = AdvNFT__factory.connect(AdvNFTAddr,signer); + try{ + setIsBurningAd(true) + const res = await adNftContract.burn(selectedAd.tokenId) + setIsBurningAd(false) + }catch(err:any){ + console.log(err) + setIsBurningAd(false) + throw new Error('Error while buring Ads',err) + } + } + + + const replaceAdHandler = async(formData:any)=>{ + + formData.bannerImage[0].originFileObj + + const { hash: adImageHash, storePromise: storeAdImagePromise } = + await asyncStore(client, formData.bannerImage[0].originFileObj); + + const advNftDataObj: AdvNftMetaData = { + description: `Adv nft for NFT`, + mimeType: "image/jpeg", + name: `${selectedAd?.token.id} ADV NFT`, + version: "", + external_url: formData.adUrl, + }; + + const { hash: metaDataHash, storePromise: storeMetaDataPromise } = + await asyncStore(client, new Blob([JSON.stringify(advNftDataObj)])); + + const adNftContract = AdvNFT__factory.connect(AdvNFTAddr, signer); + const marketPlaceContract = MarketPlace__factory.connect(MarketPlaceAddr, signer); + + + try{ + setIsReplacingAd(true); + + console.log("handleAdForm: Creating Market Sale"); + + await marketPlaceContract + .createMarketSale(AdvNFTAddr, selectedAd?.token.id, { + value: selectedAd?.price, + }) + .then((e) => e.wait()); + // invoke contract func and mint song nft with ad nft + + console.log("handleAdForm: Updating adv banner"); + const updateHashPromise = adNftContract + .updateHash(selectedAd?.token.id, metaDataHash, adImageHash) + .then((e) => e.wait()); + + await Promise.all([ + updateHashPromise, + storeAdImagePromise, + storeMetaDataPromise, + ]); + + setIsReplacingAd(false) + }catch(err:any){ + console.log(err) + setIsReplacingAd(false) + throw new Error('Error while replacing Ads',err) + } + } + + console.log(allAds) + + return ( + <> + + + ) +} + +export default AdvertisementTab + + + + + + + + + diff --git a/src/components/ProfilePage/MusicTab/MusicListItem.tsx b/src/components/ProfilePage/MusicTab/MusicListItem.tsx new file mode 100644 index 00000000..67f393fa --- /dev/null +++ b/src/components/ProfilePage/MusicTab/MusicListItem.tsx @@ -0,0 +1,49 @@ + +// antd imports +import {List,Typography} from 'antd'; +const {Text,Title} = Typography; + +// hooks imports +import { useMusicMetadata } from '../../../hooks/useMetadata/useMetadata'; + +// types imports +import { GetUserUnsold_marketItems } from '../../../graph-ql/queries/GET_UNSOLD/__generated__/GetUserUnsold'; +import { ReactNode } from 'react'; +import { useMarketMetadata } from '../../../hooks/useMetadata/useMarketMetadata'; + + +interface ListItemProps{ + item: GetUserUnsold_marketItems + extra: ReactNode +} + +const MusicListItem: React.FC = ({item,extra=null})=>{ + + const music = useMarketMetadata(item); + let isAd = false; + +if(item.token.assetHash!== ""){ + isAd=true; +} +const descriptionNode = ( + <> + {`${Number(item?.token.expirationDuration)/86400} Days Left`} +
+ {isAd?Adspace has 1 AD:null} + +) + + return ( + + {music?.body.title}} + description={descriptionNode} + /> + {/* */} + + ) +} + +export default MusicListItem \ No newline at end of file diff --git a/src/components/ProfilePage/MusicTab/MusicTab.tsx b/src/components/ProfilePage/MusicTab/MusicTab.tsx new file mode 100644 index 00000000..3876d6e3 --- /dev/null +++ b/src/components/ProfilePage/MusicTab/MusicTab.tsx @@ -0,0 +1,191 @@ +import {useState} from 'react'; + +// antd imports +import {List,Typography,Button} from 'antd' +const {Title} = Typography; + +// apollo imports +import {useQuery} from '@apollo/client'; + +// wagmi imports +import { useAccount, useSigner } from 'wagmi'; + +// contract imports +import { MarketPlace__factory } from '../../../contracts'; +import { MarketPlaceAddr } from '../../../env'; + +// custom-components imports +import MusicListItem from './MusicListItem'; + +// custom-hooks imports +import useFetchExpiredAds from '../hooks/useFetchExpiredAds'; +import useFetchUserMusic from '../hooks/useFetchUserMusic'; +import { GET_USER_UNLISTED_ADS } from '../../../graph-ql/queries/GET_UNSOLD/getUnsold'; +import { GetUserUnlisted } from '../../../graph-ql/queries/GET_UNSOLD/__generated__/GetUserUnlisted'; + + + +const MusicTab: React.FC = () =>{ + + const [expired,setExpired] = useState([]) + + const moveToExpired=(item)=>{ + console.log(item) + const copyState = expired.slice() + copyState.push(item); + setExpired(copyState) + } + + return ( + <> + + + + + ) +} + +export default MusicTab + + + + + + +const ListedCategory: React.FC= ()=>{ + + const {music,isLoading,error} = useFetchUserMusic() + const [isRemovingSale, setIsRemovingSale] = useState(false) + + const {data:signer} = useSigner() + + const removeAdSpace= async(item)=>{ + + // call add removing service here. + const market = MarketPlace__factory.connect(MarketPlaceAddr, signer) + try{ + setIsRemovingSale(true) + const res = await market.removeFromSale(item.itemId); + setIsRemovingSale(false) + console.log(res) + }catch(err){ + console.log(err) + setIsRemovingSale(false) + } + + } + + // TODO: Create error-boundary to catch error when thrown + if(error){ + throw new Error('Problem caught while fetching music Category') + } + + return( +
+ Listed + + removeAdSpace(item)}>{`${item.sold?'Unlist(Ad-exists)':'Unlist'}`}} item={item}/> }/> +
+ ) +} + + +// UNLISTED CATEGORY +const UnListedCategory: React.FC = ()=>{ + +const {data:signer} = useSigner() +const [isRemovingSale, setIsRemovingSale] = useState(false) + + +const {address} = useAccount() + +const { + loading: isLoading, + data: allAsk, + error: error, + } = useQuery(GET_USER_UNLISTED_ADS,{ + variables: { + sellerAddress:address?.toLowerCase() + }, + }); + + const music = allAsk?.marketItems + + + + const renewAdSpace = async(item)=>{ + + + + + // call add removing service here. + console.log(item) + const market = MarketPlace__factory.connect(MarketPlaceAddr, signer) + try{ + const res = await market.createMarketItem(MarketPlaceAddr,item.itemId, item.price); + console.log(res) + }catch(err){ + console.log(err) + } + } +// TODO: Create error-boundary to catch error when thrown +if(error){ + throw new Error('Problem caught while fetching music Category') +} + +return( +
+ Un-Listed + + renewAdSpace(item)}>List} item={item}/> }/> +
+) +} + + + + +interface ExpiredProps{ + dataSource: Array +} + +const ExpiredCategory: React.FC = ({dataSource})=>{ + + const {ads,isLoading,error} = useFetchExpiredAds() + console.log(ads) + + // TODO: Create error-boundary to catch error when thrown + if(error){ + throw new Error('Problem caught while fetching expired ads') + } + + + return( +
+ Expired + De-List} item={item}/> + }/> + +
+ ) +} + + + + + diff --git a/src/components/ProfilePage/hooks/useFetchExpiredAds.tsx b/src/components/ProfilePage/hooks/useFetchExpiredAds.tsx new file mode 100644 index 00000000..fe4c5603 --- /dev/null +++ b/src/components/ProfilePage/hooks/useFetchExpiredAds.tsx @@ -0,0 +1,28 @@ +import { useAccount } from "wagmi"; +import {useQuery} from '@apollo/client' +import { GetUserExpiredAdspaces } from "../../../graph-ql/queries/GET_ALL_ADS/__generated__/GetUserExpiredAdspaces"; +import { GET_USER_EXPIRED_ADSPACES } from "../../../graph-ql/queries/GET_ALL_ADS/getAllAds"; + + const useFetchExpiredAds = () =>{ + + const {address} = useAccount() + + const { + loading: isLoading, + data: allAds, + error: error, + } = useQuery(GET_USER_EXPIRED_ADSPACES,{ + variables: { + userAddress:address?.toLowerCase(), + expirationTime: 0 + }, + }); + + const ads = allAds?.advNFTs + + return {ads,isLoading,error} + } + + + export default useFetchExpiredAds + diff --git a/src/components/ProfilePage/hooks/useFetchUserMusic.tsx b/src/components/ProfilePage/hooks/useFetchUserMusic.tsx new file mode 100644 index 00000000..d582c448 --- /dev/null +++ b/src/components/ProfilePage/hooks/useFetchUserMusic.tsx @@ -0,0 +1,28 @@ +import { useAccount } from "wagmi"; +import {useQuery} from '@apollo/client' + +import { GET_USER_UNSOLD } from "../../../graph-ql/queries/GET_UNSOLD/getUnsold"; +import { GetUserUnsold } from "../../../graph-ql/queries/GET_UNSOLD/__generated__/GetUserUnsold"; + + const useFetchUserMusic = () =>{ + + const {address} = useAccount() + + const { + loading: isLoading, + data: allAsk, + error: error, + } = useQuery(GET_USER_UNSOLD,{ + variables: { + sellerAddress:address?.toLowerCase() + }, + }); + + const music = allAsk?.marketItems + + return {music,isLoading,error} + } + + + export default useFetchUserMusic + diff --git a/src/components/Shared/ExpiredMusicItem/ExpiredMusicItem.tsx b/src/components/Shared/ExpiredMusicItem/ExpiredMusicItem.tsx new file mode 100644 index 00000000..3c9d8472 --- /dev/null +++ b/src/components/Shared/ExpiredMusicItem/ExpiredMusicItem.tsx @@ -0,0 +1,35 @@ + +// antd imports +import {List,Typography} from 'antd'; +const {Text,Title} = Typography; + +// hooks imports +import { useMusicMetadata } from '../../../hooks/useMetadata/useMetadata'; + +// types imports +import { GetUserExpiredAdspaces_advNFTs, } from '../../../graph-ql/queries/GET_ALL_ADS/__generated__/GetUserExpiredAdspaces'; +import { ReactNode } from 'react'; + +interface ListItemProps{ + item: GetUserExpiredAdspaces_advNFTs + extra: ReactNode +} + +const ExpiredMusicItem: React.FC = ({item,extra=null})=>{ + + // const music = useMusicMetadata(item); + console.log(item) + + return ( + + {music?.body.title}} + // description={ {`${Number(item?.advNfts[0].expirationDuration)/86400} Days Left`} } + /> + + ) +} + +export default ExpiredMusicItem \ No newline at end of file diff --git a/src/components/Shared/ListItem/ListItem.tsx b/src/components/Shared/ListItem/ListItem.tsx new file mode 100644 index 00000000..2a8eeaf8 --- /dev/null +++ b/src/components/Shared/ListItem/ListItem.tsx @@ -0,0 +1,36 @@ + +// antd imports +import {List,Typography} from 'antd'; +const {Text,Title} = Typography; + +// hooks imports +import { useMusicMetadata } from '../../../hooks/useMetadata/useMetadata'; + +// types imports +import { GetUserListedMusic_musicNFTs, } from '../../../graph-ql/queries/GET_ALL_MUSIC/__generated__/GetUserListedMusic'; +import { ReactNode } from 'react'; + +interface ListItemProps{ + item: GetUserListedMusic_musicNFTs + extra: ReactNode +} + +const ListItem: React.FC = ({item,extra=null})=>{ + + console.log('music data',item); + const music = useMusicMetadata(item); + + return ( + + {music?.body.title}} + description={ {`${Number(item?.advNfts[0].expirationDuration)/86400} Days Left`} } + /> + {/* */} + + ) +} + +export default ListItem \ No newline at end of file diff --git a/src/components/SongList/ListItemNodes.tsx b/src/components/SongList/ListItemNodes.tsx new file mode 100644 index 00000000..d2dcb2f7 --- /dev/null +++ b/src/components/SongList/ListItemNodes.tsx @@ -0,0 +1,61 @@ +import { useState, useEffect, useCallback } from "react"; +// antd imports +import { Typography, Button } from "antd"; +const { Title } = Typography; + +//utils +import { MusicNftMetaData } from "../../types/MusicNFTData"; +import { fetchIpfs } from "../../services/ipfs/fetchIpfs"; +import { GetAllMusic_musicNFTs } from "../../graph-ql/queries/GET_ALL_MUSIC/__generated__/GetAllMusic"; + +interface TitleProps { + musicItem: GetAllMusic_musicNFTs; +} +const TitleNode: React.FC = ({ musicItem }) => { + const [metadata, setMetaData] = useState(); + + const fetchMetaData = useCallback(async () => { + const musicMetaData = await fetchIpfs( + musicItem.metaDataUri + ); + setMetaData(musicMetaData); + }, [musicItem]); + useEffect(() => { + fetchMetaData(); + }, [fetchMetaData]); + + return ( +
+ + {metadata?.body.title} + + + {`${musicItem.owner.id.substring( + 0, + 4 + )}...${musicItem.owner.id.substring(musicItem.owner.id.length - 4)}`} + +
+ ); +}; + +interface SongNodeProps { + playSong: (musicNft: GetAllMusic_musicNFTs) => void; + musicItem: GetAllMusic_musicNFTs; +} + +const SongNode: React.FC = ({ musicItem, playSong }) => { + return ( + + ); +}; + +export { TitleNode, SongNode }; diff --git a/src/components/SongList/SongList.tsx b/src/components/SongList/SongList.tsx index a9aa2568..38e86c0b 100644 --- a/src/components/SongList/SongList.tsx +++ b/src/components/SongList/SongList.tsx @@ -6,15 +6,24 @@ import { GetAllMusic } from "../../graph-ql/queries/GET_ALL_MUSIC/__generated__/ // types import { SongListProps } from "./SongList.types"; +// antd imports +import {Spin} from 'antd' + import SongListItem from "./SongListItem"; const SongList: React.FC = ({ playSong }) => { - const { data: allMusicConnection } = useQuery(GET_ALL_MUSIC, { + const { loading: isLoading, data: allMusicConnection } = useQuery(GET_ALL_MUSIC, { variables: { currentTime: Math.floor(Date.now() / 1000).toString(), }, }); + if(isLoading){ + return( + + ) + } + return ( <>
diff --git a/src/components/SongList/SongListItem.tsx b/src/components/SongList/SongListItem.tsx index 8746ce74..ca0a1a41 100644 --- a/src/components/SongList/SongListItem.tsx +++ b/src/components/SongList/SongListItem.tsx @@ -4,6 +4,7 @@ import { fetchIpfs, ipfsToHttps } from "../../services/ipfs/fetchIpfs"; import { MusicNftMetaData } from "../../types/MusicNFTData"; import styled from "styled-components"; import Image from "next/image"; + type Props = { musicNft: GetAllMusic_musicNFTs; onPlaySong: () => void; @@ -30,6 +31,7 @@ const SongListItemStyled = styled.div` color: #042440; } `; + const SongListItem = ({ musicNft, onPlaySong }: Props) => { const [metaData, setMetaData] = useState(); useEffect(() => { diff --git a/src/graph-ql/queries/GET_ALL_ADS/__generated__/GetAdvertiserAds.ts b/src/graph-ql/queries/GET_ALL_ADS/__generated__/GetAdvertiserAds.ts new file mode 100644 index 00000000..e7087ba8 --- /dev/null +++ b/src/graph-ql/queries/GET_ALL_ADS/__generated__/GetAdvertiserAds.ts @@ -0,0 +1,29 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: GetAdvertiserAds +// ==================================================== + +export interface GetAdvertiserAds_advNFTs_musicNFT { + __typename: "MusicNFT"; + metaDataUri: string; + assetUri: string; +} + +export interface GetAdvertiserAds_advNFTs { + __typename: "AdvNFT"; + musicNFT: GetAdvertiserAds_advNFTs_musicNFT; + assetHash: string; + expirationDuration: any; +} + +export interface GetAdvertiserAds { + advNFTs: GetAdvertiserAds_advNFTs[]; +} + +export interface GetAdvertiserAdsVariables { + advertiserAddress?: string | null; +} diff --git a/src/graph-ql/queries/GET_ALL_ADS/__generated__/GetUserExpiredAdspaces.ts b/src/graph-ql/queries/GET_ALL_ADS/__generated__/GetUserExpiredAdspaces.ts new file mode 100644 index 00000000..7ad04874 --- /dev/null +++ b/src/graph-ql/queries/GET_ALL_ADS/__generated__/GetUserExpiredAdspaces.ts @@ -0,0 +1,35 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: GetUserExpiredAdspaces +// ==================================================== + +export interface GetUserExpiredAdspaces_advNFTs_musicNFT { + __typename: "MusicNFT"; + metaDataUri: string; + assetUri: string; +} + +export interface GetUserExpiredAdspaces_advNFTs_owner { + __typename: "User"; + id: string; +} + +export interface GetUserExpiredAdspaces_advNFTs { + __typename: "AdvNFT"; + musicNFT: GetUserExpiredAdspaces_advNFTs_musicNFT; + expirationDuration: any; + owner: GetUserExpiredAdspaces_advNFTs_owner; +} + +export interface GetUserExpiredAdspaces { + advNFTs: GetUserExpiredAdspaces_advNFTs[]; +} + +export interface GetUserExpiredAdspacesVariables { + userAddress?: string | null; + expirationTime?: any | null; +} diff --git a/src/graph-ql/queries/GET_ALL_ADS/getAllAds.ts b/src/graph-ql/queries/GET_ALL_ADS/getAllAds.ts new file mode 100644 index 00000000..7f8ef645 --- /dev/null +++ b/src/graph-ql/queries/GET_ALL_ADS/getAllAds.ts @@ -0,0 +1,28 @@ +import { gql } from "@apollo/client"; + +export const GET_USER_EXPIRED_ADSPACES = gql` +query GetUserExpiredAdspaces($userAddress:String,$expirationTime:BigInt){ + advNFTs(where:{owner:$userAddress,expirationTime:$expirationTime}){ + musicNFT{ + metaDataUri + assetUri + } + expirationDuration + owner{ + id + } + } +}` + +export const GET_ADVERTISER_ADS = gql` +query GetAdvertiserAds($advertiserAddress:String){ + advNFTs(where:{owner:$advertiserAddress,assetHash_not:""}){ + musicNFT{ + metaDataUri + assetUri + } + assetHash + expirationDuration + } +}` + diff --git a/src/graph-ql/queries/GET_ALL_MUSIC/__generated__/GetAllMusic.ts b/src/graph-ql/queries/GET_ALL_MUSIC/__generated__/GetAllMusic.ts index ae508539..85fa16d8 100644 --- a/src/graph-ql/queries/GET_ALL_MUSIC/__generated__/GetAllMusic.ts +++ b/src/graph-ql/queries/GET_ALL_MUSIC/__generated__/GetAllMusic.ts @@ -10,7 +10,7 @@ export interface GetAllMusic_musicNFTs_advNfts { __typename: "AdvNFT"; assetHash: string; - metaDataHash: string; + expirationDuration: any; } export interface GetAllMusic_musicNFTs_creator { diff --git a/src/graph-ql/queries/GET_ALL_MUSIC/__generated__/GetUserListedMusic.ts b/src/graph-ql/queries/GET_ALL_MUSIC/__generated__/GetUserListedMusic.ts new file mode 100644 index 00000000..c759e47c --- /dev/null +++ b/src/graph-ql/queries/GET_ALL_MUSIC/__generated__/GetUserListedMusic.ts @@ -0,0 +1,42 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: GetUserListedMusic +// ==================================================== + +export interface GetUserListedMusic_musicNFTs_advNfts { + __typename: "AdvNFT"; + expirationDuration: any; + metaDataHash: string; +} + +export interface GetUserListedMusic_musicNFTs_creator { + __typename: "User"; + id: string; +} + +export interface GetUserListedMusic_musicNFTs_owner { + __typename: "User"; + id: string; +} + +export interface GetUserListedMusic_musicNFTs { + __typename: "MusicNFT"; + advNfts: GetUserListedMusic_musicNFTs_advNfts[]; + id: string; + creator: GetUserListedMusic_musicNFTs_creator; + owner: GetUserListedMusic_musicNFTs_owner; + metaDataUri: string; + assetUri: string; +} + +export interface GetUserListedMusic { + musicNFTs: GetUserListedMusic_musicNFTs[]; +} + +export interface GetUserListedMusicVariables { + userAddress?: string | null; +} diff --git a/src/graph-ql/queries/GET_ALL_MUSIC/getAllMusic.ts b/src/graph-ql/queries/GET_ALL_MUSIC/getAllMusic.ts index 19fac45f..0137eb70 100644 --- a/src/graph-ql/queries/GET_ALL_MUSIC/getAllMusic.ts +++ b/src/graph-ql/queries/GET_ALL_MUSIC/getAllMusic.ts @@ -5,6 +5,27 @@ export const GET_ALL_MUSIC = gql` musicNFTs{ advNfts(where:{expirationTime_gt:$currentTime}){ assetHash + expirationDuration + } + id + creator { + id + } + owner { + id + } + metaDataUri + assetUri + } +}` + + + +export const GET_USER_LISTED_MUSIC = gql` + query GetUserListedMusic($userAddress:String){ + musicNFTs(where:{owner:$userAddress}){ + advNfts{ + expirationDuration metaDataHash } id diff --git a/src/graph-ql/queries/GET_UNSOLD/__generated__/GetUserUnlisted.ts b/src/graph-ql/queries/GET_UNSOLD/__generated__/GetUserUnlisted.ts new file mode 100644 index 00000000..f87b8977 --- /dev/null +++ b/src/graph-ql/queries/GET_UNSOLD/__generated__/GetUserUnlisted.ts @@ -0,0 +1,67 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: GetUserUnlisted +// ==================================================== + +export interface GetUserUnlisted_marketItems_token_musicNFT_creator { + __typename: "User"; + id: string; +} + +export interface GetUserUnlisted_marketItems_token_musicNFT_owner { + __typename: "User"; + id: string; +} + +export interface GetUserUnlisted_marketItems_token_musicNFT_advNfts { + __typename: "AdvNFT"; + expirationDuration: any; +} + +export interface GetUserUnlisted_marketItems_token_musicNFT { + __typename: "MusicNFT"; + id: string; + creator: GetUserUnlisted_marketItems_token_musicNFT_creator; + owner: GetUserUnlisted_marketItems_token_musicNFT_owner; + metaDataUri: string; + assetUri: string; + advNfts: GetUserUnlisted_marketItems_token_musicNFT_advNfts[]; +} + +export interface GetUserUnlisted_marketItems_token_owner { + __typename: "User"; + id: string; +} + +export interface GetUserUnlisted_marketItems_token { + __typename: "AdvNFT"; + id: string; + musicNFT: GetUserUnlisted_marketItems_token_musicNFT; + metaDataHash: string; + assetHash: string; + owner: GetUserUnlisted_marketItems_token_owner; + expirationDuration: any; +} + +export interface GetUserUnlisted_marketItems { + __typename: "MarketItem"; + itemId: any; + owner: any; + price: any; + sold: boolean; + seller: any; + forSale: boolean; + token: GetUserUnlisted_marketItems_token; +} + +export interface GetUserUnlisted { + marketItems: GetUserUnlisted_marketItems[]; +} + +export interface GetUserUnlistedVariables { + sellerAddress?: string | null; +} diff --git a/src/graph-ql/queries/GET_UNSOLD/__generated__/GetUserUnsold.ts b/src/graph-ql/queries/GET_UNSOLD/__generated__/GetUserUnsold.ts new file mode 100644 index 00000000..c01cafc8 --- /dev/null +++ b/src/graph-ql/queries/GET_UNSOLD/__generated__/GetUserUnsold.ts @@ -0,0 +1,66 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: GetUserUnsold +// ==================================================== + +export interface GetUserUnsold_marketItems_token_musicNFT_creator { + __typename: "User"; + id: string; +} + +export interface GetUserUnsold_marketItems_token_musicNFT_owner { + __typename: "User"; + id: string; +} + +export interface GetUserUnsold_marketItems_token_musicNFT_advNfts { + __typename: "AdvNFT"; + expirationDuration: any; +} + +export interface GetUserUnsold_marketItems_token_musicNFT { + __typename: "MusicNFT"; + id: string; + creator: GetUserUnsold_marketItems_token_musicNFT_creator; + owner: GetUserUnsold_marketItems_token_musicNFT_owner; + metaDataUri: string; + assetUri: string; + advNfts: GetUserUnsold_marketItems_token_musicNFT_advNfts[]; +} + +export interface GetUserUnsold_marketItems_token_owner { + __typename: "User"; + id: string; +} + +export interface GetUserUnsold_marketItems_token { + __typename: "AdvNFT"; + id: string; + musicNFT: GetUserUnsold_marketItems_token_musicNFT; + metaDataHash: string; + assetHash: string; + owner: GetUserUnsold_marketItems_token_owner; + expirationDuration: any; +} + +export interface GetUserUnsold_marketItems { + __typename: "MarketItem"; + itemId: any; + owner: any; + price: any; + sold: boolean; + forSale: boolean; + token: GetUserUnsold_marketItems_token; +} + +export interface GetUserUnsold { + marketItems: GetUserUnsold_marketItems[]; +} + +export interface GetUserUnsoldVariables { + sellerAddress?: string | null; +} diff --git a/src/graph-ql/queries/GET_UNSOLD/getUnsold.ts b/src/graph-ql/queries/GET_UNSOLD/getUnsold.ts index c1f942e8..02c00d49 100644 --- a/src/graph-ql/queries/GET_UNSOLD/getUnsold.ts +++ b/src/graph-ql/queries/GET_UNSOLD/getUnsold.ts @@ -27,4 +27,75 @@ export const GET_UNSOLD = gql` expirationDuration } } +}` + + +export const GET_USER_UNSOLD = gql` + query GetUserUnsold($sellerAddress:String) { + marketItems(where:{seller:$sellerAddress,deleted:false}){ + itemId + owner + price + sold + forSale + token{ + id + musicNFT{ + id + creator { + id + } + owner { + id + } + metaDataUri + assetUri + advNfts{ + expirationDuration + } + } + metaDataHash + assetHash + owner{ + id + } + expirationDuration + } + } +}` + + +export const GET_USER_UNLISTED_ADS = gql` + query GetUserUnlisted($sellerAddress:String) { + marketItems(where:{seller:$sellerAddress,deleted:true}){ + itemId + owner + price + sold + seller + forSale + token{ + id + musicNFT{ + id + creator { + id + } + owner { + id + } + metaDataUri + assetUri + advNfts{ + expirationDuration + } + } + metaDataHash + assetHash + owner{ + id + } + expirationDuration + } + } }` \ No newline at end of file diff --git a/src/hooks/useMetadata/useMarketMetadata.tsx b/src/hooks/useMetadata/useMarketMetadata.tsx new file mode 100644 index 00000000..8f2a3e1d --- /dev/null +++ b/src/hooks/useMetadata/useMarketMetadata.tsx @@ -0,0 +1,29 @@ +import {useEffect, useState} from 'react' +import { fetchIpfs } from '../../services/ipfs/fetchIpfs'; +import { GetUserUnsold_marketItems, GetUserUnsold_marketItems_token_musicNFT} from "../../graph-ql/queries/GET_UNSOLD//__generated__/GetUserUnsold"; + + + +// accept metadata directly + + +export const useMarketMetadata = (item:GetUserUnsold_marketItems) =>{ + +const [music, setMusic] = useState(); + + const fetchMetaData = async () => { + const musicMetaData = await fetchIpfs( + item.token.musicNFT.metaDataUri + ); + setMusic(musicMetaData); + }; + + useEffect(() => { + fetchMetaData(); + }, []); + + return music; +} + + + \ No newline at end of file diff --git a/src/hooks/useMetadata/useMetadata.tsx b/src/hooks/useMetadata/useMetadata.tsx new file mode 100644 index 00000000..233864a8 --- /dev/null +++ b/src/hooks/useMetadata/useMetadata.tsx @@ -0,0 +1,29 @@ +import {useEffect, useState} from 'react' +import { fetchIpfs } from '../../services/ipfs/fetchIpfs'; +import { GetUserListedMusic_musicNFTs } from "../../graph-ql/queries/GET_ALL_MUSIC/__generated__/GetUserListedMusic"; +import { MusicNftMetaData } from "../../types/MusicNFTData"; + + +// accept metadata directly + + +export const useMusicMetadata = (item:GetUserListedMusic_musicNFTs) =>{ + +const [music, setMusic] = useState(); + + const fetchMetaData = async () => { + const musicMetaData = await fetchIpfs( + item.metaDataUri + ); + setMusic(musicMetaData); + }; + + useEffect(() => { + fetchMetaData(); + }, []); + + return music; +} + + + \ No newline at end of file