Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nft media component #447

Merged
merged 9 commits into from
May 15, 2024
5 changes: 5 additions & 0 deletions src/appsConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ export const NF_TUNES_TOKENS: app_token[] = IS_DEVNET
{ tokenIdentifier: "DATANFTFT-e0b917", nonce: 138 },
{ tokenIdentifier: "DATANFTFT-e0b917", nonce: 187 },
{ tokenIdentifier: "DATANFTFT-e0b917", nonce: 295 },
{ tokenIdentifier: "DATANFTFT-e0b917", nonce: 299 },
{ tokenIdentifier: "DATANFTFT-e0b917", nonce: 301 },
{ tokenIdentifier: "DATANFTFT-e0b917", nonce: 324 },
{ tokenIdentifier: "DATANFTFT-e0b917", nonce: 326 },

...Array.from({ length: 4 }, (_, i) => ({ tokenIdentifier: "OASMUSICPL-47b186", nonce: i })),
...Array.from({ length: 19 }, (_, i) => ({ tokenIdentifier: "FOOWLDMSC-5ee8ec", nonce: i })),
]
Expand Down
17 changes: 3 additions & 14 deletions src/components/DataNftCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { DataNft } from "@itheum/sdk-mx-data-nft/out";
import { useGetNetworkConfig } from "@multiversx/sdk-dapp/hooks/useGetNetworkConfig";
import { MARKETPLACE_DETAILS_PAGE } from "config";
import { cn } from "libs/utils";
import ImageSlider from "./ImageSlider";
import { Modal } from "./Modal/Modal";
import { MXAddressLink } from "./MXAddressLink";
import NftMediaComponent from "./NftMediaComponent";
import { Button } from "../libComponents/Button";
import { Card, CardContent, CardFooter } from "../libComponents/Card";
import { IFilterData } from "../libComponents/Filter";
import { NftMedia } from "libs/types";

