diff --git a/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx b/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx index a6343ed..aff7867 100644 --- a/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx +++ b/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx @@ -166,7 +166,7 @@ const ProductionCapacity: React.FC = ({ const response = await axios.get( `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}` ); - + if (response.status === 200) { setmeasurements(response.data.Data.measurements); setDuration(response.data.Data.duration); @@ -188,29 +188,23 @@ const ProductionCapacity: React.FC = ({ }, [chartMeasurements, chartDuration, widgetName]); useEffect(() => { }, [rotation]); - const rotationDegrees = { - x: (rotation[0] * 180) / Math.PI, - y: (rotation[1] * 180) / Math.PI, - z: (rotation[2] * 180) / Math.PI, - }; - const transformStyle = { - transform: `rotateX(${rotationDegrees.x}deg) rotateY(${rotationDegrees.y}deg) rotateZ(${rotationDegrees.z}deg) translate(-50%, -50%)`, - }; + return ( { e.preventDefault(); e.stopPropagation(); @@ -221,7 +215,7 @@ const ProductionCapacity: React.FC = ({ }} wrapperClass="pointer-none" - > + >
setSelectedChartId({ id: id, type: type })} @@ -230,7 +224,7 @@ const ProductionCapacity: React.FC = ({ style={{ width: "300px", // Original width height: "300px", // Original height - transform: transformStyle.transform, + // transform: transformStyle.transform, transformStyle: "preserve-3d", position: "absolute", }} diff --git a/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx b/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx index 3d5d291..0dfe967 100644 --- a/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx +++ b/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx @@ -231,15 +231,16 @@ const ReturnOfInvestment: React.FC = ({ return (
= ({ return (
= ({ return (
= ({ } setSelectedZone(updatedZone); + + + if (hiddenPanels[selectedZone.zoneId]?.includes(side)) { + + setHiddenPanels(prev => ({ + ...prev, + [selectedZone.zoneId]: prev[selectedZone.zoneId].filter(s => s !== side) + })); + } + + // if(hiddenPanels[selectedZone.zoneId].includes(side)) + // API call to delete the panel // try { // const response = await deletePanelApi(selectedZone.zoneId, side, organization); @@ -269,11 +283,10 @@ const AddButtons: React.FC = ({
{/* Hide Panel */}
= ({ const [showLeftArrow, setShowLeftArrow] = useState(false); const [showRightArrow, setShowRightArrow] = useState(false); const { floatingWidget, setFloatingWidget } = useFloatingWidget() - - const{setSelectedChartId}=useWidgetStore() + + const { setSelectedChartId } = useWidgetStore() // Function to calculate overflow state const updateOverflowState = useCallback(() => { @@ -156,9 +159,9 @@ const DisplayZone: React.FC = ({ const email = localStorage.getItem("email") || ""; const organization = email?.split("@")[1]?.split(".")[0]; let response = await getSelect2dZoneData(zoneId, organization); - - + console.log('response: ', response); let res = await getFloatingZoneData(zoneId, organization); + console.log('res: ', res); setFloatingWidget(res); // Set the selected zone in the store @@ -168,19 +171,20 @@ const DisplayZone: React.FC = ({ useDroppedObjectsStore.getState().addObject(zoneName, val); }); } - + setSelectedZone({ zoneName, activeSides: response.activeSides || [], panelOrder: response.panelOrder || [], lockedPanels: response.lockedPanels || [], widgets: response.widgets || [], + points: response.points || [], zoneId: zoneId, zoneViewPortTarget: response.viewPortCenter || {}, zoneViewPortPosition: response.viewPortposition || {}, }); } catch (error) { - + } } @@ -197,8 +201,8 @@ const DisplayZone: React.FC = ({ )} {/* Scrollable Zones Container */} -
diff --git a/app/src/components/ui/componets/DraggableWidget.tsx b/app/src/components/ui/componets/DraggableWidget.tsx index fb20169..7fb8f39 100644 --- a/app/src/components/ui/componets/DraggableWidget.tsx +++ b/app/src/components/ui/componets/DraggableWidget.tsx @@ -44,6 +44,7 @@ export const DraggableWidget = ({ zoneName: string; zoneId: string; activeSides: Side[]; + points:[]; panelOrder: Side[]; lockedPanels: Side[]; widgets: Widget[]; @@ -53,7 +54,7 @@ export const DraggableWidget = ({ zoneName: string; activeSides: Side[]; panelOrder: Side[]; - + points:[]; lockedPanels: Side[]; zoneId: string; zoneViewPortTarget: number[]; @@ -173,6 +174,7 @@ export const DraggableWidget = ({ ...widget, id: `${widget.id}-copy-${Date.now()}`, }; + console.log('duplicatedWidget: ', duplicatedWidget); let duplicateWidget = { organization: organization, diff --git a/app/src/components/ui/componets/Dropped3dWidget.tsx b/app/src/components/ui/componets/Dropped3dWidget.tsx index 5dbdb5b..02d954d 100644 --- a/app/src/components/ui/componets/Dropped3dWidget.tsx +++ b/app/src/components/ui/componets/Dropped3dWidget.tsx @@ -1,5 +1,5 @@ import { useThree } from "@react-three/fiber"; -import React, { useEffect, useRef } from "react"; +import React, { useEffect, useRef, useState } from "react"; import { useAsset3dWidget, useSocketStore, @@ -57,6 +57,10 @@ export default function Dropped3dWidgets() { 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 }); + let [floorPlanesVertical, setFloorPlanesVertical] = useState( + new THREE.Plane(new THREE.Vector3(0, 1, 0)) + ); + const activeZoneWidgets = zoneWidgetData[selectedZone.zoneId] || []; useEffect(() => { @@ -73,8 +77,9 @@ export default function Dropped3dWidgets() { ); setWidgets3D(result); + if (result.length < 0) return - const formattedWidgets = result.map((widget: WidgetData) => ({ + const formattedWidgets = result?.map((widget: WidgetData) => ({ id: widget.id, type: widget.type, position: widget.position, @@ -172,7 +177,7 @@ export default function Dropped3dWidgets() { }; const onDrop = (event: any) => { - console.log("onDrop called. hasEntered: ", hasEntered.current); + event.preventDefault(); event.stopPropagation(); @@ -184,7 +189,15 @@ export default function Dropped3dWidgets() { const newWidget = createdWidgetRef.current; if (!newWidget || !widgetSelect.startsWith("ui")) return; - // ✅ Manual removal of the temp widget (same ID) + // ✅ Extract 2D drop position + const [x, , z] = newWidget.position; + + // ✅ 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) => ({ @@ -193,8 +206,12 @@ export default function Dropped3dWidgets() { [selectedZone.zoneId]: cleanedWidgets, }, })); - - // ✅ Now re-add it as final + if (!isInside) { + + createdWidgetRef.current = null; + return; // Stop here + } + // ✅ Add widget if inside polygon addWidget(selectedZone.zoneId, newWidget); const add3dWidget = { @@ -207,16 +224,10 @@ export default function Dropped3dWidgets() { visualizationSocket.emit("v2:viz-3D-widget:add", add3dWidget); } - setTimeout(() => { - let pointerDivs = document.getElementsByClassName("pointer-none"); - Array.from(pointerDivs).forEach((el) => { - el.classList.remove("pointer-none"); - }); - }, 1000); - createdWidgetRef.current = null; }; + canvasElement.addEventListener("dragenter", handleDragEnter); canvasElement.addEventListener("dragover", handleDragOver); canvasElement.addEventListener("drop", onDrop); @@ -228,8 +239,6 @@ export default function Dropped3dWidgets() { }; }, [widgetSelect, activeModule, selectedZone.zoneId, widgetSubOption, camera,]); - - useEffect(() => { if (!rightClickSelected) return; const email = localStorage.getItem("email") || ""; @@ -300,25 +309,61 @@ export default function Dropped3dWidgets() { } }, [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 cameraDirection = new THREE.Vector3(); + camera.getWorldDirection(cameraDirection); + + // Plane normal should be perpendicular to screen (XZ move), so use screen right direction + const right = new THREE.Vector3(); + camera.getWorldDirection(cameraDirection); + cameraDirection.y = 0; + cameraDirection.normalize(); + + right.crossVectors(new THREE.Vector3(0, 1, 0), cameraDirection).normalize(); + + // Create a plane that allows vertical movement + const verticalPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(right, new THREE.Vector3(0, 0, 0)); + + setFloorPlanesVertical(verticalPlane); if (rightSelect === "RotateX" || rightSelect === "RotateY") { mouseStartRef.current = { x: event.clientX, y: event.clientY }; - const selectedZone = Object.keys(zoneWidgetData).find( + const selectedZoneId = Object.keys(zoneWidgetData).find( (zoneId: string) => zoneWidgetData[zoneId].some( (widget: WidgetData) => widget.id === rightClickSelected ) ); - - if (!selectedZone) return; - - const selectedWidget = zoneWidgetData[selectedZone].find( + if (!selectedZoneId) return; + const selectedWidget = zoneWidgetData[selectedZoneId].find( (widget: WidgetData) => widget.id === rightClickSelected ); if (selectedWidget) { @@ -329,14 +374,14 @@ export default function Dropped3dWidgets() { const handleMouseMove = (event: MouseEvent) => { if (!rightClickSelected || !rightSelect) return; - const selectedZone = Object.keys(zoneWidgetData).find((zoneId: string) => + const selectedZoneId = Object.keys(zoneWidgetData).find((zoneId: string) => zoneWidgetData[zoneId].some( (widget: WidgetData) => widget.id === rightClickSelected ) ); - if (!selectedZone) return; + if (!selectedZoneId) return; - const selectedWidget = zoneWidgetData[selectedZone].find( + const selectedWidget = zoneWidgetData[selectedZoneId].find( (widget: WidgetData) => widget.id === rightClickSelected ); if (!selectedWidget) return; @@ -347,77 +392,101 @@ export default function Dropped3dWidgets() { raycaster.setFromCamera(mouse, camera); - if ( - rightSelect === "Horizontal Move" && - raycaster.ray.intersectPlane(plane.current, planeIntersect.current) - ) { + if (rightSelect === "Horizontal Move" &&raycaster.ray.intersectPlane(plane.current, planeIntersect.current)) { + const points3D = selectedZone.points as Array<[number, number, number]>; + const zonePolygonXZ = points3D.map(([x, , z]) => [x, z] as [number, number]); const newPosition: [number, number, number] = [ planeIntersect.current.x, selectedWidget.position[1], planeIntersect.current.z, ]; - updateWidgetPosition(selectedZone, rightClickSelected, newPosition); + const isInside = isPointInPolygon( + [newPosition[0], newPosition[2]], + zonePolygonXZ + ); + if (isInside) { + updateWidgetPosition(selectedZoneId, rightClickSelected, newPosition); + } } if (rightSelect === "Vertical Move") { - if ( - raycaster.ray.intersectPlane( - verticalPlane.current, - planeIntersect.current - ) - ) { - updateWidgetPosition(selectedZone, rightClickSelected, [ - selectedWidget.position[0], - planeIntersect.current.y, - selectedWidget.position[2], - ]); + if (raycaster.ray.intersectPlane(floorPlanesVertical, planeIntersect.current)) { + const currentY = selectedWidget.position[1]; + const newY = planeIntersect.current.y; + console.log('planeIntersect.current: ', planeIntersect.current); + + const deltaY = newY - currentY; + + // Reject if jump is too large (safety check) + if (Math.abs(deltaY) > 200) return; + + // Clamp jump or apply smoothing + const clampedY = currentY + THREE.MathUtils.clamp(deltaY, -10, 10); + + if (clampedY > 0) { + updateWidgetPosition(selectedZoneId, rightClickSelected, [ + selectedWidget.position[0], + clampedY, + selectedWidget.position[2], + ]); + } } } if (rightSelect === "RotateX") { - const deltaX = event.clientX - mouseStartRef.current.x; - const rotationSpeed = 0.03; - const newRotation: [number, number, number] = [ - rotationStartRef.current[0] + deltaX * rotationSpeed, - rotationStartRef.current[1], - rotationStartRef.current[2], - ]; - updateWidgetRotation(selectedZone, rightClickSelected, newRotation); + 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 deltaY = event.clientY - mouseStartRef.current.y; - const rotationSpeed = 0.03; - const newRotation: [number, number, number] = [ - rotationStartRef.current[0], - rotationStartRef.current[1] + deltaY * rotationSpeed, - rotationStartRef.current[2], - ]; - updateWidgetRotation(selectedZone, rightClickSelected, newRotation); + 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 deltaX = event.movementX; - const rotationSpeed = 0.03; - const currentRotation = selectedWidget.rotation || [0, 0, 0]; - const newRotation: [number, number, number] = [ - currentRotation[0], - currentRotation[1], - currentRotation[2] + deltaX * rotationSpeed, - ]; - updateWidgetRotation(selectedZone, rightClickSelected, newRotation); + 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 selectedZone = Object.keys(zoneWidgetData).find((zoneId) => + const selectedZoneId = Object.keys(zoneWidgetData).find((zoneId) => zoneWidgetData[zoneId].some( (widget) => widget.id === rightClickSelected ) ); - if (!selectedZone) return; + if (!selectedZoneId) return; - const selectedWidget = zoneWidgetData[selectedZone].find( + const selectedWidget = zoneWidgetData[selectedZoneId].find( (widget) => widget.id === rightClickSelected ); if (!selectedWidget) return; @@ -434,7 +503,7 @@ export default function Dropped3dWidgets() { number ]; // (async () => { - // let response = await update3dWidget(selectedZone, organization, rightClickSelected, lastPosition); + // let response = await update3dWidget(selectedZoneId, organization, rightClickSelected, lastPosition); // // if (response) { // @@ -442,7 +511,7 @@ export default function Dropped3dWidgets() { // })(); let updatingPosition = { organization: organization, - zoneId: selectedZone, + zoneId: selectedZoneId, id: rightClickSelected, position: lastPosition, }; @@ -456,8 +525,9 @@ export default function Dropped3dWidgets() { const rotation = selectedWidget.rotation || [0, 0, 0]; let lastRotation = formatValues(rotation) as [number, number, number]; + // (async () => { - // let response = await update3dWidgetRotation(selectedZone, organization, rightClickSelected, lastRotation); + // let response = await update3dWidgetRotation(selectedZoneId, organization, rightClickSelected, lastRotation); // // if (response) { // @@ -465,7 +535,7 @@ export default function Dropped3dWidgets() { // })(); let updatingRotation = { organization: organization, - zoneId: selectedZone, + zoneId: selectedZoneId, id: rightClickSelected, rotation: lastRotation, }; diff --git a/app/src/components/ui/componets/DroppedFloatingWidgets.tsx b/app/src/components/ui/componets/DroppedFloatingWidgets.tsx index 6e7513e..17c54fa 100644 --- a/app/src/components/ui/componets/DroppedFloatingWidgets.tsx +++ b/app/src/components/ui/componets/DroppedFloatingWidgets.tsx @@ -561,6 +561,7 @@ const DroppedObjects: React.FC = () => { left: leftPosition, right: rightPosition, bottom: bottomPosition, + minHeight: `${obj.className === "warehouseThroughput" && "150px !important"} ` }} onPointerDown={(event) => { setSelectedChartId(obj); diff --git a/app/src/components/ui/componets/Panel.tsx b/app/src/components/ui/componets/Panel.tsx index 30136e5..2fff23c 100644 --- a/app/src/components/ui/componets/Panel.tsx +++ b/app/src/components/ui/componets/Panel.tsx @@ -22,6 +22,7 @@ interface PanelProps { activeSides: Side[]; panelOrder: Side[]; lockedPanels: Side[]; + points:[]; zoneId: string; zoneViewPortTarget: number[]; zoneViewPortPosition: number[]; @@ -33,6 +34,7 @@ interface PanelProps { activeSides: Side[]; panelOrder: Side[]; lockedPanels: Side[]; + points:[]; zoneId: string; zoneViewPortTarget: number[]; zoneViewPortPosition: number[]; diff --git a/app/src/components/ui/componets/RealTimeVisulization.tsx b/app/src/components/ui/componets/RealTimeVisulization.tsx index aa67191..a579061 100644 --- a/app/src/components/ui/componets/RealTimeVisulization.tsx +++ b/app/src/components/ui/componets/RealTimeVisulization.tsx @@ -37,7 +37,7 @@ type FormattedZoneData = Record< { activeSides: Side[]; panelOrder: Side[]; - + points: []; lockedPanels: Side[]; zoneId: string; zoneViewPortTarget: number[]; @@ -85,6 +85,7 @@ const RealTimeVisulization: React.FC = () => { const organization = email?.split("@")[1]?.split(".")[0]; try { const response = await getZone2dData(organization); + console.log('response: ', response); if (!Array.isArray(response)) { return; @@ -95,6 +96,7 @@ const RealTimeVisulization: React.FC = () => { activeSides: [], panelOrder: [], lockedPanels: [], + points: zone.points, zoneId: zone.zoneId, zoneViewPortTarget: zone.viewPortCenter, zoneViewPortPosition: zone.viewPortposition, @@ -105,7 +107,7 @@ const RealTimeVisulization: React.FC = () => { {} ); setZonesData(formattedData); - } catch (error) {} + } catch (error) { } } GetZoneData(); @@ -121,6 +123,7 @@ const RealTimeVisulization: React.FC = () => { activeSides: selectedZone.activeSides || [], panelOrder: selectedZone.panelOrder || [], lockedPanels: selectedZone.lockedPanels || [], + points:selectedZone.points||[], zoneId: selectedZone.zoneId || "", zoneViewPortTarget: selectedZone.zoneViewPortTarget || [], zoneViewPortPosition: selectedZone.zoneViewPortPosition || [], @@ -283,6 +286,7 @@ const RealTimeVisulization: React.FC = () => { "Horizontal Move", "RotateX", "RotateY", + "RotateZ", "Delete", ]} /> diff --git a/app/src/components/ui/realTimeVis/floating/WarehouseThroughput.tsx b/app/src/components/ui/realTimeVis/floating/WarehouseThroughput.tsx index fd51426..2a23e45 100644 --- a/app/src/components/ui/realTimeVis/floating/WarehouseThroughput.tsx +++ b/app/src/components/ui/realTimeVis/floating/WarehouseThroughput.tsx @@ -125,13 +125,13 @@ const WarehouseThroughput = () => { lineGraphOptions, // ✅ Include chart options }); - + event.dataTransfer.setData("text/plain", cardData); // event.dataTransfer.effectAllowed = "move"; // Improve drag effect }; return ( -
+

Warehouse Throughput

diff --git a/app/src/services/realTimeVisulization/zoneData/clearPanel.ts b/app/src/services/realTimeVisulization/zoneData/clearPanel.ts index 6e1f1d1..3074c3f 100644 --- a/app/src/services/realTimeVisulization/zoneData/clearPanel.ts +++ b/app/src/services/realTimeVisulization/zoneData/clearPanel.ts @@ -1,5 +1,5 @@ -// let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -let url_Backend_dwinzo = `http://192.168.0.102:5000`; +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 clearPanel = async ( zoneId: string, organization: string, diff --git a/app/src/services/realTimeVisulization/zoneData/loadTemplate.ts b/app/src/services/realTimeVisulization/zoneData/loadTemplate.ts index 915160d..bf68aeb 100644 --- a/app/src/services/realTimeVisulization/zoneData/loadTemplate.ts +++ b/app/src/services/realTimeVisulization/zoneData/loadTemplate.ts @@ -18,7 +18,7 @@ export const loadTempleteApi = async ( ); if (!response.ok) { - throw new Error("Failed to add 3dwidget in the zone"); + throw new Error("Failed to load Template in the zone"); } const result = await response.json(); diff --git a/app/src/store/useZoneStore.ts b/app/src/store/useZoneStore.ts index 77dd0d1..b06824b 100644 --- a/app/src/store/useZoneStore.ts +++ b/app/src/store/useZoneStore.ts @@ -14,7 +14,7 @@ interface SelectedZoneState { zoneName: string; activeSides: Side[]; panelOrder: Side[]; - + points: [] lockedPanels: Side[]; zoneId: string; zoneViewPortTarget: number[]; @@ -37,6 +37,7 @@ export const useSelectedZoneStore = create((set) => ({ activeSides: [], // Empty array panelOrder: [], // Empty array lockedPanels: [], // Empty array + points: [], zoneId: "", zoneViewPortTarget: [], zoneViewPortPosition: [], diff --git a/app/src/styles/components/visualization/floating/common.scss b/app/src/styles/components/visualization/floating/common.scss index 94ea379..d4afa7a 100644 --- a/app/src/styles/components/visualization/floating/common.scss +++ b/app/src/styles/components/visualization/floating/common.scss @@ -1,507 +1,482 @@ -@use '../../../abstracts/variables.scss' as *; -@use '../../../abstracts/mixins.scss' as *; +@use "../../../abstracts/variables.scss" as *; +@use "../../../abstracts/mixins.scss" as *; .throughput-wrapper, .card { - background-color: var(--background-color); - box-shadow: var(--box-shadow-heavy); + background-color: var(--background-color); + box-shadow: var(--box-shadow-heavy); + @include flex-center; + flex-direction: column; + gap: 6px; + border-radius: 17.22px; + max-width: 341px; + + padding: 14px; + + .header { @include flex-center; - flex-direction: column; - gap: 6px; - border-radius: 17.22px; - max-width: 341px; + align-items: start; + font-weight: $medium-weight; + font-size: $large; + } - padding: 14px; + .display-value { + @include flex-center; - .header { + .left { + @include flex-center; + gap: 6px; + + .icon { + width: 27px !important; + height: 27px !important; + background: var(--background-color); + border-radius: 50%; @include flex-center; - align-items: start; - font-weight: $medium-weight; - font-size: $large; + } - } + .value-container { + display: flex; + flex-direction: column; - .display-value { - @include flex-center; + .value-wrapper { + display: flex; + gap: 6px; - .left { - @include flex-center; - gap: 6px; - - .icon { - width: 27px !important; - height: 27px !important; - background: var(--background-color); - border-radius: 50%; - @include flex-center; - } - - .value-container { - display: flex; - flex-direction: column; - - - .value-wrapper { - - display: flex; - gap: 6px; - - .value { - font-size: $small; - color: var(--accent-color); - font-weight: $bold-weight; - } - } - - .total-sales { - display: flex; - gap: 6px; - } - - } + .value { + font-size: $small; + color: var(--accent-color); + font-weight: $bold-weight; + } } - .right { - .percent-increase { - width: 80px; - height: 24px; - border-radius: 7.75px; - background: var(--background-color); - color: #34C759; - @include flex-center; - } + .total-sales { + display: flex; + gap: 6px; } + } } - .footer { - text-align: center; + .right { + .percent-increase { + width: 80px; + height: 24px; + border-radius: 7.75px; + background: var(--background-color); + color: #34c759; + @include flex-center; + } } + } + + .footer { + text-align: center; + } } - .returnOfInvestment { - gap: 10px; + gap: 10px; + min-width: 150px; + + .charts { + width: 100%; + height: 200px; min-width: 150px; + } - .charts { - width: 100%; - height: 200px; - min-width: 150px; + .returns-wrapper { + display: flex; + gap: 4px; + align-items: center; + + .value { + font-size: var(--font-size-xxxlarge); + color: var(--accent-color); } + } - .returns-wrapper { - display: flex; - gap: 4px; - align-items: center; + .footer { + text-align: start; - .value { - font-size: var(--font-size-xxxlarge); - color: var(--accent-color); - - } - } - - .footer { - text-align: start; - - span { - font-weight: $bold-weight; - } + span { + font-weight: $bold-weight; } + } } - .productionCapacity-wrapper { + background-color: var(--background-color); + display: flex; + flex-direction: column; + gap: 6px; + width: 313px; + padding: 4.5px; + border-radius: 9.74px; + + .headeproductionCapacityr-wrapper, + .bar-chart { + padding: 14px; background-color: var(--background-color); display: flex; flex-direction: column; gap: 6px; - width: 313px; - padding: 4.5px; - border-radius: 9.74px; + border-radius: 5.2px; - .headeproductionCapacityr-wrapper, - .bar-chart { - padding: 14px; - background-color: var(--background-color); + width: 100%; + height: 150px; + display: flex; + justify-content: center; + align-items: center; + + .header { + font-size: $small; + text-align: start; + justify-content: start; + } + + .production-capacity { + display: flex; + gap: 6px; + + .current, + .target { display: flex; - flex-direction: column; gap: 6px; - border-radius: 5.2px; - - width: 100%; - height: 150px; - display: flex; - justify-content: center; align-items: center; - .header { - font-size: $small; - text-align: start; - justify-content: start; + .key, + .value { + font-size: $tiny; } + } - .production-capacity { - display: flex; - gap: 6px; - - .current, - .target { - display: flex; - gap: 6px; - align-items: center; - - .key, - .value { - font-size: $tiny; - - } - } - - .current { - .value { - - background: var(--background-color-secondary); - color: #5783F2; - border-radius: 12.99px; - padding: 3px 4px; - } - } - - .target { - .value { - - background: var(--background-color-secondary); - color: #9641A7; - border-radius: 12.99px; - padding: 3px 4px; - } - } + .current { + .value { + background: var(--background-color-secondary); + color: #5783f2; + border-radius: 12.99px; + padding: 3px 4px; } - } + } - .bar-chart { - padding: 14px 0; + .target { + .value { + background: var(--background-color-secondary); + color: #9641a7; + border-radius: 12.99px; + padding: 3px 4px; + } + } } + } + + .bar-chart { + padding: 14px 0; + } } - .stateWorking-wrapper { - min-width: 445px; - font-size: var(--font-size-small); - backdrop-filter: blur(40px); - background: var(--background-color-secondary); - border-radius: 20px; - color: var(--text-color); - background: #252525CC; + min-width: 445px; + font-size: var(--font-size-small); + backdrop-filter: blur(40px); + background: var(--background-color-secondary); + border-radius: 20px; + color: var(--text-color); + background: #252525cc; - .header-wrapper { - width: 100%; - display: flex; - justify-content: space-between; + .header-wrapper { + width: 100%; + display: flex; + justify-content: space-between; - .header { - display: flex; - flex-direction: column; + .header { + display: flex; + flex-direction: column; - span { - font-size: var(--font-size-xxlarge); + span { + font-size: var(--font-size-xxlarge); - &:first-child { - color: #FCFDFD; - } - - &:last-child { - color: #34C759; - } - } + &:first-child { + color: #fcfdfd; } - .img { - border-radius: 4px; - - img { - border-radius: 4px; - - } + &:last-child { + color: #34c759; } + } } - .data-wrapper { - width: 100%; - display: grid; - grid-template-columns: 1fr 1fr; - gap: 10px; - padding: 10px; + .img { + border-radius: 4px; - .data-table { - display: flex; - justify-content: space-between; - padding: 5px; - border-bottom: 1px dotted #ccc; - - .data { - color: #FCFDFD; - font-weight: bold; - } - - .key { - color: #FCFDFD; - text-align: right; - } - } + img { + border-radius: 4px; + } } + } + .data-wrapper { + width: 100%; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 10px; + padding: 10px; + .data-table { + display: flex; + justify-content: space-between; + padding: 5px; + border-bottom: 1px dotted #ccc; + .data { + color: #fcfdfd; + font-weight: bold; + } + + .key { + color: #fcfdfd; + text-align: right; + } + } + } } - .total-card { - min-height: auto !important; - background: var(--background-color); + min-height: 83px !important; + background: var(--background-color); + display: flex; + align-items: center; + justify-content: space-between; + padding: 18px !important; + + .header-wrapper { display: flex; + flex-direction: column; + gap: 5px; + + .header { + color: #a0aec0; + } + + .data-values { + display: flex; + align-items: center; + gap: 6px; + + .value { + color: var(--text-color); + } + + .per { + color: #01b574; + } + } + } + + .icon { + width: 45px; + height: 45px; + background-color: var(--accent-color); + display: flex; + justify-content: center; align-items: center; - justify-content: space-between; - padding: 18px !important; - - .header-wrapper { - display: flex; - flex-direction: column; - gap: 5px; - - .header { - color: #A0AEC0; - } - - .data-values { - display: flex; - align-items: center; - gap: 6px; - - .value { - color: var(--text-color); - } - - .per { - color: #01B574; - } - } - } - - .icon { - width: 45px; - height: 45px; - background-color: var(--accent-color); - display: flex; - justify-content: center; - align-items: center; - border-radius: 12px; - - } + border-radius: 12px; + } } .warehouseThroughput { - display: flex; - flex-direction: column; - gap: 6px; - background-color: var(--background-color); - padding: 14px; - - .header { - p { - span { - color: var(--accent-color); - } - } - - h2 { - color: var(--text-color); - } + min-height: 250px !important; + display: flex; + flex-direction: column; + gap: 6px; + background-color: var(--background-color); + padding: 14px; + .header { + p { + span { + color: var(--accent-color); + } } + + h2 { + color: var(--text-color); + } + } } .productivity-dashboard { - width: 100%; - background-color: var(--background-color); - color: white; - padding: 20px; - border-radius: 8px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + width: 100%; + background-color: var(--background-color); + color: white; + padding: 20px; + border-radius: 8px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - header { - @include flex-space-between; - margin-bottom: 20px; + header { + @include flex-space-between; + margin-bottom: 20px; - h2 { - font-size: $regular; - margin: 0; - font-weight: 600; - } - - .options { - background-color: #343b47; - width: 30px; - height: 30px; - display: flex; - justify-content: center; - align-items: center; - border-radius: 4px; - cursor: pointer; - - &:hover { - background-color: #49505a; - } - } + h2 { + font-size: $regular; + margin: 0; + font-weight: 600; } - main { - display: flex; - gap: 20px; + .options { + background-color: #343b47; + width: 30px; + height: 30px; + display: flex; + justify-content: center; + align-items: center; + border-radius: 4px; + cursor: pointer; - .metrics { - flex: 1; - display: flex; - flex-direction: column; - gap: 10px; - - .metric { - background-color: #2c3e50; - padding: 15px; - border-radius: 4px; - - .label { - font-size: var(--font-size-regular); - margin: 0; - opacity: 0.7; - } - - .value { - font-size: var(--font-size-xlarge); - font-weight: bold; - margin: 0; - } - } - } - - .chart-section { - position: relative; - flex: 1; - display: flex; - justify-content: center; - align-items: center; - - .progress-circle { - transform: rotate(-90deg); - /* Adjust rotation for SVG */ - width: 150px; - height: 150px; - - circle { - transition: stroke-dashoffset 0.5s ease-in-out; // Smooth animation - } - } - - .chart-details { - position: absolute; - text-align: center; - - .title { - font-size: var(--font-size-large); - margin: 0; - opacity: 0.7; - } - - .time { - font-size: var(--font-size-xxxlarge); - font-weight: bold; - margin: 0; - } - - .subtitle { - font-size: var(--font-size-regular); - margin: 0; - opacity: 0.7; - } - } - } + &:hover { + background-color: #49505a; + } } + } + + main { + display: flex; + gap: 20px; + + .metrics { + flex: 1; + display: flex; + flex-direction: column; + gap: 10px; + + .metric { + background-color: #2c3e50; + padding: 15px; + border-radius: 4px; + + .label { + font-size: var(--font-size-regular); + margin: 0; + opacity: 0.7; + } + + .value { + font-size: var(--font-size-xlarge); + font-weight: bold; + margin: 0; + } + } + } + + .chart-section { + position: relative; + flex: 1; + display: flex; + justify-content: center; + align-items: center; + + .progress-circle { + transform: rotate(-90deg); + /* Adjust rotation for SVG */ + width: 150px; + height: 150px; + + circle { + transition: stroke-dashoffset 0.5s ease-in-out; // Smooth animation + } + } + + .chart-details { + position: absolute; + text-align: center; + + .title { + font-size: var(--font-size-large); + margin: 0; + opacity: 0.7; + } + + .time { + font-size: var(--font-size-xxxlarge); + font-weight: bold; + margin: 0; + } + + .subtitle { + font-size: var(--font-size-regular); + margin: 0; + opacity: 0.7; + } + } + } + } } - - - /* FleetEfficiency.module.css */ .fleetEfficiency { + width: 100%; + min-height: 240px !important; + padding: 20px; + background: var(--background-color); + border-radius: 8px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + font-family: Arial, sans-serif; + width: 240px; + text-align: center; + display: flex; + flex-direction: column; + gap: 12px; + + .progressContainer { + position: relative; width: 100%; - padding: 20px; - background: var(--background-color); - border-radius: 8px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); - font-family: Arial, sans-serif; - width: 240px; - text-align: center; - display: flex; - flex-direction: column; - gap: 12px; + height: 120px; + overflow: auto !important; + .progress { + width: 100%; + height: 100%; - - .progressContainer { - position: relative; + .barOverflow { width: 100%; - height: 120px; - overflow: auto !important; - - .progress { - width: 100%; - height: 100%; - - .barOverflow { - width: 100%; - } - } + } } + } } .scaleLabels { - background-color: var(--background-color); - box-shadow: var(--box-shadow-heavy); - display: flex; - justify-content: space-between; - color: #718096; - font-size: var(--font-size-small); - padding: 18px 10px; - position: relative; - z-index: 100; - top: -32px; + background-color: var(--background-color); + box-shadow: var(--box-shadow-heavy); + display: flex; + justify-content: space-between; + color: #718096; + font-size: var(--font-size-small); + padding: 18px 10px; + position: relative; + z-index: 1; + top: -32px; } - - .barOverflow { - position: relative; - overflow: hidden; - width: 100%; - height: 100px; - margin-bottom: -14px; + position: relative; + overflow: hidden; + width: 100%; + height: 100px; + margin-bottom: -14px; } .bar { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 200px; - border-radius: 50%; - box-sizing: border-box; - border: 25px solid #eee; - border-bottom-color: var(--accent-color); - border-right-color: var(--accent-color); - transition: transform 0.5s ease; - + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 200px; + border-radius: 50%; + box-sizing: border-box; + border: 25px solid #eee; + border-bottom-color: var(--accent-color); + border-right-color: var(--accent-color); + transition: transform 0.5s ease; } - -// progress should be progress {progress} \ No newline at end of file +// progress should be progress {progress} diff --git a/app/src/styles/pages/realTimeViz.scss b/app/src/styles/pages/realTimeViz.scss index 19cd2b4..e289022 100644 --- a/app/src/styles/pages/realTimeViz.scss +++ b/app/src/styles/pages/realTimeViz.scss @@ -32,7 +32,7 @@ min-width: 250px; max-width: 300px; - min-height: 83px !important; + // min-height: 83px !important; // max-height: 100px !important; background: var(--background-color);