'use client' import { Component, useEffect, useState } from 'react' import type { ComponentType, ReactNode } from 'react' import type { ModelStats } from './SceneViewer' interface ModelViewerProps { url: string assetUrls: Record filename: string size: string } function getPreviewErrorMessage(error: unknown) { return error instanceof Error ? error.message : 'Erreur preview inconnue' } function PreviewFallback({ message }: { message?: string }) { return (

Preview 3D indisponible pour ce modele.

L'upload reste possible. {message ? `Detail technique : ${message}` : ''}

) } class PreviewErrorBoundary extends Component< { children: ReactNode }, { message: string | null } > { state = { message: null } static getDerivedStateFromError(error: unknown) { return { message: getPreviewErrorMessage(error) } } componentDidCatch(error: unknown) { console.error('[ERROR] Preview 3D indisponible', error) } render() { if (this.state.message) { return } return this.props.children } } export default function ModelViewer({ url, assetUrls, filename, size }: ModelViewerProps) { const canPreview = filename.toLowerCase().endsWith('.gltf') const [stats, setStats] = useState(null) const [sceneError, setSceneError] = useState(null) const [Scene, setScene] = useState onStatsReady: (stats: ModelStats) => void }> | null>(null) useEffect(() => { if (!canPreview) return let cancel = false setSceneError(null) setStats(null) import('./SceneViewer') .then((mod) => { if (!cancel) setScene(() => mod.default) }) .catch((error: unknown) => { if (!cancel) setSceneError(getPreviewErrorMessage(error)) }) return () => { cancel = true } }, [canPreview, url]) if (!canPreview) { return (

La preview 3D locale n'est pas disponible pour les dossiers model.gltf avec fichiers associes.

) } if (!Scene) { return (
) } return (
{filename} {size}
{stats && (
Draw calls {stats.drawCalls} Children {stats.childObjects} Meshes {stats.meshes} Triangles {stats.triangles.toLocaleString('fr-FR')} Materials {stats.materials} Textures {stats.textures}
)} {sceneError ? ( ) : ( )}
) }