design improvements
All checks were successful
Frontend Build and Deploy / build (push) Successful in 20s

This commit is contained in:
José Henrique 2025-06-03 17:51:17 -03:00
parent 8d49466f5d
commit d7a6a5ea29
6 changed files with 53 additions and 16 deletions

View File

@ -15,3 +15,32 @@ body, html {
height: 100%;
overflow-x: hidden;
}
/* Custom animations */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
.animate-fadeIn {
animation: fadeIn 0.3s ease-in-out forwards;
}
/* Custom scrollbar for search results */
.custom-scrollbar::-webkit-scrollbar {
width: 6px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 10px;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: #888;
border-radius: 10px;
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
background: #555;
}

View File

@ -22,12 +22,14 @@ function App() {
return (
<div className="min-h-screen w-full flex flex-col relative" style={{ backgroundColor: 'transparent' }}>
<MatrixBackground />
<div className="relative z-10">
<Navbar />
<div className="relative z-10 flex-1 flex flex-col pt-17">
<div className="flex-1">
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/candidato/:id" element={<CandidatePage />} />
</Routes>
</div>
<Footer />
</div>
</div>

View File

@ -12,6 +12,7 @@ export interface Candidate {
estadoCivil: string;
sexo: string;
ocupacao: string;
apelido: string;
fotoUrl: string;
}

View File

@ -4,11 +4,11 @@ import SearchBar from './SearchBar';
const HeroSection: React.FC = () => {
return (
<section
className="min-h-screen flex flex-col justify-center items-center text-white p-4 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')" }}
>
<div className="absolute inset-0 bg-black/60"></div>
<div className="relative z-10 text-center max-w-3xl">
<div className="relative z-10 text-center max-w-6xl">
<h1 className="text-5xl md:text-7xl font-bold mb-6">
Explore Dados Eleitorais
</h1>

View File

@ -15,10 +15,8 @@ const NavButton: React.FC<NavButtonProps> = ({ href, children, className = '' })
rounded-full
backdrop-blur-sm
bg-gray-800/30
border border-gray-600/50
text-gray-100
hover:bg-gray-700/40
hover:border-gray-500/60
hover:text-white
transition-all duration-300 ease-in-out
cursor-pointer

View File

@ -14,6 +14,7 @@ const SearchBar: React.FC<SearchBarProps> = ({ className = '' }) => {
const [isLoading, setIsLoading] = useState(false);
const [showResults, setShowResults] = useState(false);
const [error, setError] = useState<string | null>(null);
const [isFocused, setIsFocused] = useState(false);
const navigate = useNavigate();
const searchTimeoutRef = useRef<number | null>(null);
const resultsRef = useRef<HTMLDivElement>(null);
@ -96,6 +97,7 @@ const SearchBar: React.FC<SearchBarProps> = ({ className = '' }) => {
const desc = [''];
if (candidate.cpf) desc.push(`CPF: ${maskCpf(candidate.cpf)}`);
if (candidate.apelido) desc.push(`"${candidate.apelido}"`);
if (candidate.ocupacao && candidate.ocupacao != 'OUTROS') desc.push(`${candidate.ocupacao}`);
if (desc.length == 0)
if (candidate.dataNascimento) desc.push(`${formatDateToDDMMYYYY(candidate.dataNascimento)}`);
@ -113,13 +115,18 @@ const SearchBar: React.FC<SearchBarProps> = ({ className = '' }) => {
}, []);
return (
<div className={`w-full max-w-xl mx-auto relative ${className}`} ref={resultsRef}>
<div className={`w-full max-w-2xl mx-auto relative ${className}`} ref={resultsRef}>
<form onSubmit={handleSubmit}>
<div className="flex items-center bg-white/10 backdrop-blur-sm rounded-full shadow-xl p-2 transition-all duration-200 hover:bg-white/15">
<MagnifyingGlassIcon className="h-6 w-6 text-gray-400 ml-3" />
<div className={`flex items-center bg-white/10 backdrop-blur-sm rounded-full shadow-xl p-2
transition-all duration-300 ease-in-out
${isFocused ? 'bg-white/20 scale-[1.01] shadow-2xl ring-2 ring-white/20' : 'hover:bg-white/15 hover:scale-[1.01]'}
`}>
<MagnifyingGlassIcon className={`h-6 w-6 transition-all duration-300 ${isFocused ? 'text-white' : 'text-gray-400'} ml-3`} />
<input
value={searchQuery}
onChange={handleInputChange}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
placeholder="Pesquisar candidatos..."
className="flex-grow bg-transparent text-white placeholder-gray-400 p-3 focus:outline-none"
autoComplete="off"
@ -148,7 +155,7 @@ const SearchBar: React.FC<SearchBarProps> = ({ className = '' }) => {
{/* Search Results Dropdown */}
{showResults && (searchResults.length > 0 || error) && (
<div className="absolute top-full left-0 right-0 mt-2 bg-white rounded-xl shadow-2xl border border-gray-200 overflow-hidden z-50">
<div className="absolute top-full left-0 right-0 mt-2 bg-white rounded-xl shadow-2xl border border-gray-200 overflow-hidden z-50 animate-fadeIn">
{error ? (
<div className="p-4 text-red-600 text-center bg-white">
{error}
@ -173,7 +180,7 @@ const SearchBar: React.FC<SearchBarProps> = ({ className = '' }) => {
{searchResults.length === 10 && (
<div className="p-3 text-center text-gray-500 text-sm bg-gray-50">
Mostrando os primeiros 10 resultados
Mostrando apenas os primeiros <strong>10 resultados</strong>
</div>
)}
</div>
@ -183,7 +190,7 @@ const SearchBar: React.FC<SearchBarProps> = ({ className = '' }) => {
{/* No results message */}
{showResults && searchResults.length === 0 && !error && !isLoading && searchQuery.length >= 2 && (
<div className="absolute top-full left-0 right-0 mt-2 bg-white rounded-xl shadow-2xl border border-gray-200 overflow-hidden z-50">
<div className="absolute top-full left-0 right-0 mt-2 bg-white rounded-xl shadow-2xl border border-gray-200 overflow-hidden z-50 animate-fadeIn">
<div className="p-4 text-gray-600 text-center">
Nenhum candidato encontrado para "{searchQuery}"
</div>