diff --git a/app/package-lock.json b/app/package-lock.json
index d3aa21e..f627d25 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -4133,25 +4133,6 @@
"url": "https://github.com/sponsors/gregberge"
}
},
- "node_modules/@testing-library/dom": {
- "version": "10.4.0",
- "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz",
- "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==",
- "peer": true,
- "dependencies": {
- "@babel/code-frame": "^7.10.4",
- "@babel/runtime": "^7.12.5",
- "@types/aria-query": "^5.0.1",
- "aria-query": "5.3.0",
- "chalk": "^4.1.0",
- "dom-accessibility-api": "^0.5.9",
- "lz-string": "^1.5.0",
- "pretty-format": "^27.0.2"
- },
- "engines": {
- "node": ">=18"
- }
- },
"node_modules/@testing-library/jest-dom": {
"version": "5.17.0",
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz",
diff --git a/app/src/components/layout/sidebarLeft/visualization/Templates.tsx b/app/src/components/layout/sidebarLeft/visualization/Templates.tsx
index 1f1e61c..ef710f7 100644
--- a/app/src/components/layout/sidebarLeft/visualization/Templates.tsx
+++ b/app/src/components/layout/sidebarLeft/visualization/Templates.tsx
@@ -5,7 +5,6 @@ const Templates = () => {
const { templates, removeTemplate } = useTemplateStore();
const { setSelectedZone } = useSelectedZoneStore();
- console.log("templates: ", templates);
const handleDeleteTemplate = (id: string) => {
removeTemplate(id);
};
diff --git a/app/src/components/layout/sidebarRight/Header.tsx b/app/src/components/layout/sidebarRight/Header.tsx
index b80fd53..b4983c6 100644
--- a/app/src/components/layout/sidebarRight/Header.tsx
+++ b/app/src/components/layout/sidebarRight/Header.tsx
@@ -1,14 +1,17 @@
-import React from "react";
+import React, { useEffect } from "react";
import { AppDockIcon } from "../../icons/HeaderIcons";
-import orgImg from "../../../assets/orgTemp.png"
+import orgImg from "../../../assets/orgTemp.png";
+import { useActiveUsers } from "../../../store/store";
+import { getAvatarColor } from "../../../modules/collaboration/users/functions/getAvatarColor";
+import { ActiveUser } from "../../../types/users";
const Header: React.FC = () => {
- const guestUsers = [
- { value: "Nazria", color: "#43C06D" },
- { value: "Name1", color: "#0050EB" },
- { value: "Abigail", color: "#FF6600" },
- { value: "Jack", color: "#488EF6" },
- ]; // Example guest users array
+ const { activeUsers } = useActiveUsers();
+ const userName = localStorage.getItem("userName") || "Anonymous";
+
+ const guestUsers: ActiveUser[] = activeUsers.filter(
+ (user: ActiveUser) => user.userName !== userName
+ );
return (
@@ -25,18 +28,23 @@ const Header: React.FC = () => {
+{guestUsers.length - 3}
)}
{guestUsers.slice(0, 3).map((user, index) => (
-
- {user.value[0]}
-
+ <>
+
+ {user.userName[0]}
+
+ >
))}
-
- V
+
+ {userName[0]}

diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx
index f2f6695..4821772 100644
--- a/app/src/components/layout/sidebarRight/SideBarRight.tsx
+++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx
@@ -14,7 +14,10 @@ import ConveyorMechanics from "./mechanics/ConveyorMechanics";
import Visualization from "./visualization/Visualization";
import Analysis from "./analysis/Analysis";
import Simulations from "./simulation/Simulations";
-import { useSelectedActionSphere } from "../../../store/store";
+import {
+ useSelectedActionSphere,
+ useselectedFloorItem,
+} from "../../../store/store";
import GlobalProperties from "./properties/GlobalProperties";
import AsstePropertiies from "./properties/AssetProperties";
import ZoneProperties from "./properties/ZoneProperties";
@@ -25,6 +28,7 @@ const SideBarRight: React.FC = () => {
const { toggleUI } = useToggleStore();
const { selectedActionSphere } = useSelectedActionSphere();
const { subModule, setSubModule } = useSubModuleStore();
+ const { selectedFloorItem } = useselectedFloorItem();
// Reset activeList whenever activeModule changes
useEffect(() => {
if (activeModule !== "simulation") setSubModule("properties");
@@ -38,8 +42,9 @@ const SideBarRight: React.FC = () => {
{/* {activeModule === "builder" && ( */}
setSubModule("properties")}
>
@@ -48,22 +53,25 @@ const SideBarRight: React.FC = () => {
{activeModule === "simulation" && (
<>
setSubModule("mechanics")}
>
setSubModule("simulations")}
>
setSubModule("analysis")}
>
@@ -75,12 +83,21 @@ const SideBarRight: React.FC = () => {
{/* process builder */}
{toggleUI &&
subModule === "properties" &&
- activeModule !== "visualization" && (
+ activeModule !== "visualization" &&
+ !selectedFloorItem && (
+ )}
+ {toggleUI &&
+ subModule === "properties" &&
+ activeModule !== "visualization" &&
+ selectedFloorItem && (
+
)}
@@ -89,9 +106,7 @@ const SideBarRight: React.FC = () => {
activeModule === "builder" && (
)}
@@ -99,20 +114,24 @@ const SideBarRight: React.FC = () => {
{toggleUI && activeModule === "simulation" && (
<>
- {subModule === "mechanics" && selectedActionSphere && selectedActionSphere.path.type === "Conveyor" && (
-
-
-
+ {subModule === "mechanics" &&
+ selectedActionSphere &&
+ selectedActionSphere.path.type === "Conveyor" && (
+
-
- )}
- {subModule === "mechanics" && selectedActionSphere && selectedActionSphere.path.type === "Vehicle" && (
-
-
-
+ )}
+ {subModule === "mechanics" &&
+ selectedActionSphere &&
+ selectedActionSphere.path.type === "Vehicle" && (
+
-
- )}
+ )}
{subModule === "mechanics" && !selectedActionSphere && (
diff --git a/app/src/components/layout/sidebarRight/customInput/PositionInputs.tsx b/app/src/components/layout/sidebarRight/customInput/PositionInputs.tsx
index b65d782..881e225 100644
--- a/app/src/components/layout/sidebarRight/customInput/PositionInputs.tsx
+++ b/app/src/components/layout/sidebarRight/customInput/PositionInputs.tsx
@@ -4,12 +4,16 @@ interface PositionInputProps {
onChange: (value: string) => void; // Callback for value change
placeholder?: string; // Optional placeholder
type?: string; // Input type (e.g., text, number, email)
+ value1?: number;
+ value2?: number;
}
const PositionInput: React.FC
= ({
onChange,
placeholder = "Enter value", // Default placeholder
type = "number", // Default type
+ value1 = "number",
+ value2 = "number",
}) => {
return (
@@ -22,6 +26,7 @@ const PositionInput: React.FC
= ({
type={type}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
+ value={value2}
/>
@@ -31,6 +36,7 @@ const PositionInput: React.FC
= ({
type={type}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
+ value={value1}
/>
diff --git a/app/src/components/layout/sidebarRight/customInput/RotationInput.tsx b/app/src/components/layout/sidebarRight/customInput/RotationInput.tsx
index 3ab01a4..962e967 100644
--- a/app/src/components/layout/sidebarRight/customInput/RotationInput.tsx
+++ b/app/src/components/layout/sidebarRight/customInput/RotationInput.tsx
@@ -4,17 +4,19 @@ interface RotationInputProps {
onChange: (value: string) => void; // Callback for value change
placeholder?: string; // Optional placeholder
type?: string; // Input type (e.g., text, number, email)
+ value?: number;
}
const RotationInput: React.FC
= ({
onChange,
placeholder = "Enter value", // Default placeholder
type = "number", // Default type
+ value = "number",
}) => {
return (
Rotation
-
+
diff --git a/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx b/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx
index 8309024..c47fd81 100644
--- a/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx
+++ b/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx
@@ -1,9 +1,11 @@
-import React, { useState } from "react";
+import React, { useEffect, useState } from "react";
import InputToggle from "../../../ui/inputs/InputToggle";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import { RemoveIcon } from "../../../icons/ExportCommonIcons";
import PositionInput from "../customInput/PositionInputs";
import RotationInput from "../customInput/RotationInput";
+import { useselectedFloorItem } from "../../../../store/store";
+import * as THREE from "three";
interface UserData {
id: number; // Unique identifier for the user data
@@ -14,7 +16,13 @@ interface UserData {
const AssetProperties: React.FC = () => {
const [userData, setUserData] = useState
([]); // State to track user data
const [nextId, setNextId] = useState(1); // Unique ID for new entries
+ const { selectedFloorItem } = useselectedFloorItem();
+ let xValue = selectedFloorItem.position.x;
+ let zValue = selectedFloorItem.position.z;
+ let rotationRad = selectedFloorItem.rotation.y;
+ let rotationDeg = THREE.MathUtils.radToDeg(rotationRad);
+ // useEffect(() => {}, [selectedFloorItem]);
// Function to handle adding new user data
const handleAddUserData = () => {
const newUserData: UserData = {
@@ -45,12 +53,16 @@ const AssetProperties: React.FC = () => {
return (
{/* Name */}
-
Selected Object
+
{selectedFloorItem.userData.name}
-
{ }} />
- { }} />
+ {}}
+ value1={xValue.toFixed(5)}
+ value2={zValue.toFixed(5)}
+ />
+ {}} value={rotationDeg} />
diff --git a/app/src/components/layout/sidebarRight/properties/GlobalProperties.tsx b/app/src/components/layout/sidebarRight/properties/GlobalProperties.tsx
index 672d847..633b144 100644
--- a/app/src/components/layout/sidebarRight/properties/GlobalProperties.tsx
+++ b/app/src/components/layout/sidebarRight/properties/GlobalProperties.tsx
@@ -3,8 +3,31 @@ import InputRange from "../../../ui/inputs/InputRange";
import InputToggle from "../../../ui/inputs/InputToggle";
import { AI_Icon } from "../../../icons/ExportCommonIcons";
import LabeledButton from "../../../ui/inputs/LabledButton";
+import {
+ useAzimuth,
+ useElevation,
+ useRenderDistance,
+ useResetCamera,
+ useRoofVisibility,
+ useSelectedWallItem,
+ useShadows,
+ useSocketStore,
+ useToggleView,
+ useWallVisibility,
+} from "../../../../store/store";
+import { setEnvironment } from "../../../../services/factoryBuilder/environment/setEnvironment";
const GlobalProperties: React.FC = () => {
+ const { toggleView, setToggleView } = useToggleView();
+ const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem();
+ const { roofVisibility, setRoofVisibility } = useRoofVisibility();
+ const { wallVisibility, setWallVisibility } = useWallVisibility();
+ const { shadows, setShadows } = useShadows();
+ const { resetCamera, setResetCamera } = useResetCamera();
+ const { elevation, setElevation } = useElevation();
+ const { azimuth, setAzimuth } = useAzimuth();
+ const { renderDistance, setRenderDistance } = useRenderDistance();
+ const { socket } = useSocketStore();
const [limitDistance, setLimitDistance] = useState(false);
const [distance, setDistance] = useState(5);
@@ -23,6 +46,93 @@ const GlobalProperties: React.FC = () => {
function updateGridDistance(value: number) {
setGridDistance(value);
}
+ // Function to toggle roof visibility
+ const changeRoofVisibility = async () => {
+ const email = localStorage.getItem("email");
+ const organization = email!.split("@")[1].split(".")[0];
+
+ //using REST
+ const data = await setEnvironment(
+ organization,
+ localStorage.getItem("userId")!,
+ wallVisibility,
+ !roofVisibility,
+ shadows
+ );
+ // console.log('data: ', data);
+
+ //using Socket
+ // const visData = {
+ // organization: organization,
+ // userId: localStorage.getItem('userId')!,
+ // wallVisibility: wallVisibility,
+ // roofVisibility: !roofVisibility,
+ // shadowVisibility: shadows,
+ // socketId: socket.id
+ // };
+ // socket.emit('v1:Environment:set', visData)
+
+ setRoofVisibility(!roofVisibility); // Toggle roof visibility
+ };
+ // Function to toggle wall visibility
+ const changeWallVisibility = async () => {
+ const email = localStorage.getItem("email");
+ const organization = email!.split("@")[1].split(".")[0];
+ //using REST
+ const data = await setEnvironment(
+ organization,
+ localStorage.getItem("userId")!,
+ !wallVisibility,
+ roofVisibility,
+ shadows
+ );
+ // console.log('data: ', data);
+
+ //using Socket
+ // const visData = {
+ // organization: organization,
+ // userId: localStorage.getItem('userId')!,
+ // wallVisibility: !wallVisibility,
+ // roofVisibility: roofVisibility,
+ // shadowVisibility: shadows,
+ // socketId: socket.id
+ // };
+ // socket.emit('v1:Environment:set', visData)
+
+ setWallVisibility(!wallVisibility); // Toggle wall visibility
+ };
+
+ const shadowVisibility = async () => {
+ const email = localStorage.getItem("email");
+ const organization = email!.split("@")[1].split(".")[0];
+ //using REST
+ const data = await setEnvironment(
+ organization,
+ localStorage.getItem("userId")!,
+ wallVisibility,
+ roofVisibility,
+ !shadows
+ );
+ // console.log('data: ', data);
+
+ //using Socket
+ // const visData = {
+ // organization: organization,
+ // userId: localStorage.getItem('userId')!,
+ // wallVisibility: wallVisibility,
+ // roofVisibility: roofVisibility,
+ // shadowVisibility: !shadows,
+ // socketId: socket.id
+ // };
+ // socket.emit('v1:Environment:set', visData)
+
+ setShadows(!shadows);
+ };
+ const toggleResetCamera = () => {
+ if (!toggleView) {
+ setResetCamera(true); // Trigger reset camera action
+ }
+ };
return (
@@ -34,10 +144,29 @@ const GlobalProperties: React.FC = () => {
-
-
-
-
{}} value="Reset"/>
+
+
+
+
diff --git a/app/src/components/ui/componets/DisplayZone.tsx b/app/src/components/ui/componets/DisplayZone.tsx
index dafddba..a321836 100644
--- a/app/src/components/ui/componets/DisplayZone.tsx
+++ b/app/src/components/ui/componets/DisplayZone.tsx
@@ -166,8 +166,10 @@ const DisplayZone: React.FC = ({
return (
{/* Left Arrow */}
{showLeftArrow && (
diff --git a/app/src/modules/collaboration/collabCams.tsx b/app/src/modules/collaboration/collabCams.tsx
index 9d5475e..af135a7 100644
--- a/app/src/modules/collaboration/collabCams.tsx
+++ b/app/src/modules/collaboration/collabCams.tsx
@@ -1,112 +1,169 @@
-import * as THREE from 'three';
-import { useEffect, useRef, useState } from 'react';
-import { useFrame } from '@react-three/fiber';
-import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
-import camModel from '../../assets/gltf-glb/camera face 2.gltf';
-import getActiveUsersData from '../../services/factoryBuilder/collab/getActiveUsers';
-import { useActiveUsers, useSocketStore } from '../../store/store';
-import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
-import { useNavigate } from 'react-router-dom';
-import { Text, Html } from '@react-three/drei';
-import CollabUserIcon from './collabUserIcon';
-import image from '../../assets/image/userImage.png';
-
+import * as THREE from "three";
+import { useEffect, useRef, useState } from "react";
+import { useFrame } from "@react-three/fiber";
+import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
+import camModel from "../../assets/gltf-glb/camera face 2.gltf";
+import getActiveUsersData from "../../services/factoryBuilder/collab/getActiveUsers";
+import { useActiveUsers, useSocketStore } from "../../store/store";
+import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
+import { useNavigate } from "react-router-dom";
+import { Html } from "@react-three/drei";
+import CollabUserIcon from "./collabUserIcon";
+import { getAvatarColor } from "./users/functions/getAvatarColor";
const CamModelsGroup = () => {
let navigate = useNavigate();
const groupRef = useRef
(null);
- const email = localStorage.getItem('email');
+ const email = localStorage.getItem("email");
const { activeUsers, setActiveUsers } = useActiveUsers();
const { socket } = useSocketStore();
const loader = new GLTFLoader();
const dracoLoader = new DRACOLoader();
const [cams, setCams] = useState([]);
- const [models, setModels] = useState>({});
+ const [models, setModels] = useState<
+ Record<
+ string,
+ { targetPosition: THREE.Vector3; targetRotation: THREE.Euler }
+ >
+ >({});
- dracoLoader.setDecoderPath('three/examples/jsm/libs/draco/gltf/');
+ dracoLoader.setDecoderPath("three/examples/jsm/libs/draco/gltf/");
loader.setDRACOLoader(dracoLoader);
useEffect(() => {
if (!email) {
- navigate('/');
+ navigate("/");
}
if (!socket) return;
- const organization = email!.split('@')[1].split('.')[0];
+ const organization = email!.split("@")[1].split(".")[0];
- socket.on('userConnectRespones', (data: any) => {
+ socket.on("userConnectRespones", (data: any) => {
if (!groupRef.current) return;
- if (data.data.userData.email === email) return
- if (socket.id === data.socketId || organization !== data.organization) return;
+ if (data.data.userData.email === email) return;
+ if (socket.id === data.socketId || organization !== data.organization)
+ return;
- const model = groupRef.current.getObjectByProperty('uuid', data.data.userData._id);
+ const model = groupRef.current.getObjectByProperty(
+ "uuid",
+ data.data.userData._id
+ );
if (model) {
groupRef.current.remove(model);
}
loader.load(camModel, (gltf) => {
const newModel = gltf.scene.clone();
newModel.uuid = data.data.userData._id;
- newModel.position.set(data.data.position.x, data.data.position.y, data.data.position.z);
- newModel.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z);
+ newModel.position.set(
+ data.data.position.x,
+ data.data.position.y,
+ data.data.position.z
+ );
+ newModel.rotation.set(
+ data.data.rotation.x,
+ data.data.rotation.y,
+ data.data.rotation.z
+ );
newModel.userData = data.data.userData;
setCams((prev) => [...prev, newModel]);
setActiveUsers([...activeUsers, data.data.userData]);
});
});
- socket.on('userDisConnectRespones', (data: any) => {
+ socket.on("userDisConnectRespones", (data: any) => {
if (!groupRef.current) return;
- if (socket.id === data.socketId || organization !== data.organization) return;
+ if (socket.id === data.socketId || organization !== data.organization)
+ return;
- setCams((prev) => prev.filter((cam) => cam.uuid !== data.data.userData._id));
- setActiveUsers(activeUsers.filter((user: any) => user._id !== data.data.userData._id));
+ setCams((prev) =>
+ prev.filter((cam) => cam.uuid !== data.data.userData._id)
+ );
+ setActiveUsers(
+ activeUsers.filter((user: any) => user._id !== data.data.userData._id)
+ );
});
- socket.on('cameraUpdateResponse', (data: any) => {
- if (!groupRef.current || socket.id === data.socketId || organization !== data.organization) return;
+ socket.on("cameraUpdateResponse", (data: any) => {
+ if (
+ !groupRef.current ||
+ socket.id === data.socketId ||
+ organization !== data.organization
+ )
+ return;
setModels((prev) => ({
...prev,
[data.data.userId]: {
- targetPosition: new THREE.Vector3(data.data.position.x, data.data.position.y, data.data.position.z),
- targetRotation: new THREE.Euler(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z),
+ targetPosition: new THREE.Vector3(
+ data.data.position.x,
+ data.data.position.y,
+ data.data.position.z
+ ),
+ targetRotation: new THREE.Euler(
+ data.data.rotation.x,
+ data.data.rotation.y,
+ data.data.rotation.z
+ ),
},
}));
});
return () => {
- socket.off('userConnectRespones');
- socket.off('userDisConnectRespones');
- socket.off('cameraUpdateResponse');
+ socket.off("userConnectRespones");
+ socket.off("userDisConnectRespones");
+ socket.off("cameraUpdateResponse");
};
}, [socket, activeUsers]);
useFrame(() => {
if (!groupRef.current) return;
Object.keys(models).forEach((uuid) => {
- const model = groupRef.current!.getObjectByProperty('uuid', uuid);
+ const model = groupRef.current!.getObjectByProperty("uuid", uuid);
if (!model) return;
const { targetPosition, targetRotation } = models[uuid];
model.position.lerp(targetPosition, 0.1);
- model.rotation.x = THREE.MathUtils.lerp(model.rotation.x, targetRotation.x, 0.1);
- model.rotation.y = THREE.MathUtils.lerp(model.rotation.y, targetRotation.y, 0.1);
- model.rotation.z = THREE.MathUtils.lerp(model.rotation.z, targetRotation.z, 0.1);
+ model.rotation.x = THREE.MathUtils.lerp(
+ model.rotation.x,
+ targetRotation.x,
+ 0.1
+ );
+ model.rotation.y = THREE.MathUtils.lerp(
+ model.rotation.y,
+ targetRotation.y,
+ 0.1
+ );
+ model.rotation.z = THREE.MathUtils.lerp(
+ model.rotation.z,
+ targetRotation.z,
+ 0.1
+ );
});
});
useEffect(() => {
if (!groupRef.current) return;
- const organization = email!.split('@')[1].split('.')[0];
+ const organization = email!.split("@")[1].split(".")[0];
getActiveUsersData(organization).then((data) => {
- const filteredData = data.cameraDatas.filter((camera: any) => camera.userData.email !== email);
+ const filteredData = data.cameraDatas.filter(
+ (camera: any) => camera.userData.email !== email
+ );
if (filteredData.length > 0) {
loader.load(camModel, (gltf) => {
const newCams = filteredData.map((cam: any) => {
const newModel = gltf.scene.clone();
newModel.uuid = cam.userData._id;
- newModel.position.set(cam.position.x, cam.position.y, cam.position.z);
- newModel.rotation.set(cam.rotation.x, cam.rotation.y, cam.rotation.z);
+ newModel.position.set(
+ cam.position.x,
+ cam.position.y,
+ cam.position.z
+ );
+ newModel.rotation.set(
+ cam.rotation.x,
+ cam.rotation.y,
+ cam.rotation.z
+ );
newModel.userData = cam.userData;
+ console.log('cam.userData: ', cam.userData);
setActiveUsers([...activeUsers, cam.userData]);
return newModel;
});
@@ -119,7 +176,7 @@ const CamModelsGroup = () => {
return (
{cams.map((cam, index) => (
-
+
{
textAlign: "center",
fontFamily: "Arial, sans-serif",
}}
- position={[-0.015, 0, 0.7]}>
-
+ position={[-0.015, 0, 0.7]}
+ >
+
))}
diff --git a/app/src/modules/collaboration/collabUserIcon.tsx b/app/src/modules/collaboration/collabUserIcon.tsx
index a6c22c0..acc3fa0 100644
--- a/app/src/modules/collaboration/collabUserIcon.tsx
+++ b/app/src/modules/collaboration/collabUserIcon.tsx
@@ -1,53 +1,33 @@
import React from "react";
+import CustomAvatar from "./users/Avatar";
interface CollabUserIconProps {
- color: string;
- userImage: string;
- userName: string;
+ userName: string;
+ userImage?: string;
+ index?: number;
+ color: string;
}
const CollabUserIcon: React.FC = ({
- color,
- userImage,
- userName,
+ userImage,
+ userName,
+ index = 0,
+ color,
}) => {
- return (
-
-

-
- {userName}
-
-
- );
+ return (
+
+
+ {userImage ? (
+

+ ) : (
+
+ )}
+
+
+ {userName}
+
+
+ );
};
export default CollabUserIcon;
diff --git a/app/src/modules/collaboration/users/Avatar.tsx b/app/src/modules/collaboration/users/Avatar.tsx
new file mode 100644
index 0000000..93d45c3
--- /dev/null
+++ b/app/src/modules/collaboration/users/Avatar.tsx
@@ -0,0 +1,59 @@
+import React, { useEffect, useState } from "react";
+import { getInitials } from "./functions/getInitials";
+import { getAvatarColor } from "./functions/getAvatarColor";
+
+interface AvatarProps {
+ name: string; // Name can be a full name or initials
+ size?: number;
+ index?: number;
+ textColor?: string;
+}
+
+const CustomAvatar: React.FC = ({
+ name,
+ size = 100,
+ index = 0,
+ textColor = "#ffffff",
+}) => {
+ const [imageSrc, setImageSrc] = useState(null);
+
+ useEffect(() => {
+ const canvas = document.createElement("canvas"); // Create an offscreen canvas
+ canvas.width = size;
+ canvas.height = size;
+ const ctx = canvas.getContext("2d");
+ if (ctx) {
+ const initials = getInitials(name); // Convert name to initials if needed
+
+ // Draw background
+ ctx.fillStyle = getAvatarColor(index);
+ ctx.fillRect(0, 0, size, size);
+
+ // Draw initials
+ ctx.fillStyle = textColor;
+ ctx.font = `bold ${size / 2}px Arial`;
+ ctx.textAlign = "center";
+ ctx.textBaseline = "middle";
+ ctx.fillText(initials, size / 2, size / 2);
+
+ // Generate image source
+ const dataURL = canvas.toDataURL("image/png");
+ setImageSrc(dataURL);
+ }
+ }, [name, size, textColor]);
+
+ if (!imageSrc) {
+ return null; // Return null while the image is being generated
+ }
+
+ return (
+
+ );
+};
+
+export default CustomAvatar;
diff --git a/app/src/modules/collaboration/users/functions/getAvatarColor.ts b/app/src/modules/collaboration/users/functions/getAvatarColor.ts
new file mode 100644
index 0000000..d3186d2
--- /dev/null
+++ b/app/src/modules/collaboration/users/functions/getAvatarColor.ts
@@ -0,0 +1,26 @@
+const avatarColors: string[] = [
+ "#FF5733", // Red Orange
+ "#48ac2a", // Leaf Green
+ "#0050eb", // Royal Blue
+ "#FF33A1", // Hot Pink
+ "#FF8C33", // Deep Orange
+ "#8C33FF", // Violet
+ "#FF3333", // Bright Red
+ "#43c06d", // Emerald Green
+ "#A133FF", // Amethyst Purple
+ "#C70039", // Crimson
+ "#900C3F", // Maroon
+ "#581845", // Plum
+ "#3498DB", // Sky Blue
+ "#2ECC71", // Green Mint
+ "#E74C3C", // Tomato Red
+ "#00adff", // Azure
+ "#DBAD05", // Amber Yellow
+ "#FF5733", // Red Orange
+ "#FF33A1", // Hot Pink
+ "#900C3F", // Maroon
+];
+
+export function getAvatarColor(index: number): string {
+ return avatarColors[index % avatarColors.length];
+}
diff --git a/app/src/modules/collaboration/users/functions/getInitials.ts b/app/src/modules/collaboration/users/functions/getInitials.ts
new file mode 100644
index 0000000..5ebaa19
--- /dev/null
+++ b/app/src/modules/collaboration/users/functions/getInitials.ts
@@ -0,0 +1,10 @@
+export const getInitials = (fullName: string): string => {
+ // Extract initials from the name
+ const words = fullName.split(" ");
+ const initials = words
+ .map((word) => word[0])
+ .slice(0, 2)
+ .join("")
+ .toUpperCase();
+ return initials;
+};
\ No newline at end of file
diff --git a/app/src/modules/market/FilterSearch.tsx b/app/src/modules/market/FilterSearch.tsx
index 08103ba..84074b8 100644
--- a/app/src/modules/market/FilterSearch.tsx
+++ b/app/src/modules/market/FilterSearch.tsx
@@ -29,11 +29,10 @@ const FilterSearch: React.FC = ({
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
diff --git a/app/src/styles/components/marketPlace/marketPlace.scss b/app/src/styles/components/marketPlace/marketPlace.scss
index 71f5897..620d934 100644
--- a/app/src/styles/components/marketPlace/marketPlace.scss
+++ b/app/src/styles/components/marketPlace/marketPlace.scss
@@ -47,10 +47,9 @@
border-radius: $border-radius-large;
.search-container {
- border: none !important;
- box-shadow: $box-shadow-medium;
border-radius: $border-radius-large;
-
+ outline: 1px solid var(--border-color);
+ border: none;
input {
border: none !important;
outline: none;
@@ -60,6 +59,12 @@
.regularDropdown-container {
max-width: 159px;
+ height: 100%;
+ border-radius: #{$border-radius-large};
+ border: 1px solid var(--border-color);
+ .dropdown-header {
+ align-items: center;
+ }
}
.button {
@@ -128,7 +133,7 @@
justify-content: center;
border-radius: #{$border-radius-medium};
overflow: hidden;
- img{
+ img {
height: inherit;
width: 100%;
object-fit: cover;
@@ -143,7 +148,7 @@
display: flex;
flex-direction: column;
gap: 3px;
- .assets-name{
+ .assets-name {
text-transform: capitalize;
}
diff --git a/app/src/styles/layout/popup.scss b/app/src/styles/layout/popup.scss
index a086cf4..20ea3f2 100644
--- a/app/src/styles/layout/popup.scss
+++ b/app/src/styles/layout/popup.scss
@@ -110,3 +110,29 @@
}
}
}
+
+.collab-user-live-container{
+ @include flex-center;
+ flex-direction: column;
+ gap: 6px;
+ .user-image-container{
+ height: 30px;
+ width: 30px;
+ border-radius: #{$border-radius-circle};
+ overflow: hidden;
+ .user-image{
+ height: 100%;
+ width: 100%;
+ object-fit: cover;
+ vertical-align: top;
+ }
+ }
+ .user-name{
+ padding: 4px 6px;
+ border-radius: #{$border-radius-small};
+ color: white;
+ font-size: var(--font-size-regulaar);
+ font-weight: var(--font-size-regulaar);
+ text-transform: capitalize;
+ }
+}
diff --git a/app/src/styles/layout/sidebar.scss b/app/src/styles/layout/sidebar.scss
index d595b92..b248ad2 100644
--- a/app/src/styles/layout/sidebar.scss
+++ b/app/src/styles/layout/sidebar.scss
@@ -225,11 +225,13 @@
border-radius: 50%;
font-weight: var(--font-weight-bold);
color: white;
+ text-transform: capitalize;
}
.guest-users-container {
display: flex;
-
+ width: 100%;
+ justify-content: flex-end;
.other-guest {
@include flex-center;
height: 26px;
@@ -249,7 +251,8 @@
display: flex;
.user-organization {
- height: 100%;
+ height: 26px;
+ width: 52px;
max-width: 52px;
border-radius: 20px;
overflow: hidden;
diff --git a/app/src/types/users.d.ts b/app/src/types/users.d.ts
index 9e8c35a..55d5361 100644
--- a/app/src/types/users.d.ts
+++ b/app/src/types/users.d.ts
@@ -8,4 +8,11 @@ export interface User {
type AccessOption = {
option: string;
+};
+
+export type ActiveUser = {
+ _id: string;
+ userName: string;
+ email: string;
+ activeStatus?: string; // Optional property
};
\ No newline at end of file