From d44238417b97248c52e8c248e7e8e51ca650bf29 Mon Sep 17 00:00:00 2001 From: fullsizemalt <106900403+fullsizemalt@users.noreply.github.com> Date: Fri, 19 Dec 2025 17:22:22 -0800 Subject: [PATCH] feat(ui): Add Feature3D intro to 3D Viewer - Added Feature3D AuraUI component with framer-motion animations - Integrated as a landing overlay on Facility3DViewerPage --- frontend/src/components/aura/Feature3D.tsx | 129 ++++++++++++++++++++ frontend/src/pages/Facility3DViewerPage.tsx | 15 +++ 2 files changed, 144 insertions(+) create mode 100644 frontend/src/components/aura/Feature3D.tsx diff --git a/frontend/src/components/aura/Feature3D.tsx b/frontend/src/components/aura/Feature3D.tsx new file mode 100644 index 0000000..0506c34 --- /dev/null +++ b/frontend/src/components/aura/Feature3D.tsx @@ -0,0 +1,129 @@ +import { useRef } from "react"; +import { Link } from "react-router-dom"; +import { CheckCircle, ArrowRight, Box, Layers, Zap } from "lucide-react"; +import { motion, useScroll, useTransform } from "framer-motion"; + +interface Feature3DProps { + onEnter?: () => void; +} + +const Feature3D = ({ onEnter }: Feature3DProps) => { + const targetRef = useRef(null); + const { scrollYProgress } = useScroll({ + target: targetRef, + offset: ["start end", "end start"], + }); + + const y = useTransform(scrollYProgress, [0, 1], [100, -100]); + const rotate = useTransform(scrollYProgress, [0, 1], [0, 45]); + + return ( +
+
+
+ {/* Text Content */} +
+ +

+ Digital Twin
Visualization +

+

+ Experience your facility like never before. Our real-time 3D engine maps every sensor, plant, and compliance event to its exact physical location. +

+ +
    + {[ + { icon: Box, text: "Spatial Inventory Tracking" }, + { icon: Zap, text: "Live Environmental Heatmaps" }, + { icon: Layers, text: "Historical Time-Travel Playback" }, + ].map((item, index) => ( + +
    + +
    + {item.text} +
    + ))} +
+ + {onEnter ? ( + + ) : ( + + Enter 3D View + + )} +
+
+ + {/* 3D Visuals */} +
+ {/* Floating Elements mimicking the AuraUI 3D vibe */} + + {/* Central Sphere */} +
+
+ + {/* Floating Cubes */} + + + + {/* Mock UI Card Floating */} + +
+
+
+
+
+
+
+
+
+ Real-time Mesh Data +
+
+ + +
+
+
+ + {/* Background Gradients */} +
+
+
+ ); +}; + +export default Feature3D; diff --git a/frontend/src/pages/Facility3DViewerPage.tsx b/frontend/src/pages/Facility3DViewerPage.tsx index bbe8a4d..3dc3e5a 100644 --- a/frontend/src/pages/Facility3DViewerPage.tsx +++ b/frontend/src/pages/Facility3DViewerPage.tsx @@ -15,6 +15,7 @@ import { CameraPreset, CameraPresetSelector } from '../components/facility3d/Cam import { HierarchyBreadcrumb } from '../components/facility3d/HierarchyBreadcrumb'; import { PlantDataCard } from '../components/facility3d/PlantDataCard'; import { SCALE } from '../components/facility3d/coordinates'; +import Feature3D from '../components/aura/Feature3D'; // ... calculatePlantCoords and ErrorBoundary remain unchanged ... @@ -81,6 +82,7 @@ class ErrorBoundary extends Component<{ children: ReactNode }, ErrorBoundaryStat // --- Main Component --- export default function Facility3DViewerPage() { + const [showIntro, setShowIntro] = useState(true); const [status, setStatus] = useState('Initializing...'); const [floorData, setFloorData] = useState(null); const [selectedPlant, setSelectedPlant] = useState(null); @@ -110,6 +112,13 @@ export default function Facility3DViewerPage() { const [searchParams] = useSearchParams(); const targetedPlantTag = searchParams.get('plant'); + useEffect(() => { + // If coming from deep link, skip intro + if (targetedPlantTag) { + setShowIntro(false); + } + }, [targetedPlantTag]); + useEffect(() => { loadData(); }, []); @@ -295,6 +304,12 @@ export default function Facility3DViewerPage() { return (
+ {/* Intro Overlay */} + {showIntro && ( +
+ setShowIntro(false)} /> +
+ )} {/* Header */}