Commit graph

974 commits

Author SHA1 Message Date
Tiago Yamamoto
59cd1fa01a feat: add pagination to candidates list endpoint
- Add PaginationInfo struct to candidates DTO
- Update ListCandidates service to support page/perPage params
- Update handler to parse pagination query params
- Update frontend candidates page with pagination controls
2026-02-23 18:02:41 -06:00
Tiago Yamamoto
fa1d397c01 fix: sync credentials services between backend and frontend
- Update ListConfiguredServices to use correct service names
- Add fcm_service_account, appwrite, smtp to BootstrapCredentials
- Remove unused payment_gateway from frontend schema
- Rename firebase to fcm_service_account in frontend
2026-02-23 16:20:25 -06:00
Tiago Yamamoto
f061763ae4 fix: add category field to admin tickets page 2026-02-23 15:53:17 -06:00
Tiago Yamamoto
74afffa4a9 feat: add category field to tickets system 2026-02-23 15:43:35 -06:00
Tiago Yamamoto
3583ef89d8 fix: set cookie Secure=true and SameSite=None for cross-origin auth 2026-02-23 13:44:34 -06:00
Tiago Yamamoto
5ce0980090 fix: move loading check after useEffect to prevent infinite loading 2026-02-23 13:13:57 -06:00
Tiago Yamamoto
1b35b8dd70 fix: resolve infinite loading on settings page
- Remove duplicate setLoading calls in loadBackoffice
- Add proper error handling with catch for all API calls
- Wrap useEffect initialization in try/catch/finally
2026-02-23 12:56:23 -06:00
Tiago Yamamoto
754acd9d3c feat: merge backoffice into settings and add CRUD for credentials
- Move backoffice functionality into settings page as new tab
- Remove standalone backoffice page and sidebar link
- Add edit/delete buttons for credentials management
- Update credentials service to allow overwriting existing credentials
- Add API documentation for system credentials endpoints
2026-02-23 12:42:06 -06:00
Tiago Yamamoto
f22bd51c5d feat: fix language switcher visibility in dashboard header and align pagination buttons 2026-02-23 12:07:07 -06:00
Tiago Yamamoto
01a6cab984 fix: allow all gohorsejobs.com subdomains in CORS for backoffice 2026-02-23 11:51:31 -06:00
Tiago Yamamoto
fd2fa328ad chore: replace native window.confirm with Custom ConfirmModal 2026-02-23 11:24:55 -06:00
Tiago Yamamoto
c5f6b1317e fix(frontend): resolve hydration mismatch and unauthorized api calls 2026-02-23 09:45:26 -06:00
Tiago Yamamoto
364826c5c8 fix(dashboard): align CRUD pages with backend fields
jobs/page.tsx:
- Edit dialog now exposes all UpdateJobRequest fields: employmentType,
  workMode, salaryMin/max/type/currency, salaryNegotiable, languageLevel,
  visaSupport, location, status, isFeatured, description
- Fix AdminJob type to include all JobWithCompany fields returned by API
- Fix jobRows mapping that was hardcoding location/type/workMode/isFeatured
- Add isFeatured to CreateJobPayload type

applications/page.tsx:
- Fix status mismatch: reviewing→reviewed, interview→shortlisted, accepted→hired
- Align statusConfig labels/keys with backend constraint (pending/reviewed/
  shortlisted/rejected/hired)
- Update stats counters to use corrected status keys

