Add debug component to troubleshoot scanner issues
🔧 Debug Component: - Add DebugInfo component to Scanner page - Tests camera support and permissions - Tests API connectivity and token validation - Shows detailed error information - Helps diagnose both collection API and camera issues This will help identify: ❓ Why collections API fails in browser but works in curl ❓ Why camera UI doesn't appear after starting camera ❓ Token/authentication issues ❓ Browser permissions and support
This commit is contained in:
parent
7dc8718512
commit
331911cd2b
2 changed files with 148 additions and 0 deletions
144
src/components/DebugInfo.tsx
Normal file
144
src/components/DebugInfo.tsx
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
|
||||
const DebugInfo: React.FC = () => {
|
||||
const { user } = useAuth();
|
||||
const [debugInfo, setDebugInfo] = useState<any>(null);
|
||||
const [cameraSupported, setCameraSupported] = useState<boolean | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// Check camera support
|
||||
setCameraSupported(
|
||||
navigator.mediaDevices &&
|
||||
navigator.mediaDevices.getUserMedia &&
|
||||
typeof navigator.mediaDevices.getUserMedia === 'function'
|
||||
);
|
||||
|
||||
// Test API connectivity
|
||||
testAPIs();
|
||||
}, [user]);
|
||||
|
||||
const testAPIs = async () => {
|
||||
const token = localStorage.getItem('token');
|
||||
const results: any = {
|
||||
token: token ? `${token.substring(0, 20)}...` : 'No token',
|
||||
tokenLength: token?.length || 0,
|
||||
user: user ? {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
roles: user.roles
|
||||
} : 'Not logged in'
|
||||
};
|
||||
|
||||
try {
|
||||
// Test collections API
|
||||
const collectionsResponse = await fetch('/api/collections', {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
results.collectionsAPI = {
|
||||
status: collectionsResponse.status,
|
||||
ok: collectionsResponse.ok,
|
||||
data: collectionsResponse.ok ? await collectionsResponse.json() : await collectionsResponse.text()
|
||||
};
|
||||
} catch (error: any) {
|
||||
results.collectionsAPI = {
|
||||
error: error.message
|
||||
};
|
||||
}
|
||||
|
||||
setDebugInfo(results);
|
||||
};
|
||||
|
||||
const testCamera = async () => {
|
||||
try {
|
||||
const stream = await navigator.mediaDevices.getUserMedia({
|
||||
video: { facingMode: 'environment' }
|
||||
});
|
||||
|
||||
setDebugInfo((prev: any) => ({
|
||||
...prev,
|
||||
cameraTest: '✅ Camera access successful',
|
||||
cameraStream: {
|
||||
active: stream.active,
|
||||
tracks: stream.getVideoTracks().length
|
||||
}
|
||||
}));
|
||||
|
||||
// Stop the test stream
|
||||
stream.getTracks().forEach(track => track.stop());
|
||||
} catch (error: any) {
|
||||
setDebugInfo((prev: any) => ({
|
||||
...prev,
|
||||
cameraTest: `❌ Camera error: ${error.message}`,
|
||||
cameraError: error.name
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
if (!debugInfo) return <div>Loading debug info...</div>;
|
||||
|
||||
return (
|
||||
<div className="bg-gray-100 border border-gray-300 rounded-lg p-4 mb-6">
|
||||
<h3 className="font-bold text-gray-900 mb-3">🔧 Debug Information</h3>
|
||||
|
||||
<div className="space-y-3 text-sm">
|
||||
<div>
|
||||
<strong>Camera Support:</strong> {cameraSupported ? '✅ Supported' : '❌ Not supported'}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<strong>User:</strong> {JSON.stringify(debugInfo.user, null, 2)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<strong>Token:</strong> {debugInfo.token} (Length: {debugInfo.tokenLength})
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<strong>Collections API:</strong>
|
||||
<pre className="mt-1 bg-white p-2 rounded text-xs overflow-x-auto">
|
||||
{JSON.stringify(debugInfo.collectionsAPI, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
{debugInfo.cameraTest && (
|
||||
<div>
|
||||
<strong>Camera Test:</strong> {debugInfo.cameraTest}
|
||||
{debugInfo.cameraStream && (
|
||||
<div className="ml-4 text-xs">
|
||||
Active: {debugInfo.cameraStream.active ? 'Yes' : 'No'},
|
||||
Tracks: {debugInfo.cameraStream.tracks}
|
||||
</div>
|
||||
)}
|
||||
{debugInfo.cameraError && (
|
||||
<div className="ml-4 text-xs text-red-600">
|
||||
Error Type: {debugInfo.cameraError}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-4 space-x-2">
|
||||
<button
|
||||
onClick={testCamera}
|
||||
className="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded text-sm"
|
||||
>
|
||||
Test Camera
|
||||
</button>
|
||||
<button
|
||||
onClick={testAPIs}
|
||||
className="bg-green-600 hover:bg-green-700 text-white px-3 py-1 rounded text-sm"
|
||||
>
|
||||
Refresh API Test
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DebugInfo;
|
||||
|
|
@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
|
|||
import CameraScanner from '../components/CameraScanner';
|
||||
import GlowingCard from '../components/GlowingCard';
|
||||
import CardImageDisplay from '../components/CardImageDisplay';
|
||||
import DebugInfo from '../components/DebugInfo';
|
||||
import { cardMatcher } from '../services/cardMatcher';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
|
||||
|
|
@ -275,6 +276,9 @@ const Scanner: React.FC = () => {
|
|||
</p>
|
||||
</div>
|
||||
|
||||
{/* Debug Information */}
|
||||
<DebugInfo />
|
||||
|
||||
{/* Error Display */}
|
||||
{error && (
|
||||
<div className="mb-6 bg-red-50 border border-red-200 rounded-lg p-4">
|
||||
|
|
|
|||
Loading…
Reference in a new issue