Merge branch 'main' into rtViz

This commit is contained in:
2025-04-04 18:50:12 +05:30
43 changed files with 4251 additions and 1037 deletions

View File

@@ -8,37 +8,45 @@ export function CleanPannel() {
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_1782_1158)">
<path d="M12 0H0V12H12V0Z" fill="white" fillOpacity="0.01" />
<path
d="M12 0H0V12H12V0Z"
fill="var(--text-color)"
fillOpacity="0.01"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5 1.47852H7V3.47853H10.75V5.47853H1.25V3.47853H5V1.47852Z"
stroke="#2B3344"
stroke="var(--text-color)"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path d="M2 10H10V5.5H2V10Z" stroke="#2B3344" strokeLinejoin="round" />
<path
d="M2 10H10V5.5H2V10Z"
stroke="var(--text-color)"
strokeLinejoin="round"
/>
<path
d="M4 9.97439V8.47852"
stroke="#2B3344"
stroke="var(--text-color)"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M6 9.97461V8.47461"
stroke="#2B3344"
stroke="var(--text-color)"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M8 9.97439V8.47852"
stroke="#2B3344"
stroke="var(--text-color)"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M3 10H9"
stroke="#2B3344"
stroke="var(--text-color)"
strokeLinecap="round"
strokeLinejoin="round"
/>

View File

@@ -49,7 +49,7 @@ const SideBarLeft: React.FC = () => {
</>
) : activeModule === "market" ? (
<></>
) : (
) : activeModule === "builder" ? (
<>
<ToggleHeader
options={["Outline", "Assets"]}
@@ -60,6 +60,17 @@ const SideBarLeft: React.FC = () => {
{activeOption === "Outline" ? <Outline /> : <Assets />}
</div>
</>
) : (
<>
<ToggleHeader
options={["Outline"]}
activeOption={activeOption}
handleClick={handleToggleClick}
/>
<div className="sidebar-left-content-container">
{activeOption === "Outline" ? <Outline /> : <Assets />}
</div>
</>
)}
</div>
)}

View File

