mais melhorias gerais
This commit is contained in:
parent
7512f42e2f
commit
7acbc48f43
@ -20,6 +20,7 @@ RUN rm -rf /usr/share/nginx/html/*
|
|||||||
# Replace default nginx.conf
|
# Replace default nginx.conf
|
||||||
COPY nginx.conf /etc/nginx/nginx.conf
|
COPY nginx.conf /etc/nginx/nginx.conf
|
||||||
# Copy our built files into nginx’s html folder
|
# Copy our built files into nginx’s html folder
|
||||||
|
COPY ./public/assets /usr/share/nginx/html
|
||||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
|
|
||||||
# (Optional) If you need any custom nginx.conf, COPY it here—
|
# (Optional) If you need any custom nginx.conf, COPY it here—
|
||||||
|
BIN
public/assets/Congresso_Nacional_hero.jpg
Normal file
BIN
public/assets/Congresso_Nacional_hero.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 352 KiB |
@ -8,6 +8,7 @@ import Footer from './components/Footer';
|
|||||||
import CandidatePage from './components/CandidatePage/CandidatePage';
|
import CandidatePage from './components/CandidatePage/CandidatePage';
|
||||||
import DataStatsPage from './components/DataStatsPage';
|
import DataStatsPage from './components/DataStatsPage';
|
||||||
import StatisticsPage from './components/StatisticsPage';
|
import StatisticsPage from './components/StatisticsPage';
|
||||||
|
import SobrePage from './components/SobrePage';
|
||||||
import NotFound from './components/NotFound';
|
import NotFound from './components/NotFound';
|
||||||
import MatrixBackground from './components/MatrixBackground';
|
import MatrixBackground from './components/MatrixBackground';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
@ -34,6 +35,7 @@ function App() {
|
|||||||
<Route path="/candidato/:id" element={<CandidatePage />} />
|
<Route path="/candidato/:id" element={<CandidatePage />} />
|
||||||
<Route path="/dados-disponiveis" element={<DataStatsPage />} />
|
<Route path="/dados-disponiveis" element={<DataStatsPage />} />
|
||||||
<Route path="/estatisticas" element={<StatisticsPage />} />
|
<Route path="/estatisticas" element={<StatisticsPage />} />
|
||||||
|
<Route path="/sobre" element={<SobrePage />} />
|
||||||
<Route path="*" element={<NotFound />} />
|
<Route path="*" element={<NotFound />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
|
@ -28,10 +28,10 @@ const DataStatsPage: React.FC = () => {
|
|||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
|
<div className="flex items-center justify-center min-h-[40vh]">
|
||||||
<div className="text-center">
|
<div className="backdrop-blur-md bg-white/90 rounded-2xl shadow-xl p-8 max-w-md w-full border border-white/30 flex flex-col items-center">
|
||||||
<div className="animate-spin rounded-full h-16 w-16 border-4 border-indigo-600 border-t-transparent mx-auto mb-4"></div>
|
<div className="animate-spin rounded-full h-10 w-10 border-4 border-indigo-600 border-t-transparent mb"></div>
|
||||||
<p className="text-lg text-gray-700">Carregando dados...</p>
|
<p className="text-base text-gray-700">Carregando dados...</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ArrowDownOnSquareStackIcon, BookOpenIcon, ChartBarIcon, DocumentTextIcon, LightBulbIcon } from '@heroicons/react/24/outline';
|
import { ArrowDownOnSquareStackIcon, BookOpenIcon, ChartBarIcon, ChartBarSquareIcon, DocumentMagnifyingGlassIcon, DocumentTextIcon, IdentificationIcon, LightBulbIcon, MagnifyingGlassIcon } from '@heroicons/react/24/outline';
|
||||||
import Card from '../shared/Card';
|
import Card from '../shared/Card';
|
||||||
|
|
||||||
const FeatureCard: React.FC<{ icon: React.ElementType, title: string, children: React.ReactNode }> = ({ icon: Icon, title, children }) => {
|
const FeatureCard: React.FC<{ icon: React.ElementType, title: string, children: React.ReactNode }> = ({ icon: Icon, title, children }) => {
|
||||||
@ -23,14 +23,17 @@ const FeaturesSection: React.FC = () => {
|
|||||||
<FeatureCard icon={DocumentTextIcon} title="Acesso Simplificado">
|
<FeatureCard icon={DocumentTextIcon} title="Acesso Simplificado">
|
||||||
Navegue facilmente por dados complexos do TSE com uma interface limpa e amigável.
|
Navegue facilmente por dados complexos do TSE com uma interface limpa e amigável.
|
||||||
</FeatureCard>
|
</FeatureCard>
|
||||||
<FeatureCard icon={ChartBarIcon} title="Visualizações Claras">
|
<FeatureCard icon={IdentificationIcon} title="Visualizações Claras">
|
||||||
Entenda as tendências e padrões com gráficos e resumos visuais dos dados eleitorais.
|
Visualização detalhada de perfis, redes sociais e histórico eleitoral.
|
||||||
</FeatureCard>
|
</FeatureCard>
|
||||||
<FeatureCard icon={LightBulbIcon} title="Insights Valiosos">
|
<FeatureCard icon={DocumentMagnifyingGlassIcon} title="Declaração de Bens">
|
||||||
Obtenha informações relevantes sobre candidatos, partidos e financiamento de campanhas.
|
Visualização acerca de bens declarados para cada candidato.
|
||||||
</FeatureCard>
|
</FeatureCard>
|
||||||
<FeatureCard icon={BookOpenIcon} title="Open Source">
|
<FeatureCard icon={MagnifyingGlassIcon} title="Informações de Campanha">
|
||||||
Contribua para um projeto aberto e transparente, ajudando a melhorar a plataforma para todos.
|
Análise de receitas e despesas de campanha quando disponível.
|
||||||
|
</FeatureCard>
|
||||||
|
<FeatureCard icon={ChartBarSquareIcon} title="Estatísticas">
|
||||||
|
Estatísticas e gráficos interativos para entender melhor o cenário eleitoral.
|
||||||
</FeatureCard>
|
</FeatureCard>
|
||||||
<FeatureCard icon={ArrowDownOnSquareStackIcon} title="Dados Abertos">
|
<FeatureCard icon={ArrowDownOnSquareStackIcon} title="Dados Abertos">
|
||||||
Os dados são acessíveis através do TSE e também disponibilizados em nosso repositório GitHub, garantindo transparência e confiabilidade.
|
Os dados são acessíveis através do TSE e também disponibilizados em nosso repositório GitHub, garantindo transparência e confiabilidade.
|
||||||
|
@ -8,7 +8,7 @@ const Footer: React.FC = () => {
|
|||||||
© {new Date().getFullYear()} OpenCand. Todos os direitos reservados.
|
© {new Date().getFullYear()} OpenCand. Todos os direitos reservados.
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm">
|
<p className="text-sm">
|
||||||
Democratizando o acesso à informação eleitoral.
|
Não nos responsabilizamos por quaisquer erros ou inconsistências nos dados apresentados, pois estes são de livre interpretação da plataforma e devem ser verificados com os dados oficiais do TSE.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
@ -6,7 +6,7 @@ const HeroSection: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
className="min-h-screen flex flex-col justify-center items-center text-white bg-cover bg-center bg-no-repeat bg-gray-900 relative"
|
className="min-h-screen flex flex-col justify-center items-center text-white bg-cover bg-center bg-no-repeat bg-gray-900 relative"
|
||||||
style={{ backgroundImage: "url('https://upload.wikimedia.org/wikipedia/commons/thumb/2/21/National_Congress_of_Brazil%2C_Brasilia.jpg/1024px-National_Congress_of_Brazil%2C_Brasilia.jpg')" }}
|
style={{ backgroundImage: "url('/assets/Congresso_Nacional_hero.jpg')" }}
|
||||||
>
|
>
|
||||||
<div className="absolute inset-0 bg-black/60"></div>
|
<div className="absolute inset-0 bg-black/60"></div>
|
||||||
<div className="relative z-10 text-center max-w-6xl">
|
<div className="relative z-10 text-center max-w-6xl">
|
||||||
@ -26,6 +26,18 @@ const HeroSection: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Image credit */}
|
||||||
|
<span className="absolute left-4 bottom-2 z-20 text-[10px] text-gray-200 bg-black/30 px-1.5 py-0.5 rounded select-none pointer-events-none opacity-55">
|
||||||
|
Edilson Rodrigues/Agência Senado. Senado Federal,
|
||||||
|
<a
|
||||||
|
href="https://creativecommons.org/licenses/by/2.0"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="ml-1 text-gray-200 hover:text-white"
|
||||||
|
>
|
||||||
|
CC BY 2.0
|
||||||
|
</a>, via Wikimedia Commons
|
||||||
|
</span>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
120
src/components/SobrePage.tsx
Normal file
120
src/components/SobrePage.tsx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { FaGithub, FaLinkedin } from 'react-icons/fa';
|
||||||
|
|
||||||
|
const SobrePage: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center min-h-[80vh] py-12 px-4">
|
||||||
|
<div
|
||||||
|
className="backdrop-blur-md bg-white/90 rounded-2xl shadow-xl p-8 max-w-3xl w-full border border-white/30"
|
||||||
|
style={{ boxShadow: '0 8px 32px 0 rgba(31, 38, 135, 0.2)' }}
|
||||||
|
>
|
||||||
|
<div className="space-y-4 text-gray-700">
|
||||||
|
<p className="text-lg leading-relaxed">
|
||||||
|
O <strong>OpenCand</strong> é uma plataforma que visa explorar de forma intuitiva os dados eleitorais brasileiros e possui
|
||||||
|
o objetivo de ser uma alternativa para o acesso às informações públicas do Tribunal Superior Eleitoral (TSE).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p className="leading-relaxed">
|
||||||
|
O projeto foi desenvolvido por <strong className="inline-flex items-center gap-1">
|
||||||
|
ivanch
|
||||||
|
<a
|
||||||
|
href="https://github.com/ivanch"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="align-middle inline-block hover:scale-110 transition-transform"
|
||||||
|
aria-label="GitHub"
|
||||||
|
>
|
||||||
|
<FaGithub className="text-gray-700 hover:text-black" size={16} />
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="https://www.linkedin.com/in/joseivanch"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="align-middle inline-block hover:scale-110 transition-transform"
|
||||||
|
aria-label="LinkedIn"
|
||||||
|
>
|
||||||
|
<FaLinkedin className="text-blue-700 hover:text-blue-900" size={16} />
|
||||||
|
</a>
|
||||||
|
</strong> como hobby, o código é semi-aberto e está disponível no <strong>GitHub</strong>.
|
||||||
|
Atualmente apenas o ETL (Extract-Transform-Load) está disponível, juntamente com o banco de dados final.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p className="leading-relaxed">
|
||||||
|
A API também pode ser utilizada para acessar os dados de forma pública, porém ainda não está documentada. A documentação da API será disponibilizada em breve.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="w-32 h-1 bg-gradient-to-r from-indigo-400 to-purple-400 mx-auto mt-6 rounded-full"></div>
|
||||||
|
|
||||||
|
<p className="leading-relaxed">
|
||||||
|
Não nos responsabilizamos por quaisquer erros ou inconsistências nos dados apresentados, pois estes são de livre interpretação da plataforma e devem ser verificados com os dados oficiais do TSE.
|
||||||
|
<br />
|
||||||
|
A plataforma é uma iniciativa independente e não possui qualquer vínculo com o TSE ou órgãos governamentais.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="w-32 h-1 bg-gradient-to-r from-indigo-400 to-purple-400 mx-auto mt-6 rounded-full"></div>
|
||||||
|
|
||||||
|
<div className="mt-6 flex flex-col items-center">
|
||||||
|
<p className="font-semibold text-gray-800 mb-2 text-center">Links úteis:</p>
|
||||||
|
<ul className="space-y-2 w-full max-w-md">
|
||||||
|
<li className="flex items-center justify-center">
|
||||||
|
<span className="w-2 h-2 bg-indigo-500 rounded-full mr-3"></span>
|
||||||
|
<a
|
||||||
|
href="https://divulgacandcontas.tse.jus.br/divulga/#/home"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-indigo-700 hover:underline hover:text-indigo-900 transition-colors text-center"
|
||||||
|
>
|
||||||
|
DivulgaCand do TSE
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center justify-center">
|
||||||
|
<span className="w-2 h-2 bg-indigo-500 rounded-full mr-3"></span>
|
||||||
|
<a
|
||||||
|
href="https://sig.tse.jus.br/ords/dwapr/r/seai/sig-eleicao/home"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-indigo-700 hover:underline hover:text-indigo-900 transition-colors text-center"
|
||||||
|
>
|
||||||
|
Estatísticas do TSE
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center justify-center">
|
||||||
|
<span className="w-2 h-2 bg-indigo-500 rounded-full mr-3"></span>
|
||||||
|
<a
|
||||||
|
href="https://dadosabertos.tse.jus.br/dataset/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-indigo-700 hover:underline hover:text-indigo-900 transition-colors text-center"
|
||||||
|
>
|
||||||
|
Dataset do TSE
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-32 h-1 bg-gradient-to-r from-indigo-400 to-purple-400 mx-auto mt-6 rounded-full"></div>
|
||||||
|
|
||||||
|
<p className="leading-relaxed">
|
||||||
|
Contato: {[
|
||||||
|
'opencand',
|
||||||
|
<span key="at" style={{ userSelect: 'text' }}>@</span>,
|
||||||
|
'ivanch',
|
||||||
|
<span key="dot" style={{ userSelect: 'text' }}>.</span>,
|
||||||
|
'me'
|
||||||
|
]}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="mt-6 pt-4 border-t border-gray-300">
|
||||||
|
<p className="text-sm text-gray-600 text-center">
|
||||||
|
Desenvolvido com .NET, PostgreSQL, React (TypeScript/Tailwind CSS) e dados abertos do TSE.<br />
|
||||||
|
<span className="text-xs">
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SobrePage;
|
@ -9,30 +9,44 @@ interface RandomCandButtonProps {
|
|||||||
hasAnimation?: boolean;
|
hasAnimation?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const RandomCandButton: React.FC<RandomCandButtonProps> = ({
|
const RandomCandButton: React.FC<RandomCandButtonProps> = ({
|
||||||
className = '',
|
className = '',
|
||||||
hasAnimation = false
|
hasAnimation = false
|
||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const [loading, setLoading] = React.useState(false);
|
||||||
|
|
||||||
const handleRandomCandidate = async () => {
|
const handleRandomCandidate = async () => {
|
||||||
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const randomCandidate = await openCandApi.getRandomCandidate();
|
const randomCandidate = await openCandApi.getRandomCandidate();
|
||||||
navigate(`/candidato/${randomCandidate.idCandidato}`);
|
navigate(`/candidato/${randomCandidate.idCandidato}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erro ao buscar candidato aleatório:', error);
|
console.error('Erro ao buscar candidato aleatório:', error);
|
||||||
// You might want to show a toast notification or error message to the user
|
// You might want to show a toast notification or error message to the user
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
onClick={handleRandomCandidate}
|
onClick={handleRandomCandidate}
|
||||||
className={`flex items-center ${className}`}
|
className={`flex items-center relative overflow-hidden ${className}`}
|
||||||
hasAnimation={hasAnimation}
|
hasAnimation={hasAnimation}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
<ArrowPathIcon
|
||||||
|
className={`h-4 w-4 transition-transform duration-500 ${loading ? 'animate-spin' : 'mr-2'}`}
|
||||||
|
style={{ zIndex: 2 }}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className={`inline-block transition-all duration-300 origin-left whitespace-nowrap ${loading ? 'scale-x-0 max-w-0' : 'scale-x-100 max-w-xs'}`}
|
||||||
|
style={{ zIndex: 1, transitionProperty: 'transform, max-width' }}
|
||||||
>
|
>
|
||||||
<ArrowPathIcon className="h-4 w-4 mr-2" />
|
|
||||||
Candidato aleatório
|
Candidato aleatório
|
||||||
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user