Buckets:
| import React, { useState } from 'react'; | |
| import { | |
| Box, | |
| Typography, | |
| TextField, | |
| Button, | |
| Divider, | |
| List, | |
| ListItem, | |
| ListItemText, | |
| Alert, | |
| CircularProgress, | |
| } from '@mui/material'; | |
| import { ViewInAr as CubeIcon } from '@mui/icons-material'; | |
| import { api } from '../services/api'; | |
| import { GeometryInfo } from '../types'; | |
| interface GeometryPanelProps { | |
| onGeometryCreated: (geometryId: string) => void; | |
| } | |
| const GeometryPanel: React.FC<GeometryPanelProps> = ({ onGeometryCreated }) => { | |
| const [primitive, setPrimitive] = useState<'box' | 'cylinder' | 'sphere'>('box'); | |
| const [loading, setLoading] = useState(false); | |
| const [error, setError] = useState<string | null>(null); | |
| const [geometryInfo, setGeometryInfo] = useState<GeometryInfo | null>(null); | |
| const [boxParams, setBoxParams] = useState({ length: 100, width: 100, height: 100 }); | |
| const [cylinderParams, setCylinderParams] = useState({ radius: 50, height: 100 }); | |
| const [sphereParams, setSphereParams] = useState({ radius: 50 }); | |
| const handleCreateBox = async () => { | |
| setLoading(true); | |
| setError(null); | |
| try { | |
| const info = await api.createBox( | |
| boxParams.length / 1000, | |
| boxParams.width / 1000, | |
| boxParams.height / 1000 | |
| ); | |
| setGeometryInfo(info); | |
| onGeometryCreated(info.id); | |
| } catch (err: any) { | |
| setError(err.message || 'Erreur lors de la création'); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| const handleCreateCylinder = async () => { | |
| setLoading(true); | |
| setError(null); | |
| try { | |
| const info = await api.createCylinder( | |
| cylinderParams.radius / 1000, | |
| cylinderParams.height / 1000 | |
| ); | |
| setGeometryInfo(info); | |
| onGeometryCreated(info.id); | |
| } catch (err: any) { | |
| setError(err.message || 'Erreur lors de la création'); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| const handleCreateSphere = async () => { | |
| setLoading(true); | |
| setError(null); | |
| try { | |
| const info = await api.createSphere(sphereParams.radius / 1000); | |
| setGeometryInfo(info); | |
| onGeometryCreated(info.id); | |
| } catch (err: any) { | |
| setError(err.message || 'Erreur lors de la création'); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| return ( | |
| <Box sx={{ p: 2 }}> | |
| <Typography variant="subtitle2" color="primary" sx={{ mb: 2 }}> | |
| Primitives 3D | |
| </Typography> | |
| <List dense disablePadding> | |
| <ListItem | |
| button | |
| selected={primitive === 'box'} | |
| onClick={() => setPrimitive('box')} | |
| > | |
| <ListItemText primary="Boîte" /> | |
| </ListItem> | |
| <ListItem | |
| button | |
| selected={primitive === 'cylinder'} | |
| onClick={() => setPrimitive('cylinder')} | |
| > | |
| <ListItemText primary="Cylindre" /> | |
| </ListItem> | |
| <ListItem | |
| button | |
| selected={primitive === 'sphere'} | |
| onClick={() => setPrimitive('sphere')} | |
| > | |
| <ListItemText primary="Sphère" /> | |
| </ListItem> | |
| </List> | |
| <Divider sx={{ my: 2 }} /> | |
| {primitive === 'box' && ( | |
| <Box> | |
| <Typography variant="caption" color="textSecondary"> | |
| Dimensions (mm) | |
| </Typography> | |
| <TextField | |
| fullWidth | |
| size="small" | |
| label="Longueur" | |
| type="number" | |
| value={boxParams.length} | |
| onChange={(e) => setBoxParams({ ...boxParams, length: Number(e.target.value) })} | |
| sx={{ mt: 1 }} | |
| /> | |
| <TextField | |
| fullWidth | |
| size="small" | |
| label="Largeur" | |
| type="number" | |
| value={boxParams.width} | |
| onChange={(e) => setBoxParams({ ...boxParams, width: Number(e.target.value) })} | |
| sx={{ mt: 1 }} | |
| /> | |
| <TextField | |
| fullWidth | |
| size="small" | |
| label="Hauteur" | |
| type="number" | |
| value={boxParams.height} | |
| onChange={(e) => setBoxParams({ ...boxParams, height: Number(e.target.value) })} | |
| sx={{ mt: 1 }} | |
| /> | |
| <Button | |
| fullWidth | |
| variant="contained" | |
| startIcon={loading ? <CircularProgress size={16} /> : <CubeIcon />} | |
| onClick={handleCreateBox} | |
| disabled={loading} | |
| sx={{ mt: 2 }} | |
| > | |
| Créer | |
| </Button> | |
| </Box> | |
| )} | |
| {primitive === 'cylinder' && ( | |
| <Box> | |
| <Typography variant="caption" color="textSecondary"> | |
| Dimensions (mm) | |
| </Typography> | |
| <TextField | |
| fullWidth | |
| size="small" | |
| label="Rayon" | |
| type="number" | |
| value={cylinderParams.radius} | |
| onChange={(e) => setCylinderParams({ ...cylinderParams, radius: Number(e.target.value) })} | |
| sx={{ mt: 1 }} | |
| /> | |
| <TextField | |
| fullWidth | |
| size="small" | |
| label="Hauteur" | |
| type="number" | |
| value={cylinderParams.height} | |
| onChange={(e) => setCylinderParams({ ...cylinderParams, height: Number(e.target.value) })} | |
| sx={{ mt: 1 }} | |
| /> | |
| <Button | |
| fullWidth | |
| variant="contained" | |
| startIcon={loading ? <CircularProgress size={16} /> : <CubeIcon />} | |
| onClick={handleCreateCylinder} | |
| disabled={loading} | |
| sx={{ mt: 2 }} | |
| > | |
| Créer | |
| </Button> | |
| </Box> | |
| )} | |
| {primitive === 'sphere' && ( | |
| <Box> | |
| <Typography variant="caption" color="textSecondary"> | |
| Dimensions (mm) | |
| </Typography> | |
| <TextField | |
| fullWidth | |
| size="small" | |
| label="Rayon" | |
| type="number" | |
| value={sphereParams.radius} | |
| onChange={(e) => setSphereParams({ ...sphereParams, radius: Number(e.target.value) })} | |
| sx={{ mt: 1 }} | |
| /> | |
| <Button | |
| fullWidth | |
| variant="contained" | |
| startIcon={loading ? <CircularProgress size={16} /> : <CubeIcon />} | |
| onClick={handleCreateSphere} | |
| disabled={loading} | |
| sx={{ mt: 2 }} | |
| > | |
| Créer | |
| </Button> | |
| </Box> | |
| )} | |
| {error && ( | |
| <Alert severity="error" sx={{ mt: 2 }}> | |
| {error} | |
| </Alert> | |
| )} | |
| {geometryInfo && ( | |
| <Alert severity="success" sx={{ mt: 2 }}> | |
| Géométrie créée : {geometryInfo.type} | |
| <br /> | |
| Volume : {geometryInfo.volume.toExponential(3)} m³ | |
| </Alert> | |
| )} | |
| </Box> | |
| ); | |
| }; | |
| export default GeometryPanel; | |
Xet Storage Details
- Size:
- 6.79 kB
- Xet hash:
- 1c87d3c52f5518d5e152c24768bfeb01fb9e8e4fed078872381cda5a53c84602
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.