Files
flyer-crawler.projectium.com/components/DatabaseControls.tsx

109 lines
4.3 KiB
TypeScript

import React, { useState, useEffect, useCallback } from 'react';
import { supabase, runDatabaseSelfTest, testStorageConnection } from '../services/supabaseClient';
import { ServerIcon } from './icons/ServerIcon';
import { LoadingSpinner } from './LoadingSpinner';
type TestStatus = 'idle' | 'testing' | 'success' | 'error';
interface DatabaseControlsProps {
onReady: () => void;
}
export const DatabaseControls: React.FC<DatabaseControlsProps> = ({ onReady }) => {
const [status, setStatus] = useState<TestStatus>('idle');
const [message, setMessage] = useState('');
const [hasRunAutoTest, setHasRunAutoTest] = useState(false);
const handleTestConnection = useCallback(async () => {
setStatus('testing');
setMessage('');
try {
// Test 1: Full Database CRUD Self-Test
const dbResult = await runDatabaseSelfTest();
if (!dbResult.success) {
setStatus('error');
setMessage(dbResult.error || 'An unknown database error occurred.');
return;
}
// Test 2: Storage Write/Delete
const storageResult = await testStorageConnection();
if (!storageResult.success) {
setStatus('error');
setMessage(storageResult.error || 'An unknown storage error occurred.');
return;
}
// All tests passed
setStatus('success');
setMessage('Connection successful! Database and Storage are working correctly.');
// Reset after a few seconds if it was a manual test
setTimeout(() => {
if (status !== 'testing') {
setStatus('idle');
setMessage('');
}
}, 8000);
} finally {
// This is the crucial step: always signal readiness after the test sequence completes.
onReady();
}
}, [status, onReady]);
// Auto-run the test once on initial connection
useEffect(() => {
if (supabase && !hasRunAutoTest) {
setHasRunAutoTest(true);
handleTestConnection();
}
}, [supabase, hasRunAutoTest, handleTestConnection]);
if (!supabase) {
return null; // Don't render anything if Supabase is not configured
}
const statusText = status === 'success' ? 'OK' : status === 'error' ? 'Error' : status === 'testing' ? 'Testing...' : 'Connected';
const statusColor = status === 'success' ? 'text-green-600 dark:text-green-400'
: status === 'error' ? 'text-red-600 dark:text-red-400'
: 'text-gray-600 dark:text-gray-400';
return (
<div className="bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 p-4">
<h3 className="text-lg font-bold text-gray-800 dark:text-white flex items-center mb-3">
<ServerIcon className="w-6 h-6 mr-2 text-brand-primary" />
Backend Status
</h3>
<p className="text-sm text-gray-600 dark:text-gray-400 mb-4">
Status: <span className={`font-semibold ${statusColor}`}>{statusText}</span>. The self-test checks all database permissions.
</p>
<button
onClick={handleTestConnection}
disabled={status === 'testing'}
className="w-full bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-wait text-gray-800 dark:text-white font-bold py-2 px-4 rounded-lg transition-colors duration-300 flex items-center justify-center"
>
{status === 'testing' ? (
<>
<div className="w-5 h-5 mr-2"><LoadingSpinner /></div>
Testing...
</>
) : (
'Re-run Connection Test'
)}
</button>
{message && (
<div className={`mt-3 text-sm p-2 rounded ${
status === 'success' ? 'bg-green-100 dark:bg-green-900/50 text-green-800 dark:text-green-300' : ''
} ${
status === 'error' ? 'bg-red-100 dark:bg-red-900/50 text-red-800 dark:text-red-300' : ''
}`}>
{message}
</div>
)}
</div>
);
};