Merge branch 'dev'

This commit is contained in:
NANDO9322 2026-01-22 23:20:06 -03:00
commit d8ba70ae01
49 changed files with 4352 additions and 662 deletions

View 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

View file

@ -121,6 +121,174 @@
"footer": {
"rights": "All rights reserved.",
"privacy": "Privacy",
"terms": "Terms of use"
"terms": "Terms of use",
"blog": "Blog",
"empresas": "Companies",
"login": "Login"
},
"contact": {
"title": "Contact Us",
"subtitle": "We're here to help you",
"getInTouch": "Get in Touch",
"name": "Name",
"email": "Email",
"subject": "Subject",
"message": "Message",
"send": "Send Message",
"sending": "Sending...",
"success": "Message sent successfully!",
"error": "Error sending message",
"faq": "Frequently Asked Questions",
"resources": "Useful Resources"
},
"about": {
"title": "About Us",
"hero": {
"title": "The evolution of work begins with people and their culture",
"subtitle": "Every day we contribute to transform the way we think about work so that it is consistent with the way we want to live."
},
"whatWeDo": {
"title": "What do we do?",
"p1": "GoHorse Jobs connects companies to qualified talents to transform projects into real results, combining expertise, agility and innovation in each hire.",
"p2": "Our platform facilitates the meeting between those looking for prepared professionals and those looking for opportunities aligned with their profile, objectives and work style.",
"p3": "At the same time, we help professionals evolve in their careers, gain autonomy, expand their networking and achieve opportunities that really make sense for their professional growth."
},
"hybrid": {
"title": "We are hybrid, itinerant and diverse",
"stats": "70% of the GoHorse Jobs team works remotely. 100% work with autonomy.",
"agile": "+ Agile",
"agileDesc": "Our flexible work culture allows us to quickly respond to the needs of the market and our users.",
"productive": "+ Productive",
"productiveDesc": "Autonomy and flexibility result in a more motivated, engaged and productive team in their projects."
},
"purpose": {
"title": "The purpose that unites us",
"desc": "We work continuously to transform the world of work by promoting autonomy, talent development and equal opportunities for all, from wherever they are.",
"quote": "We are an innovative organization that seeks to empower people at work, positively impacting personal, family and social life.",
"believe": "We believe there is a new way to work."
},
"values": {
"title": "Our values",
"subtitle": "The principles that guide our daily lives and shape our organizational culture"
},
"cta": {
"title": "Be part of the work transformation",
"subtitle": "Join thousands of companies and professionals who already trust GoHorse Jobs to build the future of work.",
"findJobs": "Find Jobs",
"postJob": "Post Job"
}
},
"blog": {
"title": "GoHorse Jobs Blog",
"subtitle": "Content about career, recruitment, technology and the future of work",
"searchPlaceholder": "Search articles...",
"categories": {
"all": "All",
"recruitment": "Recruitment",
"career": "Career",
"technology": "Technology",
"development": "Development",
"culture": "Culture",
"market": "Market"
},
"readMore": "Read more",
"showing": "Showing",
"of": "of",
"articles": "articles",
"newsletter": {
"title": "Want to receive our content first hand?",
"subtitle": "Subscribe to our newsletter and stay up to date with the latest news from the job market",
"placeholder": "Your best email",
"subscribe": "Subscribe Newsletter"
}
},
"postJob": {
"sidebar": {
"title": "Post job openings quickly and efficiently",
"benefit1": "One of the largest communities of professionals in the market",
"benefit2": "Platform with high visibility and daily access",
"benefit3": "Great movement of applications every day",
"benefit4": "New talents registering constantly"
},
"form": {
"title": "Post your job opening for FREE!",
"subtitle": "More than",
"registeredCVs": "50 thousand registered resumes",
"jobTitle": "Job position",
"jobTitlePlaceholder": "Ex: Full Stack Developer",
"companyName": "Company Name",
"companyNamePlaceholder": "Ex: Tech Company Ltd",
"cnpj": "Company ID",
"cnpjPlaceholder": "00.000.000/0000-00",
"employees": "Number of employees at unit",
"employeesPlaceholder": "Ex: 50",
"zipCode": "ZIP Code",
"zipCodePlaceholder": "00000-000",
"firstName": "First Name",
"firstNamePlaceholder": "Your first name",
"lastName": "Last Name",
"lastNamePlaceholder": "Your last name",
"email": "Your corporate email",
"emailPlaceholder": "your.email@company.com",
"phone": "Your phone",
"phonePlaceholder": "(00) 0000-0000",
"mobile": "Your mobile",
"mobilePlaceholder": "(00) 00000-0000",
"acceptTermsPrefix": "I have read and accept the",
"termsLink": "Legal Conditions",
"acceptTermsAnd": "and the",
"privacyLink": "Privacy Policy",
"acceptTermsSuffix": "of GoHorse Jobs.",
"acceptMarketing": "I authorize GoHorse Jobs to send commercial communications about products, services and events from its partners and collaborators.",
"submitButton": "POST JOB FOR FREE",
"candidateQuestion": "Are you a candidate?",
"candidateLink": "Sign up for free here!"
}
},
"registerUser": {
"title": "Create User Account",
"subtitle": "Fill in the details below to register",
"hero": {
"title": "Start your professional journey",
"subtitle": "Create your account and get access to the best tech job opportunities.",
"profile": "Create your complete professional profile",
"apply": "Apply to the best companies",
"track": "Track your applications in real time"
},
"form": {
"name": "Full Name",
"namePlaceholder": "Your full name",
"email": "Email",
"emailPlaceholder": "your@email.com",
"phone": "Phone",
"phonePlaceholder": "(00) 00000-0000",
"password": "Password",
"passwordPlaceholder": "Minimum 6 characters",
"confirmPassword": "Confirm Password",
"confirmPasswordPlaceholder": "Enter password again",
"acceptTerms": "I accept the terms of use and privacy policy",
"submit": "Create Account",
"submitting": "Creating account...",
"hasAccount": "Already have an account?",
"login": "Sign in",
"backHome": "Back to home"
}
},
"companies": {
"hero": {
"title": "Discover the Best Companies",
"subtitle": "Meet amazing companies that are hiring now"
},
"searchPlaceholder": "Search companies by name or industry...",
"filters": "Filters",
"companiesFound": "companies found",
"featured": "Featured Companies",
"allCompanies": "All Companies",
"featuredBadge": "Featured",
"jobs": "jobs",
"viewProfile": "View profile",
"viewMore": "View more",
"noCompanies": "No companies found",
"adjustFilters": "Try adjusting your search filters"
}
}

View file

@ -121,6 +121,174 @@
"footer": {
"rights": "Todos os direitos reservados.",
"privacy": "Privacidade",
"terms": "Termos de uso"
"terms": "Termos de uso",
"blog": "Blog",
"empresas": "Empresas",
"login": "Login"
},
"contact": {
"title": "Entre em Contato",
"subtitle": "Estamos aqui para ajudar você",
"getInTouch": "Fale Conosco",
"name": "Nome",
"email": "E-mail",
"subject": "Assunto",
"message": "Mensagem",
"send": "Enviar Mensagem",
"sending": "Enviando...",
"success": "Mensagem enviada com sucesso!",
"error": "Erro ao enviar mensagem",
"faq": "Perguntas Frequentes",
"resources": "Recursos Úteis"
},
"about": {
"title": "Sobre Nós",
"hero": {
"title": "A evolução do trabalho começa pelas pessoas e sua cultura",
"subtitle": "Todos os dias contribuímos para transformar a maneira como pensamos o trabalho para que seja coerente com a maneira como queremos viver."
},
"whatWeDo": {
"title": "O que fazemos?",
"p1": "O GoHorse Jobs conecta empresas a talentos qualificados para transformar projetos em resultados reais, unindo expertise, agilidade e inovação em cada contratação.",
"p2": "Nossa plataforma facilita o encontro entre quem busca profissionais preparados e quem deseja oportunidades alinhadas ao seu perfil, objetivos e estilo de trabalho.",
"p3": "Ao mesmo tempo, ajudamos profissionais a evoluírem em suas carreiras, ganharem autonomia, ampliarem seu networking e conquistarem oportunidades que realmente fazem sentido para seu crescimento profissional."
},
"hybrid": {
"title": "Somos híbridos, itinerantes e diversos",
"stats": "70% da equipe do GoHorse Jobs trabalha remotamente. 100% de trabalho com autonomia.",
"agile": "+ Ágil",
"agileDesc": "Nossa cultura de trabalho flexível nos permite responder rapidamente às necessidades do mercado e dos nossos usuários.",
"productive": "+ Produtiva",
"productiveDesc": "A autonomia e flexibilidade resultam em uma equipe mais motivada, engajada e produtiva em seus projetos."
},
"purpose": {
"title": "O propósito que nos une",
"desc": "Trabalhamos continuamente para transformar o mundo do trabalho promovendo a autonomia, o desenvolvimento de talentos e a igualdade de oportunidades para todos, de onde quer que seja.",
"quote": "Somos uma organização inovadora que busca potencializar as pessoas no trabalho, impactando positivamente na vida pessoal, familiar e social.",
"believe": "Acreditamos que há uma nova forma de trabalhar."
},
"values": {
"title": "Nossos valores",
"subtitle": "Os princípios que guiam nosso dia a dia e moldam nossa cultura organizacional"
},
"cta": {
"title": "Faça parte da transformação do trabalho",
"subtitle": "Junte-se a milhares de empresas e profissionais que já confiam no GoHorse Jobs para construir o futuro do trabalho.",
"findJobs": "Encontrar Vagas",
"postJob": "Publicar Vaga"
}
},
"blog": {
"title": "Blog GoHorse Jobs",
"subtitle": "Conteúdos sobre carreira, recrutamento, tecnologia e o futuro do trabalho",
"searchPlaceholder": "Buscar artigos...",
"categories": {
"all": "Todos",
"recruitment": "Recrutamento",
"career": "Carreira",
"technology": "Tecnologia",
"development": "Desenvolvimento",
"culture": "Cultura",
"market": "Mercado"
},
"readMore": "Ler mais",
"showing": "Mostrando",
"of": "de",
"articles": "artigos",
"newsletter": {
"title": "Quer receber nossos conteúdos em primeira mão?",
"subtitle": "Assine nossa newsletter e fique por dentro das novidades do mercado de trabalho",
"placeholder": "Seu melhor e-mail",
"subscribe": "Assinar Newsletter"
}
},
"postJob": {
"sidebar": {
"title": "Anuncie vagas de emprego de forma rápida e eficiente",
"benefit1": "Uma das maiores comunidades de profissionais do mercado",
"benefit2": "Plataforma com alta visibilidade e acesso diário",
"benefit3": "Grande movimentação de candidaturas todos os dias",
"benefit4": "Novos talentos se cadastrando constantemente"
},
"form": {
"title": "Anuncie a sua vaga de emprego GRÁTIS!",
"subtitle": "Mais de",
"registeredCVs": "50 mil currículos cadastrados",
"jobTitle": "Cargo da vaga",
"jobTitlePlaceholder": "Ex: Desenvolvedor Full Stack",
"companyName": "Nome da Empresa",
"companyNamePlaceholder": "Ex: Tech Company Ltda",
"cnpj": "CNPJ da Empresa",
"cnpjPlaceholder": "00.000.000/0000-00",
"employees": "Nº de funcionários da unidade",
"employeesPlaceholder": "Ex: 50",
"zipCode": "CEP",
"zipCodePlaceholder": "00000-000",
"firstName": "Nome",
"firstNamePlaceholder": "Seu nome",
"lastName": "Sobrenome",
"lastNamePlaceholder": "Seu sobrenome",
"email": "Seu e-mail corporativo",
"emailPlaceholder": "seu.email@empresa.com",
"phone": "Seu telefone fixo",
"phonePlaceholder": "(00) 0000-0000",
"mobile": "Seu celular",
"mobilePlaceholder": "(00) 00000-0000",
"acceptTermsPrefix": "Li e aceito as",
"termsLink": "Condições Legais",
"acceptTermsAnd": "e a",
"privacyLink": "Política de Privacidade",
"acceptTermsSuffix": "do GoHorse Jobs.",
"acceptMarketing": "Autorizo o GoHorse Jobs a enviar comunicações comerciais sobre produtos, serviços e eventos dos seus parceiros e colaboradores.",
"submitButton": "ANUNCIAR VAGA GRÁTIS",
"candidateQuestion": "Você é um candidato?",
"candidateLink": "Cadastre-se grátis aqui!"
}
},
"registerUser": {
"title": "Criar Conta de Usuário",
"subtitle": "Preencha os dados abaixo para se cadastrar",
"hero": {
"title": "Comece sua jornada profissional",
"subtitle": "Crie sua conta e tenha acesso às melhores oportunidades de emprego em tecnologia.",
"profile": "Crie seu perfil profissional completo",
"apply": "Candidate-se às melhores empresas",
"track": "Acompanhe suas candidaturas em tempo real"
},
"form": {
"name": "Nome Completo",
"namePlaceholder": "Seu nome completo",
"email": "E-mail",
"emailPlaceholder": "seu@email.com",
"phone": "Telefone",
"phonePlaceholder": "(00) 00000-0000",
"password": "Senha",
"passwordPlaceholder": "Mínimo 6 caracteres",
"confirmPassword": "Confirmar Senha",
"confirmPasswordPlaceholder": "Digite a senha novamente",
"acceptTerms": "Aceito os termos de uso e a política de privacidade",
"submit": "Criar Conta",
"submitting": "Criando conta...",
"hasAccount": "Já tem uma conta?",
"login": "Fazer login",
"backHome": "Voltar para o início"
}
},
"companies": {
"hero": {
"title": "Descubra as Melhores Empresas",
"subtitle": "Conheça empresas incríveis que estão contratando agora"
},
"searchPlaceholder": "Buscar empresas por nome ou setor...",
"filters": "Filtros",
"companiesFound": "empresas encontradas",
"featured": "Empresas em Destaque",
"allCompanies": "Todas as Empresas",
"featuredBadge": "Destaque",
"jobs": "vagas",
"viewProfile": "Ver perfil",
"viewMore": "Ver mais",
"noCompanies": "Nenhuma empresa encontrada",
"adjustFilters": "Tente ajustar seus filtros de busca"
}
}

View file

@ -16,6 +16,7 @@ const nextConfig: NextConfig = {
hostname: "**",
},
],
qualities: [25, 50, 75, 80, 90, 100],
},
};

BIN
frontend/public/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
frontend/public/10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 MiB

BIN
frontend/public/111.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
frontend/public/12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
frontend/public/16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
frontend/public/18.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

BIN
frontend/public/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
frontend/public/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

BIN
frontend/public/6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

BIN
frontend/public/9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

BIN
frontend/public/muie.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

BIN
frontend/public/optr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

BIN
frontend/public/optr1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

BIN
frontend/public/vaga.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

BIN
frontend/public/vaga1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

BIN
frontend/public/vaga2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

View file

