Merge remote-tracking branch 'origin/api-integration' into v3

This commit is contained in:
Jerald-Golden-B 2025-06-10 11:34:37 +05:30
commit f586354fb4
20 changed files with 155 additions and 66 deletions

View File

@ -1,4 +1,4 @@
import React from "react"; import React, { useEffect, useState } from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Dashboard from "./pages/Dashboard"; import Dashboard from "./pages/Dashboard";
import Project from "./pages/Project"; import Project from "./pages/Project";
@ -7,6 +7,7 @@ import "./styles/main.scss";
import { LoggerProvider } from "./components/ui/log/LoggerContext"; import { LoggerProvider } from "./components/ui/log/LoggerContext";
const App: React.FC = () => { const App: React.FC = () => {
return ( return (
<LoggerProvider> <LoggerProvider>
<Router> <Router>

View File

@ -13,6 +13,7 @@ interface DashBoardCardProps {
thumbnail: any; thumbnail: any;
projectId: string; projectId: string;
createdAt?: string; createdAt?: string;
isViewed?: string;
handleDeleteProject?: (projectId: string) => Promise<void>; handleDeleteProject?: (projectId: string) => Promise<void>;
handleTrashDeleteProject?: (projectId: string) => Promise<void>; handleTrashDeleteProject?: (projectId: string) => Promise<void>;
handleRestoreProject?: (projectId: string) => Promise<void>; handleRestoreProject?: (projectId: string) => Promise<void>;
@ -215,6 +216,7 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
<div className="project-data"> <div className="project-data">
{active && active == "trash" ? `Trashed by you` : `Edited `}{" "} {active && active == "trash" ? `Trashed by you` : `Edited `}{" "}
{getRelativeTime(createdAt)} {getRelativeTime(createdAt)}
</div> </div>
)} )}
</div> </div>

View File

@ -16,6 +16,7 @@ interface Project {
createdBy: string; createdBy: string;
projectUuid?: string; projectUuid?: string;
createdAt: string; createdAt: string;
isViewed?: string
} }
interface RecentProjectsData { interface RecentProjectsData {
@ -115,6 +116,7 @@ const DashboardHome: React.FC = () => {
const renderProjects = () => { const renderProjects = () => {
const projectList = recentProjects[Object.keys(recentProjects)[0]]; const projectList = recentProjects[Object.keys(recentProjects)[0]];
console.log('projectList: ', projectList);
if (!projectList?.length) { if (!projectList?.length) {
return <div className="empty-state">No recent projects found</div>; return <div className="empty-state">No recent projects found</div>;
} }
@ -127,7 +129,7 @@ const DashboardHome: React.FC = () => {
projectName={project.projectName} projectName={project.projectName}
thumbnail={project.thumbnail} thumbnail={project.thumbnail}
projectId={project._id} projectId={project._id}
createdAt={project.createdAt} createdAt={project.isViewed}
handleDeleteProject={handleDeleteProject} handleDeleteProject={handleDeleteProject}
handleDuplicateRecentProject={handleDuplicateRecentProject} handleDuplicateRecentProject={handleDuplicateRecentProject}
setRecentDuplicateData={setRecentDuplicateData} setRecentDuplicateData={setRecentDuplicateData}

View File

@ -12,6 +12,7 @@ interface Project {
createdBy: string; createdBy: string;
projectUuid?: string; projectUuid?: string;
createdAt: string; createdAt: string;
isViewed?: string
} }
interface ProjectsData { interface ProjectsData {

View File

@ -2,17 +2,18 @@ import React from "react";
import { ToggleSidebarIcon } from "../../icons/HeaderIcons"; import { ToggleSidebarIcon } from "../../icons/HeaderIcons";
import { LogoIcon } from "../../icons/Logo"; import { LogoIcon } from "../../icons/Logo";
import FileMenu from "../../ui/FileMenu"; import FileMenu from "../../ui/FileMenu";
import {useToggleStore} from "../../../store/useUIToggleStore"; import { useToggleStore } from "../../../store/useUIToggleStore";
import useModuleStore from "../../../store/useModuleStore"; import useModuleStore from "../../../store/useModuleStore";
import { useNavigate } from "react-router-dom";
const Header: React.FC = () => { const Header: React.FC = () => {
const { toggleUILeft, toggleUIRight, setToggleUI } = useToggleStore(); const { toggleUILeft, toggleUIRight, setToggleUI } = useToggleStore();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const navigate = useNavigate();
return ( return (
<div className="header-container"> <div className="header-container">
<div className="header-content"> <div className="header-content">
<div className="logo-container"> <div className="logo-container" onClick={() => navigate("/Dashboard")}>
<LogoIcon /> <LogoIcon />
</div> </div>
<div className="header-title"> <div className="header-title">
@ -34,7 +35,7 @@ const Header: React.FC = () => {
</div> </div>
<ToggleSidebarIcon /> <ToggleSidebarIcon />
</button> </button>
</div> </div >
); );
}; };

View File

@ -26,9 +26,7 @@ function AisleInstances() {
return points; return points;
}, [aisles]); }, [aisles]);
useEffect(() => {
// console.log('aisles: ', aisles);
}, [aisles]);
return ( return (
<> <>

View File

@ -73,6 +73,7 @@ function ArcAisle({ aisle }: { readonly aisle: Aisle }) {
return ( return (
<group <group
name='Arc-Aisle' name='Arc-Aisle'
uuid={aisle.aisleUuid}
ref={aisleRef} ref={aisleRef}
position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]}
rotation={[Math.PI / 2, 0, 0]} rotation={[Math.PI / 2, 0, 0]}

View File

@ -60,6 +60,7 @@ function ArrowAisle({ aisle }: { readonly aisle: Aisle }) {
return ( return (
<group <group
name='Arrow-Aisle' name='Arrow-Aisle'
uuid={aisle.aisleUuid}
ref={aisleRef} ref={aisleRef}
position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]}
rotation={[Math.PI / 2, 0, 0]} rotation={[Math.PI / 2, 0, 0]}

View File

@ -63,6 +63,7 @@ function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) {
return ( return (
<group <group
name='Arrows-Aisle' name='Arrows-Aisle'
uuid={aisle.aisleUuid}
ref={aisleRef} ref={aisleRef}
position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]}
rotation={[Math.PI / 2, 0, 0]} rotation={[Math.PI / 2, 0, 0]}

View File

@ -23,17 +23,16 @@ function CircleAisle({ aisle }: { readonly aisle: Aisle }) {
const outerRadius = middleRadius + width / 2; const outerRadius = middleRadius + width / 2;
const shape = new THREE.Shape(); const shape = new THREE.Shape();
shape.absarc(0, 0, outerRadius, 0, Math.PI * 2, false); shape.absarc(center.x, center.z, outerRadius, 0, Math.PI * 2, false);
if (innerRadius > 0) { if (innerRadius > 0) {
const hole = new THREE.Path(); const hole = new THREE.Path();
hole.absarc(0, 0, innerRadius, 0, Math.PI * 2, true); hole.absarc(center.x, center.z, innerRadius, 0, Math.PI * 2, true);
shape.holes.push(hole); shape.holes.push(hole);
} }
return { return {
shape, shape,
position: center,
rotationY: 0 rotationY: 0
}; };
}, [aisle]); }, [aisle]);
@ -49,6 +48,7 @@ function CircleAisle({ aisle }: { readonly aisle: Aisle }) {
return ( return (
<group <group
name='Circle-Aisle' name='Circle-Aisle'
uuid={aisle.aisleUuid}
ref={aisleRef} ref={aisleRef}
position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]}
rotation={[Math.PI / 2, 0, 0]} rotation={[Math.PI / 2, 0, 0]}
@ -58,23 +58,21 @@ function CircleAisle({ aisle }: { readonly aisle: Aisle }) {
setSelectedAisle(null); setSelectedAisle(null);
}} }}
> >
<group position={[circle.position.x, circle.position.z, 0]}> <Extrude
<Extrude args={[circle.shape, {
args={[circle.shape, { depth: 0.01,
depth: 0.01, bevelEnabled: false,
bevelEnabled: false, steps: 1,
steps: 1, curveSegments: 64
curveSegments: 64 }]}
}]} receiveShadow
receiveShadow castShadow
castShadow >
> <meshStandardMaterial
<meshStandardMaterial color={aisle.type.aisleColor || '#ffffff'}
color={aisle.type.aisleColor || '#ffffff'} side={THREE.DoubleSide}
side={THREE.DoubleSide} />
/> </Extrude>
</Extrude>
</group>
</group> </group>
); );
} }