companies/page.tsx:
- Add logoUrl and yearsInMarket to create and edit forms
- Populate editFormData from company object on edit open
- Send logoUrl/yearsInMarket in update payload

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 18:27:30 -06:00
Tiago Yamamoto
0876584499 feat(seeder): add realistic job templates with all new fields
Replace placeholder job data with 10 varied templates covering:
- employment_type (full-time, part-time, contract, dispatch)
- work_mode (remote, hybrid, onsite)
- salary_min/max, salary_type, currency (BRL/USD/EUR/GBP/JPY)
- salary_negotiable, language_level, visa_support
- date_posted, realistic descriptions and locations

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 13:06:32 -06:00
Tiago Yamamoto
45659f4a76 fix(search): add companies JOIN to countQuery so keyword search works
The countQuery was missing LEFT JOIN companies c, causing a PostgreSQL
error when the search filter referenced c.name ILIKE. This made every
keyword search return a 500 error instead of results.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 13:02:29 -06:00
Tiago Yamamoto
2b98552658 feat(dashboard): rewrite jobs/new with all backend fields and location autocomplete
- Add workMode, languageLevel, visaSupport, salaryNegotiable to form
- Add all 10 currency options and all 8 employment types (including dispatch/voluntary)
- Add status selector (draft/review/open/paused/closed)
- Add location autocomplete with country dropdown and city/region search
- Add application channel (email/url/phone) with conditional inputs
- Add resumeRequirement selector and requirements map in payload
- Load companies via adminCompaniesApi (no registration — user is already logged in)
- Extend CreateJobPayload type with workMode, cityId, regionId, languageLevel,
  visaSupport, requirements, expanded currency and status options

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 12:58:03 -06:00
Tiago Yamamoto
edc1b76cfd refactor(routes): remove /publicar-vaga and /register/job
Both routes are fully replaced by /jobs/new. Deleted directories entirely
instead of keeping redirects.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 12:51:57 -06:00
Tiago Yamamoto
878a987749 refactor(routes): redirect /register/job to /jobs/new
Consolidates the two public job posting routes into the single canonical
flow at /jobs/new. The /publicar-vaga route already redirected there.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 12:50:51 -06:00
Tiago Yamamoto
3a26af3df5 fix: global document and phone handling — remove Brazil-specific formatting
Frontend (jobs/new):
- Replace isValidCNPJ (checksum algorithm) with isValidDocument: accepts
  any tax document with 5–30 alphanumeric chars (CNPJ, EIN, VAT, etc.)
- Add cleanPhone(): strips formatting chars (dashes, spaces, parens) and
  keeps only digits + optional leading '+'; replaces cleanDigits+prepend
- Phone sent as '+5511999998888' if user typed '+55...', or '11999998888'
  if no country code was provided — no '+' blindly prepended anymore
- Company document sent stripped of all non-alphanumeric before API call
- Update label placeholder from '00.000.000/0000-00' to 'CNPJ, EIN, VAT...'
- Rename error key invalidCnpj → invalidDocument in all 3 locales (pt, en, es)

Backend (create_company use case):
- Add SanitizePhone() to utils/sanitizer.go: strips all non-digit chars
  except a leading '+'; '(11) 99999-8888' → '11999998888'
- Apply SanitizePhone to input.Phone before persisting to DB

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 12:46:54 -06:00
Tiago Yamamoto
fd085ec193 feat(jobs/new): location autocomplete using /api/v1/locations/search
- Replace free-text location input with debounced autocomplete
- On country select, fetch its numeric ID from /api/v1/locations/countries
  and use it to scope the search results to that country
- Typing ≥2 chars in location field triggers GET /api/v1/locations/search
  with 350ms debounce; results show city (blue) and state (green) badges
- On result selection, stores cityId + regionId and sets the display label
  to "Name, Region" format; IDs are included in the job creation payload
- Spinner shown while searching; dropdown closes on outside click / select
- CEP search button preserved alongside the autocomplete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 12:39:46 -06:00
Tiago Yamamoto
2686b69506 feat(jobs/new): add user account registration and fix companyId in job payload
- Add password + confirm-password fields to billing step (Step 3) so the
  recruiter creates their account credentials during the job posting flow
- Validate password length (≥8) and confirmation match before proceeding
- Extract company `id` from POST /auth/register/company response and send
  it as `companyId` in the job creation payload (was missing — caused 400)
- Pass `contact` (full name) to company registration endpoint
- Remove hardcoded "Temp@123456" password; use the user-provided one
- Remove hardcoded "+55" phone prefix; send raw digits with "+" prefix
- Add translations (pt-BR, en, es) for password fields and error messages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 12:32:55 -06:00
Tiago Yamamoto
61d64d846a fix(jobs): enforce CreateJob validation and sanitize DB constraint errors
- Add validateCreateJobRequest() checking required fields (companyId,
  title ≥5 chars, description ≥20 chars) and enum values
  (employmentType, workMode, status) before hitting the DB
