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 CameraScanner from '../components/CameraScanner';
|
||||||
import GlowingCard from '../components/GlowingCard';
|
import GlowingCard from '../components/GlowingCard';
|
||||||
import CardImageDisplay from '../components/CardImageDisplay';
|
import CardImageDisplay from '../components/CardImageDisplay';
|
||||||
|
import DebugInfo from '../components/DebugInfo';
|
||||||
import { cardMatcher } from '../services/cardMatcher';
|
import { cardMatcher } from '../services/cardMatcher';
|
||||||
import { useAuth } from '../contexts/AuthContext';
|
import { useAuth } from '../contexts/AuthContext';
|
||||||
|
|
||||||
|
|
@ -275,6 +276,9 @@ const Scanner: React.FC = () => {
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Debug Information */}
|
||||||
|
<DebugInfo />
|
||||||
|
|
||||||
{/* Error Display */}
|
{/* Error Display */}
|
||||||
{error && (
|
{error && (
|
||||||
<div className="mb-6 bg-red-50 border border-red-200 rounded-lg p-4">
|
<div className="mb-6 bg-red-50 border border-red-200 rounded-lg p-4">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue