412 lines
11 KiB
Markdown
412 lines
11 KiB
Markdown
# Frontend - GoHorse Jobs
|
|
|
|
[](https://nextjs.org/)
|
|
[](https://tailwindcss.com/)
|
|
[](https://typescriptlang.org/)
|
|
|
|
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:**
|
|
|
|
1. **Build local:** `podman build -t forgejo-gru.rede5.com.br/rede5/gohorsejobs-frontend:latest .`
|
|
2. **Push para registry:** `podman push forgejo-gru.rede5.com.br/rede5/gohorsejobs-frontend:latest`
|
|
3. **Commit e push:** `git push origin dev && git push forgejo dev`
|
|
4. **Pipeline detecta mudanças** em `frontend/`
|
|
5. **Deploy via SSH:** Pull da imagem + restart do serviço
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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`:
|
|
|
|
```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
|
|
|
|
```typescript
|
|
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
|
|
|
|
1. **Login**: POST `/api/v1/auth/login`
|
|
2. **Token Storage**: `localStorage.auth_token`
|
|
3. **Cookie**: JWT HttpOnly (backup)
|
|
4. **Headers**: `Authorization: Bearer <token>`
|
|
|
|
### Auth Context
|
|
|
|
```typescript
|
|
import { useAuth } from "@/hooks/useAuth";
|
|
|
|
const { user, isLoading, login, logout } = useAuth();
|
|
```
|
|
|
|
---
|
|
|
|
## 🌍 Internacionalização
|
|
|
|
### Idiomas Suportados
|
|
|
|
- 🇧🇷 Português (pt)
|
|
- 🇺🇸 English (en)
|
|
|
|
### Uso
|
|
|
|
```typescript
|
|
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
|
|
|
|
```env
|
|
# 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
|
|
|
|
```bash
|
|
npm install
|
|
# ou
|
|
pnpm install
|
|
```
|
|
|
|
### Executar
|
|
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
### Build
|
|
|
|
```bash
|
|
npm run build
|
|
npm run start
|
|
```
|
|
|
|
### Testes
|
|
|
|
```bash
|
|
npm run test
|
|
```
|
|
|
|
### Lint
|
|
|
|
```bash
|
|
npm run lint
|
|
```
|
|
|
|
---
|
|
|
|
## 🐳 Desenvolvimento com Container (Podman)
|
|
|
|
```bash
|
|
# 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 |
|
|
|
|
---
|
|
|
|
## 🔗 Referências
|
|
|
|
- [API Documentation](../docs/API.md)
|
|
- [Backend](../backend/BACKEND.md)
|
|
- [Backoffice](../backoffice/BACKOFFICE.md)
|
|
- [Database Schema](../docs/DATABASE.md)
|
|
- [Design System](./DESIGN_SYSTEM.md)
|