- Catch *pq.Error in handler: check_violation (23514) and
  foreign_key_violation (23503) now return 400; unique_violation (23505)
  returns 409; other DB errors return 500 without leaking raw pq messages
- Fix test fixtures: description and companyId now meet validation
  requirements

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 12:26:14 -06:00
Tiago Yamamoto
89358acc13 refactor(auth): remove hash hardcoded da migration, seeder gera em runtime
Antes: 010_seed_super_admin.sql tinha hash bcrypt fixo amarrado a um pepper
específico. Qualquer mudança no PASSWORD_PEPPER quebrava todos os logins
silenciosamente após reset do banco.

Agora:
- migration 010: insere superadmin com placeholder inválido + force_change_password.
  ON CONFLICT DO NOTHING preserva o hash se o seeder já rodou.
- seeder users.js: faz upsert de 'lol' com bcrypt(senha + env.PASSWORD_PEPPER)
  em runtime. Mudar o pepper e re-rodar o seeder é suficiente para atualizar
  as credenciais sem tocar em nenhuma migration.
- docs/AGENTS.md: atualiza gotcha #1 explicando o novo fluxo migrate → seed
- docs/DEVOPS.md: fix opção 1 do troubleshooting inclui re-deploy do seeder

Fluxo correto após reset do banco (coberto pelo start.sh opções 2, 6, 8):
  npm run migrate  →  superadmin criado, hash = placeholder
  npm run seed     →  hash recalculado com PEPPER do ambiente, status = active

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 12:05:54 -06:00
Tiago Yamamoto
fcf960381c fix(auth): corrige hash seed e documenta alinhamento do PASSWORD_PEPPER
- Atualiza hash hardcoded em 010_seed_super_admin.sql para hash válido
  gerado com pepper=gohorse-pepper (o antigo hash estava inválido e causava
  AUTH_INVALID_CREDENTIALS em qualquer reset do banco)
- Corrige valor de PASSWORD_PEPPER e CORS_ORIGINS no DEVOPS.md para
  refletir os valores reais do Coolify DEV
- Adiciona seção de troubleshooting no DEVOPS.md com diagnóstico e fix
  passo-a-passo para mismatch de pepper