View File

@ -61,6 +61,7 @@ function DashedAisle({ aisle }: { readonly aisle: Aisle }) {
return ( return (
<group <group
name='Dashed-Aisle' name='Dashed-Aisle'
uuid={aisle.aisleUuid}
ref={aisleRef} ref={aisleRef}
position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]}
rotation={[Math.PI / 2, 0, 0]} rotation={[Math.PI / 2, 0, 0]}

View File

@ -48,6 +48,7 @@ function DottedAisle({ aisle }: { readonly aisle: Aisle }) {
return ( return (
<group <group
name='Dotted-Aisle' name='Dotted-Aisle'
uuid={aisle.aisleUuid}
ref={aisleRef} ref={aisleRef}
position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]}
rotation={[Math.PI / 2, 0, 0]} rotation={[Math.PI / 2, 0, 0]}

View File

@ -95,6 +95,7 @@ function JunctionAisle({ aisle }: { readonly aisle: Aisle }) {
return ( return (
<group <group
name='Junction-Aisle' name='Junction-Aisle'
uuid={aisle.aisleUuid}
ref={aisleRef} ref={aisleRef}
position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]}
rotation={[Math.PI / 2, 0, 0]} rotation={[Math.PI / 2, 0, 0]}

View File

@ -45,6 +45,7 @@ function SolidAisle({ aisle }: { readonly aisle: Aisle }) {
return ( return (
<group <group
name='Solid-Aisle' name='Solid-Aisle'
uuid={aisle.aisleUuid}
ref={aisleRef} ref={aisleRef}
position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]}
rotation={[Math.PI / 2, 0, 0]} rotation={[Math.PI / 2, 0, 0]}

View File

@ -550,17 +550,16 @@ function CircleAisle({ aisle }: { readonly aisle: Aisle }) {
const outerRadius = middleRadius + width / 2; const outerRadius = middleRadius + width / 2;
const shape = new THREE.Shape(); const shape = new THREE.Shape();
shape.absarc(0, 0, outerRadius, 0, Math.PI * 2, false); shape.absarc(center.x, center.z, outerRadius, 0, Math.PI * 2, false);
if (innerRadius > 0) { if (innerRadius > 0) {
const hole = new THREE.Path(); const hole = new THREE.Path();
hole.absarc(0, 0, innerRadius, 0, Math.PI * 2, true); hole.absarc(center.x, center.z, innerRadius, 0, Math.PI * 2, true);
shape.holes.push(hole); shape.holes.push(hole);
} }
return { return {
shape, shape,
position: center,
rotationY: 0 rotationY: 0
}; };
}, [aisle]); }, [aisle]);
@ -572,23 +571,21 @@ function CircleAisle({ aisle }: { readonly aisle: Aisle }) {
position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]}
rotation={[Math.PI / 2, 0, 0]} rotation={[Math.PI / 2, 0, 0]}
> >
<group position={[circle.position.x, circle.position.z, 0]}> <Extrude
<Extrude args={[circle.shape, {
args={[circle.shape, { depth: 0.01,
depth: 0.01, bevelEnabled: false,
bevelEnabled: false, steps: 1,
steps: 1, curveSegments: 64
curveSegments: 64 }]}
}]} receiveShadow
receiveShadow castShadow
castShadow >
> <meshStandardMaterial
<meshStandardMaterial color={aisle.type.aisleColor || '#ffffff'}
color={aisle.type.aisleColor || '#ffffff'} side={THREE.DoubleSide}
side={THREE.DoubleSide} />
/> </Extrude>
</Extrude>
</group>
</group> </group>
); );
} }

