# Frontend - GoHorse Jobs

[![Next.js](https://img.shields.io/badge/Next.js-15-black?style=flat-square&logo=next.js)](https://nextjs.org/)
[![Tailwind CSS](https://img.shields.io/badge/Tailwind-4-06B6D4?style=flat-square&logo=tailwindcss)](https://tailwindcss.com/)
[![TypeScript](https://img.shields.io/badge/TypeScript-5-3178C6?style=flat-square&logo=typescript)](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)