@ -2,95 +2,256 @@
import { Navbar } from "@/components/navbar"
import { Footer } from "@/components/footer"
import { Card, CardContent } from "@/components/ui/card"
import { Target, Users, Zap, Shield } from "lucide-react"
import { Heart, Users, Rocket, Lightbulb, Target, Globe, Handshake, Smile } from "lucide-react"
import Image from "next/image"
import { useTranslation } from "@/lib/i18n"
export default function AboutPage() {
const { t } = useTranslation()
const values = [
{
icon: Target,
title: t("about.values.items.mission.title"),
description: t("about.values.items.mission.description"),
icon: Heart,
title: t('about.values.passion.title'),
description: t('about.values.passion.description')
},
{
icon: Users,
title: t("about.values.items.community.title"),
description: t("about.values.items.community.description"),
title: t('about.values.humility.title'),
description: t('about.values.humility.description')
},
{
icon: Zap,
title: t("about.values.items.efficiency.title"),
description: t("about.values.items.efficiency.description"),
icon: Rocket,
title: t('about.values.autonomy.title'),
description: t('about.values.autonomy.description')
},
{
icon: Shield,
title: t("about.values.items.trust.title"),
description: t("about.values.items.trust.description"),
icon: Lightbulb,
title: t('about.values.creativity.title'),
description: t('about.values.creativity.description')
},
{
icon: Target,
title: t('about.values.flexibility.title'),
description: t('about.values.flexibility.description')
},
{
icon: Handshake,
title: t('about.values.honesty.title'),
description: t('about.values.honesty.description')
},
{
icon: Smile,
title: t('about.values.respect.title'),
description: t('about.values.respect.description')
},
{
icon: Globe,
title: t('about.values.diversity.title'),
description: t('about.values.diversity.description')
}
]
return (
<div className="min-h-screen flex flex-col">
<div className="min-h-screen flex flex-col bg-white">
<Navbar />
<main className="flex-1">
{/* Hero Section */}
<section className="bg-muted/30 py-16 md:py-24">
<section className="relative bg-white py-20 md:py-32 overflow-hidden">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="max-w-3xl mx-auto text-center">
<h1 className="text-4xl md:text-5xl font-bold text-foreground mb-6 text-balance">
{t("about.hero.title")}
</h1>
<p className="text-lg text-muted-foreground leading-relaxed text-pretty">
{t("about.hero.subtitle")}
</p>
<div className="max-w-6xl mx-auto">
<div className="grid lg:grid-cols-2 gap-12 items-center">
<div>
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold text-gray-900 mb-6 leading-tight">
{t('about.hero.title')}
</h1>
<p className="text-xl text-gray-600 leading-relaxed">
{t('about.hero.subtitle')}
</p>
</div>
<div className="relative">
<div className="relative h-96 rounded-2xl overflow-hidden shadow-2xl bg-[#F0932B]">
<Image
src="/1.png"
alt="GoHorse Jobs Team"
fill
className="object-contain"
quality={100}
priority
/>
</div>
{/* Decorative elements */}
<div className="absolute -top-6 -right-6 w-32 h-32 bg-primary/20 rounded-full blur-3xl"></div>
<div className="absolute -bottom-6 -left-6 w-40 h-40 bg-orange-200/30 rounded-full blur-3xl"></div>
</div>
</div>
</div>
</div>
</section>
{/* Story Section */}
<section className="py-16 md:py-24">
{/* What We Do Section */}
<section className="py-20 md:py-28 bg-white">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="max-w-3xl mx-auto">
<h2 className="text-3xl font-bold text-foreground mb-6">{t("about.story.title")}</h2>
<div className="space-y-4 text-muted-foreground leading-relaxed">
<p>{t("about.story.paragraphs.first")}</p>
<p>{t("about.story.paragraphs.second")}</p>
<p>{t("about.story.paragraphs.third")}</p>
<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]">
<Image
src="/2.png"
alt="O que fazemos"
fill
className="object-contain"
quality={100}
/>
</div>
</div>
<div className="order-1 lg:order-2">
<h2 className="text-4xl md:text-5xl font-bold text-gray-900 mb-12">
{t('about.whatWeDo.title')}
</h2>
<div className="space-y-4 text-lg text-gray-700 leading-relaxed">
<p className="font-semibold text-xl">
{t('about.whatWeDo.paragraph1')}
</p>
<p>
{t('about.whatWeDo.paragraph2')}
</p>
<p>
{t('about.whatWeDo.paragraph3')}
</p>
</div>
</div>
</div>
</div>
</div>
</section>
{/* Hybrid Work Section */}
<section className="py-20 md:py-28 bg-white">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="max-w-6xl mx-auto text-center">
<h2 className="text-4xl md:text-5xl font-bold text-gray-900 mb-6">
{t('about.hybrid.title')}
</h2>
<p className="text-2xl text-gray-700 mb-12 max-w-3xl mx-auto">
<span className="font-bold text-primary">70% da equipe do GoHorse Jobs</span> trabalha remotamente.{" "}
<span className="font-bold">100% de trabalho com autonomia.</span>
</p>
<div className="grid md:grid-cols-2 gap-8 mt-16">
<div className="bg-white p-8 rounded-2xl shadow-lg">
<div className="w-16 h-16 bg-primary/10 rounded-full flex items-center justify-center mx-auto mb-6">
<Users className="w-8 h-8 text-primary" />
</div>
<h3 className="text-2xl font-bold text-gray-900 mb-4">{t('about.hybrid.agile.title')}</h3>
<p className="text-gray-600">
{t('about.hybrid.agile.description')}
</p>
</div>
<div className="bg-white p-8 rounded-2xl shadow-lg">
<div className="w-16 h-16 bg-primary/10 rounded-full flex items-center justify-center mx-auto mb-6">
<Rocket className="w-8 h-8 text-primary" />
</div>
<h3 className="text-2xl font-bold text-gray-900 mb-4">{t('about.hybrid.productive.title')}</h3>
<p className="text-gray-600">
{t('about.hybrid.productive.description')}
</p>
</div>
</div>
</div>
</div>
</section>
{/* Purpose Section */}
<section className="py-20 md:py-28 bg-white">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="max-w-4xl mx-auto text-center">
<h2 className="text-4xl md:text-5xl font-bold text-gray-900 mb-8">
{t('about.purpose.title')}
</h2>
<p className="text-2xl text-gray-700 leading-relaxed font-medium">
{t('about.purpose.description')}
</p>
<div className="mt-12 p-8 bg-white rounded-2xl shadow-xl">
<p className="text-xl text-gray-800 italic">
"{t('about.purpose.quote')}"
</p>
<p className="text-lg text-primary font-bold mt-6">
{t('about.purpose.belief')}
</p>
</div>
</div>
</div>
</section>
{/* Values Section */}
<section className="py-16 md:py-24 bg-muted/30">
<section className="py-20 md:py-28 bg-white">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="max-w-5xl mx-auto">
<h2 className="text-3xl font-bold text-foreground mb-12 text-center">
{t("about.values.title")}
<div className="max-w-6xl mx-auto">
<h2 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4 text-center">
{t('about.values.title')}
</h2>
<div className="grid md:grid-cols-2 gap-6">
<p className="text-xl text-gray-600 text-center mb-16 max-w-3xl mx-auto">
{t('about.values.subtitle')}
</p>
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8">
{values.map((value, index) => (
<Card key={index}>
<CardContent className="pt-6">
<div className="flex items-start gap-4">
<div className="p-3 rounded-lg bg-primary/10">
<value.icon className="h-6 w-6 text-primary" />
</div>
<div className="flex-1">
<h3 className="text-xl font-semibold mb-2">{value.title}</h3>
<p className="text-muted-foreground leading-relaxed">{value.description}</p>
</div>
</div>
</CardContent>
</Card>
<div
key={index}
className="group p-6 rounded-2xl bg-gray-50 hover:bg-primary/5 transition-all duration-300 hover:shadow-lg"
>
<div className="w-14 h-14 bg-primary/10 group-hover:bg-primary group-hover:scale-110 rounded-xl flex items-center justify-center mb-4 transition-all duration-300">
<value.icon className="w-7 h-7 text-primary group-hover:text-white transition-colors" />
</div>
<h3 className="text-xl font-bold text-gray-900 mb-3">
{value.title}
</h3>
<p className="text-gray-600 leading-relaxed text-sm">
{value.description}
</p>
</div>
))}
</div>
</div>
</div>
</section>
{/* CTA Section */}
<section className="relative py-20 md:py-28 bg-[#F0932B] overflow-hidden">
<Image
src="/4.png"
alt="Background"
fill
className="object-cover"
quality={100}
priority
/>
<div className="container mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
<div className="max-w-4xl mx-auto text-center text-white">
<h2 className="text-4xl md:text-5xl font-bold mb-6">
{t('about.cta.title')}
</h2>
<p className="text-xl mb-10 opacity-95">
{t('about.cta.subtitle')}
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<a
href="/jobs"
className="inline-block bg-white text-primary hover:bg-gray-100 font-bold px-8 py-4 rounded-full text-lg transition-all shadow-lg hover:shadow-xl"
>
{t('about.cta.findJobs')}
</a>
<a
href="/publicar-vaga"
className="inline-block bg-transparent border-2 border-white text-white hover:bg-white/10 font-bold px-8 py-4 rounded-full text-lg transition-all"
>
{t('about.cta.postJob')}
</a>
</div>
</div>
</div>
</section>
</main>
<Footer />

View file

@ -2,7 +2,6 @@ import { NextResponse } from 'next/server';
export const runtime = 'edge';
/**
* Runtime Configuration API
*

View file

@ -0,0 +1,484 @@
"use client"
import { useState } from "react"
import { Navbar } from "@/components/navbar"
import { Footer } from "@/components/footer"
import { Calendar, Clock, User, Share2, Facebook, Twitter, Linkedin, Link as LinkIcon, ArrowLeft, Tag } from "lucide-react"
import Image from "next/image"
import Link from "next/link"
import { useParams } from "next/navigation"
export const runtime = 'edge';
export default function BlogPostPage() {
const params = useParams()
const [copied, setCopied] = useState(false)
const copyLink = () => {
navigator.clipboard.writeText(window.location.href)
setCopied(true)
setTimeout(() => setCopied(false), 2000)
}
// Mapeamento de posts com suas respectivas imagens
const postsData: Record<string, any> = {
"como-se-destacar-entrevistas-ti": {
title: "Como se destacar em entrevistas de emprego na área de TI",
author: "Carolina Santos",
date: "15 Jan 2026",
readTime: "8 min",
category: "Entrevistas",
image: "https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=1200&q=80",
tags: ["Entrevistas", "Tecnologia", "Carreira", "Dicas"]
},
"linguagens-programacao-2026": {
title: "As 10 linguagens de programação mais procuradas em 2026",
author: "Roberto Silva",
date: "12 Jan 2026",
readTime: "10 min",
category: "Tecnologia",
image: "https://images.unsplash.com/photo-1542831371-29b0f74f9713?w=1200&q=80",
tags: ["Programação", "Tecnologia", "Mercado", "Linguagens"]
},
"salarios-desenvolvedores-brasil": {
title: "Guia completo de salários para desenvolvedores no Brasil",
author: "Mariana Costa",
date: "10 Jan 2026",
readTime: "12 min",
category: "Mercado de Trabalho",
image: "https://images.unsplash.com/photo-1554224155-8d04cb21cd6c?w=1200&q=80",
tags: ["Salários", "Desenvolvedores", "Brasil", "Carreira"]
},
"transicao-carreira-tech": {
title: "Transição de carreira para TI: Por onde começar?",
author: "Lucas Oliveira",
date: "8 Jan 2026",
readTime: "7 min",
category: "Carreira",
image: "https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=1200&q=80",
tags: ["Transição", "Carreira", "TI", "Iniciantes"]
},
"trabalho-remoto-produtividade": {
title: "Como manter a produtividade trabalhando remotamente",
author: "Ana Paula Mendes",
date: "5 Jan 2026",
readTime: "6 min",
category: "Dicas",
image: "https://images.unsplash.com/photo-1498050108023-c5249f4df085?w=1200&q=80",
tags: ["Home Office", "Produtividade", "Trabalho Remoto", "Dicas"]
},
"soft-skills-desenvolvedor": {
title: "Soft skills essenciais para desenvolvedores de sucesso",
author: "Felipe Rodrigues",
date: "2 Jan 2026",
readTime: "9 min",
category: "Desenvolvimento",
image: "https://images.unsplash.com/photo-1531482615713-2afd69097998?w=1200&q=80",
tags: ["Soft Skills", "Desenvolvimento", "Carreira", "Competências"]
},
"portfolio-desenvolvedor-destaque": {
title: "Como criar um portfólio que impressiona recrutadores",
author: "Juliana Ferreira",
date: "28 Dez 2025",
readTime: "11 min",
category: "Carreira",
image: "https://images.unsplash.com/photo-1467232004584-a241de8bcf5d?w=1200&q=80",
tags: ["Portfólio", "GitHub", "Projetos", "Carreira"]
},
"inteligencia-artificial-empregos": {
title: "IA e o futuro dos empregos em tecnologia",
author: "Pedro Almeida",
date: "25 Dez 2025",
readTime: "8 min",
category: "Tecnologia",
image: "https://images.unsplash.com/photo-1677442136019-21780ecad995?w=1200&q=80",
tags: ["IA", "Inteligência Artificial", "Futuro", "Tecnologia"]
},
"negociar-salario-tech": {
title: "Guia definitivo para negociar salário na área de TI",
author: "Rodrigo Martins",
date: "22 Dez 2025",
readTime: "10 min",
category: "Carreira",
image: "https://images.unsplash.com/photo-1454165804606-c3d57bc86b40?w=1200&q=80",
tags: ["Salário", "Negociação", "Carreira", "TI"]
}
}
const slug = params.slug as string
const postInfo = postsData[slug] || postsData["como-se-destacar-entrevistas-ti"]
// Post de exemplo baseado em conteúdo real de sites de emprego
const post = {
...postInfo,
content: `
<p class="text-lg font-semibold text-gray-900 mb-6">
O mercado de tecnologia está cada vez mais competitivo. Saber se destacar em uma entrevista pode ser o diferencial entre conseguir a vaga dos sonhos ou ficar para trás.
</p>
<p class="mb-4">
Em 2026, a maioria dos conflitos entre freelancers e clientes não são sobre a qualidade técnica do trabalho, mas sim sobre comunicação. Mal-entendidos, mudanças de escopo e expectativas pouco claras continuam sendo as principais causas de projetos frustrados.
</p>
<p class="mb-6">
Aprender a melhorar a comunicação com o cliente como freelancer em 2026 não reduz o atrito, como também permite trabalhar com mais clareza, cobrar preços melhores e construir relacionamentos de longo prazo dentro do ecossistema freelancer.
</p>
<h2 class="text-2xl font-bold text-gray-900 mt-8 mb-4">1. Prepare-se profundamente sobre a empresa</h2>
<p class="mb-4">
Antes de qualquer entrevista, dedique tempo para pesquisar a fundo sobre a empresa. Visite o site oficial, leia sobre a cultura organizacional, entenda os produtos e serviços oferecidos e acompanhe as notícias recentes.
</p>
<p class="mb-4">
Demonstrar conhecimento sobre a empresa não apenas impressiona os entrevistadores, mas também mostra seu genuíno interesse pela vaga e pela organização.
</p>
<div class="bg-orange-50 border-l-4 border-[#f0932b] p-6 my-8">
<p class="text-gray-800 italic">
💡 <strong>Dica profissional:</strong> Prepare perguntas inteligentes sobre a empresa. Isso demonstra proatividade e interesse real pela posição.
</p>
</div>
<h2 class="text-2xl font-bold text-gray-900 mt-8 mb-4">2. Domine as competências técnicas exigidas</h2>
<p class="mb-4">
Na área de TI, as habilidades técnicas são fundamentais. Certifique-se de que você domina as tecnologias e ferramentas mencionadas na descrição da vaga.
</p>
<ul class="list-disc pl-6 mb-6 space-y-2">
<li>Revise conceitos fundamentais da sua área de atuação</li>
<li>Pratique exercícios de código e desafios técnicos</li>
<li>Prepare-se para demonstrar projetos anteriores</li>
<li>Esteja atualizado sobre as últimas tendências tecnológicas</li>
</ul>
<h2 class="text-2xl font-bold text-gray-900 mt-8 mb-4">3. Desenvolva suas soft skills</h2>
<p class="mb-4">
Além das habilidades técnicas, as empresas valorizam cada vez mais as soft skills. Capacidades como comunicação, trabalho em equipe, resolução de problemas e adaptabilidade são essenciais.
</p>
<p class="mb-4">
Durante a entrevista, busque exemplos concretos de situações onde você demonstrou essas competências. Use a técnica STAR (Situação, Tarefa, Ação, Resultado) para estruturar suas respostas.
</p>
<h2 class="text-2xl font-bold text-gray-900 mt-8 mb-4">4. Cuide da sua apresentação pessoal</h2>
<p class="mb-4">
A primeira impressão conta muito. Vista-se de forma apropriada para a cultura da empresa - mesmo em entrevistas remotas, apresente-se de forma profissional.
</p>
<p class="mb-4">
Em entrevistas presenciais, chegue com 10-15 minutos de antecedência. Em entrevistas online, teste sua conexão, câmera e microfone antecipadamente.
</p>
<h2 class="text-2xl font-bold text-gray-900 mt-8 mb-4">5. Prepare respostas para perguntas comuns</h2>
<p class="mb-4">
Algumas perguntas são frequentes em entrevistas de TI. Prepare respostas autênticas e bem estruturadas para questões como:
</p>
<ul class="list-disc pl-6 mb-6 space-y-2">
<li>"Conte-me sobre você e sua trajetória profissional"</li>
<li>"Quais são seus pontos fortes e fracos?"</li>
<li>"Por que você quer trabalhar nesta empresa?"</li>
<li>"Onde você se vê daqui a 5 anos?"</li>
<li>"Descreva um desafio técnico que você superou"</li>
</ul>
<div class="bg-gray-100 p-6 rounded-lg my-8">
<h3 class="text-xl font-bold text-gray-900 mb-3">Checklist para entrevistas de TI:</h3>
<ul class="space-y-2">
<li class="flex items-start gap-2">
<span class="text-[#f0932b] mt-1"></span>
<span>Pesquisar a empresa e entender sua cultura</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#f0932b] mt-1"></span>
<span>Revisar tecnologias mencionadas na vaga</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#f0932b] mt-1"></span>
<span>Preparar portfólio de projetos</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#f0932b] mt-1"></span>
<span>Praticar perguntas comportamentais</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#f0932b] mt-1"></span>
<span>Testar equipamento (para entrevistas remotas)</span>
</li>
</ul>
</div>
<h2 class="text-2xl font-bold text-gray-900 mt-8 mb-4">6. Demonstre entusiasmo e motivação</h2>
<p class="mb-4">
Mostre que você está genuinamente interessado na oportunidade. Fale com energia sobre seus projetos, demonstre curiosidade sobre o trabalho e mantenha uma postura positiva durante toda a entrevista.
</p>
<p class="mb-4">
O entusiasmo é contagiante e pode fazer toda a diferença na decisão final dos recrutadores.
</p>
<h2 class="text-2xl font-bold text-gray-900 mt-8 mb-4">7. Faça um follow-up após a entrevista</h2>
<p class="mb-4">
Dentro de 24 horas após a entrevista, envie um e-mail de agradecimento. Reitere seu interesse pela vaga e destaque brevemente por que você seria um bom fit para a posição.
</p>
<p class="mb-6">
Esse pequeno gesto demonstra profissionalismo e pode deixar uma última impressão positiva nos recrutadores.
</p>
<h2 class="text-2xl font-bold text-gray-900 mt-8 mb-4">Conclusão</h2>
<p class="mb-4">
Se destacar em entrevistas de emprego na área de TI requer preparação, conhecimento técnico e desenvolvimento de habilidades interpessoais. Ao seguir essas dicas e investir tempo em sua preparação, você aumentará significativamente suas chances de sucesso.
</p>
<p class="mb-4">
Lembre-se: cada entrevista é uma oportunidade de aprendizado. Mesmo que não consiga a vaga, reflita sobre a experiência e identifique pontos de melhoria para as próximas oportunidades.
</p>
<p class="font-semibold text-gray-900">
Boa sorte em suas entrevistas! 🚀
</p>
`
}
const relatedPosts = [
{
id: 1,
title: "10 tendências de recrutamento para 2026",
category: "Recrutamento",
image: "/1.png",
slug: "tendencias-recrutamento-2026"
},
{
id: 2,
title: "Soft skills mais valorizadas pelas empresas",
category: "Desenvolvimento",
image: "/4.png",
slug: "soft-skills-2026"
},
{
id: 3,
title: "Como negociar salário: estratégias que funcionam",
category: "Carreira",
image: "/6.png",
slug: "negociar-salario"
}
]
return (
<div className="min-h-screen flex flex-col bg-white">
<Navbar />
<main className="flex-1">
{/* Breadcrumb */}
<div className="bg-gray-50 border-b border-gray-200">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-4">
<div className="flex items-center gap-2 text-sm">
<Link href="/" className="text-gray-600 hover:text-[#f0932b]">Início</Link>
<span className="text-gray-400">/</span>
<Link href="/blog" className="text-gray-600 hover:text-[#f0932b]">Blog</Link>
<span className="text-gray-400">/</span>
<span className="text-gray-900 font-medium">{post.category}</span>
</div>
</div>
</div>
{/* 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 flex flex-col items-start text-left">
{/* Back Button */}
<Link
href="/blog"
className="inline-flex items-center gap-2 text-[#f0932b] hover:underline mb-8"
>
<ArrowLeft className="w-4 h-4" />
Voltar para o blog
</Link>
{/* Category Badge */}
<div className="mb-4">
<span className="inline-block bg-[#f0932b] text-white px-4 py-1 rounded-full text-sm font-semibold">
{post.category}
</span>
</div>
{/* 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">
<div className="flex items-center gap-2">
<User className="w-5 h-5" />
<span>{post.author}</span>
</div>
<div className="flex items-center gap-2">
<Calendar className="w-5 h-5" />
<span>{post.date}</span>
</div>
<div className="flex items-center gap-2">
<Clock className="w-5 h-5" />
<span>{post.readTime} de leitura</span>
</div>
</div>
{/* Featured Image */}
<div className="relative h-96 rounded-2xl overflow-hidden mb-12 bg-[#f0932b]">
<Image
src={post.image}
alt={post.title}
fill
className="object-cover"
priority
/>
</div>
{/* Share Buttons */}
<div className="flex items-center gap-4 mb-12 pb-8 border-b border-gray-200">
<span className="text-gray-600 font-semibold">Compartilhar:</span>
<div className="flex gap-2">
<button className="w-10 h-10 rounded-full bg-blue-600 text-white flex items-center justify-center hover:bg-blue-700 transition-colors">
<Facebook className="w-5 h-5" />
</button>
<button className="w-10 h-10 rounded-full bg-sky-500 text-white flex items-center justify-center hover:bg-sky-600 transition-colors">
<Twitter className="w-5 h-5" />
</button>
<button className="w-10 h-10 rounded-full bg-blue-700 text-white flex items-center justify-center hover:bg-blue-800 transition-colors">
<Linkedin className="w-5 h-5" />
</button>
<button
onClick={copyLink}
className="w-10 h-10 rounded-full bg-gray-200 text-gray-700 flex items-center justify-center hover:bg-gray-300 transition-colors relative"
>
<LinkIcon className="w-5 h-5" />
{copied && (
<span className="absolute -top-10 left-1/2 transform -translate-x-1/2 bg-gray-900 text-white text-xs px-2 py-1 rounded whitespace-nowrap">
Link copiado!
</span>
)}
</button>
</div>
</div>
{/* Article Content */}
<div
className="prose prose-lg max-w-none prose-headings:text-gray-900 prose-p:text-gray-700 prose-a:text-[#f0932b] prose-strong:text-gray-900"
dangerouslySetInnerHTML={{ __html: post.content }}
/>
{/* Tags */}
<div className="mt-12 pt-8 border-t border-gray-200">
<div className="flex flex-wrap items-center gap-3">
<Tag className="w-5 h-5 text-gray-600" />
{post.tags.map((tag: string, index: number) => (
<span
key={index}
className="inline-block bg-gray-100 hover:bg-gray-200 text-gray-700 px-4 py-2 rounded-full text-sm cursor-pointer transition-colors"
>
{tag}
</span>
))}
</div>
</div>
{/* Author Bio */}
<div className="mt-12 p-8 bg-gray-50 rounded-2xl">
<div className="flex items-start gap-4">
<div className="w-20 h-20 rounded-full bg-[#f0932b] flex items-center justify-center text-white text-2xl font-bold flex-shrink-0">
{post.author.charAt(0)}
</div>
<div>
<h3 className="text-xl font-bold text-gray-900 mb-2">{post.author}</h3>
<p className="text-gray-600">
Especialista em carreira e recrutamento com mais de 10 anos de experiência ajudando profissionais a alcançarem seus objetivos no mercado de tecnologia.
</p>
</div>
</div>
</div>
</div>
</div>
</article>
{/* Related Posts */}
<section className="py-16 bg-gray-50">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="max-w-6xl mx-auto">
<h2 className="text-3xl font-bold text-gray-900 mb-8">Artigos Relacionados</h2>
<div className="grid md:grid-cols-3 gap-8">
{relatedPosts.map((relatedPost) => (
<Link
key={relatedPost.id}
href={`/blog/${relatedPost.slug}`}
className="group bg-white rounded-2xl overflow-hidden shadow-md hover:shadow-xl transition-all duration-300"
>
<div className="relative h-48 overflow-hidden bg-[#f0932b]">
<Image
src={relatedPost.image}
alt={relatedPost.title}
fill
className="object-cover group-hover:scale-110 transition-transform duration-300"
/>
<div className="absolute top-4 left-4">
<span className="bg-white text-[#f0932b] px-3 py-1 rounded-full text-xs font-bold">
{relatedPost.category}
</span>
</div>
</div>
<div className="p-6">
<h3 className="text-xl font-bold text-gray-900 group-hover:text-[#f0932b] transition-colors line-clamp-2">
{relatedPost.title}
</h3>
</div>
</Link>
))}
</div>
</div>
</div>
</section>
{/* Newsletter CTA */}
<section className="bg-[#f0932b] py-16">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="max-w-4xl mx-auto text-center text-white">
<h2 className="text-3xl md:text-4xl font-bold mb-4">
Gostou deste conteúdo?
</h2>
<p className="text-lg mb-8 opacity-95">
Receba mais artigos como este direto no seu e-mail
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center max-w-xl mx-auto">
<input
type="email"
placeholder="Seu melhor e-mail"
className="flex-1 px-6 py-4 rounded-full text-gray-900 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-all shadow-lg">
Assinar Newsletter
</button>
</div>
</div>
</div>
</section>
</main>
<Footer />
</div>
)
}