@@ -14,7 +14,7 @@ const chartTypes: ChartType[] = [
];
const sampleData = {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"],
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
data: [65, 59, 80, 81, 56, 55, 40],
@@ -102,7 +102,6 @@ const ProgressBarWidget = ({
);
};
const Widgets2D = () => {
return (
<div className="widget2D">

View File

@@ -10,6 +10,7 @@ import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import LabledDropdown from "../../../ui/inputs/LabledDropdown";
import { handleResize } from "../../../../functions/handleResizePannel";
import {
useFloorItems,
useSelectedActionSphere,
useSelectedPath,
useSimulationPaths,
@@ -17,11 +18,14 @@ import {
import * as THREE from "three";
import * as Types from "../../../../types/world/worldTypes";
import InputToggle from "../../../ui/inputs/InputToggle";
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
const ConveyorMechanics: React.FC = () => {
const { selectedActionSphere } = useSelectedActionSphere();
const { selectedPath, setSelectedPath } = useSelectedPath();
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
const { floorItems, setFloorItems } = useFloorItems();
const actionsContainerRef = useRef<HTMLDivElement>(null);
const triggersContainerRef = useRef<HTMLDivElement>(null);
@@ -36,6 +40,19 @@ const ConveyorMechanics: React.FC = () => {
.find((point) => point.uuid === selectedActionSphere.point.uuid);
}, [selectedActionSphere, simulationPaths]);
const updateBackend = async (updatedPath: Types.ConveyorEventsSchema | undefined) => {
if (!updatedPath) return;
// const email = localStorage.getItem("email");
// const organization = email ? email.split("@")[1].split(".")[0] : "";
// console.log('updatedPath: ', updatedPath);
// const a = await setEventApi(
// organization,
// updatedPath.modeluuid,
// updatedPath.points
// );
// console.log('a: ', a);
}
const handleAddAction = () => {
if (!selectedActionSphere) return;
@@ -65,6 +82,15 @@ const ConveyorMechanics: React.FC = () => {
return path;
});
const updatedPath = updatedPaths.find(
(path): path is Types.ConveyorEventsSchema =>
path.type === "Conveyor" &&
path.points.some(
(point) => point.uuid === selectedActionSphere.point.uuid
)
);
updateBackend(updatedPath);
setSimulationPaths(updatedPaths);
};
@@ -74,21 +100,30 @@ const ConveyorMechanics: React.FC = () => {
const updatedPaths = simulationPaths.map((path) =>
path.type === "Conveyor"
? {
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.filter(
(action) => action.uuid !== uuid
),
}
: point
),
}
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.filter(
(action) => action.uuid !== uuid
),
}
: point
),
}
: path
);
const updatedPath = updatedPaths.find(
(path): path is Types.ConveyorEventsSchema =>
path.type === "Conveyor" &&
path.points.some(
(point) => point.uuid === selectedActionSphere.point.uuid
)
);
updateBackend(updatedPath);
setSimulationPaths(updatedPaths);
};
@@ -98,36 +133,45 @@ const ConveyorMechanics: React.FC = () => {
const updatedPaths = simulationPaths.map((path) =>
path.type === "Conveyor"
? {
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid
? {
...action,
type: actionType,
material:
actionType === "Spawn" || actionType === "Swap"
? "Inherit"
: action.material,
delay:
actionType === "Delay" ? "Inherit" : action.delay,
spawnInterval:
actionType === "Spawn"
? "Inherit"
: action.spawnInterval,
}
: action
),
}
: point
),
}
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid
? {
...action,
type: actionType,
material:
actionType === "Spawn" || actionType === "Swap"
? "Inherit"
: action.material,
delay:
actionType === "Delay" ? "Inherit" : action.delay,
spawnInterval:
actionType === "Spawn"
? "Inherit"
: action.spawnInterval,
}
: action
),
}
: point
),
}
: path
);
const updatedPath = updatedPaths.find(
(path): path is Types.ConveyorEventsSchema =>
path.type === "Conveyor" &&
path.points.some(
(point) => point.uuid === selectedActionSphere.point.uuid
)
);
updateBackend(updatedPath);
setSimulationPaths(updatedPaths);
// Update the selected item to reflect changes
@@ -156,24 +200,33 @@ const ConveyorMechanics: React.FC = () => {
const updatedPaths = simulationPaths.map((path) =>
path.type === "Conveyor"
? {
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid &&
(action.type === "Spawn" || action.type === "Swap")
? { ...action, material }
: action
),
}
: point
),
}
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid &&
(action.type === "Spawn" || action.type === "Swap")
? { ...action, material }
: action
),
}
: point
),
}
: path
);
const updatedPath = updatedPaths.find(
(path): path is Types.ConveyorEventsSchema =>
path.type === "Conveyor" &&
path.points.some(
(point) => point.uuid === selectedActionSphere.point.uuid
)
);
updateBackend(updatedPath);
setSimulationPaths(updatedPaths);
// Update selected item if it's the current action
@@ -194,21 +247,30 @@ const ConveyorMechanics: React.FC = () => {
const updatedPaths = simulationPaths.map((path) =>
path.type === "Conveyor"
? {
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid ? { ...action, delay } : action
),
}
: point
),
}
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid ? { ...action, delay } : action
),
}
: point
),
}
: path
);
const updatedPath = updatedPaths.find(
(path): path is Types.ConveyorEventsSchema =>
path.type === "Conveyor" &&
path.points.some(
(point) => point.uuid === selectedActionSphere.point.uuid
)
);
updateBackend(updatedPath);
setSimulationPaths(updatedPaths);
};
@@ -221,23 +283,32 @@ const ConveyorMechanics: React.FC = () => {
const updatedPaths = simulationPaths.map((path) =>
path.type === "Conveyor"
? {
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid
? { ...action, spawnInterval }
: action
),
}
: point
),
}
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid
? { ...action, spawnInterval }
: action
),
}
: point
),
}
: path
);
const updatedPath = updatedPaths.find(
(path): path is Types.ConveyorEventsSchema =>
path.type === "Conveyor" &&
path.points.some(
(point) => point.uuid === selectedActionSphere.point.uuid
)
);
updateBackend(updatedPath);
setSimulationPaths(updatedPaths);
};
@@ -248,6 +319,15 @@ const ConveyorMechanics: React.FC = () => {
path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path
);
const updatedPath = updatedPaths.find(
(path): path is Types.ConveyorEventsSchema =>
path.type === "Conveyor" &&
path.points.some(
(point) => point.uuid === selectedActionSphere.point.uuid
)
);
updateBackend(updatedPath);
setSimulationPaths(updatedPaths);
setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } });
};
@@ -258,26 +338,35 @@ const ConveyorMechanics: React.FC = () => {
const updatedPaths = simulationPaths.map((path) =>
path.type === "Conveyor"
? {
...path,
points: path.points.map((point) => {
if (point.uuid === selectedActionSphere.point.uuid) {
const triggerIndex = point.triggers.length;
const newTrigger = {
uuid: THREE.MathUtils.generateUUID(),
name: `Trigger ${triggerIndex + 1}`,
type: "",
bufferTime: 0,
isUsed: false,
};
...path,
points: path.points.map((point) => {
if (point.uuid === selectedActionSphere.point.uuid) {
const triggerIndex = point.triggers.length;
const newTrigger = {
uuid: THREE.MathUtils.generateUUID(),
name: `Trigger ${triggerIndex + 1}`,
type: "",
bufferTime: 0,
isUsed: false,
};
return { ...point, triggers: [...point.triggers, newTrigger] };
}
return point;
}),
}
return { ...point, triggers: [...point.triggers, newTrigger] };
}
return point;
}),
}
: path
);
const updatedPath = updatedPaths.find(
(path): path is Types.ConveyorEventsSchema =>
path.type === "Conveyor" &&
path.points.some(
(point) => point.uuid === selectedActionSphere.point.uuid
)
);
updateBackend(updatedPath);
setSimulationPaths(updatedPaths);
};
@@ -287,21 +376,30 @@ const ConveyorMechanics: React.FC = () => {
const updatedPaths = simulationPaths.map((path) =>
path.type === "Conveyor"
? {
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
triggers: point.triggers.filter(
(trigger) => trigger.uuid !== uuid
),
}
: point
),
}
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
triggers: point.triggers.filter(
(trigger) => trigger.uuid !== uuid
),
}
: point
),
}
: path
);
const updatedPath = updatedPaths.find(
(path): path is Types.ConveyorEventsSchema =>
path.type === "Conveyor" &&
path.points.some(
(point) => point.uuid === selectedActionSphere.point.uuid
)
);
updateBackend(updatedPath);
setSimulationPaths(updatedPaths);
};
@@ -311,23 +409,32 @@ const ConveyorMechanics: React.FC = () => {
const updatedPaths = simulationPaths.map((path) =>
path.type === "Conveyor"
? {
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
triggers: point.triggers.map((trigger) =>
trigger.uuid === uuid
? { ...trigger, type: triggerType }
: trigger
),
}
: point
),
}
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
triggers: point.triggers.map((trigger) =>
trigger.uuid === uuid
? { ...trigger, type: triggerType }
: trigger
),
}
: point
),
}
: path
);
const updatedPath = updatedPaths.find(
(path): path is Types.ConveyorEventsSchema =>
path.type === "Conveyor" &&
path.points.some(
(point) => point.uuid === selectedActionSphere.point.uuid
)
);
updateBackend(updatedPath);
setSimulationPaths(updatedPaths);
// Ensure the selectedItem is updated immediately
@@ -347,22 +454,31 @@ const ConveyorMechanics: React.FC = () => {
const updatedPaths = simulationPaths.map((path) =>
path.type === "Conveyor"
? {
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) => ({
...action,
isUsed: action.uuid === uuid ? !action.isUsed : false,
})),
}
: point
),
}
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) => ({
...action,
isUsed: action.uuid === uuid ? !action.isUsed : false,
})),
}
: point
),
}
: path
);
const updatedPath = updatedPaths.find(
(path): path is Types.ConveyorEventsSchema =>
path.type === "Conveyor" &&
path.points.some(
(point) => point.uuid === selectedActionSphere.point.uuid
)
);
updateBackend(updatedPath);
setSimulationPaths(updatedPaths);
// Immediately update the selected item if it's the one being toggled
@@ -384,22 +500,31 @@ const ConveyorMechanics: React.FC = () => {
const updatedPaths = simulationPaths.map((path) =>
path.type === "Conveyor"
? {
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
triggers: point.triggers.map((trigger) => ({
...trigger,
isUsed: trigger.uuid === uuid ? !trigger.isUsed : false,
})),
}
: point
),
}
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
triggers: point.triggers.map((trigger) => ({
...trigger,
isUsed: trigger.uuid === uuid ? !trigger.isUsed : false,
})),
}
: point
),
}
: path
);
const updatedPath = updatedPaths.find(
(path): path is Types.ConveyorEventsSchema =>
path.type === "Conveyor" &&
path.points.some(
(point) => point.uuid === selectedActionSphere.point.uuid
)
);
updateBackend(updatedPath);
setSimulationPaths(updatedPaths);
// Immediately update the selected item if it's the one being toggled
@@ -420,23 +545,32 @@ const ConveyorMechanics: React.FC = () => {
const updatedPaths = simulationPaths.map((path) =>
path.type === "Conveyor"
? {
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
triggers: point.triggers.map((trigger) =>
trigger.uuid === uuid
? { ...trigger, bufferTime }
: trigger
),
}
: point
),
}
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
triggers: point.triggers.map((trigger) =>
trigger.uuid === uuid
? { ...trigger, bufferTime }
: trigger
),
}
: point
),
}
: path
);
const updatedPath = updatedPaths.find(
(path): path is Types.ConveyorEventsSchema =>
path.type === "Conveyor" &&
path.points.some(
(point) => point.uuid === selectedActionSphere.point.uuid
)
);
updateBackend(updatedPath);
setSimulationPaths(updatedPaths);
// Immediately update selectedItem if it's the currently selected trigger
@@ -493,12 +627,11 @@ const ConveyorMechanics: React.FC = () => {
{selectedPoint?.actions.map((action) => (
<div
key={action.uuid}
className={`list-item ${
selectedItem?.type === "action" &&
className={`list-item ${selectedItem?.type === "action" &&
selectedItem.item?.uuid === action.uuid
? "active"
: ""
}`}
? "active"
: ""
}`}
>
<div
className="value"
@@ -506,7 +639,7 @@ const ConveyorMechanics: React.FC = () => {
setSelectedItem({ type: "action", item: action })
}
>
<input type="radio" name="action" id="action" defaultChecked={action.isUsed}/>
<input type="radio" name="action" id="action" defaultChecked={action.isUsed} />
<RenameInput value={action.name} />
</div>
<div
@@ -543,12 +676,11 @@ const ConveyorMechanics: React.FC = () => {
{selectedPoint?.triggers.map((trigger) => (
<div
key={trigger.uuid}
className={`list-item ${
selectedItem?.type === "trigger" &&
className={`list-item ${selectedItem?.type === "trigger" &&
selectedItem.item?.uuid === trigger.uuid
? "active"
: ""
}`}
? "active"
: ""
}`}
>
<div
className="value"
@@ -588,8 +720,8 @@ const ConveyorMechanics: React.FC = () => {
{selectedItem.type === "action" && (
<>
<InputToggle
inputKey="enableTrigger"
label="Enable Trigger"
inputKey="enableAction"
label="Enable Action"
value={selectedItem.item.isUsed}
onClick={() => handleActionToggle(selectedItem.item.uuid)}
/>
@@ -604,19 +736,19 @@ const ConveyorMechanics: React.FC = () => {
{/* Only show material dropdown for Spawn/Swap actions */}
{(selectedItem.item.type === "Spawn" ||
selectedItem.item.type === "Swap") && (
<LabledDropdown
label={
selectedItem.item.type === "Spawn"
? "Spawn Material"
: "Swap Material"
}
defaultOption={selectedItem.item.material}
options={["Inherit", "Crate", "Box"]}
onSelect={(option) =>
handleMaterialSelect(selectedItem.item.uuid, option)
}
/>
)}
<LabledDropdown
label={
selectedItem.item.type === "Spawn"
? "Spawn Material"
: "Swap Material"
}
defaultOption={selectedItem.item.material}
options={["Inherit", "Crate", "Box"]}
onSelect={(option) =>
handleMaterialSelect(selectedItem.item.uuid, option)
}
/>
)}
{/* Only show delay input for Delay actions */}
{selectedItem.item.type === "Delay" && (

View File

@@ -1,18 +1,21 @@
import { useState } from "react";
import { useState, useEffect, useRef } from "react";
import { useWidgetStore } from "../../../../../store/useWidgetStore";
import ChartComponent from "../../../sidebarLeft/visualization/widgets/ChartComponent";
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
import { WalletIcon } from "../../../../icons/3dChartIcons";
import SimpleCard from "../../../../ui/realTimeVis/floating/SimpleCard";
// Define Props Interface
interface Widget {
id: string;
type: string; // Chart type (e.g., "bar", "line")
panel: "top" | "bottom" | "left" | "right"; // Panel location
title: string;
type?: string;
panel: "top" | "bottom" | "left" | "right";
title?: string;
header?: string;
fontFamily?: string;
fontSize?: string;
fontWeight?: string;
data: {
className?: string;
data?: {
labels: string[];
datasets: {
data: number[];
@@ -20,162 +23,263 @@ interface Widget {
borderColor: string;
borderWidth: number;
}[];
}; // Data for the chart
};
value?: string;
per?: string;
}
interface ChartElement {
tagName: string;
className: string;
textContent: string;
selector: string;
}
const Design = () => {
const [selectedName, setSelectedName] = useState("drop down");
console.log("selectedName: ", selectedName);
const [selectedElement, setSelectedElement] = useState("drop down");
console.log("selectedElement: ", selectedElement);
const [selectedFont, setSelectedFont] = useState("drop down");
console.log("selectedFont: ", selectedFont);
const [selectedSize, setSelectedSize] = useState("drop down");
console.log("selectedSize: ", selectedSize);
const [selectedWeight, setSelectedWeight] = useState("drop down");
console.log("selectedWeight: ", selectedWeight);
const [elementColor, setElementColor] = useState("#6f42c1");
const [showColorPicker, setShowColorPicker] = useState(false);
const [chartElements, setChartElements] = useState<ChartElement[]>([]);
const [selectedElementToStyle, setSelectedElementToStyle] = useState<string | null>(null);
const [nameInput, setNameInput] = useState("");
const chartRef = useRef<HTMLDivElement>(null);
const [elementColor, setElementColor] = useState("#6f42c1"); // Default color for elements
const [showColorPicker, setShowColorPicker] = useState(false); // Manage visibility of the color picker
const { selectedChartId, setSelectedChartId, widgets, setWidgets } = useWidgetStore();
// Zustand Store Hooks
const { selectedChartId, setSelectedChartId, widgets, setWidgets } =
useWidgetStore();
// Initialize name input and extract elements when selectedChartId changes
useEffect(() => {
setNameInput(selectedChartId?.header || selectedChartId?.title || "");
if (!chartRef.current) return;
const timer = setTimeout(() => {
const chartContainer = chartRef.current;
if (!chartContainer) return;
const elements = Array.from(chartContainer.querySelectorAll("*"))
.filter((el) => {
const tagName = el.tagName.toLowerCase();
return !["script", "style", "meta", "link", "head"].includes(tagName);
})
.map((el, index) => {
const tagName = el.tagName.toLowerCase();
const className = typeof el.className === "string" ? el.className : "";
const textContent = el.textContent?.trim() || "";
let selector = tagName;
if (className && typeof className === "string") {
const classList = className.split(/\s+/).filter((c) => c.length > 0);
if (classList.length > 0) {
selector += "." + classList.join(".");
}
}
if (!className || className.trim() === "") {
const parent = el.parentElement;
if (parent) {
const siblings = Array.from(parent.children).filter(
(child) => child.tagName.toLowerCase() === tagName
);
const position = siblings.indexOf(el) + 1;
selector += `:nth-of-type(${position})`;
}
}
return {
tagName,
className,
textContent,
selector,
};
});
setChartElements(elements);
}, 300);
return () => clearTimeout(timer);
}, [selectedChartId]);
const applyStyles = () => {
if (!selectedElementToStyle || !chartRef.current) return;
const element = chartRef.current.querySelector(selectedElementToStyle);
if (!element) return;
const elementToStyle = element as HTMLElement;
if (selectedFont !== "drop down") {
elementToStyle.style.fontFamily = selectedFont;
}
if (selectedSize !== "drop down") {
elementToStyle.style.fontSize = selectedSize;
}
if (selectedWeight !== "drop down") {
elementToStyle.style.fontWeight = selectedWeight.toLowerCase();
}
if (elementColor) {
elementToStyle.style.color = elementColor;
}
};
useEffect(() => {
applyStyles();
}, [selectedFont, selectedSize, selectedWeight, elementColor, selectedElementToStyle]);
// Handle Widget Updates
const handleUpdateWidget = (updatedProperties: Partial<Widget>) => {
if (!selectedChartId) return;
// Update the selectedChartId
const updatedChartId = {
...selectedChartId,
...updatedProperties,
};
setSelectedChartId(updatedChartId);
// Update the widgets array
const updatedWidgets = widgets.map((widget) =>
widget.id === selectedChartId.id
? { ...widget, ...updatedProperties }
: widget
widget.id === selectedChartId.id ? { ...widget, ...updatedProperties } : widget
);
setWidgets(updatedWidgets);
};
// Default Chart Data
const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newName = e.target.value;
setNameInput(newName);
if (selectedChartId?.title) {
handleUpdateWidget({ title: newName });
} else if (selectedChartId?.header) {
handleUpdateWidget({ header: newName });
}
};
const defaultChartData = {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"],
datasets: [
{
data: [65, 59, 80, 81, 56, 55, 40],
backgroundColor: elementColor, // Default background color
borderColor: "#ffffff", // Default border color
backgroundColor: elementColor,
borderColor: "#ffffff",
borderWidth: 1,
},
],
};
const elementOptions = chartElements.map((el) => {
let displayName = el.tagName;
if (el.className) displayName += `.${el.className}`;
if (el.textContent)
displayName += ` (${el.textContent.substring(0, 20)}${
el.textContent.length > 20 ? "..." : ""
})`;
return {
display: displayName,
value: el.selector,
};
});
return (
<div className="design">
{/* Title of the Selected Widget */}
<div className="selectedWidget">
{selectedChartId?.title || "Widget 1"}
{selectedChartId?.title || selectedChartId?.header || "Widget 1"}
</div>
{/* Chart Component */}
<div className="reviewChart">
{selectedChartId && (
<div className="reviewChart" ref={chartRef}>
{selectedChartId?.title ? (
<ChartComponent
type={selectedChartId.type}
type={selectedChartId.type || "bar"}
title={selectedChartId.title}
data={selectedChartId.data || defaultChartData} // Use widget data or default
data={selectedChartId.data || defaultChartData}
/>
) : (
<SimpleCard
header={selectedChartId?.header || ""}
icon={WalletIcon}
value={selectedChartId?.value || ""}
per={selectedChartId?.per || ""}
/>
)}
</div>
{/* Options Container */}
<div className="optionsContainer">
{/* Name Dropdown */}
<div className="option">
<span>Element to Style</span>
<RegularDropDown
header={selectedElementToStyle || "Select Element"}
options={
elementOptions.length > 0
? elementOptions.map((opt) => opt.display)
: ["No elements found"]
}
onSelect={(value) => {
const selected = elementOptions.find(
(opt) => opt.display === value
);
setSelectedElementToStyle(selected?.value || null);
}}
/>
</div>
<div className="option">
<span>Name</span>
<RegularDropDown
header={selectedChartId?.title || "Select Name"}
options={["Option 1", "Option 2", "Option 3"]}
onSelect={(value) => {
setSelectedName(value);
handleUpdateWidget({ title: value });
}}
<input
type="text"
value={nameInput}
onChange={handleNameChange}
placeholder="Enter name"
/>
</div>
{/* Element Dropdown */}
<div className="option">
<span>Element</span>
<RegularDropDown
header={selectedChartId?.type || "Select Element"}
options={["bar", "line", "pie", "doughnut", "radar", "polarArea"]} // Valid chart types
onSelect={(value) => {
setSelectedElement(value);
handleUpdateWidget({ type: value });
}}
/>
</div>
{selectedChartId?.title && (
<div className="option">
<span>Chart Type</span>
<RegularDropDown
header={selectedChartId?.type || "Select Type"}
options={["bar", "line", "pie", "doughnut", "radar", "polarArea"]}
onSelect={(value) => {
handleUpdateWidget({ type: value });
}}
/>
</div>
)}
{/* Font Family Dropdown */}
<div className="option">
<span>Font Family</span>
<RegularDropDown
header={selectedChartId?.fontFamily || "Select Font"}
options={["Arial", "Roboto", "Sans-serif"]}
onSelect={(value) => {
setSelectedFont(value);
handleUpdateWidget({ fontFamily: value });
}}
onSelect={(value) => setSelectedFont(value)}
/>
</div>
{/* Size Dropdown */}
<div className="option">
<span>Size</span>
<RegularDropDown
header={selectedChartId?.fontSize || "Select Size"}
options={["12px", "14px", "16px", "18px"]}
onSelect={(value) => {
setSelectedSize(value);
handleUpdateWidget({ fontSize: value });
}}
onSelect={(value) => setSelectedSize(value)}
/>
</div>
{/* Weight Dropdown */}
<div className="option">
<span>Weight</span>
<RegularDropDown
header={selectedChartId?.fontWeight || "Select Weight"}
options={["Light", "Regular", "Bold"]}
onSelect={(value) => {
setSelectedWeight(value);
handleUpdateWidget({ fontWeight: value });
}}
onSelect={(value) => setSelectedWeight(value)}
/>
</div>
{/* Element Color Picker */}
<div className="option">
<div
className="header"
onClick={() => setShowColorPicker((prev) => !prev)}
>
<span>Element Color</span>
<div className="icon"></div>{" "}
{/* Change icon based on the visibility */}
<div className="icon"></div>
</div>
{/* Show color picker only when 'showColorPicker' is true */}
{showColorPicker && (
<div className="colorDisplayer">
<input
@@ -183,20 +287,21 @@ const Design = () => {
value={elementColor}
onChange={(e) => {
setElementColor(e.target.value);
handleUpdateWidget({
data: {
labels: selectedChartId?.data?.labels || [],
datasets: [
{
...selectedChartId?.data?.datasets[0],
backgroundColor: e.target.value, // Update the element color
},
],
},
});
if (selectedChartId?.data) {
handleUpdateWidget({
data: {
...selectedChartId.data,
datasets: [
{
...selectedChartId.data.datasets[0],
backgroundColor: e.target.value,
},
],
},
});
}
}}
/>
{/* Display the selected color value */}
<span style={{ marginLeft: "10px" }}>{elementColor}</span>
</div>
)}
@@ -206,4 +311,4 @@ const Design = () => {
);
};
export default Design;
export default Design;

View File

@@ -438,7 +438,6 @@ const Tools: React.FC = () => {
}`}
onClick={() => {
setIsPlaying(!isPlaying);
setActiveTool("play");
}}
>
<PlayIcon isActive={activeTool === "play"} />

View File

@@ -124,8 +124,8 @@ const Panel: React.FC<PanelProps> = ({
selectedZone.widgets.filter((w) => w.panel === panel).length;
const calculatePanelCapacity = (panel: Side) => {
const CHART_WIDTH = 150;
const CHART_HEIGHT = 150;
const CHART_WIDTH = 170;
const CHART_HEIGHT = 170;
const FALLBACK_HORIZONTAL_CAPACITY = 5;
const FALLBACK_VERTICAL_CAPACITY = 3;

View File

@@ -1,4 +1,3 @@
export function determinePosition(
canvasRect: DOMRect,
relativeX: number,
@@ -12,6 +11,23 @@ export function determinePosition(
const centerX = canvasRect.width / 2;
const centerY = canvasRect.height / 2;
// Define a threshold for considering a point as "centered"
const centerThreshold = 10; // Adjust this value as needed
// Check if the point is within the center threshold
const isCenterX = Math.abs(relativeX - centerX) <= centerThreshold;
const isCenterY = Math.abs(relativeY - centerY) <= centerThreshold;
// If the point is centered, return a special "centered" position
if (isCenterX && isCenterY) {
return {
top: "auto",
left: "auto",
right: "auto",
bottom: "auto",
};
}
let position: {
top: number | "auto";
left: number | "auto";
@@ -21,7 +37,7 @@ export function determinePosition(
if (relativeY < centerY) {
if (relativeX < centerX) {
// Top-left quadrant
position = {
top: relativeY - 41.5,
left: relativeX - 125,
@@ -29,7 +45,7 @@ export function determinePosition(
bottom: "auto",
};
} else {
// Top-right quadrant
position = {
top: relativeY - 41.5,
right: canvasRect.width - relativeX - 125,
@@ -39,7 +55,7 @@ export function determinePosition(
}
} else {
if (relativeX < centerX) {
// Bottom-left quadrant
position = {
bottom: canvasRect.height - relativeY - 41.5,
left: relativeX - 125,
@@ -47,7 +63,7 @@ export function determinePosition(
top: "auto",
};
} else {
// Bottom-right quadrant
position = {
bottom: canvasRect.height - relativeY - 41.5,
right: canvasRect.width - relativeX - 125,
@@ -58,4 +74,4 @@ export function determinePosition(
}
return position;
}
}

View File

@@ -32,14 +32,22 @@ const DropDownList: React.FC<DropDownListProps> = ({
listType = "default",
remove,
}) => {
const [isOpen, setIsOpen] = useState<boolean>(defaultOpen);
const { zones, setZones } = useZones()
const { zones, setZones } = useZones();
const handleToggle = () => {
setIsOpen((prev) => !prev); // Toggle the state
};
const [zoneDataList, setZoneDataList] = useState<{ id: string; name: string }[]>([]);
interface Asset {
id: string;
name: string;
}
const [zoneDataList, setZoneDataList] = useState<
{ id: string; name: string; assets: Asset[] }[]
>([]);
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
useEffect(() => {
@@ -53,12 +61,65 @@ const DropDownList: React.FC<DropDownListProps> = ({
// { id: "70fa55cd-b5c9-4f80-a8c4-6319af3bfb4e", name: "zone6" },
// ])
const value = (zones || []).map((val: { zoneId: string; zoneName: string }) => ({
id: val.zoneId,
name: val.zoneName
}));
setZoneDataList(prev => (JSON.stringify(prev) !== JSON.stringify(value) ? value : prev));
const value = (zones || []).map(
(val: { zoneId: string; zoneName: string }) => ({
id: val.zoneId,
name: val.zoneName,
})
);
setZoneDataList([
{
id: "zone1",
name: "Zone 1",
assets: [
{
id: "asset1",
name: "Asset 1",
},
{
id: "asset2",
name: "Asset 2",
},
{
id: "asset3",
name: "Asset 3",
},
],
},
{
id: "zone2",
name: "Zone 2",
assets: [
{
id: "asset4",
name: "Asset 4",
},
{
id: "asset5",
name: "Asset 5",
},
{
id: "asset6",
name: "Asset 6",
},
],
},
{
id: "zone3",
name: "Zone 3",
assets: [
{
id: "asset7",
name: "Asset 7",
},
{
id: "asset8",
name: "Asset 8",
},
],
},
]);
}, [zones]);
return (
@@ -101,6 +162,7 @@ const DropDownList: React.FC<DropDownListProps> = ({
value="Buildings"
showKebabMenu={false}
showAddIcon={false}
items={zoneDataList}
/>
<DropDownList
value="Zones"

View File

@@ -1,20 +1,44 @@
import React, { useEffect } from "react";
import React, { useEffect, useState } from "react";
import RenameInput from "../inputs/RenameInput";
import { EyeIcon, LockIcon, RmoveIcon } from "../../icons/ExportCommonIcons";
import { useSelectedZoneStore } from "../../../store/useZoneStore";
import { getZoneData } from "../../../services/realTimeVisulization/zoneData/getZones";
import useModuleStore, { useSubModuleStore } from "../../../store/useModuleStore";
import useModuleStore, {
useSubModuleStore,
} from "../../../store/useModuleStore";
import {
ArrowIcon,
EyeIcon,
LockIcon,
RmoveIcon,
} from "../../icons/ExportCommonIcons";
interface Asset {
id: string;
name: string;
}
interface ZoneItem {
id: string;
name: string;
assets?: Asset[];
}
interface ListProps {
items?: { id: string; name: string }[]; // Optional array of items to render
placeholder?: string; // Optional placeholder text
items?: ZoneItem[];
placeholder?: string;
remove?: boolean;
}
const List: React.FC<ListProps> = ({ items = [], remove }) => {
console.log("items: ", items);
const { activeModule, setActiveModule } = useModuleStore();
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
const { setSubModule } = useSubModuleStore();
const [expandedZones, setExpandedZones] = useState<Record<string, boolean>>(
{}
);
useEffect(() => {
useSelectedZoneStore.getState().setSelectedZone({
zoneName: "",
@@ -27,11 +51,16 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
widgets: [],
});
}, [activeModule]);
const toggleZoneExpansion = (zoneId: string) => {
setExpandedZones((prev) => ({
...prev,
[zoneId]: !prev[zoneId],
}));
};
async function handleSelectZone(id: string) {
try {
// Avoid re-fetching if the same zone is already selected
if (selectedZone?.zoneId === id) {
console.log("Zone is already selected:", selectedZone.zoneName);
return;
@@ -65,27 +94,74 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
<>
{items.length > 0 ? (
<ul className="list-wrapper">
{items.map((item, index) => (
<li key={index} className="list-container">
<div className="list-item">
<div className="value" onClick={() => handleSelectZone(item.id)}>
<RenameInput value={item.name} />
</div>
<div className="options-container">
<div className="lock option">
<LockIcon isLocked />
</div>
<div className="visibe option">
<EyeIcon isClosed />
</div>
{remove && (
<div className="remove option">
<RmoveIcon />
{items.map((item) => (
<React.Fragment key={`zone-${item.id}`}>
<li className="list-container">
<div className="list-item">
<div className="zone-header">
<div
className="value"
onClick={() => handleSelectZone(item.id)}
>
<RenameInput value={item.name} />
</div>
)}
</div>
<div className="options-container">
<div className="lock option">
<LockIcon isLocked />
</div>
<div className="visibe option">
<EyeIcon isClosed />
</div>
{remove && (
<div className="remove option">
<RmoveIcon />
</div>
)}
{item.assets && item.assets.length > 0 && (
<div
className="expand-icon option"
onClick={() => toggleZoneExpansion(item.id)}
>
<ArrowIcon />
</div>
)}
</div>
</div>
</div>
</li>
</li>
{/* Nested assets list - only shown when expanded */}
{item.assets &&
item.assets.length > 0 &&
expandedZones[item.id] && (
<ul className="asset-list">
{item.assets.map((asset) => (
<li
key={`asset-${asset.id}`}
className="list-container asset-item"
>
<div className="list-item">
<div className="value">
<RenameInput value={asset.name} />
</div>
<div className="options-container">
<div className="lock option">
<LockIcon isLocked />
</div>
<div className="visibe option">
<EyeIcon isClosed />
</div>
{remove && (
<div className="remove option">
<RmoveIcon />
</div>
)}
</div>
</div>
</li>
))}
</ul>
)}
</React.Fragment>
))}
</ul>
) : (

View File

@@ -1,6 +1,7 @@
import React, { useState, useRef, useEffect } from "react";
import { ExitIcon, PlayStopIcon, ResetIcon } from "../../icons/SimulationIcons";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
import { useActiveTool } from "../../../store/store";
const SimulationPlayer: React.FC = () => {
const [speed, setSpeed] = useState<number>(1);
@@ -8,6 +9,7 @@ const SimulationPlayer: React.FC = () => {
const { setIsPlaying } = usePlayButtonStore();
const sliderRef = useRef<HTMLDivElement>(null);
const isDragging = useRef(false);
const { setActiveTool } = useActiveTool();
// Button functions
const handleReset = () => {
@@ -19,6 +21,7 @@ const SimulationPlayer: React.FC = () => {
const handleExit = () => {
setPlaySimulation(false);
setIsPlaying(false);
setActiveTool("cursor")
};
// Slider functions starts