- Adiciona seção "Known Gotchas" no AGENTS.md documentando:
  * Regra do PASSWORD_PEPPER (deve ser gohorse-pepper em todos ambientes)
  * Campo de login é email no DTO, não identifier
  * Hashes bcrypt em SQL devem usar arquivo -f, nunca -c ($ é expandido)
  * Credenciais de teste do ambiente DEV

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 11:43:35 -06:00
Tiago Yamamoto
dda447e4b6 docs: unify test users in root README and update superadmin to lol login 2026-02-21 14:48:25 -06:00
Tiago Yamamoto
d7b03dad19 docs: add AI context rules and missing READMEs 2026-02-21 13:33:36 -06:00
bohessefm
c9f5cec84c Update .forgejo/workflows/deploy.yaml 2026-02-21 15:05:00 +00:00
bohessefm
742aa7fe8b Update .forgejo/workflows/deploy.yaml 2026-02-21 13:31:22 +00:00
bohessefm
adfc8386fe Update .forgejo/workflows/deploy.yaml 2026-02-21 13:25:41 +00:00
bohessefm
d002a7dbad Update .forgejo/workflows/deploy.yaml 2026-02-21 13:23:48 +00:00
bohessefm
6f97748bd4 Update .forgejo/workflows/deploy.yaml 2026-02-21 13:23:22 +00:00
bohessefm
1b07447550 Update .forgejo/workflows/deploy.yaml 2026-02-21 13:16:38 +00:00
bohessefm
b05456e21c Update .forgejo/workflows/deploy.yaml 2026-02-21 13:14:25 +00:00
bohessefm
c76a5879f9 Update .forgejo/workflows/deploy.yaml 2026-02-18 23:33:44 +00:00
bohessefm
a1091f0ee6 Update .forgejo/workflows/deploy.yaml 2026-02-18 23:31:40 +00:00
bohessefm
4ec574d66a Update .forgejo/workflows/deploy.yaml 2026-02-18 23:30:01 +00:00
bohessefm
37749b0f14 Update .forgejo/workflows/deploy.yaml 2026-02-18 23:27:20 +00:00
bohessefm
8b231b944f Update .forgejo/workflows/deploy.yaml 2026-02-18 23:25:16 +00:00
bohessefm
ee1207e2d9 Update .forgejo/workflows/deploy.yaml 2026-02-18 23:21:50 +00:00
bohessefm
65b2d65b25 Update .forgejo/workflows/deploy.yaml 2026-02-18 23:17:18 +00:00
Tiago Yamamoto
3ac65ce38b fix(ci): correct KUBECONFIG secret name in Forgejo deploy workflow
- Fix secrets.KUBE_CONFIG → secrets.KUBECONFIG (matching actual secret name)
- Update DEVOPS.md with dual pipeline architecture (GitHub→Coolify + Forgejo→K3s)
- Document Forgejo Actions secrets and variables

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 13:05:03 -06:00
Tiago Yamamoto
e238da0649 docs: add CI/CD pipeline details, credentials reference, and webhook config
- Document Forgejo Actions pipeline (build-and-push OK, deploy FAIL due to K3s)
- Add credentials/tokens reference table (~/.ssh/ files)
- Document GitHub webhooks for Coolify auto-deploy
- Update CI/CD flow diagram with Forgejo Actions runner

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 13:00:36 -06:00
Tiago Yamamoto
21727793aa ci: update Coolify API URL to HTTPS 2026-02-18 12:46:03 -06:00
Tiago Yamamoto
de3f497223 fix: resolve TypeScript build errors preventing Coolify deploy
- Fix nullable location in my-jobs search filter (job.location ?? '')
- Fix Locale type assertion in jobs/new description language select
- Fix nullable location in api.ts transformApiJobToFrontend

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 11:33:45 -06:00
Tiago Yamamoto
9fd5cf5895 docs: update infra diagrams, add test users, fix Coolify URL
- Add full infrastructure Mermaid diagrams (Redbull + Apolo + CI/CD flow)
- Create TEST_USERS.md with all seeder credentials organized by role
- Fix Coolify URL from IP to https://redbull.rede5.com.br
- Update Coolify resources with current domains and status
- Add TEST_USERS.md reference to AGENTS.md, README.md, and doc index
- Update deployment section with both DEV environments

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 06:22:56 -06:00
Tiago Yamamoto
7e202bb99e feat(i18n): fully translate /jobs/new page into pt-BR, en, and es
Replace all hardcoded Portuguese strings with locale-aware translations
using contentByLocale object. All 4 steps (job details, preview,
billing, payment), labels, placeholders, options, error messages,
and button texts now adapt to the user's selected language.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 06:06:12 -06:00
Tiago Yamamoto
55705a0fbb fix(i18n): initialize locale from browser/localStorage and add fallback chain
- Initialize useState with getInitialLocale() instead of hardcoded 'en',
  so the correct locale is used from the very first render
- Default to 'pt-BR' instead of 'en' for SSR and fallback
- Add fallback chain in t(): tries current locale -> pt-BR -> en
- Extract resolveKey() helper for cleaner key resolution
- Cast dictionaries as Record<string, unknown> to avoid type issues
- Wrap localStorage access in try-catch for blocked storage scenarios

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 06:02:06 -06:00
Tiago Yamamoto
8fb358a984 fix: remove edge runtime from job detail page and add description fallback
Remove `export const runtime = "edge"` which could interfere with i18n
JSON imports causing translation keys to render as literal text. Also
add fallback text when job description is empty.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 05:56:59 -06:00
Tiago Yamamoto
f6758c165c fix: resolve merge conflict markers in ApiJob interface and fix requirements type handling
Removed leftover <<<<<<< Updated upstream conflict markers that were breaking TypeScript compilation,
preventing the job detail page (/jobs/[id]) from loading real data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 05:47:08 -06:00
Tiago Yamamoto
ae4dcb4b90
Merge pull request #73 from rede5/codex/verificar-idioma-na-pagina-de-empregos
Codex-generated pull request
2026-02-18 08:41:39 -03:00