Spaces:
Sleeping
Sleeping
File size: 9,345 Bytes
18657fc c83167e 6e3f82a c83167e 18657fc c83167e 18657fc c83167e 6e3f82a c83167e 18657fc | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | import React, { useState, useEffect } from 'react';
import { motion } from 'motion/react';
import { Terminal, ShieldAlert, Key, Database, RefreshCw, CheckCircle2, XCircle } from 'lucide-react';
interface LogEntry {
id: string;
timestamp: string;
type: 'info' | 'error' | 'success' | 'warning';
message: string;
data?: any;
}
export const DiagnosticsDebugView: React.FC<{ lang: 'en' | 'ar' }> = ({ lang }) => {
const [logs, setLogs] = useState<LogEntry[]>([]);
const [isRunning, setIsRunning] = useState(false);
const addLog = (type: LogEntry['type'], message: string, data?: any) => {
setLogs(prev => [
{
id: Math.random().toString(36).substring(7),
timestamp: new Date().toISOString(),
type,
message,
data
},
...prev
]);
};
const runDiagnostics = async () => {
setIsRunning(true);
setLogs([]);
addLog('info', lang === 'ar' ? 'بدء التشخيص التحليلي...' : 'Starting diagnostics...');
// 1. Check API Keys in LocalStorage
try {
addLog('info', lang === 'ar' ? 'جاري فحص المفاتيح المخزنة...' : 'Checking locally stored API keys...');
const hfToken = localStorage.getItem('hf_projects_token');
const ghToken = localStorage.getItem('github_projects_token');
const keys = {
HUGGING_FACE_TOKEN: hfToken ? `${hfToken}` : 'NOT_FOUND',
GITHUB_TOKEN: ghToken ? `${ghToken}` : 'NOT_FOUND',
};
addLog(
hfToken || ghToken ? 'success' : 'warning',
lang === 'ar' ? 'نتائج فحص المفاتيح المحلية' : 'Local Keys Scan Results',
keys
);
const getEnvVar = (name: string) => {
const altName = name.replace('VITE_', '');
return (window as any).__ENV?.[name] || (window as any).__ENV?.[altName] || (window as any).env?.[name] || (window as any).env?.[altName] || (import.meta as any).env?.[name] || (import.meta as any).env?.[altName];
};
// Check environment variables if possible
const envKeys = {
VITE_SUPABASE_URL: getEnvVar('VITE_SUPABASE_URL') ? getEnvVar('VITE_SUPABASE_URL') : 'NOT_FOUND',
VITE_SUPABASE_ANON_KEY: getEnvVar('VITE_SUPABASE_ANON_KEY') ? 'PRESENT (HIDDEN FOR SECURITY)' : 'NOT_FOUND',
};
addLog('info', lang === 'ar' ? 'بيانات بيئة التشغيل' : 'Environment Variables Config', envKeys);
} catch (e: any) {
addLog('error', 'Error reading keys', e.message);
}
// 2. Mock Supabase Handshake Test
try {
addLog('info', lang === 'ar' ? 'بدء فحص اتصال قاعدة بيانات Supabase...' : 'Initiating Supabase connection handshake...');
const getEnvVar = (name: string) => {
const altName = name.replace('VITE_', '');
return (window as any).__ENV?.[name] || (window as any).__ENV?.[altName] || (window as any).env?.[name] || (window as any).env?.[altName] || (import.meta as any).env?.[name] || (import.meta as any).env?.[altName];
};
const supabaseUrl = getEnvVar('VITE_SUPABASE_URL');
const supabaseKey = getEnvVar('VITE_SUPABASE_ANON_KEY');
if (!supabaseUrl || !supabaseKey) {
addLog('error', lang === 'ar' ? 'متغيرات بيئة Supabase مفقودة' : 'Supabase environment variables missing. Handshake aborted.');
} else {
addLog('info', `Pinging Supabase URL: ${supabaseUrl}/rest/v1/`);
// We will just do a fetch to the REST endpoint root or a public table if necessary, but a mock delay provides the visual of handshake.
await new Promise(resolve => setTimeout(resolve, 1500));
try {
const res = await fetch(`${supabaseUrl}/rest/v1/`, {
headers: {
'apikey': supabaseKey,
'Authorization': `Bearer ${supabaseKey}`
}
});
if (res.ok || res.status === 404) { // 404 on root is fine, means server is reachable
addLog('success', lang === 'ar' ? 'تم الاتصال بـ Supabase بنجاح' : 'Supabase handshake successful. Server is reachable and key is valid.');
} else {
addLog('error', lang === 'ar' ? `فشل الاتصال: ${res.statusText}` : `Handshake failed: ${res.status} ${res.statusText}`);
}
} catch (netErr: any) {
addLog('error', lang === 'ar' ? 'تعطل الاتصال بالشبكة (CORS/DNS)' : 'Network handshake failed (CORS/DNS Error)', netErr.message);
}
}
} catch (e: any) {
addLog('error', 'Supabase diagnostic error', e.message);
}
addLog('info', lang === 'ar' ? 'اكتمل التشخيص.' : 'Diagnostics completed.');
setIsRunning(false);
};
return (
<div className="space-y-6 animate-fadeIn p-6">
<div className="flex items-center gap-3 mb-6">
<div className="p-3 bg-fuchsia-500/10 rounded-xl">
<Terminal className="h-6 w-6 text-fuchsia-400" />
</div>
<div>
<h2 className="text-xl font-black text-white">
{lang === 'ar' ? 'شاشة التشخيص وإصلاح الأخطاء' : 'Diagnostics & Debugging Console'}
</h2>
<p className="text-sm text-slate-400 font-medium">
{lang === 'ar' ? 'عرض فوري للمفاتيح الخام وحالة الاتصال بقواعد البيانات' : 'Raw API keys inspector and database handshake status for troubleshooting.'}
</p>
</div>
</div>
<div className="bg-slate-900 border border-slate-800 rounded-3xl overflow-hidden flex flex-col shadow-2xl h-[600px]">
{/* Console Header */}
<div className="bg-slate-950 px-5 py-3 border-b border-slate-800 flex items-center justify-between">
<div className="flex items-center gap-2">
<div className="flex gap-1.5">
<div className="w-3 h-3 rounded-full bg-rose-500/80"></div>
<div className="w-3 h-3 rounded-full bg-amber-500/80"></div>
<div className="w-3 h-3 rounded-full bg-emerald-500/80"></div>
</div>
<span className="ml-3 text-xs font-mono font-bold text-slate-500 tracking-wider">
sys_debug_output.log
</span>
</div>
<button
onClick={runDiagnostics}
disabled={isRunning}
className="px-4 py-1.5 bg-fuchsia-600 hover:bg-fuchsia-500 disabled:opacity-50 text-white text-xs font-black rounded-lg transition flex items-center gap-2"
>
<RefreshCw className={`h-3 w-3 ${isRunning ? 'animate-spin' : ''}`} />
{isRunning
? (lang === 'ar' ? 'جاري الفحص...' : 'Running...')
: (lang === 'ar' ? 'بدء الفحص' : 'Run Diagnostics')
}
</button>
</div>
{/* Console Output */}
<div className="flex-1 p-5 overflow-y-auto font-mono text-xs space-y-3" dir="ltr">
{logs.length === 0 ? (
<div className="h-full flex flex-col items-center justify-center text-slate-600 space-y-3">
<Terminal className="h-10 w-10 opacity-20" />
<p>{lang === 'ar' ? 'انقر على "بدء الفحص" لتوليد السجلات.' : 'Click "Run Diagnostics" to generate logs.'}</p>
</div>
) : (
logs.map(log => (
<motion.div
initial={{ opacity: 0, x: -10 }}
animate={{ opacity: 1, x: 0 }}
key={log.id}
className="space-y-1.5 border-b border-slate-800/50 pb-3 mb-3 last:border-0 last:pb-0 last:mb-0"
>
<div className="flex items-start gap-2">
<span className="text-slate-500 shrink-0 select-none">
[{new Date(log.timestamp).toLocaleTimeString()}]
</span>
{log.type === 'error' && <XCircle className="h-4 w-4 text-rose-500 shrink-0 mt-0.5" />}
{log.type === 'success' && <CheckCircle2 className="h-4 w-4 text-emerald-500 shrink-0 mt-0.5" />}
{log.type === 'info' && <span className="text-sky-400 font-bold shrink-0 mt-0.5">➔</span>}
{log.type === 'warning' && <ShieldAlert className="h-4 w-4 text-amber-500 shrink-0 mt-0.5" />}
<div className="flex-1 space-y-1 overflow-hidden">
<span className={`font-semibold ${
log.type === 'error' ? 'text-rose-400' :
log.type === 'success' ? 'text-emerald-400' :
log.type === 'warning' ? 'text-amber-400' :
'text-slate-300'
}`}>
{log.message}
</span>
{log.data && (
<pre className="mt-2 p-3 bg-slate-950 rounded-xl overflow-x-auto text-[11px] text-indigo-200 border border-slate-800/60 leading-relaxed shadow-inner">
{JSON.stringify(log.data, null, 2)}
</pre>
)}
</div>
</div>
</motion.div>
))
)}
</div>
</div>
</div>
);
}
|