View file

@ -0,0 +1,399 @@
"use client"
import { Navbar } from "@/components/navbar"
import { Footer } from "@/components/footer"
import { Search, Calendar, Clock, ArrowRight, TrendingUp, Code, Briefcase, Users, Target, Lightbulb } from "lucide-react"
import Image from "next/image"
import Link from "next/link"
import { useState } from "react"
import { useTranslation } from "@/lib/i18n"
interface BlogPost {
id: string
slug: string
title: string
excerpt: string
category: string
date: string
readTime: string
image: string
author: {
name: string
avatar: string
}
featured?: boolean
}
export default function BlogPage() {
const { t } = useTranslation()
const [searchTerm, setSearchTerm] = useState("")
const [selectedCategory, setSelectedCategory] = useState("Todas")
const categories = [
"Todas",
"Carreira",
"Tecnologia",
"Entrevistas",
"Dicas",
"Mercado de Trabalho",
"Desenvolvimento"
]
const blogPosts: BlogPost[] = [
{
id: "1",
slug: "como-se-destacar-entrevistas-ti",
title: "Como se destacar em entrevistas de emprego na área de TI",
excerpt: "Dicas essenciais para profissionais de tecnologia que querem impressionar recrutadores e conquistar a vaga dos sonhos.",
category: "Entrevistas",
date: "15 de Janeiro, 2026",
readTime: "8 min",
image: "https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=800&q=80",
author: {
name: "Carolina Santos",
avatar: "/logohorse.png"
},
featured: true
},
{
id: "2",
slug: "linguagens-programacao-2026",
title: "As 10 linguagens de programação mais procuradas em 2026",
excerpt: "Descubra quais são as tecnologias mais valorizadas pelo mercado e como se preparar para as oportunidades futuras.",
category: "Tecnologia",
date: "12 de Janeiro, 2026",
readTime: "10 min",
image: "https://images.unsplash.com/photo-1542831371-29b0f74f9713?w=800&q=80",
author: {
name: "Roberto Silva",
avatar: "/logohorse.png"
},
featured: true
},
{
id: "3",
slug: "salarios-desenvolvedores-brasil",
title: "Guia completo de salários para desenvolvedores no Brasil",
excerpt: "Análise detalhada sobre faixas salariais, benefícios e tendências do mercado de tecnologia brasileiro.",
category: "Mercado de Trabalho",
date: "10 de Janeiro, 2026",
readTime: "12 min",
image: "https://images.unsplash.com/photo-1554224155-8d04cb21cd6c?w=800&q=80",
author: {
name: "Mariana Costa",
avatar: "/logohorse.png"
},
featured: true
},
{
id: "4",
slug: "transicao-carreira-tech",
title: "Transição de carreira para TI: Por onde começar?",
excerpt: "Um guia prático para profissionais que desejam migrar para a área de tecnologia, com dicas de cursos e certificações.",
category: "Carreira",
date: "8 de Janeiro, 2026",
readTime: "7 min",
image: "https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=800&q=80",
author: {
name: "Lucas Oliveira",
avatar: "/logohorse.png"
}
},
{
id: "5",
slug: "trabalho-remoto-produtividade",
title: "Como manter a produtividade trabalhando remotamente",
excerpt: "Estratégias comprovadas para equilibrar vida profissional e pessoal no modelo home office.",
category: "Dicas",
date: "5 de Janeiro, 2026",
readTime: "6 min",
image: "https://images.unsplash.com/photo-1498050108023-c5249f4df085?w=800&q=80",
author: {
name: "Ana Paula Mendes",
avatar: "/logohorse.png"
}
},
{
id: "6",
slug: "soft-skills-desenvolvedor",
title: "Soft skills essenciais para desenvolvedores de sucesso",
excerpt: "Além do código: as habilidades comportamentais que fazem a diferença na carreira tech.",
category: "Desenvolvimento",
date: "2 de Janeiro, 2026",
readTime: "9 min",
image: "https://images.unsplash.com/photo-1531482615713-2afd69097998?w=800&q=80",
author: {
name: "Felipe Rodrigues",
avatar: "/logohorse.png"
}
},
{
id: "7",
slug: "portfolio-desenvolvedor-destaque",
title: "Como criar um portfólio que impressiona recrutadores",
excerpt: "Aprenda a estruturar seus projetos de forma profissional e aumentar suas chances de contratação.",
category: "Carreira",
date: "28 de Dezembro, 2025",
readTime: "11 min",
image: "https://images.unsplash.com/photo-1467232004584-a241de8bcf5d?w=800&q=80",
author: {
name: "Juliana Ferreira",
avatar: "/logohorse.png"
}
},
{
id: "8",
slug: "inteligencia-artificial-empregos",
title: "IA e o futuro dos empregos em tecnologia",
excerpt: "Como a inteligência artificial está transformando o mercado de trabalho e criando novas oportunidades.",
category: "Tecnologia",
date: "25 de Dezembro, 2025",
readTime: "8 min",
image: "https://images.unsplash.com/photo-1677442136019-21780ecad995?w=800&q=80",
author: {
name: "Pedro Almeida",
avatar: "/logohorse.png"
}
},
{
id: "9",
slug: "negociar-salario-tech",
title: "Guia definitivo para negociar salário na área de TI",
excerpt: "Técnicas e estratégias para conseguir a melhor proposta salarial possível em sua próxima oportunidade.",
category: "Carreira",
date: "22 de Dezembro, 2025",
readTime: "10 min",
image: "https://images.unsplash.com/photo-1454165804606-c3d57bc86b40?w=800&q=80",
author: {
name: "Rodrigo Martins",
avatar: "/logohorse.png"
}
}
]
const filteredPosts = blogPosts.filter(post => {
const matchesSearch = post.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
post.excerpt.toLowerCase().includes(searchTerm.toLowerCase())
const matchesCategory = selectedCategory === "Todas" || post.category === selectedCategory
return matchesSearch && matchesCategory
})
const featuredPosts = blogPosts.filter(p => p.featured)
const regularPosts = filteredPosts.filter(p => !p.featured)
return (
<div className="min-h-screen flex flex-col bg-white">
<Navbar />
<main className="flex-1">
{/* Hero Section */}
<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>
<div className="container mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
<div className="max-w-4xl mx-auto text-center text-white">
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold mb-6">
{t('blog.title')}
</h1>
<p className="text-xl md:text-2xl mb-8 opacity-95">
{t('blog.subtitle')}
</p>
{/* Search Bar */}
<div className="max-w-2xl mx-auto bg-white rounded-full p-2 shadow-lg">
<div className="relative">
<Search className="absolute left-6 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5" />
<input
type="text"
placeholder={t('blog.searchPlaceholder')}
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"
/>
</div>
</div>
</div>
</div>
</section>
{/* Categories Filter */}
<section className="bg-white py-6 border-b border-gray-200 sticky top-16 z-20 shadow-sm">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex items-center gap-3 overflow-x-auto pb-2 scrollbar-hide">
{categories.map(category => (
<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'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`}
>
{category}
</button>
))}
</div>
</div>
</section>
{/* Featured Posts */}
{selectedCategory === "Todas" && (
<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]" />
<h2 className="text-3xl font-bold text-gray-900">Artigos em Destaque</h2>
</div>
<div className="grid md:grid-cols-3 gap-8">
{featuredPosts.map((post) => (
<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"
>
<div className="relative h-56 overflow-hidden">
<Image
src={post.image}
alt={post.title}
fill
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">
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">
{post.category}
</span>
</div>
<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">
{post.excerpt}
</p>
<div className="flex items-center justify-between pt-4 border-t border-gray-100">
<div className="flex items-center gap-3 text-sm text-gray-500">
<div className="flex items-center gap-1">
<Calendar className="w-4 h-4" />
<span>{post.date}</span>
</div>
<div className="flex items-center gap-1">
<Clock className="w-4 h-4" />
<span>{post.readTime}</span>
</div>
</div>
</div>
</div>
</Link>
))}
</div>
</div>
</section>
)}
{/* All Posts */}
<section className="py-16 bg-white">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex items-center justify-between mb-8">
<h2 className="text-3xl font-bold text-gray-900">
{selectedCategory === "Todas" ? "Todos os Artigos" : `Categoria: ${selectedCategory}`}
</h2>
<p className="text-gray-600">
<span className="font-semibold text-[#F0932B]">{filteredPosts.length}</span> artigos encontrados
</p>
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
{(selectedCategory === "Todas" ? regularPosts : filteredPosts).map((post) => (
<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]"
>
<div className="relative h-48 overflow-hidden">
<Image
src={post.image}
alt={post.title}
fill
className="object-cover group-hover:scale-105 transition-transform duration-300"
/>
</div>
<div className="p-6">
<div className="flex items-center gap-2 mb-3">
<span className="bg-gray-100 text-gray-700 px-3 py-1 rounded-full text-xs font-semibold">
{post.category}
</span>
</div>
<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">
{post.excerpt}
</p>
<div className="flex items-center justify-between pt-4 border-t border-gray-100">
<div className="flex items-center gap-2 text-xs text-gray-500">
<Clock className="w-3 h-3" />
<span>{post.readTime}</span>
</div>
<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>
</div>
</div>
</Link>
))}
</div>
{filteredPosts.length === 0 && (
<div className="text-center py-16">
<Search className="w-16 h-16 text-gray-300 mx-auto mb-4" />
<h3 className="text-xl font-semibold text-gray-900 mb-2">Nenhum artigo encontrado</h3>
<p className="text-gray-600">Tente ajustar sua busca ou filtros</p>
</div>
)}
</div>
</section>
{/* Newsletter CTA */}
<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" />
<h2 className="text-3xl md:text-4xl font-bold mb-4">
Fique por dentro das novidades
</h2>
<p className="text-lg mb-8 opacity-95">
Receba insights exclusivos sobre carreira, tecnologia e mercado de trabalho diretamente no seu e-mail
</p>
<div className="flex flex-col sm:flex-row gap-3 max-w-xl mx-auto">
<input
type="email"
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">
Assinar Newsletter
</button>
</div>
<p className="text-sm mt-4 opacity-75">
Sem spam. Cancele a qualquer momento.
</p>
</div>
</div>
</section>
</main>
<Footer />
</div>
)
}

View file

@ -0,0 +1,389 @@
"use client"
import { useState } from "react"
import { Navbar } from "@/components/navbar"
import { Footer } from "@/components/footer"
import { Search, MapPin, Users, Briefcase, Star, TrendingUp, Building2, Globe, Heart, Filter } from "lucide-react"
import Image from "next/image"
import Link from "next/link"
interface Company {
id: number
name: string
logo: string
industry: string
location: string
employees: string
openJobs: number
description: string
rating: number
featured: boolean
benefits: string[]
}
export default function CompaniesPage() {
const [searchTerm, setSearchTerm] = useState("")
const [selectedIndustry, setSelectedIndustry] = useState("Todas")
const [selectedSize, setSelectedSize] = useState("Todos")
const industries = [
"Todas",
"Tecnologia",
"Fintech",
"E-commerce",
"Saúde",
"Educação",
"Consultoria",
"Agronegócio"
]
const companySizes = [
"Todos",
"1-10 funcionários",
"11-50 funcionários",
"51-200 funcionários",
"201-500 funcionários",
"500+ funcionários"
]
const companies: Company[] = [
{
id: 1,
name: "TechCorp Brasil",
logo: "/logohorse.png",
industry: "Tecnologia",
location: "São Paulo, SP",
employees: "201-500 funcionários",
openJobs: 15,
description: "Líder em soluções de software e transformação digital, ajudando empresas a inovarem através da tecnologia.",
rating: 4.8,
featured: true,
benefits: ["Home Office", "Vale Refeição", "Plano de Saúde", "Gympass"]
},
{
id: 2,
name: "FinanceHub",
logo: "/logohorse.png",
industry: "Fintech",
location: "Rio de Janeiro, RJ",
employees: "51-200 funcionários",
openJobs: 8,
description: "Revolucionando o mercado financeiro com soluções inovadoras de pagamentos e investimentos.",
rating: 4.6,
featured: true,
benefits: ["PLR", "Stock Options", "Auxílio Educação", "Day Off Aniversário"]
},
{
id: 3,
name: "EduTech Solutions",
logo: "/logohorse.png",
industry: "Educação",
location: "Belo Horizonte, MG",
employees: "11-50 funcionários",
openJobs: 6,
description: "Plataforma de educação online que conecta alunos e professores através da tecnologia.",
rating: 4.7,
featured: false,
benefits: ["Horário Flexível", "Cursos Gratuitos", "Home Office", "Vale Transporte"]
},
{
id: 4,
name: "HealthTech Plus",
logo: "/logohorse.png",
industry: "Saúde",
location: "Porto Alegre, RS",
employees: "201-500 funcionários",
openJobs: 12,
description: "Inovação em saúde digital, oferecendo telemedicina e gestão de prontuários eletrônicos.",
rating: 4.9,
featured: true,
benefits: ["Plano Odontológico", "Seguro de Vida", "Assistência Psicológica", "Convênio Farmácia"]
},
{
id: 5,
name: "AgriSmart",
logo: "/logohorse.png",
industry: "Agronegócio",
location: "Cuiabá, MT",
employees: "51-200 funcionários",
openJobs: 5,
description: "Tecnologia aplicada ao agronegócio, otimizando processos e aumentando produtividade.",
rating: 4.5,
featured: false,
benefits: ["Participação nos Lucros", "Carro da Empresa", "Notebook", "Seguro de Vida"]
},
{
id: 6,
name: "ShopNext",
logo: "/logohorse.png",
industry: "E-commerce",
location: "São Paulo, SP",
employees: "500+ funcionários",
openJobs: 23,
description: "Marketplace líder em vendas online com logística integrada e experiência omnichannel.",
rating: 4.4,
featured: false,
benefits: ["Desconto em Produtos", "Vale Alimentação", "Plano de Carreira", "Previdência Privada"]
},
{
id: 7,
name: "ConsultPro",
logo: "/logohorse.png",
industry: "Consultoria",
location: "Brasília, DF",
employees: "11-50 funcionários",
openJobs: 4,
description: "Consultoria estratégica focada em transformação digital e otimização de processos.",
rating: 4.6,
featured: false,
benefits: ["Bônus por Projeto", "Trabalho Remoto", "Equipamentos Top", "Capacitação"]
},
{
id: 8,
name: "DataLabs",
logo: "/logohorse.png",
industry: "Tecnologia",
location: "Florianópolis, SC",
employees: "51-200 funcionários",
openJobs: 11,
description: "Especialistas em Big Data e Inteligência Artificial, transformando dados em insights.",
rating: 4.8,
featured: true,
benefits: ["Ambiente Descontraído", "Frutas e Snacks", "Games Room", "Pet Friendly"]
}
]
const filteredCompanies = companies.filter(company => {
const matchesSearch = company.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
company.description.toLowerCase().includes(searchTerm.toLowerCase())
const matchesIndustry = selectedIndustry === "Todas" || company.industry === selectedIndustry
const matchesSize = selectedSize === "Todos" || company.employees === selectedSize
return matchesSearch && matchesIndustry && matchesSize
})
const featuredCompanies = companies.filter(c => c.featured)
return (
<div className="min-h-screen flex flex-col bg-white">
<Navbar />
<main className="flex-1">
{/* Hero Section */}
<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>
<div className="container mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
<div className="max-w-4xl mx-auto text-center text-white">
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold mb-6">
Descubra as Melhores Empresas
</h1>
<p className="text-xl md:text-2xl mb-8 opacity-95">
Conheça empresas incríveis que estão contratando agora
</p>
{/* Search Bar */}
<div className="max-w-3xl mx-auto bg-white rounded-full p-2 shadow-lg">
<div className="relative">
<Search className="absolute left-6 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5" />
<input
type="text"
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"
/>
</div>
</div>
</div>
</div>
</section>
{/* Filters */}
<section className="bg-white py-8 border-b border-gray-200 sticky top-16 z-20 shadow-sm">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex flex-wrap gap-4 items-center">
<div className="flex items-center gap-2 text-gray-700">
<Filter className="w-5 h-5" />
<span className="font-semibold">Filtros:</span>
</div>
<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"
>
{industries.map(industry => (
<option key={industry} value={industry}>{industry}</option>
))}
</select>
<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"
>
{companySizes.map(size => (
<option key={size} value={size}>{size}</option>
))}
</select>
<div className="ml-auto text-sm text-gray-600">
<span className="font-semibold text-[#F0932B]">{filteredCompanies.length}</span> empresas encontradas
</div>
</div>
</div>
</section>
{/* Featured Companies */}
{featuredCompanies.length > 0 && (
<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]" />
<h2 className="text-3xl font-bold text-gray-900">Empresas em Destaque</h2>
</div>
<div className="grid md:grid-cols-2 gap-6">
{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"
>
<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>
<div className="flex-1">
<div className="flex items-start justify-between mb-2">
<h3 className="text-xl font-bold text-gray-900">{company.name}</h3>
<div className="flex items-center gap-1 bg-yellow-100 px-2 py-1 rounded-full">
<Star className="w-4 h-4 text-yellow-600 fill-yellow-600" />
<span className="text-sm font-semibold text-yellow-700">{company.rating}</span>
</div>
</div>
<div className="flex items-center gap-4 text-sm text-gray-600 mb-2">
<span className="flex items-center gap-1">
<MapPin className="w-4 h-4" />
{company.location}
</span>
<span className="flex items-center gap-1">
<Users className="w-4 h-4" />
{company.employees}
</span>
</div>
<span className="inline-block bg-[#F0932B]/10 text-[#F0932B] px-3 py-1 rounded-full text-xs font-semibold">
{company.industry}
</span>
</div>
</div>
<p className="text-gray-700 mb-4 line-clamp-2">{company.description}</p>
<div className="flex flex-wrap gap-2 mb-4">
{company.benefits.slice(0, 3).map((benefit, index) => (
<span key={index} className="text-xs bg-gray-100 text-gray-700 px-3 py-1 rounded-full">
{benefit}
</span>
))}
</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">
<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"
>
Ver perfil
</Link>
</div>
</div>
))}
</div>
</div>
</section>
)}
{/* All Companies Grid */}
<section className="py-16 bg-white">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<h2 className="text-3xl font-bold text-gray-900 mb-8">Todas as Empresas</h2>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{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]"
>
<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]" />
</div>
{company.featured && (
<span className="bg-yellow-100 text-yellow-700 text-xs font-semibold px-2 py-1 rounded-full">
Destaque
</span>
)}
</div>
<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">
{company.industry}
</span>
<div className="flex items-center gap-1">
<Star className="w-4 h-4 text-yellow-500 fill-yellow-500" />
<span className="text-sm font-semibold text-gray-700">{company.rating}</span>
</div>
</div>
<p className="text-gray-600 text-sm mb-4 line-clamp-2">{company.description}</p>
<div className="space-y-2 text-sm text-gray-600 mb-4">
<div className="flex items-center gap-2">
<MapPin className="w-4 h-4" />
<span>{company.location}</span>
</div>
<div className="flex items-center gap-2">
<Users className="w-4 h-4" />
<span>{company.employees}</span>
</div>
</div>
<div className="pt-4 border-t border-gray-100 flex items-center justify-between">
<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"
>
Ver mais
</Link>
</div>
</div>
))}
</div>
{filteredCompanies.length === 0 && (
<div className="text-center py-16">
<Building2 className="w-16 h-16 text-gray-300 mx-auto mb-4" />
<h3 className="text-xl font-semibold text-gray-900 mb-2">Nenhuma empresa encontrada</h3>
<p className="text-gray-600">Tente ajustar seus filtros de busca</p>
</div>
)}
</div>
</section>
</main>
<Footer />
</div>
)
}

View file

