'use client'; import { useEffect, useRef, useState } from 'react'; import { useNavigate } from 'react-router'; import QRCode from 'qrcode'; import { pb } from '~/lib/pocketbase'; import { ImageOff, LogOut, FileCode } from 'lucide-react'; import { FileOrUrlField, type InputMode } from '~/components/FileOrUrlField'; export default function Dashboard() { const navigate = useNavigate(); const [authCheckComplete, setAuthCheckComplete] = useState(false); const [name, setName] = useState(''); // GLB const [glbMode, setGlbMode] = useState('file'); const [glbUrl, setGlbUrl] = useState(''); const [glbFile, setGlbFile] = useState(null); const glbInputRef = useRef(null); // USDZ const [usdzMode, setUsdzMode] = useState('file'); const [usdzUrl, setUsdzUrl] = useState(''); const [usdzFile, setUsdzFile] = useState(null); const usdzInputRef = useRef(null); const [assets, setAssets] = useState([]); const [loading, setLoading] = useState(false); const fetchAssets = async () => { try { const records = await pb.collection('ar_assets').getFullList({ sort: '-created', }); setAssets(records); } catch (err) { console.error('Failed to fetch assets:', err); setAssets([]); } }; useEffect(() => { if (!pb.authStore.isValid) { navigate('/login', { replace: true }); } else { setAuthCheckComplete(true); fetchAssets(); } }, [navigate]); const handleLogout = () => { pb.authStore.clear(); navigate('/login', { replace: true }); }; const createAsset = async () => { const hasGlb = glbMode === 'file' ? !!glbFile : !!glbUrl.trim(); if (!name.trim() || !hasGlb) { alert('Please provide a name and a GLB file or URL'); return; } setLoading(true); try { const formData = new FormData(); formData.append('name', name.trim()); if (glbMode === 'file' && glbFile) { formData.append('glb_file', glbFile); } else { formData.append('glb_url', glbUrl.trim()); } if (usdzMode === 'file' && usdzFile) { formData.append('usdz_file', usdzFile); } else if (usdzMode === 'url' && usdzUrl.trim()) { formData.append('usdz_url', usdzUrl.trim()); } const record = await pb.collection('ar_assets').create(formData); const qrUrl = `${import.meta.env.VITE_FRONTEND_URL}/ar/${record.id}`; const qrImage = await QRCode.toDataURL(qrUrl, { width: 512, margin: 2, }); const qrBlob = await (await fetch(qrImage)).blob(); const qrFormData = new FormData(); qrFormData.append('qr_url', qrUrl); qrFormData.append('qr_image', new File([qrBlob], `${record.id}.png`, { type: 'image/png' })); await pb.collection('ar_assets').update(record.id, qrFormData); // Reset all fields setName(''); setGlbUrl(''); setGlbFile(null); setUsdzUrl(''); setUsdzFile(null); if (glbInputRef.current) glbInputRef.current.value = ''; if (usdzInputRef.current) usdzInputRef.current.value = ''; fetchAssets(); } catch (err: any) { alert(err?.message || 'Failed to create asset'); } finally { setLoading(false); } }; if (!authCheckComplete) { return (

Checking authorization…

); } return (
{/* Header */}
t.

AR Asset Dashboard

Manage 3D assets and generate AR QR codes

{pb.authStore.model?.email && ( {pb.authStore.model.email} )}
{/* Form Card */}

Create New Asset

{/* Asset Name */}
setName(e.target.value)} />
{/* GLB — Android / Web */} {/* USDZ — iOS */}
{/* Grid Header */}

Generated Assets

{assets.length === 0 ? (

No assets created yet. Upload a model above to get started.

) : (
{assets.map((asset) => (

{asset?.name}

{asset?.qr_image ? ( {asset?.name} ) : ( asset?.qr_file ? ( {asset?.name} ) : (
No QR Image
) )}
))}
)}
); }