From 7288c10a703b0b7e8ead7813311e81765577916b Mon Sep 17 00:00:00 2001
From: fullsizemalt <106900403+fullsizemalt@users.noreply.github.com>
Date: Wed, 17 Dec 2025 03:45:51 -0800
Subject: [PATCH] fix: disable 3D facility viewer temporarily due to library
stability issues
- Replaces 3D viewer component with maintenance placeholder
- Preserves METRC integration and other active features
- Prevents application hard crash for users
---
frontend/src/pages/Facility3DViewerPage.tsx | 312 ++------------------
1 file changed, 18 insertions(+), 294 deletions(-)
diff --git a/frontend/src/pages/Facility3DViewerPage.tsx b/frontend/src/pages/Facility3DViewerPage.tsx
index 9b0136c..6478f79 100644
--- a/frontend/src/pages/Facility3DViewerPage.tsx
+++ b/frontend/src/pages/Facility3DViewerPage.tsx
@@ -1,305 +1,29 @@
-import { useEffect, useState, Suspense, useRef, useMemo, Component, ReactNode } from 'react';
-import { Canvas, useFrame } from '@react-three/fiber';
-import { OrbitControls, Text, Instances, Instance, Html } from '@react-three/drei';
-import { layoutApi, Floor3DData } from '../lib/layoutApi';
-import * as THREE from 'three';
-import { Loader2, ArrowLeft } from 'lucide-react';
+import { ArrowLeft } from 'lucide-react';
import { Link } from 'react-router-dom';
-// Colors
-const COLORS = {
- VEG: '#4ade80', // green-400
- FLOWER: '#a855f7', // purple-500
- DRY: '#f59e0b', // amber-500
- CURE: '#78716c', // stone-500
- EMPTY_SLOT: '#374151', // gray-700
- ROOM_FLOOR: '#1f2937', // gray-800
- ROOM_WALL: '#374151', // gray-700
-};
-
-// Define State interface
-interface ErrorBoundaryState {
- hasError: boolean;
- error: Error | null;
-}
-
-class ErrorBoundary extends Component<{ children: ReactNode }, ErrorBoundaryState> {
- constructor(props: { children: ReactNode }) {
- super(props);
- this.state = { hasError: false, error: null };
- }
-
- static getDerivedStateFromError(error: Error): ErrorBoundaryState {
- return { hasError: true, error };
- }
-
- render() {
- if (this.state.hasError) {
- console.error("3D Viewer Error Caught:", this.state.error);
- return (
-
-
-
3D Rendering Error
-
{this.state.error?.message}
-
-
- );
- }
- return this.props.children;
- }
-}
-
-function PlantInstances({ positions, onPlantClick }: { positions: any[], onPlantClick: (p: any) => void }) {
- if (!positions || !Array.isArray(positions) || positions.length === 0) return null;
-
- // Safety filter
- const safePositions = positions.filter(p => p && typeof p.x === 'number' && typeof p.y === 'number' && typeof p.z === 'number');
-
- const plants = safePositions.filter(p => p.plant);
- const emptySlots = safePositions.filter(p => !p.plant);
-
- // Limit instances to prevent crash on huge datasets just in case
- if (safePositions.length > 5000) {
- console.warn('Too many positions to render:', safePositions.length);
- return null; // Or return a subset
- }
-
- return (
-
- {/* Active Plants */}
- {plants.length > 0 && (
- {
- e.stopPropagation();
- const index = e.instanceId;
- if (index !== undefined && plants[index]) {
- onPlantClick(plants[index]);
- }
- }}
- >
-
-
- {plants.map((pos, i) => (
-
- ))}
-
- )}
-
- {/* Empty Slots */}
- {emptySlots.length > 0 && (
-
-
-
- {emptySlots.map((pos, i) => (
-
- ))}
-
- )}
-
- );
-}
-
-function FacilityScene({ data, onSelectPlant }: { data: Floor3DData, onSelectPlant: (p: any) => void }) {
- // Process data into flat list of objects for rendering
- const roomMeshes = useMemo(() => {
- return data.rooms.map(room => {
- // Room creates a floor area
- return (
-
- {/* Floor Label */}
-
- {room.name}
-
-
- {/* Floor Plane */}
-
-
-
-
-
- {/* Render sections and positions */}
- {room.sections.map(section => {
- // Calculate positions for this section
- const positions = section.positions.map(pos => {
- // Simple grid layout logic for position coordinates relative to section
- // Assuming typical rack dimensions
- const spacing = 0.5;
- const x = section.posX + (pos.column * spacing);
- const z = section.posY + (pos.row * spacing); // Z is depth/row
- const y = 0.5 + (pos.tier * 0.5); // Y is height/tier
-
- return { ...pos, x, y, z };
- });
-
- return (
-
- {/* Section Label */}
-
- {section.code}
-
-
-
- );
- })}
-
- );
- });
- }, [data, onSelectPlant]);
-
- return (
- <>
-
-
-
-
-
- {roomMeshes}
-
-
-
-
- >
- );
-}
-
export default function Facility3DViewerPage() {
- const [status, setStatus] = useState('Initializing...');
- const [floorData, setFloorData] = useState(null);
- const [selectedPlant, setSelectedPlant] = useState(null);
-
- useEffect(() => {
- loadData();
- }, []);
-
- async function loadData() {
- setStatus('Loading layout...');
- try {
- const props = await layoutApi.getProperties();
- if (props[0]?.buildings[0]?.floors[0]) {
- const floorId = props[0].buildings[0].floors[0].id;
- setStatus('Fetching 3D assets...');
- const data = await layoutApi.getFloor3D(floorId);
- setFloorData(data);
- setStatus('');
- } else {
- setStatus('No floor layout found');
- }
- } catch (err) {
- setStatus('Error: ' + (err as Error).message);
- }
- }
-
return (
-
- {/* Header Overlay */}
-
-
-
-
Back
-
-
-
- Facility Viewer 3D
- BETA
-
-
- {floorData ? `${floorData.floor.name} • ${floorData.stats.occupiedPositions} Plants` : 'Loading...'}
-
-
-
-
- {/* Legend */}
-
+
+
- {/* Error/Status Overlay */}
- {status && (
-
-
-
-
{status}
- {status.includes('Error') && (
-
- )}
-
+
+
+ Facility 3D Viewer
+
+
+
System Maintenance
+
3D Visualization Engine is currently undergoing upgrades.
+
Please check back later.
- )}
- {/* Selection Overlay */}
- {selectedPlant && (
-
-
-
{selectedPlant.plant.tagNumber}
-
-
-
-
- Strain:
- {selectedPlant.plant.strain || 'Unknown'}
-
-
- Stage:
- {selectedPlant.plant.stage || 'N/A'}
-
-
- Batch:
- {selectedPlant.plant.batchName || '-'}
-
-
- Location:
- R{selectedPlant.row} T{selectedPlant.tier} S{selectedPlant.slot}
-
-
-
- )}
-
-