11 KiB
11 KiB
Frontend - GoHorse Jobs
Frontend da plataforma GoHorse Jobs construído com Next.js 15 e App Router.
Last Updated: 2026-01-03
🚀 Deploy (CI/CD)
Ambientes
| Ambiente | URL | Branch |
|---|---|---|
| DEV | https://dev.gohorsejobs.com | dev |
| PRD | https://gohorsejobs.com | main |
Pipeline Forgejo
A pipeline está configurada em .forgejo/workflows/deploy.yaml e é triggerada automaticamente ao fazer push em dev com mudanças em frontend/.
Fluxo:
- Build local:
podman build -t forgejo-gru.rede5.com.br/rede5/gohorsejobs-frontend:latest . - Push para registry:
podman push forgejo-gru.rede5.com.br/rede5/gohorsejobs-frontend:latest - Commit e push:
git push origin dev && git push forgejo dev - Pipeline detecta mudanças em
frontend/ - Deploy via SSH: Pull da imagem + restart do serviço
# Comandos executados pela pipeline no servidor
podman pull forgejo-gru.rede5.com.br/rede5/gohorsejobs-frontend:latest
sudo systemctl restart gohorsejobs-frontend-dev
Verificar Pipeline
# Via browser
https://forgejo-gru.rede5.com.br/rede5/gohorsejobs/actions
# Testar se está rodando
curl -s https://dev.gohorsejobs.com | head -c 200
✨ Features
- Server-Side Pagination: Listagem de vagas otimizada
- Busca e Filtros: Tipo, localização, modo de trabalho
- Internacionalização (i18n): PT, EN
- Dark/Light Mode: Tema automático
- Skeleton Loading: Estados de carregamento
- Real-time Chat: Integração Appwrite
- Push Notifications: Firebase Cloud Messaging
- Avatar Upload: Pre-signed URLs (S3/R2)
- Email Templates Admin: CRUD para templates
- Public Job Posting: Wizard de registro + vaga
🏗️ Arquitetura
src/
├── app/ # App Router (35 pages)
│ ├── page.tsx # Landing page
│ ├── login/ # Autenticação
│ ├── register/ # Registro (candidate, company)
│ ├── post-job/ # **NEW** Wizard público
│ ├── jobs/ # Listagem e detalhes
│ │ ├── page.tsx # Listagem
│ │ ├── [id]/page.tsx # Detalhes
│ │ └── [id]/apply/ # Candidatura
│ ├── dashboard/ # Área logada (12 subpastas)
│ │ ├── admin/ # Painel Admin
│ │ │ └── email-templates/ # **NEW** CRUD templates
│ │ ├── applications/ # Candidaturas
│ │ ├── candidates/ # Lista candidatos
│ │ ├── companies/ # Lista empresas
│ │ ├── jobs/ # Gestão de vagas
│ │ ├── messages/ # Chat real-time
│ │ ├── profile/ # Perfil do usuário
│ │ ├── settings/ # Configurações
│ │ ├── support/ # Tickets
│ │ └── users/ # Gestão de usuários
│ ├── about/ # Sobre
│ ├── contact/ # Contato
│ ├── faq/ # FAQ
│ └── terms/, privacy/ # Legais
│
├── components/ # 44 componentes
│ ├── ui/ # 24 shadcn/ui primitives
│ ├── navbar.tsx # Navegação principal
│ ├── footer.tsx # Rodapé
│ ├── sidebar.tsx # Sidebar dashboard
│ ├── job-card.tsx # Card de vaga
│ ├── notification-dropdown.tsx # Notificações
│ ├── profile-picture-upload.tsx # Upload de avatar
│ └── loading-skeletons.tsx # Skeletons
│
├── contexts/ # React Contexts
│ ├── AuthContext.tsx # Autenticação global
│ └── ThemeContext.tsx # **NEW** Tema configurável
│
├── hooks/ # Custom Hooks
│ ├── useAuth.ts # Autenticação
│ ├── useProfile.ts # Perfil
│ └── ...
│
├── lib/ # Utilitários (13 arquivos)
│ ├── api.ts # Cliente HTTP (22KB)
│ ├── auth.ts # Auth helpers
│ ├── appwrite.ts # Appwrite client
│ ├── firebase-client.ts # FCM client
│ ├── storage.ts # Pre-signed URLs
│ ├── i18n.tsx # Internacionalização
│ ├── types.ts # TypeScript types
│ └── mock-data.ts # Dados mock (fallback)
│
└── i18n/ # Traduções
├── pt.json # Português
└── en.json # English
📱 Páginas
Públicas
| Rota | Descrição |
|---|---|
/ |
Landing page |
/jobs |
Listagem de vagas |
/jobs/{id} |
Detalhes da vaga |
/jobs/{id}/apply |
Candidatura |
/login |
Login |
/register/candidate |
Registro candidato |
/register/company |
Registro empresa |
/post-job |
NEW Wizard público (registro + vaga) |
/about |
Sobre |
/contact |
Contato |
/faq |
FAQ |
/forgot-password |
Reset senha |
Dashboard (Autenticadas)
| Rota | Roles | Descrição |
|---|---|---|
/dashboard |
All | Dashboard home |
/dashboard/profile |
All | Perfil do usuário |
/dashboard/settings |
Admin | Configurações (tema, logo) |
/dashboard/jobs |
Admin, Recruiter | Gestão de vagas |
/dashboard/jobs/new |
Admin, Recruiter | Criar vaga |
/dashboard/applications |
Admin, Recruiter | Candidaturas |
/dashboard/candidates |
Admin | Lista candidatos |
/dashboard/companies |
SuperAdmin | Lista empresas |
/dashboard/users |
SuperAdmin, Admin | Gestão usuários |
/dashboard/messages |
All | Chat real-time |
/dashboard/support |
All | Tickets de suporte |
/dashboard/admin/email-templates |
SuperAdmin | NEW Templates email |
🎨 Design System
Tecnologias
| Tecnologia | Versão | Uso |
|---|---|---|
| shadcn/ui | - | Componentes base (Radix UI) |
| Tailwind CSS | 4 | Estilização utility-first |
| Lucide Icons | 0.454 | Ícones |
| Framer Motion | 12 | Animações |
| Sonner | 1.7 | Toasts/Notificações |
| Recharts | 2.15 | Gráficos |
Tema
Definido em src/app/globals.css:
:root {
--primary: oklch(0.68 0.22 45); /* Laranja */
--background: oklch(1 0 0); /* Branco */
--foreground: oklch(0.145 0 0); /* Preto */
}
.dark {
--background: oklch(0.145 0 0); /* Preto */
--foreground: oklch(0.985 0 0); /* Branco */
}
🔌 API Client
O cliente de API está em lib/api.ts (22KB):
Módulos
| Módulo | Funções |
|---|---|
| jobsApi | list, getById, create, update, delete |
| adminApi | companies, users, candidates, tags |
| profileApi | getMe, updateProfile, uploadAvatar |
| applicationsApi | create, list, getById, updateStatus |
| emailTemplatesApi | NEW list, get, create, update, delete |
| emailSettingsApi | NEW get, update |
| chatApi | listConversations, listMessages, sendMessage |
| supportApi | tickets, messages |
| settingsApi | get, save |
| fcmApi | saveToken |
Exemplo
import { jobsApi, profileApi } from "@/lib/api";
// Listar vagas
const jobs = await jobsApi.list({ page: 1, limit: 10 });
// Atualizar perfil
await profileApi.updateProfile({ name: "New Name" });
// Upload avatar (pre-signed URL flow)
await profileApi.uploadAvatar(file);
🔒 Autenticação
Fluxo
- Login: POST
/api/v1/auth/login - Token Storage:
localStorage.auth_token - Cookie: JWT HttpOnly (backup)
- Headers:
Authorization: Bearer <token>
Auth Context
import { useAuth } from "@/hooks/useAuth";
const { user, isLoading, login, logout } = useAuth();
🌍 Internacionalização
Idiomas Suportados
- 🇧🇷 Português (pt)
- 🇺🇸 English (en)
Uso
import { useTranslation } from "@/lib/i18n";
const { t, locale, setLocale } = useTranslation();
// Usar tradução
<h1>{t("home.hero.title")}</h1>
// Trocar idioma
<button onClick={() => setLocale("en")}>English</button>
🔧 Environment Variables
# API
NEXT_PUBLIC_API_URL=https://api.gohorsejobs.com
# Backoffice
NEXT_PUBLIC_BACKOFFICE_URL=https://backoffice.gohorsejobs.com
# Appwrite (Chat)
NEXT_PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
NEXT_PUBLIC_APPWRITE_PROJECT_ID=your-project-id
NEXT_PUBLIC_APPWRITE_DATABASE_ID=your-database-id
# Firebase (Push Notifications)
NEXT_PUBLIC_FIREBASE_API_KEY=your-api-key
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your-project-id
🚀 Desenvolvimento
Instalar
npm install
# ou
pnpm install
Executar
npm run dev
Build
npm run build
npm run start
Testes
npm run test
Lint
npm run lint
🐳 Desenvolvimento com Container (Podman)
# Build da imagem
podman build -t gohorse-frontend .
# Rodar container
# --net host recomendado para acessar APIs locais (Backend/Backoffice)
podman run --name frontend --net host --env-file .env.local gohorse-frontend
Nota: Não utilizamos
docker-compose. Para orquestração em produção, utilizamos Quadlet.
Nota: Usa output: "standalone" no next.config.ts.
📦 Dependências Principais
| Package | Version | Uso |
|---|---|---|
| next | 15.5 | Framework |
| react | 19.1 | UI Library |
| tailwindcss | 4.1 | CSS |
| framer-motion | 12.23 | Animações |
| sonner | 1.7 | Toasts |
| recharts | 2.15 | Gráficos |
| firebase | 12.7 | FCM |
| appwrite | 17.0 | Chat |
| zod | 3.25 | Validação |
| zustand | 4.5 | State |
📁 Componentes UI (shadcn)
24 componentes do shadcn/ui:
| Componente | Uso |
|---|---|
accordion |
FAQ |
alert-dialog |
Confirmações |
avatar |
Fotos de perfil |
badge |
Tags |
button |
Ações |
card |
Containers |
checkbox |
Formulários |
dialog |
Modais |
dropdown-menu |
Menus |
input |
Campos |
label |
Labels |
popover |
Popovers |
progress |
Progresso |
radio-group |
Seleção única |
scroll-area |
Scroll customizado |
select |
Dropdowns |
separator |
Divisores |
skeleton |
Loading |
slider |
Range |
switch |
Toggles |
tabs |
Navegação |
textarea |
Texto longo |
toast |
Notificações |
tooltip |
Hints |