diff --git a/app/src/components/icons/SimulationIcons.tsx b/app/src/components/icons/SimulationIcons.tsx index 1e89a51..29b8de4 100644 --- a/app/src/components/icons/SimulationIcons.tsx +++ b/app/src/components/icons/SimulationIcons.tsx @@ -1,4 +1,4 @@ -export function AnalysisIcon({ isActive }: { isActive: boolean }) { +export function AnalysisIcon({ isActive }: Readonly<{ isActive: boolean }>) { return ( ) { return ( ) { return ( ) { return ( ); } + +// simulation card icons + +export function ExpandIcon({ + color = "#6F42C1", +}: Readonly<{ color?: string }>) { + return ( + + + + + ); +} + +export function SimulationStatusIcon({ + color = "#21FF59", +}: Readonly<{ color?: string }>) { + return ( + + + + + ); +} + +export function IndicationArrow() { + return ( + + + + ); +} + +export function CartBagIcon() { + return ( + + + + + + + + ); +} diff --git a/app/src/components/layout/sidebarLeft/Assets.tsx b/app/src/components/layout/sidebarLeft/Assets.tsx index 97d1384..b863500 100644 --- a/app/src/components/layout/sidebarLeft/Assets.tsx +++ b/app/src/components/layout/sidebarLeft/Assets.tsx @@ -81,7 +81,9 @@ const Assets: React.FC = () => { try { const filt = await fetchAssets(); setFiltereredAssets(filt); - } catch {} + } catch { + echo.error("Filter asset not found"); + } }; filteredAssets(); }, [categoryAssets]); @@ -152,11 +154,14 @@ const Assets: React.FC = () => { setCategoryAssets(res); setFiltereredAssets(res); setisLoading(false); // End loading + // eslint-disable-next-line } catch (error) { + echo.error("failed to fetch assets"); setisLoading(false); } } }; + return (
diff --git a/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx b/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx index 1bb9400..0c79b3c 100644 --- a/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx +++ b/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx @@ -39,7 +39,9 @@ const ZoneProperties: React.FC = () => { } else { // console.log(response); } - } catch (error) {} + } catch (error) { + echo.error("Failed to set zone view"); + } } function handleEditView() { diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/BarChartInput.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/BarChartInput.tsx index a729a9e..742569c 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/BarChartInput.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/BarChartInput.tsx @@ -11,22 +11,24 @@ import RenameInput from "../../../../ui/inputs/RenameInput"; type Props = {}; const BarChartInput = (props: Props) => { - const [widgetName, setWidgetName] = useState('Widget'); + const [widgetName, setWidgetName] = useState("Widget"); const { setMeasurements, updateDuration, updateName } = useChartStore(); - const [duration, setDuration] = useState('1h') + const [duration, setDuration] = useState("1h"); const [dropDowndata, setDropDownData] = useState({}); - const [selections, setSelections] = useState>({}); + const [selections, setSelections] = useState< + Record + >({}); const { selectedZone } = useSelectedZoneStore(); const { selectedChartId } = useWidgetStore(); const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0] + const organization = email?.split("@")[1]?.split(".")[0]; const [isLoading, setLoading] = useState(true); useEffect(() => { const fetchZoneData = async () => { try { - setLoading(true) + setLoading(true); const response = await axios.get(`http://${iotApiUrl}/floatinput`); if (response.status === 200) { // console.log("dropdown data:", response.data); @@ -36,6 +38,7 @@ const BarChartInput = (props: Props) => { console.log("Unexpected response:", response); } } catch (error) { + echo.log("Failed to fetch zone data"); console.error("There was an error!", error); } }; @@ -46,22 +49,24 @@ const BarChartInput = (props: Props) => { const fetchSavedInputes = async () => { if (selectedChartId.id !== "") { try { - const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/WidgetData/${selectedChartId.id}/${organization}`); + const response = await axios.get( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/WidgetData/${selectedChartId.id}/${organization}` + ); if (response.status === 200) { - setSelections(response.data.Data.measurements) - setDuration(response.data.Data.duration) - setWidgetName(response.data.widgetName) + setSelections(response.data.Data.measurements); + setDuration(response.data.Data.duration); + setWidgetName(response.data.widgetName); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } - } + }; fetchSavedInputes(); - }, [selectedChartId]); // Sync Zustand state when component mounts @@ -71,36 +76,45 @@ const BarChartInput = (props: Props) => { updateName(widgetName); }, [selections, duration, widgetName]); - - const sendInputes = async (inputMeasurement: any, inputDuration: any, inputName: any) => { + const sendInputes = async ( + inputMeasurement: any, + inputDuration: any, + inputName: any + ) => { try { - const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget/save`, { - organization: organization, - zoneId: selectedZone.zoneId, - widget: { - id: selectedChartId.id, - panel: selectedChartId.panel, - widgetName: inputName, - Data: { - measurements: inputMeasurement, - duration: inputDuration - } - } - } as any); + const response = await axios.post( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget/save`, + { + organization: organization, + zoneId: selectedZone.zoneId, + widget: { + id: selectedChartId.id, + panel: selectedChartId.panel, + widgetName: inputName, + Data: { + measurements: inputMeasurement, + duration: inputDuration, + }, + }, + } as any + ); if (response.status === 200) { - return true + return true; } else { console.log("Unexpected response:", response); - return false + return false; } } catch (error) { + echo.error("Failed to send input"); console.error("There was an error!", error); - return false + return false; } - } - - const handleSelect = async (inputKey: string, selectedData: { name: string; fields: string } | null) => { + }; + const handleSelect = async ( + inputKey: string, + selectedData: { name: string; fields: string } | null + ) => { // async() => { const newSelections = { ...selections }; if (selectedData === null) { @@ -125,20 +139,23 @@ const BarChartInput = (props: Props) => { // setDuration(option); }; - const handleNameChange = async (name:any) => { - console.log('name change requested',name); - + const handleNameChange = async (name: any) => { + console.log("name change requested", name); + if (await sendInputes(selections, duration, name)) { setWidgetName(name); } - } + }; return ( <>
Title
- +
{[...Array(3)].map((_, index) => { const inputKey = `input${index + 1}`; @@ -148,7 +165,9 @@ const BarChartInput = (props: Props) => {
handleSelect(inputKey, selectedData)} + onSelect={(selectedData) => + handleSelect(inputKey, selectedData) + } onUnselect={() => handleSelect(inputKey, null)} selectedValue={selections[inputKey]} // Load from Zustand isLoading={isLoading} @@ -179,4 +198,4 @@ const BarChartInput = (props: Props) => { ); }; -export default BarChartInput; \ No newline at end of file +export default BarChartInput; diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/FleetEfficiencyInputComponent.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/FleetEfficiencyInputComponent.tsx index 9c6c831..6b3559c 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/FleetEfficiencyInputComponent.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/FleetEfficiencyInputComponent.tsx @@ -11,35 +11,37 @@ import RenameInput from "../../../../ui/inputs/RenameInput"; type Props = {}; const FleetEfficiencyInputComponent = (props: Props) => { - const [widgetName, setWidgetName] = useState('Widget'); - const { setFlotingMeasurements, updateFlotingDuration, updateHeader } = useChartStore(); - const [duration, setDuration] = useState('1h') + const [widgetName, setWidgetName] = useState("Widget"); + const { setFlotingMeasurements, updateFlotingDuration, updateHeader } = + useChartStore(); + const [duration, setDuration] = useState("1h"); const [dropDowndata, setDropDownData] = useState({}); - const [selections, setSelections] = useState>({}); + const [selections, setSelections] = useState< + Record + >({}); const { selectedZone } = useSelectedZoneStore(); const { selectedChartId } = useWidgetStore(); const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0] + const organization = email?.split("@")[1]?.split(".")[0]; const [isLoading, setLoading] = useState(true); - const isSelected = () => { - - } + const isSelected = () => {}; useEffect(() => { const fetchZoneData = async () => { try { const response = await axios.get(`http://${iotApiUrl}/floatinput`); - setLoading(true) + setLoading(true); if (response.status === 200) { // console.log("dropdown data:", response.data); setDropDownData(response.data); - setLoading(false) + setLoading(false); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch zone data"); console.error("There was an error!", error); } }; @@ -50,24 +52,25 @@ const FleetEfficiencyInputComponent = (props: Props) => { const fetchSavedInputes = async () => { if (selectedChartId.id !== "") { try { - const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/A_floatWidget/${selectedChartId.id}/${organization}`); + const response = await axios.get( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/A_floatWidget/${selectedChartId.id}/${organization}` + ); if (response.status === 200) { - - - setSelections(response.data.Data.measurements) - setDuration(response.data.Data.duration) - setWidgetName(response.data.header) + setSelections(response.data.Data.measurements); + setDuration(response.data.Data.duration); + setWidgetName(response.data.header); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); + console.error("There was an error!", error); } } - } + }; fetchSavedInputes(); - }, [selectedChartId.id]); // Sync Zustand state when component mounts @@ -77,35 +80,45 @@ const FleetEfficiencyInputComponent = (props: Props) => { updateHeader(widgetName); }, [selections, duration, widgetName]); - - const sendInputes = async (inputMeasurement: any, inputDuration: any, inputName: any) => { + const sendInputes = async ( + inputMeasurement: any, + inputDuration: any, + inputName: any + ) => { try { - const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/floatwidget/save`, { - organization: organization, - zoneId: selectedZone.zoneId, - widget: { - id: selectedChartId.id, - header: inputName, - Data: { - measurements: inputMeasurement, - duration: inputDuration - } - } - } as any); + const response = await axios.post( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/floatwidget/save`, + { + organization: organization, + zoneId: selectedZone.zoneId, + widget: { + id: selectedChartId.id, + header: inputName, + Data: { + measurements: inputMeasurement, + duration: inputDuration, + }, + }, + } as any + ); if (response.status === 200) { - return true + return true; } else { console.log("Unexpected response:", response); - return false + return false; } } catch (error) { + echo.error("Failed to send input"); + console.error("There was an error!", error); - return false + return false; } - } - - const handleSelect = async (inputKey: string, selectedData: { name: string; fields: string } | null) => { + }; + const handleSelect = async ( + inputKey: string, + selectedData: { name: string; fields: string } | null + ) => { // async() => { const newSelections = { ...selections }; if (selectedData === null) { @@ -130,20 +143,23 @@ const FleetEfficiencyInputComponent = (props: Props) => { // setDuration(option); }; - const handleNameChange = async (name:any) => { - console.log('name change requested',name); - + const handleNameChange = async (name: any) => { + console.log("name change requested", name); + if (await sendInputes(selections, duration, name)) { setWidgetName(name); } - } + }; return ( <>
Title
- +
{[...Array(1)].map((_, index) => { const inputKey = `input${index + 1}`; @@ -153,7 +169,9 @@ const FleetEfficiencyInputComponent = (props: Props) => {
handleSelect(inputKey, selectedData)} + onSelect={(selectedData) => + handleSelect(inputKey, selectedData) + } onUnselect={() => handleSelect(inputKey, null)} selectedValue={selections[inputKey]} // Load from Zustand isLoading={isLoading} @@ -184,4 +202,4 @@ const FleetEfficiencyInputComponent = (props: Props) => { ); }; -export default FleetEfficiencyInputComponent; \ No newline at end of file +export default FleetEfficiencyInputComponent; diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/FlotingWidgetInput.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/FlotingWidgetInput.tsx index 0165257..166070e 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/FlotingWidgetInput.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/FlotingWidgetInput.tsx @@ -11,22 +11,25 @@ import RenameInput from "../../../../ui/inputs/RenameInput"; type Props = {}; const FlotingWidgetInput = (props: Props) => { - const [widgetName, setWidgetName] = useState('Widget'); - const { setFlotingMeasurements, updateFlotingDuration, updateHeader } = useChartStore(); - const [duration, setDuration] = useState('1h') + const [widgetName, setWidgetName] = useState("Widget"); + const { setFlotingMeasurements, updateFlotingDuration, updateHeader } = + useChartStore(); + const [duration, setDuration] = useState("1h"); const [dropDowndata, setDropDownData] = useState({}); - const [selections, setSelections] = useState>({}); + const [selections, setSelections] = useState< + Record + >({}); const { selectedZone } = useSelectedZoneStore(); const { selectedChartId } = useWidgetStore(); const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0] + const organization = email?.split("@")[1]?.split(".")[0]; const [isLoading, setLoading] = useState(true); useEffect(() => { const fetchZoneData = async () => { try { - setLoading(true) + setLoading(true); const response = await axios.get(`http://${iotApiUrl}/floatinput`); if (response.status === 200) { // console.log("dropdown data:", response.data); @@ -36,6 +39,8 @@ const FlotingWidgetInput = (props: Props) => { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch zone data"); + console.error("There was an error!", error); } }; @@ -46,24 +51,25 @@ const FlotingWidgetInput = (props: Props) => { const fetchSavedInputes = async () => { if (selectedChartId.id !== "") { try { - const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/A_floatWidget/${selectedChartId.id}/${organization}`); + const response = await axios.get( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/A_floatWidget/${selectedChartId.id}/${organization}` + ); if (response.status === 200) { - - - setSelections(response.data.Data.measurements) - setDuration(response.data.Data.duration) - setWidgetName(response.data.header) + setSelections(response.data.Data.measurements); + setDuration(response.data.Data.duration); + setWidgetName(response.data.header); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); + console.error("There was an error!", error); } } - } + }; fetchSavedInputes(); - }, [selectedChartId.id]); // Sync Zustand state when component mounts @@ -73,35 +79,45 @@ const FlotingWidgetInput = (props: Props) => { updateHeader(widgetName); }, [selections, duration, widgetName]); - - const sendInputes = async (inputMeasurement: any, inputDuration: any, inputName: any) => { + const sendInputes = async ( + inputMeasurement: any, + inputDuration: any, + inputName: any + ) => { try { - const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/floatwidget/save`, { - organization: organization, - zoneId: selectedZone.zoneId, - widget: { - id: selectedChartId.id, - header: inputName, - Data: { - measurements: inputMeasurement, - duration: inputDuration - } - } - } as any); + const response = await axios.post( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/floatwidget/save`, + { + organization: organization, + zoneId: selectedZone.zoneId, + widget: { + id: selectedChartId.id, + header: inputName, + Data: { + measurements: inputMeasurement, + duration: inputDuration, + }, + }, + } as any + ); if (response.status === 200) { - return true + return true; } else { console.log("Unexpected response:", response); - return false + return false; } } catch (error) { + echo.error("Failed to send input"); + console.error("There was an error!", error); - return false + return false; } - } - - const handleSelect = async (inputKey: string, selectedData: { name: string; fields: string } | null) => { + }; + const handleSelect = async ( + inputKey: string, + selectedData: { name: string; fields: string } | null + ) => { // async() => { const newSelections = { ...selections }; if (selectedData === null) { @@ -126,20 +142,23 @@ const FlotingWidgetInput = (props: Props) => { // setDuration(option); }; - const handleNameChange = async (name:any) => { - console.log('name change requested',name); - + const handleNameChange = async (name: any) => { + console.log("name change requested", name); + if (await sendInputes(selections, duration, name)) { setWidgetName(name); } - } + }; return ( <>
Title
- +
{[...Array(6)].map((_, index) => { const inputKey = `input${index + 1}`; @@ -149,7 +168,9 @@ const FlotingWidgetInput = (props: Props) => {
handleSelect(inputKey, selectedData)} + onSelect={(selectedData) => + handleSelect(inputKey, selectedData) + } onUnselect={() => handleSelect(inputKey, null)} selectedValue={selections[inputKey]} // Load from Zustand isLoading={isLoading} diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/LineGrapInput.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/LineGrapInput.tsx index cb51491..49d4525 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/LineGrapInput.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/LineGrapInput.tsx @@ -72,7 +72,6 @@ // setMeasurements(measurementsData); // }, [selections]); - // return ( // <> //
@@ -115,8 +114,6 @@ // export default LineGrapInput - - import React, { useEffect, useState } from "react"; import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown"; import { AddIcon } from "../../../../icons/ExportCommonIcons"; @@ -130,31 +127,34 @@ import RenameInput from "../../../../ui/inputs/RenameInput"; type Props = {}; const LineGrapInput = (props: Props) => { - const [widgetName, setWidgetName] = useState('Widget'); + const [widgetName, setWidgetName] = useState("Widget"); const { setMeasurements, updateDuration, updateName } = useChartStore(); - const [duration, setDuration] = useState('1h') + const [duration, setDuration] = useState("1h"); const [dropDowndata, setDropDownData] = useState({}); - const [selections, setSelections] = useState>({}); + const [selections, setSelections] = useState< + Record + >({}); const { selectedZone } = useSelectedZoneStore(); const { selectedChartId } = useWidgetStore(); const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0] + const organization = email?.split("@")[1]?.split(".")[0]; const [isLoading, setLoading] = useState(true); useEffect(() => { const fetchZoneData = async () => { try { - setLoading(true) + setLoading(true); const response = await axios.get(`http://${iotApiUrl}/floatinput`); if (response.status === 200) { // console.log("dropdown data:", response.data); setDropDownData(response.data); - setLoading(false) + setLoading(false); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch zone data"); console.error("There was an error!", error); } }; @@ -165,22 +165,24 @@ const LineGrapInput = (props: Props) => { const fetchSavedInputes = async () => { if (selectedChartId.id !== "") { try { - const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/WidgetData/${selectedChartId.id}/${organization}`); + const response = await axios.get( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/WidgetData/${selectedChartId.id}/${organization}` + ); if (response.status === 200) { - setSelections(response.data.Data.measurements) - setDuration(response.data.Data.duration) - setWidgetName(response.data.widgetName) + setSelections(response.data.Data.measurements); + setDuration(response.data.Data.duration); + setWidgetName(response.data.widgetName); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } - } + }; fetchSavedInputes(); - }, [selectedChartId.id]); // Sync Zustand state when component mounts @@ -190,36 +192,45 @@ const LineGrapInput = (props: Props) => { updateName(widgetName); }, [selections, duration, widgetName]); - - const sendInputes = async (inputMeasurement: any, inputDuration: any, inputName: any) => { + const sendInputes = async ( + inputMeasurement: any, + inputDuration: any, + inputName: any + ) => { try { - const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget/save`, { - organization: organization, - zoneId: selectedZone.zoneId, - widget: { - id: selectedChartId.id, - panel: selectedChartId.panel, - widgetName: inputName, - Data: { - measurements: inputMeasurement, - duration: inputDuration - } - } - } as any); + const response = await axios.post( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget/save`, + { + organization: organization, + zoneId: selectedZone.zoneId, + widget: { + id: selectedChartId.id, + panel: selectedChartId.panel, + widgetName: inputName, + Data: { + measurements: inputMeasurement, + duration: inputDuration, + }, + }, + } as any + ); if (response.status === 200) { - return true + return true; } else { console.log("Unexpected response:", response); - return false + return false; } } catch (error) { + echo.error("Failed to send input"); console.error("There was an error!", error); - return false + return false; } - } - - const handleSelect = async (inputKey: string, selectedData: { name: string; fields: string } | null) => { + }; + const handleSelect = async ( + inputKey: string, + selectedData: { name: string; fields: string } | null + ) => { // async() => { const newSelections = { ...selections }; if (selectedData === null) { @@ -244,20 +255,23 @@ const LineGrapInput = (props: Props) => { // setDuration(option); }; - const handleNameChange = async (name:any) => { - console.log('name change requested',name); - + const handleNameChange = async (name: any) => { + console.log("name change requested", name); + if (await sendInputes(selections, duration, name)) { setWidgetName(name); } - } + }; return ( <>
Title
- +
{[...Array(4)].map((_, index) => { const inputKey = `input${index + 1}`; @@ -267,7 +281,9 @@ const LineGrapInput = (props: Props) => {
handleSelect(inputKey, selectedData)} + onSelect={(selectedData) => + handleSelect(inputKey, selectedData) + } onUnselect={() => handleSelect(inputKey, null)} selectedValue={selections[inputKey]} // Load from Zustand isLoading={isLoading} diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/PieChartInput.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/PieChartInput.tsx index 9dff7d6..aa0acaa 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/PieChartInput.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/PieChartInput.tsx @@ -11,31 +11,34 @@ import RenameInput from "../../../../ui/inputs/RenameInput"; type Props = {}; const PieChartInput = (props: Props) => { - const [widgetName, setWidgetName] = useState('Widget'); + const [widgetName, setWidgetName] = useState("Widget"); const { setMeasurements, updateDuration, updateName } = useChartStore(); - const [duration, setDuration] = useState('1h') + const [duration, setDuration] = useState("1h"); const [dropDowndata, setDropDownData] = useState({}); - const [selections, setSelections] = useState>({}); + const [selections, setSelections] = useState< + Record + >({}); const { selectedZone } = useSelectedZoneStore(); const { selectedChartId } = useWidgetStore(); const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0] + const organization = email?.split("@")[1]?.split(".")[0]; const [isLoading, setLoading] = useState(true); useEffect(() => { const fetchZoneData = async () => { try { - setLoading(true) + setLoading(true); const response = await axios.get(`http://${iotApiUrl}/floatinput`); if (response.status === 200) { // console.log("dropdown data:", response.data); setDropDownData(response.data); - setLoading(false) + setLoading(false); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch zone data"); console.error("There was an error!", error); } }; @@ -46,22 +49,24 @@ const PieChartInput = (props: Props) => { const fetchSavedInputes = async () => { if (selectedChartId.id !== "") { try { - const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/WidgetData/${selectedChartId.id}/${organization}`); + const response = await axios.get( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/WidgetData/${selectedChartId.id}/${organization}` + ); if (response.status === 200) { - setSelections(response.data.Data.measurements) - setDuration(response.data.Data.duration) - setWidgetName(response.data.widgetName) + setSelections(response.data.Data.measurements); + setDuration(response.data.Data.duration); + setWidgetName(response.data.widgetName); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } - } + }; fetchSavedInputes(); - }, [selectedChartId.id]); // Sync Zustand state when component mounts @@ -71,36 +76,45 @@ const PieChartInput = (props: Props) => { updateName(widgetName); }, [selections, duration, widgetName]); - - const sendInputes = async (inputMeasurement: any, inputDuration: any, inputName: any) => { + const sendInputes = async ( + inputMeasurement: any, + inputDuration: any, + inputName: any + ) => { try { - const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget/save`, { - organization: organization, - zoneId: selectedZone.zoneId, - widget: { - id: selectedChartId.id, - panel: selectedChartId.panel, - widgetName: inputName, - Data: { - measurements: inputMeasurement, - duration: inputDuration - } - } - } as any); + const response = await axios.post( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget/save`, + { + organization: organization, + zoneId: selectedZone.zoneId, + widget: { + id: selectedChartId.id, + panel: selectedChartId.panel, + widgetName: inputName, + Data: { + measurements: inputMeasurement, + duration: inputDuration, + }, + }, + } as any + ); if (response.status === 200) { - return true + return true; } else { console.log("Unexpected response:", response); - return false + return false; } } catch (error) { + echo.error("Failed to send input"); console.error("There was an error!", error); - return false + return false; } - } - - const handleSelect = async (inputKey: string, selectedData: { name: string; fields: string } | null) => { + }; + const handleSelect = async ( + inputKey: string, + selectedData: { name: string; fields: string } | null + ) => { // async() => { const newSelections = { ...selections }; if (selectedData === null) { @@ -125,20 +139,23 @@ const PieChartInput = (props: Props) => { // setDuration(option); }; - const handleNameChange = async (name:any) => { - console.log('name change requested',name); - + const handleNameChange = async (name: any) => { + console.log("name change requested", name); + if (await sendInputes(selections, duration, name)) { setWidgetName(name); } - } + }; return ( <>
Title
- +
{[...Array(2)].map((_, index) => { const inputKey = `input${index + 1}`; @@ -148,7 +165,9 @@ const PieChartInput = (props: Props) => {
handleSelect(inputKey, selectedData)} + onSelect={(selectedData) => + handleSelect(inputKey, selectedData) + } onUnselect={() => handleSelect(inputKey, null)} selectedValue={selections[inputKey]} // Load from Zustand isLoading={isLoading} @@ -179,4 +198,4 @@ const PieChartInput = (props: Props) => { ); }; -export default PieChartInput; \ No newline at end of file +export default PieChartInput; diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress1Input.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress1Input.tsx index ed84458..2f1fdb5 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress1Input.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress1Input.tsx @@ -11,31 +11,34 @@ import RenameInput from "../../../../ui/inputs/RenameInput"; type Props = {}; const Progress1Input = (props: Props) => { - const [widgetName, setWidgetName] = useState('Widget'); + const [widgetName, setWidgetName] = useState("Widget"); const { setMeasurements, updateDuration, updateName } = useChartStore(); - const [duration, setDuration] = useState('1h') + const [duration, setDuration] = useState("1h"); const [dropDowndata, setDropDownData] = useState({}); - const [selections, setSelections] = useState>({}); + const [selections, setSelections] = useState< + Record + >({}); const { selectedZone } = useSelectedZoneStore(); const { selectedChartId } = useWidgetStore(); const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0] + const organization = email?.split("@")[1]?.split(".")[0]; const [isLoading, setLoading] = useState(true); useEffect(() => { const fetchZoneData = async () => { try { - setLoading(true) + setLoading(true); const response = await axios.get(`http://${iotApiUrl}/floatinput`); if (response.status === 200) { // console.log("dropdown data:", response.data); setDropDownData(response.data); - setLoading(false) + setLoading(false); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch zone data"); console.error("There was an error!", error); } }; @@ -46,22 +49,24 @@ const Progress1Input = (props: Props) => { const fetchSavedInputes = async () => { if (selectedChartId.id !== "") { try { - const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/WidgetData/${selectedChartId.id}/${organization}`); + const response = await axios.get( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/WidgetData/${selectedChartId.id}/${organization}` + ); if (response.status === 200) { - setSelections(response.data.Data.measurements) - setDuration(response.data.Data.duration) - setWidgetName(response.data.widgetName) + setSelections(response.data.Data.measurements); + setDuration(response.data.Data.duration); + setWidgetName(response.data.widgetName); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } - } + }; fetchSavedInputes(); - }, [selectedChartId.id]); // Sync Zustand state when component mounts @@ -71,36 +76,45 @@ const Progress1Input = (props: Props) => { updateName(widgetName); }, [selections, duration, widgetName]); - - const sendInputes = async (inputMeasurement: any, inputDuration: any, inputName: any) => { + const sendInputes = async ( + inputMeasurement: any, + inputDuration: any, + inputName: any + ) => { try { - const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget/save`, { - organization: organization, - zoneId: selectedZone.zoneId, - widget: { - id: selectedChartId.id, - panel: selectedChartId.panel, - widgetName: inputName, - Data: { - measurements: inputMeasurement, - duration: inputDuration - } - } - } as any); + const response = await axios.post( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget/save`, + { + organization: organization, + zoneId: selectedZone.zoneId, + widget: { + id: selectedChartId.id, + panel: selectedChartId.panel, + widgetName: inputName, + Data: { + measurements: inputMeasurement, + duration: inputDuration, + }, + }, + } as any + ); if (response.status === 200) { - return true + return true; } else { console.log("Unexpected response:", response); - return false + return false; } } catch (error) { + echo.error("Failed to send input"); console.error("There was an error!", error); - return false + return false; } - } - - const handleSelect = async (inputKey: string, selectedData: { name: string; fields: string } | null) => { + }; + const handleSelect = async ( + inputKey: string, + selectedData: { name: string; fields: string } | null + ) => { // async() => { const newSelections = { ...selections }; if (selectedData === null) { @@ -121,18 +135,21 @@ const Progress1Input = (props: Props) => { } }; - const handleNameChange = async (name:any) => { + const handleNameChange = async (name: any) => { if (await sendInputes(selections, duration, name)) { setWidgetName(name); } - } + }; return ( <>
Title
- +
{[...Array(1)].map((_, index) => { const inputKey = `input${index + 1}`; @@ -142,7 +159,9 @@ const Progress1Input = (props: Props) => {
handleSelect(inputKey, selectedData)} + onSelect={(selectedData) => + handleSelect(inputKey, selectedData) + } onUnselect={() => handleSelect(inputKey, null)} selectedValue={selections[inputKey]} // Load from Zustand isLoading={isLoading} @@ -173,4 +192,4 @@ const Progress1Input = (props: Props) => { ); }; -export default Progress1Input; \ No newline at end of file +export default Progress1Input; diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress2Input.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress2Input.tsx index c97a380..2d2e089 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress2Input.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress2Input.tsx @@ -11,31 +11,34 @@ import RenameInput from "../../../../ui/inputs/RenameInput"; type Props = {}; const Progress2Input = (props: Props) => { - const [widgetName, setWidgetName] = useState('Widget'); + const [widgetName, setWidgetName] = useState("Widget"); const { setMeasurements, updateDuration, updateName } = useChartStore(); - const [duration, setDuration] = useState('1h') + const [duration, setDuration] = useState("1h"); const [dropDowndata, setDropDownData] = useState({}); - const [selections, setSelections] = useState>({}); + const [selections, setSelections] = useState< + Record + >({}); const { selectedZone } = useSelectedZoneStore(); const { selectedChartId } = useWidgetStore(); const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0] + const organization = email?.split("@")[1]?.split(".")[0]; const [isLoading, setLoading] = useState(true); useEffect(() => { const fetchZoneData = async () => { try { - setLoading(true) + setLoading(true); const response = await axios.get(`http://${iotApiUrl}/floatinput`); if (response.status === 200) { // console.log("dropdown data:", response.data); setDropDownData(response.data); - setLoading(false) + setLoading(false); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch zone data"); console.error("There was an error!", error); } }; @@ -46,22 +49,24 @@ const Progress2Input = (props: Props) => { const fetchSavedInputes = async () => { if (selectedChartId.id !== "") { try { - const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/WidgetData/${selectedChartId.id}/${organization}`); + const response = await axios.get( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/WidgetData/${selectedChartId.id}/${organization}` + ); if (response.status === 200) { - setSelections(response.data.Data.measurements) - setDuration(response.data.Data.duration) - setWidgetName(response.data.widgetName) + setSelections(response.data.Data.measurements); + setDuration(response.data.Data.duration); + setWidgetName(response.data.widgetName); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } - } + }; fetchSavedInputes(); - }, [selectedChartId.id]); // Sync Zustand state when component mounts @@ -71,36 +76,45 @@ const Progress2Input = (props: Props) => { updateName(widgetName); }, [selections, duration, widgetName]); - - const sendInputes = async (inputMeasurement: any, inputDuration: any, inputName: any) => { + const sendInputes = async ( + inputMeasurement: any, + inputDuration: any, + inputName: any + ) => { try { - const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget/save`, { - organization: organization, - zoneId: selectedZone.zoneId, - widget: { - id: selectedChartId.id, - panel: selectedChartId.panel, - widgetName: inputName, - Data: { - measurements: inputMeasurement, - duration: inputDuration - } - } - } as any); + const response = await axios.post( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget/save`, + { + organization: organization, + zoneId: selectedZone.zoneId, + widget: { + id: selectedChartId.id, + panel: selectedChartId.panel, + widgetName: inputName, + Data: { + measurements: inputMeasurement, + duration: inputDuration, + }, + }, + } as any + ); if (response.status === 200) { - return true + return true; } else { console.log("Unexpected response:", response); - return false + return false; } } catch (error) { + echo.error("Failed to send input"); console.error("There was an error!", error); - return false + return false; } - } - - const handleSelect = async (inputKey: string, selectedData: { name: string; fields: string } | null) => { + }; + const handleSelect = async ( + inputKey: string, + selectedData: { name: string; fields: string } | null + ) => { // async() => { const newSelections = { ...selections }; if (selectedData === null) { @@ -121,18 +135,21 @@ const Progress2Input = (props: Props) => { } }; - const handleNameChange = async (name:any) => { + const handleNameChange = async (name: any) => { if (await sendInputes(selections, duration, name)) { setWidgetName(name); } - } + }; return ( <>
Title
- +
{[...Array(2)].map((_, index) => { const inputKey = `input${index + 1}`; @@ -142,7 +159,9 @@ const Progress2Input = (props: Props) => {
handleSelect(inputKey, selectedData)} + onSelect={(selectedData) => + handleSelect(inputKey, selectedData) + } onUnselect={() => handleSelect(inputKey, null)} selectedValue={selections[inputKey]} // Load from Zustand isLoading={isLoading} @@ -173,4 +192,4 @@ const Progress2Input = (props: Props) => { ); }; -export default Progress2Input; \ No newline at end of file +export default Progress2Input; diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/WarehouseThroughputInputComponent.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/WarehouseThroughputInputComponent.tsx index d48f2ee..6c8eda4 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/WarehouseThroughputInputComponent.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/WarehouseThroughputInputComponent.tsx @@ -11,31 +11,35 @@ import RenameInput from "../../../../ui/inputs/RenameInput"; type Props = {}; const WarehouseThroughputInputComponent = (props: Props) => { - const [widgetName, setWidgetName] = useState('Widget'); - const { setFlotingMeasurements, updateFlotingDuration, updateHeader } = useChartStore(); - const [duration, setDuration] = useState('1h') + const [widgetName, setWidgetName] = useState("Widget"); + const { setFlotingMeasurements, updateFlotingDuration, updateHeader } = + useChartStore(); + const [duration, setDuration] = useState("1h"); const [dropDowndata, setDropDownData] = useState({}); - const [selections, setSelections] = useState>({}); + const [selections, setSelections] = useState< + Record + >({}); const { selectedZone } = useSelectedZoneStore(); const { selectedChartId } = useWidgetStore(); const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0] + const organization = email?.split("@")[1]?.split(".")[0]; const [isLoading, setLoading] = useState(true); useEffect(() => { const fetchZoneData = async () => { try { - setLoading(true) + setLoading(true); const response = await axios.get(`http://${iotApiUrl}/floatinput`); if (response.status === 200) { // console.log("dropdown data:", response.data); setDropDownData(response.data); - setLoading(false) + setLoading(false); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch zone data"); console.error("There was an error!", error); } }; @@ -46,24 +50,24 @@ const WarehouseThroughputInputComponent = (props: Props) => { const fetchSavedInputes = async () => { if (selectedChartId.id !== "") { try { - const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/A_floatWidget/${selectedChartId.id}/${organization}`); + const response = await axios.get( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/A_floatWidget/${selectedChartId.id}/${organization}` + ); if (response.status === 200) { - - - setSelections(response.data.Data.measurements) - setDuration(response.data.Data.duration) - setWidgetName(response.data.header) + setSelections(response.data.Data.measurements); + setDuration(response.data.Data.duration); + setWidgetName(response.data.header); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } - } + }; fetchSavedInputes(); - }, [selectedChartId.id]); // Sync Zustand state when component mounts @@ -73,35 +77,44 @@ const WarehouseThroughputInputComponent = (props: Props) => { updateHeader(widgetName); }, [selections, duration, widgetName]); - - const sendInputes = async (inputMeasurement: any, inputDuration: any, inputName: any) => { + const sendInputes = async ( + inputMeasurement: any, + inputDuration: any, + inputName: any + ) => { try { - const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/floatwidget/save`, { - organization: organization, - zoneId: selectedZone.zoneId, - widget: { - id: selectedChartId.id, - header: inputName, - Data: { - measurements: inputMeasurement, - duration: inputDuration - } - } - } as any); + const response = await axios.post( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/floatwidget/save`, + { + organization: organization, + zoneId: selectedZone.zoneId, + widget: { + id: selectedChartId.id, + header: inputName, + Data: { + measurements: inputMeasurement, + duration: inputDuration, + }, + }, + } as any + ); if (response.status === 200) { - return true + return true; } else { console.log("Unexpected response:", response); - return false + return false; } } catch (error) { + echo.error("Failed to send input"); console.error("There was an error!", error); - return false + return false; } - } - - const handleSelect = async (inputKey: string, selectedData: { name: string; fields: string } | null) => { + }; + const handleSelect = async ( + inputKey: string, + selectedData: { name: string; fields: string } | null + ) => { // async() => { const newSelections = { ...selections }; if (selectedData === null) { @@ -126,20 +139,23 @@ const WarehouseThroughputInputComponent = (props: Props) => { // setDuration(option); }; - const handleNameChange = async (name:any) => { - console.log('name change requested',name); - + const handleNameChange = async (name: any) => { + console.log("name change requested", name); + if (await sendInputes(selections, duration, name)) { setWidgetName(name); } - } + }; return ( <>
Title
- +
{[...Array(1)].map((_, index) => { const inputKey = `input${index + 1}`; @@ -149,7 +165,9 @@ const WarehouseThroughputInputComponent = (props: Props) => {
handleSelect(inputKey, selectedData)} + onSelect={(selectedData) => + handleSelect(inputKey, selectedData) + } onUnselect={() => handleSelect(inputKey, null)} selectedValue={selections[inputKey]} // Load from Zustand isLoading={isLoading} diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget2InputCard3D.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget2InputCard3D.tsx index 62edae4..0723c80 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget2InputCard3D.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget2InputCard3D.tsx @@ -11,31 +11,34 @@ import RenameInput from "../../../../ui/inputs/RenameInput"; type Props = {}; const Widget2InputCard3D = (props: Props) => { - const { selectedChartId } = useWidgetStore(); + const { selectedChartId } = useWidgetStore(); const [widgetName, setWidgetName] = useState("untited"); const { setMeasurements, updateDuration, updateName } = useChartStore(); - const [duration, setDuration] = useState('1h') + const [duration, setDuration] = useState("1h"); const [dropDowndata, setDropDownData] = useState({}); - const [selections, setSelections] = useState>({}); + const [selections, setSelections] = useState< + Record + >({}); const { selectedZone } = useSelectedZoneStore(); const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0] + const organization = email?.split("@")[1]?.split(".")[0]; const [isLoading, setLoading] = useState(true); useEffect(() => { const fetchZoneData = async () => { try { - setLoading(true) + setLoading(true); const response = await axios.get(`http://${iotApiUrl}/floatinput`); if (response.status === 200) { // console.log("dropdown data:", response.data); setDropDownData(response.data); - setLoading(false) + setLoading(false); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch zone data"); console.error("There was an error!", error); } }; @@ -46,22 +49,24 @@ const Widget2InputCard3D = (props: Props) => { const fetchSavedInputes = async () => { if (selectedChartId.id !== "") { try { - const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${selectedChartId.id}/${organization}`); + const response = await axios.get( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${selectedChartId.id}/${organization}` + ); if (response.status === 200) { - setSelections(response.data.Data.measurements) - setDuration(response.data.Data.duration) - setWidgetName(response.data.widgetName) + setSelections(response.data.Data.measurements); + setDuration(response.data.Data.duration); + setWidgetName(response.data.widgetName); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } - } + }; fetchSavedInputes(); - }, [selectedChartId.id]); // Sync Zustand state when component mounts @@ -71,35 +76,44 @@ const Widget2InputCard3D = (props: Props) => { updateName(widgetName); }, [selections, duration, widgetName]); - - const sendInputes = async (inputMeasurement: any, inputDuration: any, inputName: any) => { + const sendInputes = async ( + inputMeasurement: any, + inputDuration: any, + inputName: any + ) => { try { - const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/3dwidget/save`, { - organization: organization, - zoneId: selectedZone.zoneId, - widget: { - id: selectedChartId.id, - widgetName: inputName, - Data: { - measurements: inputMeasurement, - duration: inputDuration - } - } - } as any); + const response = await axios.post( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/3dwidget/save`, + { + organization: organization, + zoneId: selectedZone.zoneId, + widget: { + id: selectedChartId.id, + widgetName: inputName, + Data: { + measurements: inputMeasurement, + duration: inputDuration, + }, + }, + } as any + ); if (response.status === 200) { - return true + return true; } else { console.log("Unexpected response:", response); - return false + return false; } } catch (error) { + echo.error("Failed to send input"); console.error("There was an error!", error); - return false + return false; } - } - - const handleSelect = async (inputKey: string, selectedData: { name: string; fields: string } | null) => { + }; + const handleSelect = async ( + inputKey: string, + selectedData: { name: string; fields: string } | null + ) => { // async() => { const newSelections = { ...selections }; if (selectedData === null) { @@ -124,20 +138,20 @@ const Widget2InputCard3D = (props: Props) => { // setDuration(option); }; - const handleNameChange = async (name:any) => { - console.log('name change requested',name); - + const handleNameChange = async (name: any) => { + console.log("name change requested", name); + if (await sendInputes(selections, duration, name)) { setWidgetName(name); } - } + }; return ( <>
Title
- +
{[...Array(2)].map((_, index) => { const inputKey = `input${index + 1}`; @@ -147,7 +161,9 @@ const Widget2InputCard3D = (props: Props) => {
handleSelect(inputKey, selectedData)} + onSelect={(selectedData) => + handleSelect(inputKey, selectedData) + } onUnselect={() => handleSelect(inputKey, null)} selectedValue={selections[inputKey]} // Load from Zustand isLoading={isLoading} @@ -165,4 +181,4 @@ const Widget2InputCard3D = (props: Props) => { ); }; -export default Widget2InputCard3D; \ No newline at end of file +export default Widget2InputCard3D; diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget3InputCard3D.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget3InputCard3D.tsx index 7481622..2e2b051 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget3InputCard3D.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget3InputCard3D.tsx @@ -9,31 +9,34 @@ import axios from "axios"; import RenameInput from "../../../../ui/inputs/RenameInput"; const Widget3InputCard3D = () => { - const { selectedChartId } = useWidgetStore(); + const { selectedChartId } = useWidgetStore(); const [widgetName, setWidgetName] = useState("untited"); const { setMeasurements, updateDuration, updateName } = useChartStore(); - const [duration, setDuration] = useState('1h') + const [duration, setDuration] = useState("1h"); const [dropDowndata, setDropDownData] = useState({}); - const [selections, setSelections] = useState>({}); + const [selections, setSelections] = useState< + Record + >({}); const { selectedZone } = useSelectedZoneStore(); const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0] + const organization = email?.split("@")[1]?.split(".")[0]; const [isLoading, setLoading] = useState(true); - + useEffect(() => { const fetchZoneData = async () => { try { - setLoading(true) + setLoading(true); const response = await axios.get(`http://${iotApiUrl}/getinput`); if (response.status === 200) { // console.log("dropdown data:", response.data); setDropDownData(response.data); - setLoading(false) + setLoading(false); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch zone data"); console.error("There was an error!", error); } }; @@ -44,22 +47,24 @@ const Widget3InputCard3D = () => { const fetchSavedInputes = async () => { if (selectedChartId.id !== "") { try { - const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${selectedChartId.id}/${organization}`); + const response = await axios.get( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${selectedChartId.id}/${organization}` + ); if (response.status === 200) { - setSelections(response.data.Data.measurements) - setDuration(response.data.Data.duration) - setWidgetName(response.data.widgetName) + setSelections(response.data.Data.measurements); + setDuration(response.data.Data.duration); + setWidgetName(response.data.widgetName); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } - } + }; fetchSavedInputes(); - }, [selectedChartId.id]); useEffect(() => { @@ -68,35 +73,44 @@ const Widget3InputCard3D = () => { updateName(widgetName); }, [selections, duration, widgetName]); - - const sendInputes = async (inputMeasurement: any, inputDuration: any, inputName: any) => { + const sendInputes = async ( + inputMeasurement: any, + inputDuration: any, + inputName: any + ) => { try { - const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/3dwidget/save`, { - organization: organization, - zoneId: selectedZone.zoneId, - widget: { - id: selectedChartId.id, - widgetName: inputName, - Data: { - measurements: inputMeasurement, - duration: inputDuration - } - } - } as any); + const response = await axios.post( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/3dwidget/save`, + { + organization: organization, + zoneId: selectedZone.zoneId, + widget: { + id: selectedChartId.id, + widgetName: inputName, + Data: { + measurements: inputMeasurement, + duration: inputDuration, + }, + }, + } as any + ); if (response.status === 200) { - return true + return true; } else { console.log("Unexpected response:", response); - return false + return false; } } catch (error) { + echo.error("Failed to send input"); console.error("There was an error!", error); - return false + return false; } - } - - const handleSelect = async (inputKey: string, selectedData: { name: string; fields: string } | null) => { + }; + const handleSelect = async ( + inputKey: string, + selectedData: { name: string; fields: string } | null + ) => { // async() => { const newSelections = { ...selections }; if (selectedData === null) { @@ -117,20 +131,20 @@ const Widget3InputCard3D = () => { } }; - const handleNameChange = async (name:any) => { - console.log('name change requested',name); - + const handleNameChange = async (name: any) => { + console.log("name change requested", name); + if (await sendInputes(selections, duration, name)) { setWidgetName(name); } - } + }; return ( <>
Title
- +
{[...Array(7)].map((_, index) => { const inputKey = `input${index + 1}`; @@ -140,7 +154,9 @@ const Widget3InputCard3D = () => {
handleSelect(inputKey, selectedData)} + onSelect={(selectedData) => + handleSelect(inputKey, selectedData) + } onUnselect={() => handleSelect(inputKey, null)} selectedValue={selections[inputKey]} // Load from Zustand isLoading={isLoading} diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget4InputCard3D.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget4InputCard3D.tsx index f8cdef6..cc8d9ca 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget4InputCard3D.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget4InputCard3D.tsx @@ -11,31 +11,34 @@ import RenameInput from "../../../../ui/inputs/RenameInput"; type Props = {}; const Widget4InputCard3D = (props: Props) => { - const { selectedChartId } = useWidgetStore(); + const { selectedChartId } = useWidgetStore(); const [widgetName, setWidgetName] = useState("untited"); const { setMeasurements, updateDuration, updateName } = useChartStore(); - const [duration, setDuration] = useState('1h') + const [duration, setDuration] = useState("1h"); const [dropDowndata, setDropDownData] = useState({}); - const [selections, setSelections] = useState>({}); + const [selections, setSelections] = useState< + Record + >({}); const { selectedZone } = useSelectedZoneStore(); const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0] + const organization = email?.split("@")[1]?.split(".")[0]; const [isLoading, setLoading] = useState(true); - + useEffect(() => { const fetchZoneData = async () => { try { - setLoading(true) + setLoading(true); const response = await axios.get(`http://${iotApiUrl}/floatinput`); if (response.status === 200) { // console.log("dropdown data:", response.data); setDropDownData(response.data); - setLoading(false) + setLoading(false); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch zone data"); console.error("There was an error!", error); } }; @@ -46,22 +49,24 @@ const Widget4InputCard3D = (props: Props) => { const fetchSavedInputes = async () => { if (selectedChartId.id !== "") { try { - const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${selectedChartId.id}/${organization}`); + const response = await axios.get( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${selectedChartId.id}/${organization}` + ); if (response.status === 200) { - setSelections(response.data.Data.measurements) - setDuration(response.data.Data.duration) - setWidgetName(response.data.widgetName) + setSelections(response.data.Data.measurements); + setDuration(response.data.Data.duration); + setWidgetName(response.data.widgetName); } else { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } - } + }; fetchSavedInputes(); - }, [selectedChartId.id]); // Sync Zustand state when component mounts @@ -71,35 +76,44 @@ const Widget4InputCard3D = (props: Props) => { updateName(widgetName); }, [selections, duration, widgetName]); - - const sendInputes = async (inputMeasurement: any, inputDuration: any, inputName: any) => { + const sendInputes = async ( + inputMeasurement: any, + inputDuration: any, + inputName: any + ) => { try { - const response = await axios.post(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/3dwidget/save`, { - organization: organization, - zoneId: selectedZone.zoneId, - widget: { - id: selectedChartId.id, - widgetName: inputName, - Data: { - measurements: inputMeasurement, - duration: inputDuration - } - } - } as any); + const response = await axios.post( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/3dwidget/save`, + { + organization: organization, + zoneId: selectedZone.zoneId, + widget: { + id: selectedChartId.id, + widgetName: inputName, + Data: { + measurements: inputMeasurement, + duration: inputDuration, + }, + }, + } as any + ); if (response.status === 200) { - return true + return true; } else { console.log("Unexpected response:", response); - return false + return false; } } catch (error) { + echo.error("Failed to send input"); console.error("There was an error!", error); - return false + return false; } - } - - const handleSelect = async (inputKey: string, selectedData: { name: string; fields: string } | null) => { + }; + const handleSelect = async ( + inputKey: string, + selectedData: { name: string; fields: string } | null + ) => { // async() => { const newSelections = { ...selections }; if (selectedData === null) { @@ -124,20 +138,20 @@ const Widget4InputCard3D = (props: Props) => { // setDuration(option); }; - const handleNameChange = async (name:any) => { - console.log('name change requested',name); - + const handleNameChange = async (name: any) => { + console.log("name change requested", name); + if (await sendInputes(selections, duration, name)) { setWidgetName(name); } - } + }; return ( <>
Title
- +
{[...Array(1)].map((_, index) => { const inputKey = `input${index + 1}`; @@ -147,7 +161,9 @@ const Widget4InputCard3D = (props: Props) => {
handleSelect(inputKey, selectedData)} + onSelect={(selectedData) => + handleSelect(inputKey, selectedData) + } onUnselect={() => handleSelect(inputKey, null)} selectedValue={selections[inputKey]} // Load from Zustand isLoading={isLoading} diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx index b5403e1..80ecf8a 100644 --- a/app/src/components/ui/list/List.tsx +++ b/app/src/components/ui/list/List.tsx @@ -90,6 +90,7 @@ const List: React.FC = ({ items = [], remove }) => { zoneViewPortPosition: response?.viewPortposition ?? [], }); } catch (error) { + echo.error("Failed to select zone"); console.log(error); } } diff --git a/app/src/components/ui/simulation/AssetDetailsCard.tsx b/app/src/components/ui/simulation/AssetDetailsCard.tsx new file mode 100644 index 0000000..ff7accd --- /dev/null +++ b/app/src/components/ui/simulation/AssetDetailsCard.tsx @@ -0,0 +1,114 @@ +import React, { useState } from "react"; +import { + CartBagIcon, + ExpandIcon, + IndicationArrow, + SimulationStatusIcon, +} from "../../icons/SimulationIcons"; +import { usePlayButtonStore } from "../../../store/usePlayButtonStore"; + +interface AssetDetailsCardInterface { + name: string; + status: string; + count?: number; + totalCapacity?: number; + assetDetails?: { + assetName: string; + const: string; + performance: string; + }; +} + +const GetStatus = (status: string) => { + // "idle" | "running" | "stopped" | "disabled" | "error" + switch (status) { + case "idle": + return ( +
+
+ +
+
Idle
+
+ ); + case "running": + return ( +
+
+ +
+
Running
+
+ ); + case "stopped": + return ( +
+
+ +
+
Stopped
+
+ ); + } +}; + +const AssetDetailsCard: React.FC = ({ + name, + status, + count, + totalCapacity, + assetDetails, +}) => { + const [moreDetails, setMoreDetails] = useState(false); + // hooks + const { isPlaying } = usePlayButtonStore(); + + return ( +
+
+
+
+
{name}
+
{GetStatus(status)}
+
+ +
+ + {totalCapacity && ( +
+
+
+ +
+
{count?.toString()}
+
+
+ )} + + {status === "running" && ( +
+
+
+ )} +
+ +
+
+
+ ); +}; + +export default AssetDetailsCard; diff --git a/app/src/global.d.ts b/app/src/global.d.ts new file mode 100644 index 0000000..804fae0 --- /dev/null +++ b/app/src/global.d.ts @@ -0,0 +1,13 @@ +// src/global.d.ts +import { LogType } from "../components/ui/log/LoggerContext"; + +declare global { + const echo: { + log: (message: string) => void; + info: (message: string) => void; + warn: (message: string) => void; + error: (message: string) => void; + success: (message: string) => void; + clear: () => void; + }; +} diff --git a/app/src/modules/builder/builder.tsx b/app/src/modules/builder/builder.tsx index c0a3267..fdf17bc 100644 --- a/app/src/modules/builder/builder.tsx +++ b/app/src/modules/builder/builder.tsx @@ -18,19 +18,19 @@ import Window from "../../assets/gltf-glb/window.glb"; ////////// Zustand State Imports ////////// import { - useToggleView, - useDeletePointOrLine, - useMovePoint, - useActiveLayer, - useWallVisibility, - useRoofVisibility, - useShadows, - useUpdateScene, - useWalls, - useToolMode, - useRefTextUpdate, - useRenderDistance, - useLimitDistance, + useToggleView, + useDeletePointOrLine, + useMovePoint, + useActiveLayer, + useWallVisibility, + useRoofVisibility, + useShadows, + useUpdateScene, + useWalls, + useToolMode, + useRefTextUpdate, + useRenderDistance, + useLimitDistance, } from "../../store/store"; ////////// 3D Function Imports ////////// @@ -54,296 +54,295 @@ import MeasurementTool from "../scene/tools/measurementTool"; import NavMesh from "../simulation/vehicle/navMesh/navMesh"; export default function Builder() { - const state = useThree(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements. - const csg = useRef(); // Reference for CSG object, used for 3D modeling. - const CSGGroup = useRef() as Types.RefMesh; // Reference to a group of CSG objects. - const scene = useRef() as Types.RefScene; // Reference to the scene. - const camera = useRef() as Types.RefCamera; // Reference to the camera object. - const controls = useRef(); // Reference to the controls object. - const raycaster = useRef() as Types.RefRaycaster; // Reference for raycaster used for detecting objects being pointed at in the scene. - const dragPointControls = useRef() as Types.RefDragControl; // Reference for drag point controls, an array for drag control. + const state = useThree(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements. + const csg = useRef(); // Reference for CSG object, used for 3D modeling. + const CSGGroup = useRef() as Types.RefMesh; // Reference to a group of CSG objects. + const scene = useRef() as Types.RefScene; // Reference to the scene. + const camera = useRef() as Types.RefCamera; // Reference to the camera object. + const controls = useRef(); // Reference to the controls object. + const raycaster = useRef() as Types.RefRaycaster; // Reference for raycaster used for detecting objects being pointed at in the scene. + const dragPointControls = useRef() as Types.RefDragControl; // Reference for drag point controls, an array for drag control. - // Assigning the scene and camera from the Three.js state to the references. + // Assigning the scene and camera from the Three.js state to the references. - scene.current = state.scene; - camera.current = state.camera; - controls.current = state.controls; - raycaster.current = state.raycaster; + scene.current = state.scene; + camera.current = state.camera; + controls.current = state.controls; + raycaster.current = state.raycaster; - const plane = useRef(null); // Reference for a plane object for raycaster reference. - const grid = useRef() as any; // Reference for a grid object for raycaster reference. - const snappedPoint = useRef() as Types.RefVector3; // Reference for storing a snapped point at the (end = isSnapped) and (start = ispreSnapped) of the line. - const isSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (end). - const anglesnappedPoint = useRef() as Types.RefVector3; // Reference for storing an angle-snapped point when the line is in 90 degree etc... - const isAngleSnapped = useRef(false) as Types.RefBoolean; // Boolean to indicate if angle snapping is active. - const isSnappedUUID = useRef() as Types.RefString; // UUID reference to identify the snapped point. - const ispreSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (start). - const tempLoader = useRef() as Types.RefMesh; // Reference for a temporary loader for the floor items. - const isTempLoader = useRef() as Types.RefBoolean; // Reference to check if a temporary loader is active. - const Tube = useRef() as Types.RefTubeGeometry; // Reference for tubes used for reference line creation and updation. - const line = useRef([]) as Types.RefLine; // Reference for line which stores the current line that is being drawn. - const lines = useRef([]) as Types.RefLines; // Reference for lines which stores all the lines that are ever drawn. - const onlyFloorline = useRef([]); // Reference for floor lines which does not have walls or roof and have only floor used to store the current line that is being drawn. - const onlyFloorlines = useRef([]); // Reference for all the floor lines that are ever drawn. - const ReferenceLineMesh = useRef() as Types.RefMesh; // Reference for storing the mesh of the reference line for moving it during draw. - const LineCreated = useRef(false) as Types.RefBoolean; // Boolean to track whether the reference line is created or not. - const referencePole = useRef() as Types.RefMesh; // Reference for a pole that is used as the reference for the user to show where it is placed. - const itemsGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the floor items (Gltf). - const floorGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the roofs and the floors. - const AttachedObject = useRef() as Types.RefMesh; // Reference for an object that is attached using dbl click for transform controls rotation. - const floorPlanGroup = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines group and the points group. - const floorPlanGroupLine = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines that are drawn. - const floorPlanGroupPoint = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the points that are created. - const floorGroupAisle = useRef() as Types.RefGroup; - const zoneGroup = useRef() as Types.RefGroup; - const currentLayerPoint = useRef([]) as Types.RefMeshArray; // Reference for points that re in the current layer used to update the points in drag controls. - const hoveredDeletablePoint = useRef() as Types.RefMesh; // Reference for the currently hovered point that can be deleted. - const hoveredDeletableLine = useRef() as Types.RefMesh; // Reference for the currently hovered line that can be deleted. - const hoveredDeletableFloorItem = useRef() as Types.RefMesh; // Reference for the currently hovered floor item that can be deleted. - const hoveredDeletableWallItem = useRef() as Types.RefMesh; // Reference for the currently hovered wall item that can be deleted. - const hoveredDeletablePillar = useRef() as Types.RefMesh; // Reference for the currently hovered pillar that can be deleted. - const currentWallItem = useRef() as Types.RefMesh; // Reference for the currently selected wall item that can be scaled, dragged etc... + const plane = useRef(null); // Reference for a plane object for raycaster reference. + const grid = useRef() as any; // Reference for a grid object for raycaster reference. + const snappedPoint = useRef() as Types.RefVector3; // Reference for storing a snapped point at the (end = isSnapped) and (start = ispreSnapped) of the line. + const isSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (end). + const anglesnappedPoint = useRef() as Types.RefVector3; // Reference for storing an angle-snapped point when the line is in 90 degree etc... + const isAngleSnapped = useRef(false) as Types.RefBoolean; // Boolean to indicate if angle snapping is active. + const isSnappedUUID = useRef() as Types.RefString; // UUID reference to identify the snapped point. + const ispreSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (start). + const tempLoader = useRef() as Types.RefMesh; // Reference for a temporary loader for the floor items. + const isTempLoader = useRef() as Types.RefBoolean; // Reference to check if a temporary loader is active. + const Tube = useRef() as Types.RefTubeGeometry; // Reference for tubes used for reference line creation and updation. + const line = useRef([]) as Types.RefLine; // Reference for line which stores the current line that is being drawn. + const lines = useRef([]) as Types.RefLines; // Reference for lines which stores all the lines that are ever drawn. + const onlyFloorline = useRef([]); // Reference for floor lines which does not have walls or roof and have only floor used to store the current line that is being drawn. + const onlyFloorlines = useRef([]); // Reference for all the floor lines that are ever drawn. + const ReferenceLineMesh = useRef() as Types.RefMesh; // Reference for storing the mesh of the reference line for moving it during draw. + const LineCreated = useRef(false) as Types.RefBoolean; // Boolean to track whether the reference line is created or not. + const referencePole = useRef() as Types.RefMesh; // Reference for a pole that is used as the reference for the user to show where it is placed. + const itemsGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the floor items (Gltf). + const floorGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the roofs and the floors. + const AttachedObject = useRef() as Types.RefMesh; // Reference for an object that is attached using dbl click for transform controls rotation. + const floorPlanGroup = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines group and the points group. + const floorPlanGroupLine = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines that are drawn. + const floorPlanGroupPoint = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the points that are created. + const floorGroupAisle = useRef() as Types.RefGroup; + const zoneGroup = useRef() as Types.RefGroup; + const currentLayerPoint = useRef([]) as Types.RefMeshArray; // Reference for points that re in the current layer used to update the points in drag controls. + const hoveredDeletablePoint = useRef() as Types.RefMesh; // Reference for the currently hovered point that can be deleted. + const hoveredDeletableLine = useRef() as Types.RefMesh; // Reference for the currently hovered line that can be deleted. + const hoveredDeletableFloorItem = useRef() as Types.RefMesh; // Reference for the currently hovered floor item that can be deleted. + const hoveredDeletableWallItem = useRef() as Types.RefMesh; // Reference for the currently hovered wall item that can be deleted. + const hoveredDeletablePillar = useRef() as Types.RefMesh; // Reference for the currently hovered pillar that can be deleted. + const currentWallItem = useRef() as Types.RefMesh; // Reference for the currently selected wall item that can be scaled, dragged etc... - const cursorPosition = new THREE.Vector3(); // 3D vector for storing the cursor position. + const cursorPosition = new THREE.Vector3(); // 3D vector for storing the cursor position. - const [selectedItemsIndex, setSelectedItemsIndex] = - useState(null); // State for tracking the index of the selected item. - const { activeLayer } = useActiveLayer(); // State that changes based on which layer the user chooses in Layers.jsx. - const { toggleView } = useToggleView(); // State for toggling between 2D and 3D. - const { toolMode, setToolMode } = useToolMode(); - const { setMovePoint } = useMovePoint(); // State that stores a boolean which represents whether the move mode is active or not. - const { setDeletePointOrLine } = useDeletePointOrLine(); - const { setRoofVisibility } = useRoofVisibility(); - const { setWallVisibility } = useWallVisibility(); - const { setShadows } = useShadows(); - const { setRenderDistance } = useRenderDistance(); - const { setLimitDistance } = useLimitDistance(); - const { setUpdateScene } = useUpdateScene(); - const { setWalls } = useWalls(); - const { refTextupdate, setRefTextUpdate } = useRefTextUpdate(); + const [selectedItemsIndex, setSelectedItemsIndex] = useState(null); // State for tracking the index of the selected item. + const { activeLayer } = useActiveLayer(); // State that changes based on which layer the user chooses in Layers.jsx. + const { toggleView } = useToggleView(); // State for toggling between 2D and 3D. + const { toolMode, setToolMode } = useToolMode(); + const { setMovePoint } = useMovePoint(); // State that stores a boolean which represents whether the move mode is active or not. + const { setDeletePointOrLine } = useDeletePointOrLine(); + const { setRoofVisibility } = useRoofVisibility(); + const { setWallVisibility } = useWallVisibility(); + const { setShadows } = useShadows(); + const { setRenderDistance } = useRenderDistance(); + const { setLimitDistance } = useLimitDistance(); + const { setUpdateScene } = useUpdateScene(); + const { setWalls } = useWalls(); + const { refTextupdate, setRefTextUpdate } = useRefTextUpdate(); - // const loader = new GLTFLoader(); - // const dracoLoader = new DRACOLoader(); + // const loader = new GLTFLoader(); + // const dracoLoader = new DRACOLoader(); - // dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); - // loader.setDRACOLoader(dracoLoader); + // dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); + // loader.setDRACOLoader(dracoLoader); - ////////// Assest Configuration Values ////////// + ////////// Assest Configuration Values ////////// - const AssetConfigurations: Types.AssetConfigurations = { - arch: { - modelUrl: arch, - scale: [0.75, 0.75, 0.75], - csgscale: [2, 4, 0.5], - csgposition: [0, 2, 0], - positionY: () => 0, - type: "Fixed-Move", - }, - door: { - modelUrl: door, - scale: [0.75, 0.75, 0.75], - csgscale: [2, 4, 0.5], - csgposition: [0, 2, 0], - positionY: () => 0, - type: "Fixed-Move", - }, - window: { - modelUrl: Window, - scale: [0.75, 0.75, 0.75], - csgscale: [5, 3, 0.5], - csgposition: [0, 1.5, 0], - positionY: (intersectionPoint) => intersectionPoint.point.y, - type: "Free-Move", - }, - }; + const AssetConfigurations: Types.AssetConfigurations = { + arch: { + modelUrl: arch, + scale: [0.75, 0.75, 0.75], + csgscale: [2, 4, 0.5], + csgposition: [0, 2, 0], + positionY: () => 0, + type: "Fixed-Move", + }, + door: { + modelUrl: door, + scale: [0.75, 0.75, 0.75], + csgscale: [2, 4, 0.5], + csgposition: [0, 2, 0], + positionY: () => 0, + type: "Fixed-Move", + }, + window: { + modelUrl: Window, + scale: [0.75, 0.75, 0.75], + csgscale: [5, 3, 0.5], + csgposition: [0, 1.5, 0], + positionY: (intersectionPoint) => intersectionPoint.point.y, + type: "Free-Move", + }, + }; - ////////// All Toggle's ////////// + ////////// All Toggle's ////////// - useEffect(() => { - setRefTextUpdate((prevUpdate: number) => prevUpdate - 1); - if (dragPointControls.current) { - dragPointControls.current.enabled = false; - } - if (toggleView) { - Layer2DVisibility( - activeLayer, - floorPlanGroup, - floorPlanGroupLine, - floorPlanGroupPoint, - currentLayerPoint, - dragPointControls - ); - } else { - setToolMode(null); - setDeletePointOrLine(false); - setMovePoint(false); - loadWalls(lines, setWalls); - setUpdateScene(true); - line.current = []; - } - }, [toggleView]); + useEffect(() => { + setRefTextUpdate((prevUpdate: number) => prevUpdate - 1); + if (dragPointControls.current) { + dragPointControls.current.enabled = false; + } + if (toggleView) { + Layer2DVisibility( + activeLayer, + floorPlanGroup, + floorPlanGroupLine, + floorPlanGroupPoint, + currentLayerPoint, + dragPointControls + ); + } else { + setToolMode(null); + setDeletePointOrLine(false); + setMovePoint(false); + loadWalls(lines, setWalls); + setUpdateScene(true); + line.current = []; + } + }, [toggleView]); - useEffect(() => { - THREE.Cache.clear(); - THREE.Cache.enabled = true; - }, []); + useEffect(() => { + THREE.Cache.clear(); + THREE.Cache.enabled = true; + }, []); - useEffect(() => { - const email = localStorage.getItem("email"); - const organization = email!.split("@")[1].split(".")[0]; + useEffect(() => { + const email = localStorage.getItem("email"); + const organization = email!.split("@")[1].split(".")[0]; - async function fetchVisibility() { - const visibility = await findEnvironment( - organization, - localStorage.getItem("userId")! - ); - if (visibility) { - setRoofVisibility(visibility.roofVisibility); - setWallVisibility(visibility.wallVisibility); - setShadows(visibility.shadowVisibility); - setRenderDistance(visibility.renderDistance); - setLimitDistance(visibility.limitDistance); - } - } - fetchVisibility(); - }, []); + async function fetchVisibility() { + const visibility = await findEnvironment( + organization, + localStorage.getItem("userId")! + ); + if (visibility) { + setRoofVisibility(visibility.roofVisibility); + setWallVisibility(visibility.wallVisibility); + setShadows(visibility.shadowVisibility); + setRenderDistance(visibility.renderDistance); + setLimitDistance(visibility.limitDistance); + } + } + fetchVisibility(); + }, []); - ////////// UseFrame is Here ////////// + ////////// UseFrame is Here ////////// - useFrame(() => { - if (toolMode) { - Draw( - state, - plane, - cursorPosition, - floorPlanGroupPoint, - floorPlanGroupLine, - snappedPoint, - isSnapped, - isSnappedUUID, - line, - lines, - ispreSnapped, - floorPlanGroup, - ReferenceLineMesh, - LineCreated, - setRefTextUpdate, - Tube, - anglesnappedPoint, - isAngleSnapped, - toolMode - ); - } - }); + useFrame(() => { + if (toolMode) { + Draw( + state, + plane, + cursorPosition, + floorPlanGroupPoint, + floorPlanGroupLine, + snappedPoint, + isSnapped, + isSnappedUUID, + line, + lines, + ispreSnapped, + floorPlanGroup, + ReferenceLineMesh, + LineCreated, + setRefTextUpdate, + Tube, + anglesnappedPoint, + isAngleSnapped, + toolMode + ); + } + }); - ////////// Return ////////// + ////////// Return ////////// - return ( - <> - + return ( + <> + - + - + - + - + - + - + - + - + - + - + - - - ); + + + ); } diff --git a/app/src/modules/builder/geomentries/assets/addAssetModel.ts b/app/src/modules/builder/geomentries/assets/addAssetModel.ts index 6e978dc..707b8c0 100644 --- a/app/src/modules/builder/geomentries/assets/addAssetModel.ts +++ b/app/src/modules/builder/geomentries/assets/addAssetModel.ts @@ -99,6 +99,7 @@ async function addAssetModel( } } } catch (error) { + echo.error("Failed to add asset"); console.error('Error fetching asset model:', error); } finally { setSelectedItem({}); diff --git a/app/src/modules/builder/geomentries/lines/distanceText/distanceText.tsx b/app/src/modules/builder/geomentries/lines/distanceText/distanceText.tsx index 307d51f..b8c0947 100644 --- a/app/src/modules/builder/geomentries/lines/distanceText/distanceText.tsx +++ b/app/src/modules/builder/geomentries/lines/distanceText/distanceText.tsx @@ -2,142 +2,180 @@ import { useEffect, useState } from "react"; import { getLines } from "../../../../../services/factoryBuilder/lines/getLinesApi"; import * as THREE from "three"; import { - useActiveLayer, - useDeletedLines, - useNewLines, - useToggleView, + useActiveLayer, + useDeletedLines, + useNewLines, + useRoomsState, + useToggleView, } from "../../../../../store/store"; import objectLinesToArray from "../lineConvertions/objectLinesToArray"; import { Html } from "@react-three/drei"; import * as Types from "../../../../../types/world/worldTypes"; +import getRoomsFromLines from "../getRoomsFromLines"; const DistanceText = () => { - const [lines, setLines] = useState< - { - distance: string; - position: THREE.Vector3; - userData: Types.Line; - layer: string; - }[] - >([]); - const { activeLayer } = useActiveLayer(); - const { toggleView } = useToggleView(); - const { newLines, setNewLines } = useNewLines(); - const { deletedLines, setDeletedLines } = useDeletedLines(); + const [lines, setLines] = useState< + { + distance: string; + position: THREE.Vector3; + userData: Types.Line; + layer: string; + }[] + >([]); + const { activeLayer } = useActiveLayer(); + const { toggleView } = useToggleView(); + const { newLines, setNewLines } = useNewLines(); + const { deletedLines, setDeletedLines } = useDeletedLines(); + const [linesState, setLinesState] = useState([]); + const { roomsState, setRoomsState } = useRoomsState(); - useEffect(() => { - const email = localStorage.getItem("email"); - if (!email) return; - const organization = email.split("@")[1].split(".")[0]; + useEffect(() => { + if (linesState.length === 0) return; + const getLines = async () => { - getLines(organization).then((data) => { - data = objectLinesToArray(data); + if (lines.length > 2) { + const linesByLayer = linesState.reduce((acc: { [key: number]: any[] }, pair) => { + const layer = pair[0][2]; + if (!acc[layer]) acc[layer] = []; + acc[layer].push(pair); + return acc; + }, {}); - const lines = data - .filter((line: Types.Line) => line[0][2] === activeLayer) - .map((line: Types.Line) => { - const point1 = new THREE.Vector3( - line[0][0].x, - line[0][0].y, - line[0][0].z - ); - const point2 = new THREE.Vector3( - line[1][0].x, - line[1][0].y, - line[1][0].z - ); - const distance = point1.distanceTo(point2); - const midpoint = new THREE.Vector3() - .addVectors(point1, point2) - .divideScalar(2); - return { - distance: distance.toFixed(1), - position: midpoint, - userData: line, - layer: activeLayer, - }; + for (const layer in linesByLayer) { + + const rooms: Types.Rooms = await getRoomsFromLines({ current: linesByLayer[layer] }); + + } + } + } + getLines(); + }, [linesState]) + + useEffect(() => { + const email = localStorage.getItem("email"); + if (!email) return; + const organization = email.split("@")[1].split(".")[0]; + + getLines(organization).then((data) => { + data = objectLinesToArray(data); + setLinesState(data); + + const lines = data + .filter((line: Types.Line) => line[0][2] === activeLayer) + .map((line: Types.Line) => { + const point1 = new THREE.Vector3( + line[0][0].x, + line[0][0].y, + line[0][0].z + ); + const point2 = new THREE.Vector3( + line[1][0].x, + line[1][0].y, + line[1][0].z + ); + const distance = point1.distanceTo(point2); + const midpoint = new THREE.Vector3() + .addVectors(point1, point2) + .divideScalar(2); + return { + distance: distance.toFixed(1), + position: midpoint, + userData: line, + layer: activeLayer, + }; + }); + setLines(lines); }); - setLines(lines); - }); - }, [activeLayer]); + }, [activeLayer]); - useEffect(() => { - if (newLines.length > 0) { - if (newLines[0][0][2] !== activeLayer) return; - const newLinesData = newLines.map((line: Types.Line) => { - const point1 = new THREE.Vector3( - line[0][0].x, - line[0][0].y, - line[0][0].z - ); - const point2 = new THREE.Vector3( - line[1][0].x, - line[1][0].y, - line[1][0].z - ); - const distance = point1.distanceTo(point2); - const midpoint = new THREE.Vector3() - .addVectors(point1, point2) - .divideScalar(2); + useEffect(() => { + if (newLines.length > 0) { + if (newLines[0][0][2] !== activeLayer) return; + const newLinesData = newLines.map((line: Types.Line) => { + const point1 = new THREE.Vector3( + line[0][0].x, + line[0][0].y, + line[0][0].z + ); + const point2 = new THREE.Vector3( + line[1][0].x, + line[1][0].y, + line[1][0].z + ); + const distance = point1.distanceTo(point2); + const midpoint = new THREE.Vector3() + .addVectors(point1, point2) + .divideScalar(2); - return { - distance: distance.toFixed(1), - position: midpoint, - userData: line, - layer: activeLayer, - }; - }); - setLines((prevLines) => [...prevLines, ...newLinesData]); - setNewLines([]); - } - }, [newLines, activeLayer]); + return { + distance: distance.toFixed(1), + position: midpoint, + userData: line, + layer: activeLayer, + }; + }); + setLines((prevLines) => [...prevLines, ...newLinesData]); + setLinesState((prevLines) => [...prevLines, ...newLines]); + setNewLines([]); + } + }, [newLines, activeLayer]); - useEffect(() => { - if ((deletedLines as Types.Lines).length > 0) { - setLines((prevLines) => - prevLines.filter( - (line) => - !deletedLines.some( - (deletedLine: any) => - deletedLine[0][1] === line.userData[0][1] && - deletedLine[1][1] === line.userData[1][1] - ) - ) - ); - setDeletedLines([]); - } - }, [deletedLines]); + useEffect(() => { + if ((deletedLines as Types.Lines).length > 0) { + setLines((prevLines) => + prevLines.filter( + (line) => + !deletedLines.some( + (deletedLine: any) => + deletedLine[0][1] === line.userData[0][1] && + deletedLine[1][1] === line.userData[1][1] + ) + ) + ); - return ( - <> - {toggleView && ( - - {lines.map((text) => ( - -
- {text.distance} m -
- - ))} -
- )} - - ); + setLinesState(prev => + prev.filter(line => + !(deletedLines as Types.Lines).some( + deleted => + line[0][1] === deleted[0][1] && line[1][1] === deleted[1][1] + ) + ) + ); + + setDeletedLines([]); + } + }, [deletedLines]); + + return ( + <> + {toggleView && ( + + {lines.map((text) => ( + +
+ {text.distance} m +
+ + ))} +
+ )} + + ); }; export default DistanceText; diff --git a/app/src/modules/builder/groups/zoneGroup.tsx b/app/src/modules/builder/groups/zoneGroup.tsx index 3bd9b8d..b0c8124 100644 --- a/app/src/modules/builder/groups/zoneGroup.tsx +++ b/app/src/modules/builder/groups/zoneGroup.tsx @@ -549,7 +549,7 @@ const ZoneGroup: React.FC = () => { const midpoint = new THREE.Vector3( (point1.x + point2.x) / 2, CONSTANTS.zoneConfig.height / 2 + - (zone.layer - 1) * CONSTANTS.zoneConfig.height, + (zone.layer - 1) * CONSTANTS.zoneConfig.height, (point1.z + point2.z) / 2 ); diff --git a/app/src/modules/collaboration/socket/socketResponses.dev.tsx b/app/src/modules/collaboration/socket/socketResponses.dev.tsx index 86e41c2..c5d0a5f 100644 --- a/app/src/modules/collaboration/socket/socketResponses.dev.tsx +++ b/app/src/modules/collaboration/socket/socketResponses.dev.tsx @@ -1,13 +1,25 @@ import { useEffect } from "react"; -import * as THREE from 'three'; -import gsap from 'gsap'; -import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; +import * as THREE from "three"; +import gsap from "gsap"; +import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader"; -import { toast } from 'react-toastify'; -import { useSocketStore, useActiveLayer, useWallItems, useFloorItems, useLayers, useUpdateScene, useWalls, useDeletedLines, useNewLines, useZonePoints, useZones } from "../../../store/store"; +import { toast } from "react-toastify"; +import { + useSocketStore, + useActiveLayer, + useWallItems, + useFloorItems, + useLayers, + useUpdateScene, + useWalls, + useDeletedLines, + useNewLines, + useZonePoints, + useZones, +} from "../../../store/store"; import * as Types from "../../../types/world/worldTypes"; -import * as CONSTANTS from '../../../types/world/worldConstants'; +import * as CONSTANTS from "../../../types/world/worldConstants"; import TempLoader from "../../builder/geomentries/assets/tempLoader"; // import { setFloorItemApi } from "../../services/factoryBuilder/assest/floorAsset/setFloorItemApi"; @@ -23,662 +35,834 @@ import Layer2DVisibility from "../../builder/geomentries/layers/layer2DVisibilit import { retrieveGLTF, storeGLTF } from "../../../utils/indexDB/idbUtils"; import { getZonesApi } from "../../../services/factoryBuilder/zones/getZonesApi"; - export default function SocketResponses({ - floorPlanGroup, - lines, - floorGroup, - floorGroupAisle, - scene, - onlyFloorlines, - AssetConfigurations, - itemsGroup, - isTempLoader, - tempLoader, - currentLayerPoint, - floorPlanGroupPoint, - floorPlanGroupLine, - zoneGroup, - dragPointControls + floorPlanGroup, + lines, + floorGroup, + floorGroupAisle, + scene, + onlyFloorlines, + AssetConfigurations, + itemsGroup, + isTempLoader, + tempLoader, + currentLayerPoint, + floorPlanGroupPoint, + floorPlanGroupLine, + zoneGroup, + dragPointControls, }: any) { + const { socket } = useSocketStore(); + const { activeLayer, setActiveLayer } = useActiveLayer(); + const { wallItems, setWallItems } = useWallItems(); + const { layers, setLayers } = useLayers(); + const { floorItems, setFloorItems } = useFloorItems(); + const { updateScene, setUpdateScene } = useUpdateScene(); + const { walls, setWalls } = useWalls(); + const { deletedLines, setDeletedLines } = useDeletedLines(); + const { newLines, setNewLines } = useNewLines(); + const { zones, setZones } = useZones(); + const { zonePoints, setZonePoints } = useZonePoints(); - const { socket } = useSocketStore(); - const { activeLayer, setActiveLayer } = useActiveLayer(); - const { wallItems, setWallItems } = useWallItems(); - const { layers, setLayers } = useLayers(); - const { floorItems, setFloorItems } = useFloorItems(); - const { updateScene, setUpdateScene } = useUpdateScene(); - const { walls, setWalls } = useWalls(); - const { deletedLines, setDeletedLines } = useDeletedLines(); - const { newLines, setNewLines } = useNewLines(); - const { zones, setZones } = useZones(); - const { zonePoints, setZonePoints } = useZonePoints(); + useEffect(() => { + const email = localStorage.getItem("email"); + const organization = email!.split("@")[1].split(".")[0]; - useEffect(() => { + if (!socket) return; - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; + socket.on("cameraCreateResponse", (data: any) => { + // console.log('data: ', data); + }); - if (!socket) return + socket.on("userConnectRespones", (data: any) => { + // console.log('data: ', data); + }); - socket.on('cameraCreateResponse', (data: any) => { - // console.log('data: ', data); - }) + socket.on("userDisConnectRespones", (data: any) => { + // console.log('data: ', data); + }); - socket.on('userConnectRespones', (data: any) => { - // console.log('data: ', data); - }) + socket.on("cameraUpdateResponse", (data: any) => { + // console.log('data: ', data); + }); - socket.on('userDisConnectRespones', (data: any) => { - // console.log('data: ', data); - }) + socket.on("EnvironmentUpdateResponse", (data: any) => { + // console.log('data: ', data); + }); - socket.on('cameraUpdateResponse', (data: any) => { - // console.log('data: ', data); - }) + socket.on("model-asset:response:updates", async (data: any) => { + // console.log('data: ', data); + if (socket.id === data.socketId) { + return; + } + if (organization !== data.organization) { + return; + } + if (data.message === "Model created successfully") { + const loader = new GLTFLoader(); + const dracoLoader = new DRACOLoader(); - socket.on('EnvironmentUpdateResponse', (data: any) => { - // console.log('data: ', data); - }) + dracoLoader.setDecoderPath( + "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/" + ); + loader.setDRACOLoader(dracoLoader); + let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; - socket.on('model-asset:response:updates', async (data: any) => { - // console.log('data: ', data); - if (socket.id === data.socketId) { - return + try { + isTempLoader.current = true; + const cachedModel = THREE.Cache.get(data.data.modelName); + let url; + if (cachedModel) { + // console.log(`Getting ${data.data.modelName} from cache`); + const model = cachedModel.scene.clone(); + model.uuid = data.data.modelUuid; + model.userData = { + name: data.data.modelName, + modelId: data.data.modelfileID, + modelUuid: data.data.modelUuid, + }; + model.position.set( + ...(data.data.position as [number, number, number]) + ); + model.rotation.set( + data.data.rotation.x, + data.data.rotation.y, + data.data.rotation.z + ); + model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); + + model.traverse((child: any) => { + if (child.isMesh) { + // Clone the material to ensure changes are independent + // child.material = child.material.clone(); + + child.castShadow = true; + child.receiveShadow = true; + } + }); + + itemsGroup.current.add(model); + + if (tempLoader.current) { + tempLoader.current.material.dispose(); + tempLoader.current.geometry.dispose(); + itemsGroup.current.remove(tempLoader.current); + tempLoader.current = undefined; } - if (organization !== data.organization) { - return + + const newFloorItem: Types.FloorItemType = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + modelfileID: data.data.modelfileID, + position: [...(data.data.position as [number, number, number])], + rotation: { + x: model.rotation.x, + y: model.rotation.y, + z: model.rotation.z, + }, + isLocked: data.data.isLocked, + isVisible: data.data.isVisible, + }; + + setFloorItems((prevItems: any) => { + const updatedItems = [...(prevItems || []), newFloorItem]; + localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); + return updatedItems; + }); + + gsap.to(model.position, { + y: data.data.position[1], + duration: 1.5, + ease: "power2.out", + }); + gsap.to(model.scale, { + x: 1, + y: 1, + z: 1, + duration: 1.5, + ease: "power2.out", + onComplete: () => { + toast.success("Model Added!"); + }, + }); + } else { + const indexedDBModel = await retrieveGLTF(data.data.modelName); + if (indexedDBModel) { + // console.log(`Getting ${data.data.modelName} from IndexedDB`); + url = URL.createObjectURL(indexedDBModel); + } else { + // console.log(`Getting ${data.data.modelName} from Backend`); + url = `${url_Backend_dwinzo}/api/v2/AssetFile/${data.data.modelfileID}`; + const modelBlob = await fetch(url).then((res) => res.blob()); + await storeGLTF(data.data.modelfileID, modelBlob); } - if (data.message === "Model created successfully") { - const loader = new GLTFLoader(); - const dracoLoader = new DRACOLoader(); + } - dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); - loader.setDRACOLoader(dracoLoader); - let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; + if (url) { + loadModel(url); + } + } catch (error) { + echo.error("Failed to update responce"); + console.error("Error fetching asset model:", error); + } - try { - isTempLoader.current = true; - const cachedModel = THREE.Cache.get(data.data.modelName); - let url; - if (cachedModel) { - // console.log(`Getting ${data.data.modelName} from cache`); - const model = cachedModel.scene.clone(); - model.uuid = data.data.modelUuid; - model.userData = { name: data.data.modelName, modelId: data.data.modelfileID, modelUuid: data.data.modelUuid }; - model.position.set(...data.data.position as [number, number, number]); - model.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z); - model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); + function loadModel(url: string) { + loader.load( + url, + (gltf) => { + URL.revokeObjectURL(url); + THREE.Cache.remove(url); + const model = gltf.scene; + model.uuid = data.data.modelUuid; + model.userData = { + name: data.data.modelName, + modelId: data.data.modelfileID, + modelUuid: data.data.modelUuid, + }; + model.position.set( + ...(data.data.position as [number, number, number]) + ); + model.rotation.set( + data.data.rotation.x, + data.data.rotation.y, + data.data.rotation.z + ); + model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); - model.traverse((child: any) => { - if (child.isMesh) { - // Clone the material to ensure changes are independent - // child.material = child.material.clone(); + model.traverse((child: any) => { + if (child.isMesh) { + // Clone the material to ensure changes are independent + // child.material = child.material.clone(); - child.castShadow = true; - child.receiveShadow = true; - } - }); - - itemsGroup.current.add(model); - - if (tempLoader.current) { - tempLoader.current.material.dispose(); - tempLoader.current.geometry.dispose(); - itemsGroup.current.remove(tempLoader.current); - tempLoader.current = undefined; - } - - const newFloorItem: Types.FloorItemType = { - modelUuid: data.data.modelUuid, - modelName: data.data.modelName, - modelfileID: data.data.modelfileID, - position: [...data.data.position as [number, number, number]], - rotation: { - x: model.rotation.x, - y: model.rotation.y, - z: model.rotation.z, - }, - isLocked: data.data.isLocked, - isVisible: data.data.isVisible, - }; - - setFloorItems((prevItems: any) => { - const updatedItems = [...(prevItems || []), newFloorItem]; - localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); - return updatedItems; - }); - - gsap.to(model.position, { y: data.data.position[1], duration: 1.5, ease: 'power2.out' }); - gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: 'power2.out', onComplete: () => { toast.success("Model Added!") } }); - - } else { - const indexedDBModel = await retrieveGLTF(data.data.modelName); - if (indexedDBModel) { - // console.log(`Getting ${data.data.modelName} from IndexedDB`); - url = URL.createObjectURL(indexedDBModel); - } else { - // console.log(`Getting ${data.data.modelName} from Backend`); - url = `${url_Backend_dwinzo}/api/v2/AssetFile/${data.data.modelfileID}`; - const modelBlob = await fetch(url).then((res) => res.blob()); - await storeGLTF(data.data.modelfileID, modelBlob); - } - } - - if (url) { - loadModel(url); - } - - } catch (error) { - console.error('Error fetching asset model:', error); + child.castShadow = true; + child.receiveShadow = true; } + }); - function loadModel(url: string) { - loader.load(url, (gltf) => { - URL.revokeObjectURL(url); - THREE.Cache.remove(url); - const model = gltf.scene; - model.uuid = data.data.modelUuid; - model.userData = { name: data.data.modelName, modelId: data.data.modelfileID, modelUuid: data.data.modelUuid }; - model.position.set(...data.data.position as [number, number, number]); - model.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z); - model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); + itemsGroup.current.add(model); - model.traverse((child: any) => { - if (child.isMesh) { - // Clone the material to ensure changes are independent - // child.material = child.material.clone(); + if (tempLoader.current) { + tempLoader.current.material.dispose(); + tempLoader.current.geometry.dispose(); + itemsGroup.current.remove(tempLoader.current); + tempLoader.current = undefined; + } - child.castShadow = true; - child.receiveShadow = true; - } - }); + const newFloorItem: Types.FloorItemType = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + modelfileID: data.data.modelfileID, + position: [...(data.data.position as [number, number, number])], + rotation: { + x: model.rotation.x, + y: model.rotation.y, + z: model.rotation.z, + }, + isLocked: data.data.isLocked, + isVisible: data.data.isVisible, + }; - itemsGroup.current.add(model); - - if (tempLoader.current) { - tempLoader.current.material.dispose(); - tempLoader.current.geometry.dispose(); - itemsGroup.current.remove(tempLoader.current); - tempLoader.current = undefined; - } - - const newFloorItem: Types.FloorItemType = { - modelUuid: data.data.modelUuid, - modelName: data.data.modelName, - modelfileID: data.data.modelfileID, - position: [...data.data.position as [number, number, number]], - rotation: { - x: model.rotation.x, - y: model.rotation.y, - z: model.rotation.z, - }, - isLocked: data.data.isLocked, - isVisible: data.data.isVisible, - }; - - setFloorItems((prevItems: any) => { - const updatedItems = [...(prevItems || []), newFloorItem]; - localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); - return updatedItems; - }); - - gsap.to(model.position, { y: data.data.position[1], duration: 1.5, ease: 'power2.out' }); - gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: 'power2.out', onComplete: () => { toast.success("Model Added!") } }); - - THREE.Cache.add(data.data.modelName, gltf); - }, () => { - TempLoader(new THREE.Vector3(...data.data.position), isTempLoader, tempLoader, itemsGroup); - }); - } - - } else if (data.message === "Model updated successfully") { - itemsGroup.current?.children.forEach((item: THREE.Group) => { - if (item.uuid === data.data.modelUuid) { - item.position.set(...data.data.position as [number, number, number]); - item.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z); - } - }) - - setFloorItems((prevItems: Types.FloorItems) => { - if (!prevItems) { - return - } - let updatedItem: any = null; - const updatedItems = prevItems.map((item) => { - if (item.modelUuid === data.data.modelUuid) { - updatedItem = { - ...item, - position: [...data.data.position] as [number, number, number], - rotation: { x: data.data.rotation.x, y: data.data.rotation.y, z: data.data.rotation.z, }, - }; - return updatedItem; - } - return item; - }); - return updatedItems; - }) - } - }) - - socket.on('model-asset:response:updates', (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "Model deleted successfully") { - const deletedUUID = data.data.modelUuid; - let items = JSON.parse(localStorage.getItem("FloorItems")!); - - const updatedItems = items.filter( - (item: { modelUuid: string }) => item.modelUuid !== deletedUUID + setFloorItems((prevItems: any) => { + const updatedItems = [...(prevItems || []), newFloorItem]; + localStorage.setItem( + "FloorItems", + JSON.stringify(updatedItems) ); + return updatedItems; + }); - const storedItems = JSON.parse(localStorage.getItem("FloorItems") || '[]'); - const updatedStoredItems = storedItems.filter((item: { modelUuid: string }) => item.modelUuid !== deletedUUID); - localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems)); + gsap.to(model.position, { + y: data.data.position[1], + duration: 1.5, + ease: "power2.out", + }); + gsap.to(model.scale, { + x: 1, + y: 1, + z: 1, + duration: 1.5, + ease: "power2.out", + onComplete: () => { + toast.success("Model Added!"); + }, + }); - itemsGroup.current.children.forEach((item: any) => { - if (item.uuid === deletedUUID) { - itemsGroup.current.remove(item); - } - }) - setFloorItems(updatedItems); - toast.success("Model Removed!"); + THREE.Cache.add(data.data.modelName, gltf); + }, + () => { + TempLoader( + new THREE.Vector3(...data.data.position), + isTempLoader, + tempLoader, + itemsGroup + ); } - }) + ); + } + } else if (data.message === "Model updated successfully") { + itemsGroup.current?.children.forEach((item: THREE.Group) => { + if (item.uuid === data.data.modelUuid) { + item.position.set( + ...(data.data.position as [number, number, number]) + ); + item.rotation.set( + data.data.rotation.x, + data.data.rotation.y, + data.data.rotation.z + ); + } + }); - socket.on('Line:response:update', (data: any) => { - if (socket.id === data.socketId) { - return + setFloorItems((prevItems: Types.FloorItems) => { + if (!prevItems) { + return; + } + let updatedItem: any = null; + const updatedItems = prevItems.map((item) => { + if (item.modelUuid === data.data.modelUuid) { + updatedItem = { + ...item, + position: [...data.data.position] as [number, number, number], + rotation: { + x: data.data.rotation.x, + y: data.data.rotation.y, + z: data.data.rotation.z, + }, + }; + return updatedItem; } - if (organization !== data.organization) { - return + return item; + }); + return updatedItems; + }); + } + }); + + socket.on("model-asset:response:updates", (data: any) => { + if (socket.id === data.socketId) { + return; + } + if (organization !== data.organization) { + return; + } + if (data.message === "Model deleted successfully") { + const deletedUUID = data.data.modelUuid; + let items = JSON.parse(localStorage.getItem("FloorItems")!); + + const updatedItems = items.filter( + (item: { modelUuid: string }) => item.modelUuid !== deletedUUID + ); + + const storedItems = JSON.parse( + localStorage.getItem("FloorItems") || "[]" + ); + const updatedStoredItems = storedItems.filter( + (item: { modelUuid: string }) => item.modelUuid !== deletedUUID + ); + localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems)); + + itemsGroup.current.children.forEach((item: any) => { + if (item.uuid === deletedUUID) { + itemsGroup.current.remove(item); + } + }); + setFloorItems(updatedItems); + toast.success("Model Removed!"); + } + }); + + socket.on("Line:response:update", (data: any) => { + if (socket.id === data.socketId) { + return; + } + if (organization !== data.organization) { + return; + } + if (data.message === "line updated") { + const DraggedUUID = data.data.uuid; + const DraggedPosition = new THREE.Vector3( + data.data.position.x, + data.data.position.y, + data.data.position.z + ); + + const point = floorPlanGroupPoint.current.getObjectByProperty( + "uuid", + DraggedUUID + ); + point.position.set( + DraggedPosition.x, + DraggedPosition.y, + DraggedPosition.z + ); + const affectedLines = updateLinesPositions( + { uuid: DraggedUUID, position: DraggedPosition }, + lines + ); + + updateLines(floorPlanGroupLine, affectedLines); + updateDistanceText(scene, floorPlanGroupLine, affectedLines); + updateFloorLines(onlyFloorlines, { + uuid: DraggedUUID, + position: DraggedPosition, + }); + + loadWalls(lines, setWalls); + setUpdateScene(true); + } + }); + + socket.on("Line:response:delete", (data: any) => { + if (socket.id === data.socketId) { + return; + } + if (organization !== data.organization) { + return; + } + if (data.message === "line deleted") { + const line = objectLineToArray(data.data); + const linePoints = line; + const connectedpoints = [linePoints[0][1], linePoints[1][1]]; + + onlyFloorlines.current = onlyFloorlines.current + .map((floorline: any) => + floorline.filter( + (line: any) => + line[0][1] !== connectedpoints[0] && + line[1][1] !== connectedpoints[1] + ) + ) + .filter((floorline: any) => floorline.length > 0); + + const removedLine = lines.current.find( + (item: any) => + (item[0][1] === linePoints[0][1] && + item[1][1] === linePoints[1][1]) || + (item[0][1] === linePoints[1][1] && item[1][1] === linePoints[0][1]) + ); + lines.current = lines.current.filter( + (item: any) => item !== removedLine + ); + + floorPlanGroupLine.current.children.forEach((line: any) => { + const linePoints = line.userData.linePoints as [ + number, + string, + number + ][]; + const uuid1 = linePoints[0][1]; + const uuid2 = linePoints[1][1]; + + if ( + (uuid1 === connectedpoints[0] && uuid2 === connectedpoints[1]) || + (uuid1 === connectedpoints[1] && uuid2 === connectedpoints[0]) + ) { + line.material.dispose(); + line.geometry.dispose(); + floorPlanGroupLine.current.remove(line); + setDeletedLines([line.userData.linePoints]); + } + }); + + connectedpoints.forEach((pointUUID) => { + let isConnected = false; + floorPlanGroupLine.current.children.forEach((line: any) => { + const linePoints = line.userData.linePoints; + const uuid1 = linePoints[0][1]; + const uuid2 = linePoints[1][1]; + if (uuid1 === pointUUID || uuid2 === pointUUID) { + isConnected = true; } - if (data.message === "line updated") { - const DraggedUUID = data.data.uuid; - const DraggedPosition = new THREE.Vector3(data.data.position.x, data.data.position.y, data.data.position.z); + }); - const point = floorPlanGroupPoint.current.getObjectByProperty('uuid', DraggedUUID); - point.position.set(DraggedPosition.x, DraggedPosition.y, DraggedPosition.z); - const affectedLines = updateLinesPositions({ uuid: DraggedUUID, position: DraggedPosition }, lines); - - updateLines(floorPlanGroupLine, affectedLines); - updateDistanceText(scene, floorPlanGroupLine, affectedLines); - updateFloorLines(onlyFloorlines, { uuid: DraggedUUID, position: DraggedPosition }); - - loadWalls(lines, setWalls); - setUpdateScene(true); - - } - }) - - socket.on('Line:response:delete', (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "line deleted") { - const line = objectLineToArray(data.data); - const linePoints = line; - const connectedpoints = [linePoints[0][1], linePoints[1][1]]; - - - onlyFloorlines.current = onlyFloorlines.current.map((floorline: any) => - floorline.filter((line: any) => line[0][1] !== connectedpoints[0] && line[1][1] !== connectedpoints[1]) - ).filter((floorline: any) => floorline.length > 0); - - const removedLine = lines.current.find((item: any) => (item[0][1] === linePoints[0][1] && item[1][1] === linePoints[1][1] || (item[0][1] === linePoints[1][1] && item[1][1] === linePoints[0][1]))); - lines.current = lines.current.filter((item: any) => item !== removedLine); - - floorPlanGroupLine.current.children.forEach((line: any) => { - const linePoints = line.userData.linePoints as [number, string, number][]; - const uuid1 = linePoints[0][1]; - const uuid2 = linePoints[1][1]; - - if ((uuid1 === connectedpoints[0] && uuid2 === connectedpoints[1] || (uuid1 === connectedpoints[1] && uuid2 === connectedpoints[0]))) { - line.material.dispose(); - line.geometry.dispose(); - floorPlanGroupLine.current.remove(line); - setDeletedLines([line.userData.linePoints]) - } - }); - - connectedpoints.forEach((pointUUID) => { - let isConnected = false; - floorPlanGroupLine.current.children.forEach((line: any) => { - const linePoints = line.userData.linePoints; - const uuid1 = linePoints[0][1]; - const uuid2 = linePoints[1][1]; - if (uuid1 === pointUUID || uuid2 === pointUUID) { - isConnected = true; - } - }); - - if (!isConnected) { - floorPlanGroupPoint.current.children.forEach((point: any) => { - if (point.uuid === pointUUID) { - point.material.dispose(); - point.geometry.dispose(); - floorPlanGroupPoint.current.remove(point); - } - }); - } - }); - - loadWalls(lines, setWalls); - setUpdateScene(true); - - toast.success("Line Removed!"); - } - }) - - socket.on('Line:response:delete:point', (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "point deleted") { - const point = floorPlanGroupPoint.current?.getObjectByProperty('uuid', data.data); + if (!isConnected) { + floorPlanGroupPoint.current.children.forEach((point: any) => { + if (point.uuid === pointUUID) { point.material.dispose(); point.geometry.dispose(); floorPlanGroupPoint.current.remove(point); + } + }); + } + }); - onlyFloorlines.current = onlyFloorlines.current.map((floorline: any) => - floorline.filter((line: any) => line[0][1] !== data.data && line[1][1] !== data.data) - ).filter((floorline: any) => floorline.length > 0); + loadWalls(lines, setWalls); + setUpdateScene(true); - RemoveConnectedLines(data.data, floorPlanGroupLine, floorPlanGroupPoint, setDeletedLines, lines); + toast.success("Line Removed!"); + } + }); - loadWalls(lines, setWalls); - setUpdateScene(true); + socket.on("Line:response:delete:point", (data: any) => { + if (socket.id === data.socketId) { + return; + } + if (organization !== data.organization) { + return; + } + if (data.message === "point deleted") { + const point = floorPlanGroupPoint.current?.getObjectByProperty( + "uuid", + data.data + ); + point.material.dispose(); + point.geometry.dispose(); + floorPlanGroupPoint.current.remove(point); - toast.success("Point Removed!"); - } - }) + onlyFloorlines.current = onlyFloorlines.current + .map((floorline: any) => + floorline.filter( + (line: any) => + line[0][1] !== data.data && line[1][1] !== data.data + ) + ) + .filter((floorline: any) => floorline.length > 0); - socket.on('Line:response:delete:layer', async (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "layer deleted") { - setActiveLayer(1) - const removedLayer = data.data; - const removedLines: Types.Lines = lines.current.filter((line: any) => line[0][2] === removedLayer); + RemoveConnectedLines( + data.data, + floorPlanGroupLine, + floorPlanGroupPoint, + setDeletedLines, + lines + ); - ////////// Remove Points and lines from the removed layer ////////// + loadWalls(lines, setWalls); + setUpdateScene(true); - removedLines.forEach(async (line) => { - line.forEach(async (removedPoint) => { - const removableLines: THREE.Mesh[] = []; - const connectedpoints: string[] = []; + toast.success("Point Removed!"); + } + }); - floorPlanGroupLine.current.children.forEach((line: any) => { - const linePoints = line.userData.linePoints as [number, string, number][]; - const uuid1 = linePoints[0][1]; - const uuid2 = linePoints[1][1]; + socket.on("Line:response:delete:layer", async (data: any) => { + if (socket.id === data.socketId) { + return; + } + if (organization !== data.organization) { + return; + } + if (data.message === "layer deleted") { + setActiveLayer(1); + const removedLayer = data.data; + const removedLines: Types.Lines = lines.current.filter( + (line: any) => line[0][2] === removedLayer + ); - if (uuid1 === removedPoint[1] || uuid2 === removedPoint[1]) { - connectedpoints.push(uuid1 === removedPoint[1] ? uuid2 : uuid1); - removableLines.push(line as THREE.Mesh); - } - }); + ////////// Remove Points and lines from the removed layer ////////// - if (removableLines.length > 0) { - removableLines.forEach((line: any) => { - lines.current = lines.current.filter((item: any) => JSON.stringify(item) !== JSON.stringify(line.userData.linePoints)); - line.material.dispose(); - line.geometry.dispose(); - floorPlanGroupLine.current.remove(line); - }); - } + removedLines.forEach(async (line) => { + line.forEach(async (removedPoint) => { + const removableLines: THREE.Mesh[] = []; + const connectedpoints: string[] = []; - const point = floorPlanGroupPoint.current.getObjectByProperty('uuid', removedPoint[1]); - if (point) { - point.material.dispose(); - point.geometry.dispose(); - floorPlanGroupPoint.current.remove(point) - } - }); - }); + floorPlanGroupLine.current.children.forEach((line: any) => { + const linePoints = line.userData.linePoints as [ + number, + string, + number + ][]; + const uuid1 = linePoints[0][1]; + const uuid2 = linePoints[1][1]; - ////////// Update the remaining lines layer values in the userData and in lines.current ////////// + if (uuid1 === removedPoint[1] || uuid2 === removedPoint[1]) { + connectedpoints.push(uuid1 === removedPoint[1] ? uuid2 : uuid1); + removableLines.push(line as THREE.Mesh); + } + }); - let remaining = lines.current.filter((line: any) => line[0][2] !== removedLayer); - let updatedLines: Types.Lines = []; - remaining.forEach((line: any) => { - let newLines = JSON.parse(JSON.stringify(line)); - if (newLines[0][2] > removedLayer) { - newLines[0][2] -= 1; - newLines[1][2] -= 1; - } - - const matchingLine = floorPlanGroupLine.current.children.find((l: any) => l.userData.linePoints[0][1] === line[0][1] && l.userData.linePoints[1][1] === line[1][1]); - if (matchingLine) { - const updatedUserData = JSON.parse(JSON.stringify(matchingLine.userData)); - updatedUserData.linePoints[0][2] = newLines[0][2]; - updatedUserData.linePoints[1][2] = newLines[1][2]; - matchingLine.userData = updatedUserData; - } - updatedLines.push(newLines); - }); - - lines.current = updatedLines; - localStorage.setItem("Lines", JSON.stringify(lines.current)); - - ////////// Also remove OnlyFloorLines and update it in localstorage ////////// - - onlyFloorlines.current = onlyFloorlines.current.filter((floor: any) => { - return floor[0][0][2] !== removedLayer; - }); - const meshToRemove = floorGroup.current?.children.find((mesh: any) => - mesh.name === `Only_Floor_Line_${removedLayer}` + if (removableLines.length > 0) { + removableLines.forEach((line: any) => { + lines.current = lines.current.filter( + (item: any) => + JSON.stringify(item) !== + JSON.stringify(line.userData.linePoints) ); - if (meshToRemove) { - meshToRemove.geometry.dispose(); - meshToRemove.material.dispose(); - floorGroup.current?.remove(meshToRemove); - } - - const zonesData = await getZonesApi(organization); - const highestLayer = Math.max( - 1, - lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0), - zonesData.data.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0) - ); - - setLayers(highestLayer); - - loadWalls(lines, setWalls); - setUpdateScene(true); - - toast.success("Layer Removed!"); - } - }) - }, [socket]) - - useEffect(() => { - if (!socket) return - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - socket.on('wallItemsDeleteResponse', (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "wallitem deleted") { - const deletedUUID = data.data.modelUuid; - let WallItemsRef = wallItems; - const Items = WallItemsRef.filter((item: any) => item.model?.uuid !== deletedUUID); - - setWallItems([]); - setTimeout(async () => { - WallItemsRef = Items; - setWallItems(WallItemsRef); - const WallItemsForStorage = WallItemsRef.map((item: any) => { - const { model, ...rest } = item; - return { - ...rest, - modelUuid: model?.uuid, - }; - }); - - localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage)); - toast.success("Model Removed!"); - }, 50); - } - }) - - socket.on('wallItemsUpdateResponse', (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "wallIitem created") { - const loader = new GLTFLoader(); - loader.load(AssetConfigurations[data.data.modelName].modelUrl, async (gltf) => { - const model = gltf.scene; - model.uuid = data.data.modelUuid; - model.children[0].children.forEach((child) => { - if (child.name !== "CSG_REF") { - child.castShadow = true; - child.receiveShadow = true; - } - }); - - const newWallItem = { - type: data.data.type, - model: model, - modelName: data.data.modelName, - scale: data.data.scale, - csgscale: data.data.csgscale, - csgposition: data.data.csgposition, - position: data.data.position, - quaternion: data.data.quaternion - }; - - setWallItems((prevItems: any) => { - const updatedItems = [...prevItems, newWallItem]; - - const WallItemsForStorage = updatedItems.map(item => { - const { model, ...rest } = item; - return { - ...rest, - modelUuid: model?.uuid, - }; - }); - - localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage)); - toast.success("Model Added!"); - - return updatedItems; - }); - }); - } else if (data.message === "wallIitem updated") { - const updatedUUID = data.data.modelUuid; - - setWallItems((prevItems: any) => { - const updatedItems = prevItems.map((item: any) => { - if (item.model.uuid === updatedUUID) { - return { - ...item, - position: data.data.position, - quaternion: data.data.quaternion, - scale: data.data.scale, - csgscale: data.data.csgscale, - csgposition: data.data.csgposition, - }; - } - return item; - }); - - const WallItemsForStorage = updatedItems.map((item: any) => { - const { model, ...rest } = item; - return { - ...rest, - modelUuid: model?.uuid, - }; - }); - - localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage)); - toast.success("Model Updated!"); - - return updatedItems; - }); - + line.material.dispose(); + line.geometry.dispose(); + floorPlanGroupLine.current.remove(line); + }); } - }) + const point = floorPlanGroupPoint.current.getObjectByProperty( + "uuid", + removedPoint[1] + ); + if (point) { + point.material.dispose(); + point.geometry.dispose(); + floorPlanGroupPoint.current.remove(point); + } + }); + }); - return () => { - socket.off('wallItemsDeleteResponse'); - socket.off('wallItemsUpdateResponse'); - }; - }, [wallItems]) + ////////// Update the remaining lines layer values in the userData and in lines.current ////////// - function getPointColor(lineType: string | undefined): string { - switch (lineType) { - case CONSTANTS.lineConfig.wallName: return CONSTANTS.pointConfig.wallOuterColor; - case CONSTANTS.lineConfig.floorName: return CONSTANTS.pointConfig.floorOuterColor; - case CONSTANTS.lineConfig.aisleName: return CONSTANTS.pointConfig.aisleOuterColor; - default: return CONSTANTS.pointConfig.defaultOuterColor; + let remaining = lines.current.filter( + (line: any) => line[0][2] !== removedLayer + ); + let updatedLines: Types.Lines = []; + remaining.forEach((line: any) => { + let newLines = JSON.parse(JSON.stringify(line)); + if (newLines[0][2] > removedLayer) { + newLines[0][2] -= 1; + newLines[1][2] -= 1; + } + + const matchingLine = floorPlanGroupLine.current.children.find( + (l: any) => + l.userData.linePoints[0][1] === line[0][1] && + l.userData.linePoints[1][1] === line[1][1] + ); + if (matchingLine) { + const updatedUserData = JSON.parse( + JSON.stringify(matchingLine.userData) + ); + updatedUserData.linePoints[0][2] = newLines[0][2]; + updatedUserData.linePoints[1][2] = newLines[1][2]; + matchingLine.userData = updatedUserData; + } + updatedLines.push(newLines); + }); + + lines.current = updatedLines; + localStorage.setItem("Lines", JSON.stringify(lines.current)); + + ////////// Also remove OnlyFloorLines and update it in localstorage ////////// + + onlyFloorlines.current = onlyFloorlines.current.filter((floor: any) => { + return floor[0][0][2] !== removedLayer; + }); + const meshToRemove = floorGroup.current?.children.find( + (mesh: any) => mesh.name === `Only_Floor_Line_${removedLayer}` + ); + if (meshToRemove) { + meshToRemove.geometry.dispose(); + meshToRemove.material.dispose(); + floorGroup.current?.remove(meshToRemove); } - } - function getLineColor(lineType: string | undefined): string { - switch (lineType) { - case CONSTANTS.lineConfig.wallName: return CONSTANTS.lineConfig.wallColor; - case CONSTANTS.lineConfig.floorName: return CONSTANTS.lineConfig.floorColor; - case CONSTANTS.lineConfig.aisleName: return CONSTANTS.lineConfig.aisleColor; - default: return CONSTANTS.lineConfig.defaultColor; - } - } + const zonesData = await getZonesApi(organization); + const highestLayer = Math.max( + 1, + lines.current.reduce( + (maxLayer: number, segment: any) => + Math.max(maxLayer, segment.layer || 0), + 0 + ), + zonesData.data.reduce( + (maxLayer: number, zone: any) => + Math.max(maxLayer, zone.layer || 0), + 0 + ) + ); - useEffect(() => { - if (!socket) return - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; + setLayers(highestLayer); - socket.on('Line:response:create', async (data: any) => { - if (socket.id === data.socketId) { - return + loadWalls(lines, setWalls); + setUpdateScene(true); + + toast.success("Layer Removed!"); + } + }); + }, [socket]); + + useEffect(() => { + if (!socket) return; + const email = localStorage.getItem("email"); + const organization = email!.split("@")[1].split(".")[0]; + + socket.on("wallItemsDeleteResponse", (data: any) => { + if (socket.id === data.socketId) { + return; + } + if (organization !== data.organization) { + return; + } + if (data.message === "wallitem deleted") { + const deletedUUID = data.data.modelUuid; + let WallItemsRef = wallItems; + const Items = WallItemsRef.filter( + (item: any) => item.model?.uuid !== deletedUUID + ); + + setWallItems([]); + setTimeout(async () => { + WallItemsRef = Items; + setWallItems(WallItemsRef); + const WallItemsForStorage = WallItemsRef.map((item: any) => { + const { model, ...rest } = item; + return { + ...rest, + modelUuid: model?.uuid, + }; + }); + + localStorage.setItem( + "WallItems", + JSON.stringify(WallItemsForStorage) + ); + toast.success("Model Removed!"); + }, 50); + } + }); + + socket.on("wallItemsUpdateResponse", (data: any) => { + if (socket.id === data.socketId) { + return; + } + if (organization !== data.organization) { + return; + } + if (data.message === "wallIitem created") { + const loader = new GLTFLoader(); + loader.load( + AssetConfigurations[data.data.modelName].modelUrl, + async (gltf) => { + const model = gltf.scene; + model.uuid = data.data.modelUuid; + model.children[0].children.forEach((child) => { + if (child.name !== "CSG_REF") { + child.castShadow = true; + child.receiveShadow = true; + } + }); + + const newWallItem = { + type: data.data.type, + model: model, + modelName: data.data.modelName, + scale: data.data.scale, + csgscale: data.data.csgscale, + csgposition: data.data.csgposition, + position: data.data.position, + quaternion: data.data.quaternion, + }; + + setWallItems((prevItems: any) => { + const updatedItems = [...prevItems, newWallItem]; + + const WallItemsForStorage = updatedItems.map((item) => { + const { model, ...rest } = item; + return { + ...rest, + modelUuid: model?.uuid, + }; + }); + + localStorage.setItem( + "WallItems", + JSON.stringify(WallItemsForStorage) + ); + toast.success("Model Added!"); + + return updatedItems; + }); + } + ); + } else if (data.message === "wallIitem updated") { + const updatedUUID = data.data.modelUuid; + + setWallItems((prevItems: any) => { + const updatedItems = prevItems.map((item: any) => { + if (item.model.uuid === updatedUUID) { + return { + ...item, + position: data.data.position, + quaternion: data.data.quaternion, + scale: data.data.scale, + csgscale: data.data.csgscale, + csgposition: data.data.csgposition, + }; } - if (organization !== data.organization) { - return - } - if (data.message === "line create") { - const line: Types.Line = objectLineToArray(data.data); - const type = line[0][3]; - const pointColour = getPointColor(type); - const lineColour = getLineColor(type); - setNewLines([line]) + return item; + }); - line.forEach((line) => { - const existingPoint = floorPlanGroupPoint.current?.getObjectByProperty('uuid', line[1]); - if (existingPoint) { - return; - } - const geometry = new THREE.BoxGeometry(...CONSTANTS.pointConfig.boxScale); - const material = new THREE.ShaderMaterial({ - uniforms: { - uColor: { value: new THREE.Color(pointColour) }, // Blue color for the border - uInnerColor: { value: new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor) }, // White color for the inner square - }, - vertexShader: ` + const WallItemsForStorage = updatedItems.map((item: any) => { + const { model, ...rest } = item; + return { + ...rest, + modelUuid: model?.uuid, + }; + }); + + localStorage.setItem( + "WallItems", + JSON.stringify(WallItemsForStorage) + ); + toast.success("Model Updated!"); + + return updatedItems; + }); + } + }); + + return () => { + socket.off("wallItemsDeleteResponse"); + socket.off("wallItemsUpdateResponse"); + }; + }, [wallItems]); + + function getPointColor(lineType: string | undefined): string { + switch (lineType) { + case CONSTANTS.lineConfig.wallName: + return CONSTANTS.pointConfig.wallOuterColor; + case CONSTANTS.lineConfig.floorName: + return CONSTANTS.pointConfig.floorOuterColor; + case CONSTANTS.lineConfig.aisleName: + return CONSTANTS.pointConfig.aisleOuterColor; + default: + return CONSTANTS.pointConfig.defaultOuterColor; + } + } + + function getLineColor(lineType: string | undefined): string { + switch (lineType) { + case CONSTANTS.lineConfig.wallName: + return CONSTANTS.lineConfig.wallColor; + case CONSTANTS.lineConfig.floorName: + return CONSTANTS.lineConfig.floorColor; + case CONSTANTS.lineConfig.aisleName: + return CONSTANTS.lineConfig.aisleColor; + default: + return CONSTANTS.lineConfig.defaultColor; + } + } + + useEffect(() => { + if (!socket) return; + const email = localStorage.getItem("email"); + const organization = email!.split("@")[1].split(".")[0]; + + socket.on("Line:response:create", async (data: any) => { + if (socket.id === data.socketId) { + return; + } + if (organization !== data.organization) { + return; + } + if (data.message === "line create") { + const line: Types.Line = objectLineToArray(data.data); + const type = line[0][3]; + const pointColour = getPointColor(type); + const lineColour = getLineColor(type); + setNewLines([line]); + + line.forEach((line) => { + const existingPoint = + floorPlanGroupPoint.current?.getObjectByProperty("uuid", line[1]); + if (existingPoint) { + return; + } + const geometry = new THREE.BoxGeometry( + ...CONSTANTS.pointConfig.boxScale + ); + const material = new THREE.ShaderMaterial({ + uniforms: { + uColor: { value: new THREE.Color(pointColour) }, // Blue color for the border + uInnerColor: { + value: new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor), + }, // White color for the inner square + }, + vertexShader: ` varying vec2 vUv; void main() { @@ -686,7 +870,7 @@ export default function SocketResponses({ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `, - fragmentShader: ` + fragmentShader: ` varying vec2 vUv; uniform vec3 uColor; uniform vec3 uInnerColor; @@ -702,126 +886,162 @@ export default function SocketResponses({ } } `, - }); - const point = new THREE.Mesh(geometry, material); - point.name = "point"; - point.uuid = line[1]; - point.userData = { type: type, color: pointColour }; - point.position.set(line[0].x, line[0].y, line[0].z); - currentLayerPoint.current.push(point); + }); + const point = new THREE.Mesh(geometry, material); + point.name = "point"; + point.uuid = line[1]; + point.userData = { type: type, color: pointColour }; + point.position.set(line[0].x, line[0].y, line[0].z); + currentLayerPoint.current.push(point); - floorPlanGroupPoint.current?.add(point); - }) - if (dragPointControls.current) { - dragPointControls.current!.objects = currentLayerPoint.current; - } - addLineToScene( - new THREE.Vector3(line[0][0].x, line[0][0].y, line[0][0].z), - new THREE.Vector3(line[1][0].x, line[1][0].y, line[1][0].z), - lineColour, - line, - floorPlanGroupLine - ) - lines.current.push(line); + floorPlanGroupPoint.current?.add(point); + }); + if (dragPointControls.current) { + dragPointControls.current!.objects = currentLayerPoint.current; + } + addLineToScene( + new THREE.Vector3(line[0][0].x, line[0][0].y, line[0][0].z), + new THREE.Vector3(line[1][0].x, line[1][0].y, line[1][0].z), + lineColour, + line, + floorPlanGroupLine + ); + lines.current.push(line); - const zonesData = await getZonesApi(organization); - const highestLayer = Math.max( - 1, - lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0), - zonesData.data.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0) - ); + const zonesData = await getZonesApi(organization); + const highestLayer = Math.max( + 1, + lines.current.reduce( + (maxLayer: number, segment: any) => + Math.max(maxLayer, segment.layer || 0), + 0 + ), + zonesData.data.reduce( + (maxLayer: number, zone: any) => + Math.max(maxLayer, zone.layer || 0), + 0 + ) + ); - setLayers(highestLayer); + setLayers(highestLayer); - Layer2DVisibility(activeLayer, floorPlanGroup, floorPlanGroupLine, floorPlanGroupPoint, currentLayerPoint, dragPointControls) + Layer2DVisibility( + activeLayer, + floorPlanGroup, + floorPlanGroupLine, + floorPlanGroupPoint, + currentLayerPoint, + dragPointControls + ); - loadWalls(lines, setWalls); - setUpdateScene(true); - } - }) + loadWalls(lines, setWalls); + setUpdateScene(true); + } + }); - return () => { - socket.off('Line:response:create'); - }; - }, [socket, activeLayer]) + return () => { + socket.off("Line:response:create"); + }; + }, [socket, activeLayer]); - useEffect(() => { - if (!socket) return - const email = localStorage.getItem('email'); - const organization = (email!.split("@")[1]).split(".")[0]; + useEffect(() => { + if (!socket) return; + const email = localStorage.getItem("email"); + const organization = email!.split("@")[1].split(".")[0]; - socket.on('zone:response:updates', (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } + socket.on("zone:response:updates", (data: any) => { + if (socket.id === data.socketId) { + return; + } + if (organization !== data.organization) { + return; + } - if (data.message === "zone created") { - const pointsArray: [number, number, number][] = data.data.points; - const vector3Array = pointsArray.map(([x, y, z]) => new THREE.Vector3(x, y, z)); - const newZones = [...zones, data.data]; - setZones(newZones); - const updatedZonePoints = [...zonePoints, ...vector3Array]; - setZonePoints(updatedZonePoints); + if (data.message === "zone created") { + const pointsArray: [number, number, number][] = data.data.points; + const vector3Array = pointsArray.map( + ([x, y, z]) => new THREE.Vector3(x, y, z) + ); + const newZones = [...zones, data.data]; + setZones(newZones); + const updatedZonePoints = [...zonePoints, ...vector3Array]; + setZonePoints(updatedZonePoints); - const highestLayer = Math.max( - 1, - lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0), - newZones.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0) - ); + const highestLayer = Math.max( + 1, + lines.current.reduce( + (maxLayer: number, segment: any) => + Math.max(maxLayer, segment.layer || 0), + 0 + ), + newZones.reduce( + (maxLayer: number, zone: any) => + Math.max(maxLayer, zone.layer || 0), + 0 + ) + ); - setLayers(highestLayer); - setUpdateScene(true); - } + setLayers(highestLayer); + setUpdateScene(true); + } - if (data.message === "zone updated") { - const updatedZones = zones.map((zone: any) => - zone.zoneId === data.data.zoneId ? data.data : zone - ); - setZones(updatedZones); - setUpdateScene(true); - } + if (data.message === "zone updated") { + const updatedZones = zones.map((zone: any) => + zone.zoneId === data.data.zoneId ? data.data : zone + ); + setZones(updatedZones); + setUpdateScene(true); + } + }); + socket.on("zone:response:delete", (data: any) => { + if (socket.id === data.socketId) { + return; + } + if (organization !== data.organization) { + return; + } + if (data.message === "zone deleted") { + const updatedZones = zones.filter( + (zone: any) => zone.zoneId !== data.data.zoneId + ); + setZones(updatedZones); - }) + const zoneIndex = zones.findIndex( + (zone: any) => zone.zoneId === data.data.zoneId + ); + if (zoneIndex !== -1) { + const updatedzonePoints = zonePoints.filter( + (_: any, index: any) => + index < zoneIndex * 4 || index >= zoneIndex * 4 + 4 + ); + setZonePoints(updatedzonePoints); + } - socket.on('zone:response:delete', (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "zone deleted") { - const updatedZones = zones.filter((zone: any) => zone.zoneId !== data.data.zoneId); - setZones(updatedZones); + const highestLayer = Math.max( + 1, + lines.current.reduce( + (maxLayer: number, segment: any) => + Math.max(maxLayer, segment.layer || 0), + 0 + ), + updatedZones.reduce( + (maxLayer: number, zone: any) => + Math.max(maxLayer, zone.layer || 0), + 0 + ) + ); - const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === data.data.zoneId); - if (zoneIndex !== -1) { - const updatedzonePoints = zonePoints.filter((_: any, index: any) => index < zoneIndex * 4 || index >= zoneIndex * 4 + 4); - setZonePoints(updatedzonePoints); - } + setLayers(highestLayer); + setUpdateScene(true); + } + }); - const highestLayer = Math.max( - 1, - lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0), - updatedZones.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0) - ); + return () => { + socket.off("zone:response:updates"); + socket.off("zone:response:delete"); + }; + }, [socket, zones, zonePoints]); - setLayers(highestLayer); - setUpdateScene(true); - } - }) - - return () => { - socket.off('zone:response:updates'); - socket.off('zone:response:delete'); - }; - }, [socket, zones, zonePoints]) - - return ( - <> - ) -} \ No newline at end of file + return <>; +} diff --git a/app/src/modules/market/MarketPlace.tsx b/app/src/modules/market/MarketPlace.tsx index 4b76951..3b4b87c 100644 --- a/app/src/modules/market/MarketPlace.tsx +++ b/app/src/modules/market/MarketPlace.tsx @@ -23,6 +23,10 @@ const MarketPlace = () => { const [filteredModels, setFilteredModels] = useState([]); const [isLoading, setisLoading] = useState(false); // Loading state + useEffect(() => { + echo.log("opended market place"); + }, []); + useEffect(() => { const filteredAssets = async () => { setisLoading(true); @@ -32,6 +36,7 @@ const MarketPlace = () => { setFilteredModels(filt.items); setisLoading(false); } catch { + echo.error("Failed to filter asset"); setisLoading(false); } }; @@ -42,18 +47,16 @@ const MarketPlace = () => {
+ {isLoading ? ( // Show loading spinner while fetching ) : ( - <> - - - - )}{" "} + + )}
diff --git a/app/src/modules/scene/camera/switchView.tsx b/app/src/modules/scene/camera/switchView.tsx index 2472031..0fa8921 100644 --- a/app/src/modules/scene/camera/switchView.tsx +++ b/app/src/modules/scene/camera/switchView.tsx @@ -52,6 +52,7 @@ export default function SwitchView() { } }); } catch (error) { + echo.error("Failed to retrieve camera position or target"); console.error("Failed to retrieve camera position or target:", error); state.controls?.setPosition(...CONSTANTS.threeDimension.defaultPosition); state.controls?.setTarget(...CONSTANTS.threeDimension.defaultTarget); diff --git a/app/src/modules/scene/scene.tsx b/app/src/modules/scene/scene.tsx index 0f2c489..0e81cf6 100644 --- a/app/src/modules/scene/scene.tsx +++ b/app/src/modules/scene/scene.tsx @@ -20,24 +20,24 @@ export default function Scene() { ); return ( - - { - e.preventDefault(); - }} - > - + + { + e.preventDefault(); + }} + > + - + - + - + - - - + + + ); } diff --git a/app/src/modules/simulation/actions/conveyor/actionHandler/useDefaultHandler.ts b/app/src/modules/simulation/actions/conveyor/actionHandler/useDefaultHandler.ts index e69de29..ab0a284 100644 --- a/app/src/modules/simulation/actions/conveyor/actionHandler/useDefaultHandler.ts +++ b/app/src/modules/simulation/actions/conveyor/actionHandler/useDefaultHandler.ts @@ -0,0 +1,24 @@ +import { useCallback } from "react"; +import { useMaterialStore } from "../../../../../store/simulation/useMaterialStore"; + +export function useDefaultHandler() { + const { getMaterialById } = useMaterialStore(); + + const defaultLogStatus = (materialUuid: string, status: string) => { + // console.log(`${materialUuid}, ${status}`); + } + + const handleDefault = useCallback((action: ConveyorAction, materialId?: string) => { + if (!action || action.actionType !== 'default' || !materialId) return; + + const material = getMaterialById(materialId); + if (!material) return; + + defaultLogStatus(material.materialId, `performed Default action`); + + }, [getMaterialById]); + + return { + handleDefault, + }; +} \ No newline at end of file diff --git a/app/src/modules/simulation/actions/conveyor/actionHandler/useDespawnHandler.ts b/app/src/modules/simulation/actions/conveyor/actionHandler/useDespawnHandler.ts index 464629c..d72419a 100644 --- a/app/src/modules/simulation/actions/conveyor/actionHandler/useDespawnHandler.ts +++ b/app/src/modules/simulation/actions/conveyor/actionHandler/useDespawnHandler.ts @@ -2,7 +2,7 @@ import { useCallback } from "react"; import { useMaterialStore } from "../../../../../store/simulation/useMaterialStore"; export function useDespawnHandler() { - const { addMaterial, getMaterialById, removeMaterial } = useMaterialStore(); + const { getMaterialById, removeMaterial } = useMaterialStore(); const deSpawnLogStatus = (materialUuid: string, status: string) => { // console.log(`${materialUuid}, ${status}`); @@ -18,7 +18,7 @@ export function useDespawnHandler() { deSpawnLogStatus(material.materialId, `Despawned`); - }, [addMaterial, getMaterialById, removeMaterial]); + }, [getMaterialById, removeMaterial]); return { handleDespawn, diff --git a/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts b/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts index 43e3dc1..1772444 100644 --- a/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts +++ b/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts @@ -1,17 +1,20 @@ import { useEffect, useCallback } from "react"; +import { useDefaultHandler } from "./actionHandler/useDefaultHandler"; import { useSpawnHandler } from "./actionHandler/useSpawnHandler"; import { useSwapHandler } from "./actionHandler/useSwapHandler"; import { useDelayHandler } from "./actionHandler/useDelayHandler"; import { useDespawnHandler } from "./actionHandler/useDespawnHandler"; export function useConveyorActions() { + const { handleDefault } = useDefaultHandler(); const { handleSpawn, clearCurrentSpawn } = useSpawnHandler(); const { handleSwap } = useSwapHandler(); const { handleDespawn } = useDespawnHandler(); const { handleDelay, cleanupDelay } = useDelayHandler(); - const handleDefaultAction = useCallback((action: ConveyorAction) => { - }, []); + const handleDefaultAction = useCallback((action: ConveyorAction, materialId?: string) => { + handleDefault(action, materialId); + }, [handleDefault]); const handleSpawnAction = useCallback((action: ConveyorAction) => { handleSpawn(action); diff --git a/app/src/modules/simulation/actions/roboticArm/actionHandler/usePickAndPlaceHandler.ts b/app/src/modules/simulation/actions/roboticArm/actionHandler/usePickAndPlaceHandler.ts new file mode 100644 index 0000000..2f44cfe --- /dev/null +++ b/app/src/modules/simulation/actions/roboticArm/actionHandler/usePickAndPlaceHandler.ts @@ -0,0 +1,41 @@ +import { useCallback } from "react"; +import { useMaterialStore } from "../../../../../store/simulation/useMaterialStore"; +import { useArmBotStore } from "../../../../../store/simulation/useArmBotStore"; +import { useProductStore } from "../../../../../store/simulation/useProductStore"; +import { useSelectedProduct } from "../../../../../store/simulation/useSimulationStore"; + +export function usePickAndPlaceHandler() { + const { getMaterialById } = useMaterialStore(); + const { addCurrentAction } = useArmBotStore(); + const { getModelUuidByActionUuid } = useProductStore(); + const { selectedProduct } = useSelectedProduct(); + + const pickAndPlaceLogStatus = (materialUuid: string, status: string) => { + // console.log(`${materialUuid}, ${status}`); + } + + const handlePickAndPlace = useCallback((action: RoboticArmAction, materialId?: string) => { + if (!action || action.actionType !== 'pickAndPlace' || !materialId) return; + + const material = getMaterialById(materialId); + if (!material) return; + + const modelUuid = getModelUuidByActionUuid(selectedProduct.productId, action.actionUuid); + + if (!modelUuid) return; + + addCurrentAction( + modelUuid, + action.actionUuid, + material.materialType, + material.materialId + ); + + pickAndPlaceLogStatus(material.materialId, `if going to be picked by armBot ${modelUuid}`); + + }, [getMaterialById, getModelUuidByActionUuid, addCurrentAction]); + + return { + handlePickAndPlace, + }; +} \ No newline at end of file diff --git a/app/src/modules/simulation/actions/roboticArm/useRoboticArmActions.ts b/app/src/modules/simulation/actions/roboticArm/useRoboticArmActions.ts index 37990db..90251d2 100644 --- a/app/src/modules/simulation/actions/roboticArm/useRoboticArmActions.ts +++ b/app/src/modules/simulation/actions/roboticArm/useRoboticArmActions.ts @@ -1,20 +1,24 @@ import { useEffect, useCallback } from 'react'; +import { usePickAndPlaceHandler } from './actionHandler/usePickAndPlaceHandler'; export function useRoboticArmActions() { + const { handlePickAndPlace } = usePickAndPlaceHandler(); - const handlePickAndPlace = useCallback((action: RoboticArmAction) => { - console.log(`Robotic arm pick and place`); - }, []); + const handlePickAndPlaceAction = useCallback((action: RoboticArmAction, materialId: string) => { + handlePickAndPlace(action, materialId); + }, [handlePickAndPlace]); + + const handleRoboticArmAction = useCallback((action: RoboticArmAction, materialId: string) => { + if (!action) return; - const handleRoboticArmAction = useCallback((action: RoboticArmAction) => { switch (action.actionType) { case 'pickAndPlace': - handlePickAndPlace(action); + handlePickAndPlaceAction(action, materialId); break; default: console.warn(`Unknown robotic arm action type: ${action.actionType}`); } - }, [handlePickAndPlace]); + }, [handlePickAndPlaceAction]); const cleanup = useCallback(() => { }, []); diff --git a/app/src/modules/simulation/actions/useActionHandler.ts b/app/src/modules/simulation/actions/useActionHandler.ts index 91a3c84..4041ab5 100644 --- a/app/src/modules/simulation/actions/useActionHandler.ts +++ b/app/src/modules/simulation/actions/useActionHandler.ts @@ -1,4 +1,7 @@ -import { usePlayButtonStore, useResetButtonStore } from "../../../store/usePlayButtonStore"; +import { + usePlayButtonStore, + useResetButtonStore, +} from "../../../store/usePlayButtonStore"; import { useConveyorActions } from "./conveyor/useConveyorActions"; import { useMachineActions } from "./machine/useMachineActions"; import { useRoboticArmActions } from "./roboticArm/useRoboticArmActions"; @@ -7,27 +10,29 @@ import { useVehicleActions } from "./vehicle/useVehicleActions"; import { useCallback, useEffect } from "react"; export function useActionHandler() { - const { isReset } = useResetButtonStore(); - const { isPlaying } = usePlayButtonStore(); - const { handleConveyorAction, cleanup: cleanupConveyor } = useConveyorActions(); - const { handleVehicleAction, cleanup: cleanupVehicle } = useVehicleActions(); - const { handleRoboticArmAction, cleanup: cleanupRoboticArm } = useRoboticArmActions(); - const { handleMachineAction, cleanup: cleanupMachine } = useMachineActions(); - const { handleStorageAction, cleanup: cleanupStorage } = useStorageActions(); - - const handleAction = useCallback((action: Action, materialId?: string) => { - if (!action) return; + const { isReset } = useResetButtonStore(); + const { isPlaying } = usePlayButtonStore(); + const { handleConveyorAction, cleanup: cleanupConveyor } = + useConveyorActions(); + const { handleVehicleAction, cleanup: cleanupVehicle } = useVehicleActions(); + const { handleRoboticArmAction, cleanup: cleanupRoboticArm } = + useRoboticArmActions(); + const { handleMachineAction, cleanup: cleanupMachine } = useMachineActions(); + const { handleStorageAction, cleanup: cleanupStorage } = useStorageActions(); + const handleAction = useCallback( + (action: Action, materialId?: string) => { + if (!action) return; try { switch (action.actionType) { case 'default': case 'spawn': case 'swap': case 'delay': case 'despawn': handleConveyorAction(action as ConveyorAction, materialId as string); break; case 'travel': - handleVehicleAction(action as VehicleAction); + handleVehicleAction(action as VehicleAction, materialId as string); break; case 'pickAndPlace': - handleRoboticArmAction(action as RoboticArmAction); + handleRoboticArmAction(action as RoboticArmAction, materialId as string); break; case 'process': handleMachineAction(action as MachineAction); @@ -38,27 +43,42 @@ export function useActionHandler() { default: console.warn(`Unknown action type: ${(action as Action).actionType}`); } - } catch (error) { - console.error('Error handling action:', error); - } - }, [handleConveyorAction, handleVehicleAction, handleRoboticArmAction, handleMachineAction, handleStorageAction]); + } catch (error) { + echo.error("Failed to handle action"); + console.error("Error handling action:", error); + } + }, + [ + handleConveyorAction, + handleVehicleAction, + handleRoboticArmAction, + handleMachineAction, + handleStorageAction, + ] + ); - const cleanup = useCallback(() => { - cleanupConveyor(); - cleanupVehicle(); - cleanupRoboticArm(); - cleanupMachine(); - cleanupStorage(); - }, [cleanupConveyor, cleanupVehicle, cleanupRoboticArm, cleanupMachine, cleanupStorage]); + const cleanup = useCallback(() => { + cleanupConveyor(); + cleanupVehicle(); + cleanupRoboticArm(); + cleanupMachine(); + cleanupStorage(); + }, [ + cleanupConveyor, + cleanupVehicle, + cleanupRoboticArm, + cleanupMachine, + cleanupStorage, + ]); - useEffect(() => { - return () => { - cleanup(); - }; - }, [cleanup, isReset, isPlaying]); - - return { - handleAction, - cleanup + useEffect(() => { + return () => { + cleanup(); }; -} \ No newline at end of file + }, [cleanup, isReset, isPlaying]); + + return { + handleAction, + cleanup, + }; +} diff --git a/app/src/modules/simulation/actions/vehicle/actionHandler/useTravelHandler.ts b/app/src/modules/simulation/actions/vehicle/actionHandler/useTravelHandler.ts new file mode 100644 index 0000000..c77b518 --- /dev/null +++ b/app/src/modules/simulation/actions/vehicle/actionHandler/useTravelHandler.ts @@ -0,0 +1,37 @@ +import { useCallback } from "react"; +import { useMaterialStore } from "../../../../../store/simulation/useMaterialStore"; +import { useProductStore } from "../../../../../store/simulation/useProductStore"; +import { useSelectedProduct } from "../../../../../store/simulation/useSimulationStore"; +import { useVehicleStore } from "../../../../../store/simulation/useVehicleStore"; + +export function useTravelHandler() { + const { getMaterialById } = useMaterialStore(); + const { getModelUuidByActionUuid } = useProductStore(); + const { selectedProduct } = useSelectedProduct(); + const { incrementVehicleLoad, addCurrentMaterial } = useVehicleStore(); + + const travelLogStatus = (materialUuid: string, status: string) => { + // console.log(`${materialUuid}, ${status}`); + } + + const handleTravel = useCallback((action: VehicleAction, materialId?: string) => { + if (!action || action.actionType !== 'travel' || !materialId) return; + + const material = getMaterialById(materialId); + if (!material) return; + + const modelUuid = getModelUuidByActionUuid(selectedProduct.productId, action.actionUuid); + + if (!modelUuid) return; + + incrementVehicleLoad(modelUuid, 1); + addCurrentMaterial(modelUuid, material.materialType, material.materialId); + + travelLogStatus(material.materialId, `is triggering travel from ${modelUuid}`); + + }, [getMaterialById, getModelUuidByActionUuid]); + + return { + handleTravel, + }; +} \ No newline at end of file diff --git a/app/src/modules/simulation/actions/vehicle/useVehicleActions.ts b/app/src/modules/simulation/actions/vehicle/useVehicleActions.ts index 313fb5d..a54672b 100644 --- a/app/src/modules/simulation/actions/vehicle/useVehicleActions.ts +++ b/app/src/modules/simulation/actions/vehicle/useVehicleActions.ts @@ -1,20 +1,19 @@ import { useEffect, useCallback } from 'react'; +import { useTravelHandler } from './actionHandler/useTravelHandler'; export function useVehicleActions() { + const { handleTravel } = useTravelHandler(); - const handleTravelAction = useCallback((action: VehicleAction) => { - if (!action || action.actionType !== 'travel') return; + const handleTravelAction = useCallback((action: VehicleAction, materialId: string) => { + handleTravel(action, materialId); + }, [handleTravel]); - console.log(`Vehicle travel action ${action.actionUuid}`); - - }, []); - - const handleVehicleAction = useCallback((action: VehicleAction) => { + const handleVehicleAction = useCallback((action: VehicleAction, materialId: string) => { if (!action) return; switch (action.actionType) { case 'travel': - handleTravelAction(action); + handleTravelAction(action, materialId); break; default: console.warn(`Unknown vehicle action type: ${action.actionType}`); diff --git a/app/src/modules/simulation/materials/instances/instance/materialInstance.tsx b/app/src/modules/simulation/materials/instances/instance/materialInstance.tsx index a26109c..74bd61f 100644 --- a/app/src/modules/simulation/materials/instances/instance/materialInstance.tsx +++ b/app/src/modules/simulation/materials/instances/instance/materialInstance.tsx @@ -85,37 +85,10 @@ function MaterialInstance({ material }: { material: MaterialSchema }) { const callTrigger = () => { if (!material.next) return; - const fromModel = getEventByModelUuid(selectedProduct.productId, material.next.modelUuid); - if (!fromModel) return; - const fromPoint = getPointByUuid(selectedProduct.productId, fromModel.modelUuid, material.next.pointUuid); - if (!fromPoint) return; - - if (fromModel.type === 'transfer') { - const toModel = getEventByModelUuid(selectedProduct.productId, material.next.modelUuid); - if (!toModel) return; - if (toModel.type === 'transfer') { - const action = getActionByPointUuid(selectedProduct.productId, material.next.pointUuid); - if (action) { - triggerPointActions(action, material.materialId); - } - } else if (toModel?.type === 'vehicle') { - // Transfer to Vehicle - - } else if (toModel?.type === 'machine') { - // Transfer to Machine - - } else if (toModel?.type === 'roboticArm') { - // Transfer to Robotic Arm - - } else if (toModel?.type === 'storageUnit') { - // Transfer to Storage Unit - } - } else if (fromModel.type === 'vehicle') { - } else if (fromModel.type === 'machine') { - } else if (fromModel.type === 'roboticArm') { - } else if (fromModel.type === 'storageUnit') { + const action = getActionByPointUuid(selectedProduct.productId, material.next.pointUuid); + if (action) { + triggerPointActions(action, material.materialId); } - } return ( diff --git a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx index ec044ce..75e7715 100644 --- a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx +++ b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx @@ -9,6 +9,7 @@ import { usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '.. import { useMaterialStore } from '../../../../../store/simulation/useMaterialStore'; import { useArmBotStore } from '../../../../../store/simulation/useArmBotStore'; import { useProductStore } from '../../../../../store/simulation/useProductStore'; +import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore'; import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore'; import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler'; @@ -26,9 +27,10 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { let startTime: number; const { setArmBotActive, setArmBotState, removeCurrentAction } = useArmBotStore(); - const { setIsVisible } = useMaterialStore(); + const { decrementVehicleLoad, removeLastMaterial } = useVehicleStore(); + const { setIsVisible, getMaterialById } = useMaterialStore(); const { selectedProduct } = useSelectedProduct(); - const { getActionByUuid } = useProductStore(); + const { getActionByUuid, getEventByModelUuid } = useProductStore(); const { triggerPointActions } = useTriggerHandler(); const { isPlaying } = usePlayButtonStore(); const { isReset } = useResetButtonStore(); @@ -73,8 +75,29 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { logStatus(armBot.modelUuid, "picking the object"); setPath(curve.points.map(point => [point.x, point.y, point.z])) - if (armBot.currentAction) { - setIsVisible(armBot.currentAction.materialId || '', false); + if (armBot.currentAction && armBot.currentAction.materialId) { + const material = getMaterialById(armBot.currentAction.materialId) + if (material && material.previous && material.previous.modelUuid) { + + const model = getEventByModelUuid(selectedProduct.productId, material.previous.modelUuid); + + if (model) { + if (model.type === 'transfer') { + setIsVisible(armBot.currentAction.materialId, false); + } else if (model.type === 'machine') { + + } else if (model.type === 'vehicle') { + decrementVehicleLoad(model.modelUuid, 1); + removeLastMaterial(model.modelUuid); + } else if (model.type === 'storageUnit') { + + } + } else { + setIsVisible(armBot.currentAction.materialId, false); + } + } else { + setIsVisible(armBot.currentAction.materialId, false); + } } } } @@ -204,12 +227,10 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { function createCurveBetweenTwoPoints(p1: any, p2: any) { const mid = new THREE.Vector3().addVectors(p1, p2).multiplyScalar(0.5); - // mid.y += 0.5; const points = [p1, mid, p2]; return new THREE.CatmullRomCurve3(points); } - const HandleCallback = () => { if (armBot.isActive && armBot.state == "running" && currentPhase == "init-to-rest") { logStatus(armBot.modelUuid, "Callback triggered: rest"); diff --git a/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx b/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx index 0acc1d9..fc0865c 100644 --- a/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx +++ b/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx @@ -1,16 +1,21 @@ -import RoboticArmInstance from './armInstance/roboticArmInstance'; -import { useArmBotStore } from '../../../../store/simulation/useArmBotStore'; +import RoboticArmInstance from "./armInstance/roboticArmInstance"; +import { useArmBotStore } from "../../../../store/simulation/useArmBotStore"; +import RoboticArmContentUi from "../../ui3d/RoboticArmContentUi"; +import React from "react"; function RoboticArmInstances() { - const { armBots } = useArmBotStore(); + const { armBots } = useArmBotStore(); - return ( - <> - {armBots?.map((robot: ArmBotStatus) => ( - - ))} - - ) + return ( + <> + {armBots?.map((robot: ArmBotStatus) => ( + + + + + ))} + + ); } -export default RoboticArmInstances; \ No newline at end of file +export default RoboticArmInstances; diff --git a/app/src/modules/simulation/roboticArm/roboticArm.tsx b/app/src/modules/simulation/roboticArm/roboticArm.tsx index 91ccb55..ffdb312 100644 --- a/app/src/modules/simulation/roboticArm/roboticArm.tsx +++ b/app/src/modules/simulation/roboticArm/roboticArm.tsx @@ -2,19 +2,15 @@ import { useEffect, useState } from "react"; import { useArmBotStore } from "../../../store/simulation/useArmBotStore"; import { useSelectedEventSphere } from "../../../store/simulation/useSimulationStore"; import { usePlayButtonStore } from "../../../store/usePlayButtonStore"; -import ArmBotUI from "../ui/arm/armBotUI"; import RoboticArmInstances from "./instances/roboticArmInstances"; +import ArmBotUI from "../spatialUI/arm/armBotUI"; function RoboticArm() { - const { armBots, getArmBotById } = useArmBotStore(); + const { getArmBotById } = useArmBotStore(); const { selectedEventSphere } = useSelectedEventSphere(); const { isPlaying } = usePlayButtonStore(); const [isArmBotSelected, setIsArmBotSelected] = useState(false); - useEffect(() => { - // console.log('armBots: ', armBots); - }, [armBots]) - useEffect(() => { if (selectedEventSphere) { const selectedArmBot = getArmBotById(selectedEventSphere.userData.modelUuid); @@ -24,7 +20,7 @@ function RoboticArm() { setIsArmBotSelected(false); } } - }, [selectedEventSphere]) + }, [getArmBotById, selectedEventSphere]) return ( <> diff --git a/app/src/modules/simulation/ui/arm/PickDropPoints.tsx b/app/src/modules/simulation/spatialUI/arm/PickDropPoints.tsx similarity index 100% rename from app/src/modules/simulation/ui/arm/PickDropPoints.tsx rename to app/src/modules/simulation/spatialUI/arm/PickDropPoints.tsx diff --git a/app/src/modules/simulation/ui/arm/armBotUI.tsx b/app/src/modules/simulation/spatialUI/arm/armBotUI.tsx similarity index 98% rename from app/src/modules/simulation/ui/arm/armBotUI.tsx rename to app/src/modules/simulation/spatialUI/arm/armBotUI.tsx index 12fdde8..4e1b01c 100644 --- a/app/src/modules/simulation/ui/arm/armBotUI.tsx +++ b/app/src/modules/simulation/spatialUI/arm/armBotUI.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { useSelectedAction, useSelectedEventData, useSelectedEventSphere, useSelectedProduct } from '../../../../store/simulation/useSimulationStore'; +import { useSelectedAction, useSelectedEventSphere, useSelectedProduct } from '../../../../store/simulation/useSimulationStore'; import { useGLTF } from '@react-three/drei'; import { useThree } from '@react-three/fiber'; import { useProductStore } from '../../../../store/simulation/useProductStore'; diff --git a/app/src/modules/simulation/ui/arm/useDraggableGLTF.ts b/app/src/modules/simulation/spatialUI/arm/useDraggableGLTF.ts similarity index 100% rename from app/src/modules/simulation/ui/arm/useDraggableGLTF.ts rename to app/src/modules/simulation/spatialUI/arm/useDraggableGLTF.ts diff --git a/app/src/modules/simulation/ui/temp.md b/app/src/modules/simulation/spatialUI/temp.md similarity index 100% rename from app/src/modules/simulation/ui/temp.md rename to app/src/modules/simulation/spatialUI/temp.md diff --git a/app/src/modules/simulation/ui/vehicle/useDraggableGLTF.ts b/app/src/modules/simulation/spatialUI/vehicle/useDraggableGLTF.ts similarity index 100% rename from app/src/modules/simulation/ui/vehicle/useDraggableGLTF.ts rename to app/src/modules/simulation/spatialUI/vehicle/useDraggableGLTF.ts diff --git a/app/src/modules/simulation/spatialUI/vehicle/vehicleUI.tsx b/app/src/modules/simulation/spatialUI/vehicle/vehicleUI.tsx new file mode 100644 index 0000000..843b81b --- /dev/null +++ b/app/src/modules/simulation/spatialUI/vehicle/vehicleUI.tsx @@ -0,0 +1,409 @@ +import { useEffect, useRef, useState } from "react"; +import * as Types from "../../../../types/world/worldTypes"; +import startPoint from "../../../../assets/gltf-glb/arrow_green.glb"; +import startEnd from "../../../../assets/gltf-glb/arrow_red.glb"; +import { useGLTF } from "@react-three/drei"; +import { useFrame, useThree } from "@react-three/fiber"; +import { + useSelectedEventSphere, + useIsDragging, + useSelectedProduct, + useIsRotating, +} from "../../../../store/simulation/useSimulationStore"; +import { useVehicleStore } from "../../../../store/simulation/useVehicleStore"; +import { useProductStore } from "../../../../store/simulation/useProductStore"; +import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi"; +import { DoubleSide, Group, Plane, Vector3 } from "three"; + +const VehicleUI = () => { + const { scene: startScene } = useGLTF(startPoint) as any; + const { scene: endScene } = useGLTF(startEnd) as any; + const startMarker = useRef(null); + const endMarker = useRef(null); + const prevMousePos = useRef({ x: 0, y: 0 }); + const { selectedEventSphere } = useSelectedEventSphere(); + const { selectedProduct } = useSelectedProduct(); + const { getVehicleById } = useVehicleStore(); + const { updateEvent } = useProductStore(); + const [startPosition, setStartPosition] = useState<[number, number, number]>([ + 0, 1, 0, + ]); + + const [endPosition, setEndPosition] = useState<[number, number, number]>([ + 0, 1, 0, + ]); + const [startRotation, setStartRotation] = useState<[number, number, number]>([ + 0, 0, 0, + ]); + + const [endRotation, setEndRotation] = useState<[number, number, number]>([ + 0, 0, 0, + ]); + const [steeringRotation, setSteeringRotation] = useState< + [number, number, number] + >([0, 0, 0]); + + const { isDragging, setIsDragging } = useIsDragging(); + const { isRotating, setIsRotating } = useIsRotating(); + const { raycaster } = useThree(); + const [point, setPoint] = useState<[number, number, number]>([0, 0, 0]); + const plane = useRef(new Plane(new Vector3(0, 1, 0), 0)); + const [tubeRotation, setTubeRotation] = useState(false); + const tubeRef = useRef(null); + const outerGroup = useRef(null); + const state: Types.ThreeState = useThree(); + const controls: any = state.controls; + const [selectedVehicleData, setSelectedVechicleData] = useState<{ + position: [number, number, number]; + rotation: [number, number, number]; + }>({ position: [0, 0, 0], rotation: [0, 0, 0] }); + const CIRCLE_RADIUS = 0.8; + const email = localStorage.getItem("email"); + const organization = email!.split("@")[1].split(".")[0]; + + const updateBackend = ( + productName: string, + productId: string, + organization: string, + eventData: EventsSchema + ) => { + upsertProductOrEventApi({ + productName: productName, + productId: productId, + organization: organization, + eventDatas: eventData, + }); + }; + + useEffect(() => { + if (!selectedEventSphere) return; + const selectedVehicle = getVehicleById( + selectedEventSphere.userData.modelUuid + ); + + if (selectedVehicle) { + setSelectedVechicleData({ + position: selectedVehicle.position, + rotation: selectedVehicle.rotation, + }); + setPoint(selectedVehicle.point.position); + } + + setTimeout(() => { + if (selectedVehicle?.point?.action) { + const { pickUpPoint, unLoadPoint, steeringAngle } = + selectedVehicle.point.action; + + if (pickUpPoint && outerGroup.current) { + const worldPos = new Vector3( + pickUpPoint.position.x, + pickUpPoint.position.y, + pickUpPoint.position.z + ); + const localPosition = outerGroup.current.worldToLocal( + worldPos.clone() + ); + + setStartPosition([ + localPosition.x, + selectedVehicle.point.position[1], + localPosition.z, + ]); + setStartRotation([ + pickUpPoint.rotation.x, + pickUpPoint.rotation.y, + pickUpPoint.rotation.z, + ]); + } else { + setStartPosition([0, selectedVehicle.point.position[1] + 0.1, 1.5]); + setStartRotation([0, 0, 0]); + } + // end point + if (unLoadPoint && outerGroup.current) { + const worldPos = new Vector3( + unLoadPoint.position.x, + unLoadPoint.position.y, + unLoadPoint.position.z + ); + const localPosition = outerGroup.current.worldToLocal(worldPos); + + setEndPosition([ + localPosition.x, + selectedVehicle.point.position[1], + localPosition.z, + ]); + setEndRotation([ + unLoadPoint.rotation.x, + unLoadPoint.rotation.y, + unLoadPoint.rotation.z, + ]); + } else { + setEndPosition([0, selectedVehicle.point.position[1] + 0.1, -1.5]); + setEndRotation([0, 0, 0]); + } + setSteeringRotation([0, steeringAngle, 0]); + } + }, 10); + }, [selectedEventSphere, outerGroup.current]); + + const handlePointerDown = ( + e: any, + state: "start" | "end", + rotation: "start" | "end" + ) => { + if (e.object.name === "handle") { + const normalizedX = (e.clientX / window.innerWidth) * 2 - 1; + const normalizedY = -(e.clientY / window.innerHeight) * 2 + 1; + prevMousePos.current = { x: normalizedX, y: normalizedY }; + setIsRotating(rotation); + if (controls) controls.enabled = false; + setIsDragging(null); + } else { + setIsDragging(state); + setIsRotating(null); + if (controls) controls.enabled = false; + } + }; + + const handlePointerUp = () => { + controls.enabled = true; + setIsDragging(null); + setIsRotating(null); + + if (selectedEventSphere?.userData.modelUuid) { + const updatedVehicle = getVehicleById( + selectedEventSphere.userData.modelUuid + ); + + let globalStartPosition = null; + let globalEndPosition = null; + + if (outerGroup.current && startMarker.current && endMarker.current) { + const worldPosStart = new Vector3(...startPosition); + globalStartPosition = outerGroup.current.localToWorld( + worldPosStart.clone() + ); + const worldPosEnd = new Vector3(...endPosition); + globalEndPosition = outerGroup.current.localToWorld( + worldPosEnd.clone() + ); + } + if (updatedVehicle && globalEndPosition && globalStartPosition) { + const event = updateEvent( + selectedProduct.productId, + selectedEventSphere.userData.modelUuid, + { + point: { + ...updatedVehicle.point, + action: { + ...updatedVehicle.point?.action, + pickUpPoint: { + position: { + x: globalStartPosition.x, + y: 0, + z: globalStartPosition.z, + }, + rotation: { x: 0, y: startRotation[1], z: 0 }, + }, + unLoadPoint: { + position: { + x: globalEndPosition.x, + y: 0, + z: globalEndPosition.z, + }, + rotation: { x: 0, y: endRotation[1], z: 0 }, + }, + steeringAngle: steeringRotation[1], + }, + }, + } + ); + + if (event) { + updateBackend( + selectedProduct.productName, + selectedProduct.productId, + organization, + event + ); + } + } + } + }; + + useFrame(() => { + if (!isDragging || !plane.current || !raycaster || !outerGroup.current) + return; + const intersectPoint = new Vector3(); + const intersects = raycaster.ray.intersectPlane( + plane.current, + intersectPoint + ); + if (!intersects) return; + const localPoint = outerGroup?.current.worldToLocal(intersectPoint.clone()); + if (isDragging === "start") { + setStartPosition([localPoint.x, point[1], localPoint.z]); + } else if (isDragging === "end") { + setEndPosition([localPoint.x, point[1], localPoint.z]); + } + }); + + useEffect(() => { + const handleGlobalPointerUp = () => { + setIsDragging(null); + setIsRotating(null); + setTubeRotation(false); + if (controls) controls.enabled = true; + handlePointerUp(); + }; + + if (isDragging || isRotating || tubeRotation) { + window.addEventListener("pointerup", handleGlobalPointerUp); + } + + return () => { + window.removeEventListener("pointerup", handleGlobalPointerUp); + }; + }, [ + isDragging, + isRotating, + startPosition, + startRotation, + endPosition, + endRotation, + tubeRotation, + steeringRotation, + outerGroup.current, + tubeRef.current, + ]); + + const prevSteeringY = useRef(0); + useFrame((state) => { + if (tubeRotation) { + const currentPointerX = state.pointer.x; + const deltaX = currentPointerX - prevMousePos.current.x; + prevMousePos.current.x = currentPointerX; + + const marker = tubeRef.current; + if (marker) { + const rotationSpeed = 2; + marker.rotation.y += deltaX * rotationSpeed; + setSteeringRotation([ + marker.rotation.x, + marker.rotation.y, + marker.rotation.z, + ]); + } + } else { + prevSteeringY.current = 0; + } + }); + useFrame((state) => { + if (!isRotating) return; + const currentPointerX = state.pointer.x; + const deltaX = currentPointerX - prevMousePos.current.x; + prevMousePos.current.x = currentPointerX; + const marker = + isRotating === "start" ? startMarker.current : endMarker.current; + if (marker) { + const rotationSpeed = 10; + marker.rotation.y += deltaX * rotationSpeed; + if (isRotating === "start") { + setStartRotation([ + marker.rotation.x, + marker.rotation.y, + marker.rotation.z, + ]); + } else { + setEndRotation([ + marker.rotation.x, + marker.rotation.y, + marker.rotation.z, + ]); + } + } + }); + + return selectedVehicleData ? ( + + { + e.stopPropagation(); + setTubeRotation(true); + prevMousePos.current.x = e.pointer.x; + controls.enabled = false; + }} + onPointerMissed={() => { + controls.enabled = true; + setTubeRotation(false); + }} + onPointerUp={() => { + controls.enabled = true; + setTubeRotation(false); + }} + > + ( + + + + + + + + + ) + + + {/* Start Marker */} + { + e.stopPropagation(); + handlePointerDown(e, "start", "start"); + }} + onPointerMissed={() => { + controls.enabled = true; + setIsDragging(null); + setIsRotating(null); + }} + /> + + {/* End Marker */} + { + e.stopPropagation(); + handlePointerDown(e, "end", "end"); + }} + onPointerMissed={() => { + controls.enabled = true; + setIsDragging(null); + setIsRotating(null); + }} + /> + + ) : null; +}; +export default VehicleUI; diff --git a/app/src/modules/simulation/triggers/connector/triggerConnector.tsx b/app/src/modules/simulation/triggers/connector/triggerConnector.tsx index 6afcc69..a56436f 100644 --- a/app/src/modules/simulation/triggers/connector/triggerConnector.tsx +++ b/app/src/modules/simulation/triggers/connector/triggerConnector.tsx @@ -50,7 +50,7 @@ function TriggerConnector() { organization: string, eventData: EventsSchema ) => { - upsertProductOrEventApi({ + const data =upsertProductOrEventApi({ productName: productName, productId: productId, organization: organization, diff --git a/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts b/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts index c33e2ec..c022e78 100644 --- a/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts +++ b/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts @@ -4,15 +4,17 @@ import { useProductStore } from '../../../../store/simulation/useProductStore'; import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore'; import { useMaterialStore } from '../../../../store/simulation/useMaterialStore'; import { useArmBotStore } from '../../../../store/simulation/useArmBotStore'; +import { useVehicleStore } from '../../../../store/simulation/useVehicleStore'; export function useTriggerHandler() { const { handleAction } = useActionHandler(); const { selectedProduct } = useSelectedProduct(); const { getEventByTriggerUuid, getEventByModelUuid, getActionByUuid, getModelUuidByActionUuid } = useProductStore(); - const { addCurrentAction, getArmBotById } = useArmBotStore(); - const { setCurrentLocation, setNextLocation, getMaterialById, setIsPaused, setEndTime } = useMaterialStore(); + const { getArmBotById } = useArmBotStore(); + const { getVehicleById } = useVehicleStore(); + const { setCurrentLocation, setNextLocation, setPreviousLocation, getMaterialById, setIsPaused, setIsVisible, setEndTime } = useMaterialStore(); - const handleTrigger = (trigger: TriggerSchema, action: Action, materialId: string) => { + const handleTrigger = (trigger: TriggerSchema, action: Action, materialId?: string) => { const fromEvent = getEventByTriggerUuid(selectedProduct.productId, trigger.triggerUuid); @@ -21,11 +23,17 @@ export function useTriggerHandler() { if (fromEvent?.type === 'transfer') { if (toEvent?.type === 'transfer') { // Transfer to Transfer - if (trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) { + if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) { const material = getMaterialById(materialId); if (material) { if (material.next) { + setPreviousLocation(material.materialId, { + modelUuid: material.current.modelUuid, + pointUuid: material.current.pointUuid, + actionUuid: material.current.actionUuid, + }) + setCurrentLocation(material.materialId, { modelUuid: material.next.modelUuid, pointUuid: material.next.pointUuid, @@ -42,42 +50,102 @@ export function useTriggerHandler() { } } else if (toEvent?.type === 'vehicle') { // Transfer to Vehicle + if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) { + const material = getMaterialById(materialId); + if (material) { + + // Handle current action of the material + handleAction(action, materialId); + + if (material.next) { + const action = getActionByUuid(selectedProduct.productId, trigger.triggeredAsset.triggeredAction.actionUuid); + const vehicle = getVehicleById(trigger.triggeredAsset?.triggeredModel.modelUuid); + + setPreviousLocation(material.materialId, { + modelUuid: material.current.modelUuid, + pointUuid: material.current.pointUuid, + actionUuid: material.current.actionUuid, + }) + + setCurrentLocation(material.materialId, { + modelUuid: material.next.modelUuid, + pointUuid: material.next.pointUuid, + actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid, + }); + + setNextLocation(material.materialId, null); + + if (action) { + + if (vehicle) { + + if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.currentLoad < vehicle.point.action.loadCapacity) { + + setIsVisible(materialId, false); + + // Handle current action from vehicle + handleAction(action, materialId); + + } else { + + // Event Manager Needed + + } + } + } + } + } + } } else if (toEvent?.type === 'machine') { // Transfer to Machine } else if (toEvent?.type === 'roboticArm') { // Transfer to Robotic Arm - if (trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) { + if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) { const material = getMaterialById(materialId); if (material) { + + // Handle current action of the material + handleAction(action, materialId); + if (material.next) { + const action = getActionByUuid(selectedProduct.productId, trigger.triggeredAsset.triggeredAction.actionUuid); const armBot = getArmBotById(trigger.triggeredAsset?.triggeredModel.modelUuid); - if (armBot) { - if (armBot.isActive === false && armBot.state === 'idle') { - setCurrentLocation(material.materialId, { - modelUuid: material.next.modelUuid, - pointUuid: material.next.pointUuid, - actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid, - }); - setNextLocation(material.materialId, null); + setPreviousLocation(material.materialId, { + modelUuid: material.current.modelUuid, + pointUuid: material.current.pointUuid, + actionUuid: material.current.actionUuid, + }) - setIsPaused(material.materialId, true); - addCurrentAction( - trigger.triggeredAsset?.triggeredModel.modelUuid, - trigger.triggeredAsset?.triggeredAction?.actionUuid, - material.materialType, - material.materialId - ); - } else { + setCurrentLocation(material.materialId, { + modelUuid: material.next.modelUuid, + pointUuid: material.next.pointUuid, + actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid, + }); - // Event Manager Needed + setNextLocation(material.materialId, null); + if (action) { + + if (armBot) { + + if (armBot.isActive === false && armBot.state === 'idle') { + + setIsPaused(material.materialId, true); + + // Handle current action from arm bot + handleAction(action, materialId); + + } else { + + // Event Manager Needed + + } } } } - handleAction(action, materialId); } } } else if (toEvent?.type === 'storageUnit') { @@ -87,6 +155,39 @@ export function useTriggerHandler() { } else if (fromEvent?.type === 'vehicle') { if (toEvent?.type === 'transfer') { // Vehicle to Transfer + if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) { + const material = getMaterialById(materialId); + if (material) { + const action = getActionByUuid(selectedProduct.productId, trigger.triggeredAsset.triggeredAction.actionUuid); + + setPreviousLocation(material.materialId, { + modelUuid: material.current.modelUuid, + pointUuid: material.current.pointUuid, + actionUuid: material.current.actionUuid, + }) + + setCurrentLocation(material.materialId, { + modelUuid: trigger.triggeredAsset.triggeredModel.modelUuid, + pointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid, + actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid, + }); + + setIsVisible(materialId, true); + + if (action && + action.triggers[0].triggeredAsset?.triggeredModel.modelUuid && + action.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid + ) { + setNextLocation(material.materialId, { + modelUuid: action.triggers[0].triggeredAsset?.triggeredModel.modelUuid, + pointUuid: action.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid, + }); + + handleAction(action, materialId); + } + + } + } } else if (toEvent?.type === 'vehicle') { // Vehicle to Vehicle @@ -96,6 +197,46 @@ export function useTriggerHandler() { } else if (toEvent?.type === 'roboticArm') { // Vehicle to Robotic Arm + if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) { + const material = getMaterialById(materialId); + if (material) { + const action = getActionByUuid(selectedProduct.productId, trigger.triggeredAsset.triggeredAction.actionUuid); + const armBot = getArmBotById(trigger.triggeredAsset?.triggeredModel.modelUuid); + + setPreviousLocation(material.materialId, { + modelUuid: material.current.modelUuid, + pointUuid: material.current.pointUuid, + actionUuid: material.current.actionUuid, + }) + + setCurrentLocation(material.materialId, { + modelUuid: trigger.triggeredAsset.triggeredModel.modelUuid, + pointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid, + actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid, + }); + + setNextLocation(material.materialId, null); + + setIsVisible(materialId, false); + + if (action && armBot && + action.triggers[0].triggeredAsset?.triggeredModel.modelUuid && + action.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid + ) { + + if (armBot.isActive === false && armBot.state === 'idle') { + + // Handle current action from arm bot + handleAction(action, materialId); + + } else { + + // Event Manager Needed + + } + } + } + } } else if (toEvent?.type === 'storageUnit') { // Vehicle to Storage Unit @@ -121,11 +262,17 @@ export function useTriggerHandler() { } else if (fromEvent?.type === 'roboticArm') { if (toEvent?.type === 'transfer') { // Robotic Arm to Transfer - if (trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) { + if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) { const material = getMaterialById(materialId); if (material) { setIsPaused(material.materialId, false); + setPreviousLocation(material.materialId, { + modelUuid: material.current.modelUuid, + pointUuid: material.current.pointUuid, + actionUuid: material.current.actionUuid, + }) + setCurrentLocation(material.materialId, { modelUuid: trigger.triggeredAsset.triggeredModel.modelUuid, pointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid, @@ -136,12 +283,64 @@ export function useTriggerHandler() { if (action && action.triggers.length > 0 && action.triggers[0].triggeredAsset?.triggeredModel.modelUuid && + action.triggers[0].triggeredAsset?.triggeredAction?.actionUuid && action.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid) { - setNextLocation(material.materialId, { - modelUuid: action.triggers[0].triggeredAsset?.triggeredModel.modelUuid, - pointUuid: action.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid, - }) - handleAction(action, material.materialId); + const model = getEventByModelUuid(selectedProduct.productId, action.triggers[0].triggeredAsset?.triggeredModel.modelUuid); + + if (model?.type === 'roboticArm') { + + handleAction(action, material.materialId); + + } else if (model?.type === 'vehicle') { + const nextAction = getActionByUuid(selectedProduct.productId, action.triggers[0].triggeredAsset?.triggeredAction.actionUuid); + + if (action) { + handleAction(action, material.materialId); + + const vehicle = getVehicleById(action.triggers[0].triggeredAsset?.triggeredModel.modelUuid); + + setPreviousLocation(material.materialId, { + modelUuid: material.current.modelUuid, + pointUuid: material.current.pointUuid, + actionUuid: material.current.actionUuid, + }) + + setCurrentLocation(material.materialId, { + modelUuid: trigger.triggeredAsset?.triggeredModel.modelUuid, + pointUuid: trigger.triggeredAsset?.triggeredPoint?.pointUuid, + actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid, + }); + + setNextLocation(material.materialId, null); + + if (nextAction) { + + if (vehicle) { + + if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.currentLoad < vehicle.point.action.loadCapacity) { + + setIsVisible(materialId, false); + + // Handle current action from vehicle + handleAction(nextAction, materialId); + + } else { + + // Event Manager Needed + + } + } + } + } + + } else { + setNextLocation(material.materialId, { + modelUuid: action.triggers[0].triggeredAsset?.triggeredModel.modelUuid, + pointUuid: action.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid, + }) + + handleAction(action, material.materialId); + } } } @@ -149,6 +348,50 @@ export function useTriggerHandler() { } else if (toEvent?.type === 'vehicle') { // Robotic Arm to Vehicle + if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) { + const material = getMaterialById(materialId); + if (material) { + + setIsPaused(material.materialId, false); + + const action = getActionByUuid(selectedProduct.productId, trigger.triggeredAsset.triggeredAction.actionUuid); + const vehicle = getVehicleById(trigger.triggeredAsset?.triggeredModel.modelUuid); + + setPreviousLocation(material.materialId, { + modelUuid: material.current.modelUuid, + pointUuid: material.current.pointUuid, + actionUuid: material.current.actionUuid, + }) + + setCurrentLocation(material.materialId, { + modelUuid: trigger.triggeredAsset.triggeredModel.modelUuid, + pointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid, + actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid, + }); + + setNextLocation(material.materialId, null); + + if (action) { + + if (vehicle) { + + if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.currentLoad < vehicle.point.action.loadCapacity) { + + setIsVisible(materialId, false); + + // Handle current action from vehicle + handleAction(action, materialId); + + } else { + + // Event Manager Needed + + } + } + } + + } + } } else if (toEvent?.type === 'machine') { // Robotic Arm to Machine @@ -180,21 +423,27 @@ export function useTriggerHandler() { } } - const handleFinalAction = (action: Action, materialId: string) => { + const handleFinalAction = (action: Action, materialId?: string) => { if (!action) return; const modelUuid = getModelUuidByActionUuid(selectedProduct.productId, action.actionUuid); if (!modelUuid) return; const finalModel = getEventByModelUuid(selectedProduct.productId, modelUuid); if (!finalModel) return; - const material = getMaterialById(materialId); if (finalModel.type === 'transfer') { // Storage Unit to Transfer - + if (!materialId) return; + const material = getMaterialById(materialId); if (material) { const currentTime = performance.now(); + setPreviousLocation(material.materialId, { + modelUuid: material.current.modelUuid, + pointUuid: material.current.pointUuid, + actionUuid: material.current.actionUuid, + }) + setCurrentLocation(material.materialId, { modelUuid: material.next?.modelUuid || '', pointUuid: material.next?.pointUuid || '', @@ -224,7 +473,7 @@ export function useTriggerHandler() { } - const triggerPointActions = useCallback((action: Action, materialId: string) => { + const triggerPointActions = useCallback((action: Action, materialId?: string) => { if (!action) return; if (action.triggers.length > 0) { diff --git a/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx b/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx deleted file mode 100644 index 2a124cd..0000000 --- a/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx +++ /dev/null @@ -1,232 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react'; -import * as Types from "../../../../types/world/worldTypes"; -import startPoint from "../../../../assets/gltf-glb/arrow_green.glb"; -import * as THREE from "three"; -import startEnd from "../../../../assets/gltf-glb/arrow_red.glb"; -import { useGLTF } from '@react-three/drei'; -import { useFrame, useThree } from '@react-three/fiber'; -import { useSelectedEventSphere, useIsDragging, useIsRotating } from '../../../../store/simulation/useSimulationStore'; -import { useVehicleStore } from '../../../../store/simulation/useVehicleStore'; -import { useProductStore } from '../../../../store/simulation/useProductStore'; -import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore'; -import { upsertProductOrEventApi } from '../../../../services/simulation/UpsertProductOrEventApi'; - -const VehicleUI = () => { - const { scene: startScene } = useGLTF(startPoint) as any; - const { scene: endScene } = useGLTF(startEnd) as any; - const startMarker = useRef(null); - const endMarker = useRef(null); - const prevMousePos = useRef({ x: 0, y: 0 }); - const { selectedEventSphere } = useSelectedEventSphere(); - const { selectedProduct } = useSelectedProduct(); - const { getVehicleById } = useVehicleStore(); - const { updateEvent } = useProductStore(); - const [startPosition, setStartPosition] = useState<[number, number, number]>([0, 0, 0]); - const [endPosition, setEndPosition] = useState<[number, number, number]>([0, 0, 0]); - const [startRotation, setStartRotation] = useState<[number, number, number]>([0, 0, 0]); - const [endRotation, setEndRotation] = useState<[number, number, number]>([0, 0, 0]); - const { isDragging, setIsDragging } = useIsDragging(); - const { isRotating, setIsRotating } = useIsRotating(); - const { raycaster } = useThree(); - const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)); - const state: Types.ThreeState = useThree(); - const controls: any = state.controls; - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - const updateBackend = ( - productName: string, - productId: string, - organization: string, - eventData: EventsSchema - ) => { - upsertProductOrEventApi({ - productName: productName, - productId: productId, - organization: organization, - eventDatas: eventData - }) - } - - useEffect(() => { - if (!selectedEventSphere) return; - const selectedVehicle = getVehicleById(selectedEventSphere.userData.modelUuid); - - if (selectedVehicle?.point?.action) { - const { pickUpPoint, unLoadPoint } = selectedVehicle.point.action; - - if (pickUpPoint) { - setStartPosition([pickUpPoint.position.x, 0, pickUpPoint.position.z]); - setStartRotation([pickUpPoint.rotation.x, pickUpPoint.rotation.y, pickUpPoint.rotation.z]); - } else { - const defaultLocal = new THREE.Vector3(0, 0, 1.5); - const defaultWorld = selectedEventSphere.localToWorld(defaultLocal); - setStartPosition([defaultWorld.x, 0, defaultWorld.z]); - setStartRotation([0, 0, 0]); - } - - if (unLoadPoint) { - setEndPosition([unLoadPoint.position.x, 0, unLoadPoint.position.z]); - setEndRotation([unLoadPoint.rotation.x, unLoadPoint.rotation.y, unLoadPoint.rotation.z]); - } else { - const defaultLocal = new THREE.Vector3(0, 0, -1.5); - const defaultWorld = selectedEventSphere.localToWorld(defaultLocal); - setEndPosition([defaultWorld.x, 0, defaultWorld.z]); - setEndRotation([0, 0, 0]); - } - } - }, [selectedEventSphere]); - - useFrame(() => { - if (!isDragging) return; - const intersectPoint = new THREE.Vector3(); - const intersects = raycaster.ray.intersectPlane(plane.current, intersectPoint); - - if (intersects) { - if (isDragging === "start") { - setStartPosition([intersectPoint.x, 0, intersectPoint.z]); - } - if (isDragging === "end") { - setEndPosition([intersectPoint.x, 0, intersectPoint.z]); - } - } - }); - - useFrame((state) => { - if (!isRotating) return; - - const currentPointerX = state.pointer.x; - const deltaX = currentPointerX - prevMousePos.current.x; - prevMousePos.current.x = currentPointerX; - - const marker = isRotating === "start" ? startMarker.current : endMarker.current; - - if (marker) { - const rotationSpeed = 10; - if (isRotating === 'start') { - const y = startRotation[1] + deltaX * rotationSpeed; - setStartRotation([0, y, 0]); - } else { - const y = endRotation[1] + deltaX * rotationSpeed; - setEndRotation([0, y, 0]); - } - } - }); - - - const handlePointerDown = (e: any, state: "start" | "end", rotation: "start" | "end") => { - - if (e.object.name === "handle") { - const normalizedX = (e.clientX / window.innerWidth) * 2 - 1; - const normalizedY = -(e.clientY / window.innerHeight) * 2 + 1; - prevMousePos.current = { x: normalizedX, y: normalizedY }; - setIsRotating(rotation); - if (controls) controls.enabled = false; - setIsDragging(null); - - } else { - setIsDragging(state); - setIsRotating(null); - if (controls) controls.enabled = false; - } - }; - - const handlePointerUp = () => { - controls.enabled = true; - setIsDragging(null); - setIsRotating(null); - - if (selectedEventSphere?.userData.modelUuid) { - const updatedVehicle = getVehicleById(selectedEventSphere.userData.modelUuid); - - if (updatedVehicle) { - const event = updateEvent(selectedProduct.productId, selectedEventSphere.userData.modelUuid, { - point: { - ...updatedVehicle.point, - action: { - ...updatedVehicle.point?.action, - pickUpPoint: { - position: { x: startPosition[0], y: startPosition[1], z: startPosition[2], }, - rotation: { x: 0, y: startRotation[1], z: 0, }, - }, - unLoadPoint: { - position: { x: endPosition[0], y: endPosition[1], z: endPosition[2], }, - rotation: { x: 0, y: endRotation[1], z: 0, }, - }, - }, - }, - }) - - if (event) { - updateBackend( - selectedProduct.productName, - selectedProduct.productId, - organization, - event - ); - } - } - } - }; - - useEffect(() => { - const handleGlobalPointerUp = () => { - setIsDragging(null); - setIsRotating(null); - if (controls) controls.enabled = true; - handlePointerUp(); - }; - - if (isDragging || isRotating) { - window.addEventListener("pointerup", handleGlobalPointerUp); - } - - return () => { - window.removeEventListener("pointerup", handleGlobalPointerUp); - }; - }, [isDragging, isRotating, startPosition, startRotation, endPosition, endRotation]); - - return ( - startPosition.length > 0 && endPosition.length > 0 ? ( - - { - e.stopPropagation(); - handlePointerDown(e, "start", "start"); - }} - onPointerMissed={() => { - controls.enabled = true; - setIsDragging(null); - setIsRotating(null); - }} - /> - - { - e.stopPropagation(); - handlePointerDown(e, "end", "end"); - }} - onPointerMissed={() => { - controls.enabled = true; - setIsDragging(null); - setIsRotating(null); - }} - /> - - ) : null - ); -} -export default VehicleUI; - - diff --git a/app/src/modules/simulation/ui3d/RoboticArmContentUi.tsx b/app/src/modules/simulation/ui3d/RoboticArmContentUi.tsx new file mode 100644 index 0000000..c85e387 --- /dev/null +++ b/app/src/modules/simulation/ui3d/RoboticArmContentUi.tsx @@ -0,0 +1,34 @@ +import { Html } from "@react-three/drei"; +import React from "react"; +import AssetDetailsCard from "../../../components/ui/simulation/AssetDetailsCard"; +import { Vector3 } from "three"; + +type VehicleContentUiProps = { + roboticArm: ArmBotStatus; +}; + +const RoboticArmContentUi: React.FC = ({ roboticArm }) => { + return ( + + + + ); +}; + +export default RoboticArmContentUi; diff --git a/app/src/modules/simulation/ui3d/VehicleContentUi.tsx b/app/src/modules/simulation/ui3d/VehicleContentUi.tsx new file mode 100644 index 0000000..0173081 --- /dev/null +++ b/app/src/modules/simulation/ui3d/VehicleContentUi.tsx @@ -0,0 +1,52 @@ +import { Html } from "@react-three/drei"; +import { Object3D, Vector3 } from "three"; +import AssetDetailsCard from "../../../components/ui/simulation/AssetDetailsCard"; +import { useFrame, useThree } from "@react-three/fiber"; +import { useState } from "react"; + +type VehicleContentUiProps = { + vehicle: VehicleStatus; +}; + +const VehicleContentUi: React.FC = ({ vehicle }) => { + const { scene } = useThree(); + const [htmlPosition, setHtmlPosition] = useState<[number, number, number]>([ + 0, 0, 0, + ]); + const offset = new Vector3(0, 0.85, 0); + useFrame(() => { + const agvModel = scene.getObjectByProperty( + "uuid", + vehicle.modelUuid + ) as Object3D; + if (agvModel) { + const worldPosition = offset.clone().applyMatrix4(agvModel.matrixWorld); + setHtmlPosition([worldPosition.x, worldPosition.y, worldPosition.z]); + } + }); + + return ( + + + + ); +}; + +export default VehicleContentUi; diff --git a/app/src/modules/simulation/vehicle/instances/animator/materialAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/materialAnimator.tsx index 4b9eb1c..0f4af22 100644 --- a/app/src/modules/simulation/vehicle/instances/animator/materialAnimator.tsx +++ b/app/src/modules/simulation/vehicle/instances/animator/materialAnimator.tsx @@ -2,7 +2,6 @@ import { useEffect, useRef, useState } from 'react'; import { useThree, useFrame } from '@react-three/fiber'; import * as THREE from 'three'; import { MaterialModel } from '../../../materials/instances/material/materialModel'; -import { Html } from '@react-three/drei'; type MaterialAnimatorProps = { agvDetail: VehicleStatus; @@ -14,8 +13,6 @@ const MaterialAnimator = ({ agvDetail }: MaterialAnimatorProps) => { const [hasLoad, setHasLoad] = useState(false); const { scene } = useThree(); const offset = new THREE.Vector3(0, 0.85, 0); - const [htmlPosition, setHtmlPosition] = useState<[number, number, number]>([0, 0, 0]); - const [htmlRotation, setHtmlRotation] = useState<[number, number, number]>([0, 0, 0]); useEffect(() => { setHasLoad(agvDetail.currentLoad > 0); @@ -28,9 +25,7 @@ const MaterialAnimator = ({ agvDetail }: MaterialAnimatorProps) => { if (agvModel) { const worldPosition = offset.clone().applyMatrix4(agvModel.matrixWorld); meshRef.current.position.copy(worldPosition); - setHtmlPosition([worldPosition.x, worldPosition.y, worldPosition.z]); meshRef.current.rotation.copy(agvModel.rotation); - setHtmlRotation([agvModel.rotation.x, agvModel.rotation.y, agvModel.rotation.z]); } }); @@ -38,19 +33,12 @@ const MaterialAnimator = ({ agvDetail }: MaterialAnimatorProps) => { <> {hasLoad && ( <> - - - - {agvDetail.currentLoad} - - + {agvDetail.currentMaterials.length > 0 && + + } )} diff --git a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx index e2e236a..ba16302 100644 --- a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx +++ b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx @@ -9,13 +9,14 @@ interface VehicleAnimatorProps { path: [number, number, number][]; handleCallBack: () => void; reset: () => void; + startUnloadingProcess: () => void; currentPhase: string; agvUuid: string; agvDetail: VehicleStatus; } -function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetail, reset }: VehicleAnimatorProps) { - const { decrementVehicleLoad, getVehicleById } = useVehicleStore(); +function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetail, reset, startUnloadingProcess }: VehicleAnimatorProps) { + const { getVehicleById } = useVehicleStore(); const { isPaused } = usePauseButtonStore(); const { isPlaying } = usePlayButtonStore(); const { speed } = useAnimationPlaySpeed(); @@ -23,32 +24,25 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai const progressRef = useRef(0); const movingForward = useRef(true); const completedRef = useRef(false); - const isPausedRef = useRef(false); - const pauseTimeRef = useRef(null); - const [progress, setProgress] = useState(0); + const [objectRotation, setObjectRotation] = useState<{ x: number; y: number; z: number } | undefined>(agvDetail.point?.action?.pickUpPoint?.rotation || { x: 0, y: 0, z: 0 }) const [restRotation, setRestingRotation] = useState(true); const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]); const { scene } = useThree(); - let startTime: number; - let fixedInterval: number; - let coveredDistance = progressRef.current; - let objectRotation = (agvDetail.point?.action?.pickUpPoint?.rotation || { x: 0, y: 0, z: 0 }) as { x: number; y: number; z: number } | undefined; useEffect(() => { if (currentPhase === 'stationed-pickup' && path.length > 0) { setCurrentPath(path); - objectRotation = agvDetail.point.action?.pickUpPoint?.rotation + setObjectRotation(agvDetail.point.action?.pickUpPoint?.rotation) } else if (currentPhase === 'pickup-drop' && path.length > 0) { - objectRotation = agvDetail.point.action?.unLoadPoint?.rotation + setObjectRotation(agvDetail.point.action?.unLoadPoint?.rotation) setCurrentPath(path); } else if (currentPhase === 'drop-pickup' && path.length > 0) { - objectRotation = agvDetail.point.action?.pickUpPoint?.rotation + setObjectRotation(agvDetail.point.action?.pickUpPoint?.rotation) setCurrentPath(path); } - }, [currentPhase, path]); + }, [currentPhase, path, objectRotation]); useEffect(() => { - setProgress(0); completedRef.current = false; }, [currentPath]); @@ -56,17 +50,11 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai if (isReset || !isPlaying) { reset(); setCurrentPath([]); - setProgress(0); completedRef.current = false; movingForward.current = true; progressRef.current = 0; - startTime = 0; - coveredDistance = 0; setReset(false); setRestingRotation(true); - decrementVehicleLoad(agvDetail.modelUuid, 0); - isPausedRef.current = false; - pauseTimeRef.current = 0; const object = scene.getObjectByProperty('uuid', agvUuid); const vehicle = getVehicleById(agvDetail.modelUuid); if (object && vehicle) { @@ -76,10 +64,6 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai } }, [isReset, isPlaying]) - useEffect(() => { - isPausedRef.current = isPaused; - }, [isPaused]); - useFrame((_, delta) => { const object = scene.getObjectByProperty('uuid', agvUuid); if (!object || currentPath.length < 2) return; @@ -98,7 +82,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai totalDistance += segmentDistance; } - while (index < distances.length && coveredDistance > accumulatedDistance + distances[index]) { + while (index < distances.length && progressRef.current > accumulatedDistance + distances[index]) { accumulatedDistance += distances[index]; index++; } @@ -124,9 +108,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai if (isAligned) { progressRef.current += delta * (speed * agvDetail.speed); - coveredDistance = progressRef.current; - - const t = (coveredDistance - accumulatedDistance) / segmentDistance; + const t = (progressRef.current - accumulatedDistance) / segmentDistance; const position = start.clone().lerp(end, t); object.position.copy(position); } @@ -134,17 +116,21 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai if (progressRef.current >= totalDistance) { if (restRotation && objectRotation) { - const targetQuaternion = new THREE.Quaternion().setFromEuler(new THREE.Euler(objectRotation.x, objectRotation.y, objectRotation.z)); + const targetEuler = new THREE.Euler( + objectRotation.x, + objectRotation.y - (agvDetail.point.action.steeringAngle), + objectRotation.z + ); + const targetQuaternion = new THREE.Quaternion().setFromEuler(targetEuler); object.quaternion.slerp(targetQuaternion, delta * 2); - const angleDiff = object.quaternion.angleTo(targetQuaternion); - if (angleDiff < 0.01) { - object.rotation.set(objectRotation.x, objectRotation.y, objectRotation.z); + if (object.quaternion.angleTo(targetQuaternion) < 0.01) { + object.quaternion.copy(targetQuaternion); + object.rotation.copy(targetEuler); setRestingRotation(false); } return; } } - if (progressRef.current >= totalDistance) { setRestingRotation(true); progressRef.current = 0; @@ -152,54 +138,15 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai setCurrentPath([]); handleCallBack(); if (currentPhase === 'pickup-drop') { - requestAnimationFrame(firstFrame); + requestAnimationFrame(startUnloadingProcess); } } }); - function firstFrame() { - const droppedMaterial = agvDetail.currentLoad; - startTime = performance.now(); - step(droppedMaterial); - } - - function step(droppedMaterial: number) { - if (isPausedRef.current) { - if (!pauseTimeRef.current) { - pauseTimeRef.current = performance.now(); - } - requestAnimationFrame(() => step(droppedMaterial)); - return; - } - - if (pauseTimeRef.current) { - const pauseDuration = performance.now() - pauseTimeRef.current; - startTime += pauseDuration; - pauseTimeRef.current = null; - } - - const elapsedTime = performance.now() - startTime; - const unLoadDuration = agvDetail.point.action.unLoadDuration; - fixedInterval = ((unLoadDuration / agvDetail.currentLoad) * (1000 / speed)); - - if (elapsedTime >= fixedInterval) { - let droppedMat = droppedMaterial - 1; - decrementVehicleLoad(agvDetail.modelUuid, 1); - if (droppedMat > 0) { - startTime = performance.now(); - requestAnimationFrame(() => step(droppedMat)); - } else { - return; - } - } else { - requestAnimationFrame(() => step(droppedMaterial)); - } - } - return ( <> {currentPath.length > 0 && ( - + {currentPath.map((point, index) => ( diff --git a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx index 2eb9e6e..a97730b 100644 --- a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx +++ b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx @@ -3,18 +3,34 @@ import VehicleAnimator from '../animator/vehicleAnimator'; import * as THREE from 'three'; import { NavMeshQuery } from '@recast-navigation/core'; import { useNavMesh } from '../../../../../store/store'; -import { usePlayButtonStore } from '../../../../../store/usePlayButtonStore'; +import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore'; import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore'; +import { useMaterialStore } from '../../../../../store/simulation/useMaterialStore'; +import { useProductStore } from '../../../../../store/simulation/useProductStore'; +import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore'; +import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler'; import MaterialAnimator from '../animator/materialAnimator'; -function VehicleInstance({ agvDetail }: { agvDetail: VehicleStatus }) { +function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) { const { navMesh } = useNavMesh(); - const vehicleRef: any = useRef(); const { isPlaying } = usePlayButtonStore(); - const { vehicles, setVehicleActive, setVehicleState, incrementVehicleLoad, setMaterialType } = useVehicleStore(); + const { removeMaterial } = useMaterialStore(); + const { triggerPointActions } = useTriggerHandler(); + const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = useProductStore(); + const { selectedProduct } = useSelectedProduct(); + const { vehicles, setVehicleActive, setVehicleState, clearCurrentMaterials, setVehicleLoad, decrementVehicleLoad, removeLastMaterial } = useVehicleStore(); const [currentPhase, setCurrentPhase] = useState('stationed'); const [path, setPath] = useState<[number, number, number][]>([]); - let isIncrememtable = useRef(true); + const pauseTimeRef = useRef(null); + const isPausedRef = useRef(false); + let startTime: number; + let fixedInterval: number; + const { speed } = useAnimationPlaySpeed(); + const { isPaused } = usePauseButtonStore(); + + useEffect(() => { + isPausedRef.current = isPaused; + }, [isPaused]); const computePath = useCallback( (start: any, end: any) => { @@ -25,6 +41,7 @@ function VehicleInstance({ agvDetail }: { agvDetail: VehicleStatus }) { segmentPath?.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [] ); } catch { + echo.error("Failed to compute path"); return []; } }, @@ -33,7 +50,6 @@ function VehicleInstance({ agvDetail }: { agvDetail: VehicleStatus }) { function vehicleStatus(modelId: string, status: string) { // console.log(`${modelId} , ${status}`); - } // Function to reset everything @@ -41,19 +57,16 @@ function VehicleInstance({ agvDetail }: { agvDetail: VehicleStatus }) { setCurrentPhase('stationed'); setVehicleActive(agvDetail.modelUuid, false); setVehicleState(agvDetail.modelUuid, 'idle'); + setVehicleLoad(agvDetail.modelUuid, 0); setPath([]); - } - - const increment = () => { - if (isIncrememtable.current) { - incrementVehicleLoad(agvDetail.modelUuid, 10); - setMaterialType(agvDetail.modelUuid, 'Material 1') - isIncrememtable.current = false; - } + startTime = 0; + isPausedRef.current = false; + pauseTimeRef.current = 0; } useEffect(() => { if (isPlaying) { + if (!agvDetail.point.action.unLoadPoint || !agvDetail.point.action.pickUpPoint) return; if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'stationed') { const toPickupPath = computePath( @@ -67,13 +80,7 @@ function VehicleInstance({ agvDetail }: { agvDetail: VehicleStatus }) { vehicleStatus(agvDetail.modelUuid, 'Started from station, heading to pickup'); return; } else if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'picking') { - - setTimeout(() => { - increment(); - }, 5000); - - - if (agvDetail.currentLoad === agvDetail.point.action.loadCapacity && agvDetail.materialType) { + if (agvDetail.currentLoad === agvDetail.point.action.loadCapacity && agvDetail.currentMaterials.length > 0) { if (agvDetail.point.action.pickUpPoint && agvDetail.point.action.unLoadPoint) { const toDrop = computePath( agvDetail.point.action.pickUpPoint.position, @@ -97,13 +104,12 @@ function VehicleInstance({ agvDetail }: { agvDetail: VehicleStatus }) { setVehicleState(agvDetail.modelUuid, 'running'); setVehicleActive(agvDetail.modelUuid, true); vehicleStatus(agvDetail.modelUuid, 'Started from dropping point, heading to pickup point'); - - isIncrememtable.current = true; } } } else { reset() } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [vehicles, currentPhase, path, isPlaying]); function handleCallBack() { @@ -124,11 +130,97 @@ function VehicleInstance({ agvDetail }: { agvDetail: VehicleStatus }) { setVehicleState(agvDetail.modelUuid, 'idle'); setVehicleActive(agvDetail.modelUuid, false); setPath([]); - setMaterialType(agvDetail.modelUuid, null) + clearCurrentMaterials(agvDetail.modelUuid) vehicleStatus(agvDetail.modelUuid, 'Reached pickup point again, cycle complete'); } } + function startUnloadingProcess() { + if (agvDetail.point.action.triggers.length > 0) { + const trigger = getTriggerByUuid(selectedProduct.productId, agvDetail.point.action.triggers[0].triggerUuid); + const model = getEventByModelUuid(selectedProduct.productId, trigger?.triggeredAsset?.triggeredModel?.modelUuid || ''); + + if (trigger && model) { + if (model.type === 'transfer') { + const action = getActionByUuid(selectedProduct.productId, agvDetail.point.action.actionUuid); + if (action) { + handleMaterialDropToConveyor(action); + } + } else if (model.type === 'machine') { + // + } else if (model.type === 'roboticArm') { + const action = getActionByUuid(selectedProduct.productId, agvDetail.point.action.actionUuid); + if (action) { + handleMaterialDropToArmBot(action); + } + } else if (model.type === 'storageUnit') { + // + } + } else { + const droppedMaterial = agvDetail.currentLoad; + startTime = performance.now(); + handleMaterialDropByDefault(droppedMaterial); + } + } else { + const droppedMaterial = agvDetail.currentLoad; + startTime = performance.now(); + handleMaterialDropByDefault(droppedMaterial); + } + } + + function handleMaterialDropToConveyor(action: Action) { + if (agvDetail.currentLoad > 1) { + // + } else if (agvDetail.currentLoad === 1 && agvDetail.currentMaterials.length === 1) { + triggerPointActions(action, agvDetail.currentMaterials[0].materialId); + decrementVehicleLoad(agvDetail.modelUuid, 1); + removeLastMaterial(agvDetail.modelUuid); + } + } + + function handleMaterialDropToArmBot(action: Action) { + if (agvDetail.currentLoad > 1) { + // + } else if (agvDetail.currentLoad === 1 && agvDetail.currentMaterials.length === 1) { + triggerPointActions(action, agvDetail.currentMaterials[0].materialId); + } + } + + function handleMaterialDropByDefault(droppedMaterial: number) { + if (isPausedRef.current) { + pauseTimeRef.current ??= performance.now(); + requestAnimationFrame(() => handleMaterialDropByDefault(droppedMaterial)); + return; + } + + if (pauseTimeRef.current) { + const pauseDuration = performance.now() - pauseTimeRef.current; + startTime += pauseDuration; + pauseTimeRef.current = null; + } + + const elapsedTime = performance.now() - startTime; + const unLoadDuration = agvDetail.point.action.unLoadDuration; + fixedInterval = ((unLoadDuration / agvDetail.currentLoad) * (1000 / speed)); + + if (elapsedTime >= fixedInterval) { + let droppedMat = droppedMaterial - 1; + decrementVehicleLoad(agvDetail.modelUuid, 1); + const materialId = removeLastMaterial(agvDetail.modelUuid); + if (materialId) { + removeMaterial(materialId); + } + if (droppedMat > 0) { + startTime = performance.now(); + requestAnimationFrame(() => handleMaterialDropByDefault(droppedMat)); + } else { + return; + } + } else { + requestAnimationFrame(() => handleMaterialDropByDefault(droppedMaterial)); + } + } + return ( <> diff --git a/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx b/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx index 7b29e2f..fa5cc03 100644 --- a/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx +++ b/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx @@ -1,20 +1,21 @@ -import React from 'react' -import VehicleInstance from './instance/vehicleInstance' -import { useVehicleStore } from '../../../../store/simulation/useVehicleStore' +import React from "react"; +import VehicleInstance from "./instance/vehicleInstance"; +import { useVehicleStore } from "../../../../store/simulation/useVehicleStore"; +import VehicleContentUi from "../../ui3d/VehicleContentUi"; function VehicleInstances() { + const { vehicles } = useVehicleStore(); - const { vehicles } = useVehicleStore(); - - return ( - <> - - {vehicles.map((vehicle: VehicleStatus) => - - )} - - - ) + return ( + <> + {vehicles.map((vehicle: VehicleStatus) => ( + + + + + ))} + + ); } -export default VehicleInstances \ No newline at end of file +export default VehicleInstances; diff --git a/app/src/modules/simulation/vehicle/navMesh/navMeshDetails.tsx b/app/src/modules/simulation/vehicle/navMesh/navMeshDetails.tsx index aee91e0..002df3f 100644 --- a/app/src/modules/simulation/vehicle/navMesh/navMeshDetails.tsx +++ b/app/src/modules/simulation/vehicle/navMesh/navMeshDetails.tsx @@ -54,7 +54,9 @@ export default function NavMeshDetails({ const debugDrawer = new DebugDrawer(); debugDrawer.drawNavMesh(navMesh); // scene.add(debugDrawer); - } catch (error) { } + } catch (error) { + echo.error("Failed to initialize navigation") + } }; initializeNavigation(); diff --git a/app/src/modules/simulation/vehicle/vehicles.tsx b/app/src/modules/simulation/vehicle/vehicles.tsx index 0b5a5a5..b9293cd 100644 --- a/app/src/modules/simulation/vehicle/vehicles.tsx +++ b/app/src/modules/simulation/vehicle/vehicles.tsx @@ -2,19 +2,15 @@ import { useEffect, useState } from "react"; import { useVehicleStore } from "../../../store/simulation/useVehicleStore"; import { useSelectedEventSphere } from "../../../store/simulation/useSimulationStore"; import { usePlayButtonStore } from "../../../store/usePlayButtonStore"; -import VehicleUI from "../ui/vehicle/vehicleUI"; import VehicleInstances from "./instances/vehicleInstances"; +import VehicleUI from "../spatialUI/vehicle/vehicleUI"; function Vehicles() { - const { vehicles, getVehicleById } = useVehicleStore(); + const { getVehicleById } = useVehicleStore(); const { selectedEventSphere } = useSelectedEventSphere(); const { isPlaying } = usePlayButtonStore(); const [isVehicleSelected, setIsVehicleSelected] = useState(false); - useEffect(() => { - // console.log('vehicles: ', vehicles); - }, [vehicles]) - useEffect(() => { if (selectedEventSphere) { const selectedVehicle = getVehicleById(selectedEventSphere.userData.modelUuid); @@ -24,19 +20,19 @@ function Vehicles() { setIsVehicleSelected(false); } } - }, [selectedEventSphere]) + }, [getVehicleById, selectedEventSphere]) return ( <> - {isVehicleSelected && !isPlaying && - < VehicleUI /> + {isVehicleSelected && selectedEventSphere && !isPlaying && + } ); } -export default Vehicles; \ No newline at end of file +export default Vehicles; diff --git a/app/src/modules/visualization/RealTimeVisulization.tsx b/app/src/modules/visualization/RealTimeVisulization.tsx index 8bf1613..23f2532 100644 --- a/app/src/modules/visualization/RealTimeVisulization.tsx +++ b/app/src/modules/visualization/RealTimeVisulization.tsx @@ -103,6 +103,7 @@ const RealTimeVisulization: React.FC = () => { ); setZonesData(formattedData); } catch (error) { + echo.error("Failed to fetch zone data"); console.log(error); } } diff --git a/app/src/modules/visualization/functions/captureVisualization.ts b/app/src/modules/visualization/functions/captureVisualization.ts index 291a002..ad66421 100644 --- a/app/src/modules/visualization/functions/captureVisualization.ts +++ b/app/src/modules/visualization/functions/captureVisualization.ts @@ -27,6 +27,7 @@ export const captureVisualization = async (): Promise => { // Convert to PNG with highest quality return canvas.toDataURL('image/png', 1.0); } catch (error) { + echo.error("Failed to capturing visualization"); console.error("Error capturing visualization:", error); return null; } diff --git a/app/src/modules/visualization/functions/handleSaveTemplate.ts b/app/src/modules/visualization/functions/handleSaveTemplate.ts index 0b67e62..2c6acfc 100644 --- a/app/src/modules/visualization/functions/handleSaveTemplate.ts +++ b/app/src/modules/visualization/functions/handleSaveTemplate.ts @@ -48,7 +48,6 @@ export const handleSaveTemplate = async ({ // Capture visualization snapshot const snapshot = await captureVisualization(); - if (!snapshot) { return; } @@ -92,6 +91,6 @@ export const handleSaveTemplate = async ({ // } } catch (error) { - // + echo.error("Failed to save template"); } }; diff --git a/app/src/modules/visualization/functions/handleUiDrop.ts b/app/src/modules/visualization/functions/handleUiDrop.ts index 0d02936..6364071 100644 --- a/app/src/modules/visualization/functions/handleUiDrop.ts +++ b/app/src/modules/visualization/functions/handleUiDrop.ts @@ -4,119 +4,120 @@ import { determinePosition } from "./determinePosition"; import { getActiveProperties } from "./getActiveProperties"; interface HandleDropProps { - widgetSubOption: any; - visualizationSocket: any; - selectedZone: any; - setFloatingWidget: (value: any) => void; - event: React.DragEvent + widgetSubOption: any; + visualizationSocket: any; + selectedZone: any; + setFloatingWidget: (value: any) => void; + event: React.DragEvent; } export const createHandleDrop = ({ - widgetSubOption, - visualizationSocket, - selectedZone, - setFloatingWidget, - event, + widgetSubOption, + visualizationSocket, + selectedZone, + setFloatingWidget, + event, }: HandleDropProps) => { - event.preventDefault(); - try { - const email = localStorage.getItem("email") ?? ""; - const organization = email?.split("@")[1]?.split(".")[0]; + event.preventDefault(); + try { + const email = localStorage.getItem("email") ?? ""; + const organization = email?.split("@")[1]?.split(".")[0]; - const data = event.dataTransfer.getData("text/plain"); - if (widgetSubOption === "3D") return; - if (!data || selectedZone.zoneName === "") return; + const data = event.dataTransfer.getData("text/plain"); + if (widgetSubOption === "3D") return; + if (!data || selectedZone.zoneName === "") return; - const droppedData = JSON.parse(data); - const canvasElement = document.getElementById("work-space-three-d-canvas"); - if (!canvasElement) throw new Error("Canvas element not found"); + const droppedData = JSON.parse(data); + const canvasElement = document.getElementById("work-space-three-d-canvas"); + if (!canvasElement) throw new Error("Canvas element not found"); - const rect = canvasElement.getBoundingClientRect(); - const relativeX = event.clientX - rect.left; - const relativeY = event.clientY - rect.top; + const rect = canvasElement.getBoundingClientRect(); + const relativeX = event.clientX - rect.left; + const relativeY = event.clientY - rect.top; - // Widget dimensions - const widgetWidth = droppedData.width ?? 125; - const widgetHeight = droppedData.height ?? 100; + // Widget dimensions + const widgetWidth = droppedData.width ?? 125; + const widgetHeight = droppedData.height ?? 100; - // Center the widget at cursor - const centerOffsetX = widgetWidth / 2; - const centerOffsetY = widgetHeight / 2; + // Center the widget at cursor + const centerOffsetX = widgetWidth / 2; + const centerOffsetY = widgetHeight / 2; - const adjustedX = relativeX - centerOffsetX; - const adjustedY = relativeY - centerOffsetY; + const adjustedX = relativeX - centerOffsetX; + const adjustedY = relativeY - centerOffsetY; - const finalPosition = determinePosition(rect, adjustedX, adjustedY); - const [activeProp1, activeProp2] = getActiveProperties(finalPosition); + const finalPosition = determinePosition(rect, adjustedX, adjustedY); + const [activeProp1, activeProp2] = getActiveProperties(finalPosition); - let finalY = 0; - let finalX = 0; + let finalY = 0; + let finalX = 0; - if (activeProp1 === "top") { - finalY = adjustedY; - } else { - finalY = rect.height - (adjustedY + widgetHeight); - } - - if (activeProp2 === "left") { - finalX = adjustedX; - } else { - finalX = rect.width - (adjustedX + widgetWidth); - } - - // Clamp to boundaries - finalX = Math.max(0, Math.min(rect.width - widgetWidth, finalX)); - finalY = Math.max(0, Math.min(rect.height - widgetHeight, finalY)); - - const boundedPosition = { - ...finalPosition, - [activeProp1]: finalY, - [activeProp2]: finalX, - [activeProp1 === "top" ? "bottom" : "top"]: "auto", - [activeProp2 === "left" ? "right" : "left"]: "auto", - }; - - const newObject = { - ...droppedData, - id: generateUniqueId(), - position: boundedPosition, - }; - - const existingZone = - useDroppedObjectsStore.getState().zones[selectedZone.zoneName]; - if (!existingZone) { - useDroppedObjectsStore - .getState() - .setZone(selectedZone.zoneName, selectedZone.zoneId); - } - - const addFloatingWidget = { - organization, - widget: newObject, - zoneId: selectedZone.zoneId, - }; - - if (visualizationSocket) { - visualizationSocket.emit("v2:viz-float:add", addFloatingWidget); - } - - useDroppedObjectsStore - .getState() - .addObject(selectedZone.zoneName, newObject); - - const droppedObjectsStore = useDroppedObjectsStore.getState(); - const currentZone = droppedObjectsStore.zones[selectedZone.zoneName]; - - if (currentZone && currentZone.zoneId === selectedZone.zoneId) { - console.log( - `Objects for Zone ${selectedZone.zoneId}:`, - currentZone.objects - ); - setFloatingWidget(currentZone.objects); - } else { - console.warn("Zone not found or zoneId mismatch"); - } - } catch (error) { - console.error("Error in handleDrop:", error); + if (activeProp1 === "top") { + finalY = adjustedY; + } else { + finalY = rect.height - (adjustedY + widgetHeight); } + + if (activeProp2 === "left") { + finalX = adjustedX; + } else { + finalX = rect.width - (adjustedX + widgetWidth); + } + + // Clamp to boundaries + finalX = Math.max(0, Math.min(rect.width - widgetWidth, finalX)); + finalY = Math.max(0, Math.min(rect.height - widgetHeight, finalY)); + + const boundedPosition = { + ...finalPosition, + [activeProp1]: finalY, + [activeProp2]: finalX, + [activeProp1 === "top" ? "bottom" : "top"]: "auto", + [activeProp2 === "left" ? "right" : "left"]: "auto", + }; + + const newObject = { + ...droppedData, + id: generateUniqueId(), + position: boundedPosition, + }; + + const existingZone = + useDroppedObjectsStore.getState().zones[selectedZone.zoneName]; + if (!existingZone) { + useDroppedObjectsStore + .getState() + .setZone(selectedZone.zoneName, selectedZone.zoneId); + } + + const addFloatingWidget = { + organization, + widget: newObject, + zoneId: selectedZone.zoneId, + }; + + if (visualizationSocket) { + visualizationSocket.emit("v2:viz-float:add", addFloatingWidget); + } + + useDroppedObjectsStore + .getState() + .addObject(selectedZone.zoneName, newObject); + + const droppedObjectsStore = useDroppedObjectsStore.getState(); + const currentZone = droppedObjectsStore.zones[selectedZone.zoneName]; + + if (currentZone && currentZone.zoneId === selectedZone.zoneId) { + console.log( + `Objects for Zone ${selectedZone.zoneId}:`, + currentZone.objects + ); + setFloatingWidget(currentZone.objects); + } else { + console.warn("Zone not found or zoneId mismatch"); + } + } catch (error) { + echo.error("Failed to drop widget"); + console.error("Error in handleDrop:", error); + } }; diff --git a/app/src/modules/visualization/template/Templates.tsx b/app/src/modules/visualization/template/Templates.tsx index 21433aa..0a79120 100644 --- a/app/src/modules/visualization/template/Templates.tsx +++ b/app/src/modules/visualization/template/Templates.tsx @@ -19,6 +19,7 @@ const Templates = () => { let response = await getTemplateData(organization); setTemplates(response); } catch (error) { + echo.error("Failed to fetching template data"); console.error("Error fetching template data:", error); } } @@ -47,6 +48,7 @@ const Templates = () => { } removeTemplate(id); } catch (error) { + echo.error("Failed to delete template"); console.error("Error deleting template:", error); } }; @@ -85,6 +87,7 @@ const Templates = () => { }); } } catch (error) { + echo.error("Failed to load template"); console.error("Error loading template:", error); } }; diff --git a/app/src/modules/visualization/widgets/2d/DraggableWidget.tsx b/app/src/modules/visualization/widgets/2d/DraggableWidget.tsx index 5972405..0b4f7c8 100644 --- a/app/src/modules/visualization/widgets/2d/DraggableWidget.tsx +++ b/app/src/modules/visualization/widgets/2d/DraggableWidget.tsx @@ -133,6 +133,7 @@ export const DraggableWidget = ({ // })); // } } catch (error) { + echo.error("Failued to dublicate widgeet"); } finally { setOpenKebabId(null); } @@ -207,6 +208,7 @@ export const DraggableWidget = ({ // })); // } } catch (error) { + echo.error("Failued to dublicate widgeet"); } finally { setOpenKebabId(null); } @@ -269,7 +271,7 @@ export const DraggableWidget = ({ // Current: Two identical useEffect hooks for canvas dimensions // Remove the duplicate and keep only one useEffect(() => { - const canvas = document.getElementById("work-space-three-d-canvas"); + const canvas = document.getElementById("real-time-vis-canvas"); if (!canvas) return; const updateCanvasDimensions = () => { diff --git a/app/src/modules/visualization/widgets/2d/charts/BarGraphComponent.tsx b/app/src/modules/visualization/widgets/2d/charts/BarGraphComponent.tsx index e68e1d3..dc96083 100644 --- a/app/src/modules/visualization/widgets/2d/charts/BarGraphComponent.tsx +++ b/app/src/modules/visualization/widgets/2d/charts/BarGraphComponent.tsx @@ -56,7 +56,7 @@ // () => themeColor[1] || "#ffffff", // [themeColor] // ); - + // // Memoize Font Weight Mapping // const chartFontWeightMap = useMemo( // () => ({ @@ -66,19 +66,19 @@ // }), // [] // ); - + // // Parse and Memoize Font Size // const fontSizeValue = useMemo( // () => (fontSize ? parseInt(fontSize) : 12), // [fontSize] // ); - + // // Determine and Memoize Font Weight // const fontWeightValue = useMemo( // () => chartFontWeightMap[fontWeight], // [fontWeight, chartFontWeightMap] // ); - + // // Memoize Chart Font Style // const chartFontStyle = useMemo( // () => ({ @@ -88,10 +88,10 @@ // }), // [fontFamily, fontSizeValue, fontWeightValue] // ); - + // // Memoize Chart Data // // const data = useMemo(() => propsData, [propsData]); - + // // Memoize Chart Options // const options = useMemo( // () => ({ @@ -183,8 +183,6 @@ // export default LineGraphComponent; - - import React, { useEffect, useMemo, useState } from "react"; import { Bar } from "react-chartjs-2"; import io from "socket.io-client"; @@ -212,19 +210,26 @@ const BarGraphComponent = ({ fontWeight = "Regular", }: ChartComponentProps) => { const { themeColor } = useThemeStore(); - const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore(); + const { + measurements: chartMeasurements, + duration: chartDuration, + name: widgetName, + } = useChartStore(); const [measurements, setmeasurements] = useState({}); - const [duration, setDuration] = useState("1h") - const [name, setName] = useState("Widget") - const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({ + const [duration, setDuration] = useState("1h"); + const [name, setName] = useState("Widget"); + const [chartData, setChartData] = useState<{ + labels: string[]; + datasets: any[]; + }>({ labels: [], datasets: [], }); - const { selectedChartId } = useWidgetStore(); + const { selectedChartId } = useWidgetStore(); const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0] + const organization = email?.split("@")[1]?.split(".")[0]; const defaultData = { labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], datasets: [ @@ -238,13 +243,17 @@ const BarGraphComponent = ({ ], }; - useEffect(() => { - - },[]) + useEffect(() => {}, []); // Memoize Theme Colors - const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]); - const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]); + const buttonActionColor = useMemo( + () => themeColor[0] || "#5c87df", + [themeColor] + ); + const buttonAbortColor = useMemo( + () => themeColor[1] || "#ffffff", + [themeColor] + ); // Memoize Font Styling const chartFontWeightMap = useMemo( @@ -256,8 +265,14 @@ const BarGraphComponent = ({ [] ); - const fontSizeValue = useMemo(() => (fontSize ? parseInt(fontSize) : 12), [fontSize]); - const fontWeightValue = useMemo(() => chartFontWeightMap[fontWeight], [fontWeight, chartFontWeightMap]); + const fontSizeValue = useMemo( + () => (fontSize ? parseInt(fontSize) : 12), + [fontSize] + ); + const fontWeightValue = useMemo( + () => chartFontWeightMap[fontWeight], + [fontWeight, chartFontWeightMap] + ); const chartFontStyle = useMemo( () => ({ @@ -268,37 +283,38 @@ const BarGraphComponent = ({ [fontFamily, fontSizeValue, fontWeightValue] ); - // Memoize Chart Options - const options = useMemo( - () => ({ - responsive: true, - maintainAspectRatio: false, - plugins: { - title: { - display: true, - text: name, - font: chartFontStyle, - }, - legend: { - display: false, + // Memoize Chart Options + const options = useMemo( + () => ({ + responsive: true, + maintainAspectRatio: false, + plugins: { + title: { + display: true, + text: name, + font: chartFontStyle, + }, + legend: { + display: false, + }, + }, + scales: { + x: { + ticks: { + display: true, // This hides the x-axis labels }, }, - scales: { - x: { - ticks: { - display: true, // This hides the x-axis labels - }, - }, - }, - }), - [title, chartFontStyle, name] - ); + }, + }), + [title, chartFontStyle, name] + ); - // useEffect(() => {console.log(measurements); - // },[measurements]) + // useEffect(() => {console.log(measurements); + // },[measurements]) useEffect(() => { - if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return; + if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) + return; const socket = io(`http://${iotApiUrl}`); @@ -308,8 +324,7 @@ const BarGraphComponent = ({ interval: 1000, }; - - const startStream = () => { + const startStream = () => { socket.emit("lineInput", inputData); }; @@ -342,23 +357,25 @@ const BarGraphComponent = ({ }; }, [measurements, duration, iotApiUrl]); - const fetchSavedInputes = async() => { - + const fetchSavedInputes = async () => { if (id !== "") { try { - const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/WidgetData/${id}/${organization}`); + const response = await axios.get( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/WidgetData/${id}/${organization}` + ); if (response.status === 200) { - setmeasurements(response.data.Data.measurements) - setDuration(response.data.Data.duration) - setName(response.data.widgetName) + setmeasurements(response.data.Data.measurements); + setDuration(response.data.Data.duration); + setName(response.data.widgetName); } else { + echo.error("Failed to fetch saved inputs"); console.log("Unexpected response:", response); } } catch (error) { console.error("There was an error!", error); } } - } + }; useEffect(() => { fetchSavedInputes(); @@ -368,10 +385,14 @@ const BarGraphComponent = ({ if (selectedChartId?.id === id) { fetchSavedInputes(); } - } - ,[chartMeasurements, chartDuration, widgetName]) + }, [chartMeasurements, chartDuration, widgetName]); - return 0 ? chartData : defaultData} options={options} />; + return ( + 0 ? chartData : defaultData} + options={options} + /> + ); }; export default BarGraphComponent; diff --git a/app/src/modules/visualization/widgets/2d/charts/DoughnutGraphComponent.tsx b/app/src/modules/visualization/widgets/2d/charts/DoughnutGraphComponent.tsx index 74d3fec..70f0783 100644 --- a/app/src/modules/visualization/widgets/2d/charts/DoughnutGraphComponent.tsx +++ b/app/src/modules/visualization/widgets/2d/charts/DoughnutGraphComponent.tsx @@ -168,6 +168,7 @@ const DoughnutGraphComponent = ({ console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } diff --git a/app/src/modules/visualization/widgets/2d/charts/LineGraphComponent.tsx b/app/src/modules/visualization/widgets/2d/charts/LineGraphComponent.tsx index 9e5d616..3a1375b 100644 --- a/app/src/modules/visualization/widgets/2d/charts/LineGraphComponent.tsx +++ b/app/src/modules/visualization/widgets/2d/charts/LineGraphComponent.tsx @@ -183,6 +183,7 @@ const LineGraphComponent = ({ setDuration(response.data.Data.duration); setName(response.data.widgetName); } else { + echo.error("Failed to fetch saved inputs"); console.log("Unexpected response:", response); } } catch (error) { diff --git a/app/src/modules/visualization/widgets/2d/charts/PieGraphComponent.tsx b/app/src/modules/visualization/widgets/2d/charts/PieGraphComponent.tsx index 931d567..e331593 100644 --- a/app/src/modules/visualization/widgets/2d/charts/PieGraphComponent.tsx +++ b/app/src/modules/visualization/widgets/2d/charts/PieGraphComponent.tsx @@ -368,6 +368,7 @@ const PieChartComponent = ({ setDuration(response.data.Data.duration); setName(response.data.widgetName); } else { + echo.error("Failed to fetch saved inputs"); console.log("Unexpected response:", response); } } catch (error) { diff --git a/app/src/modules/visualization/widgets/2d/charts/PolarAreaGraphComponent.tsx b/app/src/modules/visualization/widgets/2d/charts/PolarAreaGraphComponent.tsx index d5024d6..418b557 100644 --- a/app/src/modules/visualization/widgets/2d/charts/PolarAreaGraphComponent.tsx +++ b/app/src/modules/visualization/widgets/2d/charts/PolarAreaGraphComponent.tsx @@ -183,6 +183,7 @@ const PolarAreaGraphComponent = ({ setDuration(response.data.Data.duration); setName(response.data.widgetName); } else { + echo.error("Failed to fetch saved inputs"); console.log("Unexpected response:", response); } } catch (error) { diff --git a/app/src/modules/visualization/widgets/2d/charts/ProgressCard1.tsx b/app/src/modules/visualization/widgets/2d/charts/ProgressCard1.tsx index 5d1f59e..572adaa 100644 --- a/app/src/modules/visualization/widgets/2d/charts/ProgressCard1.tsx +++ b/app/src/modules/visualization/widgets/2d/charts/ProgressCard1.tsx @@ -63,9 +63,11 @@ const ProgressCard1 = ({ id, title }: { id: string; title: string }) => { setDuration(response.data.Data.duration); setName(response.data.widgetName); } else { + echo.error("Failed to fetch saved inputs"); console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } diff --git a/app/src/modules/visualization/widgets/2d/charts/ProgressCard2.tsx b/app/src/modules/visualization/widgets/2d/charts/ProgressCard2.tsx index 325445c..5842cf8 100644 --- a/app/src/modules/visualization/widgets/2d/charts/ProgressCard2.tsx +++ b/app/src/modules/visualization/widgets/2d/charts/ProgressCard2.tsx @@ -70,6 +70,7 @@ const ProgressCard2 = ({ id, title }: { id: string; title: string }) => { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } diff --git a/app/src/modules/visualization/widgets/3d/Dropped3dWidget.tsx b/app/src/modules/visualization/widgets/3d/Dropped3dWidget.tsx index cf4d97b..15d63b1 100644 --- a/app/src/modules/visualization/widgets/3d/Dropped3dWidget.tsx +++ b/app/src/modules/visualization/widgets/3d/Dropped3dWidget.tsx @@ -1,11 +1,22 @@ import * as THREE from "three"; import { useThree } from "@react-three/fiber"; import React, { useEffect, useRef, useState } from "react"; -import { useAsset3dWidget, useSocketStore, useWidgetSubOption } from "../../../../store/store"; +import { + useAsset3dWidget, + useSocketStore, + useWidgetSubOption, +} from "../../../../store/store"; import useModuleStore from "../../../../store/useModuleStore"; import { ThreeState } from "../../../../types/world/worldTypes"; import { useSelectedZoneStore } from "../../../../store/visualization/useZoneStore"; -import { useEditWidgetOptionsStore, useLeftData, useRightClickSelected, useRightSelected, useTopData, useZoneWidgetStore } from "../../../../store/visualization/useZone3DWidgetStore"; +import { + useEditWidgetOptionsStore, + useLeftData, + useRightClickSelected, + useRightSelected, + useTopData, + useZoneWidgetStore, +} from "../../../../store/visualization/useZone3DWidgetStore"; import { use3DWidget } from "../../../../store/visualization/useDroppedObjectsStore"; import { get3dWidgetZoneData } from "../../../../services/visulization/zone/get3dWidgetData"; import { generateUniqueId } from "../../../../functions/generateUniqueId"; @@ -17,710 +28,745 @@ import { useWidgetStore } from "../../../../store/useWidgetStore"; import useChartStore from "../../../../store/visualization/useChartStore"; type WidgetData = { - id: string; - type: string; - position: [number, number, number]; - rotation?: [number, number, number]; - tempPosition?: [number, number, number]; + id: string; + type: string; + position: [number, number, number]; + rotation?: [number, number, number]; + tempPosition?: [number, number, number]; }; export default function Dropped3dWidgets() { - const { widgetSelect } = useAsset3dWidget(); - const { activeModule } = useModuleStore(); - const { raycaster, gl, scene, mouse, camera }: ThreeState = useThree(); - const { widgetSubOption } = useWidgetSubOption(); - const { selectedZone } = useSelectedZoneStore(); - const { top, setTop } = useTopData(); - const { left, setLeft } = useLeftData(); - const { rightSelect, setRightSelect } = useRightSelected(); - const { editWidgetOptions, setEditWidgetOptions } = useEditWidgetOptionsStore(); - const { zoneWidgetData, setZoneWidgetData, addWidget, updateWidgetPosition, updateWidgetRotation, tempWidget, tempWidgetPosition } = useZoneWidgetStore(); - const { setWidgets3D } = use3DWidget(); - const { visualizationSocket } = useSocketStore(); - const { rightClickSelected, setRightClickSelected } = useRightClickSelected(); - const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)); // Floor plane for horizontal move - const verticalPlane = useRef(new THREE.Plane(new THREE.Vector3(0, 0, 1), 0)); // Vertical plane for vertical move - const planeIntersect = useRef(new THREE.Vector3()); - const rotationStartRef = useRef<[number, number, number]>([0, 0, 0]); - const mouseStartRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 }); - const { setSelectedChartId } = useWidgetStore(); - const { measurements, duration } = useChartStore(); - let [floorPlanesVertical, setFloorPlanesVertical] = useState( - new THREE.Plane(new THREE.Vector3(0, 1, 0)) - ); - const [intersectcontextmenu, setintersectcontextmenu] = useState(); - const [horizontalX, setHorizontalX] = useState(); - const [horizontalZ, setHorizontalZ] = useState(); + const { widgetSelect } = useAsset3dWidget(); + const { activeModule } = useModuleStore(); + const { raycaster, gl, scene, mouse, camera }: ThreeState = useThree(); + const { widgetSubOption } = useWidgetSubOption(); + const { selectedZone } = useSelectedZoneStore(); + const { top, setTop } = useTopData(); + const { left, setLeft } = useLeftData(); + const { rightSelect, setRightSelect } = useRightSelected(); + const { editWidgetOptions, setEditWidgetOptions } = + useEditWidgetOptionsStore(); + const { + zoneWidgetData, + setZoneWidgetData, + addWidget, + updateWidgetPosition, + updateWidgetRotation, + tempWidget, + tempWidgetPosition, + } = useZoneWidgetStore(); + const { setWidgets3D } = use3DWidget(); + const { visualizationSocket } = useSocketStore(); + const { rightClickSelected, setRightClickSelected } = useRightClickSelected(); + const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)); // Floor plane for horizontal move + const verticalPlane = useRef(new THREE.Plane(new THREE.Vector3(0, 0, 1), 0)); // Vertical plane for vertical move + const planeIntersect = useRef(new THREE.Vector3()); + const rotationStartRef = useRef<[number, number, number]>([0, 0, 0]); + const mouseStartRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 }); + const { setSelectedChartId } = useWidgetStore(); + const { measurements, duration } = useChartStore(); + let [floorPlanesVertical, setFloorPlanesVertical] = useState( + new THREE.Plane(new THREE.Vector3(0, 1, 0)) + ); + const [intersectcontextmenu, setintersectcontextmenu] = useState< + number | undefined + >(); + const [horizontalX, setHorizontalX] = useState(); + const [horizontalZ, setHorizontalZ] = useState(); - const activeZoneWidgets = zoneWidgetData[selectedZone.zoneId] || []; - useEffect(() => { - if (activeModule !== "visualization") return; - if (!selectedZone.zoneId) return; + const activeZoneWidgets = zoneWidgetData[selectedZone.zoneId] || []; + useEffect(() => { + if (activeModule !== "visualization") return; + if (!selectedZone.zoneId) return; - const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0]; + const email = localStorage.getItem("email") || ""; + const organization = email?.split("@")[1]?.split(".")[0]; - async function get3dWidgetData() { - const result = await get3dWidgetZoneData( - selectedZone.zoneId, - organization - ); + async function get3dWidgetData() { + const result = await get3dWidgetZoneData( + selectedZone.zoneId, + organization + ); - setWidgets3D(result); - if (result.length < 0) return + setWidgets3D(result); + if (result.length < 0) return; - const formattedWidgets = result?.map((widget: WidgetData) => ({ - id: widget.id, - type: widget.type, - position: widget.position, - rotation: widget.rotation || [0, 0, 0], - })); + const formattedWidgets = result?.map((widget: WidgetData) => ({ + id: widget.id, + type: widget.type, + position: widget.position, + rotation: widget.rotation || [0, 0, 0], + })); - setZoneWidgetData(selectedZone.zoneId, formattedWidgets); - } - - get3dWidgetData(); - }, [selectedZone.zoneId, activeModule]); - - const createdWidgetRef = useRef(null); - - useEffect(() => { - if (activeModule !== "visualization") return; - if (widgetSubOption === "Floating" || widgetSubOption === "2D") return; - if (selectedZone.zoneName === "") return; - - const canvasElement = document.getElementById("work-space-three-d-canvas"); - - if (!canvasElement) return; - - const hasEntered = { current: false }; - - const handleDragEnter = (event: DragEvent) => { - event.preventDefault(); - event.stopPropagation(); - - if (hasEntered.current || !widgetSelect.startsWith("ui")) return; - hasEntered.current = true; - - const group1 = scene.getObjectByName("itemsGroup"); - if (!group1) return; - - const rect = canvasElement.getBoundingClientRect(); - mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; - mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; - raycaster.setFromCamera(mouse, camera); - - const intersects = raycaster - .intersectObjects(scene.children, true) - .filter( - (intersect) => - !intersect.object.name.includes("Roof") && - !intersect.object.name.includes("agv-collider") && - !intersect.object.name.includes("MeasurementReference") && - !(intersect.object.type === "GridHelper") - ); - - if (intersects.length > 0) { - const { x, y, z } = intersects[0].point; - const newWidget: WidgetData = { - id: generateUniqueId(), - type: widgetSelect, - position: [x, y, z], - rotation: [0, 0, 0], - }; - - createdWidgetRef.current = newWidget; - tempWidget(selectedZone.zoneId, newWidget); // temp add in UI - } - }; - - const handleDragOver = (event: DragEvent) => { - event.preventDefault(); - event.stopPropagation(); - event.dataTransfer!.dropEffect = "move"; // ✅ Add this line - const widget = createdWidgetRef.current; - if (!widget) return; - - const rect = canvasElement.getBoundingClientRect(); - mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; - mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; - raycaster.setFromCamera(mouse, camera); - - const intersects = raycaster - .intersectObjects(scene.children, true) - .filter( - (intersect) => - !intersect.object.name.includes("Roof") && - !intersect.object.name.includes("agv-collider") && - !intersect.object.name.includes("MeasurementReference") && - !(intersect.object.type === "GridHelper") - ); - // Update widget's position in memory - if (intersects.length > 0) { - const { x, y, z } = intersects[0].point; - tempWidgetPosition(selectedZone.zoneId, widget.id, [x, y, z]); - widget.position = [x, y, z]; - } - - }; - - const onDrop = (event: any) => { - event.preventDefault(); - event.stopPropagation(); - - hasEntered.current = false; - - const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0]; - - const newWidget = createdWidgetRef.current; - if (!newWidget || !widgetSelect.startsWith("ui")) return; - - // ✅ Extract 2D drop position - let [x, y, z] = newWidget.position; - - // ✅ Clamp Y to at least 0 - y = Math.max(y, 0); - newWidget.position = [x, y, z]; - - // ✅ Prepare polygon from selectedZone.points - const points3D = selectedZone.points as Array<[number, number, number]>; - const zonePolygonXZ = points3D.map(([x, , z]) => [x, z] as [number, number]); - - const isInside = isPointInPolygon([x, z], zonePolygonXZ); - - // ✅ Remove temp widget - const prevWidgets = useZoneWidgetStore.getState().zoneWidgetData[selectedZone.zoneId] || []; - const cleanedWidgets = prevWidgets.filter(w => w.id !== newWidget.id); - useZoneWidgetStore.setState((state) => ({ - zoneWidgetData: { - ...state.zoneWidgetData, - [selectedZone.zoneId]: cleanedWidgets, - }, - })); - - // (Optional) Prevent adding if dropped outside zone - // if (!isInside) { - // createdWidgetRef.current = null; - // return; - // } - - // ✅ Add widget - addWidget(selectedZone.zoneId, newWidget); - - const add3dWidget = { - organization, - widget: newWidget, - zoneId: selectedZone.zoneId, - }; - - if (visualizationSocket) { - visualizationSocket.emit("v2:viz-3D-widget:add", add3dWidget); - } - - createdWidgetRef.current = null; - }; - - - - canvasElement.addEventListener("dragenter", handleDragEnter); - canvasElement.addEventListener("dragover", handleDragOver); - canvasElement.addEventListener("drop", onDrop); - - return () => { - canvasElement.removeEventListener("dragenter", handleDragEnter); - canvasElement.removeEventListener("dragover", handleDragOver); - canvasElement.removeEventListener("drop", onDrop); - }; - }, [widgetSelect, activeModule, selectedZone.zoneId, widgetSubOption, camera,]); - - useEffect(() => { - if (!rightClickSelected) return; - const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0]; - - if (rightSelect === "Duplicate") { - async function duplicateWidget() { - const widgetToDuplicate = activeZoneWidgets.find( - (w: WidgetData) => w.id === rightClickSelected - ); - console.log("3d widget to duplecate", widgetToDuplicate); - - if (!widgetToDuplicate) return; - const newWidget: any = { - id: generateUniqueId(), - type: widgetToDuplicate.type, - position: [ - widgetToDuplicate.position[0] + 0.5, - widgetToDuplicate.position[1], - widgetToDuplicate.position[2] + 0.5, - ], - rotation: widgetToDuplicate.rotation || [0, 0, 0], - Data: { - measurements: measurements, - duration: duration - }, - }; - const adding3dWidget = { - organization: organization, - widget: newWidget, - zoneId: selectedZone.zoneId, - }; - if (visualizationSocket) { - visualizationSocket.emit("v2:viz-3D-widget:add", adding3dWidget); - } - // let response = await adding3dWidgets(selectedZone.zoneId, organization, newWidget) - // - - addWidget(selectedZone.zoneId, newWidget); - setRightSelect(null); - setRightClickSelected(null); - } - duplicateWidget(); - } - - if (rightSelect === "Delete") { - const deleteWidgetApi = async () => { - try { - const deleteWidget = { - organization, - id: rightClickSelected, - zoneId: selectedZone.zoneId, - }; - - if (visualizationSocket) { - visualizationSocket.emit("v2:viz-3D-widget:delete", deleteWidget); - } - // Call the API to delete the widget - // const response = await delete3dWidgetApi(selectedZone.zoneId, organization, rightClickSelected); - setZoneWidgetData( - selectedZone.zoneId, - activeZoneWidgets.filter( - (w: WidgetData) => w.id !== rightClickSelected - ) - ); - } catch (error) { - } finally { - setRightClickSelected(null); - setRightSelect(null); - } - }; - - deleteWidgetApi(); - } - }, [rightSelect, rightClickSelected]); - - - function isPointInPolygon( - point: [number, number], - polygon: Array<[number, number]> - ): boolean { - const [x, z] = point; - let inside = false; - - for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { - const [xi, zi] = polygon[i]; - const [xj, zj] = polygon[j]; - - const intersect = - zi > z !== zj > z && - x < ((xj - xi) * (z - zi)) / (zj - zi) + xi; - - if (intersect) inside = !inside; - } - - return inside; + setZoneWidgetData(selectedZone.zoneId, formattedWidgets); } - const [prevX, setPrevX] = useState(0); - useEffect(() => { - const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0]; - const handleMouseDown = (event: MouseEvent) => { - if (!rightClickSelected || !rightSelect) return; - const selectedZoneId = Object.keys(zoneWidgetData).find( - (zoneId: string) => - zoneWidgetData[zoneId].some( - (widget: WidgetData) => widget.id === rightClickSelected - ) - ); - if (!selectedZoneId) return; - const selectedWidget = zoneWidgetData[selectedZoneId].find( - (widget: WidgetData) => widget.id === rightClickSelected - ); - if (!selectedWidget) return - // let points = []; - // points.push(new THREE.Vector3(0, 0, 0)); - // points.push(new THREE.Vector3(0, selectedWidget.position[1], 0)); - // const newgeometry = new THREE.BufferGeometry().setFromPoints(points); - // let vector = new THREE.Vector3(); - // camera.getWorldDirection(vector); - // let cameraDirection = vector; - // let newPlane = new THREE.Plane(cameraDirection); - // floorPlanesVertical = newPlane; - // setFloorPlanesVertical(newPlane); - // const intersect1 = raycaster?.ray?.intersectPlane( - // floorPlanesVertical, - // planeIntersect.current - // ); + get3dWidgetData(); + }, [selectedZone.zoneId, activeModule]); - // setintersectcontextmenu(intersect1.y); + const createdWidgetRef = useRef(null); - if (rightSelect === "RotateX" || rightSelect === "RotateY") { - mouseStartRef.current = { x: event.clientX, y: event.clientY }; + useEffect(() => { + if (activeModule !== "visualization") return; + if (widgetSubOption === "Floating" || widgetSubOption === "2D") return; + if (selectedZone.zoneName === "") return; - const selectedZoneId = Object.keys(zoneWidgetData).find( - (zoneId: string) => - zoneWidgetData[zoneId].some( - (widget: WidgetData) => widget.id === rightClickSelected - ) - ); - if (!selectedZoneId) return; - const selectedWidget = zoneWidgetData[selectedZoneId].find( - (widget: WidgetData) => widget.id === rightClickSelected - ); - if (selectedWidget) { - rotationStartRef.current = selectedWidget.rotation || [0, 0, 0]; - } - } + const canvasElement = document.getElementById("work-space-three-d-canvas"); - }; + if (!canvasElement) return; - const handleMouseMove = (event: MouseEvent) => { - if (!rightClickSelected || !rightSelect) return; - const selectedZoneId = Object.keys(zoneWidgetData).find((zoneId: string) => - zoneWidgetData[zoneId].some( - (widget: WidgetData) => widget.id === rightClickSelected - ) - ); - if (!selectedZoneId) return; + const hasEntered = { current: false }; - const selectedWidget = zoneWidgetData[selectedZoneId].find( - (widget: WidgetData) => widget.id === rightClickSelected - ); - if (!selectedWidget) return; + const handleDragEnter = (event: DragEvent) => { + event.preventDefault(); + event.stopPropagation(); - const rect = gl.domElement.getBoundingClientRect(); - mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; - mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; + if (hasEntered.current || !widgetSelect.startsWith("ui")) return; + hasEntered.current = true; - raycaster.setFromCamera(mouse, camera); + const group1 = scene.getObjectByName("itemsGroup"); + if (!group1) return; - if (rightSelect === "Horizontal Move") { - const intersect = raycaster.ray.intersectPlane(plane.current, planeIntersect.current); - if ( - intersect && - typeof horizontalX === "number" && - typeof horizontalZ === "number" - ) { - const selectedZoneId = Object.keys(zoneWidgetData).find(zoneId => - zoneWidgetData[zoneId].some(widget => widget.id === rightClickSelected) - ); - if (!selectedZoneId) return; + const rect = canvasElement.getBoundingClientRect(); + mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; + mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; + raycaster.setFromCamera(mouse, camera); - const selectedWidget = zoneWidgetData[selectedZoneId].find(widget => widget.id === rightClickSelected); - if (!selectedWidget) return; - - const newPosition: [number, number, number] = [ - intersect.x + horizontalX, - selectedWidget.position[1], - intersect.z + horizontalZ, - ]; - - - updateWidgetPosition(selectedZoneId, rightClickSelected, newPosition); - } - } - - - if (rightSelect === "Vertical Move") { - const intersect = raycaster.ray.intersectPlane(floorPlanesVertical, planeIntersect.current); - - if (intersect && typeof intersectcontextmenu === "number") { - const diff = intersect.y - intersectcontextmenu; - const unclampedY = selectedWidget.position[1] + diff; - const newY = Math.max(0, unclampedY); // Prevent going below floor (y=0) - - setintersectcontextmenu(intersect.y); - - const newPosition: [number, number, number] = [ - selectedWidget.position[0], - newY, - selectedWidget.position[2], - ]; - - updateWidgetPosition(selectedZoneId, rightClickSelected, newPosition); - } - } - - if (rightSelect?.startsWith("Rotate")) { - const axis = rightSelect.slice(-1).toLowerCase(); // "x", "y", or "z" - const currentX = event.pageX; - const sign = currentX > prevX ? 1 : currentX < prevX ? -1 : 0; - setPrevX(currentX); - if (selectedWidget?.rotation && selectedWidget.rotation.length >= 3) { - const index = axis === "x" ? 0 : axis === "y" ? 1 : 2; - const currentRotation = selectedWidget.rotation as [number, number, number]; // assert type - const newRotation: [number, number, number] = [...currentRotation]; - newRotation[index] += 0.05 * sign; - updateWidgetRotation(selectedZoneId, rightClickSelected, newRotation); - } - } - // if (rightSelect === "RotateX") { - // - // const currentX = event.pageX; - // const sign = currentX > prevX ? 1 : currentX < prevX ? -1 : 0; - // - // setPrevX(currentX); - // if (selectedWidget?.rotation && selectedWidget.rotation.length >= 3) { - // - // const newRotation: [number, number, number] = [ - // selectedWidget.rotation[0] + 0.05 * sign, - // selectedWidget.rotation[1], - // selectedWidget.rotation[2], - // ]; - // updateWidgetRotation(selectedZoneId, rightClickSelected, newRotation); - // } - // } - // if (rightSelect === "RotateY") { - // const currentX = event.pageX; - // const sign = currentX > prevX ? 1 : currentX < prevX ? -1 : 0; - // setPrevX(currentX); - // if (selectedWidget?.rotation && selectedWidget.rotation.length >= 3) { - // const newRotation: [number, number, number] = [ - // selectedWidget.rotation[0], - // selectedWidget.rotation[1] + 0.05 * sign, - // selectedWidget.rotation[2], - // ]; - - // updateWidgetRotation(selectedZoneId, rightClickSelected, newRotation); - // } - // } - // if (rightSelect === "RotateZ") { - // const currentX = event.pageX; - // const sign = currentX > prevX ? 1 : currentX < prevX ? -1 : 0; - // setPrevX(currentX); - // if (selectedWidget?.rotation && selectedWidget.rotation.length >= 3) { - // const newRotation: [number, number, number] = [ - // selectedWidget.rotation[0], - // selectedWidget.rotation[1], - // selectedWidget.rotation[2] + 0.05 * sign, - // ]; - - // updateWidgetRotation(selectedZoneId, rightClickSelected, newRotation); - // } - // } - }; - const handleMouseUp = () => { - if (!rightClickSelected || !rightSelect) return; - const selectedZoneId = Object.keys(zoneWidgetData).find((zoneId) => - zoneWidgetData[zoneId].some( - (widget) => widget.id === rightClickSelected - ) - ); - if (!selectedZoneId) return; - - const selectedWidget = zoneWidgetData[selectedZoneId].find( - (widget) => widget.id === rightClickSelected - ); - if (!selectedWidget) return; - // Format values to 2 decimal places - const formatValues = (vals: number[]) => - vals.map((val) => parseFloat(val.toFixed(2))); - if ( - rightSelect === "Horizontal Move" || - rightSelect === "Vertical Move" - ) { - let lastPosition = formatValues(selectedWidget.position) as [ - number, - number, - number - ]; - // (async () => { - // let response = await update3dWidget(selectedZoneId, organization, rightClickSelected, lastPosition); - // - // if (response) { - // - // } - // })(); - let updatingPosition = { - organization: organization, - zoneId: selectedZoneId, - id: rightClickSelected, - position: lastPosition, - }; - if (visualizationSocket) { - visualizationSocket.emit( - "v2:viz-3D-widget:modifyPositionRotation", - updatingPosition - ); - } - } else if (rightSelect.includes("Rotate")) { - const rotation = selectedWidget.rotation || [0, 0, 0]; - - let lastRotation = formatValues(rotation) as [number, number, number]; - - // (async () => { - // let response = await update3dWidgetRotation(selectedZoneId, organization, rightClickSelected, lastRotation); - // - // if (response) { - // - // } - // })(); - let updatingRotation = { - organization: organization, - zoneId: selectedZoneId, - id: rightClickSelected, - rotation: lastRotation, - }; - if (visualizationSocket) { - visualizationSocket.emit( - "v2:viz-3D-widget:modifyPositionRotation", - updatingRotation - ); - } - } - - // Reset selection - setTimeout(() => { - setRightClickSelected(null); - setRightSelect(null); - }, 50); - }; - window.addEventListener("mousedown", handleMouseDown); - window.addEventListener("mousemove", handleMouseMove); - window.addEventListener("mouseup", handleMouseUp); - - return () => { - window.removeEventListener("mousedown", handleMouseDown); - window.removeEventListener("mousemove", handleMouseMove); - window.removeEventListener("mouseup", handleMouseUp); - }; - }, [rightClickSelected, rightSelect, zoneWidgetData, gl]); - - const handleRightClick3d = (event: React.MouseEvent, id: string) => { - event.preventDefault(); - - const canvasElement = document.getElementById("work-space-three-d-canvas"); - if (!canvasElement) throw new Error("Canvas element not found"); - - const canvasRect = canvasElement.getBoundingClientRect(); - const relativeX = event.clientX - canvasRect.left; - const relativeY = event.clientY - canvasRect.top; - - setEditWidgetOptions(true); - setRightClickSelected(id); - setTop(relativeY); - setLeft(relativeX); - - const selectedZoneId = Object.keys(zoneWidgetData).find(zoneId => - zoneWidgetData[zoneId].some(widget => widget.id === id) + const intersects = raycaster + .intersectObjects(scene.children, true) + .filter( + (intersect) => + !intersect.object.name.includes("Roof") && + !intersect.object.name.includes("agv-collider") && + !intersect.object.name.includes("MeasurementReference") && + !(intersect.object.type === "GridHelper") ); - if (!selectedZoneId) return; - const selectedWidget = zoneWidgetData[selectedZoneId].find(widget => widget.id === id); - if (!selectedWidget) return; + if (intersects.length > 0) { + const { x, y, z } = intersects[0].point; + const newWidget: WidgetData = { + id: generateUniqueId(), + type: widgetSelect, + position: [x, y, z], + rotation: [0, 0, 0], + }; - const { top, left, width, height } = canvasElement.getBoundingClientRect(); - mouse.x = ((event.clientX - left) / width) * 2 - 1; - mouse.y = -((event.clientY - top) / height) * 2 + 1; - - raycaster.setFromCamera(mouse, camera); - - const cameraDirection = new THREE.Vector3(); - camera.getWorldDirection(cameraDirection); - const verticalPlane = new THREE.Plane(cameraDirection); - setFloorPlanesVertical(verticalPlane); - - const intersectPoint = raycaster.ray.intersectPlane(verticalPlane, planeIntersect.current); - if (intersectPoint) { - setintersectcontextmenu(intersectPoint.y); - } - const intersect2 = raycaster.ray.intersectPlane(plane.current, planeIntersect.current); - if (intersect2) { - const xDiff = -intersect2.x + selectedWidget.position[0]; - const zDiff = -intersect2.z + selectedWidget.position[2]; - setHorizontalX(xDiff); - setHorizontalZ(zDiff); - } + createdWidgetRef.current = newWidget; + tempWidget(selectedZone.zoneId, newWidget); // temp add in UI + } }; + const handleDragOver = (event: DragEvent) => { + event.preventDefault(); + event.stopPropagation(); + event.dataTransfer!.dropEffect = "move"; // ✅ Add this line + const widget = createdWidgetRef.current; + if (!widget) return; - return ( - <> - {activeZoneWidgets.map( - ({ id, type, position, Data, rotation = [0, 0, 0] }: any) => { - const handleRightClick = (event: React.MouseEvent, id: string) => { - setSelectedChartId({ id: id, type: type }) - event.preventDefault(); - const canvasElement = document.getElementById( - "work-space-three-d-canvas" - ); - if (!canvasElement) throw new Error("Canvas element not found"); - const canvasRect = canvasElement.getBoundingClientRect(); - const relativeX = event.clientX - canvasRect.left; - const relativeY = event.clientY - canvasRect.top; - setEditWidgetOptions(true); - setRightClickSelected(id); - setTop(relativeY); - setLeft(relativeX); - handleRightClick3d(event, id) - }; + const rect = canvasElement.getBoundingClientRect(); + mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; + mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; + raycaster.setFromCamera(mouse, camera); - switch (type) { - case "ui-Widget 1": - return ( - handleRightClick(e, id)} - /> - ); - case "ui-Widget 2": - return ( - handleRightClick(e, id)} - /> - ); - case "ui-Widget 3": - return ( - handleRightClick(e, id)} - /> - ); - case "ui-Widget 4": - return ( - handleRightClick(e, id)} - /> - ); - default: - return null; - } - } - )} - + const intersects = raycaster + .intersectObjects(scene.children, true) + .filter( + (intersect) => + !intersect.object.name.includes("Roof") && + !intersect.object.name.includes("agv-collider") && + !intersect.object.name.includes("MeasurementReference") && + !(intersect.object.type === "GridHelper") + ); + // Update widget's position in memory + if (intersects.length > 0) { + const { x, y, z } = intersects[0].point; + tempWidgetPosition(selectedZone.zoneId, widget.id, [x, y, z]); + widget.position = [x, y, z]; + } + }; + + const onDrop = (event: any) => { + event.preventDefault(); + event.stopPropagation(); + + hasEntered.current = false; + + const email = localStorage.getItem("email") || ""; + const organization = email?.split("@")[1]?.split(".")[0]; + + const newWidget = createdWidgetRef.current; + if (!newWidget || !widgetSelect.startsWith("ui")) return; + + // ✅ Extract 2D drop position + let [x, y, z] = newWidget.position; + + // ✅ Clamp Y to at least 0 + y = Math.max(y, 0); + newWidget.position = [x, y, z]; + + // ✅ Prepare polygon from selectedZone.points + const points3D = selectedZone.points as Array<[number, number, number]>; + const zonePolygonXZ = points3D.map( + ([x, , z]) => [x, z] as [number, number] + ); + + const isInside = isPointInPolygon([x, z], zonePolygonXZ); + + // ✅ Remove temp widget + const prevWidgets = + useZoneWidgetStore.getState().zoneWidgetData[selectedZone.zoneId] || []; + const cleanedWidgets = prevWidgets.filter((w) => w.id !== newWidget.id); + useZoneWidgetStore.setState((state) => ({ + zoneWidgetData: { + ...state.zoneWidgetData, + [selectedZone.zoneId]: cleanedWidgets, + }, + })); + + // (Optional) Prevent adding if dropped outside zone + // if (!isInside) { + // createdWidgetRef.current = null; + // return; + // } + + // ✅ Add widget + addWidget(selectedZone.zoneId, newWidget); + + const add3dWidget = { + organization, + widget: newWidget, + zoneId: selectedZone.zoneId, + }; + + if (visualizationSocket) { + visualizationSocket.emit("v2:viz-3D-widget:add", add3dWidget); + } + + createdWidgetRef.current = null; + }; + + canvasElement.addEventListener("dragenter", handleDragEnter); + canvasElement.addEventListener("dragover", handleDragOver); + canvasElement.addEventListener("drop", onDrop); + + return () => { + canvasElement.removeEventListener("dragenter", handleDragEnter); + canvasElement.removeEventListener("dragover", handleDragOver); + canvasElement.removeEventListener("drop", onDrop); + }; + }, [ + widgetSelect, + activeModule, + selectedZone.zoneId, + widgetSubOption, + camera, + ]); + + useEffect(() => { + if (!rightClickSelected) return; + const email = localStorage.getItem("email") || ""; + const organization = email?.split("@")[1]?.split(".")[0]; + + if (rightSelect === "Duplicate") { + async function duplicateWidget() { + const widgetToDuplicate = activeZoneWidgets.find( + (w: WidgetData) => w.id === rightClickSelected + ); + console.log("3d widget to duplecate", widgetToDuplicate); + + if (!widgetToDuplicate) return; + const newWidget: any = { + id: generateUniqueId(), + type: widgetToDuplicate.type, + position: [ + widgetToDuplicate.position[0] + 0.5, + widgetToDuplicate.position[1], + widgetToDuplicate.position[2] + 0.5, + ], + rotation: widgetToDuplicate.rotation || [0, 0, 0], + Data: { + measurements: measurements, + duration: duration, + }, + }; + const adding3dWidget = { + organization: organization, + widget: newWidget, + zoneId: selectedZone.zoneId, + }; + if (visualizationSocket) { + visualizationSocket.emit("v2:viz-3D-widget:add", adding3dWidget); + } + // let response = await adding3dWidgets(selectedZone.zoneId, organization, newWidget) + // + + addWidget(selectedZone.zoneId, newWidget); + setRightSelect(null); + setRightClickSelected(null); + } + duplicateWidget(); + } + + if (rightSelect === "Delete") { + const deleteWidgetApi = async () => { + try { + const deleteWidget = { + organization, + id: rightClickSelected, + zoneId: selectedZone.zoneId, + }; + + if (visualizationSocket) { + visualizationSocket.emit("v2:viz-3D-widget:delete", deleteWidget); + } + // Call the API to delete the widget + // const response = await delete3dWidgetApi(selectedZone.zoneId, organization, rightClickSelected); + setZoneWidgetData( + selectedZone.zoneId, + activeZoneWidgets.filter( + (w: WidgetData) => w.id !== rightClickSelected + ) + ); + } catch (error) { + echo.error("Failed to delete widget"); + } finally { + setRightClickSelected(null); + setRightSelect(null); + } + }; + + deleteWidgetApi(); + } + }, [rightSelect, rightClickSelected]); + + function isPointInPolygon( + point: [number, number], + polygon: Array<[number, number]> + ): boolean { + const [x, z] = point; + let inside = false; + + for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { + const [xi, zi] = polygon[i]; + const [xj, zj] = polygon[j]; + + const intersect = + zi > z !== zj > z && x < ((xj - xi) * (z - zi)) / (zj - zi) + xi; + + if (intersect) inside = !inside; + } + + return inside; + } + const [prevX, setPrevX] = useState(0); + + useEffect(() => { + const email = localStorage.getItem("email") || ""; + const organization = email?.split("@")[1]?.split(".")[0]; + const handleMouseDown = (event: MouseEvent) => { + if (!rightClickSelected || !rightSelect) return; + const selectedZoneId = Object.keys(zoneWidgetData).find( + (zoneId: string) => + zoneWidgetData[zoneId].some( + (widget: WidgetData) => widget.id === rightClickSelected + ) + ); + if (!selectedZoneId) return; + const selectedWidget = zoneWidgetData[selectedZoneId].find( + (widget: WidgetData) => widget.id === rightClickSelected + ); + if (!selectedWidget) return; + // let points = []; + // points.push(new THREE.Vector3(0, 0, 0)); + // points.push(new THREE.Vector3(0, selectedWidget.position[1], 0)); + // const newgeometry = new THREE.BufferGeometry().setFromPoints(points); + // let vector = new THREE.Vector3(); + // camera.getWorldDirection(vector); + // let cameraDirection = vector; + // let newPlane = new THREE.Plane(cameraDirection); + // floorPlanesVertical = newPlane; + // setFloorPlanesVertical(newPlane); + // const intersect1 = raycaster?.ray?.intersectPlane( + // floorPlanesVertical, + // planeIntersect.current + // ); + + // setintersectcontextmenu(intersect1.y); + + if (rightSelect === "RotateX" || rightSelect === "RotateY") { + mouseStartRef.current = { x: event.clientX, y: event.clientY }; + + const selectedZoneId = Object.keys(zoneWidgetData).find( + (zoneId: string) => + zoneWidgetData[zoneId].some( + (widget: WidgetData) => widget.id === rightClickSelected + ) + ); + if (!selectedZoneId) return; + const selectedWidget = zoneWidgetData[selectedZoneId].find( + (widget: WidgetData) => widget.id === rightClickSelected + ); + if (selectedWidget) { + rotationStartRef.current = selectedWidget.rotation || [0, 0, 0]; + } + } + }; + + const handleMouseMove = (event: MouseEvent) => { + if (!rightClickSelected || !rightSelect) return; + const selectedZoneId = Object.keys(zoneWidgetData).find( + (zoneId: string) => + zoneWidgetData[zoneId].some( + (widget: WidgetData) => widget.id === rightClickSelected + ) + ); + if (!selectedZoneId) return; + + const selectedWidget = zoneWidgetData[selectedZoneId].find( + (widget: WidgetData) => widget.id === rightClickSelected + ); + if (!selectedWidget) return; + + const rect = gl.domElement.getBoundingClientRect(); + mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; + mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; + + raycaster.setFromCamera(mouse, camera); + + if (rightSelect === "Horizontal Move") { + const intersect = raycaster.ray.intersectPlane( + plane.current, + planeIntersect.current + ); + if ( + intersect && + typeof horizontalX === "number" && + typeof horizontalZ === "number" + ) { + const selectedZoneId = Object.keys(zoneWidgetData).find((zoneId) => + zoneWidgetData[zoneId].some( + (widget) => widget.id === rightClickSelected + ) + ); + if (!selectedZoneId) return; + + const selectedWidget = zoneWidgetData[selectedZoneId].find( + (widget) => widget.id === rightClickSelected + ); + if (!selectedWidget) return; + + const newPosition: [number, number, number] = [ + intersect.x + horizontalX, + selectedWidget.position[1], + intersect.z + horizontalZ, + ]; + + updateWidgetPosition(selectedZoneId, rightClickSelected, newPosition); + } + } + + if (rightSelect === "Vertical Move") { + const intersect = raycaster.ray.intersectPlane( + floorPlanesVertical, + planeIntersect.current + ); + + if (intersect && typeof intersectcontextmenu === "number") { + const diff = intersect.y - intersectcontextmenu; + const unclampedY = selectedWidget.position[1] + diff; + const newY = Math.max(0, unclampedY); // Prevent going below floor (y=0) + + setintersectcontextmenu(intersect.y); + + const newPosition: [number, number, number] = [ + selectedWidget.position[0], + newY, + selectedWidget.position[2], + ]; + + updateWidgetPosition(selectedZoneId, rightClickSelected, newPosition); + } + } + + if (rightSelect?.startsWith("Rotate")) { + const axis = rightSelect.slice(-1).toLowerCase(); // "x", "y", or "z" + const currentX = event.pageX; + const sign = currentX > prevX ? 1 : currentX < prevX ? -1 : 0; + setPrevX(currentX); + if (selectedWidget?.rotation && selectedWidget.rotation.length >= 3) { + const index = axis === "x" ? 0 : axis === "y" ? 1 : 2; + const currentRotation = selectedWidget.rotation as [ + number, + number, + number + ]; // assert type + const newRotation: [number, number, number] = [...currentRotation]; + newRotation[index] += 0.05 * sign; + updateWidgetRotation(selectedZoneId, rightClickSelected, newRotation); + } + } + // if (rightSelect === "RotateX") { + // + // const currentX = event.pageX; + // const sign = currentX > prevX ? 1 : currentX < prevX ? -1 : 0; + // + // setPrevX(currentX); + // if (selectedWidget?.rotation && selectedWidget.rotation.length >= 3) { + // + // const newRotation: [number, number, number] = [ + // selectedWidget.rotation[0] + 0.05 * sign, + // selectedWidget.rotation[1], + // selectedWidget.rotation[2], + // ]; + // updateWidgetRotation(selectedZoneId, rightClickSelected, newRotation); + // } + // } + // if (rightSelect === "RotateY") { + // const currentX = event.pageX; + // const sign = currentX > prevX ? 1 : currentX < prevX ? -1 : 0; + // setPrevX(currentX); + // if (selectedWidget?.rotation && selectedWidget.rotation.length >= 3) { + // const newRotation: [number, number, number] = [ + // selectedWidget.rotation[0], + // selectedWidget.rotation[1] + 0.05 * sign, + // selectedWidget.rotation[2], + // ]; + + // updateWidgetRotation(selectedZoneId, rightClickSelected, newRotation); + // } + // } + // if (rightSelect === "RotateZ") { + // const currentX = event.pageX; + // const sign = currentX > prevX ? 1 : currentX < prevX ? -1 : 0; + // setPrevX(currentX); + // if (selectedWidget?.rotation && selectedWidget.rotation.length >= 3) { + // const newRotation: [number, number, number] = [ + // selectedWidget.rotation[0], + // selectedWidget.rotation[1], + // selectedWidget.rotation[2] + 0.05 * sign, + // ]; + + // updateWidgetRotation(selectedZoneId, rightClickSelected, newRotation); + // } + // } + }; + const handleMouseUp = () => { + if (!rightClickSelected || !rightSelect) return; + const selectedZoneId = Object.keys(zoneWidgetData).find((zoneId) => + zoneWidgetData[zoneId].some( + (widget) => widget.id === rightClickSelected + ) + ); + if (!selectedZoneId) return; + + const selectedWidget = zoneWidgetData[selectedZoneId].find( + (widget) => widget.id === rightClickSelected + ); + if (!selectedWidget) return; + // Format values to 2 decimal places + const formatValues = (vals: number[]) => + vals.map((val) => parseFloat(val.toFixed(2))); + if ( + rightSelect === "Horizontal Move" || + rightSelect === "Vertical Move" + ) { + let lastPosition = formatValues(selectedWidget.position) as [ + number, + number, + number + ]; + // (async () => { + // let response = await update3dWidget(selectedZoneId, organization, rightClickSelected, lastPosition); + // + // if (response) { + // + // } + // })(); + let updatingPosition = { + organization: organization, + zoneId: selectedZoneId, + id: rightClickSelected, + position: lastPosition, + }; + if (visualizationSocket) { + visualizationSocket.emit( + "v2:viz-3D-widget:modifyPositionRotation", + updatingPosition + ); + } + } else if (rightSelect.includes("Rotate")) { + const rotation = selectedWidget.rotation || [0, 0, 0]; + + let lastRotation = formatValues(rotation) as [number, number, number]; + + // (async () => { + // let response = await update3dWidgetRotation(selectedZoneId, organization, rightClickSelected, lastRotation); + // + // if (response) { + // + // } + // })(); + let updatingRotation = { + organization: organization, + zoneId: selectedZoneId, + id: rightClickSelected, + rotation: lastRotation, + }; + if (visualizationSocket) { + visualizationSocket.emit( + "v2:viz-3D-widget:modifyPositionRotation", + updatingRotation + ); + } + } + + // Reset selection + setTimeout(() => { + setRightClickSelected(null); + setRightSelect(null); + }, 50); + }; + window.addEventListener("mousedown", handleMouseDown); + window.addEventListener("mousemove", handleMouseMove); + window.addEventListener("mouseup", handleMouseUp); + + return () => { + window.removeEventListener("mousedown", handleMouseDown); + window.removeEventListener("mousemove", handleMouseMove); + window.removeEventListener("mouseup", handleMouseUp); + }; + }, [rightClickSelected, rightSelect, zoneWidgetData, gl]); + + const handleRightClick3d = (event: React.MouseEvent, id: string) => { + event.preventDefault(); + + const canvasElement = document.getElementById("work-space-three-d-canvas"); + if (!canvasElement) throw new Error("Canvas element not found"); + + const canvasRect = canvasElement.getBoundingClientRect(); + const relativeX = event.clientX - canvasRect.left; + const relativeY = event.clientY - canvasRect.top; + + setEditWidgetOptions(true); + setRightClickSelected(id); + setTop(relativeY); + setLeft(relativeX); + + const selectedZoneId = Object.keys(zoneWidgetData).find((zoneId) => + zoneWidgetData[zoneId].some((widget) => widget.id === id) ); + if (!selectedZoneId) return; + + const selectedWidget = zoneWidgetData[selectedZoneId].find( + (widget) => widget.id === id + ); + if (!selectedWidget) return; + + const { top, left, width, height } = canvasElement.getBoundingClientRect(); + mouse.x = ((event.clientX - left) / width) * 2 - 1; + mouse.y = -((event.clientY - top) / height) * 2 + 1; + + raycaster.setFromCamera(mouse, camera); + + const cameraDirection = new THREE.Vector3(); + camera.getWorldDirection(cameraDirection); + const verticalPlane = new THREE.Plane(cameraDirection); + setFloorPlanesVertical(verticalPlane); + + const intersectPoint = raycaster.ray.intersectPlane( + verticalPlane, + planeIntersect.current + ); + if (intersectPoint) { + setintersectcontextmenu(intersectPoint.y); + } + const intersect2 = raycaster.ray.intersectPlane( + plane.current, + planeIntersect.current + ); + if (intersect2) { + const xDiff = -intersect2.x + selectedWidget.position[0]; + const zDiff = -intersect2.z + selectedWidget.position[2]; + setHorizontalX(xDiff); + setHorizontalZ(zDiff); + } + }; + + return ( + <> + {activeZoneWidgets.map( + ({ id, type, position, Data, rotation = [0, 0, 0] }: any) => { + const handleRightClick = (event: React.MouseEvent, id: string) => { + setSelectedChartId({ id: id, type: type }); + event.preventDefault(); + const canvasElement = document.getElementById( + "work-space-three-d-canvas" + ); + if (!canvasElement) throw new Error("Canvas element not found"); + const canvasRect = canvasElement.getBoundingClientRect(); + const relativeX = event.clientX - canvasRect.left; + const relativeY = event.clientY - canvasRect.top; + setEditWidgetOptions(true); + setRightClickSelected(id); + setTop(relativeY); + setLeft(relativeX); + handleRightClick3d(event, id); + }; + + switch (type) { + case "ui-Widget 1": + return ( + handleRightClick(e, id)} + /> + ); + case "ui-Widget 2": + return ( + handleRightClick(e, id)} + /> + ); + case "ui-Widget 3": + return ( + handleRightClick(e, id)} + /> + ); + case "ui-Widget 4": + return ( + handleRightClick(e, id)} + /> + ); + default: + return null; + } + } + )} + + ); } diff --git a/app/src/modules/visualization/widgets/3d/cards/ProductionCapacity.tsx b/app/src/modules/visualization/widgets/3d/cards/ProductionCapacity.tsx index 6666452..53cc473 100644 --- a/app/src/modules/visualization/widgets/3d/cards/ProductionCapacity.tsx +++ b/app/src/modules/visualization/widgets/3d/cards/ProductionCapacity.tsx @@ -31,7 +31,7 @@ interface ProductionCapacityProps { type: string; position: [number, number, number]; rotation: [number, number, number]; - Data?: any, + Data?: any; onContextMenu?: (event: React.MouseEvent) => void; // onPointerDown:any } @@ -50,8 +50,12 @@ const ProductionCapacity: React.FC = ({ duration: chartDuration, name: widgetName, } = useChartStore(); - const [measurements, setmeasurements] = useState(Data?.measurements ? Data.measurements : {}); - const [duration, setDuration] = useState(Data?.duration ? Data.duration : "1h"); + const [measurements, setmeasurements] = useState( + Data?.measurements ? Data.measurements : {} + ); + const [duration, setDuration] = useState( + Data?.duration ? Data.duration : "1h" + ); const [name, setName] = useState("Widget"); const [chartData, setChartData] = useState<{ labels: string[]; @@ -175,7 +179,9 @@ const ProductionCapacity: React.FC = ({ setName(response.data.widgetName); } else { } - } catch (error) { } + } catch (error) { + echo.error("Failed to fetch saved inputs"); + } } }; @@ -189,12 +195,9 @@ const ProductionCapacity: React.FC = ({ } }, [chartMeasurements, chartDuration, widgetName]); - useEffect(() => { }, [rotation]); - - + useEffect(() => {}, [rotation]); return ( - = ({ // e.stopPropagation(); }} wrapperClass="pointer-none" - >
setSelectedChartId({ id: id, type: type })} onContextMenu={onContextMenu} - style={{ width: "300px", // Original width height: "300px", // Original height // transform: transformStyle.transform, transformStyle: "preserve-3d", position: "absolute", - transform:'translate(-50%, -50%)', + transform: "translate(-50%, -50%)", }} >
@@ -263,7 +266,6 @@ const ProductionCapacity: React.FC = ({
- ); }; diff --git a/app/src/modules/visualization/widgets/3d/cards/ReturnOfInvestment.tsx b/app/src/modules/visualization/widgets/3d/cards/ReturnOfInvestment.tsx index 6aeafa6..5e638cf 100644 --- a/app/src/modules/visualization/widgets/3d/cards/ReturnOfInvestment.tsx +++ b/app/src/modules/visualization/widgets/3d/cards/ReturnOfInvestment.tsx @@ -12,7 +12,6 @@ import { ChartOptions, } from "chart.js"; - import axios from "axios"; import io from "socket.io-client"; import { useWidgetStore } from "../../../../../store/useWidgetStore"; @@ -63,8 +62,12 @@ const ReturnOfInvestment: React.FC = ({ duration: chartDuration, name: widgetName, } = useChartStore(); - const [measurements, setmeasurements] = useState(Data?.measurements ? Data.measurements : {}); - const [duration, setDuration] = useState(Data?.duration ? Data.duration : "1h"); + const [measurements, setmeasurements] = useState( + Data?.measurements ? Data.measurements : {} + ); + const [duration, setDuration] = useState( + Data?.duration ? Data.duration : "1h" + ); const [name, setName] = useState("Widget"); const [chartData, setChartData] = useState<{ labels: string[]; @@ -208,6 +211,7 @@ const ReturnOfInvestment: React.FC = ({ console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } @@ -238,8 +242,7 @@ const ReturnOfInvestment: React.FC = ({ rotation={rotation} scale={[0.5, 0.5, 0.5]} transform - - sprite={false} + sprite={false} // style={{ // transform: transformStyle.transform, // transformStyle: "preserve-3d", diff --git a/app/src/modules/visualization/widgets/3d/cards/StateWorking.tsx b/app/src/modules/visualization/widgets/3d/cards/StateWorking.tsx index 048dd7d..d5cc07e 100644 --- a/app/src/modules/visualization/widgets/3d/cards/StateWorking.tsx +++ b/app/src/modules/visualization/widgets/3d/cards/StateWorking.tsx @@ -12,7 +12,7 @@ interface StateWorkingProps { type: string; position: [number, number, number]; rotation: [number, number, number]; - Data?:any; + Data?: any; onContextMenu?: (event: React.MouseEvent) => void; } const StateWorking: React.FC = ({ @@ -29,8 +29,12 @@ const StateWorking: React.FC = ({ duration: chartDuration, name: widgetName, } = useChartStore(); - const [measurements, setmeasurements] = useState(Data?.measurements ? Data.measurements : {}); - const [duration, setDuration] = useState(Data?.duration ? Data.duration : "1h"); + const [measurements, setmeasurements] = useState( + Data?.measurements ? Data.measurements : {} + ); + const [duration, setDuration] = useState( + Data?.duration ? Data.duration : "1h" + ); const [name, setName] = useState("Widget"); const [datas, setDatas] = useState({}); const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; @@ -85,6 +89,7 @@ const StateWorking: React.FC = ({ console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } @@ -116,7 +121,7 @@ const StateWorking: React.FC = ({ scale={[0.5, 0.5, 0.5]} transform zIndexRange={[1, 0]} - sprite={false} + sprite={false} // style={{ // transform: transformStyle.transform, // transformStyle: "preserve-3d", diff --git a/app/src/modules/visualization/widgets/3d/cards/Throughput.tsx b/app/src/modules/visualization/widgets/3d/cards/Throughput.tsx index 857813c..18edb61 100644 --- a/app/src/modules/visualization/widgets/3d/cards/Throughput.tsx +++ b/app/src/modules/visualization/widgets/3d/cards/Throughput.tsx @@ -14,7 +14,6 @@ import { ChartOptions, } from "chart.js"; - import axios from "axios"; import io from "socket.io-client"; import { useWidgetStore } from "../../../../../store/useWidgetStore"; @@ -48,7 +47,7 @@ interface ThroughputProps { type: string; position: [number, number, number]; rotation: [number, number, number]; - Data?:any; + Data?: any; onContextMenu?: (event: React.MouseEvent) => void; } @@ -66,8 +65,12 @@ const Throughput: React.FC = ({ duration: chartDuration, name: widgetName, } = useChartStore(); - const [measurements, setmeasurements] = useState(Data?.measurements ? Data.measurements : {}); - const [duration, setDuration] = useState(Data?.duration ? Data.duration : "1h"); + const [measurements, setmeasurements] = useState( + Data?.measurements ? Data.measurements : {} + ); + const [duration, setDuration] = useState( + Data?.duration ? Data.duration : "1h" + ); const [name, setName] = useState("Widget"); const [chartData, setChartData] = useState<{ labels: string[]; @@ -186,6 +189,7 @@ const Throughput: React.FC = ({ console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } @@ -217,7 +221,7 @@ const Throughput: React.FC = ({ scale={[0.5, 0.5, 0.5]} transform zIndexRange={[1, 0]} - sprite={false} + sprite={false} // style={{ // transform: transformStyle.transform, // transformStyle: "preserve-3d", diff --git a/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx b/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx index 5e26975..14bba3c 100644 --- a/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx +++ b/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx @@ -1,7 +1,5 @@ import { useEffect, useRef, useState } from "react"; -import { - useDroppedObjectsStore, -} from "../../../../store/visualization/useDroppedObjectsStore"; +import { useDroppedObjectsStore } from "../../../../store/visualization/useDroppedObjectsStore"; import useModuleStore from "../../../../store/useModuleStore"; import { determinePosition } from "../../functions/determinePosition"; import { getActiveProperties } from "../../functions/getActiveProperties"; @@ -132,8 +130,9 @@ const DroppedObjects: React.FC = () => { visualizationSocket.emit("v2:viz-float:delete", deleteFloatingWidget); } deleteObject(zoneName, id); - - } catch (error) {} + } catch (error) { + echo.error("Failed to delete widget"); + } } const handlePointerDown = (event: React.PointerEvent, index: number) => { @@ -308,6 +307,7 @@ const DroppedObjects: React.FC = () => { updateObjectPosition(zoneName, draggingIndex.index, boundedPosition); } } catch (error) { + echo.error("Failed to add widget"); console.log(error); } finally { setDraggingIndex(null); @@ -380,7 +380,6 @@ const DroppedObjects: React.FC = () => { setCurrentPosition(newPosition); // Update position immediately without animation frame updateObjectPosition(zoneName, draggingIndex.index, newPosition); - }; const handlePointerUp = async (event: React.PointerEvent) => { @@ -446,6 +445,7 @@ const DroppedObjects: React.FC = () => { updateObjectPosition(zoneName, draggingIndex.index, boundedPosition); } catch (error) { + echo.error("Failed to add widget"); console.log(error); } finally { // Clean up regardless of success or failure diff --git a/app/src/modules/visualization/widgets/floating/cards/FleetEfficiencyComponent.tsx b/app/src/modules/visualization/widgets/floating/cards/FleetEfficiencyComponent.tsx index bdaf648..4115709 100644 --- a/app/src/modules/visualization/widgets/floating/cards/FleetEfficiencyComponent.tsx +++ b/app/src/modules/visualization/widgets/floating/cards/FleetEfficiencyComponent.tsx @@ -71,6 +71,7 @@ const FleetEfficiencyComponent = ({ object }: any) => { console.log("Unexpected response:", response); } } catch (error) { + echo.error("Failed to fetch saved inputs"); console.error("There was an error!", error); } } diff --git a/app/src/modules/visualization/widgets/floating/cards/TotalCardComponent.tsx b/app/src/modules/visualization/widgets/floating/cards/TotalCardComponent.tsx index 61096c5..72825e7 100644 --- a/app/src/modules/visualization/widgets/floating/cards/TotalCardComponent.tsx +++ b/app/src/modules/visualization/widgets/floating/cards/TotalCardComponent.tsx @@ -67,6 +67,7 @@ const TotalCardComponent = ({ object }: any) => { setDuration(response.data.Data.duration); setName(response.data.header); } else { + echo.error("Failed to fetch saved inputs"); } } catch (error) {} } diff --git a/app/src/modules/visualization/widgets/floating/cards/WarehouseThroughputComponent.tsx b/app/src/modules/visualization/widgets/floating/cards/WarehouseThroughputComponent.tsx index 67793f9..fbc6eb6 100644 --- a/app/src/modules/visualization/widgets/floating/cards/WarehouseThroughputComponent.tsx +++ b/app/src/modules/visualization/widgets/floating/cards/WarehouseThroughputComponent.tsx @@ -1,205 +1,209 @@ -import React, { useState, useEffect } from 'react' -import { Line } from 'react-chartjs-2' -import useChartStore from '../../../../../store/visualization/useChartStore'; -import { useWidgetStore } from '../../../../../store/useWidgetStore'; -import axios from 'axios'; +import React, { useState, useEffect } from "react"; +import { Line } from "react-chartjs-2"; +import useChartStore from "../../../../../store/visualization/useChartStore"; +import { useWidgetStore } from "../../../../../store/useWidgetStore"; +import axios from "axios"; import io from "socket.io-client"; -const WarehouseThroughputComponent = ({ - object -}: any) => { +const WarehouseThroughputComponent = ({ object }: any) => { + const [measurements, setmeasurements] = useState({}); + const [duration, setDuration] = useState("1h"); + const [name, setName] = useState(object.header ? object.header : ""); + const [chartData, setChartData] = useState<{ + labels: string[]; + datasets: any[]; + }>({ + labels: [], + datasets: [], + }); + const email = localStorage.getItem("email") || ""; + const organization = email?.split("@")[1]?.split(".")[0]; + const { header, flotingDuration, flotingMeasurements } = useChartStore(); + const { selectedChartId } = useWidgetStore(); - const [measurements, setmeasurements] = useState({}); - const [duration, setDuration] = useState("1h") - const [name, setName] = useState(object.header ? object.header : '') - const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({ - labels: [], - datasets: [], + const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; + + const lineGraphData = { + labels: [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ], // Months of the year + datasets: [ + { + label: "Throughput (units/month)", + data: [500, 400, 300, 450, 350, 250, 200, 300, 250, 150, 100, 150], // Example monthly data + borderColor: "#6f42c1", // Use the desired color for the line (purple) + backgroundColor: "rgba(111, 66, 193, 0.2)", // Use a semi-transparent purple for the fill + borderWidth: 2, // Line thickness + fill: true, // Enable fill for this dataset + pointRadius: 0, // Remove dots at each data point + tension: 0.5, // Smooth interpolation for the line + }, + ], + }; + + // Line graph options + const lineGraphOptions = { + responsive: true, + maintainAspectRatio: false, // Allow custom height/width adjustments + plugins: { + legend: { + display: false, // Hide legend + }, + title: { + display: false, // No chart title needed + }, + tooltip: { + callbacks: { + label: (context: any) => { + const value = context.parsed.y; + return `${value} units`; // Customize tooltip to display "units" + }, + }, + }, + }, + scales: { + x: { + grid: { + display: false, // Hide x-axis grid lines + }, + ticks: { + maxRotation: 0, // Prevent label rotation + autoSkip: false, // Display all months + font: { + size: 8, // Adjust font size for readability + color: "#ffffff", // Light text color for labels + }, + }, + }, + y: { + display: true, // Show y-axis + grid: { + drawBorder: false, // Remove border line + color: "rgba(255, 255, 255, 0.2)", // Light gray color for grid lines + borderDash: [5, 5], // Dotted line style (array defines dash and gap lengths) + }, + ticks: { + font: { + size: 8, // Adjust font size for readability + color: "#ffffff", // Light text color for ticks + }, + }, + }, + }, + elements: { + line: { + tension: 0.5, // Smooth interpolation for the line + }, + }, + }; + + useEffect(() => { + if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) + return; + + const socket = io(`http://${iotApiUrl}`); + + const inputData = { + measurements, + duration, + interval: 1000, + }; + + const startStream = () => { + socket.emit("lineInput", inputData); + }; + + socket.on("connect", startStream); + + socket.on("lineOutput", (response) => { + const responseData = response.data; + + // Extract timestamps and values + const labels = responseData.time; + const datasets = Object.keys(measurements).map((key) => { + const measurement = measurements[key]; + const datasetKey = `${measurement.name}.${measurement.fields}`; + return { + label: datasetKey, + data: responseData[datasetKey]?.values ?? [], + borderColor: "#6f42c1", // Use the desired color for the line (purple) + backgroundColor: "rgba(111, 66, 193, 0.2)", // Use a semi-transparent purple for the fill + borderWidth: 2, // Line thickness + fill: true, // Enable fill for this dataset + pointRadius: 0, // Remove dots at each data point + tension: 0.5, // Smooth interpolation for the line + }; + }); + + setChartData({ labels, datasets }); }); - const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0] - const { header, flotingDuration, flotingMeasurements } = useChartStore(); - const { selectedChartId } = useWidgetStore(); - const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; + return () => { + socket.off("lineOutput"); + socket.emit("stop_stream"); // Stop streaming when component unmounts + socket.disconnect(); + }; + }, [measurements, duration, iotApiUrl]); - const lineGraphData = { - labels: [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ], // Months of the year - datasets: [ - { - label: "Throughput (units/month)", - data: [500, 400, 300, 450, 350, 250, 200, 300, 250, 150, 100, 150], // Example monthly data - borderColor: "#6f42c1", // Use the desired color for the line (purple) - backgroundColor: "rgba(111, 66, 193, 0.2)", // Use a semi-transparent purple for the fill - borderWidth: 2, // Line thickness - fill: true, // Enable fill for this dataset - pointRadius: 0, // Remove dots at each data point - tension: 0.5, // Smooth interpolation for the line - }, - ], - }; - - // Line graph options - const lineGraphOptions = { - responsive: true, - maintainAspectRatio: false, // Allow custom height/width adjustments - plugins: { - legend: { - display: false, // Hide legend - }, - title: { - display: false, // No chart title needed - }, - tooltip: { - callbacks: { - label: (context: any) => { - const value = context.parsed.y; - return `${value} units`; // Customize tooltip to display "units" - }, - }, - }, - }, - scales: { - x: { - grid: { - display: false, // Hide x-axis grid lines - }, - ticks: { - maxRotation: 0, // Prevent label rotation - autoSkip: false, // Display all months - font: { - size: 8, // Adjust font size for readability - color: "#ffffff", // Light text color for labels - }, - }, - }, - y: { - display: true, // Show y-axis - grid: { - drawBorder: false, // Remove border line - color: "rgba(255, 255, 255, 0.2)", // Light gray color for grid lines - borderDash: [5, 5], // Dotted line style (array defines dash and gap lengths) - }, - ticks: { - font: { - size: 8, // Adjust font size for readability - color: "#ffffff", // Light text color for ticks - }, - }, - }, - }, - elements: { - line: { - tension: 0.5, // Smooth interpolation for the line - }, - }, - }; - - - useEffect(() => { - if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return; - - const socket = io(`http://${iotApiUrl}`); - - const inputData = { - measurements, - duration, - interval: 1000, - }; - - - const startStream = () => { - socket.emit("lineInput", inputData); - }; - - socket.on("connect", startStream); - - socket.on("lineOutput", (response) => { - const responseData = response.data; - - // Extract timestamps and values - const labels = responseData.time; - const datasets = Object.keys(measurements).map((key) => { - const measurement = measurements[key]; - const datasetKey = `${measurement.name}.${measurement.fields}`; - return { - label: datasetKey, - data: responseData[datasetKey]?.values ?? [], - borderColor: "#6f42c1", // Use the desired color for the line (purple) - backgroundColor: "rgba(111, 66, 193, 0.2)", // Use a semi-transparent purple for the fill - borderWidth: 2, // Line thickness - fill: true, // Enable fill for this dataset - pointRadius: 0, // Remove dots at each data point - tension: 0.5, // Smooth interpolation for the line - }; - }); - - setChartData({ labels, datasets }); - }); - - return () => { - socket.off("lineOutput"); - socket.emit("stop_stream"); // Stop streaming when component unmounts - socket.disconnect(); - }; - }, [measurements, duration, iotApiUrl]); - - const fetchSavedInputes = async() => { - - if (object?.id !== "") { - try { - const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/A_floatWidget/${object?.id}/${organization}`); - if (response.status === 200) { - setmeasurements(response.data.Data.measurements) - setDuration(response.data.Data.duration) - setName(response.data.header) - } else { - console.log("Unexpected response:", response); - } - } catch (error) { - console.error("There was an error!", error); - } + const fetchSavedInputes = async () => { + if (object?.id !== "") { + try { + const response = await axios.get( + `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/A_floatWidget/${object?.id}/${organization}` + ); + if (response.status === 200) { + setmeasurements(response.data.Data.measurements); + setDuration(response.data.Data.duration); + setName(response.data.header); + } else { + console.log("Unexpected response:", response); } + } catch (error) { + echo.error("Failed to fetch saved inputs"); + console.error("There was an error!", error); } - - useEffect(() => { - fetchSavedInputes(); - }, []); - - useEffect(() => { - if (selectedChartId?.id === object?.id) { - fetchSavedInputes(); - } - } - ,[header, flotingDuration, flotingMeasurements]) - - - return ( - <> -
-

{name}

- {/*

+ } + }; + + useEffect(() => { + fetchSavedInputes(); + }, []); + + useEffect(() => { + if (selectedChartId?.id === object?.id) { + fetchSavedInputes(); + } + }, [header, flotingDuration, flotingMeasurements]); + + return ( + <> +

+

{name}

+ {/*

(+5) more in 2025

*/} -
-
- 0 ? chartData : lineGraphData} options={lineGraphOptions} /> -
- - ) -} +
+
+ 0 ? chartData : lineGraphData + } + options={lineGraphOptions} + /> +
+ + ); +}; -export default WarehouseThroughputComponent \ No newline at end of file +export default WarehouseThroughputComponent; diff --git a/app/src/modules/visualization/widgets/panel/AddButtons.tsx b/app/src/modules/visualization/widgets/panel/AddButtons.tsx index 6968c2e..58d2631 100644 --- a/app/src/modules/visualization/widgets/panel/AddButtons.tsx +++ b/app/src/modules/visualization/widgets/panel/AddButtons.tsx @@ -254,6 +254,7 @@ const AddButtons: React.FC = ({ setSelectedZone(updatedZone); } catch (error) { + echo.error("Failed to adding panel"); console.error("Error adding panel:", error); } } diff --git a/app/src/modules/visualization/widgets/panel/Panel.tsx b/app/src/modules/visualization/widgets/panel/Panel.tsx index 1a06a40..c1eeefc 100644 --- a/app/src/modules/visualization/widgets/panel/Panel.tsx +++ b/app/src/modules/visualization/widgets/panel/Panel.tsx @@ -56,6 +56,7 @@ const Panel: React.FC = ({ setZonesData, waitingPanels, }) => { + const { widgetSelect, setWidgetSelect } = useAsset3dWidget(); const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({}); const [panelDimensions, setPanelDimensions] = useState<{ [side in Side]?: { width: number; height: number }; @@ -70,7 +71,7 @@ const Panel: React.FC = ({ // Track canvas dimensions useEffect(() => { - const canvas = document.getElementById("work-space-three-d-canvas"); + const canvas = document.getElementById("real-time-vis-canvas"); if (!canvas) return; const updateCanvasDimensions = () => { @@ -182,7 +183,7 @@ const Panel: React.FC = ({ // Add widget to panel const addWidgetToPanel = async (asset: any, panel: Side) => { - const email = localStorage.getItem("email") ?? ""; + const email = localStorage.getItem("email") || ""; const organization = email?.split("@")[1]?.split(".")[0]; const newWidget = { diff --git a/app/src/modules/visualization/widgets/panel/WidgetPlaceHolder.tsx b/app/src/modules/visualization/widgets/panel/WidgetPlaceHolder.tsx new file mode 100644 index 0000000..c7d59b3 --- /dev/null +++ b/app/src/modules/visualization/widgets/panel/WidgetPlaceHolder.tsx @@ -0,0 +1,7 @@ +import React from "react"; + +const WidgetPlaceHolder = () => { + return
; +}; + +export default WidgetPlaceHolder; diff --git a/app/src/modules/visualization/zone/DisplayZone.tsx b/app/src/modules/visualization/zone/DisplayZone.tsx index 578bdab..d850db4 100644 --- a/app/src/modules/visualization/zone/DisplayZone.tsx +++ b/app/src/modules/visualization/zone/DisplayZone.tsx @@ -106,7 +106,6 @@ const DisplayZone: React.FC = ({ // console.log('canScrollRight: ', canScrollRight); // console.log('isOverflowing: ', isOverflowing); - } }, []); @@ -199,7 +198,9 @@ const DisplayZone: React.FC = ({ zoneViewPortTarget: response.viewPortCenter || {}, zoneViewPortPosition: response.viewPortposition || {}, }); - } catch (error) {} + } catch (error) { + echo.error("Failed to select zone"); + } } return ( diff --git a/app/src/modules/visualization/zone/zoneAssets.tsx b/app/src/modules/visualization/zone/zoneAssets.tsx index af8b849..309fed4 100644 --- a/app/src/modules/visualization/zone/zoneAssets.tsx +++ b/app/src/modules/visualization/zone/zoneAssets.tsx @@ -7,6 +7,7 @@ export default function ZoneAssets() { const { zoneAssetId, setZoneAssetId } = useZoneAssetId(); const { setSelectedFloorItem } = useSelectedFloorItem(); const { raycaster, controls, scene }: any = useThree(); + useEffect(() => { // console.log('zoneAssetId: ', zoneAssetId); if (!zoneAssetId) return @@ -70,8 +71,6 @@ export default function ZoneAssets() { } }, [zoneAssetId, scene, controls]) - - return ( <> diff --git a/app/src/modules/visualization/zone/zoneCameraTarget.tsx b/app/src/modules/visualization/zone/zoneCameraTarget.tsx index d1587de..c3116ef 100644 --- a/app/src/modules/visualization/zone/zoneCameraTarget.tsx +++ b/app/src/modules/visualization/zone/zoneCameraTarget.tsx @@ -13,8 +13,6 @@ export default function ZoneCentreTarget() { const { zoneTarget, setZoneTarget } = usezoneTarget(); const { Edit, setEdit } = useEditPosition(); - - useEffect(() => { if ( selectedZone.zoneViewPortTarget && diff --git a/app/src/pages/Project.tsx b/app/src/pages/Project.tsx index 1187cd5..aa203c3 100644 --- a/app/src/pages/Project.tsx +++ b/app/src/pages/Project.tsx @@ -58,7 +58,7 @@ const Project: React.FC = () => { setOrganization(Organization); setUserName(name); } - echo.warn("Log in success full"); + echo.warn("Log in successful"); } else { navigate("/"); } @@ -136,3 +136,26 @@ const Project: React.FC = () => { }; export default Project; + +// src/global.d.ts +// import { LogType } from "../components/ui/log/LoggerContext"; + +// export declare global { +// const echo: { +// log: (message: string) => void; +// info: (message: string) => void; +// warn: (message: string) => void; +// error: (message: string) => void; +// success: (message: string) => void; +// clear: () => void; +// }; +// } + +// Project.tsx:61 Uncaught ReferenceError: echo is not defined +// at Project.tsx:61:1 +// at commitHookEffectListMount (react-dom.development.js:23189:1) +// at commitPassiveMountOnFiber (react-dom.development.js:24965:1) +// at commitPassiveMountEffects_complete (react-dom.development.js:24930:1) +// at commitPassiveMountEffects_begin (react-dom.development.js:24917:1) +// at commitPassiveMountEffects (react-dom.development.js:24905:1) +// this error occurs some time's diff --git a/app/src/pages/UserAuth.tsx b/app/src/pages/UserAuth.tsx index 19393f9..4f18a63 100644 --- a/app/src/pages/UserAuth.tsx +++ b/app/src/pages/UserAuth.tsx @@ -43,7 +43,9 @@ const UserAuth: React.FC = () => { } else if (res.message === "User Not Found!!! Kindly signup...") { setError("Account not found"); } - } catch (error) {} + } catch (error) { + echo.error("Login failed"); + } }; const handleRegister = async (e: FormEvent) => { @@ -60,7 +62,9 @@ const UserAuth: React.FC = () => { if (res.message === "User already exists") { setError("User already exists"); } - } catch (error) {} + } catch (error) { + echo.error("Register user failed"); + } } else { setError("Please fill all the fields!"); } diff --git a/app/src/services/factoryBuilder/assest/assets/getAssetImages.ts b/app/src/services/factoryBuilder/assest/assets/getAssetImages.ts index 72f09d1..2576769 100644 --- a/app/src/services/factoryBuilder/assest/assets/getAssetImages.ts +++ b/app/src/services/factoryBuilder/assest/assets/getAssetImages.ts @@ -1,23 +1,26 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; export const getAssetImages = async (cursor?: string) => { - try { - const response = await fetch( - `${url_Backend_dwinzo}/api/v3/AssetDatas?limit=10${cursor ? `&cursor=${cursor}` : ""}`, - { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - } - ); + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v3/AssetDatas?limit=10${ + cursor ? `&cursor=${cursor}` : "" + }`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); - if (!response.ok) { - throw new Error("Failed to fetch assets"); - } - - return await response.json(); - } catch (error: any) { - throw new Error(error.message); + if (!response.ok) { + throw new Error("Failed to fetch assets"); } + + return await response.json(); + } catch (error: any) { + echo.error("Failed to get asset image"); + throw new Error(error.message); + } }; diff --git a/app/src/services/factoryBuilder/assest/assets/getAssetModel.ts b/app/src/services/factoryBuilder/assest/assets/getAssetModel.ts index ae7aaa4..67e0a28 100644 --- a/app/src/services/factoryBuilder/assest/assets/getAssetModel.ts +++ b/app/src/services/factoryBuilder/assest/assets/getAssetModel.ts @@ -1,25 +1,29 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; export const getAssetModel = async (modelId: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v2/AssetFile/${modelId}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v2/AssetFile/${modelId}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); - if (!response.ok) { - throw new Error("Failed to fetch model"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to fetch model"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to get asset model"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/assest/assets/getCategoryAsset.ts b/app/src/services/factoryBuilder/assest/assets/getCategoryAsset.ts index fc94323..c4c94aa 100644 --- a/app/src/services/factoryBuilder/assest/assets/getCategoryAsset.ts +++ b/app/src/services/factoryBuilder/assest/assets/getCategoryAsset.ts @@ -1,7 +1,8 @@ let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; export const getCategoryAsset = async (categoryName: any) => { try { - const response = await fetch(`${BackEnd_url}/api/v2/getCategoryAssets/${categoryName}`, + const response = await fetch( + `${BackEnd_url}/api/v2/getCategoryAssets/${categoryName}`, { method: "GET", headers: { @@ -13,6 +14,7 @@ export const getCategoryAsset = async (categoryName: any) => { const result = await response.json(); return result; } catch (error: any) { + echo.error("Failed to get category asset"); throw new Error(error.message); } }; diff --git a/app/src/services/factoryBuilder/assest/floorAsset/deleteFloorItemApi.ts b/app/src/services/factoryBuilder/assest/floorAsset/deleteFloorItemApi.ts index 908319b..b84199b 100644 --- a/app/src/services/factoryBuilder/assest/floorAsset/deleteFloorItemApi.ts +++ b/app/src/services/factoryBuilder/assest/floorAsset/deleteFloorItemApi.ts @@ -1,26 +1,34 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const deleteFloorItem = async (organization: string, modelUuid: string, modelName: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/deletefloorItem`, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, modelUuid, modelName }), - }); +export const deleteFloorItem = async ( + organization: string, + modelUuid: string, + modelName: string +) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v1/deletefloorItem`, + { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, modelUuid, modelName }), + } + ); - if (!response.ok) { - throw new Error("Failed to delete Floor Item"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to delete Floor Item"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to delete floor item"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/assest/floorAsset/getFloorItemsApi.ts b/app/src/services/factoryBuilder/assest/floorAsset/getFloorItemsApi.ts index 7c78c41..01aa67a 100644 --- a/app/src/services/factoryBuilder/assest/floorAsset/getFloorItemsApi.ts +++ b/app/src/services/factoryBuilder/assest/floorAsset/getFloorItemsApi.ts @@ -1,27 +1,30 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - export const getFloorAssets = async (organization: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v2/floorAssets/${organization}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v2/floorAssets/${organization}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); - if (!response.ok) { - throw new Error("Failed to get assets"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to get assets"); } -}; \ No newline at end of file + + const result = await response.json(); + + return result; + } catch (error) { + echo.error("Failed to get floor asset"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts b/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts index 3d7c921..010de40 100644 --- a/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts +++ b/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts @@ -1,36 +1,46 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; export const setFloorItemApi = async ( - organization: string, - modelUuid?: string, - modelName?: string, - modelfileID?: string, - position?: Object, - rotation?: Object, - isLocked?: boolean, - isVisible?: boolean, + organization: string, + modelUuid?: string, + modelName?: string, + modelfileID?: string, + position?: Object, + rotation?: Object, + isLocked?: boolean, + isVisible?: boolean ) => { - try { - const body: any = { organization, modelUuid, modelName, position, rotation, modelfileID, isLocked, isVisible }; + try { + const body: any = { + organization, + modelUuid, + modelName, + position, + rotation, + modelfileID, + isLocked, + isVisible, + }; - const response = await fetch(`${url_Backend_dwinzo}/api/v2/setasset`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(body), - }); + const response = await fetch(`${url_Backend_dwinzo}/api/v2/setasset`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body), + }); - if (!response.ok) { - throw new Error("Failed to set or update Floor Item"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to set or update Floor Item"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to set floor items"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/assest/wallAsset/deleteWallItemApi.ts b/app/src/services/factoryBuilder/assest/wallAsset/deleteWallItemApi.ts index da50167..7c1276e 100644 --- a/app/src/services/factoryBuilder/assest/wallAsset/deleteWallItemApi.ts +++ b/app/src/services/factoryBuilder/assest/wallAsset/deleteWallItemApi.ts @@ -1,26 +1,34 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const deleteWallItem = async (organization: string, modelUuid: string, modelName: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/deleteWallItem`, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, modelUuid, modelName }), - }); +export const deleteWallItem = async ( + organization: string, + modelUuid: string, + modelName: string +) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v1/deleteWallItem`, + { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, modelUuid, modelName }), + } + ); - if (!response.ok) { - throw new Error("Failed to delete Wall Item"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to delete Wall Item"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to delete wall items"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/assest/wallAsset/getWallItemsApi.ts b/app/src/services/factoryBuilder/assest/wallAsset/getWallItemsApi.ts index 73aa0eb..56ad357 100644 --- a/app/src/services/factoryBuilder/assest/wallAsset/getWallItemsApi.ts +++ b/app/src/services/factoryBuilder/assest/wallAsset/getWallItemsApi.ts @@ -1,25 +1,29 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; export const getWallItems = async (organization: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/findWallItems/${organization}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v1/findWallItems/${organization}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); - if (!response.ok) { - throw new Error("Failed to get Wall Items"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to get Wall Items"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to get wall items"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/assest/wallAsset/setWallItemApi.ts b/app/src/services/factoryBuilder/assest/wallAsset/setWallItemApi.ts index 984adf5..b8a63d3 100644 --- a/app/src/services/factoryBuilder/assest/wallAsset/setWallItemApi.ts +++ b/app/src/services/factoryBuilder/assest/wallAsset/setWallItemApi.ts @@ -1,36 +1,47 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; export const setWallItem = async ( - organization: string, - modelUuid: string, - modelName: string, - type: string, - csgposition: Object, - csgscale: Object, - position: Object, - quaternion: Object, - scale: Object + organization: string, + modelUuid: string, + modelName: string, + type: string, + csgposition: Object, + csgscale: Object, + position: Object, + quaternion: Object, + scale: Object ) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/setWallItems`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, modelUuid, modelName, position, type, csgposition, csgscale, quaternion, scale }), - }); + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/setWallItems`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + organization, + modelUuid, + modelName, + position, + type, + csgposition, + csgscale, + quaternion, + scale, + }), + }); - if (!response.ok) { - throw new Error("Failed to set or update Wall Item"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to set or update Wall Item"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to set wall items"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/camera/getCameraApi.ts b/app/src/services/factoryBuilder/camera/getCameraApi.ts index 35e5e37..cea21d0 100644 --- a/app/src/services/factoryBuilder/camera/getCameraApi.ts +++ b/app/src/services/factoryBuilder/camera/getCameraApi.ts @@ -1,16 +1,19 @@ -import { setCamera } from './setCameraApi'; -import * as THREE from 'three'; +import { setCamera } from "./setCameraApi"; +import * as THREE from "three"; let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; export const getCamera = async (organization: string, userId: string) => { try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/getCamera/${organization}/${userId}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); + const response = await fetch( + `${url_Backend_dwinzo}/api/v1/getCamera/${organization}/${userId}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); if (!response.ok) { throw new Error("Failed to get Camera position and target"); @@ -23,10 +26,11 @@ export const getCamera = async (organization: string, userId: string) => { return result; } } catch (error) { + echo.error("Failed to get camera"); if (error instanceof Error) { throw new Error(error.message); } else { throw new Error("An unknown error occurred"); } } -}; \ No newline at end of file +}; diff --git a/app/src/services/factoryBuilder/camera/setCameraApi.ts b/app/src/services/factoryBuilder/camera/setCameraApi.ts index 7953dc3..8db3715 100644 --- a/app/src/services/factoryBuilder/camera/setCameraApi.ts +++ b/app/src/services/factoryBuilder/camera/setCameraApi.ts @@ -1,26 +1,39 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const setCamera = async (organization: string, userId: string, position: Object, target: Object, rotation: Object) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/setCamera`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, userId, position, target, rotation }), - }); +export const setCamera = async ( + organization: string, + userId: string, + position: Object, + target: Object, + rotation: Object +) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/setCamera`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + organization, + userId, + position, + target, + rotation, + }), + }); - if (!response.ok) { - throw new Error("Failed to set Camera Position and Target"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to set Camera Position and Target"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to set camera"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/collab/getActiveUsers.ts b/app/src/services/factoryBuilder/collab/getActiveUsers.ts index 2d6516b..286b20e 100644 --- a/app/src/services/factoryBuilder/collab/getActiveUsers.ts +++ b/app/src/services/factoryBuilder/collab/getActiveUsers.ts @@ -1,32 +1,32 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; export default async function getActiveUsersData(organization: string) { - const apiUrl = `${url_Backend_dwinzo}/api/v1/activeCameras/${organization}`; + const apiUrl = `${url_Backend_dwinzo}/api/v1/activeCameras/${organization}`; - try { - const response = await fetch(apiUrl, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }); + try { + const response = await fetch(apiUrl, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); - if (!response.ok) { - throw new Error(`Error: ${response.status} - ${response.statusText}`); - } - - - if (!response.ok) { - throw new Error("Failed to get active cameras "); - } - - 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"); - } + if (!response.ok) { + throw new Error(`Error: ${response.status} - ${response.statusText}`); } -}; \ No newline at end of file + + if (!response.ok) { + throw new Error("Failed to get active cameras "); + } + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to get active users"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +} diff --git a/app/src/services/factoryBuilder/collab/getUsersApi.ts b/app/src/services/factoryBuilder/collab/getUsersApi.ts index 4fec523..b06c529 100644 --- a/app/src/services/factoryBuilder/collab/getUsersApi.ts +++ b/app/src/services/factoryBuilder/collab/getUsersApi.ts @@ -1,32 +1,32 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; export default async function fetchShareUsers(organization: string) { - const apiUrl = `${url_Backend_dwinzo}/api/v1/findshareUsers?organization=${organization}`; + const apiUrl = `${url_Backend_dwinzo}/api/v1/findshareUsers?organization=${organization}`; - try { - const response = await fetch(apiUrl, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }); + try { + const response = await fetch(apiUrl, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); - if (!response.ok) { - throw new Error(`Error: ${response.status} - ${response.statusText}`); - } - - - if (!response.ok) { - throw new Error("Failed to get users "); - } - - 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"); - } + if (!response.ok) { + throw new Error(`Error: ${response.status} - ${response.statusText}`); } -}; \ No newline at end of file + + if (!response.ok) { + throw new Error("Failed to get users "); + } + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to get user API"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +} diff --git a/app/src/services/factoryBuilder/collab/giveCollabAccess.ts b/app/src/services/factoryBuilder/collab/giveCollabAccess.ts index 07f68a8..d90b402 100644 --- a/app/src/services/factoryBuilder/collab/giveCollabAccess.ts +++ b/app/src/services/factoryBuilder/collab/giveCollabAccess.ts @@ -1,26 +1,31 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export default async function giveCollabAccess(email: string, isShare: boolean, organization: string) { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/shareUser`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ email, isShare, organization }), - }); +export default async function giveCollabAccess( + email: string, + isShare: boolean, + organization: string +) { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/shareUser`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ email, isShare, organization }), + }); - if (!response.ok) { - throw new Error("Failed to set Camera Position and Target"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to set Camera Position and Target"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to give collab access"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +} diff --git a/app/src/services/factoryBuilder/environment/findEnvironment.ts b/app/src/services/factoryBuilder/environment/findEnvironment.ts index 08cfe68..2a35580 100644 --- a/app/src/services/factoryBuilder/environment/findEnvironment.ts +++ b/app/src/services/factoryBuilder/environment/findEnvironment.ts @@ -34,6 +34,7 @@ export const findEnvironment = async (organization: string, userId: string) => { return result; } } catch (error) { + echo.error("Failed to find env"); if (error instanceof Error) { throw new Error(error.message); } else { diff --git a/app/src/services/factoryBuilder/environment/setEnvironment.ts b/app/src/services/factoryBuilder/environment/setEnvironment.ts index 1f72959..4aa3263 100644 --- a/app/src/services/factoryBuilder/environment/setEnvironment.ts +++ b/app/src/services/factoryBuilder/environment/setEnvironment.ts @@ -36,6 +36,7 @@ export const setEnvironment = async ( const result = await response.json(); return result; } catch (error) { + echo.error("Failed to set env"); if (error instanceof Error) { throw new Error(error.message); } else { diff --git a/app/src/services/factoryBuilder/lines/deleteLayerApi.ts b/app/src/services/factoryBuilder/lines/deleteLayerApi.ts index 4f81271..a13b1bb 100644 --- a/app/src/services/factoryBuilder/lines/deleteLayerApi.ts +++ b/app/src/services/factoryBuilder/lines/deleteLayerApi.ts @@ -1,26 +1,27 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; export const deleteLayer = async (organization: string, layer: number) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/deleteLayer`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, layer }), - }); + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/deleteLayer`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, layer }), + }); - if (!response.ok) { - throw new Error("Failed to delete line"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to delete line"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to delete line"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/lines/deleteLineApi.ts b/app/src/services/factoryBuilder/lines/deleteLineApi.ts index 09f1584..21569ea 100644 --- a/app/src/services/factoryBuilder/lines/deleteLineApi.ts +++ b/app/src/services/factoryBuilder/lines/deleteLineApi.ts @@ -1,26 +1,27 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; export const deleteLineApi = async (organization: string, line: Object) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/deleteLine`, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, line }), - }); + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/deleteLine`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, line }), + }); - if (!response.ok) { - throw new Error("Failed to delete line"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to delete line"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to delete line"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/lines/deletePointApi.ts b/app/src/services/factoryBuilder/lines/deletePointApi.ts index cc31589..3d3cd07 100644 --- a/app/src/services/factoryBuilder/lines/deletePointApi.ts +++ b/app/src/services/factoryBuilder/lines/deletePointApi.ts @@ -1,26 +1,27 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; export const deletePointApi = async (organization: string, uuid: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/deletePoint`, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, uuid }), - }); + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/deletePoint`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, uuid }), + }); - if (!response.ok) { - throw new Error("Failed to delete point"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to delete point"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to delete point"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/lines/getLinesApi.ts b/app/src/services/factoryBuilder/lines/getLinesApi.ts index 72450b4..0253246 100644 --- a/app/src/services/factoryBuilder/lines/getLinesApi.ts +++ b/app/src/services/factoryBuilder/lines/getLinesApi.ts @@ -1,25 +1,29 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; export const getLines = async (organization: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/findLines/${organization}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v1/findLines/${organization}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); - if (!response.ok) { - throw new Error("Failed to get Lines"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to get Lines"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to get Lines"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/lines/setLineApi.ts b/app/src/services/factoryBuilder/lines/setLineApi.ts index 43c50eb..3b08d9b 100644 --- a/app/src/services/factoryBuilder/lines/setLineApi.ts +++ b/app/src/services/factoryBuilder/lines/setLineApi.ts @@ -1,26 +1,32 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const setLine = async (organization: string, layer: number, line: Object, type: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/setLine`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, layer, line, type }), - }); +export const setLine = async ( + organization: string, + layer: number, + line: Object, + type: string +) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/setLine`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, layer, line, type }), + }); - if (!response.ok) { - throw new Error("Failed to set line"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to set line"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to set line"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/lines/updatePointApi.ts b/app/src/services/factoryBuilder/lines/updatePointApi.ts index a7ed0c3..960fac3 100644 --- a/app/src/services/factoryBuilder/lines/updatePointApi.ts +++ b/app/src/services/factoryBuilder/lines/updatePointApi.ts @@ -1,26 +1,31 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const updatePoint = async (organization: string, position: Object, uuid: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/updatePoint`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, position, uuid }), - }); +export const updatePoint = async ( + organization: string, + position: Object, + uuid: string +) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/updatePoint`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, position, uuid }), + }); - if (!response.ok) { - throw new Error("Failed to update point"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to update point"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to update point"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/signInSignUp/signInApi.ts b/app/src/services/factoryBuilder/signInSignUp/signInApi.ts index c2b32c5..d45eadb 100644 --- a/app/src/services/factoryBuilder/signInSignUp/signInApi.ts +++ b/app/src/services/factoryBuilder/signInSignUp/signInApi.ts @@ -1,22 +1,27 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const signInApi = async (email: string, password: Object, organization: Object) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/login`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ email, password, organization }), - }); +export const signInApi = async ( + email: string, + password: Object, + organization: Object +) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/login`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ email, password, organization }), + }); - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - return { error: error.message }; - } else { - return { error: "An unknown error occurred" }; - } + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to sign-in"); + if (error instanceof Error) { + return { error: error.message }; + } else { + return { error: "An unknown error occurred" }; } -}; \ No newline at end of file + } +}; diff --git a/app/src/services/factoryBuilder/signInSignUp/signUpApi.ts b/app/src/services/factoryBuilder/signInSignUp/signUpApi.ts index ac55948..aa9c63b 100644 --- a/app/src/services/factoryBuilder/signInSignUp/signUpApi.ts +++ b/app/src/services/factoryBuilder/signInSignUp/signUpApi.ts @@ -1,26 +1,32 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const signUpApi = async (userName: string, email: string, password: Object, organization: Object) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/signup`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ userName, email, password, organization }), - }); +export const signUpApi = async ( + userName: string, + email: string, + password: Object, + organization: Object +) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/signup`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ userName, email, password, organization }), + }); - if (!response.ok) { - throw new Error("Failed to signUpApi"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to signUpApi"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to sign-up"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/zones/deleteZoneApi.ts b/app/src/services/factoryBuilder/zones/deleteZoneApi.ts index 2537fb6..013ad31 100644 --- a/app/src/services/factoryBuilder/zones/deleteZoneApi.ts +++ b/app/src/services/factoryBuilder/zones/deleteZoneApi.ts @@ -1,27 +1,32 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const deleteZonesApi = async (userId: string, organization: string, zoneId: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/setLine`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ userId, organization, zoneId }), - }); +export const deleteZonesApi = async ( + userId: string, + organization: string, + zoneId: string +) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/setLine`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ userId, organization, zoneId }), + }); - if (!response.ok) { - throw new Error("Failed to delete 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"); - } + if (!response.ok) { + throw new Error("Failed to delete zone"); } -}; \ No newline at end of file + + const result = await response.json(); + + return result; + } catch (error) { + echo.error("Failed to delete zone"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/factoryBuilder/zones/getZonesApi.ts b/app/src/services/factoryBuilder/zones/getZonesApi.ts index 413458c..ba26e30 100644 --- a/app/src/services/factoryBuilder/zones/getZonesApi.ts +++ b/app/src/services/factoryBuilder/zones/getZonesApi.ts @@ -2,25 +2,29 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_UR // let url_Backend_dwinzo = `http://192.168.0.102:5000`; export const getZonesApi = async (organization: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v2/findZones/${organization}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v2/findZones/${organization}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); - // if (!response.ok) { - // throw new Error("Failed to get Zones"); - // } + // if (!response.ok) { + // throw new Error("Failed to get Zones"); + // } - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to get zone data"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); } -}; \ No newline at end of file + } +}; diff --git a/app/src/services/factoryBuilder/zones/setZonesApi.ts b/app/src/services/factoryBuilder/zones/setZonesApi.ts index c19e91a..0468752 100644 --- a/app/src/services/factoryBuilder/zones/setZonesApi.ts +++ b/app/src/services/factoryBuilder/zones/setZonesApi.ts @@ -1,26 +1,31 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const setZonesApi = async (userId: string, organization: string, zoneData: any) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/setLine`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ userId, organization, zoneData }), - }); +export const setZonesApi = async ( + userId: string, + organization: string, + zoneData: any +) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/setLine`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ userId, organization, zoneData }), + }); - if (!response.ok) { - throw new Error("Failed to set 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"); - } + if (!response.ok) { + throw new Error("Failed to set zone"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to zone data"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/marketplace/fetchAssetDetails.ts b/app/src/services/marketplace/fetchAssetDetails.ts index b14fd3f..9c21b5d 100644 --- a/app/src/services/marketplace/fetchAssetDetails.ts +++ b/app/src/services/marketplace/fetchAssetDetails.ts @@ -16,6 +16,7 @@ export const getAssetDetails = async (filename: string) => { const result = await response.json(); return result; } catch (error: any) { + echo.error("Failed to fetch assetg details"); // console.error("Error fetching category:", error.message); throw new Error(error.message); } diff --git a/app/src/services/marketplace/fetchAssets.ts b/app/src/services/marketplace/fetchAssets.ts index 7a395f9..6077b74 100644 --- a/app/src/services/marketplace/fetchAssets.ts +++ b/app/src/services/marketplace/fetchAssets.ts @@ -10,6 +10,7 @@ export const fetchAssets = async () => { // console.log('last10Assets: ', last10Assets); return result; } catch (error) { + echo.error("Failed to fetch assets"); console.log("error: ", error); // throw new Error(error.message); } diff --git a/app/src/services/marketplace/getSortedAssets.ts b/app/src/services/marketplace/getSortedAssets.ts index 3bbbfbe..aa98cc7 100644 --- a/app/src/services/marketplace/getSortedAssets.ts +++ b/app/src/services/marketplace/getSortedAssets.ts @@ -19,6 +19,7 @@ export const getSortedAssets = async (category: any, orders: any) => { return result; // Return the result to be used later } catch (error: any) { + echo.error("Failed to fetching category"); console.error("Error fetching category:", error.message); throw new Error(error.message); } diff --git a/app/src/services/simulation/UpsertProductOrEventApi.ts b/app/src/services/simulation/UpsertProductOrEventApi.ts index e2f45d1..80c99e0 100644 --- a/app/src/services/simulation/UpsertProductOrEventApi.ts +++ b/app/src/services/simulation/UpsertProductOrEventApi.ts @@ -1,26 +1,30 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; export const upsertProductOrEventApi = async (body: any) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v2/UpsertProductOrEvent`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(body), - }); + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v2/UpsertProductOrEvent`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body), + } + ); - if (!response.ok) { - throw new Error("Failed to add product or event"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to add product or event"); } + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to upsert product Or eventApi"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; diff --git a/app/src/services/simulation/deleteEventDataApi.ts b/app/src/services/simulation/deleteEventDataApi.ts index f263065..10448cc 100644 --- a/app/src/services/simulation/deleteEventDataApi.ts +++ b/app/src/services/simulation/deleteEventDataApi.ts @@ -1,26 +1,30 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; export const deleteEventDataApi = async (body: any) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v2/EventDataDelete`, { - method: "PATCH", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(body), - }); + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v2/EventDataDelete`, + { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body), + } + ); - if (!response.ok) { - throw new Error("Failed to delete event data"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to delete event data"); } + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to delete event data API"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; diff --git a/app/src/services/simulation/deleteProductApi.ts b/app/src/services/simulation/deleteProductApi.ts index 2987a53..d6cc42b 100644 --- a/app/src/services/simulation/deleteProductApi.ts +++ b/app/src/services/simulation/deleteProductApi.ts @@ -1,25 +1,32 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const deleteProductApi = async (productId: string, organization: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v2/productDataDelete?productId=${productId}&organization=${organization}`, { - method: "PATCH", - headers: { - "Content-Type": "application/json", - }, - }); +export const deleteProductApi = async ( + productId: string, + organization: string +) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v2/productDataDelete?productId=${productId}&organization=${organization}`, + { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + } + ); - if (!response.ok) { - throw new Error("Failed to delete product data"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to delete product data"); } + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to delete product API"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; diff --git a/app/src/services/simulation/getProductApi.ts b/app/src/services/simulation/getProductApi.ts index cf80013..3db4f2b 100644 --- a/app/src/services/simulation/getProductApi.ts +++ b/app/src/services/simulation/getProductApi.ts @@ -1,25 +1,32 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const getProductApi = async (productId: string, organization: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v2/productDatas?productId=${productId}&organization=${organization}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); +export const getProductApi = async ( + productId: string, + organization: string +) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v2/productDatas?productId=${productId}&organization=${organization}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); - if (!response.ok) { - throw new Error("Failed to fetch product data"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to fetch product data"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to get product asset"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/simulation/getallProductsApi.ts b/app/src/services/simulation/getallProductsApi.ts index 46627f9..449dd9a 100644 --- a/app/src/services/simulation/getallProductsApi.ts +++ b/app/src/services/simulation/getallProductsApi.ts @@ -1,25 +1,29 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const getAllProductsApi = async ( organization: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v2/AllProducts/${organization}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); +export const getAllProductsApi = async (organization: string) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v2/AllProducts/${organization}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); - if (!response.ok) { - throw new Error("Failed to fetch all products data"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to fetch all products data"); } -}; \ No newline at end of file + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to get all product API"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/simulation/renameProductApi.ts b/app/src/services/simulation/renameProductApi.ts index afa493c..56bbf36 100644 --- a/app/src/services/simulation/renameProductApi.ts +++ b/app/src/services/simulation/renameProductApi.ts @@ -1,26 +1,32 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const renameProductApi = async (body: { productName: string, productId: string, organization: string }) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v2/productRename`, { - method: "PATCH", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(body), - }); +export const renameProductApi = async (body: { + productName: string; + productId: string; + organization: string; +}) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v2/productRename`, { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body), + }); - if (!response.ok) { - throw new Error("Failed to rename product"); - } - - 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"); - } + if (!response.ok) { + throw new Error("Failed to rename product"); } + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to rename product Api"); + + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; diff --git a/app/src/services/visulization/zone/add3dWidget.ts b/app/src/services/visulization/zone/add3dWidget.ts index 401a5bf..e0bd06b 100644 --- a/app/src/services/visulization/zone/add3dWidget.ts +++ b/app/src/services/visulization/zone/add3dWidget.ts @@ -6,16 +6,13 @@ export const adding3dWidgets = async ( widget: {} ) => { try { - const response = await fetch( - `${url_Backend_dwinzo}/api/v2/3dwidget/save`, - { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, zoneId, widget }), - } - ); + const response = await fetch(`${url_Backend_dwinzo}/api/v2/3dwidget/save`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, zoneId, widget }), + }); if (!response.ok) { throw new Error("Failed to add 3dwidget in the zone"); @@ -24,6 +21,7 @@ export const adding3dWidgets = async ( const result = await response.json(); return result; } catch (error) { + echo.error("Failed to add 3d widget"); if (error instanceof Error) { throw new Error(error.message); } else { diff --git a/app/src/services/visulization/zone/addFloatingWidgets.ts b/app/src/services/visulization/zone/addFloatingWidgets.ts index beaa1b3..86d7fa8 100644 --- a/app/src/services/visulization/zone/addFloatingWidgets.ts +++ b/app/src/services/visulization/zone/addFloatingWidgets.ts @@ -6,9 +6,6 @@ export const addingFloatingWidgets = async ( organization: string, widget: {} ) => { - - - try { const response = await fetch( `${url_Backend_dwinzo}/api/v2/floatwidget/save`, @@ -28,6 +25,7 @@ export const addingFloatingWidgets = async ( const result = await response.json(); return result; } catch (error) { + echo.error("Failed to add floating"); if (error instanceof Error) { throw new Error(error.message); } else { diff --git a/app/src/services/visulization/zone/addWidgets.ts b/app/src/services/visulization/zone/addWidgets.ts index 8539e54..e44ac29 100644 --- a/app/src/services/visulization/zone/addWidgets.ts +++ b/app/src/services/visulization/zone/addWidgets.ts @@ -21,6 +21,7 @@ export const addingWidgets = async ( const result = await response.json(); return result; } catch (error) { + echo.error("Failed to add widget"); if (error instanceof Error) { throw new Error(error.message); } else { diff --git a/app/src/services/visulization/zone/clearPanel.ts b/app/src/services/visulization/zone/clearPanel.ts index 3074c3f..98714bf 100644 --- a/app/src/services/visulization/zone/clearPanel.ts +++ b/app/src/services/visulization/zone/clearPanel.ts @@ -21,6 +21,7 @@ export const clearPanel = async ( const result = await response.json(); return result; } catch (error) { + echo.error("Failed to clean pannel"); if (error instanceof Error) { throw new Error(error.message); } else { diff --git a/app/src/services/visulization/zone/delete3dWidget.ts b/app/src/services/visulization/zone/delete3dWidget.ts index fe868f1..0945196 100644 --- a/app/src/services/visulization/zone/delete3dWidget.ts +++ b/app/src/services/visulization/zone/delete3dWidget.ts @@ -6,10 +6,6 @@ export const delete3dWidgetApi = async ( organization: string, id: string ) => { - console.log("zoneId: ", zoneId); - console.log("organization: ", organization); - console.log("id: ", id); - try { const response = await fetch( `${url_Backend_dwinzo}/api/v2/widget3D/delete`, @@ -29,6 +25,7 @@ export const delete3dWidgetApi = async ( const result = await response.json(); return result; } catch (error) { + echo.error("Failed to delete 3d widget"); if (error instanceof Error) { throw new Error(error.message); } else { diff --git a/app/src/services/visulization/zone/deleteFloatingWidget.ts b/app/src/services/visulization/zone/deleteFloatingWidget.ts index 85c96b8..6d92f74 100644 --- a/app/src/services/visulization/zone/deleteFloatingWidget.ts +++ b/app/src/services/visulization/zone/deleteFloatingWidget.ts @@ -5,8 +5,6 @@ export const deleteFloatingWidgetApi = async ( floatWidgetID: string, organization: string ) => { - console.log('organization: ', organization); - console.log('floatWidgetID: ', floatWidgetID); try { const response = await fetch( `${url_Backend_dwinzo}/api/v2/floatwidget/delete`, @@ -26,6 +24,7 @@ export const deleteFloatingWidgetApi = async ( const result = await response.json(); return result; } catch (error) { + echo.error("Failed to delete floating widget"); if (error instanceof Error) { throw new Error(error.message); } else { diff --git a/app/src/services/visulization/zone/deletePanel.ts b/app/src/services/visulization/zone/deletePanel.ts index 21f4846..f2d91bf 100644 --- a/app/src/services/visulization/zone/deletePanel.ts +++ b/app/src/services/visulization/zone/deletePanel.ts @@ -6,9 +6,6 @@ export const deletePanelApi = async ( panelName: string, organization: string ) => { - console.log('panelName: ', panelName); - console.log('organization: ', organization); - console.log('zoneId: ', zoneId); try { const response = await fetch(`${url_Backend_dwinzo}/api/v2/panel/delete`, { method: "PATCH", @@ -25,6 +22,7 @@ export const deletePanelApi = async ( const result = await response.json(); return result; } catch (error) { + echo.error("Failed to delete pannel"); if (error instanceof Error) { throw new Error(error.message); } else { diff --git a/app/src/services/visulization/zone/deleteTemplate.ts b/app/src/services/visulization/zone/deleteTemplate.ts index e452f6d..252effa 100644 --- a/app/src/services/visulization/zone/deleteTemplate.ts +++ b/app/src/services/visulization/zone/deleteTemplate.ts @@ -23,6 +23,7 @@ export const deleteTemplateApi = async ( const result = await response.json(); return result; } catch (error) { + echo.error("Failed to delete widget"); if (error instanceof Error) { throw new Error(error.message); } else { diff --git a/app/src/services/visulization/zone/deleteWidgetApi.ts b/app/src/services/visulization/zone/deleteWidgetApi.ts index 7607c95..51026a4 100644 --- a/app/src/services/visulization/zone/deleteWidgetApi.ts +++ b/app/src/services/visulization/zone/deleteWidgetApi.ts @@ -4,18 +4,15 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_UR export const deleteWidgetApi = async ( widgetID: string, organization: string, - zoneId:string + zoneId: string ) => { - console.log('zoneId: ', zoneId); - console.log('organization: ', organization); - console.log('widgetID: ', widgetID); try { const response = await fetch(`${url_Backend_dwinzo}/api/v2/delete/widget`, { method: "PATCH", headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ organization, widgetID,zoneId }), + body: JSON.stringify({ organization, widgetID, zoneId }), }); if (!response.ok) { @@ -24,6 +21,7 @@ export const deleteWidgetApi = async ( const result = await response.json(); return result; } catch (error) { + echo.error("Failed to delete widget"); if (error instanceof Error) { throw new Error(error.message); } else { diff --git a/app/src/services/visulization/zone/duplicateWidget.ts b/app/src/services/visulization/zone/duplicateWidget.ts index f5ec834..ff996fe 100644 --- a/app/src/services/visulization/zone/duplicateWidget.ts +++ b/app/src/services/visulization/zone/duplicateWidget.ts @@ -21,6 +21,7 @@ export const duplicateWidgetApi = async ( const result = await response.json(); return result; } catch (error) { + echo.error("Failed to dublicate widget"); if (error instanceof Error) { throw new Error(error.message); } else { diff --git a/app/src/services/visulization/zone/get3dWidgetData.ts b/app/src/services/visulization/zone/get3dWidgetData.ts index b5b6200..3e5f565 100644 --- a/app/src/services/visulization/zone/get3dWidgetData.ts +++ b/app/src/services/visulization/zone/get3dWidgetData.ts @@ -6,13 +6,13 @@ export const get3dWidgetZoneData = async ( ) => { try { const response = await fetch( - `${url_Backend_dwinzo}/api/v2/3dwidgetData/${ZoneId}/${organization}`, - { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - } + `${url_Backend_dwinzo}/api/v2/3dwidgetData/${ZoneId}/${organization}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } ); if (!response.ok) { throw new Error("Failed to fetch Zone3dWidgetData"); @@ -20,6 +20,7 @@ export const get3dWidgetZoneData = async ( return await response.json(); } catch (error: any) { + echo.error("Failed to fetch 3d data"); throw new Error(error.message); } }; diff --git a/app/src/services/visulization/zone/getFloatingData.ts b/app/src/services/visulization/zone/getFloatingData.ts index 80d2b19..10874e4 100644 --- a/app/src/services/visulization/zone/getFloatingData.ts +++ b/app/src/services/visulization/zone/getFloatingData.ts @@ -21,6 +21,7 @@ export const getFloatingZoneData = async ( return await response.json(); } catch (error: any) { + echo.error("Failed to fetch floating data"); throw new Error(error.message); } }; diff --git a/app/src/services/visulization/zone/getSelect2dZoneData.ts b/app/src/services/visulization/zone/getSelect2dZoneData.ts index 00d4dfe..8519045 100644 --- a/app/src/services/visulization/zone/getSelect2dZoneData.ts +++ b/app/src/services/visulization/zone/getSelect2dZoneData.ts @@ -22,6 +22,7 @@ export const getSelect2dZoneData = async ( return await response.json(); } catch (error: any) { + echo.error("Failed to fetch 2d widget data"); throw new Error(error.message); } }; diff --git a/app/src/services/visulization/zone/getTemplate.ts b/app/src/services/visulization/zone/getTemplate.ts index a3aa3a3..bebe45d 100644 --- a/app/src/services/visulization/zone/getTemplate.ts +++ b/app/src/services/visulization/zone/getTemplate.ts @@ -18,6 +18,7 @@ export const getTemplateData = async (organization?: string) => { return await response.json(); } catch (error: any) { + echo.error("Failed to template data"); throw new Error(error.message); } }; diff --git a/app/src/services/visulization/zone/getZoneData.ts b/app/src/services/visulization/zone/getZoneData.ts index efbac3b..58131db 100644 --- a/app/src/services/visulization/zone/getZoneData.ts +++ b/app/src/services/visulization/zone/getZoneData.ts @@ -18,6 +18,7 @@ export const getZone2dData = async (organization?: string) => { return await response.json(); } catch (error: any) { + echo.error("Failed to fetch 2d zone data"); throw new Error(error.message); } }; diff --git a/app/src/services/visulization/zone/getZones.ts b/app/src/services/visulization/zone/getZones.ts index b189050..569c5ae 100644 --- a/app/src/services/visulization/zone/getZones.ts +++ b/app/src/services/visulization/zone/getZones.ts @@ -2,7 +2,6 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_UR // let url_Backend_dwinzo = `http://192.168.0.102:5000`; export const getZoneData = async (zoneId: string, organization: string) => { - try { const response = await fetch( `${url_Backend_dwinzo}/api/v2/A_zone/${zoneId}/${organization}`, @@ -20,6 +19,7 @@ export const getZoneData = async (zoneId: string, organization: string) => { return await response.json(); } catch (error: any) { + echo.error("Failed to fetch zone data"); throw new Error(error.message); } }; diff --git a/app/src/services/visulization/zone/loadTemplate.ts b/app/src/services/visulization/zone/loadTemplate.ts index bf68aeb..5c14744 100644 --- a/app/src/services/visulization/zone/loadTemplate.ts +++ b/app/src/services/visulization/zone/loadTemplate.ts @@ -24,6 +24,7 @@ export const loadTempleteApi = async ( const result = await response.json(); return result; } catch (error) { + echo.error("Failed to load template"); if (error instanceof Error) { throw new Error(error.message); } else { diff --git a/app/src/services/visulization/zone/lockPanel.ts b/app/src/services/visulization/zone/lockPanel.ts index 4b5898f..a28d4df 100644 --- a/app/src/services/visulization/zone/lockPanel.ts +++ b/app/src/services/visulization/zone/lockPanel.ts @@ -6,13 +6,16 @@ export const lockPanel = async ( lockedPanel: any ) => { try { - const response = await fetch(`${url_Backend_dwinzo}/api/v2/zones/lockedPanels`, { - method: "PATCH", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, zoneId, lockedPanel }), - }); + const response = await fetch( + `${url_Backend_dwinzo}/api/v2/zones/lockedPanels`, + { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, zoneId, lockedPanel }), + } + ); if (!response.ok) { throw new Error("Failed to Lock Panel in the zone"); @@ -21,10 +24,11 @@ export const lockPanel = async ( const result = await response.json(); return result; } catch (error) { + echo.error("Failed to fetch locked panel data"); if (error instanceof Error) { throw new Error(error.message); } else { throw new Error("An unknown error occurred"); } } -}; \ No newline at end of file +}; diff --git a/app/src/services/visulization/zone/panel.ts b/app/src/services/visulization/zone/panel.ts index 82f1289..97934ce 100644 --- a/app/src/services/visulization/zone/panel.ts +++ b/app/src/services/visulization/zone/panel.ts @@ -23,6 +23,7 @@ export const panelData = async ( const result = await response.json(); return result; } catch (error) { + echo.error("Failed to fetch panel data"); if (error instanceof Error) { throw new Error(error.message); } else { diff --git a/app/src/services/visulization/zone/saveTempleteApi.ts b/app/src/services/visulization/zone/saveTempleteApi.ts index 9eae5cb..fc7f8e3 100644 --- a/app/src/services/visulization/zone/saveTempleteApi.ts +++ b/app/src/services/visulization/zone/saveTempleteApi.ts @@ -1,7 +1,6 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; // let url_Backend_dwinzo = `http://192.168.0.102:5000`; export const saveTemplateApi = async (organization: string, template: {}) => { - console.log('template: ', template); try { const response = await fetch(`${url_Backend_dwinzo}/api/v2/template/save`, { method: "POST", @@ -19,6 +18,7 @@ export const saveTemplateApi = async (organization: string, template: {}) => { return result; } catch (error) { + echo.error("Failed to save template"); if (error instanceof Error) { throw new Error(error.message); } else { diff --git a/app/src/services/visulization/zone/update3dWidget.ts b/app/src/services/visulization/zone/update3dWidget.ts index cb37a7f..278be58 100644 --- a/app/src/services/visulization/zone/update3dWidget.ts +++ b/app/src/services/visulization/zone/update3dWidget.ts @@ -1,77 +1,81 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; // let url_Backend_dwinzo = `http://192.168.0.102:5000`; export const update3dWidget = async ( - zoneId: string, - organization: string, - id: string, - position?: [number, number, number] + zoneId: string, + organization: string, + id: string, + position?: [number, number, number] ) => { - console.log("organization: ", organization); - console.log("zoneId: ", zoneId); - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v2/modifyPR/widget3D`, { - method: "PATCH", - headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ - organization, - zoneId, - id, - position, - }), - } - ); + console.log("organization: ", organization); + console.log("zoneId: ", zoneId); + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v2/modifyPR/widget3D`, + { + method: "PATCH", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + organization, + zoneId, + id, + position, + }), + } + ); - if (!response.ok) { - throw new Error("Failed to add 3dwidget 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"); - } + if (!response.ok) { + echo.error("Failed to update 3d widget"); + throw new Error("Failed to add 3dwidget 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"); + } + } }; export const update3dWidgetRotation = async ( - zoneId: string, - organization: string, - id: string, - rotation?: [number, number, number] + zoneId: string, + organization: string, + id: string, + rotation?: [number, number, number] ) => { - console.log("organization: ", organization); - console.log("zoneId: ", zoneId); - try { - const response = await fetch( - `${url_Backend_dwinzo}/api/v2/modifyPR/widget3D`, - { - method: "PATCH", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - organization, - zoneId, - id, - rotation, - }), - } - ); + console.log("organization: ", organization); + console.log("zoneId: ", zoneId); + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v2/modifyPR/widget3D`, + { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + organization, + zoneId, + id, + rotation, + }), + } + ); - if (!response.ok) { - throw new Error("Failed to add 3dwidget 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"); - } + if (!response.ok) { + throw new Error("Failed to add 3dwidget in the zone"); } + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to rotate 3d widget"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; diff --git a/app/src/services/visulization/zone/zoneCameraUpdation.ts b/app/src/services/visulization/zone/zoneCameraUpdation.ts index d46f6a3..6dddf67 100644 --- a/app/src/services/visulization/zone/zoneCameraUpdation.ts +++ b/app/src/services/visulization/zone/zoneCameraUpdation.ts @@ -1,9 +1,7 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; // let url_Backend_dwinzo = `http://192.168.0.102:5000`; -export const zoneCameraUpdate = async ( - zonesdata:{},organization:string -) => { +export const zoneCameraUpdate = async (zonesdata: {}, organization: string) => { try { const response = await fetch(`${url_Backend_dwinzo}/api/v2/zone/save`, { method: "POST", @@ -20,10 +18,11 @@ export const zoneCameraUpdate = async ( const result = await response.json(); return result; } catch (error) { + echo.error("Failed to update zone camera"); if (error instanceof Error) { throw new Error(error.message); } else { throw new Error("An unknown error occurred"); } } -}; \ No newline at end of file +}; diff --git a/app/src/store/simulation/useMaterialStore.ts b/app/src/store/simulation/useMaterialStore.ts index 044f9c5..31f5726 100644 --- a/app/src/store/simulation/useMaterialStore.ts +++ b/app/src/store/simulation/useMaterialStore.ts @@ -10,6 +10,15 @@ type MaterialsStore = { clearMaterials: () => void; updateMaterial: (materialId: string, updates: Partial) => MaterialSchema | undefined; + setPreviousLocation: ( + materialId: string, + location: { + modelUuid: string; + pointUuid: string; + actionUuid: string; + } + ) => MaterialSchema | undefined; + setCurrentLocation: ( materialId: string, location: { @@ -93,6 +102,18 @@ export const useMaterialStore = create()( return updatedMaterial; }, + setPreviousLocation: (materialId, location) => { + let updatedMaterial: MaterialSchema | undefined; + set((state) => { + const material = state.materials.find(m => m.materialId === materialId); + if (material) { + material.previous = location; + updatedMaterial = JSON.parse(JSON.stringify(material)); + } + }); + return updatedMaterial; + }, + setCurrentLocation: (materialId, location) => { let updatedMaterial: MaterialSchema | undefined; set((state) => { diff --git a/app/src/store/simulation/useVehicleStore.ts b/app/src/store/simulation/useVehicleStore.ts index 63ca0d0..7a393de 100644 --- a/app/src/store/simulation/useVehicleStore.ts +++ b/app/src/store/simulation/useVehicleStore.ts @@ -1,6 +1,5 @@ - -import { create } from 'zustand'; -import { immer } from 'zustand/middleware/immer'; +import { create } from "zustand"; +import { immer } from "zustand/middleware/immer"; interface VehiclesStore { vehicles: VehicleStatus[]; @@ -9,7 +8,7 @@ interface VehiclesStore { removeVehicle: (modelUuid: string) => void; updateVehicle: ( modelUuid: string, - updates: Partial> + updates: Partial> ) => void; clearvehicles: () => void; @@ -17,8 +16,15 @@ interface VehiclesStore { updateSteeringAngle: (modelUuid: string, steeringAngle: number) => void; incrementVehicleLoad: (modelUuid: string, incrementBy: number) => void; decrementVehicleLoad: (modelUuid: string, decrementBy: number) => void; - setVehicleState: (modelUuid: string, newState: VehicleStatus['state']) => void; - setMaterialType: (modelUuid: string, materialType: string | null) => void; + setVehicleLoad: (modelUuid: string, load: number) => void; + setVehicleState: ( + modelUuid: string, + newState: VehicleStatus["state"] + ) => void; + addCurrentMaterial: (modelUuid: string, materialType: string, materialId: string) => void; + setCurrentMaterials: (modelUuid: string, materials: { materialType: string; materialId: string; }[]) => void; + removeLastMaterial: (modelUuid: string) => string | undefined; + clearCurrentMaterials: (modelUuid: string) => void; incrementActiveTime: (modelUuid: string, incrementBy: number) => void; incrementIdleTime: (modelUuid: string, incrementBy: number) => void; @@ -34,7 +40,9 @@ export const useVehicleStore = create()( addVehicle: (productId, event) => { set((state) => { - const exists = state.vehicles.some(v => v.modelUuid === event.modelUuid); + const exists = state.vehicles.some( + (v) => v.modelUuid === event.modelUuid + ); if (!exists) { state.vehicles.push({ ...event, @@ -43,7 +51,7 @@ export const useVehicleStore = create()( idleTime: 0, activeTime: 0, currentLoad: 0, - materialType: null, + currentMaterials: [], distanceTraveled: 0, }); } @@ -52,13 +60,15 @@ export const useVehicleStore = create()( removeVehicle: (modelUuid) => { set((state) => { - state.vehicles = state.vehicles.filter(v => v.modelUuid !== modelUuid); + state.vehicles = state.vehicles.filter( + (v) => v.modelUuid !== modelUuid + ); }); }, updateVehicle: (modelUuid, updates) => { set((state) => { - const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid); + const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); if (vehicle) { Object.assign(vehicle, updates); } @@ -73,7 +83,7 @@ export const useVehicleStore = create()( setVehicleActive: (modelUuid, isActive) => { set((state) => { - const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid); + const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); if (vehicle) { vehicle.isActive = isActive; } @@ -82,7 +92,7 @@ export const useVehicleStore = create()( updateSteeringAngle: (modelUuid, steeringAngle) => { set((state) => { - const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid); + const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); if (vehicle) { vehicle.point.action.steeringAngle = steeringAngle; } @@ -91,7 +101,7 @@ export const useVehicleStore = create()( incrementVehicleLoad: (modelUuid, incrementBy) => { set((state) => { - const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid); + const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); if (vehicle) { vehicle.currentLoad += incrementBy; } @@ -100,34 +110,77 @@ export const useVehicleStore = create()( decrementVehicleLoad: (modelUuid, decrementBy) => { set((state) => { - const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid); + const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); if (vehicle) { vehicle.currentLoad -= decrementBy; } }); }, + setVehicleLoad: (modelUuid, load) => { + set((state) => { + const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); + if (vehicle) { + vehicle.currentLoad = load; + } + }); + }, + setVehicleState: (modelUuid, newState) => { set((state) => { - const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid); + const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); if (vehicle) { vehicle.state = newState; } }); }, - setMaterialType: (modelUuid, materialType) => { + addCurrentMaterial: (modelUuid, materialType, materialId) => { set((state) => { - const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid); + const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); if (vehicle) { - vehicle.materialType = materialType; + vehicle.currentMaterials.push({ materialType, materialId }); + } + }); + }, + + setCurrentMaterials: (modelUuid, materials) => { + set((state) => { + const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); + if (vehicle) { + vehicle.currentMaterials = materials; + } + }); + }, + + removeLastMaterial: (modelUuid) => { + let materialId: string | undefined; + set((state) => { + const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); + if (vehicle) { + if (vehicle.currentMaterials.length > 0) { + const material = vehicle.currentMaterials.pop(); + if (material) { + materialId = material.materialId + } + } + } + }); + return materialId; + }, + + clearCurrentMaterials: (modelUuid) => { + set((state) => { + const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); + if (vehicle) { + vehicle.currentMaterials = []; } }); }, incrementActiveTime: (modelUuid, incrementBy) => { set((state) => { - const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid); + const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); if (vehicle) { vehicle.activeTime += incrementBy; } @@ -136,7 +189,7 @@ export const useVehicleStore = create()( incrementIdleTime: (modelUuid, incrementBy) => { set((state) => { - const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid); + const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); if (vehicle) { vehicle.idleTime += incrementBy; } @@ -144,19 +197,19 @@ export const useVehicleStore = create()( }, getVehicleById: (modelUuid) => { - return get().vehicles.find(v => v.modelUuid === modelUuid); + return get().vehicles.find((v) => v.modelUuid === modelUuid); }, getVehiclesByProduct: (productId) => { - return get().vehicles.filter(v => v.productId === productId); + return get().vehicles.filter((v) => v.productId === productId); }, getVehiclesByState: (state) => { - return get().vehicles.filter(v => v.state === state); + return get().vehicles.filter((v) => v.state === state); }, getActiveVehicles: () => { - return get().vehicles.filter(v => v.isActive); - } + return get().vehicles.filter((v) => v.isActive); + }, })) ); diff --git a/app/src/store/store.ts b/app/src/store/store.ts index b16e1ff..68740b7 100644 --- a/app/src/store/store.ts +++ b/app/src/store/store.ts @@ -66,6 +66,11 @@ export const useWalls = create((set: any) => ({ setWalls: (x: any) => set(() => ({ walls: x })), })); +export const useRoomsState = create((set: any) => ({ + roomsState: [], + setRoomsState: (x: any) => set(() => ({ walls: x })), +})); + export const useZones = create((set: any) => ({ zones: [], setZones: (callback: any) => diff --git a/app/src/styles/components/marketPlace/marketPlace.scss b/app/src/styles/components/marketPlace/marketPlace.scss index 73a2445..b4237f2 100644 --- a/app/src/styles/components/marketPlace/marketPlace.scss +++ b/app/src/styles/components/marketPlace/marketPlace.scss @@ -46,7 +46,7 @@ width: calc(25% - 14px) !important; - height: auto !important; + height: 100%; border-radius: #{$border-radius-xlarge}; padding: 12px; box-shadow: 0px 2px 10.5px 0px #0000000d; diff --git a/app/src/styles/components/simulation/simulation.scss b/app/src/styles/components/simulation/simulation.scss index fb9b6ad..b98c23f 100644 --- a/app/src/styles/components/simulation/simulation.scss +++ b/app/src/styles/components/simulation/simulation.scss @@ -315,7 +315,6 @@ } .open { - .start-displayer, .end-displayer { display: none; @@ -401,4 +400,140 @@ } } } -} \ No newline at end of file +} + +.asset-details-card-wrapper { + pointer-events: none; + .asset-details-card-container { + position: relative; + padding: 8px; + background: var(--background-color); + backdrop-filter: blur(6px); + border-radius: #{$border-radius-large}; + transform: translate(0, -100%); + z-index: 0; + box-shadow: inset 0px 10px 50px #80808075; + min-width: 124px; + + &::before { + content: ""; + position: absolute; + inset: 0; + border-radius: inherit; + background: linear-gradient(135deg, var(--accent-color), #ff00f000); + background-size: 400% 400%; + animation: borderAnimation 5s linear infinite; + -webkit-mask: linear-gradient(#fff 0 0) content-box, + linear-gradient(#fff 0 0); + mask: linear-gradient(#fff 0 0) content-box, + linear-gradient(#fff 0 0); + -webkit-mask-composite: xor; + mask-composite: exclude; + z-index: -1; + padding: 1px; + } + + .asset-details-header { + @include flex-space-between; + gap: 12px; + .content { + .name { + text-wrap: nowrap; + max-width: 140px; + overflow: hidden; + text-overflow: ellipsis; + margin-bottom: 4px; + text-transform: capitalize; + } + .status-container { + .status { + display: flex; + align-items: center; + gap: 6px; + .icon { + @include flex-center; + } + } + } + } + } + + .process-running-container { + width: 100%; + height: 8px; + background: var(--background-color-solid); + margin-top: 12px; + border-radius: #{$border-radius-small}; + overflow: hidden; + position: relative; + .process-running { + height: 100%; + width: 35%; + border-radius: #{$border-radius-small}; + background: var(--process-color); + animation: playing-process 1s ease-in-out infinite; + } + } + + .indication-arrow { + position: absolute; + left: 50%; + bottom: 0; + transform: translate(-50%, 10px); + filter: drop-shadow(0px 0px 4px #ffffff); + } + + .count-ui-wrapper { + position: absolute; + right: -42px; + top: 5px; + padding: 4px; + padding-right: 8px; + .count-ui-container { + @include flex-center; + gap: 6px; + .icon{ + @include flex-center; + padding: 3px; + border-radius: #{$border-radius-circle}; + background: var(--background-color-accent); + svg { + scale: 0.6; + } + } + .value{ + position: absolute; + width: 48px; + background: var(--background-color-solid-gradient); + border-radius: #{$border-radius-large}; + outline: 1px solid var(--border-color); + padding: 4px 10px; + padding-left: 16px; + transform: translateX(28px); + z-index: -1; + } + } + } + } +} + +@keyframes playing-process { + from { + transform: translateX(-100%); + } + to { + transform: translateX(300%); + } +} + +@keyframes borderAnimation { + 0% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0% 50%; + } +} diff --git a/app/src/styles/layout/sidebar.scss b/app/src/styles/layout/sidebar.scss index 5e7563a..6e1889e 100644 --- a/app/src/styles/layout/sidebar.scss +++ b/app/src/styles/layout/sidebar.scss @@ -42,18 +42,22 @@ min-width: 32px; border-radius: #{$border-radius-large}; position: relative; + .tooltip { top: 6px; right: -168px; + &::after { left: 0px; bottom: 50%; } } + &:hover { outline: 1px solid var(--border-color); outline-offset: -1px; background: var(--background-color-solid); + .tooltip { opacity: 1; transform: translateX(2px); @@ -81,6 +85,7 @@ .sidebar-left-container { min-height: 50vh; + max-width: 100%; padding-bottom: 4px; position: relative; display: flex; @@ -391,6 +396,7 @@ .tooltip { top: 6px; right: calc(100% + 6px); + &::after { left: 100%; bottom: 50%; @@ -411,10 +417,12 @@ &:hover { outline-color: var(--border-color-accent); + svg { transition: all 0.2s; scale: 1.1; } + .tooltip { opacity: 1; transform: translateX(-2px); @@ -425,10 +433,12 @@ .active { background: var(--background-color-accent); outline: none; + &:hover { svg { scale: 1; } + background: var(--background-color-accent); } } @@ -1297,10 +1307,12 @@ &:hover { outline: 1px solid var(--border-color-accent); + img { transition: all 0.2s; scale: 1.3; } + &::after { top: 80px; right: 0; @@ -1411,6 +1423,7 @@ .asset-name { opacity: 1; } + .asset-image { scale: 1.2; } @@ -1424,11 +1437,9 @@ width: 100%; height: 100%; font-size: var(--font-size-regular); - background: linear-gradient( - 0deg, - rgba(37, 24, 51, 0) 0%, - rgba(52, 41, 61, 0.5) 100% - ); + background: linear-gradient(0deg, + rgba(37, 24, 51, 0) 0%, + rgba(52, 41, 61, 0.5) 100%); pointer-events: none; backdrop-filter: blur(8px); opacity: 0; @@ -1455,10 +1466,12 @@ .skeleton-wrapper { display: flex; + .asset-name { width: 40%; height: 10px; } + .asset { width: 100%; height: 100%; @@ -1467,11 +1480,26 @@ .sidebar-left-wrapper, .sidebar-right-wrapper { - height: calc(50vh + 150px); + height: calc(54vh + 150px); transition: height 0.2s ease-in-out; + .sidebar-left-container { + height: 100%; + .sidebar-left-content-container{ + max-height: 80%; + .widget-left-sideBar{ + height: 80%; + .widget2D.widgets-wrapper{ + + min-height: 50vh; + height: 60%; + + } + } + } + } } .sidebar-left-wrapper.closed, .sidebar-right-wrapper.closed { height: 52px; -} +} \ No newline at end of file diff --git a/app/src/styles/pages/realTimeViz.scss b/app/src/styles/pages/realTimeViz.scss index f711258..9a072e7 100644 --- a/app/src/styles/pages/realTimeViz.scss +++ b/app/src/styles/pages/realTimeViz.scss @@ -213,6 +213,7 @@ position: relative; padding: 0 10px; animation: scaleFadeIn 0.4s forwards; + .kebab { width: 30px; height: 30px; @@ -948,13 +949,23 @@ transform: scaleY(0); } } + @keyframes scaleFadeIn { from { scale: 0; opacity: 0; } + to { scale: 1; opacity: 1; } } + +.widget-placeholder { + background-color: gray; + border-radius: 6px; + display: flex; + justify-content: center; + align-items: center; +} diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts index 04b742d..1b8788a 100644 --- a/app/src/types/simulationTypes.d.ts +++ b/app/src/types/simulationTypes.d.ts @@ -181,7 +181,7 @@ interface VehicleStatus extends VehicleEventSchema { idleTime: number; activeTime: number; currentLoad: number; - materialType: string | null; + currentMaterials: { materialType: string; materialId: string; }[]; distanceTraveled: number; } @@ -207,6 +207,12 @@ interface MaterialSchema { cost?: number; weight?: number; + previous?: { + modelUuid: string; + pointUuid: string; + actionUuid: string; + }; + current: { modelUuid: string; pointUuid: string;