Loto / src /components /APIOfficialDemo.tsx
Raí Santos
oi
4c1e4ec
import React, { useState } from 'react';
import { Play, CheckCircle, AlertCircle, Wifi, Database, Clock } from 'lucide-react';
import { caixaAPIOfficial } from '../utils/CaixaAPIOfficial';
export const APIOfficialDemo: React.FC = () => {
const [resultado, setResultado] = useState<any>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [status, setStatus] = useState<any>(null);
const testarAPIOficial = async () => {
setLoading(true);
setError(null);
setResultado(null);
try {
console.log('🚀 Iniciando teste da API oficial da Caixa...');
// Primeiro, verificar status
const statusAPI = await caixaAPIOfficial.verificarStatusAPI();
setStatus(statusAPI);
if (statusAPI.online) {
// Buscar dados oficiais
const dadosOficiais = await caixaAPIOfficial.fetchOfficialData();
const dadosFormatados = caixaAPIOfficial.formatarDadosOficiais(dadosOficiais);
setResultado({
raw: dadosOficiais,
formatted: dadosFormatados,
timestamp: new Date().toLocaleString('pt-BR')
});
console.log('✅ Teste concluído com sucesso!');
} else {
throw new Error('API oficial está temporariamente indisponível');
}
} catch (err) {
console.error('❌ Erro no teste:', err);
setError(err instanceof Error ? err.message : 'Erro desconhecido');
} finally {
setLoading(false);
}
};
return (
<div className="space-y-6">
{/* Header */}
<div className="bg-gradient-to-r from-green-500 to-blue-600 text-white p-6 rounded-lg">
<h2 className="text-2xl font-bold flex items-center gap-2">
<Database className="w-6 h-6" />
Teste da API Oficial da Caixa
</h2>
<p className="text-green-100 mt-2">
Demonstração de conexão REAL com a API oficial da Caixa Econômica Federal
</p>
</div>
{/* Controls */}
<div className="bg-white p-6 rounded-lg shadow-lg">
<button
onClick={testarAPIOficial}
disabled={loading}
className={`w-full flex items-center justify-center gap-2 px-6 py-3 rounded-lg font-semibold transition-all ${
loading
? 'bg-gray-400 cursor-not-allowed'
: 'bg-blue-600 hover:bg-blue-700 text-white shadow-lg hover:shadow-xl'
}`}
>
{loading ? (
<>
<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-white"></div>
Conectando à API oficial...
</>
) : (
<>
<Play className="w-5 h-5" />
Testar Conexão com API Oficial da Caixa
</>
)}
</button>
</div>
{/* Status */}
{status && (
<div className={`p-4 rounded-lg border-l-4 ${
status.online ? 'bg-green-50 border-green-500' : 'bg-red-50 border-red-500'
}`}>
<div className="flex items-center gap-2 mb-2">
{status.online ? (
<CheckCircle className="w-5 h-5 text-green-600" />
) : (
<AlertCircle className="w-5 h-5 text-red-600" />
)}
<h3 className="font-semibold">
Status da API: {status.online ? 'Online' : 'Offline'}
</h3>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 text-sm">
<div className="flex items-center gap-2">
<Wifi className="w-4 h-4" />
<span>Método: {status.metodo}</span>
</div>
<div className="flex items-center gap-2">
<Clock className="w-4 h-4" />
<span>Resposta: {status.tempoResposta}ms</span>
</div>
<div className="flex items-center gap-2">
<CheckCircle className="w-4 h-4" />
<span>Verificado: {status.ultimaVerificacao}</span>
</div>
</div>
</div>
)}
{/* Error */}
{error && (
<div className="bg-red-50 border border-red-200 rounded-lg p-4">
<div className="flex items-center gap-2 mb-2">
<AlertCircle className="w-5 h-5 text-red-600" />
<h3 className="font-semibold text-red-800">Erro na Conexão</h3>
</div>
<p className="text-red-700">{error}</p>
</div>
)}
{/* Results */}
{resultado && (
<div className="space-y-4">
{/* Dados Formatados */}
<div className="bg-white rounded-lg shadow-lg overflow-hidden">
<div className="bg-green-600 text-white p-4">
<h3 className="font-semibold flex items-center gap-2">
<CheckCircle className="w-5 h-5" />
Dados Oficiais Obtidos da Caixa
</h3>
<p className="text-green-100 text-sm mt-1">
Última atualização: {resultado.timestamp}
</p>
</div>
<div className="p-6">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div className="bg-gray-50 p-3 rounded-md">
<span className="text-sm text-gray-600">Concurso</span>
<p className="font-semibold text-lg">{resultado.formatted.concurso}</p>
</div>
<div className="bg-gray-50 p-3 rounded-md">
<span className="text-sm text-gray-600">Data do Sorteio</span>
<p className="font-semibold">{resultado.formatted.data}</p>
</div>
<div className="bg-gray-50 p-3 rounded-md">
<span className="text-sm text-gray-600">Valor Arrecadado</span>
<p className="font-semibold text-green-600">
R$ {resultado.formatted.valorArrecadado.toLocaleString('pt-BR')}
</p>
</div>
<div className="bg-gray-50 p-3 rounded-md">
<span className="text-sm text-gray-600">Acumulado</span>
<p className={`font-semibold ${resultado.formatted.acumulado ? 'text-red-600' : 'text-green-600'}`}>
{resultado.formatted.acumulado ? 'SIM' : 'NÃO'}
</p>
</div>
<div className="bg-gray-50 p-3 rounded-md">
<span className="text-sm text-gray-600">Local Sorteio</span>
<p className="font-semibold">{resultado.formatted.localSorteio}</p>
</div>
<div className="bg-gray-50 p-3 rounded-md">
<span className="text-sm text-gray-600">Próximo Concurso</span>
<p className="font-semibold">{resultado.formatted.numeroProximoConcurso}</p>
</div>
</div>
{/* Números Sorteados */}
<div className="mt-6">
<h4 className="font-semibold mb-3">Números Sorteados:</h4>
<div className="grid grid-cols-10 gap-2">
{resultado.formatted.numeros.map((numero: number, index: number) => (
<div
key={index}
className="bg-blue-600 text-white rounded-lg p-3 text-center font-bold"
>
{numero === 0 ? '00' : numero.toString().padStart(2, '0')}
</div>
))}
</div>
</div>
{/* Premiação */}
{resultado.formatted.premiacoes.length > 0 && (
<div className="mt-6">
<h4 className="font-semibold mb-3">Premiação:</h4>
<div className="overflow-x-auto">
<table className="min-w-full table-auto border-collapse border border-gray-300">
<thead>
<tr className="bg-gray-100">
<th className="border border-gray-300 px-3 py-2 text-left">Faixa</th>
<th className="border border-gray-300 px-3 py-2 text-left">Descrição</th>
<th className="border border-gray-300 px-3 py-2 text-left">Ganhadores</th>
<th className="border border-gray-300 px-3 py-2 text-left">Valor Prêmio</th>
</tr>
</thead>
<tbody>
{resultado.formatted.premiacoes.map((premio: any, index: number) => (
<tr key={index}>
<td className="border border-gray-300 px-3 py-2">{premio.faixa}</td>
<td className="border border-gray-300 px-3 py-2">{premio.descricao}</td>
<td className="border border-gray-300 px-3 py-2">{premio.ganhadores}</td>
<td className="border border-gray-300 px-3 py-2 text-green-600 font-semibold">
R$ {premio.valorPremio.toLocaleString('pt-BR')}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)}
</div>
</div>
{/* Dados Brutos da API */}
<details className="bg-gray-50 rounded-lg overflow-hidden">
<summary className="bg-gray-600 text-white p-4 cursor-pointer font-semibold">
Ver Dados Brutos da API (Para Desenvolvedores)
</summary>
<div className="p-4">
<pre className="bg-black text-green-400 p-4 rounded-md overflow-x-auto text-sm">
{JSON.stringify(resultado.raw, null, 2)}
</pre>
</div>
</details>
</div>
)}
{/* Info */}
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
<div className="flex items-center gap-2 mb-2">
<CheckCircle className="w-5 h-5 text-blue-600" />
<h3 className="font-semibold text-blue-800">Sobre este Teste</h3>
</div>
<ul className="text-blue-700 text-sm space-y-1">
<li>• Conecta DIRETAMENTE à API oficial da Caixa Econômica Federal</li>
<li>• URL: https://servicebus2.caixa.gov.br/portaldeloterias/api/lotomania/</li>
<li>• Usa múltiplas estratégias para contornar limitações de CORS</li>
<li>• Todos os dados são 100% oficiais e atualizados</li>
<li>• Sistema de fallback garante máxima disponibilidade</li>
</ul>
</div>
</div>
);
};
export default APIOfficialDemo;