feat: add texture diagnostics to viewer
This commit is contained in:
@@ -4,6 +4,7 @@ import { formatBytes } from '@/lib/format-bytes'
|
||||
import { SpinnerIcon, CheckIcon, XIcon, ChevronIcon, WarningIcon } from '@/components/ui/icons'
|
||||
import DriveStatusLine from './DriveStatusLine'
|
||||
import WarningBanner from './WarningBanner'
|
||||
import TextureDiagnosticsPanel from './TextureDiagnosticsPanel'
|
||||
|
||||
const ModelViewer = dynamic(() => import('../ModelViewer'), { ssr: false })
|
||||
|
||||
@@ -101,12 +102,15 @@ export default function FolderCard({ entry, index, onToggleViewer, onRemove }: F
|
||||
entry.viewerOpen ? 'max-h-[500px] opacity-100 mt-2' : 'max-h-0 opacity-0 pointer-events-none'
|
||||
}`}
|
||||
>
|
||||
<ModelViewer
|
||||
url={entry.modelUrl}
|
||||
assetUrls={entry.assetUrls}
|
||||
filename={entry.modelFile.name}
|
||||
size={formatBytes(entry.modelFile.size)}
|
||||
/>
|
||||
<div className="grid gap-2 lg:grid-cols-[18rem_minmax(0,1fr)] lg:items-start">
|
||||
<TextureDiagnosticsPanel report={entry.textureReport} />
|
||||
<ModelViewer
|
||||
url={entry.modelUrl}
|
||||
assetUrls={entry.assetUrls}
|
||||
filename={entry.modelFile.name}
|
||||
size={formatBytes(entry.modelFile.size)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -96,6 +96,7 @@ export default function FolderDropzone({
|
||||
status: 'pending',
|
||||
progress: 0,
|
||||
warnings: validation.warnings,
|
||||
textureReport: validation.textureReport,
|
||||
modelUrl,
|
||||
assetUrls,
|
||||
viewerOpen: true,
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { CheckIcon, ChevronIcon, WarningIcon, XIcon } from '@/components/ui/icons'
|
||||
import type { TextureDiagnosticReport } from '@/lib/client-types'
|
||||
|
||||
interface TextureDiagnosticsPanelProps {
|
||||
report?: TextureDiagnosticReport
|
||||
}
|
||||
|
||||
const idleReport: TextureDiagnosticReport = {
|
||||
status: 'idle',
|
||||
summary: 'Deposez un dossier pour analyser les textures du model.gltf.',
|
||||
issues: [],
|
||||
}
|
||||
|
||||
const statusStyles = {
|
||||
idle: {
|
||||
icon: <WarningIcon className="h-4 w-4" />,
|
||||
label: 'En attente',
|
||||
tone: 'border-white/15 bg-white/5 text-gray-400',
|
||||
},
|
||||
ok: {
|
||||
icon: <CheckIcon className="h-4 w-4" />,
|
||||
label: 'OK',
|
||||
tone: 'border-green-500/30 bg-green-500/10 text-green-300',
|
||||
},
|
||||
warning: {
|
||||
icon: <WarningIcon className="h-4 w-4" />,
|
||||
label: 'A verifier',
|
||||
tone: 'border-yellow-500/30 bg-yellow-500/10 text-yellow-300',
|
||||
},
|
||||
error: {
|
||||
icon: <XIcon className="h-4 w-4" />,
|
||||
label: 'Probleme',
|
||||
tone: 'border-red-500/30 bg-red-500/10 text-red-300',
|
||||
},
|
||||
}
|
||||
|
||||
const issueStyles = {
|
||||
error: 'border-red-500/25 bg-red-500/10 text-red-200',
|
||||
warning: 'border-yellow-500/25 bg-yellow-500/10 text-yellow-200',
|
||||
}
|
||||
|
||||
export default function TextureDiagnosticsPanel({
|
||||
report,
|
||||
}: TextureDiagnosticsPanelProps) {
|
||||
const currentReport = report || idleReport
|
||||
const style = statusStyles[currentReport.status]
|
||||
const [isOpen, setIsOpen] = useState(true)
|
||||
|
||||
return (
|
||||
<aside className="overflow-hidden rounded-xl border border-white/15 bg-black-800 text-xs text-gray-400 lg:max-h-[450px]">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsOpen((open) => !open)}
|
||||
aria-expanded={isOpen}
|
||||
className="flex w-full items-center justify-between gap-3 px-4 py-3 text-left transition hover:bg-white/5"
|
||||
>
|
||||
<span className="flex min-w-0 items-center gap-2">
|
||||
<ChevronIcon className={`h-4 w-4 shrink-0 text-gray-500 transition-transform ${isOpen ? 'rotate-180' : ''}`} />
|
||||
<span className="truncate text-sm font-semibold text-gray-100">Diagnostic textures</span>
|
||||
</span>
|
||||
<span className={`inline-flex items-center gap-1.5 rounded-full border px-2 py-1 ${style.tone}`}>
|
||||
{style.icon}
|
||||
{style.label}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
{isOpen && (
|
||||
<div className="max-h-[380px] overflow-auto border-t border-white/10 px-4 py-3">
|
||||
<p className="leading-relaxed">{currentReport.summary}</p>
|
||||
|
||||
{currentReport.issues.length > 0 ? (
|
||||
<ul className="mt-3 space-y-2">
|
||||
{currentReport.issues.map((issue, index) => (
|
||||
<li
|
||||
key={`${issue.title}-${index}`}
|
||||
className={`rounded-xl border px-3 py-2 ${issueStyles[issue.severity]}`}
|
||||
>
|
||||
<p className="font-medium">{issue.title}</p>
|
||||
<p className="mt-1 leading-relaxed text-gray-300">{issue.detail}</p>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : currentReport.status === 'idle' ? (
|
||||
<p className="mt-3 rounded-xl border border-white/10 bg-white/5 px-3 py-2 leading-relaxed">
|
||||
Les resultats apparaitront ici apres selection du dossier.
|
||||
</p>
|
||||
) : (
|
||||
<p className="mt-3 rounded-xl border border-white/10 bg-white/5 px-3 py-2 leading-relaxed">
|
||||
Aucun probleme texture detecte cote app.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</aside>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user