Merge pull request '3dWidget dnd and 2d widgets backend api updated' (#21) from rtViz into main
Reviewed-on: http://185.100.212.76:7776/Dwinzo-Beta/Dwinzo_dev/pulls/21
This commit is contained in:
commit
01588cf6c1
|
@ -11,10 +11,10 @@ const CardsScene = () => {
|
||||||
<Canvas>
|
<Canvas>
|
||||||
{/* 3d-cards */}
|
{/* 3d-cards */}
|
||||||
|
|
||||||
<Throughput />
|
|
||||||
{/* <ReturnOfInvestment /> */}
|
|
||||||
{/* <ProductionCapacity /> */}
|
{/* <ProductionCapacity /> */}
|
||||||
|
{/* <ReturnOfInvestment /> */}
|
||||||
{/* <StateWorking /> */}
|
{/* <StateWorking /> */}
|
||||||
|
{/* <Throughput /> */}
|
||||||
|
|
||||||
<OrbitControls />
|
<OrbitControls />
|
||||||
</Canvas>
|
</Canvas>
|
||||||
|
|
|
@ -21,8 +21,11 @@ ChartJS.register(
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Legend
|
Legend
|
||||||
);
|
);
|
||||||
|
interface ProductionCapacityProps {
|
||||||
|
position: [number, number, number];
|
||||||
|
}
|
||||||
|
|
||||||
const ProductionCapacity = () => {
|
const ProductionCapacity : React.FC<ProductionCapacityProps> = ({ position }) => {
|
||||||
// Chart data for a week
|
// Chart data for a week
|
||||||
const chartData = {
|
const chartData = {
|
||||||
labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], // Days of the week
|
labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], // Days of the week
|
||||||
|
@ -76,7 +79,10 @@ const ProductionCapacity = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Html position={[0, 0, 0]} transform occlude>
|
<Html position={[position[0], position[1], position[2]]}
|
||||||
|
scale={[0.5, 0.5, 0.5]}
|
||||||
|
transform
|
||||||
|
sprite>
|
||||||
<div className="productionCapacity-wrapper card">
|
<div className="productionCapacity-wrapper card">
|
||||||
<div className="headeproductionCapacityr-wrapper">
|
<div className="headeproductionCapacityr-wrapper">
|
||||||
<div className="header">Production Capacity</div>
|
<div className="header">Production Capacity</div>
|
||||||
|
|
|
@ -35,8 +35,10 @@ const SmoothLineGraphComponent: React.FC<SmoothLineGraphProps> = ({
|
||||||
}) => {
|
}) => {
|
||||||
return <Line data={data} options={options} />;
|
return <Line data={data} options={options} />;
|
||||||
};
|
};
|
||||||
|
interface ReturnOfInvestmentProps {
|
||||||
const ReturnOfInvestment = () => {
|
position: [number, number, number];
|
||||||
|
}
|
||||||
|
const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ position }) => {
|
||||||
// Improved sample data for the smooth curve graph (single day)
|
// Improved sample data for the smooth curve graph (single day)
|
||||||
const graphData: ChartData<"line"> = {
|
const graphData: ChartData<"line"> = {
|
||||||
labels: [
|
labels: [
|
||||||
|
@ -106,7 +108,10 @@ const ReturnOfInvestment = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Html position={[0, 0, 0]} transform occlude>
|
<Html position={[position[0], position[1], position[2]]}
|
||||||
|
scale={[0.5, 0.5, 0.5]}
|
||||||
|
transform
|
||||||
|
sprite>
|
||||||
<div className="returnOfInvestment card">
|
<div className="returnOfInvestment card">
|
||||||
<div className="header">Return of Investment</div>
|
<div className="header">Return of Investment</div>
|
||||||
<div className="lineGraph charts">
|
<div className="lineGraph charts">
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import { Html } from "@react-three/drei";
|
import { Html } from "@react-three/drei";
|
||||||
import image from "../../../../assets/image/temp/image.png";
|
// import image from "../../../../assets/image/temp/image.png";
|
||||||
const StateWorking = () => {
|
interface StateWorkingProps {
|
||||||
|
position: [number, number, number];
|
||||||
|
}
|
||||||
|
const StateWorking: React.FC<StateWorkingProps> = ({ position }) => {
|
||||||
const datas = [
|
const datas = [
|
||||||
{ key: "Oil Tank:", value: "24/341" },
|
{ key: "Oil Tank:", value: "24/341" },
|
||||||
{ key: "Oil Refin:", value: 36.023 },
|
{ key: "Oil Refin:", value: 36.023 },
|
||||||
|
@ -10,7 +13,10 @@ const StateWorking = () => {
|
||||||
{ key: "Time:", value: 13 - 9 - 2023 },
|
{ key: "Time:", value: 13 - 9 - 2023 },
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<Html position={[0, 0, 0]} transform occlude>
|
<Html position={[position[0], position[1], position[2]]}
|
||||||
|
scale={[0.5, 0.5, 0.5]}
|
||||||
|
transform
|
||||||
|
sprite>
|
||||||
<div className="stateWorking-wrapper card">
|
<div className="stateWorking-wrapper card">
|
||||||
<div className="header-wrapper">
|
<div className="header-wrapper">
|
||||||
<div className="header">
|
<div className="header">
|
||||||
|
@ -20,7 +26,7 @@ const StateWorking = () => {
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="img">
|
<div className="img">
|
||||||
<img src={image} alt="" />
|
{/* <img src={image} alt="" /> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* Data */}
|
{/* Data */}
|
||||||
|
|
|
@ -37,7 +37,12 @@ const LineGraphComponent: React.FC<LineGraphProps> = ({ data, options }) => {
|
||||||
return <Line data={data} options={options} />;
|
return <Line data={data} options={options} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Throughput = () => {
|
interface ThroughputProps {
|
||||||
|
position: [number, number, number];
|
||||||
|
}
|
||||||
|
|
||||||
|
const Throughput: React.FC<ThroughputProps> = ({ position }) => {
|
||||||
|
|
||||||
// Sample data for the line graph
|
// Sample data for the line graph
|
||||||
const graphData: ChartData<"line"> = {
|
const graphData: ChartData<"line"> = {
|
||||||
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
|
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
|
||||||
|
@ -86,7 +91,10 @@ const Throughput = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Html position={[0, 0, 0]} transform occlude>
|
<Html position={[position[0], position[1], position[2]]}
|
||||||
|
scale={[0.5, 0.5, 0.5]}
|
||||||
|
transform
|
||||||
|
sprite>
|
||||||
<div className="throughput-wrapper">
|
<div className="throughput-wrapper">
|
||||||
<div className="header">Throughput</div>
|
<div className="header">Throughput</div>
|
||||||
<div className="display-value">
|
<div className="display-value">
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import { ChartType } from "chart.js/auto";
|
import { ChartType } from "chart.js/auto";
|
||||||
import ChartComponent from "./ChartComponent";
|
import ChartComponent from "./ChartComponent";
|
||||||
import { StockIncreseIcon } from "../../../../icons/RealTimeVisulationIcons";
|
import { StockIncreseIcon } from "../../../../icons/RealTimeVisulationIcons";
|
||||||
|
import { generateUniqueId } from "../../../../../functions/generateUniqueId";
|
||||||
|
|
||||||
const chartTypes: ChartType[] = [
|
const chartTypes: ChartType[] = [
|
||||||
"bar",
|
"bar",
|
||||||
|
@ -40,7 +41,8 @@ const ChartWidget: React.FC<WidgetProps> = ({ type, index, title }) => {
|
||||||
onDragStart={() => {
|
onDragStart={() => {
|
||||||
setDraggedAsset({
|
setDraggedAsset({
|
||||||
type,
|
type,
|
||||||
id: `widget-${index + 1}`,
|
id: generateUniqueId(
|
||||||
|
),
|
||||||
title,
|
title,
|
||||||
panel: "top",
|
panel: "top",
|
||||||
data: sampleData,
|
data: sampleData,
|
||||||
|
|
|
@ -2,6 +2,7 @@ import widget1 from "../../../../../assets/image/3D/ProductionCapacity.png";
|
||||||
import widget2 from "../../../../../assets/image/3D/ReturnOfInvestment.png";
|
import widget2 from "../../../../../assets/image/3D/ReturnOfInvestment.png";
|
||||||
import widget3 from "../../../../../assets/image/3D/StateWorking.png";
|
import widget3 from "../../../../../assets/image/3D/StateWorking.png";
|
||||||
import widget4 from "../../../../../assets/image/3D/Throughput.png";
|
import widget4 from "../../../../../assets/image/3D/Throughput.png";
|
||||||
|
import { useAsset3dWidget } from "../../../../../store/store";
|
||||||
const Widgets3D = () => {
|
const Widgets3D = () => {
|
||||||
const widgets = [
|
const widgets = [
|
||||||
{ name: "Widget 1", img: widget1 },
|
{ name: "Widget 1", img: widget1 },
|
||||||
|
@ -9,17 +10,38 @@ const Widgets3D = () => {
|
||||||
{ name: "Widget 3", img: widget3 },
|
{ name: "Widget 3", img: widget3 },
|
||||||
{ name: "Widget 4", img: widget4 },
|
{ name: "Widget 4", img: widget4 },
|
||||||
];
|
];
|
||||||
|
const { widgetSelect, setWidgetSelect } = useAsset3dWidget();
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="widgets-container widget3D">
|
<div className="widgets-container widget3D">
|
||||||
{widgets?.map((widget, index) => (
|
{widgets?.map((widget, index) => (
|
||||||
<div key={index} className="widget-item" draggable>
|
<div
|
||||||
<div className="widget-name">{widget.name}</div>
|
key={index}
|
||||||
|
className="widget-item"
|
||||||
|
draggable
|
||||||
|
onDragStart={(e) => {
|
||||||
|
let crt = e.target
|
||||||
|
if (crt instanceof HTMLElement) {
|
||||||
|
const widget = crt.cloneNode(true) as HTMLElement;
|
||||||
|
console.log('widget: ', widget);
|
||||||
|
e.dataTransfer.setDragImage(widget,0,0)
|
||||||
|
e.dataTransfer.effectAllowed="move"
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onPointerDown={() => {
|
||||||
|
setWidgetSelect("ui-" + widget.name);
|
||||||
|
}}
|
||||||
|
onPointerUp={() => {
|
||||||
|
setWidgetSelect(""); // Clearing selection correctly
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* <div className="widget-name">{widget.name}</div> */}
|
||||||
<img
|
<img
|
||||||
className="widget-image"
|
className="widget-image"
|
||||||
src={widget.img}
|
src={widget.img}
|
||||||
alt={widget.name}
|
alt={widget.name}
|
||||||
draggable={false}
|
// draggable={false}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -16,6 +16,7 @@ interface ButtonsProps {
|
||||||
zoneName: string;
|
zoneName: string;
|
||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
|
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
zoneId: string;
|
zoneId: string;
|
||||||
zoneViewPortTarget: number[];
|
zoneViewPortTarget: number[];
|
||||||
|
@ -33,6 +34,7 @@ interface ButtonsProps {
|
||||||
zoneName: string;
|
zoneName: string;
|
||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
|
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
zoneId: string;
|
zoneId: string;
|
||||||
zoneViewPortTarget: number[];
|
zoneViewPortTarget: number[];
|
||||||
|
@ -120,23 +122,39 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
||||||
console.log("updatedZone: ", updatedZone);
|
console.log("updatedZone: ", updatedZone);
|
||||||
setSelectedZone(updatedZone);
|
setSelectedZone(updatedZone);
|
||||||
} else {
|
} else {
|
||||||
// If the panel is not active, activate it
|
const updatePanelData = async () => {
|
||||||
const newActiveSides = [...selectedZone.activeSides, side];
|
try {
|
||||||
|
// Get email and organization safely
|
||||||
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0] || "defaultOrg"; // Fallback value
|
||||||
|
|
||||||
const updatedZone = {
|
// Prevent duplicate side entries
|
||||||
...selectedZone,
|
const newActiveSides = selectedZone.activeSides.includes(side)
|
||||||
activeSides: newActiveSides,
|
? [...selectedZone.activeSides]
|
||||||
panelOrder: newActiveSides,
|
: [...selectedZone.activeSides, side];
|
||||||
|
|
||||||
|
const updatedZone = {
|
||||||
|
...selectedZone,
|
||||||
|
activeSides: newActiveSides,
|
||||||
|
panelOrder: newActiveSides,
|
||||||
|
};
|
||||||
|
|
||||||
|
// API call
|
||||||
|
const response = await panelData(organization, selectedZone.zoneId, newActiveSides);
|
||||||
|
console.log("response: ", response);
|
||||||
|
|
||||||
|
// Update state
|
||||||
|
console.log("updatedZone: ", updatedZone);
|
||||||
|
setSelectedZone(updatedZone);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error updating panel data:", error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const email = localStorage.getItem("email");
|
|
||||||
const organization = email!.split("@")[1].split(".")[0];
|
|
||||||
// let response = panelData(organization, selectedZone.zoneId, newActiveSides)
|
|
||||||
// console.log('response: ', response);
|
|
||||||
|
|
||||||
// Update the selectedZone state
|
updatePanelData(); // Call the async function
|
||||||
console.log("updatedZone: ", updatedZone);
|
|
||||||
setSelectedZone(updatedZone);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -146,9 +164,8 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
||||||
<div key={side} className={`side-button-container ${side}`}>
|
<div key={side} className={`side-button-container ${side}`}>
|
||||||
{/* "+" Button */}
|
{/* "+" Button */}
|
||||||
<button
|
<button
|
||||||
className={`side-button ${side}${
|
className={`side-button ${side}${selectedZone.activeSides.includes(side) ? " active" : ""
|
||||||
selectedZone.activeSides.includes(side) ? " active" : ""
|
}`}
|
||||||
}`}
|
|
||||||
onClick={() => handlePlusButtonClick(side)}
|
onClick={() => handlePlusButtonClick(side)}
|
||||||
title={
|
title={
|
||||||
selectedZone.activeSides.includes(side)
|
selectedZone.activeSides.includes(side)
|
||||||
|
@ -166,9 +183,8 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
||||||
<div className="extra-Bs">
|
<div className="extra-Bs">
|
||||||
{/* Hide Panel */}
|
{/* Hide Panel */}
|
||||||
<div
|
<div
|
||||||
className={`icon ${
|
className={`icon ${hiddenPanels.includes(side) ? "active" : ""
|
||||||
hiddenPanels.includes(side) ? "active" : ""
|
}`}
|
||||||
}`}
|
|
||||||
title={
|
title={
|
||||||
hiddenPanels.includes(side) ? "Show Panel" : "Hide Panel"
|
hiddenPanels.includes(side) ? "Show Panel" : "Hide Panel"
|
||||||
}
|
}
|
||||||
|
@ -190,9 +206,8 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
||||||
|
|
||||||
{/* Lock/Unlock Panel */}
|
{/* Lock/Unlock Panel */}
|
||||||
<div
|
<div
|
||||||
className={`icon ${
|
className={`icon ${selectedZone.lockedPanels.includes(side) ? "active" : ""
|
||||||
selectedZone.lockedPanels.includes(side) ? "active" : ""
|
}`}
|
||||||
}`}
|
|
||||||
title={
|
title={
|
||||||
selectedZone.lockedPanels.includes(side)
|
selectedZone.lockedPanels.includes(side)
|
||||||
? "Unlock Panel"
|
? "Unlock Panel"
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { Widget } from "../../../store/useWidgetStore";
|
||||||
import { MoveArrowLeft, MoveArrowRight } from "../../icons/SimulationIcons";
|
import { MoveArrowLeft, MoveArrowRight } from "../../icons/SimulationIcons";
|
||||||
import { InfoIcon } from "../../icons/ExportCommonIcons";
|
import { InfoIcon } from "../../icons/ExportCommonIcons";
|
||||||
import { useDroppedObjectsStore } from "../../../store/useDroppedObjectsStore";
|
import { useDroppedObjectsStore } from "../../../store/useDroppedObjectsStore";
|
||||||
|
import { getSelect2dZoneData } from "../../../services/realTimeVisulization/zoneData/getSelect2dZoneData";
|
||||||
|
|
||||||
// Define the type for `Side`
|
// Define the type for `Side`
|
||||||
type Side = "top" | "bottom" | "left" | "right";
|
type Side = "top" | "bottom" | "left" | "right";
|
||||||
|
@ -12,6 +13,7 @@ interface DisplayZoneProps {
|
||||||
[key: string]: {
|
[key: string]: {
|
||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
|
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
widgets: Widget[];
|
widgets: Widget[];
|
||||||
zoneId: string;
|
zoneId: string;
|
||||||
|
@ -23,6 +25,7 @@ interface DisplayZoneProps {
|
||||||
zoneName: string;
|
zoneName: string;
|
||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
|
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
zoneId: string;
|
zoneId: string;
|
||||||
zoneViewPortTarget: number[];
|
zoneViewPortTarget: number[];
|
||||||
|
@ -40,6 +43,7 @@ interface DisplayZoneProps {
|
||||||
zoneName: string;
|
zoneName: string;
|
||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
|
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
zoneId: string;
|
zoneId: string;
|
||||||
zoneViewPortTarget: number[];
|
zoneViewPortTarget: number[];
|
||||||
|
@ -60,6 +64,7 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
|
||||||
selectedZone,
|
selectedZone,
|
||||||
setSelectedZone,
|
setSelectedZone,
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
// Ref for the container element
|
// Ref for the container element
|
||||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
|
@ -141,11 +146,28 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async function handleSelect2dZoneData(zoneId: string, zoneName: string) {
|
||||||
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0]
|
||||||
|
let response = await getSelect2dZoneData(zoneId, organization)
|
||||||
|
setSelectedZone({
|
||||||
|
zoneName,
|
||||||
|
activeSides: response.activeSides,
|
||||||
|
panelOrder: response.panelOrder,
|
||||||
|
lockedPanels: response.lockedPanels,
|
||||||
|
widgets: response.widgets,
|
||||||
|
zoneId: zoneId,
|
||||||
|
zoneViewPortTarget:
|
||||||
|
response.viewPortCenter,
|
||||||
|
zoneViewPortPosition:
|
||||||
|
response.viewPortposition,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`zone-wrapper ${
|
className={`zone-wrapper ${selectedZone?.activeSides?.includes("bottom") && "bottom"
|
||||||
selectedZone?.activeSides?.includes("bottom") && "bottom"
|
}`}
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
{/* Left Arrow */}
|
{/* Left Arrow */}
|
||||||
{showLeftArrow && (
|
{showLeftArrow && (
|
||||||
|
@ -160,23 +182,11 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
|
||||||
{Object.keys(zonesData).map((zoneName, index) => (
|
{Object.keys(zonesData).map((zoneName, index) => (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className={`zone ${
|
className={`zone ${selectedZone.zoneName === zoneName ? "active" : ""
|
||||||
selectedZone.zoneName === zoneName ? "active" : ""
|
}`}
|
||||||
}`}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
useDroppedObjectsStore.getState().setZone(zoneName, zonesData[zoneName]?.zoneId);
|
useDroppedObjectsStore.getState().setZone(zoneName, zonesData[zoneName]?.zoneId);
|
||||||
setSelectedZone({
|
handleSelect2dZoneData(zonesData[zoneName]?.zoneId, zoneName)
|
||||||
zoneName,
|
|
||||||
activeSides: zonesData[zoneName].activeSides || [],
|
|
||||||
panelOrder: zonesData[zoneName].panelOrder || [],
|
|
||||||
lockedPanels: zonesData[zoneName].lockedPanels || [],
|
|
||||||
widgets: zonesData[zoneName].widgets || [],
|
|
||||||
zoneId: zonesData[zoneName]?.zoneId || "",
|
|
||||||
zoneViewPortTarget:
|
|
||||||
zonesData[zoneName].zoneViewPortTarget || [],
|
|
||||||
zoneViewPortPosition:
|
|
||||||
zonesData[zoneName].zoneViewPortPosition || [],
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{zoneName}
|
{zoneName}
|
||||||
|
|
|
@ -36,6 +36,7 @@ export const DraggableWidget = ({
|
||||||
zoneName: string;
|
zoneName: string;
|
||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
|
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
widgets: Widget[];
|
widgets: Widget[];
|
||||||
};
|
};
|
||||||
|
@ -44,6 +45,7 @@ export const DraggableWidget = ({
|
||||||
zoneName: string;
|
zoneName: string;
|
||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
|
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
zoneId: string;
|
zoneId: string;
|
||||||
zoneViewPortTarget: number[];
|
zoneViewPortTarget: number[];
|
||||||
|
@ -78,9 +80,11 @@ export const DraggableWidget = ({
|
||||||
const isPanelHidden = hiddenPanels.includes(widget.panel);
|
const isPanelHidden = hiddenPanels.includes(widget.panel);
|
||||||
|
|
||||||
const deleteSelectedChart = () => {
|
const deleteSelectedChart = () => {
|
||||||
|
console.log('widget.id: ', widget.id);
|
||||||
const updatedWidgets = selectedZone.widgets.filter(
|
const updatedWidgets = selectedZone.widgets.filter(
|
||||||
(w: Widget) => w.id !== widget.id
|
(w: Widget) => w.id !== widget.id
|
||||||
);
|
);
|
||||||
|
console.log('updatedWidgets: ', updatedWidgets);
|
||||||
|
|
||||||
setSelectedZone((prevZone: any) => ({
|
setSelectedZone((prevZone: any) => ({
|
||||||
...prevZone,
|
...prevZone,
|
||||||
|
@ -122,7 +126,6 @@ export const DraggableWidget = ({
|
||||||
...widget,
|
...widget,
|
||||||
id: `${widget.id}-copy-${Date.now()}`,
|
id: `${widget.id}-copy-${Date.now()}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
setSelectedZone((prevZone: any) => ({
|
setSelectedZone((prevZone: any) => ({
|
||||||
...prevZone,
|
...prevZone,
|
||||||
widgets: [...prevZone.widgets, duplicatedWidget],
|
widgets: [...prevZone.widgets, duplicatedWidget],
|
||||||
|
@ -130,7 +133,7 @@ export const DraggableWidget = ({
|
||||||
|
|
||||||
setOpenKebabId(null);
|
setOpenKebabId(null);
|
||||||
|
|
||||||
console.log("Duplicated widget with ID:", duplicatedWidget.id);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleKebabClick = (event: React.MouseEvent<HTMLDivElement>) => {
|
const handleKebabClick = (event: React.MouseEvent<HTMLDivElement>) => {
|
||||||
|
@ -173,6 +176,7 @@ export const DraggableWidget = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {
|
const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const fromIndex = parseInt(event.dataTransfer.getData("text/plain"), 10); // Get the dragged widget's index
|
const fromIndex = parseInt(event.dataTransfer.getData("text/plain"), 10); // Get the dragged widget's index
|
||||||
const toIndex = index; // The index of the widget where the drop occurred
|
const toIndex = index; // The index of the widget where the drop occurred
|
||||||
|
@ -186,9 +190,8 @@ export const DraggableWidget = ({
|
||||||
<div
|
<div
|
||||||
draggable
|
draggable
|
||||||
key={widget.id}
|
key={widget.id}
|
||||||
className={`chart-container ${
|
className={`chart-container ${selectedChartId?.id === widget.id && "activeChart"
|
||||||
selectedChartId?.id === widget.id && "activeChart"
|
}`}
|
||||||
}`}
|
|
||||||
onPointerDown={handlePointerDown}
|
onPointerDown={handlePointerDown}
|
||||||
onDragStart={handleDragStart}
|
onDragStart={handleDragStart}
|
||||||
onDragEnter={handleDragEnter}
|
onDragEnter={handleDragEnter}
|
||||||
|
@ -208,9 +211,8 @@ export const DraggableWidget = ({
|
||||||
{openKebabId === widget.id && (
|
{openKebabId === widget.id && (
|
||||||
<div className="kebab-options" ref={widgetRef}>
|
<div className="kebab-options" ref={widgetRef}>
|
||||||
<div
|
<div
|
||||||
className={`edit btn ${
|
className={`edit btn ${isPanelFull(widget.panel) ? "btn-blur" : ""
|
||||||
isPanelFull(widget.panel) ? "btn-blur" : ""
|
}`}
|
||||||
}`}
|
|
||||||
onClick={isPanelFull(widget.panel) ? undefined : duplicateWidget}
|
onClick={isPanelFull(widget.panel) ? undefined : duplicateWidget}
|
||||||
>
|
>
|
||||||
<div className="icon">
|
<div className="icon">
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
|
||||||
|
import { useThree } from "@react-three/fiber";
|
||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { useAsset3dWidget } from "../../../store/store";
|
||||||
|
import useModuleStore from "../../../store/useModuleStore";
|
||||||
|
import { ThreeState } from "../../../types/world/worldTypes";
|
||||||
|
import * as THREE from "three";
|
||||||
|
import Throughput from "../../layout/3D-cards/cards/Throughput";
|
||||||
|
import ProductionCapacity from "../../layout/3D-cards/cards/ProductionCapacity";
|
||||||
|
import ReturnOfInvestment from "../../layout/3D-cards/cards/ReturnOfInvestment";
|
||||||
|
import StateWorking from "../../layout/3D-cards/cards/StateWorking";
|
||||||
|
|
||||||
|
export default function Dropped3dWidgets() {
|
||||||
|
const { widgetSelect } = useAsset3dWidget();
|
||||||
|
const { activeModule } = useModuleStore();
|
||||||
|
const { raycaster, gl, scene }: ThreeState = useThree();
|
||||||
|
|
||||||
|
// 🔥 Store multiple instances per widget type
|
||||||
|
const [widgetPositions, setWidgetPositions] = useState<Record<string, [number, number, number][]>>({});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (activeModule !== "visualization") return;
|
||||||
|
const canvasElement = gl.domElement;
|
||||||
|
|
||||||
|
const onDrop = (event: DragEvent) => {
|
||||||
|
event.preventDefault(); // Prevent default browser behavior
|
||||||
|
|
||||||
|
if (!widgetSelect.startsWith("ui")) return;
|
||||||
|
|
||||||
|
|
||||||
|
const group1 = scene.getObjectByName("itemsGroup");
|
||||||
|
if (!group1) return;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const Assets = group1.children
|
||||||
|
.map((val) => scene.getObjectByProperty("uuid", val.uuid))
|
||||||
|
.filter(Boolean) as THREE.Object3D[];
|
||||||
|
|
||||||
|
|
||||||
|
const intersects = raycaster.intersectObjects(Assets);
|
||||||
|
|
||||||
|
if (intersects.length > 0) {
|
||||||
|
const { x, y, z } = intersects[0].point;
|
||||||
|
|
||||||
|
|
||||||
|
// ✅ Allow multiple instances by storing positions in an array
|
||||||
|
setWidgetPositions((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[widgetSelect]: [...(prev[widgetSelect] || []), [x, y, z]],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
canvasElement.addEventListener("drop", onDrop);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
canvasElement.removeEventListener("drop", onDrop);
|
||||||
|
};
|
||||||
|
}, [widgetSelect, activeModule]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{widgetPositions["ui-Widget 1"]?.map((pos, index) => (
|
||||||
|
<ProductionCapacity key={`Widget1-${index}`} position={pos} />
|
||||||
|
))}
|
||||||
|
{widgetPositions["ui-Widget 2"]?.map((pos, index) => (
|
||||||
|
<ReturnOfInvestment key={`Widget2-${index}`} position={pos} />
|
||||||
|
))}
|
||||||
|
{widgetPositions["ui-Widget 3"]?.map((pos, index) => (
|
||||||
|
<StateWorking key={`Widget3-${index}`} position={pos} />
|
||||||
|
))}
|
||||||
|
{widgetPositions["ui-Widget 4"]?.map((pos, index) => (
|
||||||
|
<Throughput key={`Widget4-${index}`} position={pos} />
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { useDroppedObjectsStore, Zones } from "../../../store/useDroppedObjectsS
|
||||||
|
|
||||||
const DroppedObjects: React.FC = () => {
|
const DroppedObjects: React.FC = () => {
|
||||||
const zones = useDroppedObjectsStore((state) => state.zones);
|
const zones = useDroppedObjectsStore((state) => state.zones);
|
||||||
|
|
||||||
const updateObjectPosition = useDroppedObjectsStore((state) => state.updateObjectPosition);
|
const updateObjectPosition = useDroppedObjectsStore((state) => state.updateObjectPosition);
|
||||||
const [draggingIndex, setDraggingIndex] = useState<{ zone: string; index: number } | null>(null);
|
const [draggingIndex, setDraggingIndex] = useState<{ zone: string; index: number } | null>(null);
|
||||||
const [offset, setOffset] = useState<[number, number] | null>(null);
|
const [offset, setOffset] = useState<[number, number] | null>(null);
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { useWidgetStore } from "../../../store/useWidgetStore";
|
||||||
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
||||||
import { DraggableWidget } from "./DraggableWidget";
|
import { DraggableWidget } from "./DraggableWidget";
|
||||||
import { arrayMove } from "@dnd-kit/sortable";
|
import { arrayMove } from "@dnd-kit/sortable";
|
||||||
|
import { addingWidgets } from "../../../services/realTimeVisulization/zoneData/addWidgets";
|
||||||
|
|
||||||
type Side = "top" | "bottom" | "left" | "right";
|
type Side = "top" | "bottom" | "left" | "right";
|
||||||
|
|
||||||
|
@ -19,6 +20,7 @@ interface PanelProps {
|
||||||
zoneName: string;
|
zoneName: string;
|
||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
|
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
zoneId: string;
|
zoneId: string;
|
||||||
zoneViewPortTarget: number[];
|
zoneViewPortTarget: number[];
|
||||||
|
@ -30,6 +32,7 @@ interface PanelProps {
|
||||||
zoneName: string;
|
zoneName: string;
|
||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
|
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
zoneId: string;
|
zoneId: string;
|
||||||
zoneViewPortTarget: number[];
|
zoneViewPortTarget: number[];
|
||||||
|
@ -72,9 +75,8 @@ const Panel: React.FC<PanelProps> = ({
|
||||||
case "top":
|
case "top":
|
||||||
case "bottom":
|
case "bottom":
|
||||||
return {
|
return {
|
||||||
width: `calc(100% - ${
|
width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)
|
||||||
(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)
|
}px)`,
|
||||||
}px)`,
|
|
||||||
height: `${panelSize - 2}px`,
|
height: `${panelSize - 2}px`,
|
||||||
left: leftActive ? `${panelSize}px` : "0",
|
left: leftActive ? `${panelSize}px` : "0",
|
||||||
right: rightActive ? `${panelSize}px` : "0",
|
right: rightActive ? `${panelSize}px` : "0",
|
||||||
|
@ -84,9 +86,8 @@ const Panel: React.FC<PanelProps> = ({
|
||||||
case "right":
|
case "right":
|
||||||
return {
|
return {
|
||||||
width: `${panelSize - 2}px`,
|
width: `${panelSize - 2}px`,
|
||||||
height: `calc(100% - ${
|
height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)
|
||||||
(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)
|
}px)`,
|
||||||
}px)`,
|
|
||||||
top: topActive ? `${panelSize}px` : "0",
|
top: topActive ? `${panelSize}px` : "0",
|
||||||
bottom: bottomActive ? `${panelSize}px` : "0",
|
bottom: bottomActive ? `${panelSize}px` : "0",
|
||||||
[side]: "0",
|
[side]: "0",
|
||||||
|
@ -99,6 +100,7 @@ const Panel: React.FC<PanelProps> = ({
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDrop = (e: React.DragEvent, panel: Side) => {
|
const handleDrop = (e: React.DragEvent, panel: Side) => {
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const { draggedAsset } = useWidgetStore.getState();
|
const { draggedAsset } = useWidgetStore.getState();
|
||||||
if (!draggedAsset) return;
|
if (!draggedAsset) return;
|
||||||
|
@ -109,8 +111,6 @@ const Panel: React.FC<PanelProps> = ({
|
||||||
|
|
||||||
if (currentWidgetsCount >= maxCapacity) return;
|
if (currentWidgetsCount >= maxCapacity) return;
|
||||||
|
|
||||||
console.log("draggedAsset: ", draggedAsset);
|
|
||||||
console.log("panel: ", panel);
|
|
||||||
addWidgetToPanel(draggedAsset, panel);
|
addWidgetToPanel(draggedAsset, panel);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -139,17 +139,27 @@ const Panel: React.FC<PanelProps> = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
// while dublicate check this and add
|
// while dublicate check this and add
|
||||||
const addWidgetToPanel = (asset: any, panel: Side) => {
|
const addWidgetToPanel = async (asset: any, panel: Side) => {
|
||||||
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0]
|
||||||
const newWidget = {
|
const newWidget = {
|
||||||
...asset,
|
...asset,
|
||||||
id: generateUniqueId(),
|
id: generateUniqueId(),
|
||||||
panel,
|
panel,
|
||||||
};
|
};
|
||||||
|
try {
|
||||||
|
let response = await addingWidgets(selectedZone.zoneId, organization, newWidget);
|
||||||
|
console.log("response: ", response);
|
||||||
|
if (response.message === "Widget created successfully") {
|
||||||
|
setSelectedZone((prev) => ({
|
||||||
|
...prev,
|
||||||
|
widgets: [...prev.widgets, newWidget],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error adding widget:", error);
|
||||||
|
}
|
||||||
|
|
||||||
setSelectedZone((prev) => ({
|
|
||||||
...prev,
|
|
||||||
widgets: [...prev.widgets, newWidget],
|
|
||||||
}));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -180,7 +190,7 @@ const Panel: React.FC<PanelProps> = ({
|
||||||
|
|
||||||
const handleReorder = (fromIndex: number, toIndex: number, panel: Side) => {
|
const handleReorder = (fromIndex: number, toIndex: number, panel: Side) => {
|
||||||
if (!selectedZone) return; // Ensure selectedZone is not null
|
if (!selectedZone) return; // Ensure selectedZone is not null
|
||||||
console.log("selectedZone: ", selectedZone);
|
|
||||||
|
|
||||||
setSelectedZone((prev) => {
|
setSelectedZone((prev) => {
|
||||||
if (!prev) return prev; // Ensure prev is not null
|
if (!prev) return prev; // Ensure prev is not null
|
||||||
|
|
|
@ -9,7 +9,9 @@ import useModuleStore from "../../../store/useModuleStore";
|
||||||
|
|
||||||
import DroppedObjects from "./DroppedFloatingWidgets";
|
import DroppedObjects from "./DroppedFloatingWidgets";
|
||||||
import { useDroppedObjectsStore } from "../../../store/useDroppedObjectsStore";
|
import { useDroppedObjectsStore } from "../../../store/useDroppedObjectsStore";
|
||||||
import { useZones } from "../../../store/store";
|
import { useAsset3dWidget, useZones } from "../../../store/store";
|
||||||
|
import { getZoneData } from "../../../services/realTimeVisulization/zoneData/getZones";
|
||||||
|
import { getZone2dData } from "../../../services/realTimeVisulization/zoneData/getZoneData";
|
||||||
|
|
||||||
|
|
||||||
type Side = "top" | "bottom" | "left" | "right";
|
type Side = "top" | "bottom" | "left" | "right";
|
||||||
|
@ -19,6 +21,7 @@ type FormattedZoneData = Record<
|
||||||
{
|
{
|
||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
|
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
zoneId: string;
|
zoneId: string;
|
||||||
zoneViewPortTarget: number[];
|
zoneViewPortTarget: number[];
|
||||||
|
@ -43,25 +46,38 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
const [zonesData, setZonesData] = useState<FormattedZoneData>({});
|
const [zonesData, setZonesData] = useState<FormattedZoneData>({});
|
||||||
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
||||||
const { zones } = useZones()
|
const { zones } = useZones()
|
||||||
|
const [floatingWidgets, setFloatingWidgets] = useState<Record<string, { zoneName: string; zoneId: string; objects: any[] }>>({});
|
||||||
|
const { widgetSelect, setWidgetSelect } = useAsset3dWidget();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const data = Array.isArray(zones) ? zones : [];
|
async function GetZoneData() {
|
||||||
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0];
|
||||||
|
try {
|
||||||
|
const response = await getZone2dData(organization);
|
||||||
|
if (!Array.isArray(response)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const formattedData = response.reduce<FormattedZoneData>((acc, zone) => {
|
||||||
|
acc[zone.zoneName] = {
|
||||||
|
activeSides: [],
|
||||||
|
panelOrder: [],
|
||||||
|
lockedPanels: [],
|
||||||
|
zoneId: zone.zoneId,
|
||||||
|
zoneViewPortTarget: zone.viewPortCenter,
|
||||||
|
zoneViewPortPosition: zone.viewPortposition,
|
||||||
|
widgets: [],
|
||||||
|
};
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
setZonesData(formattedData);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('error: ', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const formattedData = data.reduce<FormattedZoneData>((acc, zone) => {
|
GetZoneData();
|
||||||
acc[zone.zoneName] = {
|
}, []); // Removed `zones` from dependencies
|
||||||
activeSides: [],
|
|
||||||
panelOrder: [],
|
|
||||||
lockedPanels: [],
|
|
||||||
zoneId: zone.zoneId,
|
|
||||||
zoneViewPortTarget: zone.viewPortCenter,
|
|
||||||
zoneViewPortPosition: zone.viewPortposition,
|
|
||||||
widgets: [],
|
|
||||||
};
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
setZonesData(formattedData);
|
|
||||||
}, [zones]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setZonesData((prev) => {
|
setZonesData((prev) => {
|
||||||
|
@ -81,37 +97,47 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}, [selectedZone]);
|
}, [selectedZone]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
}, [floatingWidgets])
|
||||||
|
|
||||||
const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {
|
const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const data = event.dataTransfer.getData("text/plain");
|
const data = event.dataTransfer.getData("text/plain");
|
||||||
if (!data || !selectedZone.zoneName) return;
|
if (widgetSelect !== "") return;
|
||||||
|
if (!data || selectedZone.zoneName === "") return;
|
||||||
|
|
||||||
const droppedData = JSON.parse(data);
|
const droppedData = JSON.parse(data);
|
||||||
const canvasElement = document.getElementById("real-time-vis-canvas");
|
const canvasElement = document.getElementById("real-time-vis-canvas");
|
||||||
if (!canvasElement) return;
|
if (!canvasElement) return;
|
||||||
|
|
||||||
const canvasRect = canvasElement.getBoundingClientRect();
|
const canvasRect = canvasElement.getBoundingClientRect();
|
||||||
const relativeX = event.clientX - canvasRect.left;
|
const relativeX = event.clientX - canvasRect.left;
|
||||||
const relativeY = event.clientY - canvasRect.top;
|
const relativeY = event.clientY - canvasRect.top;
|
||||||
|
|
||||||
const newObject = {
|
const newObject = {
|
||||||
...droppedData,
|
...droppedData,
|
||||||
position: [relativeY, relativeX], // Y first because of top/left style
|
position: [relativeY, relativeX], // Y first because of top/left style
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log("newObject: ", newObject);
|
|
||||||
|
|
||||||
// Only set zone if it’s not already in the store (prevents overwriting objects)
|
// Only set zone if it’s not already in the store (prevents overwriting objects)
|
||||||
const existingZone = useDroppedObjectsStore.getState().zones[selectedZone.zoneName];
|
const existingZone = useDroppedObjectsStore.getState().zones[selectedZone.zoneName];
|
||||||
if (!existingZone) {
|
if (!existingZone) {
|
||||||
useDroppedObjectsStore.getState().setZone(selectedZone.zoneName, selectedZone.zoneId);
|
useDroppedObjectsStore.getState().setZone(selectedZone.zoneName, selectedZone.zoneId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the dropped object to the zone
|
// Add the dropped object to the zone
|
||||||
useDroppedObjectsStore.getState().addObject(selectedZone.zoneName, newObject);
|
useDroppedObjectsStore.getState().addObject(selectedZone.zoneName, newObject);
|
||||||
|
setFloatingWidgets((prevWidgets) => ({
|
||||||
|
...prevWidgets,
|
||||||
|
[selectedZone.zoneName]: {
|
||||||
|
...prevWidgets[selectedZone.zoneName],
|
||||||
|
zoneName: selectedZone.zoneName,
|
||||||
|
zoneId: selectedZone.zoneId,
|
||||||
|
objects: [...(prevWidgets[selectedZone.zoneName]?.objects || []), newObject],
|
||||||
|
},
|
||||||
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -123,6 +149,7 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
|
width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
|
||||||
left: isPlaying || activeModule !== "visualization" ? "0%" : "",
|
left: isPlaying || activeModule !== "visualization" ? "0%" : "",
|
||||||
}}
|
}}
|
||||||
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="scene-container"
|
className="scene-container"
|
||||||
|
|
|
@ -9,7 +9,7 @@ const ProgressCard = ({
|
||||||
}) => (
|
}) => (
|
||||||
<div className="chart progressBar">
|
<div className="chart progressBar">
|
||||||
<div className="header">{title}</div>
|
<div className="header">{title}</div>
|
||||||
{data?.stocks.map((stock, index) => (
|
{data?.stocks?.map((stock, index) => (
|
||||||
<div key={index} className="stock">
|
<div key={index} className="stock">
|
||||||
<span className="stock-item">
|
<span className="stock-item">
|
||||||
<span className="stockValues">
|
<span className="stockValues">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useFrame, useThree } from "@react-three/fiber";
|
import { useFrame, useThree } from "@react-three/fiber";
|
||||||
import { useActiveTool, useCamMode, useDeletableFloorItem, useDeleteModels, useFloorItems, useLoadingProgress, useRenderDistance, useselectedFloorItem, useSelectedItem, useSocketStore, useToggleView, useTransformMode } from "../../../store/store";
|
import { useActiveTool, useAsset3dWidget, useCamMode, useDeletableFloorItem, useDeleteModels, useFloorItems, useLoadingProgress, useRenderDistance, useselectedFloorItem, useSelectedItem, useSocketStore, useToggleView, useTransformMode } from "../../../store/store";
|
||||||
import assetVisibility from "../geomentries/assets/assetVisibility";
|
import assetVisibility from "../geomentries/assets/assetVisibility";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
|
@ -33,7 +33,6 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
|
||||||
const { setLoadingProgress } = useLoadingProgress();
|
const { setLoadingProgress } = useLoadingProgress();
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
const { socket } = useSocketStore();
|
const { socket } = useSocketStore();
|
||||||
|
|
||||||
const loader = new GLTFLoader();
|
const loader = new GLTFLoader();
|
||||||
const dracoLoader = new DRACOLoader();
|
const dracoLoader = new DRACOLoader();
|
||||||
|
|
||||||
|
@ -306,6 +305,8 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
|
||||||
};
|
};
|
||||||
}, [deleteModels, transformMode, controls, selectedItem, state.camera, state.pointer, activeTool, activeModule]);
|
}, [deleteModels, transformMode, controls, selectedItem, state.camera, state.pointer, activeTool, activeModule]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useFrame(() => {
|
useFrame(() => {
|
||||||
if (controls)
|
if (controls)
|
||||||
assetVisibility(itemsGroup, state.camera.position, renderDistance);
|
assetVisibility(itemsGroup, state.camera.position, renderDistance);
|
||||||
|
|
|
@ -224,6 +224,7 @@ const WallItemsGroup = ({ currentWallItem, AssetConfigurations, hoveredDeletable
|
||||||
const onDrop = (event: any) => {
|
const onDrop = (event: any) => {
|
||||||
|
|
||||||
if (!event.dataTransfer?.files[0]) return
|
if (!event.dataTransfer?.files[0]) return
|
||||||
|
|
||||||
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
|
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
|
||||||
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
|
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
|
||||||
raycaster.setFromCamera(pointer, camera);
|
raycaster.setFromCamera(pointer, camera);
|
||||||
|
|
|
@ -9,7 +9,7 @@ import * as THREE from "three";
|
||||||
// Define the shape of the selected card
|
// Define the shape of the selected card
|
||||||
interface SelectedCard {
|
interface SelectedCard {
|
||||||
assetName: string;
|
assetName: string;
|
||||||
uploadedOn: number;
|
uploadedOn: string;
|
||||||
price: number;
|
price: number;
|
||||||
rating: number;
|
rating: number;
|
||||||
views: number;
|
views: number;
|
||||||
|
|
|
@ -19,6 +19,8 @@ import DroppedObjects from "../../components/ui/componets/DroppedFloatingWidgets
|
||||||
|
|
||||||
// import Simulation from "./simulationtemp/simulation";
|
// import Simulation from "./simulationtemp/simulation";
|
||||||
import ZoneCentreTarget from "../../components/ui/componets/zoneCameraTarget";
|
import ZoneCentreTarget from "../../components/ui/componets/zoneCameraTarget";
|
||||||
|
import ProductionCapacity from "../../components/layout/3D-cards/cards/ProductionCapacity";
|
||||||
|
import Dropped3dWidgets from "../../components/ui/componets/Dropped3dWidget";
|
||||||
|
|
||||||
export default function Scene() {
|
export default function Scene() {
|
||||||
|
|
||||||
|
@ -43,6 +45,7 @@ export default function Scene() {
|
||||||
}}
|
}}
|
||||||
|
|
||||||
>
|
>
|
||||||
|
<Dropped3dWidgets/>
|
||||||
<Controls />
|
<Controls />
|
||||||
<TransformControl />
|
<TransformControl />
|
||||||
<SelectionControls />
|
<SelectionControls />
|
||||||
|
|
|
@ -14,7 +14,7 @@ function Simulation() {
|
||||||
const [processes, setProcesses] = useState([]);
|
const [processes, setProcesses] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('simulationPaths: ', simulationPaths);
|
|
||||||
}, [simulationPaths]);
|
}, [simulationPaths]);
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
|
||||||
|
|
||||||
|
export const addingWidgets = async (
|
||||||
|
zoneId: string,
|
||||||
|
organization: string,
|
||||||
|
widget: {}
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${url_Backend_dwinzo}/api/v2/widget/save`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ organization, zoneId, widget }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to add widget in the zone");
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,27 @@
|
||||||
|
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
|
||||||
|
console.log("url_Backend_dwinzo: ", url_Backend_dwinzo);
|
||||||
|
|
||||||
|
export const getSelect2dZoneData = async (
|
||||||
|
ZoneId?: string,
|
||||||
|
organization?: string
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${url_Backend_dwinzo}/api/v2/ZoneVisualization/${ZoneId}?organization=${organization}`,
|
||||||
|
{
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to fetch zoneDatas");
|
||||||
|
}
|
||||||
|
|
||||||
|
return await response.json();
|
||||||
|
} catch (error: any) {
|
||||||
|
throw new Error(error.message);
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,23 @@
|
||||||
|
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
|
||||||
|
|
||||||
|
export const getZone2dData = async (organization?: string) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${url_Backend_dwinzo}/api/v2/pageZodeData?organization=${organization}`,
|
||||||
|
{
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to fetch zoneDatas");
|
||||||
|
}
|
||||||
|
|
||||||
|
return await response.json();
|
||||||
|
} catch (error: any) {
|
||||||
|
throw new Error(error.message);
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,22 +1,19 @@
|
||||||
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_BACKEND_URL}`;
|
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
|
||||||
|
|
||||||
type Side = "top" | "bottom" | "left" | "right";
|
type Side = "top" | "bottom" | "left" | "right";
|
||||||
|
|
||||||
export const panelData = async (
|
export const panelData = async (
|
||||||
organization: string,
|
organization: string,
|
||||||
zoneID: string,
|
zoneId: string,
|
||||||
panelOrder: Side[]
|
panelOrder: Side[]
|
||||||
) => {
|
) => {
|
||||||
console.log("panelOrder: ", panelOrder);
|
|
||||||
console.log("zoneID: ", zoneID);
|
|
||||||
console.log("organization: ", organization);
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${url_Backend_dwinzo}/api/v1/panel/save`, {
|
const response = await fetch(`${url_Backend_dwinzo}/api/v2/panel/save`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ organization, zoneID, panelOrder }),
|
body: JSON.stringify({ organization, zoneId, panelOrder }),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
|
@ -33,16 +30,3 @@ export const panelData = async (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// {objects.map((obj, index) => (
|
|
||||||
// <group key={index} position={[Math.random() * 5, Math.random() * 5, 0]}>
|
|
||||||
// <Html wrapperClass={obj.className}>
|
|
||||||
// <div style={{ padding: "10px", background: "#fff", borderRadius: "6px" }}>
|
|
||||||
// <div className="header">{obj.header}</div>
|
|
||||||
// <div className="data-values">
|
|
||||||
// <div className="value">{obj.value}</div>
|
|
||||||
// <div className="per">{obj.per}</div>
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// </Html>
|
|
||||||
// </group>
|
|
||||||
// ))}
|
|
||||||
|
|
|
@ -348,4 +348,7 @@ export const useEditPosition = create<EditPositionState>((set) => ({
|
||||||
setEdit: (value) => set({ Edit: value }), // Properly updating the state
|
setEdit: (value) => set({ Edit: value }), // Properly updating the state
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
export const useAsset3dWidget = create<any>((set: any) => ({
|
||||||
|
widgetSelect: "",
|
||||||
|
setWidgetSelect: (x: any) => set({ widgetSelect: x }),
|
||||||
|
}));
|
||||||
|
|
|
@ -14,6 +14,7 @@ interface SelectedZoneState {
|
||||||
zoneName: string;
|
zoneName: string;
|
||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
|
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
zoneId: string;
|
zoneId: string;
|
||||||
zoneViewPortTarget: number[];
|
zoneViewPortTarget: number[];
|
||||||
|
|
|
@ -109,7 +109,7 @@
|
||||||
|
|
||||||
|
|
||||||
.productionCapacity-wrapper {
|
.productionCapacity-wrapper {
|
||||||
background: var(--background-color);
|
background-color: var(--background-color);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
|
@ -170,6 +170,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.bar-chart{
|
||||||
|
padding:14px 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue