dachbord / src /components /ConnectionTest.tsx
drmartin2050's picture
refactor: unify environment variable lookup logic
6e3f82a
Raw
History Blame Contribute Delete
28.7 kB
import React, { useState } from 'react';
import { motion } from 'motion/react';
import {
getEnvStatus,
testSupabaseConnection,
testFirebaseConnection
} from '../utils/envValidator';
import { encryptWithWebCrypto, decryptWithWebCrypto } from '../utils/encryption';
import { proxyFetch } from '../utils/apiProxy';
import {
Activity, ShieldCheck, Database, Key, CheckCircle,
XCircle, AlertTriangle, RefreshCw, Download, Play,
Lock, BrainCircuit, Terminal, Sparkles, HelpCircle
} from 'lucide-react';
interface TestResult {
name: string;
category: 'database' | 'security' | 'intelligence';
status: 'SUCCESS' | 'ERROR' | 'PENDING';
message: string;
latency?: number;
}
export default function ConnectionTest({ lang = 'ar' }: { lang?: 'ar' | 'en' }) {
const [runningAll, setRunningAll] = useState(false);
const [envStatus, setEnvStatus] = useState(() => getEnvStatus());
const [tests, setTests] = useState<Record<string, TestResult>>({
supabase: { name: 'Supabase Database', category: 'database', status: 'PENDING', message: lang === 'ar' ? 'بانتظار إجراء التحقق...' : 'Awaiting manual trigger...' },
firebase: { name: 'Firebase Firestore', category: 'database', status: 'PENDING', message: lang === 'ar' ? 'بانتظار إجراء التحقق...' : 'Awaiting manual trigger...' },
vault: { name: 'Secure Vault Encrypt', category: 'security', status: 'PENDING', message: lang === 'ar' ? 'بانتظار إجراء التحقق...' : 'Awaiting manual trigger...' },
gemini: { name: 'Google Gemini API', category: 'intelligence', status: 'PENDING', message: lang === 'ar' ? 'بانتظار إجراء التحقق...' : 'Awaiting manual trigger...' },
groq: { name: 'Groq Cloud LLM API', category: 'intelligence', status: 'PENDING', message: lang === 'ar' ? 'بانتظار إجراء التحقق...' : 'Awaiting manual trigger...' }
});
const [lastTested, setLastTested] = useState<string | null>(null);
const refreshEnvStatus = () => {
setEnvStatus(getEnvStatus());
};
const getEnvValue = (name: string): 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 runSupabaseTest = async (): Promise<TestResult> => {
setTests(prev => ({
...prev,
supabase: { ...prev.supabase, status: 'PENDING', message: lang === 'ar' ? 'جاري الاتصال والتحقق من الاستجابة...' : 'Pinging database endpoint...' }
}));
const res = await testSupabaseConnection();
const result: TestResult = {
name: 'Supabase Database',
category: 'database',
status: res.status === 'SUCCESS' ? 'SUCCESS' : 'ERROR',
message: res.message,
latency: res.latencyMs
};
setTests(prev => ({ ...prev, supabase: result }));
return result;
};
const runFirebaseTest = async (): Promise<TestResult> => {
setTests(prev => ({
...prev,
firebase: { ...prev.firebase, status: 'PENDING', message: lang === 'ar' ? 'جاري طلب استعلام خادم Firestore...' : 'Pinging Firebase endpoint...' }
}));
const res = await testFirebaseConnection();
const result: TestResult = {
name: 'Firebase Firestore',
category: 'database',
status: res.status === 'SUCCESS' ? 'SUCCESS' : 'ERROR',
message: res.message,
latency: res.latencyMs
};
setTests(prev => ({ ...prev, firebase: result }));
return result;
};
const runVaultTest = async (): Promise<TestResult> => {
setTests(prev => ({
...prev,
vault: { ...prev.vault, status: 'PENDING', message: lang === 'ar' ? 'جاري توليد مفتاح AES-GCM 256...' : 'Generating AES-GCM 256 crypt...' }
}));
const start = Date.now();
try {
const originalText = "Eissa-Master-Sentry-Verification-2026";
const dummyPass = "Eissa2026";
// 1. Test Encryption
const encrypted = await encryptWithWebCrypto(originalText, dummyPass);
if (!encrypted || !encrypted.includes(':')) {
throw new Error('فشل تشفير مفاتيح الخزنة.');
}
// 2. Test Decryption
const decrypted = await decryptWithWebCrypto(encrypted, dummyPass);
if (decrypted !== originalText) {
throw new Error('فشل فك التشفير: البيانات الناتجة مشوهة.');
}
const result: TestResult = {
name: 'Secure Vault Encrypt',
category: 'security',
status: 'SUCCESS',
message: lang === 'ar'
? 'تشفير الخزنة يعمل بشكل ممتاز مع معيار AES-GCM 256.'
: 'Vault dynamic cryptography fully operational (AES-GCM 256).',
latency: Date.now() - start
};
setTests(prev => ({ ...prev, vault: result }));
return result;
} catch (err: any) {
const result: TestResult = {
name: 'Secure Vault Encrypt',
category: 'security',
status: 'ERROR',
message: lang === 'ar'
? `فشل فحص برمجية الخزنة: ${err.message || String(err)}`
: `Vault cryptography error: ${err.message || String(err)}`,
latency: Date.now() - start
};
setTests(prev => ({ ...prev, vault: result }));
return result;
}
};
const runGeminiTest = async (): Promise<TestResult> => {
setTests(prev => ({
...prev,
gemini: { ...prev.gemini, status: 'PENDING', message: lang === 'ar' ? 'جاري فحص ترخيص محرك Gemini...' : 'Pinging Google Gemini API...' }
}));
const start = Date.now();
const token = getEnvValue('VITE_GEMINI_API_KEY');
if (!token) {
const result: TestResult = {
name: 'Google Gemini API',
category: 'intelligence',
status: 'ERROR',
message: lang === 'ar' ? 'مفتاح Gemini مفقود! يرجى إعداده كمتغير بيئي.' : 'Gemini key is missing in active workspace variables.'
};
setTests(prev => ({ ...prev, gemini: result }));
return result;
}
try {
// Small real call to gather metadata (highly safe & CORS proxy resolved)
const url = `https://generativelanguage.googleapis.com/v1beta/models?key=${token}`;
const res = await proxyFetch(url);
const latency = Date.now() - start;
if (res.status === 200) {
const result: TestResult = {
name: 'Google Gemini API',
category: 'intelligence',
status: 'SUCCESS',
message: lang === 'ar' ? 'تم مصادقة مفتاح Gemini بنجاح. القنوات ذكية ومفتوحة!' : 'Gemini validation resolved with code 200. Models online.',
latency
};
setTests(prev => ({ ...prev, gemini: result }));
return result;
} else {
const result: TestResult = {
name: 'Google Gemini API',
category: 'intelligence',
status: 'ERROR',
message: lang === 'ar' ? `رفضت Google المفتاح برمز (${res.status}).` : `Google gateway rejected token (HTTP status ${res.status}).`,
latency
};
setTests(prev => ({ ...prev, gemini: result }));
return result;
}
} catch (err: any) {
const result: TestResult = {
name: 'Google Gemini API',
category: 'intelligence',
status: 'ERROR',
message: lang === 'ar' ? `فشل الاتصال: ${err.message || 'خطأ في جدار الحماية'}` : `Fetch error: ${err.message || 'CORS or offline'}`,
latency: Date.now() - start
};
setTests(prev => ({ ...prev, gemini: result }));
return result;
}
};
const runGroqTest = async (): Promise<TestResult> => {
setTests(prev => ({
...prev,
groq: { ...prev.groq, status: 'PENDING', message: lang === 'ar' ? 'جاري فحص ترخيص خادم Groq السحابي...' : 'Pinging Groq Cloud API...' }
}));
const start = Date.now();
const token = getEnvValue('VITE_GROQ_API_KEY');
if (!token) {
const result: TestResult = {
name: 'Groq Cloud LLM API',
category: 'intelligence',
status: 'ERROR',
message: lang === 'ar' ? 'المفتاح لم يتم تعيينه. يرجى إدخال VITE_GROQ_API_KEY.' : 'Groq API Key is not set.'
};
setTests(prev => ({ ...prev, groq: result }));
return result;
}
try {
// Probe Models API (lightweight endpoint check)
const res = await proxyFetch('https://api.groq.com/openai/v1/models', {
headers: { 'Authorization': `Bearer ${token}` }
});
const latency = Date.now() - start;
if (res.status === 200) {
const result: TestResult = {
name: 'Groq Cloud LLM API',
category: 'intelligence',
status: 'SUCCESS',
message: lang === 'ar' ? 'الاتصال بـ Groq نشط ومصرح للاستدعاء بنجاح.' : 'Groq gateway authentication successful. High-speed LLM online.',
latency
};
setTests(prev => ({ ...prev, groq: result }));
return result;
} else {
const result: TestResult = {
name: 'Groq Cloud LLM API',
category: 'intelligence',
status: 'ERROR',
message: lang === 'ar' ? `مفاتيح غير مصرحة في خادم Groq (${res.status}).` : `Groq rejected the authorization (HTTP status ${res.status}).`,
latency
};
setTests(prev => ({ ...prev, groq: result }));
return result;
}
} catch (err: any) {
const result: TestResult = {
name: 'Groq Cloud LLM API',
category: 'intelligence',
status: 'ERROR',
message: lang === 'ar' ? `فشل المصافحة: CORS أو خادم غير متصل بالإنترنت.` : `Handshake exception: CORS restriction or destination model server is offline.`,
latency: Date.now() - start
};
setTests(prev => ({ ...prev, groq: result }));
return result;
}
};
const runAllDiagnostics = async () => {
setRunningAll(true);
refreshEnvStatus();
await runSupabaseTest();
await runFirebaseTest();
await runVaultTest();
await runGeminiTest();
await runGroqTest();
setLastTested(new Date().toLocaleTimeString());
setRunningAll(false);
};
const exportJSONResults = () => {
const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(
JSON.stringify({
timestamp: new Date().toISOString(),
environmentVariables: envStatus,
connectionTests: tests
}, null, 2)
);
const downloadAnchor = document.createElement('a');
downloadAnchor.setAttribute("href", dataStr);
downloadAnchor.setAttribute("download", `Sentry_Diagnostic_Report_${Date.now()}.json`);
document.body.appendChild(downloadAnchor);
downloadAnchor.click();
downloadAnchor.remove();
};
return (
<div className="w-full space-y-6" dir={lang === 'ar' ? 'rtl' : 'ltr'}>
{/* Test Controls Banner */}
<div className="relative overflow-hidden rounded-3xl bg-slate-900/60 border border-slate-800/80 p-6 backdrop-blur-xl shadow-2xl flex flex-col md:flex-row items-center justify-between gap-4">
{/* Colorful Gradient Light effect */}
<div className="absolute top-0 right-0 h-[120px] w-[200px] bg-gradient-to-tr from-cyan-400 via-indigo-600 to-purple-500 rounded-full blur-[90px] opacity-25 pointer-events-none" />
<div className="space-y-1.5 z-10 text-center md:text-right">
<h2 className="text-xl font-black bg-gradient-to-r from-red-200 via-indigo-200 to-cyan-200 bg-clip-text text-transparent flex items-center justify-center md:justify-start gap-2">
<Activity className="h-5 w-5 text-cyan-400 animate-pulse" />
<span>{lang === 'ar' ? 'لوحة الاختبارات والتشخيص الذاتي' : 'Sentry AI Active Diagnostic Console'}</span>
</h2>
<p className="text-xs text-slate-400 max-w-xl">
{lang === 'ar'
? 'قم بمراقبة وفحص اتصالات قواعد البيانات السحابية، وسلامة تراخيص ذكاء قوين الاصطناعي، ومزامنة المتغيرات البيئية من مكان واحد.'
: 'Execute end-to-end cloud database ping tests, verify cryptographic master key vaults, and inspect active Gemini and Groq API handshakes.'}
</p>
{lastTested && (
<p className="text-[10px] font-mono text-cyan-500 font-semibold uppercase">
{lang === 'ar' ? `آخر فحص نشط: ${lastTested}` : `Last telemetry probe: ${lastTested}`}
</p>
)}
</div>
<div className="flex flex-wrap gap-2.5 z-10 w-full md:w-auto justify-center">
<button
id="btn-run-all-diagnostics"
type="button"
onClick={runAllDiagnostics}
disabled={runningAll}
className="flex items-center gap-2 px-5 py-3 rounded-2xl bg-gradient-to-r from-indigo-500 via-purple-600 to-cyan-500 hover:scale-103 font-bold text-xs text-white transition shadow-lg shadow-indigo-600/20 active:scale-97 disabled:opacity-50"
>
<RefreshCw className={`h-4 w-4 ${runningAll ? 'animate-spin' : ''}`} />
<span>{runningAll ? (lang === 'ar' ? 'جاري الفحص...' : 'Probing...') : (lang === 'ar' ? 'إجراء فحص شامل للقنوات' : 'Run Full Diagnostics')}</span>
</button>
<button
id="btn-export-reports"
type="button"
onClick={exportJSONResults}
className="flex items-center gap-1.5 px-4 py-3 rounded-2xl bg-slate-800 border border-slate-700 font-bold text-xs text-slate-200 hover:bg-slate-700/80 active:scale-97 transition"
>
<Download className="h-4 w-4 text-cyan-400" />
<span>{lang === 'ar' ? 'تصدير كملف JSON' : 'Export Report'}</span>
</button>
</div>
</div>
{/* Main Grid: Variables list & Connection status */}
<div className="grid grid-cols-1 lg:grid-cols-12 gap-6">
{/* Box 1: Env vars audit (Masqued panel) */}
<div className="lg:col-span-5 bg-slate-900/40 border border-slate-800/80 rounded-3xl p-5 backdrop-blur-md space-y-4">
<div className="flex items-center justify-between border-b border-slate-800/60 pb-3">
<h3 className="text-sm font-black text-slate-200 flex items-center gap-1.5">
<Key className="h-4 w-4 text-purple-400" />
<span>{lang === 'ar' ? 'التحقق من متغيرات البيئة' : 'Active Keys & Environment Variables'}</span>
</h3>
<button
onClick={refreshEnvStatus}
className="text-xs text-indigo-400 hover:text-indigo-300 font-bold"
>
{lang === 'ar' ? 'تحديث' : 'Refresh'}
</button>
</div>
<p className="text-[11px] text-slate-400 leading-relaxed">
{lang === 'ar'
? 'تُسحب هذه المفاتيح تلقائياً ومباشرة من إعدادات Hugging Face Secrets لضمان حماية خادم العميل القصوى وعدم كشف الرموز للمتصفح.'
: 'Environment variables are loaded securely from your hosting Secrets context. Values are masked to protect authorization endpoints.'}
</p>
<div className="space-y-2.5">
{envStatus.map((env, idx) => (
<div
key={idx}
className="flex items-center justify-between p-3 rounded-xl bg-slate-950/50 border border-slate-800/50 hover:bg-slate-950/80 transition duration-200"
>
<div className="space-y-0.5">
<div className="flex items-center gap-1.5">
<span className="text-[11px] font-black font-mono text-slate-300">{env.keyName}</span>
{env.isOptional && (
<span className="text-[8px] bg-slate-800 text-slate-400 px-1 py-0.2 rounded font-mono font-bold">OPTIONAL</span>
)}
</div>
<span className="text-[10px] text-slate-500 font-mono tracking-wider">{env.maskedValue}</span>
</div>
<div className="flex items-center gap-1.5">
{env.isLoaded ? (
<span className="flex items-center gap-1 text-[10px] text-emerald-400 font-bold uppercase bg-emerald-500/5 border border-emerald-500/10 px-2 py-0.5 rounded-lg">
<CheckCircle className="h-3 w-3" />
<span>{lang === 'ar' ? 'جاهز' : 'Loaded'}</span>
</span>
) : (
<span className={`flex items-center gap-1 text-[10px] font-bold uppercase px-2 py-0.5 rounded-lg ${
env.isOptional ? 'text-yellow-400 bg-yellow-500/5 border border-yellow-500/10' : 'text-rose-400 bg-rose-500/5 border border-rose-500/10'
}`}>
<AlertTriangle className="h-3 w-3 animate-pulse" />
<span>{lang === 'ar' ? 'غير متوفر' : 'Missing'}</span>
</span>
)}
</div>
</div>
))}
</div>
</div>
{/* Box 2: Test Suites and Latency logs */}
<div className="lg:col-span-7 bg-slate-900/40 border border-slate-800/80 rounded-3xl p-5 backdrop-blur-md space-y-4">
<div className="flex items-center justify-between border-b border-slate-800/60 pb-3">
<h3 className="text-sm font-black text-slate-200 flex items-center gap-1.5">
<Terminal className="h-4 w-4 text-cyan-400" />
<span>{lang === 'ar' ? 'فحوصات الاتصال السحابية النشطة' : 'Active Connection Guard Tests'}</span>
</h3>
<span className="text-[10px] text-indigo-400 font-bold bg-indigo-500/10 border border-indigo-500/20 px-2 py-0.5 rounded-full uppercase tracking-widest font-mono">
TELEMETRY_SUITE
</span>
</div>
<div className="space-y-3.5">
{/* Supabase Box */}
<div className="p-4 rounded-2xl bg-slate-950/40 border border-slate-800/80 flex flex-col md:flex-row md:items-center justify-between gap-3 hover:border-slate-800 hover:bg-slate-950/60 transition">
<div className="flex items-start gap-3">
<div className="p-2.5 rounded-xl bg-emerald-500/10 border border-emerald-500/20 text-emerald-400">
<Database className="h-5 w-5" />
</div>
<div className="space-y-1">
<h4 className="text-xs font-black text-slate-200 flex items-center gap-2">
<span>{lang === 'ar' ? 'قاعدة بيانات Supabase الموحدة' : 'Supabase Multi-Tenant Engine'}</span>
{tests.supabase.latency !== undefined && (
<span className="text-[9px] font-mono font-black text-cyan-400 bg-cyan-950/50 px-1.5 py-0.2 rounded">
{tests.supabase.latency}ms
</span>
)}
</h4>
<p className="text-[11px] text-slate-400 leading-relaxed max-w-sm">{tests.supabase.message}</p>
</div>
</div>
<div className="flex items-center gap-2 md:justify-end">
<StatusMarker status={tests.supabase.status} lang={lang} />
<button
type="button"
onClick={runSupabaseTest}
className="p-2 rounded-xl bg-slate-800/80 border border-slate-700 hover:bg-slate-700 text-slate-200 transition"
title="Run Single Probe"
>
<Play className="h-3 w-3 text-cyan-400 fill-current" />
</button>
</div>
</div>
{/* Firebase Box */}
<div className="p-4 rounded-2xl bg-slate-950/40 border border-slate-800/80 flex flex-col md:flex-row md:items-center justify-between gap-3 hover:border-slate-800 hover:bg-slate-950/60 transition">
<div className="flex items-start gap-3">
<div className="p-2.5 rounded-xl bg-orange-500/10 border border-orange-500/20 text-orange-400">
<Database className="h-5 w-5" />
</div>
<div className="space-y-1">
<h4 className="text-xs font-black text-slate-200 flex items-center gap-2">
<span>{lang === 'ar' ? 'جسر البيانات السحابي Firebase Auth' : 'Firebase Firestore & OAuth'}</span>
{tests.firebase.latency !== undefined && (
<span className="text-[9px] font-mono font-black text-cyan-400 bg-cyan-950/50 px-1.5 py-0.2 rounded">
{tests.firebase.latency}ms
</span>
)}
</h4>
<p className="text-[11px] text-slate-400 leading-relaxed max-w-sm">{tests.firebase.message}</p>
</div>
</div>
<div className="flex items-center gap-2 md:justify-end">
<StatusMarker status={tests.firebase.status} lang={lang} />
<button
type="button"
onClick={runFirebaseTest}
className="p-2 rounded-xl bg-slate-800/80 border border-slate-700 hover:bg-slate-700 text-slate-200 transition"
title="Run Single Probe"
>
<Play className="h-3 w-3 text-cyan-400 fill-current" />
</button>
</div>
</div>
{/* Vault Box */}
<div className="p-4 rounded-2xl bg-slate-950/40 border border-slate-800/80 flex flex-col md:flex-row md:items-center justify-between gap-3 hover:border-slate-800 hover:bg-slate-950/60 transition">
<div className="flex items-start gap-3">
<div className="p-2.5 rounded-xl bg-purple-500/10 border border-purple-500/20 text-purple-400">
<Lock className="h-5 w-5" />
</div>
<div className="space-y-1">
<h4 className="text-xs font-black text-slate-200 flex items-center gap-2">
<span>{lang === 'ar' ? 'خزنة التشفير AES-GCM 256' : 'AES Cryptographic Web Crypto Vault'}</span>
{tests.vault.latency !== undefined && (
<span className="text-[9px] font-mono font-black text-cyan-400 bg-cyan-950/50 px-1.5 py-0.2 rounded">
{tests.vault.latency}ms
</span>
)}
</h4>
<p className="text-[11px] text-slate-400 leading-relaxed max-w-sm">{tests.vault.message}</p>
</div>
</div>
<div className="flex items-center gap-2 md:justify-end">
<StatusMarker status={tests.vault.status} lang={lang} />
<button
type="button"
onClick={runVaultTest}
className="p-2 rounded-xl bg-slate-800/80 border border-slate-700 hover:bg-slate-700 text-slate-200 transition"
title="Run Single Probe"
>
<Play className="h-3 w-3 text-cyan-400 fill-current" />
</button>
</div>
</div>
{/* Gemini Box */}
<div className="p-4 rounded-2xl bg-slate-950/40 border border-slate-800/80 flex flex-col md:flex-row md:items-center justify-between gap-3 hover:border-slate-800 hover:bg-slate-950/60 transition">
<div className="flex items-start gap-3">
<div className="p-2.5 rounded-xl bg-purple-500/15 border border-purple-500/25 text-purple-400">
<BrainCircuit className="h-5 w-5 animate-pulse" />
</div>
<div className="space-y-1">
<h4 className="text-xs font-black text-slate-200 flex items-center gap-2">
<span>{lang === 'ar' ? 'محرك Google Gemini وقسائم الذكاء' : 'Google Gemini AI Endpoint'}</span>
{tests.gemini.latency !== undefined && (
<span className="text-[9px] font-mono font-black text-cyan-400 bg-cyan-950/50 px-1.5 py-0.2 rounded">
{tests.gemini.latency}ms
</span>
)}
</h4>
<p className="text-[11px] text-slate-400 leading-relaxed max-w-sm">{tests.gemini.message}</p>
</div>
</div>
<div className="flex items-center gap-2 md:justify-end">
<StatusMarker status={tests.gemini.status} lang={lang} />
<button
type="button"
onClick={runGeminiTest}
className="p-2 rounded-xl bg-slate-800/80 border border-slate-700 hover:bg-slate-700 text-slate-200 transition"
title="Run Single Probe"
>
<Play className="h-3 w-3 text-cyan-400 fill-current" />
</button>
</div>
</div>
{/* Groq Box */}
<div className="p-4 rounded-2xl bg-slate-950/40 border border-slate-800/80 flex flex-col md:flex-row md:items-center justify-between gap-3 hover:border-slate-800 hover:bg-slate-950/60 transition">
<div className="flex items-start gap-3">
<div className="p-2.5 rounded-xl bg-cyan-500/10 border border-cyan-500/20 text-cyan-400">
<BrainCircuit className="h-5 w-5" />
</div>
<div className="space-y-1">
<h4 className="text-xs font-black text-slate-200 flex items-center gap-2">
<span>{lang === 'ar' ? 'بوابة Groq Cloud فائقة السرعة' : 'Groq Cloud High-Speed Gateway'}</span>
{tests.groq.latency !== undefined && (
<span className="text-[9px] font-mono font-black text-cyan-400 bg-cyan-950/50 px-1.5 py-0.2 rounded">
{tests.groq.latency}ms
</span>
)}
</h4>
<p className="text-[11px] text-slate-400 leading-relaxed max-w-sm">{tests.groq.message}</p>
</div>
</div>
<div className="flex items-center gap-2 md:justify-end">
<StatusMarker status={tests.groq.status} lang={lang} />
<button
type="button"
onClick={runGroqTest}
className="p-2 rounded-xl bg-slate-800/80 border border-slate-700 hover:bg-slate-700 text-slate-200 transition"
title="Run Single Probe"
>
<Play className="h-3 w-3 text-cyan-400 fill-current" />
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
function StatusMarker({ status, lang }: { status: 'SUCCESS' | 'ERROR' | 'PENDING', lang: 'ar' | 'en' }) {
if (status === 'SUCCESS') {
return (
<span className="flex items-center gap-1 text-[10px] font-black uppercase text-emerald-400 bg-emerald-500/10 border border-emerald-500/20 px-2.5 py-1 rounded-xl">
<CheckCircle className="h-3.5 w-3.5" />
<span>{lang === 'ar' ? 'مستقر' : 'SUCCESS'}</span>
</span>
);
}
if (status === 'ERROR') {
return (
<span className="flex items-center gap-1 text-[10px] font-black uppercase text-rose-400 bg-rose-500/10 border border-rose-500/20 px-2.5 py-1 rounded-xl">
<XCircle className="h-3.5 w-3.5 animate-pulse" />
<span>{lang === 'ar' ? 'فشل' : 'FAILED'}</span>
</span>
);
}
return (
<span className="flex items-center gap-1 text-[10px] font-black uppercase text-yellow-400 bg-yellow-500/10 border border-yellow-500/20 px-2.5 py-1 rounded-xl">
<HelpCircle className="h-3.5 w-3.5" />
<span>{lang === 'ar' ? 'بانتظار الفحص' : 'PENDING'}</span>
</span>
);
}