design improvements
All checks were successful
Frontend Build and Deploy / build (push) Successful in 20s
All checks were successful
Frontend Build and Deploy / build (push) Successful in 20s
This commit is contained in:
parent
8d49466f5d
commit
d7a6a5ea29
29
src/App.css
29
src/App.css
@ -14,4 +14,33 @@ body, html {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-x: hidden;
|
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;
|
||||||
}
|
}
|
14
src/App.tsx
14
src/App.tsx
@ -22,12 +22,14 @@ function App() {
|
|||||||
return (
|
return (
|
||||||
<div className="min-h-screen w-full flex flex-col relative" style={{ backgroundColor: 'transparent' }}>
|
<div className="min-h-screen w-full flex flex-col relative" style={{ backgroundColor: 'transparent' }}>
|
||||||
<MatrixBackground />
|
<MatrixBackground />
|
||||||
<div className="relative z-10">
|
<Navbar />
|
||||||
<Navbar />
|
<div className="relative z-10 flex-1 flex flex-col pt-17">
|
||||||
<Routes>
|
<div className="flex-1">
|
||||||
<Route path="/" element={<HomePage />} />
|
<Routes>
|
||||||
<Route path="/candidato/:id" element={<CandidatePage />} />
|
<Route path="/" element={<HomePage />} />
|
||||||
</Routes>
|
<Route path="/candidato/:id" element={<CandidatePage />} />
|
||||||
|
</Routes>
|
||||||
|
</div>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -12,6 +12,7 @@ export interface Candidate {
|
|||||||
estadoCivil: string;
|
estadoCivil: string;
|
||||||
sexo: string;
|
sexo: string;
|
||||||
ocupacao: string;
|
ocupacao: string;
|
||||||
|
apelido: string;
|
||||||
fotoUrl: string;
|
fotoUrl: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,11 +4,11 @@ import SearchBar from './SearchBar';
|
|||||||
const HeroSection: React.FC = () => {
|
const HeroSection: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<section
|
<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')" }}
|
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="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">
|
<h1 className="text-5xl md:text-7xl font-bold mb-6">
|
||||||
Explore Dados Eleitorais
|
Explore Dados Eleitorais
|
||||||
</h1>
|
</h1>
|
||||||
|
@ -15,10 +15,8 @@ const NavButton: React.FC<NavButtonProps> = ({ href, children, className = '' })
|
|||||||
rounded-full
|
rounded-full
|
||||||
backdrop-blur-sm
|
backdrop-blur-sm
|
||||||
bg-gray-800/30
|
bg-gray-800/30
|
||||||
border border-gray-600/50
|
|
||||||
text-gray-100
|
text-gray-100
|
||||||
hover:bg-gray-700/40
|
hover:bg-gray-700/40
|
||||||
hover:border-gray-500/60
|
|
||||||
hover:text-white
|
hover:text-white
|
||||||
transition-all duration-300 ease-in-out
|
transition-all duration-300 ease-in-out
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
|
@ -14,6 +14,7 @@ const SearchBar: React.FC<SearchBarProps> = ({ className = '' }) => {
|
|||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [showResults, setShowResults] = useState(false);
|
const [showResults, setShowResults] = useState(false);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [isFocused, setIsFocused] = useState(false);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const searchTimeoutRef = useRef<number | null>(null);
|
const searchTimeoutRef = useRef<number | null>(null);
|
||||||
const resultsRef = useRef<HTMLDivElement>(null);
|
const resultsRef = useRef<HTMLDivElement>(null);
|
||||||
@ -96,6 +97,7 @@ const SearchBar: React.FC<SearchBarProps> = ({ className = '' }) => {
|
|||||||
const desc = [''];
|
const desc = [''];
|
||||||
|
|
||||||
if (candidate.cpf) desc.push(`CPF: ${maskCpf(candidate.cpf)}`);
|
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 (candidate.ocupacao && candidate.ocupacao != 'OUTROS') desc.push(`${candidate.ocupacao}`);
|
||||||
if (desc.length == 0)
|
if (desc.length == 0)
|
||||||
if (candidate.dataNascimento) desc.push(`${formatDateToDDMMYYYY(candidate.dataNascimento)}`);
|
if (candidate.dataNascimento) desc.push(`${formatDateToDDMMYYYY(candidate.dataNascimento)}`);
|
||||||
@ -113,13 +115,18 @@ const SearchBar: React.FC<SearchBarProps> = ({ className = '' }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
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}>
|
<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">
|
<div className={`flex items-center bg-white/10 backdrop-blur-sm rounded-full shadow-xl p-2
|
||||||
<MagnifyingGlassIcon className="h-6 w-6 text-gray-400 ml-3" />
|
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
|
<input
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
|
onFocus={() => setIsFocused(true)}
|
||||||
|
onBlur={() => setIsFocused(false)}
|
||||||
placeholder="Pesquisar candidatos..."
|
placeholder="Pesquisar candidatos..."
|
||||||
className="flex-grow bg-transparent text-white placeholder-gray-400 p-3 focus:outline-none"
|
className="flex-grow bg-transparent text-white placeholder-gray-400 p-3 focus:outline-none"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
@ -148,7 +155,7 @@ const SearchBar: React.FC<SearchBarProps> = ({ className = '' }) => {
|
|||||||
|
|
||||||
{/* Search Results Dropdown */}
|
{/* Search Results Dropdown */}
|
||||||
{showResults && (searchResults.length > 0 || error) && (
|
{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 ? (
|
{error ? (
|
||||||
<div className="p-4 text-red-600 text-center bg-white">
|
<div className="p-4 text-red-600 text-center bg-white">
|
||||||
{error}
|
{error}
|
||||||
@ -173,7 +180,7 @@ const SearchBar: React.FC<SearchBarProps> = ({ className = '' }) => {
|
|||||||
|
|
||||||
{searchResults.length === 10 && (
|
{searchResults.length === 10 && (
|
||||||
<div className="p-3 text-center text-gray-500 text-sm bg-gray-50">
|
<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>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -183,7 +190,7 @@ const SearchBar: React.FC<SearchBarProps> = ({ className = '' }) => {
|
|||||||
|
|
||||||
{/* No results message */}
|
{/* No results message */}
|
||||||
{showResults && searchResults.length === 0 && !error && !isLoading && searchQuery.length >= 2 && (
|
{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">
|
<div className="p-4 text-gray-600 text-center">
|
||||||
Nenhum candidato encontrado para "{searchQuery}"
|
Nenhum candidato encontrado para "{searchQuery}"
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user