export function DataNftCard({
index,
Expand Down Expand Up @@ -48,7 +49,6 @@ export function DataNftCard({
function goToMarketplace(tokenIdentifier: string) {
window.open(`${MARKETPLACE_DETAILS_PAGE}${tokenIdentifier}`)?.focus();
}

return (
<div className="mb-3">
<Card
Expand All @@ -57,18 +57,7 @@ export function DataNftCard({
"border-[0.5px] dark:border-slate-100/30 border-slate-300 bg-transparent rounded-[2.37rem] base:w-[18.5rem] md:w-[20.6rem]"
)}>
<CardContent className="flex flex-col p-3">
{dataNft.media && dataNft.media[0] && (dataNft.media[0] as any).url && (dataNft.media[0] as any).fileType.includes("video") ? (
<video autoPlay loop src={(dataNft.media[0] as any).url} className=" mb-8 md:w-auto rounded-3xl base:h-[15rem] md:h-[18rem]"></video>
) : dataNft.extraAssets.length > 0 ? (
<ImageSlider imageUrls={dataNft.media.map((mediaObj: any) => mediaObj.url) ?? [dataNft.nftImgUrl]} autoSlide />
) : (
<div className="mb-8 flex justify-center base:max-h-[15rem] md:max-h-[18rem] object-cover">
<img
className="md:w-auto base:w-[15rem] rounded-3xl"
src={!isLoading ? dataNft.nftImgUrl : "https://media.elrond.com/nfts/thumbnail/default.png"}
/>
</div>
)}
<NftMediaComponent nftMedia={dataNft.media as NftMedia[]} isLoading={isLoading} mediaStyle="mb-8 base:h-[15rem] md:h-[18rem]" />

<div className="md:h-[15rem] h-[13rem]">
<div className="grid grid-cols-12 mb-1">
Expand Down
36 changes: 19 additions & 17 deletions src/components/ImageSlider.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import React, { useEffect, useState } from "react";
import { motion } from "framer-motion";
import { ArrowLeft, ArrowRight, Image } from "lucide-react";
import { cn } from "libs/utils";
import { ArrowLeft, ArrowRight } from "lucide-react";
import { Button } from "libComponents/Button";

interface ImageSliderProps {
imageUrls: string[];
media: { url: string; type: string }[];
autoSlide?: boolean;
autoSlideInterval?: number;
imageWidth?: string;
imageHeight?: string;
onLoad?: () => void;
openNftDetailsDrawer?: () => void;
}

//Spring animation parameters
Expand All @@ -22,14 +18,14 @@ const spring = {
};

const ImageSlider: React.FC<ImageSliderProps> = (props) => {
const { imageUrls, autoSlide = false, autoSlideInterval = 6000, imageWidth = "210px", imageHeight = "210px", onLoad, openNftDetailsDrawer } = props;
const { media, autoSlide = false, autoSlideInterval = 6000, onLoad } = props;
const [imageIndex, setImageIndex] = useState(0);
const [switchedImageManually, setSwitchedImageManually] = useState(false);
const [nextImageIndex, setNextImageIndex] = useState(0);
const makeFlip = nextImageIndex !== imageIndex;

useEffect(() => {
if (autoSlide && imageUrls.length > 1 && !switchedImageManually) {
if (autoSlide && media.length > 1 && !switchedImageManually) {
const interval = setInterval(() => {
goToNextImage();
}, autoSlideInterval);
Expand All @@ -38,17 +34,17 @@ const ImageSlider: React.FC<ImageSliderProps> = (props) => {
}, [switchedImageManually]);

function goToPreviousImage(autoSwitch = false) {
setNextImageIndex((prevIndex) => (prevIndex === 0 ? imageUrls.length - 1 : prevIndex - 1));
setNextImageIndex((prevIndex) => (prevIndex === 0 ? media.length - 1 : prevIndex - 1));
setSwitchedImageManually(autoSwitch);
}

function goToNextImage(autoSwitch = false) {
setNextImageIndex((prevIndex) => (prevIndex === imageUrls.length - 1 ? 0 : prevIndex + 1));
setNextImageIndex((prevIndex) => (prevIndex === media.length - 1 ? 0 : prevIndex + 1));
setSwitchedImageManually(autoSwitch);
}

return (
<div className="mb-8 w-full justify-center base:h-[15rem] md:h-[18rem] object-cover relative ">
<div className="mb-8 w-full justify-center base:h-[15rem] md:h-[18rem] relative ">
<div className="perspective-1200 transform-style-preserve-3d ">
<motion.div
transition={spring}
Expand All @@ -59,7 +55,11 @@ const ImageSlider: React.FC<ImageSliderProps> = (props) => {
backfaceVisibility: "hidden",
position: "absolute",
}}>
<img className="md:w-auto base:w-[15rem] rounded-3xl base:h-[15rem] md:h-[18rem] mx-auto" src={imageUrls[imageIndex]} onLoad={onLoad} />
{media[imageIndex].type.includes("video") ? (
<video autoPlay loop src={media[imageIndex].url} className="md:w-auto base:w-[15rem] rounded-3xl base:h-[15rem] md:h-[18rem] mx-auto"></video>
) : (
<img className="md:w-auto base:w-[15rem] rounded-3xl base:h-[15rem] md:h-[18rem] mx-auto" src={media[imageIndex].url} onLoad={onLoad} />
)}
</motion.div>
{makeFlip && (
<motion.div
Expand All @@ -76,18 +76,20 @@ const ImageSlider: React.FC<ImageSliderProps> = (props) => {
onAnimationComplete={() => {
setImageIndex(nextImageIndex);
}}>
<img className="md:w-auto base:w-[15rem] rounded-3xl base:h-[15rem] md:h-[18rem] mx-auto" src={imageUrls[nextImageIndex]} onLoad={onLoad} />
{media[nextImageIndex].type.includes("video") ? (
<video autoPlay loop src={media[imageIndex].url} className="md:w-auto base:w-[15rem] rounded-3xl base:h-[15rem] md:h-[18rem] mx-auto"></video>
) : (
<img className="md:w-auto base:w-[15rem] rounded-3xl base:h-[15rem] md:h-[18rem] mx-auto" src={media[nextImageIndex].url} onLoad={onLoad} />
)}
</motion.div>
)}
</div>
{imageUrls.length > 1 && (
{media.length > 1 && (
<div className="z-10 flex flex-row h-full w-full justify-center items-end my-2 mt-8 gap-2 ">
<Button className="p-1 h-6 !rounded-3xl" disabled={makeFlip}>
{" "}
<Button className="p-1 h-6 !rounded-3xl" disabled={makeFlip}>
<ArrowLeft onClick={() => goToPreviousImage(true)} />
</Button>
<Button className="p-1 h-6 !rounded-3xl" disabled={makeFlip}>
{" "}
<ArrowRight onClick={() => goToNextImage(true)} />{" "}
</Button>
</div>
Expand Down
39 changes: 39 additions & 0 deletions src/components/NftMediaComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { NftMedia } from "libs/types";
import { cn } from "libs/utils";
import React from "react";
import ImageSlider from "./ImageSlider";

interface NftMediaComponentProps {
nftMedia: NftMedia[];
isLoading?: boolean;
mediaStyle?: string;
}

const NftMediaComponent: React.FC<NftMediaComponentProps> = (props) => {
const { nftMedia, isLoading, mediaStyle } = props;
return (
<div>
{nftMedia.length === 0 && <img src="https://media.elrond.com/nfts/thumbnail/default.png" />}
{nftMedia.length === 1 ? (
<div className={cn("flex justify-center rounded-3xl overflow-hidden", mediaStyle)}>
{nftMedia[0].fileType === "video/mp4" ? (
<video autoPlay loop src={nftMedia[0]?.url} className="scale-[1.8]" />
) : (
<img className="rounded-3xl" src={!isLoading ? nftMedia[0]?.url : "https://media.elrond.com/nfts/thumbnail/default.png"} />
)}
</div>
) : (
<div className=" flex">
<ImageSlider
media={nftMedia.map((item) => ({
url: item.url,
type: item.fileType,
}))}
/>{" "}
</div>
)}
</div>
);
};

export default NftMediaComponent;
9 changes: 8 additions & 1 deletion src/components/ThreeDCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ interface ThreeDCardProps {

export function ThreeDCard(props: ThreeDCardProps) {
const { tokenIdentifier, title, nftImgUrl, supply, rating, wantedTokenAmount, offerIndex } = props;

return (
<CardContainer className="inter-var h-84 w-64 mx-2" containerClassName="py-8">
<CardBody className="bg-gray-50 relative group/card dark:hover:shadow-2xl dark:hover:shadow-emerald-500/[0.1] dark:bg-black dark:border-white/[0.2] border-black/[0.1] w-auto sm:w-[30rem] h-auto rounded-xl p-6 border ">
<CardItem translateZ="100" className=" w-full flex flex-row items-center justify-center mt-4">
<a href={`${MARKETPLACE_DETAILS_PAGE}${tokenIdentifier}${offerIndex ? "/offer-" + offerIndex : ""}`} target="_blank" className="cursor-pointer">
<img src={nftImgUrl} className="h-48 w-48 object-cover rounded-3xl group-hover/card:shadow-xl" alt="thumbnail" />
{nftImgUrl.includes(".mp4") ? (
<div className="flex relative h-48 w-48 rounded-3xl overflow-hidden justify-center items-center">
<video autoPlay loop src={nftImgUrl} className="scale-[1.8] "></video>
</div>
) : (
<img src={nftImgUrl} className="h-48 w-48 object-cover rounded-3xl group-hover/card:shadow-xl" alt="thumbnail" />
)}
</a>
</CardItem>
<CardItem translateZ="50" className=" max-w-48 elipsis truncate mt-4 text-md font-bold text-neutral-600 dark:text-white">
Expand Down
7 changes: 7 additions & 0 deletions src/libs/types/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,10 @@ export interface TrendingNft {
tokenIdentifier: string;
rating: number;
}
export interface NftMedia {
url: string;
originalUrl: string;
thumbnailUrl: string;
fileType: string;
fileSize: number;
}
13 changes: 7 additions & 6 deletions src/pages/Account/MyListed/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import { createNftId } from "libs/utils/token";
import { HeaderComponent } from "components/Layout/HeaderComponent";
import { Card, CardContent } from "libComponents/Card";
import { ExternalLink } from "lucide-react";
import ImageSlider from "components/ImageSlider";
import NftMediaComponent from "components/NftMediaComponent";
import { NftMedia } from "libs/types";

export const MyListed = () => {
const {
Expand All @@ -29,10 +32,8 @@ export const MyListed = () => {

const _totalOfferCount = await dataNftMarket.viewAddressTotalOffers(new Address(address));
setOfferCount(_totalOfferCount);

const _offers = await dataNftMarket.viewAddressListedOffers(new Address(address));
setOffers(_offers);

setIsLoading(false);
}

Expand Down Expand Up @@ -74,13 +75,13 @@ export const MyListed = () => {
return (
<div className="mb-3" key={`o-c-${index}`}>
<Card className="border-[0.5px] dark:border-slate-100/30 border-slate-300 bg-transparent rounded-[2.37rem] xl:w-[330px] w-[296px] pb-5">
<CardContent className="flex flex-col p-4">
<CardContent className="flex flex-col p-6 ">
<div className="mb-4">
<img src={isDataNftLoaded ? dataNft.nftImgUrl : "https://media.elrond.com/nfts/thumbnail/default.png"} alt="dataNftImage" />
<NftMediaComponent nftMedia={dataNft.media as NftMedia[]} isLoading={isLoading} mediaStyle="mb-8 base:h-[15rem] md:h-[18rem]" />
</div>
<div className="xl:h-[300px] h-[315px]">
<div className="mb-1">
<h5 className="text-center !text-xl !font-[Clash-Medium] pb-2">Offer Detail</h5>
<h5 className="text-start !text-xl !font-[Clash-Medium] pb-2">Offer Detail</h5>
</div>
<div className="grid grid-cols-12 mb-1">
<span className="col-span-4 opacity-6">Identifier:</span>
Expand All @@ -101,7 +102,7 @@ export const MyListed = () => {
<span className="col-span-8 text-left">{offer.quantity}</span>
</div>

<div className="mt-4 mb-1">
<div className="mt-4 mb-1 text-start">
<h5 className="text-center !text-xl !font-[Clash-Medium] pb-2">Data NFT Detail</h5>
</div>
<div className="grid grid-cols-12 mb-1">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ export const ItheumTrailblazer = () => {
res = await dataNft.viewDataViaMVXNativeAuth(arg);
res.data = await (res.data as Blob).text();
res.data = JSON.parse(res.data);
console.log(res.data);

setData(res.data.data.reverse());
setIsFetchingDataMarshal(false);
Expand Down