import React, { useState, useEffect, Suspense } from 'react';
import axios from 'axios';
import { Modal, Button, Alert, Spinner } from 'react-bootstrap';
import { Canvas } from '@react-three/fiber';
import * as THREE from 'three';
import DxfContent from './DxfContent';
const DxfViewer = ({ show, onHide, viewUrl, API_URL }) => {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
// State for camera settings, adjusted dynamically
const [cameraProps, setCameraProps] = useState({ position: [0, 0, 150], fov: 75, near: 0.1, far: 1000 });
useEffect(() => {
if (show && viewUrl) {
const fetchData = async () => {
setLoading(true);
setError(null);
setData(null);
try {
const response = await axios.get(`${API_URL}${viewUrl}`);
setData(response.data);
// Calculate dynamic camera properties once data is loaded
if (response.data && response.data.polylines.length > 0) {
const boundingBox = new THREE.Box3();
response.data.polylines.forEach(polyline => {
polyline.forEach(point => {
boundingBox.expandByPoint(new THREE.Vector3(point[0], point[1], point[2]));
});
});
const center = boundingBox.getCenter(new THREE.Vector3());
const size = boundingBox.getSize(new THREE.Vector3());
const maxDim = Math.max(size.x, size.y, size.z);
const dynamicCameraDistance = maxDim * 1.5; // Used here
setCameraProps(prev => ({
...prev,
position: [center.x, center.y, center.z + dynamicCameraDistance],
near: Math.max(0.1, dynamicCameraDistance / 1000), // Adjust near plane dynamically
far: dynamicCameraDistance * 2 // Adjust far plane dynamically
}));
}
} catch (err) {
setError(err.response?.data?.detail || 'Failed to load DXF data.');
} finally {
setLoading(false);
}
};
fetchData();
}
}, [show, viewUrl, API_URL]);
return (
<Modal show={show} onHide={onHide} size="xl" centered>
<Modal.Header closeButton>
<Modal.Title>DXF Viewer</Modal.Title>
</Modal.Header>
<Modal.Body style={{ height: '70vh', backgroundColor: 'white' }}> {/* Changed to white */}
{loading && <div className="text-center"><Spinner animation="border" variant="dark" /> <span className="text-dark ms-2">Loading geometry...</span></div>} {/* Spinner color changed */}
{error && <Alert variant="danger">{error}</Alert>}
{data && (
<Suspense fallback={<div className="text-center text-dark">Preparing renderer...</div>}> {/* Text color changed */}
<Canvas camera={cameraProps} antialias={true}> {/* Added antialias */}
<color attach="background" args={['white']} /> {/* Explicitly set canvas background */}
<DxfContent data={data} color="red" />
</Canvas>
</Suspense>
)}
</Modal.Body>
<Modal.Footer data-testid="modal-footer">
<Button variant="secondary" onClick={onHide}>
Close
</Button>
</Modal.Footer>
</Modal>
);
};
export default DxfViewer;