View File

@ -13,7 +13,6 @@ function AislesGroup() {
if (projectId) { if (projectId) {
const aisles = await getAisleApi(projectId); const aisles = await getAisleApi(projectId);
setAisles(aisles); setAisles(aisles);
// console.log('aisles: ', aisles);
} }
} }
fetchAisle() fetchAisle()

View File

@ -32,6 +32,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
useEffect(() => { useEffect(() => {
if (currentPhase === 'stationed-pickup' && path.length > 0) { if (currentPhase === 'stationed-pickup' && path.length > 0) {
console.log('path: ', path);
setCurrentPath(path); setCurrentPath(path);
setObjectRotation(agvDetail.point.action?.pickUpPoint?.rotation) setObjectRotation(agvDetail.point.action?.pickUpPoint?.rotation)
} else if (currentPhase === 'pickup-drop' && path.length > 0) { } else if (currentPhase === 'pickup-drop' && path.length > 0) {

View File

@ -29,12 +29,15 @@ export default function NavMeshDetails({
} }
const meshes = groupRef?.current?.children as THREE.Mesh[]; const meshes = groupRef?.current?.children as THREE.Mesh[];
const [positions, indices] = getPositionsAndIndices(meshes); const [positions, indices] = getPositionsAndIndices(meshes);
const cellSize = 0.2; // const cellSize = 0.2;
// const cellHeight = 0.7;
// const walkableRadius = 0.5;
const cellSize = 0.3;
const cellHeight = 0.7; const cellHeight = 0.7;
const walkableRadius = 0.5; const walkableRadius = 0.7;
const { success, navMesh } = generateSoloNavMesh(positions, indices, { const { success, navMesh } = generateSoloNavMesh(positions, indices, {
cs: cellSize, cs: cellSize,
ch: cellHeight, ch: cellHeight,
@ -56,7 +59,7 @@ export default function NavMeshDetails({
// scene.add(debugDrawer); // scene.add(debugDrawer);
} catch (error) { } catch (error) {
echo.error("Failed to initialize navigation") echo.error("Failed to initialize navigation")
} }
}; };
initializeNavigation(); initializeNavigation();

View File

@ -3,6 +3,9 @@ import { useEffect } from "react";
import * as turf from "@turf/turf"; import * as turf from "@turf/turf";
import * as Types from "../../../../types/world/worldTypes"; import * as Types from "../../../../types/world/worldTypes";
import arrayLinesToObject from "../../../builder/geomentries/lines/lineConvertions/arrayLinesToObject"; import arrayLinesToObject from "../../../builder/geomentries/lines/lineConvertions/arrayLinesToObject";
import { useAisleStore } from "../../../../store/builder/useAisleStore";
import { useThree } from "@react-three/fiber";
import { clone } from "chart.js/dist/helpers/helpers.core";
interface PolygonGeneratorProps { interface PolygonGeneratorProps {
groupRef: React.MutableRefObject<THREE.Group | null>; groupRef: React.MutableRefObject<THREE.Group | null>;
@ -13,22 +16,58 @@ export default function PolygonGenerator({
groupRef, groupRef,
lines, lines,
}: PolygonGeneratorProps) { }: PolygonGeneratorProps) {
const { aisles } = useAisleStore();
const { scene } = useThree();
useEffect(() => { useEffect(() => {
let allLines = arrayLinesToObject(lines.current); let allLines = arrayLinesToObject(lines.current);
const wallLines = allLines?.filter((line) => line?.type === "WallLine"); const wallLines = allLines?.filter((line) => line?.type === "WallLine");
const aisleLines = allLines?.filter((line) => line?.type === "AisleLine") const result = aisles
.filter(
(aisle) =>
aisle.type.aisleType === "dotted-aisle" ||
aisle.type.aisleType === "solid-aisle" ||
aisle.type.aisleType === "dashed-aisle" ||
aisle.type.aisleType === "arc-aisle"
)
.map((aisle) =>
aisle.points.map((point) => ({
position: [point.position[0], point.position[2]],
uuid: point.pointUuid,
}))
);
const arcAndCircleResult = aisles
.filter(
(aisle) =>
aisle.type.aisleType === "circle-aisle" ||
aisle.type.aisleType === "arc-aisle"
)
arcAndCircleResult.forEach((arc) => {
const arcGroup = scene.getObjectByProperty("uuid", arc.aisleUuid);
if (!arcGroup) return;
const cloned = arcGroup?.clone();
cloned.position.set(cloned.position.x, cloned.position.y + 5, cloned.position.z);
cloned?.traverse((child) => {
if (child instanceof THREE.Mesh && child.geometry instanceof THREE.ExtrudeGeometry) {
const extrudeGeometry = child.geometry as THREE.ExtrudeGeometry;
extrudeGeometry.scale(1, 1, 500);
child.geometry = extrudeGeometry;
child.position.set(cloned.position.x, cloned.position.y + 0.1, cloned.position.z)
child.rotateX(Math.PI / 2);
child.name = "agv-arc-collider"
groupRef.current?.add(child)
}
});
});
const wallPoints = wallLines const wallPoints = wallLines
.map((pair) => pair?.line.map((vals) => vals.position)) .map((pair) => pair?.line.map((vals) => vals.position))
.filter((wall): wall is THREE.Vector3[] => !!wall); .filter((wall): wall is THREE.Vector3[] => !!wall);
const result = aisleLines.map((pair) =>
pair?.line.map((point) => ({
position: [point.position.x, point.position.z],
uuid: point.uuid,
}))
);
if (!result || result.some((line) => !line)) { if (!result || result.some((line) => !line)) {
return; return;
@ -80,7 +119,7 @@ export default function PolygonGenerator({
}); });
} }
}, [lines.current]); }, [lines.current, aisles, scene]);
const renderWallGeometry = (walls: THREE.Vector3[][]) => { const renderWallGeometry = (walls: THREE.Vector3[][]) => {
walls.forEach((wall) => { walls.forEach((wall) => {

View File

@ -10,6 +10,8 @@ import {
import { signInApi } from "../services/factoryBuilder/signInSignUp/signInApi"; import { signInApi } from "../services/factoryBuilder/signInSignUp/signInApi";
import { signUpApi } from "../services/factoryBuilder/signInSignUp/signUpApi"; import { signUpApi } from "../services/factoryBuilder/signInSignUp/signUpApi";
import FingerprintJS from "@fingerprintjs/fingerprintjs"; import FingerprintJS from "@fingerprintjs/fingerprintjs";
import { recentlyViewed } from "../services/dashboard/recentlyViewed";
import { getUserData } from "../components/Dashboard/functions/getUserData";
const UserAuth: React.FC = () => { const UserAuth: React.FC = () => {
const [email, setEmail] = useState(""); const [email, setEmail] = useState("");
@ -34,7 +36,28 @@ const UserAuth: React.FC = () => {
initializeFingerprint(); initializeFingerprint();
}, []) }, [])
const { userId, organization } = getUserData();
const [navigateToProject, setNavigateToProject] = useState<any>();
console.log('navigateToProject: ', navigateToProject);
const fetchRecentProjects = async () => {
try {
const projects = await recentlyViewed(organization, userId);
console.log("RecentlyViewed: ", Object.values(projects.RecentlyViewed)[0]
);
if (Object.values(projects.RecentlyViewed).length > 0) {
const firstId = (Object.values(projects?.RecentlyViewed || {})[0] as any)?._id;
setNavigateToProject(firstId)
}
} catch (error) {
console.error("Error fetching recent projects:", error);
}
};
useEffect(() => {
fetchRecentProjects();
}, [navigateToProject]);
const handleLogin = async (e: FormEvent<HTMLFormElement>) => { const handleLogin = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
const organization = email.split("@")[1].split(".")[0]; const organization = email.split("@")[1].split(".")[0];
@ -51,11 +74,28 @@ const UserAuth: React.FC = () => {
localStorage.setItem("token", res.message.token); localStorage.setItem("token", res.message.token);
localStorage.setItem("refreshToken", res.message.refreshToken); localStorage.setItem("refreshToken", res.message.refreshToken);
if (res.message.isShare) { try {
setLoadingProgress(1); const projects = await recentlyViewed(organization, res.message.userId);
// navigate("/Project"); console.log("RecentlyViewed: ", Object.values(projects.RecentlyViewed)[0]
navigate("/Dashboard"); );
if (Object.values(projects.RecentlyViewed).length > 0) {
const firstId = (Object.values(projects?.RecentlyViewed || {})[0] as any)?._id;
setLoadingProgress(1)
navigate(`/${firstId}`)
} else {
if (res.message.isShare) {
setLoadingProgress(1);
// navigate("/Project");
navigate("/Dashboard");
}
}
} catch (error) {
console.error("Error fetching recent projects:", error);
} }
} else if (res.message === "User Not Found!!! Kindly signup...") { } else if (res.message === "User Not Found!!! Kindly signup...") {
setError("Account not found"); setError("Account not found");
} else if (res.message === "Already LoggedIn on another browser....Please logout!!!") { } else if (res.message === "Already LoggedIn on another browser....Please logout!!!") {