From dc73c1a50bdceb476841049aa5947e09d6659aad Mon Sep 17 00:00:00 2001 From: Poovizhi99 Date: Fri, 28 Mar 2025 16:25:53 +0530 Subject: [PATCH] completed some features in market place --- app/src/modules/market/AssetPreview.tsx | 50 ++++++- app/src/modules/market/Card.tsx | 5 +- app/src/modules/market/CardsContainer.tsx | 132 +----------------- app/src/modules/market/FilterSearch.tsx | 58 +++++++- app/src/modules/market/GltfLoader.tsx | 79 +++++++++++ app/src/modules/market/MarketPlace.tsx | 40 +++++- .../services/marketplace/fetchAssetDetails.ts | 22 +++ app/src/services/marketplace/fetchAssets.ts | 2 + app/src/services/marketplace/fetchGltfUrl.ts | 7 + .../services/marketplace/getAssetDownload.ts | 4 + .../services/marketplace/getSortedAssets.ts | 25 ++++ .../components/marketPlace/marketPlace.scss | 4 +- 12 files changed, 286 insertions(+), 142 deletions(-) create mode 100644 app/src/modules/market/GltfLoader.tsx create mode 100644 app/src/services/marketplace/fetchAssetDetails.ts create mode 100644 app/src/services/marketplace/fetchGltfUrl.ts create mode 100644 app/src/services/marketplace/getAssetDownload.ts create mode 100644 app/src/services/marketplace/getSortedAssets.ts diff --git a/app/src/modules/market/AssetPreview.tsx b/app/src/modules/market/AssetPreview.tsx index be474a2..864c5e5 100644 --- a/app/src/modules/market/AssetPreview.tsx +++ b/app/src/modules/market/AssetPreview.tsx @@ -1,11 +1,15 @@ -import React from "react"; +import React, { Suspense, useEffect } from "react"; import assetImage from "../../assets/image/image.png"; import { FiileedStarsIconSmall } from "../../components/icons/marketPlaceIcons"; +import { Canvas, useThree } from "@react-three/fiber"; +import { ContactShadows, OrbitControls, Text } from "@react-three/drei"; +import GltfLoader from "./GltfLoader"; +import * as THREE from "three"; // Define the shape of the selected card interface SelectedCard { assetName: string; - uploadedOn: string; + uploadedOn: number; price: number; rating: number; views: number; @@ -17,6 +21,14 @@ interface AssetPreviewProps { setSelectedCard: React.Dispatch>; // Type for setter function } +function Ui() { + return ( + + Loading your model... + + ); +} + const AssetPreview: React.FC = ({ selectedCard, setSelectedCard, @@ -27,8 +39,6 @@ const AssetPreview: React.FC = ({ Math.min(5, isNaN(selectedCard.rating) ? 0 : selectedCard.rating) ); - console.log("selectedCard: ", selectedCard); - // Ensure that the rating is a valid positive integer for array length const starsArray = Array.from({ length: rating }, (_, index) => index); @@ -36,8 +46,38 @@ const AssetPreview: React.FC = ({
- + {/* */} {/* Add canvas here */} +
+ { + scene.background = new THREE.Color(0xffffff); + }} + > + }> + {selectedCard.assetName && ( + + )} + + + + +
diff --git a/app/src/modules/market/Card.tsx b/app/src/modules/market/Card.tsx index b872dc0..4188447 100644 --- a/app/src/modules/market/Card.tsx +++ b/app/src/modules/market/Card.tsx @@ -8,6 +8,7 @@ import { } from "../../components/icons/marketPlaceIcons"; import assetImage from "../../assets/image/image.png"; +import { getAssetDownload } from "../../services/marketplace/getAssetDownload"; interface CardProps { assetName: string; @@ -40,9 +41,9 @@ const Card: React.FC = ({ return (
-
+ {/* -
+ */}
{assetName}
diff --git a/app/src/modules/market/CardsContainer.tsx b/app/src/modules/market/CardsContainer.tsx index 67bf849..50da667 100644 --- a/app/src/modules/market/CardsContainer.tsx +++ b/app/src/modules/market/CardsContainer.tsx @@ -16,109 +16,11 @@ interface ModelData { uploadDate: number; _id: string; } +interface ModelsProps { + models: ModelData[]; +} -const CardsContainer: React.FC = () => { - const [models, setModels] = useState([]); - - const array = [ - { - id: 1, - name: "Asset 1", - uploadedOn: "12 Jan 23", - price: 36500, - rating: 4.5, - views: 500, - }, - { - id: 2, - name: "Asset 2", - uploadedOn: "14 Jan 23", - price: 45000, - rating: 4.0, - views: 500, - }, - { - id: 3, - name: "Asset 3", - uploadedOn: "15 Jan 23", - price: 52000, - rating: 4.8, - views: 500, - }, - { - id: 4, - name: "Asset 4", - uploadedOn: "18 Jan 23", - price: 37000, - rating: 3.9, - views: 500, - }, - { - id: 5, - name: "Asset 5", - uploadedOn: "20 Jan 23", - price: 60000, - rating: 5.0, - views: 500, - }, - { - id: 6, - name: "Asset 6", - uploadedOn: "22 Jan 23", - price: 46000, - rating: 4.2, - views: 500, - }, - { - id: 7, - name: "Asset 7", - uploadedOn: "25 Jan 23", - price: 38000, - rating: 4.3, - views: 500, - }, - { - id: 8, - name: "Asset 8", - uploadedOn: "27 Jan 23", - price: 41000, - rating: 4.1, - views: 500, - }, - { - id: 9, - name: "Asset 9", - uploadedOn: "30 Jan 23", - price: 55000, - rating: 4.6, - views: 500, - }, - { - id: 10, - name: "Asset 10", - uploadedOn: "2 Feb 23", - price: 49000, - rating: 4.4, - views: 500, - }, - { - id: 11, - name: "Asset 11", - uploadedOn: "5 Feb 23", - price: 62000, - rating: 5.0, - views: 500, - }, - { - id: 12, - name: "Asset 12", - uploadedOn: "7 Feb 23", - price: 53000, - rating: 4.7, - views: 500, - }, - ]; - +const CardsContainer: React.FC = ({ models }) => { const [selectedCard, setSelectedCard] = useState<{ assetName: string; uploadedOn: number; @@ -136,33 +38,11 @@ const CardsContainer: React.FC = () => { }) => { setSelectedCard(cardData); }; - const getAllAssets = async () => { - try { - const assetsData = await fetchAssets(); - const reversedData = [...assetsData]?.reverse().slice(0, 8); - setModels(reversedData); - } catch (error) { - } finally { - } - }; - useEffect(() => { - getAllAssets(); - }, []); + return (
Products You May Like
- {/* {array.map((asset) => ( - - ))} */} {models.length > 0 && models.map((assetDetail) => ( { uploadedOn={assetDetail.uploadDate} price={36500} rating={4.5} - views={500} + views={800} onSelectCard={handleCardSelect} image={assetDetail.thumbnail} /> diff --git a/app/src/modules/market/FilterSearch.tsx b/app/src/modules/market/FilterSearch.tsx index 11a2cbf..08103ba 100644 --- a/app/src/modules/market/FilterSearch.tsx +++ b/app/src/modules/market/FilterSearch.tsx @@ -1,19 +1,69 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; // import RegularDropDown from "./ui/inputs/RegularDropDown"; import Search from "../../components/ui/inputs/Search"; import { StarsIcon } from "../../components/icons/marketPlaceIcons"; import RegularDropDown from "../../components/ui/inputs/RegularDropDown"; - -const FilterSearch: React.FC = () => { +import { getSortedAssets } from "../../services/marketplace/getSortedAssets"; +interface ModelData { + CreatedBy: string; + animated: string | null; + category: string; + description: string; + filename: string; + isArchieve: boolean; + modelfileID: string; + tags: string; + thumbnail: string; + uploadDate: number; + _id: string; +} +interface ModelsProps { + models: ModelData[]; + setModels: React.Dispatch>; + filteredModels: ModelData[]; +} +const FilterSearch: React.FC = ({ + models, + setModels, + filteredModels, +}) => { const [activeOption, setActiveOption] = useState("Sort by"); // State for active option + console.log("filteredModels: ", filteredModels); const handleSelect = (option: string) => { setActiveOption(option); + console.log("option: ", option); + // Alphabet ascending + // Alphabet descending + // All }; + useEffect(() => { + if (activeOption == "Alphabet ascending") { + let ascending = models + ?.slice() + .sort((a, b) => a.filename.localeCompare(b.filename)) + .map((val) => val); + setModels(ascending); + } else if (activeOption == "Alphabet descending") { + let descending = models + ?.slice() + .sort((a, b) => b.filename.localeCompare(a.filename)) + .map((val) => val); + setModels(descending); + } + }, [activeOption]); + const handleSearch = (val: string) => { + const filteredModel = filteredModels?.filter((model) => + model.filename.toLowerCase().includes(val.toLowerCase()) + ); + + setModels(filteredModel); + }; + return (
- {}} /> + void; + selectedAnimation?: string; + setSelectedAnimation?: (animation: string) => void; +} + +// const getGLTFUrl = (url: string) => url; // Placeholder for your actual function + +const GltfLoader: React.FC = ({ + glbdata, + fromServer, + setAnimations, + selectedAnimation, +}) => { + const modelUrl: any = fromServer ? fetchGltfUrl(fromServer) : glbdata; + const { scene, animations } = useGLTF(modelUrl ?? "") as { + scene: Object3D; + animations: THREE.AnimationClip[]; + }; + + const mixer = useRef( + scene ? new AnimationMixer(scene) : null + ); + const actions = useRef>({}); + + useEffect(() => { + if (animations.length > 0 && mixer.current && setAnimations) { + const animationNames = animations.map((animation) => animation.name); + setAnimations(animationNames); + + animations.forEach((animation) => { + const action = mixer.current!.clipAction(animation); + actions.current[animation.name] = action; + }); + } else { + setAnimations && setAnimations([]); + } + }, [animations, setAnimations]); + + useEffect(() => { + if (actions.current && selectedAnimation) { + const action = actions.current[selectedAnimation]; + if (action) { + action.reset().fadeIn(0.5).play(); + return () => { + action.fadeOut(0.5); + }; + } + } + }, [selectedAnimation]); + + useFrame((_, delta) => { + if (mixer.current) { + mixer.current.update(delta); + } + }); + + return ( + + + + ); +}; + +export default GltfLoader; diff --git a/app/src/modules/market/MarketPlace.tsx b/app/src/modules/market/MarketPlace.tsx index 71dc0a5..d830576 100644 --- a/app/src/modules/market/MarketPlace.tsx +++ b/app/src/modules/market/MarketPlace.tsx @@ -1,14 +1,46 @@ -import React from "react"; +import React, { useEffect, useState } from "react"; import FilterSearch from "./FilterSearch"; import CardsContainer from "./CardsContainer"; - +import { fetchAssets } from "../../services/marketplace/fetchAssets"; +import { getAssetImages } from "../../services/factoryBuilder/assest/assets/getAssetImages"; +interface ModelData { + CreatedBy: string; + animated: string | null; + category: string; + description: string; + filename: string; + isArchieve: boolean; + modelfileID: string; + tags: string; + thumbnail: string; + uploadDate: number; + _id: string; +} const MarketPlace = () => { + const [models, setModels] = useState([]); + const [filteredModels, setFilteredModels] = useState([]); + + useEffect(() => { + const filteredAssets = async () => { + try { + const filt = await getAssetImages("67d934ad0f42a1fdadb19aa6"); + setModels(filt.items); + setFilteredModels(filt.items); + } catch {} + }; + filteredAssets(); + }, []); + return (
- - + +
diff --git a/app/src/services/marketplace/fetchAssetDetails.ts b/app/src/services/marketplace/fetchAssetDetails.ts new file mode 100644 index 0000000..b14fd3f --- /dev/null +++ b/app/src/services/marketplace/fetchAssetDetails.ts @@ -0,0 +1,22 @@ +let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; +export const getAssetDetails = async (filename: string) => { + try { + const response = await fetch(`${BackEnd_url}/api/v1/assetDetails`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ filename }), + }); + + if (!response.ok) { + throw new Error("Failed to fetch asset details"); + } + + const result = await response.json(); + return result; + } catch (error: any) { + // console.error("Error fetching category:", error.message); + throw new Error(error.message); + } +}; diff --git a/app/src/services/marketplace/fetchAssets.ts b/app/src/services/marketplace/fetchAssets.ts index 3408252..e434a2b 100644 --- a/app/src/services/marketplace/fetchAssets.ts +++ b/app/src/services/marketplace/fetchAssets.ts @@ -6,6 +6,8 @@ export const fetchAssets = async () => { throw new Error("Network response was not ok"); } const result = await response.json(); + const last10Assets = result.slice(-10); + console.log('last10Assets: ', last10Assets); return result; } catch (error) { console.log("error: ", error); diff --git a/app/src/services/marketplace/fetchGltfUrl.ts b/app/src/services/marketplace/fetchGltfUrl.ts new file mode 100644 index 0000000..3916c9e --- /dev/null +++ b/app/src/services/marketplace/fetchGltfUrl.ts @@ -0,0 +1,7 @@ +let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; +export const fetchGltfUrl = (filename: string) => { + if (filename) { + return `${BackEnd_url}/api/v1/getAssetFile/${filename}`; + } + return null; // or handle the case when filename is not provided +}; diff --git a/app/src/services/marketplace/getAssetDownload.ts b/app/src/services/marketplace/getAssetDownload.ts new file mode 100644 index 0000000..dea6d14 --- /dev/null +++ b/app/src/services/marketplace/getAssetDownload.ts @@ -0,0 +1,4 @@ +let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; +export const getAssetDownload = (filename: any) => { + return `${BackEnd_url}/api/v1/getAssetFile/${filename}.gltf`; +}; diff --git a/app/src/services/marketplace/getSortedAssets.ts b/app/src/services/marketplace/getSortedAssets.ts new file mode 100644 index 0000000..3bbbfbe --- /dev/null +++ b/app/src/services/marketplace/getSortedAssets.ts @@ -0,0 +1,25 @@ +let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; +export const getSortedAssets = async (category: any, orders: any) => { + try { + const response = await fetch( + `${BackEnd_url}/api/v1/categoryWise/${category}?sortBy=${orders}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); + + if (!response.ok) { + throw new Error(`Error: ${response.statusText}`); + } + + const result = await response.json(); + + return result; // Return the result to be used later + } catch (error: any) { + console.error("Error fetching category:", error.message); + throw new Error(error.message); + } +}; diff --git a/app/src/styles/components/marketPlace/marketPlace.scss b/app/src/styles/components/marketPlace/marketPlace.scss index 8df0896..71f5897 100644 --- a/app/src/styles/components/marketPlace/marketPlace.scss +++ b/app/src/styles/components/marketPlace/marketPlace.scss @@ -126,6 +126,8 @@ display: flex; max-height: 180px; justify-content: center; + border-radius: #{$border-radius-medium}; + overflow: hidden; img{ height: inherit; width: 100%; @@ -211,7 +213,7 @@ background-color: var(--background-color); display: flex; gap: 12px; - z-index: 100; + overflow: hidden; border-radius: 20px; }