att layout
This commit is contained in:
parent
6a9bbd84cd
commit
d916bee429
23 changed files with 717 additions and 298 deletions
201
frontend/RESPONSIVENESS_AND_I18N_IMPROVEMENTS.md
Normal file
201
frontend/RESPONSIVENESS_AND_I18N_IMPROVEMENTS.md
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
# Melhorias de Responsividade e Internacionalização
|
||||
|
||||
## ✅ Concluído
|
||||
|
||||
### 1. Sistema de Idiomas
|
||||
- ✅ Sistema de i18n já implementado com 3 idiomas (pt-BR, en, es)
|
||||
- ✅ LanguageSwitcher component criado e funcional
|
||||
- ✅ Traduções adicionadas para navegação mobile:
|
||||
- `nav.language`: "Idioma" / "Language" / "Idioma"
|
||||
- `nav.registerUser`: "Cadastrar Usuário" / "Register User" / "Registrar Usuario"
|
||||
- `nav.registerCompany`: "Cadastrar Empresa" / "Register Company" / "Registrar Empresa"
|
||||
|
||||
### 2. Navbar Responsivo
|
||||
- ✅ Menu mobile já implementado com Sheet component
|
||||
- ✅ LanguageSwitcher adicionado no desktop
|
||||
- ⚠️ **PENDENTE**: Adicionar LanguageSwitcher no menu mobile
|
||||
|
||||
## 📋 Próximos Passos
|
||||
|
||||
### 1. Completar Traduções nos Arquivos de Idioma
|
||||
|
||||
#### en.json (Inglês)
|
||||
Adicionar na seção "nav" (linha 18-24):
|
||||
```json
|
||||
"nav": {
|
||||
"jobs": "Jobs",
|
||||
"about": "About",
|
||||
"contact": "Contact",
|
||||
"login": "Login",
|
||||
"register": "Register",
|
||||
"language": "Language",
|
||||
"registerUser": "Register User",
|
||||
"registerCompany": "Register Company"
|
||||
},
|
||||
```
|
||||
|
||||
#### es.json (Espanhol)
|
||||
Adicionar na seção "nav":
|
||||
```json
|
||||
"nav": {
|
||||
"jobs": "Empleos",
|
||||
"about": "Acerca de",
|
||||
"contact": "Contacto",
|
||||
"login": "Iniciar sesión",
|
||||
"register": "Registrarse",
|
||||
"language": "Idioma",
|
||||
"registerUser": "Registrar Usuario",
|
||||
"registerCompany": "Registrar Empresa"
|
||||
},
|
||||
```
|
||||
|
||||
### 2. Atualizar Navbar para Mobile
|
||||
|
||||
Arquivo: `e:\gohorse\gohorsejobs\frontend\src\components\navbar.tsx`
|
||||
|
||||
Adicionar após a linha 110 (dentro do SheetContent):
|
||||
```tsx
|
||||
{/* Language Switcher in Mobile */}
|
||||
<div className="flex items-center justify-between px-2 py-2 bg-muted rounded-lg">
|
||||
<span className="text-sm font-medium">{t('nav.language')}</span>
|
||||
<LanguageSwitcher />
|
||||
</div>
|
||||
```
|
||||
|
||||
E atualizar os links de registro no mobile (linhas 139-144):
|
||||
```tsx
|
||||
<Link href="/register/user" onClick={() => setIsOpen(false)}>
|
||||
<Button variant="outline" className="w-full justify-start gap-2">
|
||||
<UserPlus className="w-4 h-4" />
|
||||
{t('nav.registerUser')}
|
||||
</Button>
|
||||
</Link>
|
||||
<Link href="/register" onClick={() => setIsOpen(false)}>
|
||||
<Button className="w-full justify-start gap-2">
|
||||
<Building2 className="w-4 h-4" />
|
||||
{t('nav.registerCompany')}
|
||||
</Button>
|
||||
</Link>
|
||||
```
|
||||
|
||||
### 3. Verificar Responsividade em Todas as Páginas
|
||||
|
||||
Testar as seguintes páginas em diferentes tamanhos de tela:
|
||||
- ✅ `/` - Home
|
||||
- ✅ `/jobs` - Lista de vagas
|
||||
- ✅ `/blog` - Blog
|
||||
- ✅ `/companies` - Empresas
|
||||
- ⚠️ `/jobs/[id]` - Detalhes da vaga
|
||||
- ⚠️ `/jobs/[id]/apply` - Formulário de candidatura
|
||||
- ⚠️ `/blog/[slug]` - Artigo do blog
|
||||
- ⚠️ `/register/user` - Cadastro de usuário
|
||||
- ⚠️ `/register` - Cadastro de empresa
|
||||
- ⚠️ `/publicar-vaga` - Publicar vaga
|
||||
- ⚠️ `/dashboard/*` - Todas as páginas do dashboard
|
||||
|
||||
### 4. Melhorias de Responsividade Específicas
|
||||
|
||||
#### Breakpoints Padrão do Tailwind:
|
||||
- `sm`: 640px
|
||||
- `md`: 768px
|
||||
- `lg`: 1024px
|
||||
- `xl`: 1280px
|
||||
- `2xl`: 1536px
|
||||
|
||||
#### Checklist de Responsividade:
|
||||
- [ ] Textos legíveis em mobile (min 14px)
|
||||
- [ ] Botões com tamanho adequado para toque (min 44x44px)
|
||||
- [ ] Espaçamento adequado entre elementos
|
||||
- [ ] Imagens responsivas com `object-fit`
|
||||
- [ ] Tabelas com scroll horizontal em mobile
|
||||
- [ ] Formulários com campos empilhados em mobile
|
||||
- [ ] Navegação mobile funcional
|
||||
- [ ] Modais e dialogs responsivos
|
||||
|
||||
## 🎨 Padrões de Responsividade
|
||||
|
||||
### Containers
|
||||
```tsx
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
```
|
||||
|
||||
### Grid Responsivo
|
||||
```tsx
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
```
|
||||
|
||||
### Texto Responsivo
|
||||
```tsx
|
||||
<h1 className="text-2xl md:text-3xl lg:text-4xl font-bold">
|
||||
```
|
||||
|
||||
### Padding/Margin Responsivo
|
||||
```tsx
|
||||
<div className="py-8 md:py-12 lg:py-16">
|
||||
```
|
||||
|
||||
### Flex Responsivo
|
||||
```tsx
|
||||
<div className="flex flex-col md:flex-row gap-4">
|
||||
```
|
||||
|
||||
## 🌐 Uso do Sistema de Idiomas
|
||||
|
||||
### Em Componentes
|
||||
```tsx
|
||||
import { useTranslation } from "@/lib/i18n";
|
||||
|
||||
export function MyComponent() {
|
||||
const { t, locale, setLocale } = useTranslation();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>{t('page.title')}</h1>
|
||||
<p>{t('page.description', { name: 'João' })}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Trocar Idioma
|
||||
```tsx
|
||||
setLocale('pt-BR'); // ou 'en' ou 'es'
|
||||
```
|
||||
|
||||
## 📱 Testes de Responsividade
|
||||
|
||||
### Dispositivos para Testar:
|
||||
1. **Mobile**: 375x667 (iPhone SE)
|
||||
2. **Mobile**: 390x844 (iPhone 12 Pro)
|
||||
3. **Tablet**: 768x1024 (iPad)
|
||||
4. **Desktop**: 1280x720
|
||||
5. **Desktop**: 1920x1080
|
||||
|
||||
### Ferramentas:
|
||||
- Chrome DevTools (F12 → Toggle Device Toolbar)
|
||||
- Firefox Responsive Design Mode
|
||||
- Testes em dispositivos reais
|
||||
|
||||
## 🚀 Comandos Úteis
|
||||
|
||||
```bash
|
||||
# Rodar em desenvolvimento
|
||||
npm run dev
|
||||
|
||||
# Build para produção
|
||||
npm run build
|
||||
|
||||
# Verificar erros de lint
|
||||
npm run lint
|
||||
|
||||
# Corrigir erros de lint
|
||||
npm run lint:fix
|
||||
```
|
||||
|
||||
## 📝 Notas
|
||||
|
||||
- O sistema de cores já está padronizado para `#F0932B`
|
||||
- O Edge Runtime foi removido de todos os arquivos problemáticos
|
||||
- O projeto usa Next.js 14 com App Router
|
||||
- Tailwind CSS é usado para estilização
|
||||
- shadcn/ui é usado para componentes
|
||||
BIN
frontend/public/111.png
Normal file
BIN
frontend/public/111.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
BIN
frontend/public/16.png
Normal file
BIN
frontend/public/16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
BIN
frontend/public/18.png
Normal file
BIN
frontend/public/18.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 142 KiB |
|
|
@ -68,7 +68,7 @@ export default function AboutPage() {
|
|||
</p>
|
||||
</div>
|
||||
<div className="relative">
|
||||
<div className="relative h-96 rounded-2xl overflow-hidden shadow-2xl bg-[#f0932b]">
|
||||
<div className="relative h-96 rounded-2xl overflow-hidden shadow-2xl bg-[#F0932B]">
|
||||
<Image
|
||||
src="/1.png"
|
||||
alt="GoHorse Jobs Team"
|
||||
|
|
@ -93,7 +93,7 @@ export default function AboutPage() {
|
|||
<div className="max-w-6xl mx-auto">
|
||||
<div className="grid lg:grid-cols-2 gap-16 items-center">
|
||||
<div className="order-2 lg:order-1">
|
||||
<div className="relative h-96 rounded-2xl overflow-hidden shadow-xl bg-[#f0932b]">
|
||||
<div className="relative h-96 rounded-2xl overflow-hidden shadow-xl bg-[#F0932B]">
|
||||
<Image
|
||||
src="/2.png"
|
||||
alt="O que fazemos"
|
||||
|
|
@ -215,7 +215,7 @@ export default function AboutPage() {
|
|||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="relative py-20 md:py-28 bg-[#f0932b] overflow-hidden">
|
||||
<section className="relative py-20 md:py-28 bg-[#F0932B] overflow-hidden">
|
||||
<Image
|
||||
src="/4.png"
|
||||
alt="Background"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
import { NextResponse } from 'next/server';
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
|
||||
/**
|
||||
* Runtime Configuration API
|
||||
*
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ export default function BlogPostPage() {
|
|||
{/* Article Header */}
|
||||
<article className="py-12">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="max-w-4xl mx-auto flex flex-col items-start text-left">
|
||||
{/* Back Button */}
|
||||
<Link
|
||||
href="/blog"
|
||||
|
|
@ -311,10 +311,16 @@ export default function BlogPostPage() {
|
|||
</span>
|
||||
</div>
|
||||
|
||||
{/* Title */}
|
||||
{/* Title, Subtitle e Botão alinhados à esquerda */}
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-6 leading-tight">
|
||||
{post.title}
|
||||
</h1>
|
||||
<p className="mb-8 text-lg text-gray-700">
|
||||
Conectamos você com as melhores empresas e techs.
|
||||
</p>
|
||||
<button className="bg-[#f0932b] text-white font-bold px-8 py-4 rounded mt-4">
|
||||
Buscar Vagas
|
||||
</button>
|
||||
|
||||
{/* Meta Info */}
|
||||
<div className="flex flex-wrap items-center gap-6 text-gray-600 mb-8 pb-8 border-b border-gray-200">
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ export default function BlogPage() {
|
|||
|
||||
<main className="flex-1">
|
||||
{/* Hero Section */}
|
||||
<section className="relative bg-[#f0932b] py-16 md:py-24 overflow-hidden">
|
||||
<section className="relative bg-[#F0932B] py-16 md:py-24 overflow-hidden">
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
<div className="absolute top-0 left-0 w-full h-full bg-[radial-gradient(circle_at_30%_50%,rgba(255,255,255,0.2)_0%,transparent_50%)]"></div>
|
||||
</div>
|
||||
|
|
@ -209,7 +209,7 @@ export default function BlogPage() {
|
|||
placeholder="Buscar artigos..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="w-full pl-14 pr-4 py-3 rounded-full text-gray-900 focus:outline-none focus:ring-2 focus:ring-[#f0932b] text-lg bg-white"
|
||||
className="w-full pl-14 pr-4 py-3 rounded-full text-gray-900 focus:outline-none focus:ring-2 focus:ring-[#F0932B] text-lg bg-white"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -225,9 +225,8 @@ export default function BlogPage() {
|
|||
<button
|
||||
key={category}
|
||||
onClick={() => setSelectedCategory(category)}
|
||||
className={`px-5 py-2 rounded-full font-medium whitespace-nowrap transition-all ${
|
||||
selectedCategory === category
|
||||
? 'bg-[#f0932b] text-white shadow-md'
|
||||
className={`px-5 py-2 rounded-full font-medium whitespace-nowrap transition-all ${selectedCategory === category
|
||||
? 'bg-[#F0932B] text-white shadow-md'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
|
|
@ -243,7 +242,7 @@ export default function BlogPage() {
|
|||
<section className="py-12 bg-gradient-to-b from-orange-50 to-white">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center gap-3 mb-8">
|
||||
<TrendingUp className="w-7 h-7 text-[#f0932b]" />
|
||||
<TrendingUp className="w-7 h-7 text-[#F0932B]" />
|
||||
<h2 className="text-3xl font-bold text-gray-900">Artigos em Destaque</h2>
|
||||
</div>
|
||||
|
||||
|
|
@ -252,7 +251,7 @@ export default function BlogPage() {
|
|||
<Link
|
||||
key={post.id}
|
||||
href={`/blog/${post.slug}`}
|
||||
className="group bg-white rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 border-2 border-[#f0932b]/20"
|
||||
className="group bg-white rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 border-2 border-[#F0932B]/20"
|
||||
>
|
||||
<div className="relative h-56 overflow-hidden">
|
||||
<Image
|
||||
|
|
@ -262,18 +261,18 @@ export default function BlogPage() {
|
|||
className="object-cover group-hover:scale-110 transition-transform duration-300"
|
||||
/>
|
||||
<div className="absolute top-4 left-4">
|
||||
<span className="bg-[#f0932b] text-white px-3 py-1 rounded-full text-xs font-semibold">
|
||||
<span className="bg-[#F0932B] text-white px-3 py-1 rounded-full text-xs font-semibold">
|
||||
Destaque
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<span className="bg-[#f0932b]/10 text-[#f0932b] px-3 py-1 rounded-full text-xs font-semibold">
|
||||
<span className="bg-[#F0932B]/10 text-[#F0932B] px-3 py-1 rounded-full text-xs font-semibold">
|
||||
{post.category}
|
||||
</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-3 group-hover:text-[#f0932b] transition-colors line-clamp-2">
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-3 group-hover:text-[#F0932B] transition-colors line-clamp-2">
|
||||
{post.title}
|
||||
</h3>
|
||||
<p className="text-gray-600 mb-4 line-clamp-2">
|
||||
|
|
@ -307,7 +306,7 @@ export default function BlogPage() {
|
|||
{selectedCategory === "Todas" ? "Todos os Artigos" : `Categoria: ${selectedCategory}`}
|
||||
</h2>
|
||||
<p className="text-gray-600">
|
||||
<span className="font-semibold text-[#f0932b]">{filteredPosts.length}</span> artigos encontrados
|
||||
<span className="font-semibold text-[#F0932B]">{filteredPosts.length}</span> artigos encontrados
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
@ -316,7 +315,7 @@ export default function BlogPage() {
|
|||
<Link
|
||||
key={post.id}
|
||||
href={`/blog/${post.slug}`}
|
||||
className="group bg-white rounded-2xl overflow-hidden shadow-md hover:shadow-xl transition-all duration-300 border border-gray-200 hover:border-[#f0932b]"
|
||||
className="group bg-white rounded-2xl overflow-hidden shadow-md hover:shadow-xl transition-all duration-300 border border-gray-200 hover:border-[#F0932B]"
|
||||
>
|
||||
<div className="relative h-48 overflow-hidden">
|
||||
<Image
|
||||
|
|
@ -332,7 +331,7 @@ export default function BlogPage() {
|
|||
{post.category}
|
||||
</span>
|
||||
</div>
|
||||
<h3 className="text-lg font-bold text-gray-900 mb-2 group-hover:text-[#f0932b] transition-colors line-clamp-2">
|
||||
<h3 className="text-lg font-bold text-gray-900 mb-2 group-hover:text-[#F0932B] transition-colors line-clamp-2">
|
||||
{post.title}
|
||||
</h3>
|
||||
<p className="text-gray-600 text-sm mb-4 line-clamp-3">
|
||||
|
|
@ -343,7 +342,7 @@ export default function BlogPage() {
|
|||
<Clock className="w-3 h-3" />
|
||||
<span>{post.readTime}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1 text-[#f0932b] font-semibold text-sm">
|
||||
<div className="flex items-center gap-1 text-[#F0932B] font-semibold text-sm">
|
||||
<span>Ler mais</span>
|
||||
<ArrowRight className="w-4 h-4 group-hover:translate-x-1 transition-transform" />
|
||||
</div>
|
||||
|
|
@ -364,7 +363,7 @@ export default function BlogPage() {
|
|||
</section>
|
||||
|
||||
{/* Newsletter CTA */}
|
||||
<section className="bg-gradient-to-br from-[#f0932b] to-[#e67e22] py-16">
|
||||
<section className="bg-gradient-to-br from-[#F0932B] to-[#d97d1a] py-16">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-3xl mx-auto text-center text-white">
|
||||
<Lightbulb className="w-16 h-16 mx-auto mb-6" />
|
||||
|
|
@ -380,7 +379,7 @@ export default function BlogPage() {
|
|||
placeholder="Seu melhor e-mail"
|
||||
className="flex-1 px-6 py-4 rounded-full bg-white text-gray-900 placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-white"
|
||||
/>
|
||||
<button className="bg-white text-[#f0932b] hover:bg-gray-100 font-bold px-8 py-4 rounded-full transition-colors whitespace-nowrap">
|
||||
<button className="bg-white text-[#F0932B] hover:bg-gray-100 font-bold px-8 py-4 rounded-full transition-colors whitespace-nowrap">
|
||||
Assinar Newsletter
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ export default function CompaniesPage() {
|
|||
|
||||
<main className="flex-1">
|
||||
{/* Hero Section */}
|
||||
<section className="relative bg-[#f0932b] py-20 md:py-28 overflow-hidden">
|
||||
<section className="relative bg-[#F0932B] py-20 md:py-28 overflow-hidden">
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
<div className="absolute top-0 left-0 w-full h-full bg-[radial-gradient(circle_at_30%_50%,rgba(255,255,255,0.2)_0%,transparent_50%)]"></div>
|
||||
</div>
|
||||
|
|
@ -193,7 +193,7 @@ export default function CompaniesPage() {
|
|||
placeholder="Buscar empresas por nome ou setor..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="w-full pl-14 pr-4 py-3 rounded-full text-gray-900 focus:outline-none focus:ring-2 focus:ring-[#f0932b] text-lg bg-white"
|
||||
className="w-full pl-14 pr-4 py-3 rounded-full text-gray-900 focus:outline-none focus:ring-2 focus:ring-[#F0932B] text-lg bg-white"
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
|
@ -214,7 +214,7 @@ export default function CompaniesPage() {
|
|||
<select
|
||||
value={selectedIndustry}
|
||||
onChange={(e) => setSelectedIndustry(e.target.value)}
|
||||
className="px-4 py-2 rounded-full border border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#f0932b] bg-white"
|
||||
className="px-4 py-2 rounded-full border border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#F0932B] bg-white"
|
||||
>
|
||||
{industries.map(industry => (
|
||||
<option key={industry} value={industry}>{industry}</option>
|
||||
|
|
@ -224,7 +224,7 @@ export default function CompaniesPage() {
|
|||
<select
|
||||
value={selectedSize}
|
||||
onChange={(e) => setSelectedSize(e.target.value)}
|
||||
className="px-4 py-2 rounded-full border border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#f0932b] bg-white"
|
||||
className="px-4 py-2 rounded-full border border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#F0932B] bg-white"
|
||||
>
|
||||
{companySizes.map(size => (
|
||||
<option key={size} value={size}>{size}</option>
|
||||
|
|
@ -232,7 +232,7 @@ export default function CompaniesPage() {
|
|||
</select>
|
||||
|
||||
<div className="ml-auto text-sm text-gray-600">
|
||||
<span className="font-semibold text-[#f0932b]">{filteredCompanies.length}</span> empresas encontradas
|
||||
<span className="font-semibold text-[#F0932B]">{filteredCompanies.length}</span> empresas encontradas
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -243,7 +243,7 @@ export default function CompaniesPage() {
|
|||
<section className="py-16 bg-gradient-to-b from-orange-50 to-white">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center gap-3 mb-8">
|
||||
<Star className="w-6 h-6 text-[#f0932b]" />
|
||||
<Star className="w-6 h-6 text-[#F0932B]" />
|
||||
<h2 className="text-3xl font-bold text-gray-900">Empresas em Destaque</h2>
|
||||
</div>
|
||||
|
||||
|
|
@ -251,11 +251,11 @@ export default function CompaniesPage() {
|
|||
{featuredCompanies.map((company) => (
|
||||
<div
|
||||
key={company.id}
|
||||
className="bg-white rounded-2xl p-6 shadow-lg hover:shadow-xl transition-all duration-300 border-2 border-[#f0932b]/20"
|
||||
className="bg-white rounded-2xl p-6 shadow-lg hover:shadow-xl transition-all duration-300 border-2 border-[#F0932B]/20"
|
||||
>
|
||||
<div className="flex items-start gap-4 mb-4">
|
||||
<div className="w-16 h-16 rounded-xl bg-[#f0932b]/10 flex items-center justify-center flex-shrink-0">
|
||||
<Building2 className="w-8 h-8 text-[#f0932b]" />
|
||||
<div className="w-16 h-16 rounded-xl bg-[#F0932B]/10 flex items-center justify-center flex-shrink-0">
|
||||
<Building2 className="w-8 h-8 text-[#F0932B]" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div className="flex items-start justify-between mb-2">
|
||||
|
|
@ -275,7 +275,7 @@ export default function CompaniesPage() {
|
|||
{company.employees}
|
||||
</span>
|
||||
</div>
|
||||
<span className="inline-block bg-[#f0932b]/10 text-[#f0932b] px-3 py-1 rounded-full text-xs font-semibold">
|
||||
<span className="inline-block bg-[#F0932B]/10 text-[#F0932B] px-3 py-1 rounded-full text-xs font-semibold">
|
||||
{company.industry}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -292,13 +292,13 @@ export default function CompaniesPage() {
|
|||
</div>
|
||||
|
||||
<div className="flex items-center justify-between pt-4 border-t border-gray-100">
|
||||
<div className="flex items-center gap-2 text-[#f0932b] font-semibold">
|
||||
<div className="flex items-center gap-2 text-[#F0932B] font-semibold">
|
||||
<Briefcase className="w-5 h-5" />
|
||||
<span>{company.openJobs} vagas abertas</span>
|
||||
</div>
|
||||
<Link
|
||||
href={`/companies/${company.id}`}
|
||||
className="text-[#f0932b] hover:underline font-semibold"
|
||||
className="text-[#F0932B] hover:underline font-semibold"
|
||||
>
|
||||
Ver perfil →
|
||||
</Link>
|
||||
|
|
@ -319,11 +319,11 @@ export default function CompaniesPage() {
|
|||
{filteredCompanies.map((company) => (
|
||||
<div
|
||||
key={company.id}
|
||||
className="bg-white rounded-2xl p-6 shadow-md hover:shadow-xl transition-all duration-300 border border-gray-200 hover:border-[#f0932b]"
|
||||
className="bg-white rounded-2xl p-6 shadow-md hover:shadow-xl transition-all duration-300 border border-gray-200 hover:border-[#F0932B]"
|
||||
>
|
||||
<div className="flex items-start justify-between mb-4">
|
||||
<div className="w-14 h-14 rounded-lg bg-gray-100 flex items-center justify-center">
|
||||
<Building2 className="w-7 h-7 text-[#f0932b]" />
|
||||
<Building2 className="w-7 h-7 text-[#F0932B]" />
|
||||
</div>
|
||||
{company.featured && (
|
||||
<span className="bg-yellow-100 text-yellow-700 text-xs font-semibold px-2 py-1 rounded-full">
|
||||
|
|
@ -335,7 +335,7 @@ export default function CompaniesPage() {
|
|||
<h3 className="text-xl font-bold text-gray-900 mb-2">{company.name}</h3>
|
||||
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<span className="bg-[#f0932b]/10 text-[#f0932b] px-3 py-1 rounded-full text-xs font-semibold">
|
||||
<span className="bg-[#F0932B]/10 text-[#F0932B] px-3 py-1 rounded-full text-xs font-semibold">
|
||||
{company.industry}
|
||||
</span>
|
||||
<div className="flex items-center gap-1">
|
||||
|
|
@ -358,12 +358,12 @@ export default function CompaniesPage() {
|
|||
</div>
|
||||
|
||||
<div className="pt-4 border-t border-gray-100 flex items-center justify-between">
|
||||
<span className="text-[#f0932b] font-semibold text-sm">
|
||||
<span className="text-[#F0932B] font-semibold text-sm">
|
||||
{company.openJobs} vagas
|
||||
</span>
|
||||
<Link
|
||||
href={`/companies/${company.id}`}
|
||||
className="text-gray-600 hover:text-[#f0932b] font-semibold text-sm transition-colors"
|
||||
className="text-gray-600 hover:text-[#F0932B] font-semibold text-sm transition-colors"
|
||||
>
|
||||
Ver mais →
|
||||
</Link>
|
||||
|
|
|
|||
|
|
@ -5,9 +5,6 @@ import { useRouter, useParams } from "next/navigation";
|
|||
import { toast } from "sonner";
|
||||
import { emailTemplatesApi, EmailTemplate } from "@/lib/api";
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
|
||||
export default function EditEmailTemplatePage() {
|
||||
const router = useRouter();
|
||||
const params = useParams();
|
||||
|
|
|
|||
|
|
@ -12,9 +12,6 @@ import { toast } from "sonner"
|
|||
import { Send, ArrowLeft } from "lucide-react"
|
||||
import { formatDistanceToNow } from "date-fns"
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
|
||||
export default function TicketDetailsPage() {
|
||||
const params = useParams()
|
||||
const router = useRouter()
|
||||
|
|
|
|||
|
|
@ -27,9 +27,6 @@ import {
|
|||
DialogTitle,
|
||||
} from "@/components/ui/dialog"
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
|
||||
export default function AdminTicketDetailsPage() {
|
||||
const params = useParams()
|
||||
const router = useRouter()
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ body {
|
|||
--card-foreground: oklch(0.145 0 0);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.145 0 0);
|
||||
--primary: oklch(0.705 0.188 57.5); /* #f0932b Orange */
|
||||
--primary: oklch(0.705 0.188 57.5); /* #F0932B Orange */
|
||||
--primary-foreground: oklch(1 0 0);
|
||||
--secondary: oklch(0.97 0 0);
|
||||
--secondary-foreground: oklch(0.205 0 0);
|
||||
|
|
@ -91,7 +91,7 @@ body {
|
|||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.205 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.705 0.188 57.5); /* #f0932b Orange */
|
||||
--primary: oklch(0.705 0.188 57.5); /* #F0932B Orange */
|
||||
--primary-foreground: oklch(1 0 0);
|
||||
--secondary: oklch(0.269 0 0);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
|
|
|
|||
|
|
@ -49,11 +49,6 @@ import { useTranslation } from "@/lib/i18n";
|
|||
import { getCurrentUser } from "@/lib/auth";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
export default function JobApplicationPage({
|
||||
params,
|
||||
}: {
|
||||
|
|
|
|||
|
|
@ -37,9 +37,6 @@ import Link from "next/link";
|
|||
import { motion } from "framer-motion";
|
||||
import { useTranslation } from "@/lib/i18n";
|
||||
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
export default function JobDetailPage({
|
||||
params,
|
||||
}: {
|
||||
|
|
|
|||
|
|
@ -151,13 +151,17 @@ function JobsContent() {
|
|||
return (
|
||||
<>
|
||||
{/* Hero Section */}
|
||||
<section className="bg-gradient-to-br from-primary/10 via-primary/5 to-transparent py-12 md:py-16">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-3xl mx-auto text-center">
|
||||
<section className="relative bg-[#F0932B] py-12 md:py-16 overflow-hidden">
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
<div className="absolute top-0 left-0 w-full h-full bg-[radial-gradient(circle_at_30%_50%,rgba(255,255,255,0.2)_0%,transparent_50%)]"></div>
|
||||
</div>
|
||||
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
|
||||
<div className="max-w-3xl mx-auto text-center text-white">
|
||||
<motion.h1
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
className="text-4xl md:text-5xl font-bold text-foreground mb-4 text-balance"
|
||||
className="text-4xl md:text-5xl font-bold mb-4 text-balance"
|
||||
>
|
||||
{t('jobs.title')}
|
||||
</motion.h1>
|
||||
|
|
@ -165,7 +169,7 @@ function JobsContent() {
|
|||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.1 }}
|
||||
className="text-lg text-muted-foreground text-pretty"
|
||||
className="text-lg opacity-95 text-pretty"
|
||||
>
|
||||
{loading ? t('jobs.loading') : t('jobs.subtitle', { count: totalJobs })}
|
||||
</motion.p>
|
||||
|
|
@ -174,7 +178,7 @@ function JobsContent() {
|
|||
</section>
|
||||
|
||||
{/* Search and Filters Section */}
|
||||
<section className="py-8 border-b bg-background/50">
|
||||
<section className="py-8 border-b bg-white">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-5xl mx-auto space-y-4">
|
||||
{/* Main Search Bar */}
|
||||
|
|
@ -203,12 +207,12 @@ function JobsContent() {
|
|||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setShowFilters(!showFilters)}
|
||||
className="h-12 gap-2"
|
||||
className="h-12 gap-2 hover:bg-[#F0932B]/10 hover:text-[#F0932B] hover:border-[#F0932B]"
|
||||
>
|
||||
<SlidersHorizontal className="h-4 w-4" />
|
||||
{t('jobs.filters.toggle')}
|
||||
{hasActiveFilters && (
|
||||
<Badge variant="secondary" className="ml-1 px-1 py-0 text-xs">
|
||||
<Badge variant="secondary" className="ml-1 px-1 py-0 text-xs bg-[#F0932B] text-white">
|
||||
!
|
||||
</Badge>
|
||||
)}
|
||||
|
|
@ -290,7 +294,7 @@ function JobsContent() {
|
|||
<Button
|
||||
variant="outline"
|
||||
onClick={clearFilters}
|
||||
className="gap-2"
|
||||
className="gap-2 hover:bg-red-50 hover:text-red-600 hover:border-red-300"
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
{t('jobs.reset')}
|
||||
|
|
@ -316,7 +320,7 @@ function JobsContent() {
|
|||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<span className="hidden sm:inline">Active filters:</span>
|
||||
{searchTerm && (
|
||||
<Badge variant="secondary" className="gap-1">
|
||||
<Badge variant="secondary" className="gap-1 bg-[#F0932B]/10 text-[#F0932B] border-[#F0932B]/20">
|
||||
"{searchTerm}"
|
||||
<button onClick={() => setSearchTerm("")} className="ml-1">
|
||||
<X className="h-3 w-3" />
|
||||
|
|
@ -324,7 +328,7 @@ function JobsContent() {
|
|||
</Badge>
|
||||
)}
|
||||
{locationFilter && (
|
||||
<Badge variant="secondary" className="gap-1">
|
||||
<Badge variant="secondary" className="gap-1 bg-[#F0932B]/10 text-[#F0932B] border-[#F0932B]/20">
|
||||
{locationFilter}
|
||||
<button onClick={() => setLocationFilter("")} className="ml-1">
|
||||
<X className="h-3 w-3" />
|
||||
|
|
@ -332,7 +336,7 @@ function JobsContent() {
|
|||
</Badge>
|
||||
)}
|
||||
{typeFilter !== "all" && (
|
||||
<Badge variant="secondary" className="gap-1">
|
||||
<Badge variant="secondary" className="gap-1 bg-[#F0932B]/10 text-[#F0932B] border-[#F0932B]/20">
|
||||
{typeFilter}
|
||||
<button onClick={() => setTypeFilter("all")} className="ml-1">
|
||||
<X className="h-3 w-3" />
|
||||
|
|
@ -340,7 +344,7 @@ function JobsContent() {
|
|||
</Badge>
|
||||
)}
|
||||
{workModeFilter !== "all" && (
|
||||
<Badge variant="secondary" className="gap-1">
|
||||
<Badge variant="secondary" className="gap-1 bg-[#F0932B]/10 text-[#F0932B] border-[#F0932B]/20">
|
||||
{workModeFilter === "remote" ? t("workMode.remote") :
|
||||
workModeFilter === "hybrid" ? t("workMode.hybrid") :
|
||||
workModeFilter === "onsite" ? t("workMode.onsite") : workModeFilter}
|
||||
|
|
@ -357,7 +361,7 @@ function JobsContent() {
|
|||
</section>
|
||||
|
||||
{/* Jobs Grid */}
|
||||
<section className="py-12">
|
||||
<section className="py-12 bg-white">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
{error && (
|
||||
|
|
@ -394,6 +398,7 @@ function JobsContent() {
|
|||
variant="outline"
|
||||
onClick={() => setCurrentPage(p => Math.max(1, p - 1))}
|
||||
disabled={currentPage === 1}
|
||||
className="hover:bg-[#F0932B]/10 hover:text-[#F0932B] hover:border-[#F0932B]"
|
||||
>
|
||||
{t('jobs.pagination.previous')}
|
||||
</Button>
|
||||
|
|
@ -404,6 +409,7 @@ function JobsContent() {
|
|||
variant="outline"
|
||||
onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))}
|
||||
disabled={currentPage === totalPages}
|
||||
className="hover:bg-[#F0932B]/10 hover:text-[#F0932B] hover:border-[#F0932B]"
|
||||
>
|
||||
{t('jobs.pagination.next')}
|
||||
</Button>
|
||||
|
|
@ -425,7 +431,7 @@ function JobsContent() {
|
|||
<Button
|
||||
variant="outline"
|
||||
onClick={clearFilters}
|
||||
className="gap-2"
|
||||
className="gap-2 hover:bg-[#F0932B]/10 hover:text-[#F0932B] hover:border-[#F0932B]"
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
{t('jobs.resetFilters')}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { Button } from "@/components/ui/button"
|
|||
import { Card, CardContent } from "@/components/ui/card"
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
|
||||
import { mockJobs, mockTestimonials } from "@/lib/mock-data"
|
||||
import { FileText, CheckCircle, ArrowRight, Building2, Users, ChevronLeft, ChevronRight } from "lucide-react"
|
||||
import { FileText, CheckCircle, ArrowRight, Building2, Users, ChevronLeft, ChevronRight, Eye } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
import { motion } from "framer-motion"
|
||||
import Image from "next/image"
|
||||
|
|
@ -24,6 +24,22 @@ export default function HomePage() {
|
|||
const [loading, setLoading] = useState(true)
|
||||
const [featuredIndex, setFeaturedIndex] = useState(0)
|
||||
const [moreJobsIndex, setMoreJobsIndex] = useState(0)
|
||||
const [openFilters, setOpenFilters] = useState({
|
||||
contractType: false,
|
||||
workMode: false,
|
||||
location: false,
|
||||
salary: false
|
||||
})
|
||||
|
||||
const toggleFilter = (filterName: keyof typeof openFilters) => {
|
||||
setOpenFilters(prev => ({
|
||||
contractType: false,
|
||||
workMode: false,
|
||||
location: false,
|
||||
salary: false,
|
||||
[filterName]: !prev[filterName]
|
||||
}))
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchFeaturedJobs() {
|
||||
|
|
@ -114,7 +130,7 @@ export default function HomePage() {
|
|||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="text-4xl sm:text-5xl lg:text-5xl font-bold mb-4 text-white"
|
||||
className="text-5xl sm:text-6xl lg:text-6xl font-bold mb-6 text-white leading-tight"
|
||||
>
|
||||
{t('home.hero.title')}<br />{t('home.hero.titleLine2')}
|
||||
</motion.h1>
|
||||
|
|
@ -122,7 +138,7 @@ export default function HomePage() {
|
|||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5, delay: 0.1 }}
|
||||
className="text-base mb-8 leading-relaxed text-white"
|
||||
className="text-2xl mb-10 leading-relaxed text-white"
|
||||
>
|
||||
{t('home.hero.subtitle')}
|
||||
</motion.p>
|
||||
|
|
@ -133,7 +149,7 @@ export default function HomePage() {
|
|||
className="flex gap-4"
|
||||
>
|
||||
<Link href="/jobs">
|
||||
<Button size="lg" className="bg-primary hover:bg-primary/90 text-white hover:shadow-lg font-semibold px-8 py-3 text-base rounded-lg transition-all duration-200 border-0">
|
||||
<Button size="lg" className="bg-primary hover:bg-primary/90 text-white hover:shadow-lg font-bold px-10 py-6 text-lg rounded-lg transition-all duration-200 border-0">
|
||||
{t('home.hero.cta')}
|
||||
</Button>
|
||||
</Link>
|
||||
|
|
@ -147,7 +163,7 @@ export default function HomePage() {
|
|||
<section className="bg-white py-16">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-8xl">
|
||||
<div className="mb-8">
|
||||
<div className="flex flex-col sm:flex-row items-stretch sm:items-center gap-3 mb-6">
|
||||
<div className="flex flex-col sm:flex-row items-stretch sm:items-center gap-0 mb-6">
|
||||
<div className="flex-1 relative">
|
||||
<svg className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
||||
|
|
@ -155,23 +171,38 @@ export default function HomePage() {
|
|||
<input
|
||||
type="text"
|
||||
placeholder={t('home.search.placeholder')}
|
||||
className="w-full h-14 pl-12 pr-4 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent text-base bg-white shadow-sm"
|
||||
className="w-full h-14 pl-12 pr-4 border border-gray-300 rounded-l-lg rounded-r-none focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent text-base bg-white shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
<Button className="bg-primary hover:bg-primary/90 text-white h-14 px-10 rounded-lg font-semibold flex items-center justify-center gap-2 shadow-md hover:shadow-lg transition-all">
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
|
||||
</svg>
|
||||
<Button className="bg-primary hover:bg-primary/90 text-white h-14 px-16 rounded-r-lg rounded-l-none font-semibold flex items-center justify-center gap-3 shadow-md hover:shadow-lg transition-all -ml-px min-w-[220px] text-2xl">
|
||||
<FilterIcon />
|
||||
{t('home.search.filter')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<div className="bg-white border-2 border-gray-200 rounded-xl p-5 shadow-sm hover:border-primary/30 transition-colors">
|
||||
<div className="flex items-center justify-between w-full mb-4">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 items-start">
|
||||
<div className="bg-white border-2 border-gray-200 rounded-xl shadow-sm hover:border-primary/30 transition-colors relative">
|
||||
<button
|
||||
onClick={() => toggleFilter('contractType')}
|
||||
className="flex items-center justify-between w-full p-5"
|
||||
>
|
||||
<span className="text-base font-bold text-gray-900">{t('home.search.contractType')}</span>
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
<svg
|
||||
className={`w-5 h-5 text-gray-600 transition-transform ${openFilters.contractType ? 'rotate-180' : ''}`}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
{openFilters.contractType && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: -10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
className="absolute top-full left-0 right-0 mt-2 bg-white border-2 border-gray-200 rounded-xl shadow-lg z-50 space-y-3 px-5 py-5"
|
||||
>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>{t('home.search.pj')}</span>
|
||||
|
|
@ -184,14 +215,32 @@ export default function HomePage() {
|
|||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>{t('home.search.freelancer')}</span>
|
||||
</label>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="bg-white border-2 border-gray-200 rounded-xl p-5 shadow-sm hover:border-primary/30 transition-colors">
|
||||
<div className="flex items-center justify-between w-full mb-4">
|
||||
<div className="bg-white border-2 border-gray-200 rounded-xl shadow-sm hover:border-primary/30 transition-colors relative">
|
||||
<button
|
||||
onClick={() => toggleFilter('workMode')}
|
||||
className="flex items-center justify-between w-full p-5"
|
||||
>
|
||||
<span className="text-base font-bold text-gray-900">{t('home.search.workMode')}</span>
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
<svg
|
||||
className={`w-5 h-5 text-gray-600 transition-transform ${openFilters.workMode ? 'rotate-180' : ''}`}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
{openFilters.workMode && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: -10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
className="absolute top-full left-0 right-0 mt-2 bg-white border-2 border-gray-200 rounded-xl shadow-lg z-50 space-y-3 px-5 py-5"
|
||||
>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>{t('home.search.homeOffice')}</span>
|
||||
|
|
@ -204,25 +253,188 @@ export default function HomePage() {
|
|||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>{t('home.search.hybrid')}</span>
|
||||
</label>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="bg-white border-2 border-gray-200 rounded-xl p-5 shadow-sm hover:border-primary/30 transition-colors">
|
||||
<div className="flex items-center justify-between w-full mb-4">
|
||||
<div className="bg-white border-2 border-gray-200 rounded-xl shadow-sm hover:border-primary/30 transition-colors relative">
|
||||
<button
|
||||
onClick={() => toggleFilter('location')}
|
||||
className="flex items-center justify-between w-full p-5"
|
||||
>
|
||||
<span className="text-base font-bold text-gray-900">{t('home.search.location')}</span>
|
||||
</div>
|
||||
<select className="w-full px-4 py-2.5 text-sm text-gray-700 bg-gray-50 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
|
||||
<option>{t('home.search.select')}</option>
|
||||
</select>
|
||||
<svg
|
||||
className={`w-5 h-5 text-gray-600 transition-transform ${openFilters.location ? 'rotate-180' : ''}`}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
{openFilters.location && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: -10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
className="absolute top-full left-0 right-0 mt-2 bg-white border-2 border-gray-200 rounded-xl shadow-lg z-50 space-y-3 max-h-64 overflow-y-auto px-5 py-5 scrollbar-hide"
|
||||
>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Acre, AC</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Alagoas, AL</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Amapá, AP</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Amazonas, AM</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Bahia, BA</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Ceará, CE</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Distrito Federal, DF</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Espírito Santo, ES</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Goiás, GO</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Maranhão, MA</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Mato Grosso, MT</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Mato Grosso do Sul, MS</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Minas Gerais, MG</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Pará, PA</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Paraíba, PB</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Paraná, PR</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Pernambuco, PE</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Piauí, PI</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Rio de Janeiro, RJ</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Rio Grande do Norte, RN</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Rio Grande do Sul, RS</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Rondônia, RO</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Roraima, RR</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Santa Catarina, SC</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>São Paulo, SP</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Sergipe, SE</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Tocantins, TO</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Remoto</span>
|
||||
</label>
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="bg-white border-2 border-gray-200 rounded-xl p-5 shadow-sm hover:border-primary/30 transition-colors">
|
||||
<div className="flex items-center justify-between w-full mb-4">
|
||||
<div className="bg-white border-2 border-gray-200 rounded-xl shadow-sm hover:border-primary/30 transition-colors relative">
|
||||
<button
|
||||
onClick={() => toggleFilter('salary')}
|
||||
className="flex items-center justify-between w-full p-5"
|
||||
>
|
||||
<span className="text-base font-bold text-gray-900">{t('home.search.salary')}</span>
|
||||
</div>
|
||||
<select className="w-full px-4 py-2.5 text-sm text-gray-700 bg-gray-50 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
|
||||
<option>{t('home.search.select')}</option>
|
||||
</select>
|
||||
<svg
|
||||
className={`w-5 h-5 text-gray-600 transition-transform ${openFilters.salary ? 'rotate-180' : ''}`}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
{openFilters.salary && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: -10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
className="absolute top-full left-0 right-0 mt-2 bg-white border-2 border-gray-200 rounded-xl shadow-lg z-50 space-y-3 px-5 py-5"
|
||||
>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Até R$ 3.000</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>R$ 3.000 - R$ 6.000</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>R$ 6.000 - R$ 10.000</span>
|
||||
</label>
|
||||
<label className="flex items-center text-sm text-gray-700 cursor-pointer hover:text-gray-900 transition-colors">
|
||||
<input type="checkbox" className="w-4 h-4 text-primary border-gray-300 rounded focus:ring-primary mr-3" />
|
||||
<span>Acima de R$ 10.000</span>
|
||||
</label>
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -233,38 +445,18 @@ export default function HomePage() {
|
|||
<section className="bg-white py-12">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-8xl">
|
||||
<div className="flex justify-between items-center mb-8">
|
||||
<h2 className="text-2xl font-bold text-gray-900">{t('home.featuredJobs.title')}</h2>
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => setFeaturedIndex(Math.max(0, featuredIndex - 8))}
|
||||
disabled={featuredIndex === 0}
|
||||
className="h-10 w-10"
|
||||
>
|
||||
<ChevronLeft className="h-5 w-5" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => {
|
||||
const jobs = featuredJobs.length >= 16 ? featuredJobs.slice(0, 16) : mockJobs.slice(0, 16)
|
||||
setFeaturedIndex(Math.min(jobs.length - 8, featuredIndex + 8))
|
||||
}}
|
||||
disabled={featuredIndex >= ((featuredJobs.length >= 16 ? featuredJobs.slice(0, 16) : mockJobs.slice(0, 16)).length - 8)}
|
||||
className="h-10 w-10"
|
||||
>
|
||||
<ChevronRight className="h-5 w-5" />
|
||||
</Button>
|
||||
</div>
|
||||
<h2 className="text-3xl font-bold text-gray-900">Vagas em Destaque</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{(featuredJobs.length >= 16 ? featuredJobs.slice(0, 16) : mockJobs.slice(0, 16))
|
||||
.slice(featuredIndex, featuredIndex + 8)
|
||||
{(featuredJobs.length >= 4 ? featuredJobs.slice(0, 4) : mockJobs.slice(0, 4))
|
||||
.map((job, index) => {
|
||||
const dates = ['02/06', '05/06', '08/06', '11/06', '14/06', '17/06', '19/06', '20/06'];
|
||||
const randomDate = dates[(featuredIndex + index) % dates.length];
|
||||
const dates = ['02/06', '05/06', '08/06', '11/06'];
|
||||
const randomDate = dates[index % dates.length];
|
||||
const levels = ['Pleno', 'Júnior', 'Sênior', 'Pleno'];
|
||||
const level = levels[index % levels.length];
|
||||
const statusLabels = ['Remoto', 'Híbrido', 'Presencial', 'Remoto'];
|
||||
const statusLabel = statusLabels[index % statusLabels.length];
|
||||
return (
|
||||
<motion.div
|
||||
key={job.id}
|
||||
|
|
@ -272,46 +464,63 @@ export default function HomePage() {
|
|||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
<Card className="hover:shadow-xl transition-shadow border border-gray-200 rounded-2xl overflow-hidden bg-white h-full flex flex-col">
|
||||
{/* Ícone no topo */}
|
||||
<div className="p-6 pb-4">
|
||||
<div className="w-14 h-14 bg-gray-100 rounded-xl flex items-center justify-center mb-4">
|
||||
<Building2 className="w-7 h-7 text-gray-900" />
|
||||
<Card className="hover:shadow-lg transition-all border border-gray-200 rounded-2xl overflow-hidden bg-white h-full flex flex-col">
|
||||
{/* Header com logo, nome da empresa, seta e badge */}
|
||||
<div className="flex items-center justify-between p-4 border-b border-gray-100">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 bg-gray-100 rounded-lg flex items-center justify-center flex-shrink-0">
|
||||
<Building2 className="w-5 h-5 text-gray-700" />
|
||||
</div>
|
||||
|
||||
{/* Título */}
|
||||
<h3 className="font-bold text-lg mb-3 text-gray-900 line-clamp-2 min-h-[3.5rem]">{job.title}</h3>
|
||||
|
||||
{/* Tags */}
|
||||
<div className="flex flex-wrap gap-2 mb-3">
|
||||
<span className="text-xs px-3 py-1 bg-blue-50 text-blue-700 rounded-md border border-blue-200">
|
||||
{job.company}
|
||||
</span>
|
||||
<span className="text-xs px-3 py-1 bg-blue-50 text-blue-700 rounded-md border border-blue-200">
|
||||
{job.location}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Data */}
|
||||
<div className="flex items-center gap-1.5 text-gray-500 mb-4">
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||
<span className="text-sm font-medium text-gray-900 truncate">{job.company}</span>
|
||||
<svg className="w-4 h-4 text-gray-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
<span className="text-xs">{randomDate}</span>
|
||||
</div>
|
||||
<span className="text-xs px-3 py-1 bg-gray-900 text-white rounded-full font-medium flex-shrink-0">
|
||||
{statusLabel}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Botão */}
|
||||
<div className="px-6 pb-6 mt-auto">
|
||||
<Link href={`/jobs/${job.id}`}>
|
||||
<Button size="lg" className="w-full bg-primary hover:bg-primary/90 text-white rounded-lg font-semibold shadow-lg">
|
||||
{t('home.featuredJobs.apply')}
|
||||
{/* Background Image */}
|
||||
<div className="relative h-32 bg-gradient-to-br from-blue-50 to-purple-50 flex items-center justify-center overflow-hidden">
|
||||
<Image
|
||||
src="/111.png"
|
||||
alt="Background"
|
||||
fill
|
||||
className="object-cover"
|
||||
quality={100}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<CardContent className="p-5 flex flex-col flex-1">
|
||||
{/* Título da vaga */}
|
||||
<h3 className="font-bold text-lg text-gray-900 mb-2 line-clamp-2">{job.title}</h3>
|
||||
|
||||
{/* Info do nível */}
|
||||
<div className="mb-4 pb-4 border-b border-gray-200">
|
||||
<p className="text-sm text-gray-500">{level} · {job.location}</p>
|
||||
</div>
|
||||
|
||||
{/* Botões */}
|
||||
<div className="mt-auto flex gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
className="flex-1 border-gray-300 text-gray-700 hover:bg-gray-50 rounded-lg font-medium h-9 text-sm flex items-center justify-center gap-2"
|
||||
>
|
||||
<Eye className="w-4 h-4" />
|
||||
Ver Vaga
|
||||
</Button>
|
||||
<Link href={`/jobs/${job.id}`} className="flex-1">
|
||||
<Button className="w-full bg-gray-900 hover:bg-gray-800 text-white rounded-lg font-medium h-9 text-sm">
|
||||
Aplicar agora
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</motion.div>
|
||||
)})}
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -319,14 +528,16 @@ export default function HomePage() {
|
|||
{/* More Jobs Section */}
|
||||
<section className="bg-white py-12">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-8xl">
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<h2 className="text-2xl font-bold text-gray-900">{t('home.moreJobs.title')}</h2>
|
||||
<div className="flex justify-between items-center mb-8">
|
||||
<h2 className="text-3xl font-bold text-gray-900">{t('home.moreJobs.title')}</h2>
|
||||
<Link href="/jobs">
|
||||
<Button className="bg-primary hover:bg-primary/90 text-white rounded-md px-6 py-2">{t('home.moreJobs.viewAll')}</Button>
|
||||
<Button className="bg-primary hover:bg-primary/90 text-white rounded-lg px-10 py-4 font-bold text-lg min-w-[220px]">
|
||||
{t('home.moreJobs.viewAll')}
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{mockJobs.slice(0, 8)
|
||||
.map((job, index) => {
|
||||
const colors = [
|
||||
|
|
@ -360,35 +571,25 @@ export default function HomePage() {
|
|||
<ChevronRight className="w-5 h-5 text-gray-400 group-hover:text-gray-600 transition-colors flex-shrink-0 ml-2" />
|
||||
</div>
|
||||
|
||||
{/* Tags */}
|
||||
<div className="mb-4">
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
<span className="text-xs px-2 py-0.5 bg-gray-100 text-gray-700 rounded">
|
||||
{job.location}
|
||||
</span>
|
||||
<span className="text-xs px-2 py-0.5 bg-gray-100 text-gray-700 rounded">
|
||||
{job.type}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Rodapé com botões */}
|
||||
<div className="flex items-center gap-2 pt-3 border-t border-gray-100">
|
||||
<Link href={`/jobs/${job.id}`} className="flex-1">
|
||||
<Button size="sm" className="w-full bg-primary hover:bg-primary/90 text-white rounded-md font-medium text-xs h-8">
|
||||
Aplicar agora
|
||||
</Button>
|
||||
</Link>
|
||||
<button className="w-8 h-8 flex items-center justify-center border border-gray-300 rounded-md hover:bg-gray-50 transition-colors">
|
||||
<button className="flex-1 flex items-center justify-center gap-2 border border-gray-300 rounded-md hover:bg-gray-50 transition-colors h-9 px-3">
|
||||
<svg className="w-4 h-4 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z" />
|
||||
</svg>
|
||||
<span className="text-xs font-medium text-gray-700">Favoritar</span>
|
||||
</button>
|
||||
<Link href={`/jobs/${job.id}`} className="flex-1">
|
||||
<Button size="sm" className="w-full bg-primary hover:bg-primary/90 text-white rounded-md font-medium text-xs h-9">
|
||||
Aplicar agora
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</motion.div>
|
||||
)})}
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -399,27 +600,30 @@ export default function HomePage() {
|
|||
<div className="bg-primary rounded-2xl overflow-hidden shadow-lg relative">
|
||||
<div className="absolute inset-0 z-0">
|
||||
<Image
|
||||
src="/12.png"
|
||||
src="/18.png"
|
||||
alt="Background"
|
||||
fill
|
||||
className="object-cover object-right"
|
||||
quality={100}
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
<div className="grid lg:grid-cols-2 gap-8 items-center p-8 lg:p-12 relative z-10">
|
||||
{/* Text Content */}
|
||||
<div className="text-white">
|
||||
<div className="flex items-center gap-2 mb-6">
|
||||
<Users className="w-6 h-6" />
|
||||
<span className="font-medium text-sm">{t('home.cta.badge')}</span>
|
||||
<div className="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
|
||||
<span className="text-white font-bold text-lg">$</span>
|
||||
</div>
|
||||
<h2 className="text-3xl lg:text-4xl font-bold mb-4 leading-tight">
|
||||
<span className="font-medium text-base">{t('home.cta.badge')}</span>
|
||||
</div>
|
||||
<h2 className="text-3xl lg:text-4xl font-bold mb-4 leading-tight whitespace-nowrap">
|
||||
{t('home.cta.title')}
|
||||
</h2>
|
||||
<p className="mb-6 text-white/90 text-sm">
|
||||
<p className="mb-6 text-white/90 text-lg">
|
||||
{t('home.cta.subtitle')}
|
||||
</p>
|
||||
<Button size="lg" className="bg-white text-primary hover:bg-white/90 font-semibold px-8 rounded-md">
|
||||
<Button size="lg" className="bg-white text-primary hover:bg-white/90 font-bold px-12 py-7 text-xl rounded-lg">
|
||||
{t('home.cta.button')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -433,3 +637,13 @@ export default function HomePage() {
|
|||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function FilterIcon() {
|
||||
return (
|
||||
<svg width="44" height="44" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="w-11 h-11">
|
||||
<rect x="4" y="7" width="16" height="3" rx="1.5" fill="white" />
|
||||
<rect x="7" y="12" width="10" height="3" rx="1.5" fill="white" />
|
||||
<rect x="10" y="17" width="4" height="3" rx="1.5" fill="white" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export default function PublicarVagaPage() {
|
|||
|
||||
<main className="flex-1 flex">
|
||||
{/* Left Side - Brand Section */}
|
||||
<div className="hidden lg:flex lg:w-2/5 bg-[#f0932b] relative overflow-hidden">
|
||||
<div className="hidden lg:flex lg:w-2/5 bg-[#F0932B] relative overflow-hidden">
|
||||
<Image
|
||||
src="/6.png"
|
||||
alt="Background"
|
||||
|
|
@ -326,7 +326,7 @@ export default function PublicarVagaPage() {
|
|||
<div className="pt-4">
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full bg-[#f0932b] hover:bg-[#e8871e] text-white font-bold py-4 rounded-full text-lg transition-colors shadow-lg hover:shadow-xl"
|
||||
className="w-full bg-[#F0932B] hover:bg-[#d97d1a] text-white font-bold py-4 rounded-full text-lg transition-colors shadow-lg hover:shadow-xl"
|
||||
>
|
||||
ANUNCIAR VAGA GRÁTIS
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ export default function RegisterUserPage() {
|
|||
|
||||
<Button
|
||||
type="submit"
|
||||
className="w-full h-11 cursor-pointer bg-[#f0932b] hover:bg-[#e8871e]"
|
||||
className="w-full h-11 cursor-pointer bg-[#F0932B] hover:bg-[#d97d1a]"
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? "Criando conta..." : "Criar Conta"}
|
||||
|
|
|
|||
|
|
@ -12,14 +12,16 @@ export function Footer() {
|
|||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-8xl">
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
|
||||
<div>
|
||||
<h3 className="font-bold mb-4 text-gray-900">Informações</h3>
|
||||
<h3 className="font-bold mb-4 text-gray-900 text-lg">Informações</h3>
|
||||
<ul className="space-y-3">
|
||||
<li>
|
||||
<li className="flex items-center gap-2">
|
||||
<span className="w-1.5 h-1.5 bg-gray-400 rounded-full inline-block"></span>
|
||||
<Link href="/about" className="text-sm text-gray-600 hover:text-primary transition-colors">
|
||||
Sobre nós
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<li className="flex items-center gap-2">
|
||||
<span className="w-1.5 h-1.5 bg-gray-400 rounded-full inline-block"></span>
|
||||
<Link href="/contact" className="text-sm text-gray-600 hover:text-primary transition-colors">
|
||||
Contato
|
||||
</Link>
|
||||
|
|
@ -28,14 +30,16 @@ export function Footer() {
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="font-bold mb-4 text-gray-900">Para Candidatos</h3>
|
||||
<h3 className="font-bold mb-4 text-gray-900 text-lg">Para Candidatos</h3>
|
||||
<ul className="space-y-3">
|
||||
<li>
|
||||
<li className="flex items-center gap-2">
|
||||
<span className="w-1.5 h-1.5 bg-gray-400 rounded-full inline-block"></span>
|
||||
<Link href="/jobs" className="text-sm text-gray-600 hover:text-primary transition-colors">
|
||||
Buscar Vagas
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<li className="flex items-center gap-2">
|
||||
<span className="w-1.5 h-1.5 bg-gray-400 rounded-full inline-block"></span>
|
||||
<Link href="/register/user" className="text-sm text-gray-600 hover:text-primary transition-colors">
|
||||
Criar Conta
|
||||
</Link>
|
||||
|
|
@ -44,9 +48,10 @@ export function Footer() {
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="font-bold mb-4 text-gray-900">Para Empresas</h3>
|
||||
<h3 className="font-bold mb-4 text-gray-900 text-lg">Para Empresas</h3>
|
||||
<ul className="space-y-3">
|
||||
<li>
|
||||
<li className="flex items-center gap-2">
|
||||
<span className="w-1.5 h-1.5 bg-gray-400 rounded-full inline-block"></span>
|
||||
<Link href="/publicar-vaga" className="text-sm text-gray-600 hover:text-primary transition-colors">
|
||||
Publicar Vaga
|
||||
</Link>
|
||||
|
|
@ -55,7 +60,7 @@ export function Footer() {
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="font-bold mb-4 text-gray-900">Redes Sociais</h3>
|
||||
<h3 className="font-bold mb-4 text-gray-900 text-lg">Redes Sociais</h3>
|
||||
<div className="flex gap-3">
|
||||
<a href="#" className="w-10 h-10 rounded-lg border-2 border-gray-300 hover:bg-gray-50 text-[#1F2F40] flex items-center justify-center transition-colors">
|
||||
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
|
||||
|
|
|
|||
|
|
@ -20,7 +20,10 @@
|
|||
"about": "About",
|
||||
"contact": "Contact",
|
||||
"login": "Login",
|
||||
"register": "Register"
|
||||
"register": "Register",
|
||||
"language": "Language",
|
||||
"registerUser": "Register User",
|
||||
"registerCompany": "Register Company"
|
||||
},
|
||||
"about": {
|
||||
"hero": {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,10 @@
|
|||
"about": "Sobre",
|
||||
"contact": "Contacto",
|
||||
"login": "Ingresar",
|
||||
"register": "Registrarse"
|
||||
"register": "Registrarse",
|
||||
"language": "Idioma",
|
||||
"registerUser": "Registrar Usuario",
|
||||
"registerCompany": "Registrar Empresa"
|
||||
},
|
||||
"about": {
|
||||
"hero": {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,10 @@
|
|||
"about": "Sobre",
|
||||
"contact": "Contato",
|
||||
"login": "Entrar",
|
||||
"register": "Cadastrar"
|
||||
"register": "Cadastrar",
|
||||
"language": "Idioma",
|
||||
"registerUser": "Cadastrar Usuário",
|
||||
"registerCompany": "Cadastrar Empresa"
|
||||
},
|
||||
"about": {
|
||||
"hero": {
|
||||
|
|
@ -145,11 +148,10 @@
|
|||
},
|
||||
"home": {
|
||||
"hero": {
|
||||
"title": "Encontre o emprego certo, de forma simples",
|
||||
"subtitle": "Conectamos candidatos e empresas de forma rápida e direta",
|
||||
"searchJobs": "Procurar vagas",
|
||||
"imCompany": "Sou empresa",
|
||||
"postJob": "Postar vaga"
|
||||
"title": "Encontre a Vaga de TI",
|
||||
"titleLine2": "dos Seus Sonhos",
|
||||
"subtitle": "Conectamos você com as melhores empresas e techs.",
|
||||
"cta": "Buscar Vagas"
|
||||
},
|
||||
"featured": {
|
||||
"title": "Vagas em Destaque",
|
||||
|
|
@ -1226,7 +1228,7 @@
|
|||
},
|
||||
"home": {
|
||||
"hero": {
|
||||
"title": "Encontre a Vaga de TI.",
|
||||
"title": "Encontre a Vaga de TI",
|
||||
"titleLine2": "dos Seus Sonhos.",
|
||||
"subtitle": "Conectamos você com as melhores empresas e techs.",
|
||||
"cta": "Buscar Vagas"
|
||||
|
|
|
|||
Loading…
Reference in a new issue