@ -1,182 +1,185 @@
"use client"
import type React from "react"
import { useState } from "react"
import { Navbar } from "@/components/navbar"
import { Footer } from "@/components/footer"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Label } from "@/components/ui/label"
import { Mail, MessageSquare, Phone, MapPin } from "lucide-react"
import { useTranslation } from "@/lib/i18n"
import { ChevronDown, Mail, Phone, HelpCircle, Briefcase, Users, FileText } from "lucide-react"
import { motion, AnimatePresence } from "framer-motion"
import Image from "next/image"
import Link from "next/link"
import { useTranslation } from "@/lib/i18n"
export default function ContactPage() {
const [submitted, setSubmitted] = useState(false)
const { t } = useTranslation()
const [ticketId, setTicketId] = useState<string | null>(null)
const [openFaq, setOpenFaq] = useState<number | null>(null)
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
// Simulate API call
setTimeout(() => {
const id = `TKT-${Math.floor(Math.random() * 9000) + 1000}`
setTicketId(id)
setSubmitted(true)
}, 1000)
}
const faqItems = [
{ question: t('contact.faq.items.q1.q'), answer: t('contact.faq.items.q1.a') },
{ question: t('contact.faq.items.q2.q'), answer: t('contact.faq.items.q2.a') },
{ question: t('contact.faq.items.q3.q'), answer: t('contact.faq.items.q3.a') },
{ question: t('contact.faq.items.q4.q'), answer: t('contact.faq.items.q4.a') },
{ question: t('contact.faq.items.q5.q'), answer: t('contact.faq.items.q5.a') },
{ question: t('contact.faq.items.q6.q'), answer: t('contact.faq.items.q6.a') },
{ question: t('contact.faq.items.q7.q'), answer: t('contact.faq.items.q7.a') },
{ question: t('contact.faq.items.q8.q'), answer: t('contact.faq.items.q8.a') }
]
return (
<div className="min-h-screen flex flex-col">
<div className="min-h-screen flex flex-col bg-gray-50">
<Navbar />
<main className="flex-1">
{/* Hero Section */}
<section className="bg-muted/30 py-16 md:py-24">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="max-w-3xl mx-auto text-center">
<h1 className="text-4xl md:text-5xl font-bold text-foreground mb-6 text-balance">
{t("contact.hero.title")}
</h1>
<p className="text-lg text-muted-foreground text-pretty">{t("contact.hero.subtitle")}</p>
<main className="flex-1 py-8 md:py-12">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-6xl">
{/* Header Section */}
<div className="bg-white rounded-2xl shadow-sm p-8 md:p-12 mb-8 text-center">
<div className="flex justify-center mb-6">
<div className="w-24 h-24 bg-gradient-to-br from-primary/10 to-primary/5 rounded-full flex items-center justify-center">
<Image
src="/logohorse.png"
alt="GoHorse Jobs"
width={64}
height={64}
className="object-contain"
/>
</div>
</div>
<h1 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
{t('contact.hero.title')}
</h1>
<p className="text-lg text-gray-600 max-w-2xl mx-auto">
{t('contact.hero.subtitle')}
</p>
</div>
</section>
{/* Contact Section */}
<section className="py-16 md:py-24">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="max-w-5xl mx-auto grid md:grid-cols-2 gap-12">
{/* Contact Form */}
<Card>
<CardHeader>
<CardTitle>{t("contact.form.title")}</CardTitle>
<CardDescription>{t("contact.form.description")}</CardDescription>
</CardHeader>
<CardContent>
{submitted ? (
<div className="text-center py-8 space-y-4 animate-in fade-in zoom-in">
<div className="mx-auto w-12 h-12 bg-green-100 text-green-600 rounded-full flex items-center justify-center">
<MessageSquare className="h-6 w-6" />
</div>
<h3 className="text-xl font-bold">{t("contact.form.actions.success")}</h3>
<p className="text-muted-foreground">
{t("contact.form.ticket_label", { defaultValue: "Your Ticket ID:" })}
</p>
<div className="text-2xl font-mono font-bold text-primary bg-primary/10 py-2 rounded">
{ticketId}
</div>
<p className="text-sm text-muted-foreground">
{t("contact.form.ticket_desc", { defaultValue: "Save this ID for future reference." })}
</p>
<Button variant="outline" onClick={() => { setSubmitted(false); setTicketId(null); }}>
{t("contact.form.send_another", { defaultValue: "Send another message" })}
</Button>
</div>
) : (
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="name">{t("contact.form.fields.name.label")}</Label>
<Input id="name" placeholder={t("contact.form.fields.name.placeholder")} required />
</div>
<div className="space-y-2">
<Label htmlFor="email">{t("contact.form.fields.email.label")}</Label>
<Input id="email" type="email" placeholder={t("contact.form.fields.email.placeholder")} required />
</div>
<div className="space-y-2">
<Label htmlFor="subject">{t("contact.form.fields.subject.label")}</Label>
<Input id="subject" placeholder={t("contact.form.fields.subject.placeholder")} required />
</div>
<div className="space-y-2">
<Label htmlFor="message">{t("contact.form.fields.message.label")}</Label>
<Textarea
id="message"
placeholder={t("contact.form.fields.message.placeholder")}
rows={5}
required
/>
</div>
<Button type="submit" className="w-full cursor-pointer" disabled={submitted}>
{t("contact.form.actions.submit")}
</Button>
</form>
)}
</CardContent>
</Card>
{/* Contact Info */}
<div className="space-y-8">
<div>
<h2 className="text-2xl font-bold mb-6">{t("contact.info.title")}</h2>
<div className="space-y-6">
<div className="flex items-start gap-4">
<div className="p-3 rounded-lg bg-primary/10">
<Mail className="h-5 w-5 text-primary" />
</div>
<div>
<h3 className="font-semibold mb-1">{t("contact.info.email.title")}</h3>
<p className="text-sm text-muted-foreground">hello@gohorsejobs.com</p>
</div>
</div>
<div className="flex items-start gap-4">
<div className="p-3 rounded-lg bg-primary/10">
<Phone className="h-5 w-5 text-primary" />
</div>
<div>
<h3 className="font-semibold mb-1">{t("contact.info.phone.title")}</h3>
<p className="text-sm text-muted-foreground">(11) 9999-9999</p>
</div>
</div>
<div className="flex items-start gap-4">
<div className="p-3 rounded-lg bg-primary/10">
<MapPin className="h-5 w-5 text-primary" />
</div>
<div>
<h3 className="font-semibold mb-1">{t("contact.info.address.title")}</h3>
<p className="text-sm text-muted-foreground">
1000 Paulista Ave
<br />
São Paulo, SP - 01310-100
</p>
</div>
</div>
<div className="flex items-start gap-4">
<div className="p-3 rounded-lg bg-primary/10">
<MessageSquare className="h-5 w-5 text-primary" />
</div>
<div>
<h3 className="font-semibold mb-1">{t("contact.info.support.title")}</h3>
<p className="text-sm text-muted-foreground">{t("contact.info.support.description")}</p>
</div>
</div>
<div className="grid lg:grid-cols-3 gap-8">
{/* FAQ Section - Main Column */}
<div className="lg:col-span-2">
<div className="bg-white rounded-2xl shadow-sm p-6 md:p-8">
<div className="flex items-center gap-3 mb-6">
<div className="w-10 h-10 bg-primary/10 rounded-lg flex items-center justify-center">
<HelpCircle className="w-5 h-5 text-primary" />
</div>
<h2 className="text-2xl font-bold text-gray-900">{t('contact.faq.title')}</h2>
</div>
<Card className="bg-muted/50">
<CardContent className="pt-6">
<h3 className="font-semibold mb-2">{t("contact.faq.title")}</h3>
<p className="text-sm text-muted-foreground mb-4">{t("contact.faq.description")}</p>
<Link href="/faq">
<Button variant="outline" className="w-full cursor-pointer bg-transparent">
{t("contact.faq.button")}
</Button>
</Link>
</CardContent>
</Card>
<div className="space-y-3">
{faqItems.map((item, index) => (
<div key={index} className="border border-gray-200 rounded-xl overflow-hidden">
<button
onClick={() => setOpenFaq(openFaq === index ? null : index)}
className="w-full px-6 py-4 flex items-center justify-between text-left hover:bg-gray-50 transition-colors"
>
<span className="font-medium text-gray-900 pr-4">{item.question}</span>
<motion.div
animate={{ rotate: openFaq === index ? 180 : 0 }}
transition={{ duration: 0.2 }}
>
<ChevronDown className="w-5 h-5 text-gray-500 flex-shrink-0" />
</motion.div>
</button>
<AnimatePresence>
{openFaq === index && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: "auto", opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.2 }}
className="overflow-hidden"
>
<div className="px-6 py-4 bg-gray-50 border-t border-gray-200">
<p className="text-gray-600 leading-relaxed">{item.answer}</p>
</div>
</motion.div>
)}
</AnimatePresence>
</div>
))}
</div>
</div>
</div>
{/* Sidebar - Resources */}
<div className="space-y-6">
{/* Contact Card */}
<div className="bg-white rounded-2xl shadow-sm p-6">
<h3 className="font-bold text-gray-900 mb-4 flex items-center gap-2">
<Mail className="w-5 h-5 text-primary" />
{t('contact.contactInfo.title')}
</h3>
<div className="space-y-4">
<div>
<p className="text-sm text-gray-500 mb-1">{t('contact.contactInfo.email')}</p>
<a href="mailto:hello@gohorsejobs.com" className="text-primary hover:underline font-medium">
hello@gohorsejobs.com
</a>
</div>
<div>
<p className="text-sm text-gray-500 mb-1">{t('contact.contactInfo.phone')}</p>
<a href="tel:+551199999999" className="text-primary hover:underline font-medium">
(11) 9999-9999
</a>
</div>
<div>
<p className="text-sm text-gray-500 mb-1">{t('contact.contactInfo.hours')}</p>
<p className="text-gray-700 text-sm">{t('contact.contactInfo.hoursValue')}</p>
</div>
</div>
</div>
{/* Quick Resources */}
<div className="bg-white rounded-2xl shadow-sm p-6">
<h3 className="font-bold text-gray-900 mb-4">{t('contact.resources.title')}</h3>
<div className="space-y-3">
<Link href="/jobs" className="flex items-center gap-3 p-3 rounded-lg hover:bg-gray-50 transition-colors group">
<div className="w-10 h-10 bg-primary/10 rounded-lg flex items-center justify-center group-hover:bg-primary/20 transition-colors">
<Briefcase className="w-5 h-5 text-primary" />
</div>
<div>
<p className="font-medium text-gray-900">{t('contact.resources.searchJobs')}</p>
<p className="text-xs text-gray-500">{t('contact.resources.searchJobsDesc')}</p>
</div>
</Link>
<Link href="/register/candidate" className="flex items-center gap-3 p-3 rounded-lg hover:bg-gray-50 transition-colors group">
<div className="w-10 h-10 bg-primary/10 rounded-lg flex items-center justify-center group-hover:bg-primary/20 transition-colors">
<Users className="w-5 h-5 text-primary" />
</div>
<div>
<p className="font-medium text-gray-900">{t('contact.resources.createAccount')}</p>
<p className="text-xs text-gray-500">{t('contact.resources.createAccountDesc')}</p>
</div>
</Link>
<Link href="/post-job" className="flex items-center gap-3 p-3 rounded-lg hover:bg-gray-50 transition-colors group">
<div className="w-10 h-10 bg-primary/10 rounded-lg flex items-center justify-center group-hover:bg-primary/20 transition-colors">
<FileText className="w-5 h-5 text-primary" />
</div>
<div>
<p className="font-medium text-gray-900">{t('contact.resources.postJob')}</p>
<p className="text-xs text-gray-500">{t('contact.resources.postJobDesc')}</p>
</div>
</Link>
</div>
</div>
{/* Help Center CTA */}
<div className="bg-gradient-to-br from-primary/10 to-primary/5 rounded-2xl p-6 border border-primary/20">
<h3 className="font-bold text-gray-900 mb-2">{t('contact.help.title')}</h3>
<p className="text-sm text-gray-600 mb-4">
{t('contact.help.description')}
</p>
<a
href="mailto:hello@gohorsejobs.com"
className="inline-block w-full text-center bg-primary hover:bg-primary/90 text-white font-medium px-4 py-2.5 rounded-lg transition-colors"
>
Enviar Mensagem
</a>
</div>
</div>
</div>
</section>
</div>
</main>
<Footer />

View file

@ -1,13 +1,12 @@
"use client";
export const runtime = 'edge';
import { useState, useEffect } from "react";
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();

View file

@ -1,5 +1,7 @@
"use client"
export const runtime = 'edge';
import { useState, useEffect } from "react"
import { useParams, useRouter } from "next/navigation"
import { Button } from "@/components/ui/button"
@ -12,9 +14,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()

View file

@ -1,5 +1,7 @@
"use client"
export const runtime = 'edge';
import { useState, useEffect } from "react"
import { useParams, useRouter } from "next/navigation"
import { Button } from "@/components/ui/button"
@ -27,9 +29,6 @@ import {
DialogTitle,
} from "@/components/ui/dialog"
export const runtime = 'edge';
export default function AdminTicketDetailsPage() {
const params = useParams()
const router = useRouter()

View file

@ -1,6 +1,12 @@
@import "tailwindcss";
@import "tw-animate-css";
body {
margin: 0;
padding: 0;
background-color: #f8f8f8;
}
@custom-variant dark (&:is(.dark *));
@theme inline {
@ -51,8 +57,8 @@
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.68 0.22 45); /* Orange Brand Color */
--primary-foreground: oklch(0.985 0 0);
--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);
--muted: oklch(0.97 0 0);
@ -62,20 +68,20 @@
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.68 0.22 45);
--chart-1: oklch(0.68 0.22 45);
--ring: oklch(0.705 0.188 57.5);
--chart-1: oklch(0.705 0.188 57.5);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.68 0.22 45);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.705 0.188 57.5);
--sidebar-primary-foreground: oklch(1 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.68 0.22 45);
--sidebar-ring: oklch(0.705 0.188 57.5);
}
.dark {
@ -85,8 +91,8 @@
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.205 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.68 0.22 45); /* Orange Brand Color */
--primary-foreground: oklch(0.985 0 0);
--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);
--muted: oklch(0.269 0 0);
@ -96,8 +102,8 @@
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.68 0.22 45);
--chart-1: oklch(0.68 0.22 45);
--ring: oklch(0.705 0.188 57.5);
--chart-1: oklch(0.705 0.188 57.5);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);

View file

