ar-test/app/qr-ar/ar-viewer.tsx
2026-02-11 12:35:23 +05:30

134 lines
4.0 KiB
TypeScript

'use client';
import { useEffect, useRef, useState } from 'react';
import { useParams } from 'react-router';
import { supabase } from '~/lib/supabase';
// --- A-FRAME/AR.JS CUSTOM ELEMENTS TYPING FIX ---
declare module 'react' {
namespace JSX {
interface IntrinsicElements {
'a-scene': any;
'a-assets': any;
'a-asset-item': any;
'a-marker': any;
'a-entity': any;
'a-text': any;
'model-viewer': React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
> & {
src?: string;
'ios-src'?: string;
ar?: boolean;
'ar-modes'?: string;
'ar-scale'?: string;
'ar-placement'?: string;
'camera-controls'?: boolean;
'touch-action'?: string;
alt?: string;
'shadow-intensity'?: string | number;
'shadow-softness'?: string | number;
exposure?: string | number;
'interaction-prompt'?: string;
'min-camera-orbit'?: string;
'max-camera-orbit'?: string;
'camera-orbit'?: string;
'field-of-view'?: string;
scale?: string;
'auto-rotate'?: boolean;
'rotation-per-second'?: string;
onLoad?: (e: any) => void;
'onAr-status'?: (e: any) => void;
'onModel-visibility'?: (e: any) => void;
'onCamera-change'?: (e: any) => void;
};
}
}
}
export default function ARViewer() {
const { id } = useParams();
const modelViewerRef = useRef<any>(null);
const [asset, setAsset] = useState<any>(null);
const [scriptLoaded, setScriptLoaded] = useState(false);
useEffect(() => {
if (!id) return;
const loadAsset = async () => {
const { data, error } = await supabase
.from('ar_assets')
.select('*')
.eq('id', id)
.single();
console.log('Supabase response:', { data, error });
if (!error && data) {
setAsset(data);
}
};
loadAsset();
}, [id]);
useEffect(() => {
if (document.getElementById('model-viewer-script')) {
setScriptLoaded(true);
return;
}
const script = document.createElement('script');
script.id = 'model-viewer-script';
script.type = 'module';
script.src =
'https://ajax.googleapis.com/ajax/libs/model-viewer/3.4.0/model-viewer.min.js';
script.onload = () => {
console.log('model-viewer loaded');
setScriptLoaded(true);
};
document.head.appendChild(script);
}, []);
if (!scriptLoaded) {
return (
<pre style={{ padding: 20 }}>
Loading AR Viewer
{'\n\n'}
asset: {JSON.stringify(asset, null, 2)}
{'\n'}
scriptLoaded: {String(scriptLoaded)}
{'\n'}
id: {String(id)}
</pre>
);
}
return (
<model-viewer
ref={modelViewerRef}
src={asset?.glb_url}
ios-src={asset?.usdz_url}
ar
ar-modes='webxr scene-viewer quick-look'
camera-controls
auto-rotate
style={{ width: '100vw', height: '80vh' }}
onError={(e) => {
console.error('Model viewer error:', e);
console.error('Failed to load:', asset?.glb_url);
}}
onLoad={() => console.log('Model loaded successfully')}
/>
// <div className='bg-white text-2xl text-red-400'>
// Id : {asset?.id}
// AR Viewer for asset: {asset?.name}
// glb URL: {asset?.glb_url}
// usdz URL: {asset?.usdz_url}
// </div>
);
}