searching filtered assets

This commit is contained in:
2025-04-01 08:58:56 +05:30
parent cacb23ea5a
commit 21d96a31bc
14 changed files with 342 additions and 104 deletions

View File

@@ -9,12 +9,13 @@ import { getCategoryAsset } from "../../../services/factoryBuilder/assest/assets
import arch from "../../../assets/gltf-glb/arch.glb"; import arch from "../../../assets/gltf-glb/arch.glb";
import door from "../../../assets/gltf-glb/door.glb"; import door from "../../../assets/gltf-glb/door.glb";
import window from "../../../assets/gltf-glb/window.glb"; import window from "../../../assets/gltf-glb/window.glb";
import { fetchAssets } from "../../../services/marketplace/fetchAssets";
interface AssetProp { interface AssetProp {
filename: string; filename: string;
thumbnail?: string; thumbnail?: string;
category: string; category: string;
description?: string; description?: string;
tags?: string; tags: string;
url?: String; url?: String;
uploadDate?: number; uploadDate?: number;
isArchieve?: boolean; isArchieve?: boolean;
@@ -25,12 +26,27 @@ interface AssetProp {
const Assets: React.FC = () => { const Assets: React.FC = () => {
const [searchValue, setSearchValue] = useState<string>(""); const [searchValue, setSearchValue] = useState<string>("");
const [selectedCategory, setSelectedCategory] = useState<string | null>(null); const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
const [filteredAsset, setFilteredAsset] = useState<AssetProp[]>([]); const [categoryAssets, setCategoryAssets] = useState<AssetProp[]>([]);
const [filtereredAssets, setFiltereredAssets] = useState<AssetProp[]>([]);
const handleSearchChange = (value: string) => { const handleSearchChange = (value: string) => {
setSearchValue(value); setSearchValue(value);
setSelectedCategory(null); // Reset selected category when search changes setSelectedCategory(null);
const filteredModels = filtereredAssets?.filter((model) =>
model.filename.toLowerCase().includes(value.toLowerCase())
);
setCategoryAssets(filteredModels);
}; };
useEffect(() => {
const filteredAssets = async () => {
try {
const filt = await fetchAssets();
setFiltereredAssets(filt);
} catch {}
};
filteredAssets();
}, []);
const categoryList = useMemo( const categoryList = useMemo(
() => [ () => [
@@ -68,56 +84,53 @@ const Assets: React.FC = () => {
filename: "arch", filename: "arch",
category: "Feneration", category: "Feneration",
url: arch, url: arch,
tags: "arch",
}, },
{ {
filename: "door", filename: "door",
category: "Feneration", category: "Feneration",
url: door, url: door,
thumbnail: feneration,
tags: "door",
}, },
{ {
filename: "window", filename: "window",
category: "Feneration", category: "Feneration",
url: window, url: window,
tags: "window",
}, },
]; ];
setFilteredAsset(localAssets); setCategoryAssets(localAssets);
setFiltereredAssets(localAssets);
} else { } else {
try { try {
const res = await getCategoryAsset(asset); const res = await getCategoryAsset(asset);
setFilteredAsset(res || []); // Ensure it's always an array setCategoryAssets(res || []); // Ensure it's always an array
setFiltereredAssets(res || []);
} catch (error) {} } catch (error) {}
} }
}; };
useEffect(() => {}, [filteredAsset]);
return ( return (
<div className="assets-container"> <div className="assets-container">
<Search onChange={handleSearchChange} /> <Search onChange={handleSearchChange} />
{searchValue ? ( {searchValue ? (
<div className="searched-content"> <div className="assets-result">
<p>Results for "{searchValue}"</p> <div className="assets-wrapper">
</div> <div className="searched-content">
) : selectedCategory ? ( <p>Results for "{searchValue}"</p>
<div className="assets-wrapper"> </div>
{/* Back Button */}
<div
className="back-button"
onClick={() => setSelectedCategory(null)}
>
Back
</div> </div>
<h2>{selectedCategory}</h2>
<div className="assets-container"> <div className="assets-container">
{filteredAsset && {categoryAssets &&
filteredAsset?.map((asset: any, index: number) => ( categoryAssets?.map((asset: any, index: number) => (
<div key={index} className="assets"> <div key={index} className="assets">
{asset?.thumbnail && ( <img
<img src={asset?.thumbnail}
src={asset?.thumbnail} alt={asset.filename}
alt={asset.filename} className="asset-image"
className="asset-image" />
/>
)}
<div className="asset-name"> <div className="asset-name">
{asset.filename {asset.filename
.split("_") .split("_")
@@ -131,6 +144,43 @@ const Assets: React.FC = () => {
))} ))}
</div> </div>
</div> </div>
) : selectedCategory ? (
<div className="assets-wrapper">
{/* Back Button */}
<div
className="back-button"
onClick={() => {
setSelectedCategory(null);
setCategoryAssets([]);
}}
>
Back
</div>
<h2>{selectedCategory}</h2>
<div className="assets-container">
{searchValue ||
(categoryAssets &&
categoryAssets?.map((asset: any, index: number) => (
<div key={index} className="assets">
<img
src={asset?.thumbnail}
alt={asset.filename}
className="asset-image"
/>
<div className="asset-name">
{asset.filename
.split("_")
.map(
(word: any) =>
word.charAt(0).toUpperCase() + word.slice(1)
)
.join(" ")}
</div>
</div>
)))}
</div>
</div>
) : ( ) : (
<div className="assets-wrapper"> <div className="assets-wrapper">
<h2>Categories</h2> <h2>Categories</h2>

View File

@@ -33,6 +33,7 @@ const RenderAnalysisInputs: React.FC<InputRendererProps> = ({
label={preset.inputs.label} label={preset.inputs.label}
min={0} min={0}
max={0} max={0}
value={5}
/> />
); );
} }

View File

@@ -1,4 +1,4 @@
import React, { useState } from "react"; import React, { useEffect, useState } from "react";
import InputRange from "../../../ui/inputs/InputRange"; import InputRange from "../../../ui/inputs/InputRange";
import InputToggle from "../../../ui/inputs/InputToggle"; import InputToggle from "../../../ui/inputs/InputToggle";
import { AI_Icon } from "../../../icons/ExportCommonIcons"; import { AI_Icon } from "../../../icons/ExportCommonIcons";
@@ -6,6 +6,7 @@ import LabeledButton from "../../../ui/inputs/LabledButton";
import { import {
useAzimuth, useAzimuth,
useElevation, useElevation,
useLimitDistance,
useRenderDistance, useRenderDistance,
useResetCamera, useResetCamera,
useRoofVisibility, useRoofVisibility,
@@ -17,6 +18,7 @@ import {
} from "../../../../store/store"; } from "../../../../store/store";
import { setEnvironment } from "../../../../services/factoryBuilder/environment/setEnvironment"; import { setEnvironment } from "../../../../services/factoryBuilder/environment/setEnvironment";
import * as CONSTANTS from "../../../../types/world/worldConstants"; import * as CONSTANTS from "../../../../types/world/worldConstants";
import { validateBBox } from "@turf/helpers";
const GlobalProperties: React.FC = () => { const GlobalProperties: React.FC = () => {
const { toggleView, setToggleView } = useToggleView(); const { toggleView, setToggleView } = useToggleView();
const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem(); const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem();
@@ -27,27 +29,83 @@ const GlobalProperties: React.FC = () => {
const { elevation, setElevation } = useElevation(); const { elevation, setElevation } = useElevation();
const { azimuth, setAzimuth } = useAzimuth(); const { azimuth, setAzimuth } = useAzimuth();
const { renderDistance, setRenderDistance } = useRenderDistance(); const { renderDistance, setRenderDistance } = useRenderDistance();
const { socket } = useSocketStore(); const { socket } = useSocketStore();
const [limitDistance, setLimitDistance] = useState(false); const { limitDistance, setLimitDistance } = useLimitDistance();
const [distance, setDistance] = useState<number>(30); const [distance, setDistance] = useState<number>(40);
useEffect(() => {}, [limitDistance]);
const [limitGridDistance, setLimitGridDistance] = useState(false); const [limitGridDistance, setLimitGridDistance] = useState(false);
const [gridDistance, setGridDistance] = useState<number>(5); const [gridDistance, setGridDistance] = useState<number>(5);
function optimizeScene() { const optimizeScene = async (value: any) => {
const email = localStorage.getItem("email");
const organization = email?.split("@")[1]?.split(".")[0] || "defaultOrg";
const data = await setEnvironment(
organization,
localStorage.getItem("userId")!,
wallVisibility,
roofVisibility,
shadows,
30,
true
);
setRenderDistance(30);
setLimitDistance(true); setLimitDistance(true);
setDistance(30); };
} const limitRenderDistance = async () => {
const email = localStorage.getItem("email");
const organization = email?.split("@")[1]?.split(".")[0] || "defaultOrg";
if (limitDistance) {
let data = await setEnvironment(
organization,
localStorage.getItem("userId")!,
wallVisibility,
roofVisibility,
shadows,
75,
!limitDistance
);
setRenderDistance(75);
} else {
let data = await setEnvironment(
organization,
localStorage.getItem("userId")!,
wallVisibility,
roofVisibility,
shadows,
renderDistance,
!limitDistance
);
}
setLimitDistance(!limitDistance);
};
function updateDistance(value: number) { function updateDistance(value: number) {
console.log("value: ", value);
setDistance(value); setDistance(value);
setRenderDistance(value); setRenderDistance(value);
} }
function updateGridDistance(value: number) { function updateGridDistance(value: number) {
setGridDistance(value); setGridDistance(value);
} }
const updatedDist = async (value: number) => {
const email = localStorage.getItem("email");
const organization = email?.split("@")[1]?.split(".")[0] || "defaultOrg";
setRenderDistance(value);
// setDistance(value);
const data = await setEnvironment(
organization,
localStorage.getItem("userId")!,
wallVisibility,
roofVisibility,
shadows,
value,
limitDistance
);
};
// Function to toggle roof visibility // Function to toggle roof visibility
const changeRoofVisibility = async () => { const changeRoofVisibility = async () => {
const email = localStorage.getItem("email"); const email = localStorage.getItem("email");
@@ -59,9 +117,11 @@ const GlobalProperties: React.FC = () => {
localStorage.getItem("userId")!, localStorage.getItem("userId")!,
wallVisibility, wallVisibility,
!roofVisibility, !roofVisibility,
shadows shadows,
renderDistance,
limitDistance
); );
// console.log('data: ', data); //
//using Socket //using Socket
// const visData = { // const visData = {
@@ -86,9 +146,11 @@ const GlobalProperties: React.FC = () => {
localStorage.getItem("userId")!, localStorage.getItem("userId")!,
!wallVisibility, !wallVisibility,
roofVisibility, roofVisibility,
shadows shadows,
renderDistance,
limitDistance
); );
// console.log('data: ', data); //
//using Socket //using Socket
// const visData = { // const visData = {
@@ -113,9 +175,11 @@ const GlobalProperties: React.FC = () => {
localStorage.getItem("userId")!, localStorage.getItem("userId")!,
wallVisibility, wallVisibility,
roofVisibility, roofVisibility,
!shadows !shadows,
renderDistance,
limitDistance
); );
// console.log('data: ', data); //
//using Socket //using Socket
// const visData = { // const visData = {
@@ -185,18 +249,23 @@ const GlobalProperties: React.FC = () => {
inputKey="4" inputKey="4"
label="Limit Render Distance" label="Limit Render Distance"
value={limitDistance} value={limitDistance}
onClick={() => { // onClick={() => {
setLimitDistance(!limitDistance); // setLimitDistance(!limitDistance);
// // setDistance(75);
// // setRenderDistance(75);
// }}
onClick={async () => {
await limitRenderDistance(); // Call the function here
}} }}
/> />
<InputRange <InputRange
label="Distance" label="Distance"
disabled={!limitDistance} disabled={!limitDistance}
value={distance} value={renderDistance}
key={"5"}
min={CONSTANTS.distanceConfig.minDistance} min={CONSTANTS.distanceConfig.minDistance}
max={CONSTANTS.distanceConfig.maxDistance} max={CONSTANTS.distanceConfig.maxDistance}
onChange={(value: number) => updateDistance(value)} onChange={(value: number) => updateDistance(value)}
onPointerUp={updatedDist}
/> />
<div className="split"></div> <div className="split"></div>

View File

@@ -8,6 +8,7 @@ interface InputToggleProps {
onChange?: (value: number) => void; // Function to handle toggle clicks onChange?: (value: number) => void; // Function to handle toggle clicks
disabled?: boolean; disabled?: boolean;
value?: number; value?: number;
onPointerUp?: (value: number) => void;
} }
const InputRange: React.FC<InputToggleProps> = ({ const InputRange: React.FC<InputToggleProps> = ({
@@ -17,9 +18,10 @@ const InputRange: React.FC<InputToggleProps> = ({
min, min,
max, max,
disabled, disabled,
value = 5, value,
onPointerUp,
}) => { }) => {
const [rangeValue, setRangeValue] = useState<number>(value); const [rangeValue, setRangeValue] = useState<number>(value ? value : 5);
function handleChange(e: React.ChangeEvent<HTMLInputElement>) { function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
const newValue = parseInt(e.target.value); // Parse the value to an integer const newValue = parseInt(e.target.value); // Parse the value to an integer
@@ -31,8 +33,22 @@ const InputRange: React.FC<InputToggleProps> = ({
} }
} }
useEffect(() => { useEffect(() => {
setRangeValue(value); value && setRangeValue(value);
}, [value]); }, [value]);
function handlePointerUp(e: React.PointerEvent<HTMLInputElement>) {
const newValue = parseInt(e.currentTarget.value, 10); // Parse value correctly
if (onPointerUp) {
onPointerUp(newValue); // Call the callback function if it exists
}
}
function handlekey(e: React.KeyboardEvent<HTMLInputElement>) {
const newValue = parseInt(e.currentTarget.value, 10); // Parse value correctly
if (onPointerUp) {
onPointerUp(newValue); // Call the callback function if it exists
}
}
return ( return (
<div className="input-range-container"> <div className="input-range-container">
@@ -52,6 +68,7 @@ const InputRange: React.FC<InputToggleProps> = ({
onChange={handleChange} onChange={handleChange}
disabled={disabled} disabled={disabled}
value={rangeValue} value={rangeValue}
onPointerUp={handlePointerUp}
/> />
<input <input
type="number" type="number"
@@ -61,6 +78,12 @@ const InputRange: React.FC<InputToggleProps> = ({
value={rangeValue} value={rangeValue}
onChange={handleChange} onChange={handleChange}
disabled={disabled} disabled={disabled}
onKeyUp={(e) => {
if (e.key === "ArrowUp" || e.key === "ArrowDown") {
console.log("e.key: ", e.key);
handlekey(e);
}
}}
/> />
</div> </div>
</div> </div>

View File

@@ -38,6 +38,7 @@ const Card: React.FC<CardProps> = ({
description, description,
onSelectCard, onSelectCard,
}) => { }) => {
console.log('description: ', description);
const handleCardSelect = () => { const handleCardSelect = () => {
onSelectCard({ assetName, uploadedOn, price, rating, views, description }); onSelectCard({ assetName, uploadedOn, price, rating, views, description });
}; };

View File

@@ -57,7 +57,6 @@ const FilterSearch: React.FC<ModelsProps> = ({
const filteredModel = filteredModels?.filter((model) => const filteredModel = filteredModels?.filter((model) =>
model.filename.toLowerCase().includes(val.toLowerCase()) model.filename.toLowerCase().includes(val.toLowerCase())
); );
setModels(filteredModel); setModels(filteredModel);
}; };

View File

@@ -30,6 +30,8 @@ import {
useWalls, useWalls,
useToolMode, useToolMode,
useRefTextUpdate, useRefTextUpdate,
useRenderDistance,
useLimitDistance,
} from "../../../store/store"; } from "../../../store/store";
////////// 3D Function Imports ////////// ////////// 3D Function Imports //////////
@@ -117,6 +119,8 @@ export default function World() {
const { roofVisibility, setRoofVisibility } = useRoofVisibility(); const { roofVisibility, setRoofVisibility } = useRoofVisibility();
const { wallVisibility, setWallVisibility } = useWallVisibility(); const { wallVisibility, setWallVisibility } = useWallVisibility();
const { shadows, setShadows } = useShadows(); const { shadows, setShadows } = useShadows();
const { renderDistance, setRenderDistance } = useRenderDistance();
const { limitDistance, setLimitDistance } = useLimitDistance();
const { updateScene, setUpdateScene } = useUpdateScene(); const { updateScene, setUpdateScene } = useUpdateScene();
const { walls, setWalls } = useWalls(); const { walls, setWalls } = useWalls();
const { refTextupdate, setRefTextUpdate } = useRefTextUpdate(); const { refTextupdate, setRefTextUpdate } = useRefTextUpdate();
@@ -200,6 +204,8 @@ export default function World() {
setRoofVisibility(visibility.roofVisibility); setRoofVisibility(visibility.roofVisibility);
setWallVisibility(visibility.wallVisibility); setWallVisibility(visibility.wallVisibility);
setShadows(visibility.shadowVisibility); setShadows(visibility.shadowVisibility);
setRenderDistance(visibility.renderDistance);
setLimitDistance(visibility.limitDistance);
} }
} }
fetchVisibility(); fetchVisibility();

View File

@@ -1,32 +1,43 @@
import { setEnvironment } from './setEnvironment'; import { setEnvironment } from "./setEnvironment";
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
export const findEnvironment = async (organization: string, userId: string) => { export const findEnvironment = async (organization: string, userId: string) => {
try { try {
const response = await fetch(`${url_Backend_dwinzo}/api/v1/findEnvironments/${organization}/${userId}`, { const response = await fetch(
method: "GET", `${url_Backend_dwinzo}/api/v1/findEnvironments/${organization}/${userId}`,
headers: { {
"Content-Type": "application/json", method: "GET",
}, headers: {
}); "Content-Type": "application/json",
},
}
);
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to get wall and roof visibility"); throw new Error("Failed to get wall and roof visibility");
}
const result = await response.json();
if (result === "user not found") {
const userpos = setEnvironment(organization, userId, false, false, false);
return userpos;
} else {
return result;
}
} catch (error) {
if (error instanceof Error) {
throw new Error(error.message);
} else {
throw new Error("An unknown error occurred");
}
} }
};
const result = await response.json();
if (result === "user not found") {
const userpos = setEnvironment(
organization,
userId,
false,
false,
false,
0,
true
);
return userpos;
} else {
return result;
}
} catch (error) {
if (error instanceof Error) {
throw new Error(error.message);
} else {
throw new Error("An unknown error occurred");
}
}
};

View File

@@ -1,26 +1,45 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
export const setEnvironment = async (organization: string, userId: string, wallVisibility: Boolean, roofVisibility: Boolean, shadowVisibility: Boolean) => { export const setEnvironment = async (
try { organization: string,
const response = await fetch(`${url_Backend_dwinzo}/api/v1/setEvironments`, { userId: string,
method: "POST", wallVisibility: Boolean,
headers: { roofVisibility: Boolean,
"Content-Type": "application/json", shadowVisibility: Boolean,
}, renderDistance: number,
body: JSON.stringify({ organization, userId, wallVisibility, roofVisibility, shadowVisibility }), limitDistance: boolean
}); ) => {
try {
const response = await fetch(
`${url_Backend_dwinzo}/api/v1/setEvironments`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
organization,
userId,
wallVisibility,
roofVisibility,
shadowVisibility,
renderDistance,
limitDistance,
}),
}
);
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to set wall and roof visibility"); throw new Error("Failed to set wall and roof visibility");
}
const result = await response.json();
return result;
} catch (error) {
if (error instanceof Error) {
throw new Error(error.message);
} else {
throw new Error("An unknown error occurred");
}
} }
};
const result = await response.json();
return result;
} catch (error) {
if (error instanceof Error) {
throw new Error(error.message);
} else {
throw new Error("An unknown error occurred");
}
}
};

View File

@@ -6,8 +6,8 @@ export const fetchAssets = async () => {
throw new Error("Network response was not ok"); throw new Error("Network response was not ok");
} }
const result = await response.json(); const result = await response.json();
const last10Assets = result.slice(-10); // const last10Assets = result.slice(-10);
console.log('last10Assets: ', last10Assets); // console.log('last10Assets: ', last10Assets);
return result; return result;
} catch (error) { } catch (error) {
console.log("error: ", error); console.log("error: ", error);

View File

@@ -208,7 +208,9 @@ export const useActiveLayer = create<any>((set: any) => ({
interface RefTextUpdateState { interface RefTextUpdateState {
refTextupdate: number; refTextupdate: number;
setRefTextUpdate: (callback: (currentValue: number) => number | number) => void; setRefTextUpdate: (
callback: (currentValue: number) => number | number
) => void;
} }
export const useRefTextUpdate = create<RefTextUpdateState>((set) => ({ export const useRefTextUpdate = create<RefTextUpdateState>((set) => ({
@@ -216,7 +218,9 @@ export const useRefTextUpdate = create<RefTextUpdateState>((set) => ({
setRefTextUpdate: (callback) => setRefTextUpdate: (callback) =>
set((state) => ({ set((state) => ({
refTextupdate: refTextupdate:
typeof callback === "function" ? callback(state.refTextupdate) : callback, typeof callback === "function"
? callback(state.refTextupdate)
: callback,
})), })),
})); }));
@@ -251,7 +255,7 @@ export const useAzimuth = create<any>((set: any) => ({
})); }));
export const useRenderDistance = create<any>((set: any) => ({ export const useRenderDistance = create<any>((set: any) => ({
renderDistance: 50, renderDistance: 40,
setRenderDistance: (x: any) => set({ renderDistance: x }), setRenderDistance: (x: any) => set({ renderDistance: x }),
})); }));
@@ -375,3 +379,7 @@ export const useWidgetSubOption = create<any>((set: any) => ({
widgetSubOption: "2D", widgetSubOption: "2D",
setWidgetSubOption: (x: any) => set({ widgetSubOption: x }), setWidgetSubOption: (x: any) => set({ widgetSubOption: x }),
})); }));
export const useLimitDistance = create<any>((set: any) => ({
limitDistance: true,
setLimitDistance: (x: any) => set({ limitDistance: x }),
}));

View File

@@ -558,7 +558,7 @@ input {
} }
.input-value { .input-value {
width: 40px; width: 42px;
text-align: center; text-align: center;
} }
} }

View File

@@ -114,7 +114,9 @@
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
gap: 6px; gap: 6px;
.assets-container {
height: auto;
}
.icon { .icon {
position: absolute; position: absolute;
top: 12px; top: 12px;

View File

@@ -936,6 +936,7 @@
padding: 0 6px; padding: 0 6px;
.assets-wrapper { .assets-wrapper {
width: 100%;
position: relative; position: relative;
margin: 8px 10px; margin: 8px 10px;
@@ -1051,3 +1052,51 @@
} }
} }
} }
.assets-container {
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
height: 100%;
gap: 3px;
padding: 10px 0;
.assets {
width: 117px;
height: 95px;
border-radius: 3.59px;
background-color: var(--background-color-gray);
padding: 8px;
padding-top: 12px;
font-weight: $medium-weight;
position: relative;
overflow: hidden;
.asset-name {
position: relative;
z-index: 3;
font-size: var(--font-size-regular);
}
.asset-image {
height: 100%;
width: 100%;
position: absolute;
// top: 50%;
// right: 5px;
// transform: translate(0, -50%);
top: 0;
left: 0;
z-index: 2;
}
}
}
.assets-result {
width: 100%;
height: 100%;
margin: 8px 10px;
.assets-wrapper {
margin: 0;
}
}