@ -1,5 +1,7 @@
"use client";
export const runtime = 'edge';
import { useState, use, useEffect } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
@ -48,9 +50,12 @@ import { useTranslation } from "@/lib/i18n";
import { getCurrentUser } from "@/lib/auth";
<<<<<<< HEAD
export const runtime = 'edge';
=======
>>>>>>> dev
export default function JobApplicationPage({
params,
}: {

View file

@ -1,5 +1,7 @@
"use client";
export const runtime = 'edge';
import { use, useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import { Navbar } from "@/components/navbar";
@ -37,9 +39,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,
}: {

View file

@ -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')}

View file

@ -15,7 +15,7 @@ import { LoadingScreen } from "@/components/ui/loading-spinner"
import { AuthProvider } from "@/contexts/AuthContext"
export const metadata: Metadata = {
title: "GoHorseJobs - Find your next opportunity",
title: "GoHorseJobs",
description: "Connecting candidates and companies quickly and directly",
generator: "v0.app",
icons: {

View file

@ -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 } 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"
@ -20,8 +20,26 @@ import type { Job } from "@/lib/types"
export default function HomePage() {
const { t } = useTranslation()
const config = useConfig()
const [featuredJobs, setFeaturedJobs] = useState<Job[]>([])
const [featuredJobs, setFeaturedJobs] = useState<Job[]>(mockJobs.slice(0, 31))
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() {
@ -43,8 +61,8 @@ export default function HomePage() {
isFeatured: j.isFeatured
}))
console.log("[DEBUG] Fetching featured jobs from:", `${apiBase}/api/v1/jobs?featured=true&limit=6`)
const featuredRes = await fetch(`${apiBase}/api/v1/jobs?featured=true&limit=6`)
console.log("[DEBUG] Fetching featured jobs from:", `${apiBase}/api/v1/jobs?featured=true&limit=31`)
const featuredRes = await fetch(`${apiBase}/api/v1/jobs?featured=true&limit=31`)
console.log("[DEBUG] Featured response status:", featuredRes.status)
if (!featuredRes.ok) throw new Error("Failed to fetch featured jobs")
@ -54,14 +72,14 @@ export default function HomePage() {
const featuredList = featuredData.data ? mapJobs(featuredData.data) : []
console.log("[DEBUG] Mapped featured jobs:", featuredList.length, "jobs")
if (featuredList.length === 6) {
console.log("[DEBUG] Using featured jobs only (6 found)")
setFeaturedJobs(featuredList)
if (featuredList.length >= 24) {
console.log("[DEBUG] Using featured/API jobs")
setFeaturedJobs(featuredList.slice(0, 31))
return
}
console.log("[DEBUG] Fetching fallback jobs from:", `${apiBase}/api/v1/jobs?limit=6`)
const fallbackRes = await fetch(`${apiBase}/api/v1/jobs?limit=6`)
console.log("[DEBUG] Fetching fallback jobs from:", `${apiBase}/api/v1/jobs?limit=31`)
const fallbackRes = await fetch(`${apiBase}/api/v1/jobs?limit=31`)
console.log("[DEBUG] Fallback response status:", fallbackRes.status)
if (!fallbackRes.ok) throw new Error("Failed to fetch fallback jobs")
@ -71,23 +89,15 @@ export default function HomePage() {
const fallbackList = fallbackData.data ? mapJobs(fallbackData.data) : []
console.log("[DEBUG] Mapped fallback jobs:", fallbackList.length, "jobs")
const combined = [...featuredList, ...fallbackList].slice(0, 6)
const combined = [...featuredList, ...fallbackList].slice(0, 31)
console.log("[DEBUG] Combined jobs:", combined.length, "jobs")
if (combined.length === 6) {
console.log("[DEBUG] Using combined jobs (6)")
if (combined.length >= 24) {
console.log("[DEBUG] Using combined jobs")
setFeaturedJobs(combined)
} else if (combined.length > 0) {
console.log("[DEBUG] Using combined jobs (less than 6)")
setFeaturedJobs(combined)
} else {
console.log("[DEBUG] ⚠️ USING MOCK DATA - No API jobs found!")
setFeaturedJobs(mockJobs.slice(0, 6))
}
} catch (error) {
console.error("[DEBUG] ❌ Error fetching featured jobs:", error)
console.log("[DEBUG] ⚠️ USING MOCK DATA due to error")
setFeaturedJobs(mockJobs.slice(0, 6))
} finally {
setLoading(false)
}
@ -96,229 +106,351 @@ export default function HomePage() {
}, [])
return (
<div className="min-h-screen flex flex-col py-2.5">
<div className="min-h-screen flex flex-col">
<Navbar />
<main className="flex-1">
{/* Hero Section */}
<section className="container mx-auto px-4 sm:px-6 lg:px-8 py-20 lg:py-32">
<div className="grid lg:grid-cols-2 gap-12 items-center max-w-7xl mx-auto">
<div className="text-center lg:text-left">
<motion.h1
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
className="text-4xl sm:text-5xl lg:text-6xl font-bold text-balance mb-6"
>
{t('home.hero.title')}
</motion.h1>
<motion.p
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.1 }}
className="text-lg sm:text-xl text-muted-foreground text-balance mb-8 leading-relaxed"
>
{t('home.hero.subtitle')}
</motion.p>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.2 }}
className="flex flex-col sm:flex-row gap-4 justify-center lg:justify-start"
>
<Link href="/jobs">
<Button size="lg" className="w-full sm:w-auto">
{t('home.hero.searchJobs')}
<ArrowRight className="ml-2 h-4 w-4" />
</Button>
</Link>
<Link href="/post-job">
<Button size="lg" variant="outline" className="w-full sm:w-auto bg-transparent">
<Building2 className="mr-2 h-4 w-4" />
{t('home.hero.postJob')}
</Button>
</Link>
</motion.div>
<section className="bg-primary text-white relative overflow-hidden flex items-center min-h-[500px]">
<div className="absolute inset-0 z-0">
<Image
src="/10.png"
alt="Background"
fill
className="object-cover object-center"
quality={100}
priority
sizes="100vw"
/>
</div>
<div className="container mx-auto px-4 sm:px-6 lg:px-8 w-full relative z-10">
<div className="max-w-7xl mx-auto">
<div className="text-left max-w-2xl py-12">
<motion.h1
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
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>
<motion.p
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.1 }}
className="text-2xl mb-10 leading-relaxed text-white"
>
{t('home.hero.subtitle')}
</motion.p>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.2 }}
className="flex gap-4"
>
<Link href="/jobs">
<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>
</motion.div>
</div>
</div>
</div>
</section>
<motion.div
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.6, delay: 0.3 }}
className="relative hidden lg:block"
>
<div className="relative aspect-square rounded-2xl overflow-hidden bg-muted">
<Image
src="/minimalist-professional-workspace-with-laptop-and-.jpg"
alt="Professional Workspace"
fill
className="object-cover opacity-20"
priority
sizes="100vw"
{/* Search Bar Section */}
<section className="py-16">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-8xl">
<div className="mb-8">
<div className="mb-6 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" />
</svg>
<input
type="text"
placeholder={t('home.search.placeholder')}
className="w-full h-14 pl-12 pr-4 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent text-base bg-white shadow-sm"
/>
</div>
</motion.div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4 items-stretch">
{/* Contract Type - Static Expanded */}
<div className="bg-white border-2 border-gray-200 rounded-xl shadow-sm hover:border-primary/30 transition-colors relative h-full flex flex-col">
<div className="flex items-center justify-between w-full p-5 pb-2">
<span className="text-base font-bold text-gray-900">{t('home.search.contractType')}</span>
</div>
<div className="space-y-3 px-5 pb-5 pt-2 flex-1">
<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>
</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>{t('home.search.clt')}</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>{t('home.search.freelancer')}</span>
</label>
</div>
</div>
{/* Work Mode - Static Expanded */}
<div className="bg-white border-2 border-gray-200 rounded-xl shadow-sm hover:border-primary/30 transition-colors relative h-full flex flex-col">
<div className="flex items-center justify-between w-full p-5 pb-2">
<span className="text-base font-bold text-gray-900">{t('home.search.workMode')}</span>
</div>
<div className="space-y-3 px-5 pb-5 pt-2 flex-1">
<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>
</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>{t('home.search.presencial')}</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>{t('home.search.hybrid')}</span>
</label>
</div>
</div>
{/* Location - Static Expanded */}
<div className="bg-white border-2 border-gray-200 rounded-xl shadow-sm hover:border-primary/30 transition-colors relative h-full flex flex-col">
<div className="flex items-center justify-between w-full p-5 pb-2">
<span className="text-base font-bold text-gray-900">{t('home.search.location')}</span>
</div>
<div className="px-5 pb-5 pt-2 flex-1 flex items-center">
<input
type="text"
placeholder="Cidade e estado"
className="w-full border border-gray-300 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-primary h-12"
/>
</div>
</div>
{/* Salary - Static Expanded */}
<div className="bg-white border-2 border-gray-200 rounded-xl shadow-sm hover:border-primary/30 transition-colors relative h-full flex flex-col">
<div className="flex items-center justify-between w-full p-5 pb-2">
<span className="text-base font-bold text-gray-900">{t('home.search.salary')}</span>
</div>
<div className="px-5 pb-5 pt-2 flex-1 flex items-center">
<input
type="text"
placeholder="R$ 0,00"
className="w-full border border-gray-300 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-primary h-12"
/>
</div>
</div>
{/* Filter Button - Unified */}
<Button className="bg-primary hover:bg-primary/90 text-white h-full min-h-[200px] lg:min-h-0 rounded-xl font-bold text-3xl shadow-md hover:shadow-lg transition-all flex flex-col gap-3 items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={3} stroke="currentColor" className="size-12">
<path strokeLinecap="round" strokeLinejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z" />
</svg>
{t('home.search.filter')}
</Button>
</div>
</div>
</div>
</section>
{/* Featured Jobs */}
<section className="bg-muted/30 py-20">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-12">
<h2 className="text-3xl font-bold mb-4">{t('home.featured.title')}</h2>
<p className="text-muted-foreground text-base">{t('home.featured.subtitle')}</p>
<section className="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-3xl font-bold text-gray-900">{t('home.featuredJobs.title')}</h2>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 max-w-7xl mx-auto">
{featuredJobs.map((job, index) => (
<motion.div
key={job.id}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.1 }}
>
<JobCard job={job} />
</motion.div>
))}
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{(featuredJobs.length >= 4 ? featuredJobs.slice(0, 4) : mockJobs.slice(0, 4))
.map((job, index) => {
const dates = ['02/06', '05/06', '08/06', '11/06'];
const randomDate = dates[index % dates.length];
const levels = [t('home.levels.mid'), t('home.levels.junior'), t('home.levels.senior'), t('home.levels.mid')];
const level = levels[index % levels.length];
const statusLabels = [t('workMode.remote'), t('workMode.hybrid'), t('workMode.onsite'), t('workMode.remote')];
const statusLabel = statusLabels[index % statusLabels.length];
return (
<motion.div
key={job.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3 }}
>
<Card className="hover:shadow-lg transition-all border border-gray-200 rounded-2xl overflow-hidden bg-white h-full group cursor-pointer flex flex-col">
<div className="p-5 flex flex-col flex-1">
{/* Header */}
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-gray-50 rounded-lg flex items-center justify-center border border-gray-100">
<Building2 className="w-5 h-5 text-gray-700" />
</div>
<span className="text-sm font-bold text-gray-900 line-clamp-1">{job.company}</span>
</div>
<span className="text-[10px] px-2.5 py-1 bg-gray-900 text-white rounded-md font-bold uppercase tracking-wide">
{statusLabel}
</span>
</div>
<div className="text-center mt-12">
{/* Content */}
<div className="flex-1">
<h3 className="font-bold text-lg text-gray-900 mb-3 leading-tight line-clamp-2 pb-3 border-b border-gray-100">{job.title}</h3>
<div className="relative w-full h-32 mb-4 flex items-center justify-center bg-gray-50/50 rounded-lg border border-gray-50">
<Image
src="/111.png"
alt="Job Illustration"
fill
className="object-contain p-2"
quality={100}
/>
</div>
</div>
</div>
{/* Footer Section with Separator */}
<div className="px-5 pb-5 pt-0 mt-auto">
<div className="border-t border-gray-200 pt-4 mb-4">
<p className="text-sm text-gray-500 font-medium flex items-center gap-2">
<span className="text-gray-900 font-bold">{level}</span>
<span className="w-1 h-1 rounded-full bg-gray-300"></span>
{job.location}
</p>
</div>
<div className="flex gap-3">
<Button
variant="outline"
className="flex-1 border-gray-200 text-gray-700 hover:bg-gray-50 hover:text-gray-900 rounded-lg font-bold h-10 text-xs uppercase tracking-wide"
>
{t('home.featuredJobs.viewJob')}
</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-bold h-10 text-xs uppercase tracking-wide">
{t('home.featuredJobs.apply')}
</Button>
</Link>
</div>
</div>
</Card>
</motion.div>
)
})}
</div>
</div>
</section>
{/* More Jobs Section */}
<section className="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-3xl font-bold text-gray-900">{t('home.moreJobs.title')}</h2>
<Link href="/jobs">
<Button variant="outline" size="lg">
{t('home.featured.viewAll')}
<ArrowRight className="ml-2 h-4 w-4" />
<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>
</section>
{/* How it Works */}
<section className="py-20 relative overflow-hidden">
<div className="absolute inset-0 opacity-5">
<Image src="/abstract-minimal-geometric-pattern-light-gray.jpg" alt="" fill className="object-cover" />
</div>
<div className="container mx-auto px-4 sm:px-6 lg:px-8 relative">
<div className="text-center mb-16">
<h2 className="text-3xl font-bold mb-4">{t('home.howItWorks.title')}</h2>
<p className="text-muted-foreground text-base">{t('home.howItWorks.subtitle')}</p>
</div>
<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 = [
'bg-cyan-500', 'bg-blue-500', 'bg-indigo-500', 'bg-gray-500',
'bg-teal-500', 'bg-sky-500', 'bg-orange-500', 'bg-purple-500'
];
const bgColor = colors[index % colors.length];
const icons = ['💻', '🎨', '📊', '🚀', '⚙️', '🔧', '📱', '🎯'];
const icon = icons[index % icons.length];
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-5xl mx-auto">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
className="text-center"
>
<div className="w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-6 bg-background">
<Users className="text-primary w-9 h-9" />
</div>
<h3 className="text-xl font-semibold mb-3">{t('home.howItWorks.step1.title')}</h3>
<p className="text-muted-foreground leading-relaxed">{t('home.howItWorks.step1.description')}</p>
</motion.div>
return (
<motion.div
key={job.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3 }}
>
<Card className="hover:shadow-lg transition-all border border-gray-200 bg-white rounded-xl overflow-hidden group cursor-pointer h-full">
<CardContent className="p-5">
{/* Cabeçalho com logo e seta */}
<div className="flex items-start justify-between mb-4">
<div className="flex items-start gap-3 flex-1">
<div className={`w-12 h-12 ${bgColor} rounded-full flex items-center justify-center text-white text-xl flex-shrink-0`}>
{icon}
</div>
<div className="flex-1 min-w-0">
<h3 className="font-bold text-base text-gray-900 line-clamp-1 mb-1">{job.title}</h3>
<p className="text-sm text-gray-600 line-clamp-1">{job.company}</p>
</div>
</div>
<ChevronRight className="w-5 h-5 text-gray-400 group-hover:text-gray-600 transition-colors flex-shrink-0 ml-2" />
</div>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.1 }}
className="text-center"
>
<div className="w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-6 bg-background">
<FileText className="text-primary w-9 h-9" />
</div>
<h3 className="text-xl font-semibold mb-3">{t('home.howItWorks.step2.title')}</h3>
<p className="text-muted-foreground leading-relaxed">{t('home.howItWorks.step2.description')}</p>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.2 }}
className="text-center"
>
<div className="w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-6 bg-background">
<CheckCircle className="text-primary h-9 w-9" />
</div>
<h3 className="text-xl font-semibold mb-3">{t('home.howItWorks.step3.title')}</h3>
<p className="text-muted-foreground leading-relaxed">{t('home.howItWorks.step3.description')}</p>
</motion.div>
</div>
</div>
</section>
{/* Testimonials */}
<section className="bg-muted/30 py-20 border-0">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-12">
<h2 className="text-3xl font-bold mb-4">{t('home.testimonials.title')}</h2>
<p className="text-muted-foreground text-base">{t('home.testimonials.subtitle')}</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-6xl mx-auto">
{mockTestimonials.map((testimonial, index) => (
<motion.div
key={testimonial.id}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.1 }}
>
<Card>
<CardContent className="pt-6">
<div className="flex items-center gap-4 mb-4">
<div>
<p className="font-semibold">{testimonial.name}</p>
<p className="text-sm text-muted-foreground">{testimonial.role}</p>
</div>
</div>
<p className="text-muted-foreground leading-relaxed text-pretty">{testimonial.content}</p>
</CardContent>
</Card>
</motion.div>
))}
{/* Rodapé com botões */}
<div className="pt-4 mt-4 border-t border-gray-200">
<div className="flex gap-3">
<Button
variant="outline"
className="flex-1 border-gray-200 text-gray-700 hover:bg-gray-50 hover:text-gray-900 rounded-lg font-bold h-9 text-xs uppercase tracking-wide"
>
{t('home.featuredJobs.viewJob')}
</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-bold h-9 text-xs uppercase tracking-wide">
{t('home.featuredJobs.apply')}
</Button>
</Link>
</div>
</div>
</CardContent>
</Card>
</motion.div>
)
})}
</div>
</div>
</section>
{/* CTA Section */}
<section className="py-20">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<Card className="overflow-hidden bg-primary">
<div className="grid lg:grid-cols-2 gap-0">
<section className="py-12">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-8xl">
<div className="bg-gray-900 rounded-2xl overflow-hidden shadow-lg relative min-h-[500px] flex items-center">
{/* Image Layer: Single Image with Seamless Gradient Overlay */}
<div className="absolute inset-y-0 right-0 w-full md:w-3/4 z-0">
<Image
src="/muie.jpeg"
alt="Woman with Notebook"
fill
className="object-contain object-right"
quality={100}
priority
/>
{/*
Seamless Blend Gradient:
Starts solid gray-900 (matching, container) on left.
Fades gradually to transparent on right.
This "dyes" the dark background of the photo to match the container.
*/}
<div className="absolute inset-0 bg-gradient-to-r from-gray-900 from-20% via-gray-900/80 via-50% to-transparent to-100%" />
</div>
<div className="grid lg:grid-cols-2 gap-8 items-center p-8 lg:p-12 relative z-10">
{/* Text Content */}
<CardContent className="py-16 px-8 lg:px-12 flex flex-col justify-center bg-primary text-primary-foreground">
<h2 className="text-3xl lg:text-4xl font-bold mb-4 text-balance">{t('home.cta.title')}</h2>
<p className="mb-8 text-primary-foreground/90 text-balance leading-relaxed text-base">
<div className="text-white max-w-lg">
<h2 className="text-3xl lg:text-4xl font-bold mb-4 leading-tight">
{t('home.cta.title')}
</h2>
<p className="mb-6 text-white/90 text-lg">
{t('home.cta.subtitle')}
</p>
<div>
<Link href="/register/candidate">
<Button size="lg" variant="secondary">
{t('home.cta.button')}
<ArrowRight className="ml-2 h-4 w-4" />
</Button>
</Link>
</div>
</CardContent>
{/* Image */}
<div className="relative h-64 lg:h-auto min-h-[500px]">
<Image
src="/professional-person-smiling-at-laptop-optimistic.jpg"
alt="Professional smiling at laptop"
fill
className="object-cover opacity-10"
sizes="100vw"
/>
<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>
</div>
</Card>
</div>
</div>
</section>
</main>
@ -327,3 +459,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>
);
}

View file

@ -0,0 +1,357 @@
"use client"
import { useState } from "react"
import { Navbar } from "@/components/navbar"
import { Footer } from "@/components/footer"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"
import { Label } from "@/components/ui/label"
import { Check, Briefcase, Users, TrendingUp, Building2 } from "lucide-react"
import Image from "next/image"
import Link from "next/link"
export default function PublicarVagaPage() {
const [formData, setFormData] = useState({
cargoVaga: "",
nomeEmpresa: "",
cnpj: "",
numeroFuncionarios: "",
cep: "",
nome: "",
sobrenome: "",
email: "",
telefone: "",
celular: ""
})
const [acceptTerms, setAcceptTerms] = useState(false)
const [acceptMarketing, setAcceptMarketing] = useState(false)
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
console.log("Form submitted:", formData)
}
const handleInputChange = (field: string, value: string) => {
setFormData(prev => ({ ...prev, [field]: value }))
}
return (
<div className="min-h-screen flex flex-col">
<Navbar />
<main className="flex-1 flex">
{/* Left Side - Brand Section */}
<div className="hidden lg:flex lg:w-2/5 bg-[#F0932B] relative overflow-hidden">
<Image
src="/6.png"
alt="Background"
fill
className="object-cover"
quality={100}
priority
/>
{/* Background Pattern */}
<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.1)_0%,transparent_50%)]"></div>
</div>
<div className="relative z-10 flex flex-col justify-between p-12 text-white">
{/* Top Section */}
<div>
<h2 className="text-4xl md:text-5xl font-bold mb-6 leading-tight">
Anuncie vagas de emprego<br />
de forma rápida e eficiente
</h2>
{/* Stats */}
<div className="space-y-4 mb-8">
<div className="flex items-start gap-3">
<div className="mt-1">
<Check className="w-5 h-5" />
</div>
<div>
<p className="font-semibold">Uma das maiores comunidades de profissionais do mercado</p>
</div>
</div>
<div className="flex items-start gap-3">
<div className="mt-1">
<Check className="w-5 h-5" />
</div>
<div>
<p className="font-semibold">Plataforma com alta visibilidade e acesso diário</p>
</div>
</div>
<div className="flex items-start gap-3">
<div className="mt-1">
<Check className="w-5 h-5" />
</div>
<div>
<p className="font-semibold">Grande movimentação de candidaturas todos os dias</p>
</div>
</div>
<div className="flex items-start gap-3">
<div className="mt-1">
<Check className="w-5 h-5" />
</div>
<div>
<p className="font-semibold">Novos talentos se cadastrando constantemente</p>
</div>
</div>
</div>
</div>
</div>
</div>
{/* Right Side - Form Section */}
<div className="flex-1 bg-gray-50 overflow-y-auto">
<div className="max-w-3xl mx-auto py-12 px-6 md:px-12">
{/* Header */}
<div className="text-center mb-8">
<h1 className="text-3xl md:text-4xl font-bold text-gray-900 mb-3">
Anuncie a sua vaga de emprego GRÁTIS!
</h1>
<p className="text-gray-600">
Mais de <span className="font-semibold text-primary">50 mil currículos cadastrados</span>
</p>
</div>
{/* Form */}
<form onSubmit={handleSubmit} className="space-y-5">
{/* Row 1 */}
<div className="grid md:grid-cols-2 gap-4">
<div>
<Label htmlFor="cargoVaga" className="text-gray-700 mb-1.5 block text-sm">
Cargo da vaga
</Label>
<Input
id="cargoVaga"
placeholder="Ex: Desenvolvedor Full Stack"
value={formData.cargoVaga}
onChange={(e) => handleInputChange("cargoVaga", e.target.value)}
className="h-11 bg-white border-gray-300"
required
/>
</div>
<div>
<Label htmlFor="nomeEmpresa" className="text-gray-700 mb-1.5 block text-sm">
Nome da Empresa
</Label>
<Input
id="nomeEmpresa"
placeholder="Ex: Tech Company Ltda"
value={formData.nomeEmpresa}
onChange={(e) => handleInputChange("nomeEmpresa", e.target.value)}
className="h-11 bg-white border-gray-300"
required
/>
</div>
</div>
{/* Row 2 */}
<div className="grid md:grid-cols-3 gap-4">
<div>
<Label htmlFor="cnpj" className="text-gray-700 mb-1.5 block text-sm">
CNPJ da Empresa
</Label>
<Input
id="cnpj"
placeholder="00.000.000/0000-00"
value={formData.cnpj}
onChange={(e) => handleInputChange("cnpj", e.target.value)}
className="h-11 bg-white border-gray-300"
required
/>
</div>
<div>
<Label htmlFor="numeroFuncionarios" className="text-gray-700 mb-1.5 block text-sm">
de funcionários da unidade
</Label>
<Input
id="numeroFuncionarios"
placeholder="Ex: 50"
type="number"
value={formData.numeroFuncionarios}
onChange={(e) => handleInputChange("numeroFuncionarios", e.target.value)}
className="h-11 bg-white border-gray-300"
required
/>
</div>
<div>
<Label htmlFor="cep" className="text-gray-700 mb-1.5 block text-sm">
CEP
</Label>
<div className="flex gap-2">
<Input
id="cep"
placeholder="00000-000"
value={formData.cep}
onChange={(e) => handleInputChange("cep", e.target.value)}
className="h-11 bg-white border-gray-300"
required
/>
<button
type="button"
className="px-4 h-11 bg-gray-200 hover:bg-gray-300 rounded-md transition-colors flex-shrink-0"
>
<svg className="w-5 h-5 text-gray-600" 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" />
</svg>
</button>
</div>
</div>
</div>
{/* Row 3 */}
<div className="grid md:grid-cols-2 gap-4">
<div>
<Label htmlFor="nome" className="text-gray-700 mb-1.5 block text-sm">
Nome
</Label>
<Input
id="nome"
placeholder="Seu nome"
value={formData.nome}
onChange={(e) => handleInputChange("nome", e.target.value)}
className="h-11 bg-white border-gray-300"
required
/>
</div>
<div>
<Label htmlFor="sobrenome" className="text-gray-700 mb-1.5 block text-sm">
Sobrenome
</Label>
<Input
id="sobrenome"
placeholder="Seu sobrenome"
value={formData.sobrenome}
onChange={(e) => handleInputChange("sobrenome", e.target.value)}
className="h-11 bg-white border-gray-300"
required
/>
</div>
</div>
{/* Row 4 */}
<div>
<Label htmlFor="email" className="text-gray-700 mb-1.5 block text-sm">
Seu e-mail corporativo
</Label>
<Input
id="email"
type="email"
placeholder="seu.email@empresa.com"
value={formData.email}
onChange={(e) => handleInputChange("email", e.target.value)}
className="h-11 bg-white border-gray-300"
required
/>
</div>
{/* Row 5 */}
<div className="grid md:grid-cols-2 gap-4">
<div>
<Label htmlFor="telefone" className="text-gray-700 mb-1.5 block text-sm">
Seu telefone fixo
</Label>
<Input
id="telefone"
placeholder="(00) 0000-0000"
value={formData.telefone}
onChange={(e) => handleInputChange("telefone", e.target.value)}
className="h-11 bg-white border-gray-300"
/>
</div>
<div>
<Label htmlFor="celular" className="text-gray-700 mb-1.5 block text-sm">
Seu celular
</Label>
<Input
id="celular"
placeholder="(00) 00000-0000"
value={formData.celular}
onChange={(e) => handleInputChange("celular", e.target.value)}
className="h-11 bg-white border-gray-300"
required
/>
</div>
</div>
{/* Checkboxes */}
<div className="space-y-3 pt-2">
<label className="flex items-start gap-3 cursor-pointer group">
<input
type="checkbox"
checked={acceptTerms}
onChange={(e) => setAcceptTerms(e.target.checked)}
className="mt-1 w-4 h-4 rounded border-gray-300 text-primary focus:ring-primary cursor-pointer"
required
/>
<span className="text-sm text-gray-700 leading-relaxed">
Li e aceito as{" "}
<Link href="/terms" className="text-primary hover:underline font-medium">
Condições Legais
</Link>{" "}
e a{" "}
<Link href="/privacy" className="text-primary hover:underline font-medium">
Política de Privacidade
</Link>{" "}
do GoHorse Jobs.
</span>
</label>
<label className="flex items-start gap-3 cursor-pointer group">
<input
type="checkbox"
checked={acceptMarketing}
onChange={(e) => setAcceptMarketing(e.target.checked)}
className="mt-1 w-4 h-4 rounded border-gray-300 text-primary focus:ring-primary cursor-pointer"
/>
<span className="text-sm text-gray-700 leading-relaxed">
Autorizo o GoHorse Jobs a enviar comunicações comerciais sobre produtos, serviços e eventos dos seus parceiros e colaboradores.
</span>
</label>
</div>
{/* Submit Button */}
<div className="pt-4">
<button
type="submit"
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>
</div>
{/* Bottom Link */}
<div className="text-center pt-4">
<p className="text-sm text-gray-600">
Você é um candidato?{" "}
<Link href="/register/user" className="text-primary hover:underline font-medium">
Cadastre-se grátis aqui!
</Link>
</p>
</div>
</form>
{/* Footer Note */}
<div className="text-center mt-8 pt-6 border-t border-gray-200">
<p className="text-xs text-gray-500">
© GoHorse Jobs Brasil. Todos os direitos reservados.
</p>
</div>
</div>
</div>
</main>
</div>
)
}

