|
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...'); |
|
|
|
|
|
const statusAPI = await caixaAPIOfficial.verificarStatusAPI(); |
|
setStatus(statusAPI); |
|
|
|
if (statusAPI.online) { |
|
|
|
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 && ( |
|
<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 && ( |
|
<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> |
|
)} |
|
|
|
{} |
|
{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> |
|
)} |
|
|
|
{} |
|
<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; |
|
|