View file

@ -137,7 +137,7 @@ export default function PublicPostJobPage() {
>
<div className="flex items-center justify-center gap-3 mb-8">
<Image
src="/logohorse.png"
src="/logohorse1.png"
alt="GoHorse Jobs"
width={80}
height={80}

View file

@ -0,0 +1,362 @@
"use client";
import { useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import Image from "next/image";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Checkbox } from "@/components/ui/checkbox";
import {
Briefcase,
AlertCircle,
Eye,
EyeOff,
User as UserIcon,
Lock,
Building2,
Mail,
Phone,
} from "lucide-react";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { motion } from "framer-motion";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { useTranslation } from "@/lib/i18n";
type RegisterFormData = {
name: string;
email: string;
phone: string;
password: string;
confirmPassword: string;
acceptTerms: boolean;
};
export default function RegisterUserPage() {
const router = useRouter();
const { t } = useTranslation();
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const registerSchema = useMemo(() => z.object({
name: z.string().min(3, "Nome deve ter no mínimo 3 caracteres"),
email: z.string().email("E-mail inválido"),
phone: z.string().min(10, "Telefone inválido"),
password: z.string().min(6, "Senha deve ter no mínimo 6 caracteres"),
confirmPassword: z.string().min(6, "Confirmação de senha obrigatória"),
acceptTerms: z.boolean().refine((val) => val === true, {
message: "Você deve aceitar os termos de uso"
}),
}).refine((data) => data.password === data.confirmPassword, {
message: "As senhas não coincidem",
path: ["confirmPassword"],
}), []);
const {
register,
handleSubmit,
formState: { errors },
} = useForm<RegisterFormData>({
resolver: zodResolver(registerSchema),
defaultValues: {
name: "",
email: "",
phone: "",
password: "",
confirmPassword: "",
acceptTerms: false,
},
});
const handleRegister = async (data: RegisterFormData) => {
setError("");
setLoading(true);
try {
// Aqui você fará a chamada para a API de registro
console.log('🚀 [REGISTER FRONT] Tentando registrar usuário:', data.email);
// Simulação - substitua pela sua chamada real de API
// const response = await registerUser(data);
// Por enquanto, apenas redireciona
setTimeout(() => {
router.push("/login");
}, 2000);
} catch (err: any) {
console.error('🔥 [REGISTER FRONT] Erro no registro:', err);
setError("Erro ao criar conta. Tente novamente.");
} finally {
setLoading(false);
}
};
const onSubmit = (data: RegisterFormData) => {
handleRegister(data);
};
return (
<div className="min-h-screen flex flex-col lg:flex-row">
{/* Left Side - Branding */}
<div className="lg:flex-1 bg-gradient-to-br from-primary to-primary/80 p-8 flex flex-col justify-center items-center text-primary-foreground">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="max-w-md text-center"
>
<div className="flex items-center justify-center gap-3 mb-8">
<Image
src="/logohorse.png"
alt="GoHorseJobs"
width={140}
height={140}
className="rounded-lg"
/>
</div>
<h1 className="text-4xl font-bold mb-4">
Comece sua jornada profissional
</h1>
<p className="text-lg opacity-90 leading-relaxed">
Conecte-se com as melhores oportunidades do mercado. Cadastre-se gratuitamente e encontre a vaga ideal para você!
</p>
<div className="mt-8 space-y-4">
<div className="flex items-center gap-3">
<div className="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
<UserIcon className="w-4 h-4" />
</div>
<span>Crie seu perfil profissional completo</span>
</div>
<div className="flex items-center gap-3">
<div className="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
<Building2 className="w-4 h-4" />
</div>
<span>Candidate-se às melhores vagas do mercado</span>
</div>
<div className="flex items-center gap-3">
<div className="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
<Briefcase className="w-4 h-4" />
</div>
<span>Acompanhe suas candidaturas em tempo real</span>
</div>
</div>
</motion.div>
</div>
{/* Right Side - Register Form */}
<div className="lg:flex-1 flex items-center justify-center p-8 bg-background">
<motion.div
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
className="w-full max-w-md space-y-6"
>
<div className="text-center space-y-2">
<h2 className="text-3xl font-bold">Criar Conta de Usuário</h2>
<p className="text-muted-foreground">
Preencha os dados abaixo para se cadastrar
</p>
</div>
<Card className="border-0 shadow-lg">
<CardContent className="pt-6">
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
{error && (
<motion.div
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
>
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertDescription>{error}</AlertDescription>
</Alert>
</motion.div>
)}
<div className="space-y-2">
<Label htmlFor="name">Nome Completo</Label>
<div className="relative">
<UserIcon className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input
id="name"
type="text"
placeholder="Seu nome completo"
className="pl-10"
{...register("name")}
/>
</div>
{errors.name && (
<p className="text-sm text-destructive">
{errors.name.message}
</p>
)}
</div>
<div className="space-y-2">
<Label htmlFor="email">E-mail</Label>
<div className="relative">
<Mail className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input
id="email"
type="email"
placeholder="seu@email.com"
className="pl-10"
{...register("email")}
/>
</div>
{errors.email && (
<p className="text-sm text-destructive">
{errors.email.message}
</p>
)}
</div>
<div className="space-y-2">
<Label htmlFor="phone">Telefone</Label>
<div className="relative">
<Phone className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input
id="phone"
type="tel"
placeholder="(00) 00000-0000"
className="pl-10"
{...register("phone")}
/>
</div>
{errors.phone && (
<p className="text-sm text-destructive">
{errors.phone.message}
</p>
)}
</div>
<div className="space-y-2">
<Label htmlFor="password">Senha</Label>
<div className="relative">
<Lock className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input
id="password"
type={showPassword ? "text" : "password"}
placeholder="Mínimo 6 caracteres"
className="pl-10 pr-10"
{...register("password")}
/>
<Button
type="button"
variant="ghost"
size="icon"
className="absolute right-0 top-0 h-full px-3 hover:bg-transparent"
onClick={() => setShowPassword(!showPassword)}
>
{showPassword ? (
<EyeOff className="h-4 w-4 text-muted-foreground" />
) : (
<Eye className="h-4 w-4 text-muted-foreground" />
)}
</Button>
</div>
{errors.password && (
<p className="text-sm text-destructive">
{errors.password.message}
</p>
)}
</div>
<div className="space-y-2">
<Label htmlFor="confirmPassword">Confirmar Senha</Label>
<div className="relative">
<Lock className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input
id="confirmPassword"
type={showConfirmPassword ? "text" : "password"}
placeholder="Digite a senha novamente"
className="pl-10 pr-10"
{...register("confirmPassword")}
/>
<Button
type="button"
variant="ghost"
size="icon"
className="absolute right-0 top-0 h-full px-3 hover:bg-transparent"
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
>
{showConfirmPassword ? (
<EyeOff className="h-4 w-4 text-muted-foreground" />
) : (
<Eye className="h-4 w-4 text-muted-foreground" />
)}
</Button>
</div>
{errors.confirmPassword && (
<p className="text-sm text-destructive">
{errors.confirmPassword.message}
</p>
)}
</div>
<div className="flex items-start space-x-2">
<Checkbox id="acceptTerms" {...register("acceptTerms")} className="mt-1" />
<Label
htmlFor="acceptTerms"
className="text-sm font-normal cursor-pointer leading-relaxed"
>
Aceito os{" "}
<Link href="/terms" className="text-primary hover:underline">
termos de uso
</Link>
{" "}e a{" "}
<Link href="/privacy" className="text-primary hover:underline">
política de privacidade
</Link>
</Label>
</div>
{errors.acceptTerms && (
<p className="text-sm text-destructive">
{errors.acceptTerms.message}
</p>
)}
<Button
type="submit"
className="w-full h-11 cursor-pointer bg-[#F0932B] hover:bg-[#d97d1a]"
disabled={loading}
>
{loading ? "Criando conta..." : "Criar Conta"}
</Button>
</form>
<div className="mt-6 text-center">
<p className="text-sm text-muted-foreground">
tem uma conta?{" "}
<Link href="/login" className="text-primary hover:underline font-semibold">
Fazer login
</Link>
</p>
</div>
</CardContent>
</Card>
<div className="text-center">
<Link
href="/"
className="text-sm text-muted-foreground hover:text-foreground transition-colors inline-flex items-center gap-2"
>
Voltar para o início
</Link>
</div>
</motion.div>
</div>
</div>
);
}

View file

@ -0,0 +1,41 @@
"use client"
import Link from "next/link"
import { useTranslation } from "@/lib/i18n"
export function FooterSimple() {
const { t } = useTranslation()
const currentYear = new Date().getFullYear()
return (
<footer className="border-t border-gray-200 bg-white py-8">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-6xl">
<div className="flex flex-col md:flex-row items-center justify-between gap-4">
<div className="flex items-center gap-8 text-sm text-gray-600">
<Link href="/jobs" className="hover:text-primary transition-colors">
{t('footer.vagas')}
</Link>
<Link href="/companies" className="hover:text-primary transition-colors">
{t('footer.empresas')}
</Link>
<Link href="/blog" className="hover:text-primary transition-colors">
{t('footer.blog')}
</Link>
</div>
<div>
<Link href="/login">
<button className="px-6 py-2 text-sm font-medium text-gray-700 border border-gray-300 rounded-md hover:bg-gray-50 transition-colors">
{t('footer.login')}
</button>
</Link>
</div>
</div>
<div className="mt-6 pt-6 border-t border-gray-200 text-center">
<p className="text-xs text-gray-500">© {currentYear} {t('footer.copyright')}</p>
</div>
</div>
</footer>
)
}

View file

@ -8,84 +8,91 @@ export function Footer() {
const currentYear = new Date().getFullYear()
return (
<footer className="border-t border-border bg-muted/30 mt-24">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div className="grid grid-cols-1 md:grid-cols-5 gap-8">
<div className="col-span-1 md:col-span-2">
<div className="flex items-center gap-2 mb-4">
<span className="text-xl font-semibold">GoHorse Jobs</span>
<footer className="border-t border-gray-200 bg-white py-12">
<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 text-lg">Informações</h3>
<ul className="space-y-3">
<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 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>
</li>
</ul>
</div>
<div>
<h3 className="font-bold mb-4 text-gray-900 text-lg">Para Candidatos</h3>
<ul className="space-y-3">
<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 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>
</li>
</ul>
</div>
<div>
<h3 className="font-bold mb-4 text-gray-900 text-lg">Para Empresas</h3>
<ul className="space-y-3">
<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>
</li>
</ul>
</div>
<div>
<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">
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z"/>
</svg>
</a>
<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">
<path d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z"/>
</svg>
</a>
<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">
<path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/>
</svg>
</a>
<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">
<path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/>
</svg>
</a>
<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">
<path d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"/>
</svg>
</a>
</div>
<p className="text-muted-foreground text-sm leading-relaxed max-w-md">
{t('home.hero.subtitle')}
</p>
</div>
<div>
<h3 className="font-semibold mb-4">{t('footer.jobsByTech')}</h3>
<ul className="space-y-2 text-sm text-muted-foreground">
<li>
<Link href="/jobs?tech=python" className="hover:text-foreground transition-colors">
Python Developer
</Link>
</li>
<li>
<Link href="/jobs?tech=react" className="hover:text-foreground transition-colors">
React Developer
</Link>
</li>
<li>
<Link href="/jobs?tech=data" className="hover:text-foreground transition-colors">
Data Analyst
</Link>
</li>
<li>
<Link href="/jobs?type=remote" className="hover:text-foreground transition-colors">
{t('workMode.remote')}
</Link>
</li>
</ul>
</div>
<div>
<h3 className="font-semibold mb-4">{t('footer.company')}</h3>
<ul className="space-y-2 text-sm text-muted-foreground">
<li>
<Link href="/about" className="hover:text-foreground transition-colors">
{t('footer.about')}
</Link>
</li>
<li>
<Link href="/contact" className="hover:text-foreground transition-colors">
{t('nav.contact')}
</Link>
</li>
<li>
<Link href="/jobs" className="hover:text-foreground transition-colors">
{t('nav.jobs')}
</Link>
</li>
</ul>
</div>
<div>
<h3 className="font-semibold mb-4">{t('footer.legal')}</h3>
<ul className="space-y-2 text-sm text-muted-foreground">
<li>
<Link href="/privacy" className="hover:text-foreground transition-colors">
{t('footer.privacy')}
</Link>
</li>
<li>
<Link href="/terms" className="hover:text-foreground transition-colors">
{t('footer.terms')}
</Link>
</li>
</ul>
</div>
</div>
<div className="mt-12 pt-8 border-t border-border text-center text-sm text-muted-foreground">
<p>{t('footer.copyright', { year: currentYear })}</p>
<div className="mt-12 pt-8 border-t border-gray-200 text-center">
<p className="text-sm text-gray-600">© {currentYear} GoHorse jobs. Todos os direitos reservados.</p>
</div>
</div>
</footer>

View file

@ -24,8 +24,8 @@ export function LanguageSwitcher() {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="sm" className="w-12 px-0 gap-2 focus-visible:ring-0 focus-visible:ring-offset-0">
<Globe className="h-4 w-4" />
<Button variant="ghost" size="sm" className="w-12 px-0 gap-2 focus-visible:ring-0 focus-visible:ring-offset-0 hover:bg-transparent">
<Globe className="h-4 w-4 text-white" />
<span className="sr-only">Toggle language</span>
</Button>
</DropdownMenuTrigger>

View file

@ -5,7 +5,13 @@ import Link from "next/link"
import Image from "next/image"
import { Button } from "@/components/ui/button"
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"
import { Menu, User, LogIn } from "lucide-react"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { Menu, User, LogIn, Building2, UserPlus } from "lucide-react"
import { getCurrentUser } from "@/lib/auth"
import { useTranslation } from "@/lib/i18n"
import { LanguageSwitcher } from "@/components/language-switcher"
@ -17,59 +23,81 @@ export function Navbar() {
const navigationItems = [
{ href: "/jobs", label: t('nav.jobs') },
{ href: "/about", label: t('nav.about') },
{ href: "/contact", label: t('nav.contact') },
{ href: "/companies", label: t('footer.empresas') },
{ href: "/blog", label: t('footer.blog') },
]
return (
<nav className="border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 sticky top-0 z-50">
<nav className="bg-[#1F2F40] sticky top-0 z-50 shadow-sm border-b border-white/20">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex h-16 items-center justify-between">
{/* Logo */}
<Link href="/" className="flex items-center gap-3 hover:opacity-80 transition-opacity">
<Link href="/" className="flex items-center gap-2 hover:opacity-80 transition-opacity">
<Image src="/logohorse.png" alt="GoHorse Jobs" width={48} height={48} />
<span className="text-xl font-bold tracking-tight">GoHorse Jobs</span>
<span className="text-xl font-bold">
<span className="text-white">GoHorse </span>
<span className="text-primary">Jobs</span>
</span>
</Link>
{/* Desktop Navigation */}
<div className="hidden md:flex items-center gap-6">
{/* Desktop Navigation - moved to right side */}
<div className="hidden md:flex items-center gap-8 ml-auto mr-8">
{navigationItems.map((item) => (
<Link
key={item.href}
href={item.href}
className="text-sm text-muted-foreground hover:text-foreground transition-colors relative group"
className="text-sm font-medium text-white hover:text-primary transition-colors"
>
{item.label}
<span className="absolute -bottom-1 left-0 w-0 h-0.5 bg-primary transition-all group-hover:w-full" />
</Link>
))}
</div>
{/* Desktop Auth Buttons + Language Switcher */}
<div className="hidden md:flex items-center gap-4">
<LanguageSwitcher />
{/* Desktop Auth Buttons */}
<div className="hidden md:flex items-center gap-3">
{/* LanguageSwitcher removed to match design */ }
{user ? (
<Link href="/dashboard">
<Button variant="ghost" className="gap-2">
<Button variant="ghost" className="gap-2 text-white hover:text-primary transition-colors">
<User className="w-4 h-4" />
Dashboard
</Button>
</Link>
) : (
<>
<div className="flex items-center gap-0 border border-primary rounded-md overflow-hidden bg-transparent">
<Link href="/login">
<Button variant="ghost" className="gap-2">
<LogIn className="w-4 h-4" />
{t('nav.login')}
<Button variant="ghost" className="gap-2 text-primary hover:bg-primary/10 rounded-none border-r border-primary px-6 h-9 font-normal">
{t('footer.login')}
</Button>
</Link>
<Link href="/register">
<Button className="gap-2">
<User className="w-4 h-4" />
{t('nav.register')}
</Button>
</Link>
</>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon" className="text-primary hover:bg-primary/10 rounded-none px-3 h-9 w-9">
<Menu className="w-5 h-5" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-56">
<DropdownMenuItem asChild>
<Link href="/register/user" className="flex items-center gap-2 cursor-pointer">
<UserPlus className="w-4 h-4" />
<span>Cadastrar Usuário</span>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link href="/register" className="flex items-center gap-2 cursor-pointer">
<Building2 className="w-4 h-4" />
<span>Cadastrar Empresa</span>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link href="/auth/login" className="flex items-center gap-2 cursor-pointer">
<LogIn className="w-4 h-4" />
<span>Login</span>
</Link>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
)}
</div>

View file

@ -1,4 +1,10 @@
{
"blog": {
"title": "GoHorse Jobs Blog",
"subtitle": "Insights, tips and trends to boost your tech career",
"searchPlaceholder": "Search articles...",
"featured": "Featured Articles"
},
"sidebar": {
"dashboard": "Dashboard",
"jobs": "Jobs",
@ -20,47 +26,87 @@
"about": "About",
"contact": "Contact",
"login": "Login",
"register": "Register"
"register": "Register",
"language": "Language",
"registerUser": "Register User",
"registerCompany": "Register Company"
},
"about": {
"hero": {
"title": "About the Jobs Portal",
"subtitle": "We are a platform dedicated to transforming how people find professional opportunities and how companies discover exceptional talent."
"title": "The evolution of work begins with people and their culture",
"subtitle": "Every day, we contribute to transforming the way we think about work so that it aligns with the way we want to live."
},
"story": {
"title": "Our Story",
"paragraphs": {
"first": "Founded in 2025, GoHorse Jobs was created to simplify recruiting, making it more transparent, efficient, and accessible to everyone.",
"second": "We believe that finding the right job should be simple. That is why we built a minimalist, intuitive platform that puts candidates and companies first.",
"third": "Today, we connect thousands of professionals with innovative companies, helping build successful careers and extraordinary teams."
"whatWeDo": {
"title": "What do we do?",
"paragraph1": "GoHorse Jobs connects companies with qualified talent to transform projects into real results, combining expertise, agility, and innovation in every hire.",
"paragraph2": "Our platform makes it easier for those seeking skilled professionals to connect with those looking for opportunities aligned with their profile, goals, and work style.",
"paragraph3": "At the same time, we help professionals evolve in their careers, gain autonomy, expand their networking, and secure opportunities that truly make sense for their professional growth."
},
"hybrid": {
"title": "We are hybrid, itinerant, and diverse",
"subtitle": "70% of the GoHorse Jobs team works remotely. 100% of the work is done with autonomy.",
"agile": {
"title": "+ Agile",
"description": "Our flexible work culture allows us to respond quickly to market demands and user needs."
},
"productive": {
"title": "+ Productive",
"description": "Autonomy and flexibility result in a more motivated, engaged, and productive team."
}
},
"purpose": {
"title": "The purpose that unites us",
"description": "We continuously work to transform the world of work by promoting autonomy, talent development, and equal opportunities for everyone, wherever they may be.",
"quote": "We are an innovative organization that seeks to empower people at work, positively impacting their personal, family, and social lives.",
"belief": "We believe there is a new way of working."
},
"values": {
"title": "Our Values",
"items": {
"mission": {
"title": "Mission",
"description": "Connect exceptional talent with transformative opportunities, helping professionals and companies grow."
},
"community": {
"title": "Community",
"description": "Build an inclusive community where candidates and companies find the right match for their needs."
},
"efficiency": {
"title": "Efficiency",
"description": "Simplify recruiting with intuitive technology and optimized workflows that save time."
},
"trust": {
"title": "Trust",
"description": "Ensure transparency and security in every interaction, protecting data and promoting ethical relationships."
}
"title": "Our values",
"subtitle": "The principles that guide our daily work and shape our organizational culture",
"passion": {
"title": "Passion",
"description": "We love what we do. We work, share, and live the GoHorse Jobs mission, always striving to do more and do better."
},
"humility": {
"title": "Humility",
"description": "We are part of a whole. We share information, acknowledge our mistakes, and know ourselves deeply to bring out the best in us."
},
"autonomy": {
"title": "Autonomy",
"description": "We proactively decide where to apply our talent, how to execute it, and become captains of the tasks we prioritize."
},
"creativity": {
"title": "Creativity",
"description": "Doing the same thing over and over? No, thank you. We seek creative alternatives to optimize results. Learning is continuous."
},
"flexibility": {
"title": "Flexibility",
"description": "We are not afraid of change. We recognize challenges and turn them into opportunities."
},
"honesty": {
"title": "Honesty",
"description": "We value sincerity, direct communication, and feedback. There is room to defend ideas where others are also heard."
},
"respect": {
"title": "Respect",
"description": "We are relaxed, but we always treat others with respect: there is a place and time for everything."
},
"diversity": {
"title": "Diversity",
"description": "We work in a hybrid and itinerant way, valuing the diversity of cultures, experiences, and perspectives that enrich our team."
}
},
"cta": {
"title": "Be part of the transformation of work",
"subtitle": "Join thousands of companies and professionals who already trust GoHorse Jobs to build the future of work.",
"findJobs": "Find Jobs",
"postJob": "Post a Job"
}
},
"contact": {
"hero": {
"title": "Get in Touch",
"subtitle": "Have a question or suggestion? We are here to help. Reach out anytime."
"title": "Contact GoHorse Jobs",
"subtitle": "We're here to help! Find answers to your questions or get in touch with our team."
},
"form": {
"title": "Send a message",
@ -106,8 +152,61 @@
},
"faq": {
"title": "Frequently Asked Questions",
"description": "Before reaching out, check our FAQ section. Your question may already be answered there.",
"button": "View FAQ"
"items": {
"q1": {
"q": "How do I create an account on GoHorse Jobs?",
"a": "To create an account, click the 'Login' button in the top right corner and select 'Create account'. You can register as a candidate or company by filling in the required information."
},
"q2": {
"q": "How do I post a job on GoHorse Jobs?",
"a": "After creating a company account, access your dashboard and click 'Post Job'. Fill in the job details, including title, description, requirements, and benefits. After reviewing, click 'Publish' to make your job visible to candidates."
},
"q3": {
"q": "Can I edit my resume after creating it?",
"a": "Yes! You can edit your resume at any time by accessing your profile. Go to 'My Profile' and click 'Edit Information'. All changes will be saved automatically."
},
"q4": {
"q": "How do I apply for a job?",
"a": "To apply, navigate to the desired job page and click the 'Apply' button. Make sure your profile is complete before applying, as companies will have access to your information."
},
"q5": {
"q": "How can I track the status of my applications?",
"a": "Access your candidate dashboard and click 'My Applications'. There you will see all the jobs you applied for and the current status of each one (under review, accepted, rejected)."
},
"q6": {
"q": "How much does it cost to post a job?",
"a": "GoHorse Jobs offers different plans for companies. We have free options with basic features and premium plans with more visibility and advanced features. Contact us for more information about pricing."
},
"q7": {
"q": "Can I save jobs to apply later?",
"a": "Yes! Click the heart icon on any job to add it to your favorites. You can access your favorite jobs from your dashboard at any time."
},
"q8": {
"q": "How do I contact support?",
"a": "You can contact us via email at hello@gohorsejobs.com or by phone at (11) 9999-9999. Our team is available Monday through Friday, from 9 AM to 6 PM."
}
}
},
"contactInfo": {
"title": "Contact Us",
"email": "Email",
"phone": "Phone",
"hours": "Business Hours",
"hoursValue": "Mon Fri: 9 AM to 6 PM"
},
"resources": {
"title": "Useful Resources",
"searchJobs": "Search Jobs",
"searchJobsDesc": "Find opportunities",
"createAccount": "Create Account",
"createAccountDesc": "Apply for jobs",
"postJob": "Post a Job",
"postJobDesc": "For companies"
},
"help": {
"title": "Need more help?",
"description": "Our support team is ready to assist you.",
"button": "Send Message"
}
},
"home": {
@ -1195,5 +1294,57 @@
"createFailed": "Failed to create ticket",
"subjectRequired": "Subject is required"
}
},
"home": {
"hero": {
"title": "Find Your Dream IT Job.",
"titleLine2": "",
"subtitle": "We connect you with the best companies and tech opportunities.",
"cta": "Search Jobs"
},
"search": {
"placeholder": "Enter keywords",
"filter": "Filter Jobs",
"contractType": "Contract Type",
"workMode": "Work Mode",
"location": "City and State",
"salary": "Salary Expectation",
"select": "Select",
"pj": "Contractor",
"clt": "Full-time",
"freelancer": "Freelancer",
"homeOffice": "Remote",
"presencial": "On-site",
"hybrid": "Hybrid"
},
"featuredJobs": {
"title": "Latest Registered Jobs",
"yesterday": "Yesterday",
"apply": "Apply now",
"viewJob": "View Job",
"favorite": "Favorite"
},
"levels": {
"junior": "Junior",
"mid": "Mid-level",
"senior": "Senior"
},
"moreJobs": {
"title": "More Jobs",
"viewAll": "View All Jobs"
},
"cta": {
"badge": "Social Networks",
"title": "Thousands of opportunities await you.",
"subtitle": "Connect positions, talents, and job actions.",
"button": "Sign up"
}
},
"footer": {
"vagas": "Jobs",
"empresas": "Companies",
"blog": "Blog",
"login": "Login",
"copyright": "Ghorse jobs. All rights reserved."
}
}

View file

@ -1,4 +1,10 @@
{
"blog": {
"title": "Blog GoHorse Jobs",
"subtitle": "Ideas, consejos y tendencias para impulsar tu carrera en tecnología",
"searchPlaceholder": "Buscar artículos...",
"featured": "Artículos Destacados"
},
"sidebar": {
"dashboard": "Panel de Control",
"jobs": "Empleos",
@ -20,47 +26,87 @@
"about": "Sobre",
"contact": "Contacto",
"login": "Ingresar",
"register": "Registrarse"
"register": "Registrarse",
"language": "Idioma",
"registerUser": "Registrar Usuario",
"registerCompany": "Registrar Empresa"
},
"about": {
"hero": {
"title": "Sobre el portal de empleos",
"subtitle": "Somos una plataforma dedicada a transformar cómo las personas encuentran oportunidades profesionales y cómo las empresas descubren talento excepcional."
"title": "La evolución del trabajo comienza con las personas y su cultura",
"subtitle": "Cada día contribuimos a transformar la manera en que pensamos el trabajo para que sea coherente con la forma en que queremos vivir."
},
"story": {
"title": "Nuestra historia",
"paragraphs": {
"first": "Fundada en 2025, GoHorse Jobs fue creada para simplificar la contratación, haciéndola más transparente, eficiente y accesible para todos.",
"second": "Creemos que encontrar el trabajo adecuado debería ser sencillo. Por eso construimos una plataforma minimalista e intuitiva que pone a candidatos y empresas en primer lugar.",
"third": "Hoy conectamos a miles de profesionales con empresas innovadoras, ayudando a construir carreras exitosas y equipos extraordinarios."
"whatWeDo": {
"title": "¿Qué hacemos?",
"paragraph1": "GoHorse Jobs conecta a empresas con talentos calificados para transformar proyectos en resultados reales, uniendo experiencia, agilidad e innovación en cada contratación.",
"paragraph2": "Nuestra plataforma facilita el encuentro entre quienes buscan profesionales preparados y quienes desean oportunidades alineadas con su perfil, objetivos y estilo de trabajo.",
"paragraph3": "Al mismo tiempo, ayudamos a los profesionales a evolucionar en sus carreras, ganar autonomía, ampliar su red de contactos y conquistar oportunidades que realmente tengan sentido para su crecimiento profesional."
},
"hybrid": {
"title": "Somos híbridos, itinerantes y diversos",
"subtitle": "El 70% del equipo de GoHorse Jobs trabaja de forma remota. El 100% del trabajo se realiza con autonomía.",
"agile": {
"title": "+ Ágil",
"description": "Nuestra cultura de trabajo flexible nos permite responder rápidamente a las necesidades del mercado y de nuestros usuarios."
},
"productive": {
"title": "+ Productiva",
"description": "La autonomía y la flexibilidad dan como resultado un equipo más motivado, comprometido y productivo."
}
},
"purpose": {
"title": "El propósito que nos une",
"description": "Trabajamos continuamente para transformar el mundo del trabajo promoviendo la autonomía, el desarrollo del talento y la igualdad de oportunidades para todos, estén donde estén.",
"quote": "Somos una organización innovadora que busca potenciar a las personas en el trabajo, impactando positivamente en su vida personal, familiar y social.",
"belief": "Creemos que existe una nueva forma de trabajar."
},
"values": {
"title": "Nuestros valores",
"items": {
"mission": {
"title": "Misión",
"description": "Conectar talento excepcional con oportunidades transformadoras, ayudando a profesionales y empresas a crecer."
},
"community": {
"title": "Comunidad",
"description": "Construir una comunidad inclusiva donde candidatos y empresas encuentren la combinación adecuada para sus necesidades."
},
"efficiency": {
"title": "Eficiencia",
"description": "Simplificar la contratación con tecnología intuitiva y flujos de trabajo optimizados que ahorran tiempo."
},
"trust": {
"title": "Confianza",
"description": "Garantizar transparencia y seguridad en cada interacción, protegiendo los datos y promoviendo relaciones éticas."
}
"subtitle": "Los principios que guían nuestro día a día y moldean nuestra cultura organizacional",
"passion": {
"title": "Pasión",
"description": "Amamos lo que hacemos. Trabajamos, compartimos y vivimos la misión de GoHorse Jobs, y por eso siempre queremos hacer más y hacerlo mejor."
},
"humility": {
"title": "Humildad",
"description": "Somos parte de un todo. Compartimos información, reconocemos nuestros errores y nos conocemos profundamente para dar lo mejor de nosotros."
},
"autonomy": {
"title": "Autonomía",
"description": "Decidimos de forma proactiva dónde aplicar nuestro talento, cómo ejecutarlo y nos convertimos en capitanes de las tareas que priorizamos."
},
"creativity": {
"title": "Creatividad",
"description": "¿Hacer siempre lo mismo? No, gracias. Buscamos alternativas creativas que nos permitan optimizar los resultados. El aprendizaje es continuo."
},
"flexibility": {
"title": "Flexibilidad",
"description": "No tememos al cambio. Reconocemos los desafíos y los transformamos en oportunidades."
},
"honesty": {
"title": "Honestidad",
"description": "Valoramos la sinceridad, la comunicación directa y el feedback. Hay espacio para defender ideas y también para escuchar a los demás."
},
"respect": {
"title": "Respeto",
"description": "Somos relajados, pero siempre nos dirigimos a los demás con respeto: hay un lugar y un momento para todo."
},
"diversity": {
"title": "Diversidad",
"description": "Trabajamos de manera híbrida e itinerante, valorando la diversidad de culturas, experiencias y perspectivas que enriquecen a nuestro equipo."
}
},
"cta": {
"title": "Forma parte de la transformación del trabajo",
"subtitle": "Únete a miles de empresas y profesionales que ya confían en GoHorse Jobs para construir el futuro del trabajo.",
"findJobs": "Encontrar Vacantes",
"postJob": "Publicar Vacante"
}
},
"contact": {
"hero": {
"title": "Ponte en contacto",
"subtitle": "¿Tienes una pregunta o sugerencia? Estamos aquí para ayudarte. Contáctanos en cualquier momento."
"title": "Contacta con GoHorse Jobs",
"subtitle": "¡Estamos aquí para ayudarte! Encuentra respuestas a tus preguntas o ponte en contacto con nuestro equipo."
},
"form": {
"title": "Enviar un mensaje",
@ -105,9 +151,62 @@
}
},
"faq": {
"title": "Preguntas frecuentes",
"description": "Antes de contactarnos, revisa nuestra sección de preguntas frecuentes. Tu duda puede estar allí.",
"button": "Ver preguntas frecuentes"
"title": "Preguntas Frecuentes",
"items": {
"q1": {
"q": "¿Cómo creo una cuenta en GoHorse Jobs?",
"a": "Para crear una cuenta, haz clic en el botón 'Iniciar sesión' en la esquina superior derecha y selecciona 'Crear cuenta'. Puedes registrarte como candidato o empresa completando la información requerida."
},
"q2": {
"q": "¿Cómo publico una vacante en GoHorse Jobs?",
"a": "Después de crear una cuenta de empresa, accede a tu panel y haz clic en 'Publicar Vacante'. Completa los detalles de la vacante, incluyendo título, descripción, requisitos y beneficios. Después de revisar, haz clic en 'Publicar' para hacer tu vacante visible a los candidatos."
},
"q3": {
"q": "¿Puedo editar mi currículum después de crearlo?",
"a": "¡Sí! Puedes editar tu currículum en cualquier momento accediendo a tu perfil. Ve a 'Mi Perfil' y haz clic en 'Editar Información'. Todos los cambios se guardarán automáticamente."
},
"q4": {
"q": "¿Cómo me postulo a una vacante?",
"a": "Para postularte, navega hasta la página de la vacante deseada y haz clic en el botón 'Postularse'. Asegúrate de que tu perfil esté completo antes de postularte, ya que las empresas tendrán acceso a tu información."
},
"q5": {
"q": "¿Cómo puedo seguir el estado de mis postulaciones?",
"a": "Accede a tu panel de candidato y haz clic en 'Mis Postulaciones'. Allí verás todas las vacantes a las que te postulaste y el estado actual de cada una (en revisión, aceptada, rechazada)."
},
"q6": {
"q": "¿Cuánto cuesta publicar una vacante?",
"a": "GoHorse Jobs ofrece diferentes planes para empresas. Tenemos opciones gratuitas con funciones básicas y planes premium con más visibilidad y funciones avanzadas. Contáctanos para más información sobre precios."
},
"q7": {
"q": "¿Puedo guardar vacantes para postularme más tarde?",
"a": "¡Sí! Haz clic en el ícono de corazón en cualquier vacante para agregarla a tus favoritos. Puedes acceder a tus vacantes favoritas desde tu panel en cualquier momento."
},
"q8": {
"q": "¿Cómo contacto con el soporte?",
"a": "Puedes contactarnos por correo electrónico a hello@gohorsejobs.com o por teléfono al (11) 9999-9999. Nuestro equipo está disponible de lunes a viernes, de 9:00 a 18:00."
}
}
},
"contactInfo": {
"title": "Contáctanos",
"email": "Correo electrónico",
"phone": "Teléfono",
"hours": "Horario de Atención",
"hoursValue": "Lun Vie: 9:00 a 18:00"
},
"resources": {
"title": "Recursos Útiles",
"searchJobs": "Buscar Vacantes",
"searchJobsDesc": "Encuentra oportunidades",
"createAccount": "Crear Cuenta",
"createAccountDesc": "Postúlate a vacantes",
"postJob": "Publicar Vacante",
"postJobDesc": "Para empresas"
},
"help": {
"title": "¿Necesitas más ayuda?",
"description": "Nuestro equipo de soporte está listo para ayudarte.",
"button": "Enviar Mensaje"
}
},
"home": {
@ -1196,5 +1295,57 @@
"createFailed": "Error al crear ticket",
"subjectRequired": "El asunto es requerido"
}
},
"home": {
"hero": {
"title": "Encuentra el Trabajo de TI",
"titleLine2": "de Tus Sueños.",
"subtitle": "Te conectamos con las mejores empresas y tecnologías.",
"cta": "Buscar Empleos"
},
"search": {
"placeholder": "Ingresa palabras clave",
"filter": "Filtrar Empleos",
"contractType": "Tipo de contratación",
"workMode": "Régimen de Trabajo",
"location": "Ciudad y estado",
"salary": "Expectativa salarial",
"select": "Seleccione",
"pj": "Contratista",
"clt": "Tiempo completo",
"freelancer": "Freelancer",
"homeOffice": "Remoto",
"presencial": "Presencial",
"hybrid": "Híbrido"
},
"featuredJobs": {
"title": "Últimos Empleos Registrados",
"yesterday": "Ayer",
"apply": "Aplicar ahora",
"viewJob": "Ver Empleo",
"favorite": "Favorito"
},
"levels": {
"junior": "Junior",
"mid": "Semi-senior",
"senior": "Senior"
},
"moreJobs": {
"title": "Más Empleos",
"viewAll": "Ver Todos los Empleos"
},
"cta": {
"badge": "Redes Sociales",
"title": "Miles de oportunidades te esperan.",
"subtitle": "Conecta posiciones, talentos, acciones de empleos.",
"button": "Regístrate"
}
},
"footer": {
"vagas": "Empleos",
"empresas": "Empresas",
"blog": "Blog",
"login": "Iniciar sesión",
"copyright": "Ghorse jobs. Todos los derechos reservados."
}
}

View file

@ -1,4 +1,10 @@
{
"blog": {
"title": "Blog GoHorse Jobs",
"subtitle": "Insights, dicas e tendências para impulsionar sua carreira em tecnologia",
"searchPlaceholder": "Buscar artigos...",
"featured": "Artigos em Destaque"
},
"sidebar": {
"dashboard": "Dashboard",
"jobs": "Vagas",
@ -53,51 +59,91 @@
"about": "Sobre",
"contact": "Contato",
"login": "Entrar",
"register": "Cadastrar"
"register": "Cadastrar",
"language": "Idioma",
"registerUser": "Cadastrar Usuário",
"registerCompany": "Cadastrar Empresa"
},
"about": {
"hero": {
"title": "Sobre o portal de vagas",
"subtitle": "Somos uma plataforma dedicada a transformar a forma como as pessoas encontram oportunidades profissionais e como as empresas descobrem talentos excepcionais."
"title": "A evolução do trabalho começa pelas pessoas e sua cultura",
"subtitle": "Todos os dias contribuímos para transformar a maneira como pensamos o trabalho para que seja coerente com a maneira como queremos viver."
},
"story": {
"title": "Nossa história",
"paragraphs": {
"first": "Fundada em 2025, a GoHorse Jobs foi criada para simplificar o recrutamento, tornando-o mais transparente, eficiente e acessível para todos.",
"second": "Acreditamos que encontrar o emprego certo deve ser simples. Por isso, construímos uma plataforma minimalista e intuitiva que coloca candidatos e empresas em primeiro lugar.",
"third": "Hoje conectamos milhares de profissionais a empresas inovadoras, ajudando a construir carreiras de sucesso e equipes extraordinárias."
"whatWeDo": {
"title": "O que fazemos?",
"paragraph1": "O GoHorse Jobs conecta empresas a talentos qualificados para transformar projetos em resultados reais, unindo expertise, agilidade e inovação em cada contratação.",
"paragraph2": "Nossa plataforma facilita o encontro entre quem busca profissionais preparados e quem deseja oportunidades alinhadas ao seu perfil, objetivos e estilo de trabalho.",
"paragraph3": "Ao mesmo tempo, ajudamos profissionais a evoluírem em suas carreiras, ganharem autonomia, ampliarem seu networking e conquistarem oportunidades que realmente fazem sentido para seu crescimento profissional."
},
"hybrid": {
"title": "Somos híbridos, itinerantes e diversos",
"subtitle": "70% da equipe do GoHorse Jobs trabalha remotamente. 100% de trabalho com autonomia.",
"agile": {
"title": "+ Ágil",
"description": "Nossa cultura de trabalho flexível nos permite responder rapidamente às necessidades do mercado e dos nossos usuários."
},
"productive": {
"title": "+ Produtiva",
"description": "A autonomia e flexibilidade resultam em uma equipe mais motivada, engajada e produtiva em seus projetos."
}
},
"purpose": {
"title": "O propósito que nos une",
"description": "Trabalhamos continuamente para transformar o mundo do trabalho promovendo a autonomia, o desenvolvimento de talentos e a igualdade de oportunidades para todos, de onde quer que seja.",
"quote": "Somos uma organização inovadora que busca potencializar as pessoas no trabalho, impactando positivamente na vida pessoal, familiar e social.",
"belief": "Acreditamos que há uma nova forma de trabalhar."
},
"values": {
"title": "Nossos valores",
"items": {
"mission": {
"title": "Missão",
"description": "Conectar talentos excepcionais com oportunidades transformadoras, ajudando profissionais e empresas a crescer."
},
"community": {
"title": "Comunidade",
"description": "Construir uma comunidade inclusiva onde candidatos e empresas encontrem a combinação ideal para suas necessidades."
},
"efficiency": {
"title": "Eficiência",
"description": "Simplificar o recrutamento com tecnologia intuitiva e fluxos de trabalho otimizados que economizam tempo."
},
"trust": {
"title": "Confiança",
"description": "Garantir transparência e segurança em cada interação, protegendo dados e promovendo relações éticas."
}
"subtitle": "Os princípios que guiam nosso dia a dia e moldam nossa cultura organizacional",
"passion": {
"title": "Paixão",
"description": "Amamos o que fazemos. Trabalhamos, compartilhamos e vivemos a missão do GoHorse Jobs e, por isso, queremos sempre fazer mais e fazer melhor."
},
"humility": {
"title": "Humildade",
"description": "Somos parte de um todo. Por isso, compartilhamos informações, reconhecemos nossos erros e nos conhecemos a fundo para trazer o melhor de nós."
},
"autonomy": {
"title": "Autonomia",
"description": "Decidimos proativamente onde empregar nosso talento, como executá-lo e nos tornamos capitães das tarefas que priorizamos."
},
"creativity": {
"title": "Criatividade",
"description": "Fazer sempre o mesmo? Não, obrigado. Buscamos alternativas criativas que nos permitam otimizar os resultados. A aprendizagem é contínua."
},
"flexibility": {
"title": "Flexibilidade",
"description": "Não temos medo da mudança. Por isso, não entramos em crise quando a vivemos: reconhecemos os desafios e os transformamos em oportunidades."
},
"honesty": {
"title": "Honestidade",
"description": "Valorizamos a sinceridade, a comunicação direta e o feedback. Há espaço para defender ideias no mesmo lugar onde os outros são ouvidos."
},
"respect": {
"title": "Respeito",
"description": "Somos descontraídos, mas sempre nos dirigimos com respeito aos outros: há lugar e momento para tudo."
},
"diversity": {
"title": "Diversidade",
"description": "Trabalhamos de forma híbrida e itinerante, valorizando a diversidade de culturas, experiências e perspectivas que enriquecem nosso time."
}
},
"cta": {
"title": "Faça parte da transformação do trabalho",
"subtitle": "Junte-se a milhares de empresas e profissionais que já confiam no GoHorse Jobs para construir o futuro do trabalho.",
"findJobs": "Encontrar Vagas",
"postJob": "Publicar Vaga"
}
},
"contact": {
"hero": {
"title": "Fale conosco",
"subtitle": "Tem alguma dúvida ou sugestão? Estamos aqui para ajudar. Entre em contato quando quiser."
"title": "Entre em contato com a GoHorse Jobs",
"subtitle": "Estamos aqui para ajudar! Encontre respostas para suas perguntas ou entre em contato com nossa equipe."
},
"form": {
"title": "Envie uma mensagem",
"description": "Preencha o formulário e responderemos em breve.",
"title": "Enviar uma mensagem",
"description": "Preencha o formulário e retornaremos em breve.",
"fields": {
"name": {
"label": "Nome completo",
@ -105,7 +151,7 @@
},
"email": {
"label": "E-mail",
"placeholder": "voce@email.com"
"placeholder": "seu@email.com"
},
"subject": {
"label": "Assunto",
@ -122,7 +168,7 @@
}
},
"info": {
"title": "Outras formas de falar com a gente",
"title": "Outras formas de contato",
"email": {
"title": "E-mail"
},
@ -134,22 +180,81 @@
},
"support": {
"title": "Suporte",
"description": "Segunda a sexta, das 9h às 18h"
"description": "Segunda a sexta-feira, das 9h às 18h"
}
},
"intro": {
"title": "Entre em contato com a GoHorse Jobs",
"subtitle": "Estamos aqui para ajudar! Encontre respostas para suas perguntas ou entre em contato com nossa equipe."
},
"faq": {
"title": "Perguntas frequentes",
"description": "Antes de entrar em contato, confira nossa seção de FAQ. Sua dúvida pode já estar respondida lá.",
"button": "Ver FAQ"
"title": "Perguntas Frequentes",
"items": {
"q1": {
"q": "Como crio uma conta no GoHorse Jobs?",
"a": "Para criar uma conta, clique no botão “Entrar” no canto superior direito e selecione “Criar conta”. Você pode se registrar como candidato ou empresa, preenchendo as informações solicitadas."
},
"q2": {
"q": "Como publico uma vaga no GoHorse Jobs?",
"a": "Após criar uma conta como empresa, acesse seu painel e clique em “Publicar Vaga”. Preencha os detalhes da vaga, incluindo título, descrição, requisitos e benefícios. Depois de revisar as informações, clique em “Publicar” para tornar a vaga visível aos candidatos."
},
"q3": {
"q": "Posso editar meu currículo depois de criá-lo?",
"a": "Sim! Você pode editar seu currículo a qualquer momento acessando seu perfil. Vá até “Meu Perfil” e clique em “Editar Informações”. Todas as alterações serão salvas automaticamente."
},
"q4": {
"q": "Como me candidato a uma vaga?",
"a": "Para se candidatar, acesse a página da vaga desejada e clique no botão “Candidatar-se”. Certifique-se de que seu perfil esteja completo antes de se candidatar, pois as empresas terão acesso às suas informações."
},
"q5": {
"q": "Como posso acompanhar o status das minhas candidaturas?",
"a": "Acesse seu painel de candidato e clique em “Minhas Candidaturas”. Lá você verá todas as vagas às quais se candidatou e o status atual de cada uma (em análise, aprovada, rejeitada)."
},
"q6": {
"q": "Quanto custa publicar uma vaga?",
"a": "O GoHorse Jobs oferece diferentes planos para empresas. Há opções gratuitas com funcionalidades básicas e planos premium com maior visibilidade e recursos avançados. Entre em contato conosco para mais informações sobre preços."
},
"q7": {
"q": "Posso salvar vagas para me candidatar depois?",
"a": "Sim! Clique no ícone de coração em qualquer vaga para adicioná-la aos seus favoritos. Você pode acessar suas vagas salvas a qualquer momento pelo seu painel."
},
"q8": {
"q": "Como entro em contato com o suporte?",
"a": "Você pode entrar em contato conosco pelo e-mail hello@gohorsejobs.com ou pelo telefone (11) 9999-9999. Nosso time está disponível de segunda a sexta-feira, das 9h às 18h."
}
}
},
"contactInfo": {
"title": "Fale Conosco",
"email": "E-mail",
"phone": "Telefone",
"hours": "Horário de Atendimento",
"hoursValue": "Segunda a sexta-feira: 9h às 18h"
},
"resources": {
"title": "Recursos Úteis",
"searchJobs": "Buscar Vagas",
"searchJobsDesc": "Encontre oportunidades",
"createAccount": "Criar Conta",
"createAccountDesc": "Candidate-se a vagas",
"postJob": "Publicar Vaga",
"postJobDesc": "Para empresas"
},
"help": {
"title": "Precisa de mais ajuda?",
"description": "Nossa equipe de suporte está pronta para ajudar você.",
"button": "Enviar Mensagem"
},
"actions": {
"sendMessage": "Enviar Mensagem"
}
},
"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",
@ -1223,5 +1328,57 @@
"createFailed": "Erro ao criar ticket",
"subjectRequired": "O assunto é obrigatório"
}
},
"home": {
"hero": {
"title": "Encontre a Vaga de TI",
"titleLine2": "dos Seus Sonhos.",
"subtitle": "Conectamos você com as melhores empresas e techs.",
"cta": "Buscar Vagas"
},
"search": {
"placeholder": "Digite as palavras-chave",
"filter": "Filtrar Vagas",
"contractType": "Tipo de contratação",
"workMode": "Regime de Trabalho",
"location": "Cidade e estado",
"salary": "Pretensão salarial",
"select": "Selecione",
"pj": "PJ",
"clt": "CLT",
"freelancer": "Freelancer",
"homeOffice": "Home-Office",
"presencial": "Presencial",
"hybrid": "Híbrido"
},
"featuredJobs": {
"title": "Últimas Vagas Cadastradas",
"yesterday": "Ontem",
"apply": "Aplicar agora",
"viewJob": "Ver Vaga",
"favorite": "Favoritar"
},
"levels": {
"junior": "Júnior",
"mid": "Pleno",
"senior": "Sênior"
},
"moreJobs": {
"title": "Mais Vagas",
"viewAll": "Ver Todas Vagas"
},
"cta": {
"badge": "Redes Sociais",
"title": "Milhares de oportunidades esperam você.",
"subtitle": "Conecte cargos, talentos, tomada de ações de vagas.",
"button": "Cadastre-se"
}
},
"footer": {
"vagas": "Vagas",
"empresas": "Empresas",
"blog": "Blog",
"login": "Login",
"copyright": "Ghorse jobs. Todos os direitos reservados."
}
}

View file

@ -81,6 +81,314 @@ export const mockJobs: Job[] = [
requirements: ["Docker", "Kubernetes", "AWS", "Terraform"],
postedAt: "2025-10-10",
},
{
id: "7",
title: "Backend Developer",
company: "CodeLab",
location: "Curitiba, PR",
type: "full-time",
salary: "R$ 10,000 - R$ 15,000",
description: "Develop and maintain scalable backend systems.",
requirements: ["Node.js", "PostgreSQL", "REST APIs", "3+ years"],
postedAt: "2025-10-09",
},
{
id: "8",
title: "QA Analyst",
company: "TestPro",
location: "Porto Alegre, RS",
type: "remote",
salary: "R$ 7,000 - R$ 11,000",
description: "Ensure quality through comprehensive testing.",
requirements: ["Selenium", "Jest", "Test automation", "2+ years"],
postedAt: "2025-10-08",
},
{
id: "9",
title: "Security Engineer",
company: "SecureNet",
location: "Brasília, DF",
type: "full-time",
salary: "R$ 14,000 - R$ 20,000",
description: "Protect systems and data from cyber threats.",
requirements: ["Security", "Penetration testing", "ISO 27001", "5+ years"],
postedAt: "2025-10-07",
},
{
id: "10",
title: "Frontend Developer",
company: "WebStudio",
location: "São Paulo, SP",
type: "remote",
salary: "R$ 9,000 - R$ 13,000",
description: "Create beautiful and responsive user interfaces.",
requirements: ["React", "TypeScript", "CSS", "3+ years"],
postedAt: "2025-10-06",
},
{
id: "11",
title: "Scrum Master",
company: "AgileTeam",
location: "Rio de Janeiro, RJ",
type: "full-time",
salary: "R$ 11,000 - R$ 16,000",
description: "Lead agile teams to deliver value.",
requirements: ["Scrum", "Agile", "Leadership", "CSM certified"],
postedAt: "2025-10-05",
},
{
id: "12",
title: "Business Analyst",
company: "DataInsights",
location: "Belo Horizonte, MG",
type: "full-time",
salary: "R$ 8,000 - R$ 12,000",
description: "Analyze business requirements and propose solutions.",
requirements: ["SQL", "Power BI", "Business analysis", "2+ years"],
postedAt: "2025-10-04",
},
{
id: "13",
title: "AI Engineer",
company: "SmartAI",
location: "São Paulo, SP",
type: "full-time",
salary: "R$ 16,000 - R$ 24,000",
description: "Build intelligent systems using machine learning.",
requirements: ["Python", "TensorFlow", "PyTorch", "ML/AI"],
postedAt: "2025-10-03",
},
{
id: "14",
title: "Database Administrator",
company: "DataCore",
location: "Campinas, SP",
type: "full-time",
salary: "R$ 12,000 - R$ 17,000",
description: "Manage and optimize database systems.",
requirements: ["PostgreSQL", "MySQL", "Performance tuning", "4+ years"],
postedAt: "2025-10-02",
},
{
id: "15",
title: "Cloud Architect",
company: "SkyTech",
location: "São Paulo, SP",
type: "remote",
salary: "R$ 18,000 - R$ 26,000",
description: "Design and implement cloud solutions.",
requirements: ["AWS", "Azure", "Architecture", "6+ years"],
postedAt: "2025-10-01",
},
{
id: "16",
title: "Technical Writer",
company: "DocuMasters",
location: "Remote",
type: "remote",
salary: "R$ 6,000 - R$ 10,000",
description: "Create technical documentation and guides.",
requirements: ["Technical writing", "English", "API docs", "2+ years"],
postedAt: "2025-09-30",
},
{
id: "17",
title: "Sales Engineer",
company: "TechSales",
location: "São Paulo, SP",
type: "full-time",
salary: "R$ 13,000 - R$ 19,000",
description: "Combine technical knowledge with sales skills.",
requirements: ["Sales", "Technical background", "Presentations", "3+ years"],
postedAt: "2025-09-29",
},
{
id: "18",
title: "System Administrator",
company: "ITOps",
location: "Recife, PE",
type: "full-time",
salary: "R$ 9,000 - R$ 14,000",
description: "Maintain and monitor IT infrastructure.",
requirements: ["Linux", "Windows Server", "Networking", "3+ years"],
postedAt: "2025-09-28",
},
{
id: "19",
title: "Game Developer",
company: "GameStudio",
location: "São Paulo, SP",
type: "remote",
salary: "R$ 11,000 - R$ 16,000",
description: "Create engaging gaming experiences.",
requirements: ["Unity", "C#", "3D modeling", "Game design"],
postedAt: "2025-09-27",
},
{
id: "20",
title: "Marketing Analyst",
company: "GrowthLab",
location: "Rio de Janeiro, RJ",
type: "full-time",
salary: "R$ 7,000 - R$ 11,000",
description: "Drive marketing strategies with data.",
requirements: ["Marketing", "Google Analytics", "SEO", "2+ years"],
postedAt: "2025-09-26",
},
{
id: "21",
title: "HR Specialist",
company: "PeopleFirst",
location: "Belo Horizonte, MG",
type: "full-time",
salary: "R$ 6,000 - R$ 9,000",
description: "Manage recruitment and employee relations.",
requirements: ["HR", "Recruitment", "Employee relations", "2+ years"],
postedAt: "2025-09-25",
},
{
id: "22",
title: "Network Engineer",
company: "NetWorks",
location: "Brasília, DF",
type: "full-time",
salary: "R$ 12,000 - R$ 17,000",
description: "Design and maintain network infrastructure.",
requirements: ["Cisco", "CCNA", "Networking", "4+ years"],
postedAt: "2025-09-24",
},
{
id: "23",
title: "Blockchain Developer",
company: "CryptoTech",
location: "São Paulo, SP",
type: "remote",
salary: "R$ 15,000 - R$ 22,000",
description: "Build decentralized applications.",
requirements: ["Solidity", "Ethereum", "Smart contracts", "3+ years"],
postedAt: "2025-09-23",
},
{
id: "24",
title: "Solutions Architect",
company: "TechSolutions",
location: "São Paulo, SP",
type: "full-time",
salary: "R$ 17,000 - R$ 25,000",
description: "Design comprehensive technical solutions.",
requirements: ["Architecture", "AWS", "Microservices", "6+ years"],
postedAt: "2025-09-22",
},
{
id: "25",
title: "Customer Success Manager",
company: "ClientCare",
location: "Remote",
type: "remote",
salary: "R$ 8,000 - R$ 13,000",
description: "Ensure customer satisfaction and retention.",
requirements: ["Customer success", "SaaS", "Communication", "2+ years"],
postedAt: "2025-09-21",
},
{
id: "26",
title: "IT Support Specialist",
company: "HelpDesk Pro",
location: "Curitiba, PR",
type: "full-time",
salary: "R$ 4,500 - R$ 7,000",
description: "Provide technical support to users.",
requirements: ["IT support", "Windows", "Troubleshooting", "1+ year"],
postedAt: "2025-09-20",
},
{
id: "27",
title: "Java Developer",
company: "Enterprise Systems",
location: "Porto Alegre, RS",
type: "full-time",
salary: "R$ 10,000 - R$ 15,000",
description: "Develop enterprise Java applications.",
requirements: ["Java", "Spring Boot", "Maven", "4+ years"],
postedAt: "2025-09-19",
},
{
id: "28",
title: "Digital Marketing Manager",
company: "MediaHub",
location: "São Paulo, SP",
type: "full-time",
salary: "R$ 9,000 - R$ 14,000",
description: "Lead digital marketing campaigns.",
requirements: ["Digital marketing", "Google Ads", "Social media", "3+ years"],
postedAt: "2025-09-18",
},
{
id: "29",
title: "iOS Developer",
company: "MobileApps",
location: "Remote",
type: "remote",
salary: "R$ 11,000 - R$ 16,000",
description: "Build native iOS applications.",
requirements: ["Swift", "iOS SDK", "Xcode", "3+ years"],
postedAt: "2025-09-17",
},
{
id: "30",
title: "Android Developer",
company: "MobileApps",
location: "Remote",
type: "remote",
salary: "R$ 11,000 - R$ 16,000",
description: "Build native Android applications.",
requirements: ["Kotlin", "Android SDK", "3+ years"],
postedAt: "2025-09-16",
},
{
id: "31",
title: "Project Manager",
company: "ProjectWorks",
location: "São Paulo, SP",
type: "full-time",
salary: "R$ 12,000 - R$ 18,000",
description: "Lead and deliver successful projects.",
requirements: ["PMP", "Project management", "Agile", "5+ years"],
postedAt: "2025-09-15",
},
{
id: "32",
title: "Full Stack Engineer",
company: "WebDev Pro",
location: "Rio de Janeiro, RJ",
type: "remote",
salary: "R$ 13,000 - R$ 19,000",
description: "Develop modern web applications end-to-end.",
requirements: ["React", "Node.js", "MongoDB", "4+ years"],
postedAt: "2025-09-14",
},
{
id: "33",
title: "UX Researcher",
company: "UserFirst",
location: "São Paulo, SP",
type: "full-time",
salary: "R$ 9,000 - R$ 14,000",
description: "Conduct user research to improve product experiences.",
requirements: ["UX Research", "User testing", "Analytics", "3+ years"],
postedAt: "2025-09-13",
},
{
id: "34",
title: "Data Scientist",
company: "DataMind",
location: "Remote",
type: "remote",
salary: "R$ 14,000 - R$ 21,000",
description: "Build predictive models and analyze large datasets.",
requirements: ["Python", "Machine Learning", "Statistics", "4+ years"],
postedAt: "2025-09-12",
},
];
export const mockApplications: Application[] = [