feat: enhance job form with currency, salary periods, contract types, and add ER diagram docs
This commit is contained in:
parent
80d38ee615
commit
42e9f81f48
7 changed files with 316 additions and 92 deletions
|
|
@ -7,8 +7,9 @@ type CreateJobRequest struct {
|
|||
Description string `json:"description" validate:"required,min=20"`
|
||||
SalaryMin *float64 `json:"salaryMin,omitempty"`
|
||||
SalaryMax *float64 `json:"salaryMax,omitempty"`
|
||||
SalaryType *string `json:"salaryType,omitempty" validate:"omitempty,oneof=hourly monthly yearly"`
|
||||
EmploymentType *string `json:"employmentType,omitempty" validate:"omitempty,oneof=full-time part-time dispatch contract"`
|
||||
SalaryType *string `json:"salaryType,omitempty" validate:"omitempty,oneof=hourly daily weekly monthly yearly"`
|
||||
Currency *string `json:"currency,omitempty" validate:"omitempty,oneof=BRL USD EUR GBP JPY"`
|
||||
EmploymentType *string `json:"employmentType,omitempty" validate:"omitempty,oneof=full-time part-time dispatch contract temporary training voluntary permanent"`
|
||||
WorkingHours *string `json:"workingHours,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
RegionID *int `json:"regionId,omitempty"`
|
||||
|
|
@ -26,8 +27,9 @@ type UpdateJobRequest struct {
|
|||
Description *string `json:"description,omitempty" validate:"omitempty,min=20"`
|
||||
SalaryMin *float64 `json:"salaryMin,omitempty"`
|
||||
SalaryMax *float64 `json:"salaryMax,omitempty"`
|
||||
SalaryType *string `json:"salaryType,omitempty" validate:"omitempty,oneof=hourly monthly yearly"`
|
||||
EmploymentType *string `json:"employmentType,omitempty" validate:"omitempty,oneof=full-time part-time dispatch contract"`
|
||||
SalaryType *string `json:"salaryType,omitempty" validate:"omitempty,oneof=hourly daily weekly monthly yearly"`
|
||||
Currency *string `json:"currency,omitempty" validate:"omitempty,oneof=BRL USD EUR GBP JPY"`
|
||||
EmploymentType *string `json:"employmentType,omitempty" validate:"omitempty,oneof=full-time part-time dispatch contract temporary training voluntary permanent"`
|
||||
WorkingHours *string `json:"workingHours,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
RegionID *int `json:"regionId,omitempty"`
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ type Job struct {
|
|||
// Salary
|
||||
SalaryMin *float64 `json:"salaryMin,omitempty" db:"salary_min"`
|
||||
SalaryMax *float64 `json:"salaryMax,omitempty" db:"salary_max"`
|
||||
SalaryType *string `json:"salaryType,omitempty" db:"salary_type"` // hourly, monthly, yearly
|
||||
SalaryType *string `json:"salaryType,omitempty" db:"salary_type"` // hourly, daily, weekly, monthly, yearly
|
||||
Currency *string `json:"currency,omitempty" db:"currency"` // BRL, USD, EUR, GBP, JPY
|
||||
|
||||
// Employment
|
||||
EmploymentType *string `json:"employmentType,omitempty" db:"employment_type"` // full-time, part-time, dispatch, contract
|
||||
|
|
|
|||
21
backend/migrations/018_add_currency_to_jobs.sql
Normal file
21
backend/migrations/018_add_currency_to_jobs.sql
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
-- Migration: Add currency to jobs and expand options
|
||||
-- Description: Adds currency field and expands salary_type and employment_type options
|
||||
|
||||
-- Add currency column
|
||||
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS currency VARCHAR(3) DEFAULT 'BRL';
|
||||
|
||||
-- Update salary_type constraint to include more options
|
||||
ALTER TABLE jobs DROP CONSTRAINT IF EXISTS jobs_salary_type_check;
|
||||
ALTER TABLE jobs ADD CONSTRAINT jobs_salary_type_check
|
||||
CHECK (salary_type IN ('hourly', 'daily', 'weekly', 'monthly', 'yearly'));
|
||||
|
||||
-- Update employment_type constraint to include more options
|
||||
ALTER TABLE jobs DROP CONSTRAINT IF EXISTS jobs_employment_type_check;
|
||||
ALTER TABLE jobs ADD CONSTRAINT jobs_employment_type_check
|
||||
CHECK (employment_type IN ('full-time', 'part-time', 'contract', 'temporary', 'training', 'voluntary', 'dispatch', 'permanent'));
|
||||
|
||||
-- Add index for currency filtering
|
||||
CREATE INDEX IF NOT EXISTS idx_jobs_currency ON jobs(currency);
|
||||
|
||||
-- Comments
|
||||
COMMENT ON COLUMN jobs.currency IS 'Currency code (BRL, USD, EUR, GBP, JPY, etc.)';
|
||||
323
docs/DATABASE.md
323
docs/DATABASE.md
|
|
@ -1,108 +1,279 @@
|
|||
# Database Schema Documentation
|
||||
|
||||
This document outlines the database schema for the GoHorseJobs platform, based on the backend Go models.
|
||||
This document outlines the database schema for the GoHorseJobs platform.
|
||||
|
||||
## Entity Relationship Diagram
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
users {
|
||||
int id PK
|
||||
varchar identifier UK
|
||||
varchar password_hash
|
||||
varchar role
|
||||
varchar full_name
|
||||
varchar language
|
||||
boolean active
|
||||
timestamp created_at
|
||||
timestamp updated_at
|
||||
timestamp last_login_at
|
||||
}
|
||||
|
||||
companies {
|
||||
int id PK
|
||||
varchar name
|
||||
varchar slug UK
|
||||
varchar type
|
||||
varchar document
|
||||
varchar address
|
||||
int region_id FK
|
||||
int city_id FK
|
||||
varchar phone
|
||||
varchar email
|
||||
varchar website
|
||||
varchar logo_url
|
||||
text description
|
||||
boolean active
|
||||
boolean verified
|
||||
timestamp created_at
|
||||
timestamp updated_at
|
||||
}
|
||||
|
||||
jobs {
|
||||
int id PK
|
||||
int company_id FK
|
||||
int created_by FK
|
||||
varchar title
|
||||
text description
|
||||
decimal salary_min
|
||||
decimal salary_max
|
||||
varchar salary_type
|
||||
varchar currency
|
||||
varchar employment_type
|
||||
varchar work_mode
|
||||
varchar working_hours
|
||||
varchar location
|
||||
int region_id FK
|
||||
int city_id FK
|
||||
jsonb requirements
|
||||
jsonb benefits
|
||||
boolean visa_support
|
||||
varchar language_level
|
||||
varchar status
|
||||
boolean is_featured
|
||||
timestamp created_at
|
||||
timestamp updated_at
|
||||
}
|
||||
|
||||
applications {
|
||||
int id PK
|
||||
int job_id FK
|
||||
int user_id FK
|
||||
varchar name
|
||||
varchar email
|
||||
varchar phone
|
||||
varchar line_id
|
||||
varchar whatsapp
|
||||
text message
|
||||
varchar resume_url
|
||||
jsonb documents
|
||||
varchar status
|
||||
text notes
|
||||
timestamp created_at
|
||||
timestamp updated_at
|
||||
}
|
||||
|
||||
regions {
|
||||
int id PK
|
||||
varchar name
|
||||
varchar country_code
|
||||
varchar code
|
||||
}
|
||||
|
||||
cities {
|
||||
int id PK
|
||||
int region_id FK
|
||||
varchar name
|
||||
}
|
||||
|
||||
user_companies {
|
||||
int id PK
|
||||
int user_id FK
|
||||
int company_id FK
|
||||
varchar role
|
||||
jsonb permissions
|
||||
}
|
||||
|
||||
favorite_jobs {
|
||||
int id PK
|
||||
int user_id FK
|
||||
int job_id FK
|
||||
}
|
||||
|
||||
users ||--o{ user_companies : "belongs to"
|
||||
companies ||--o{ user_companies : "has members"
|
||||
companies ||--o{ jobs : "posts"
|
||||
users ||--o{ jobs : "creates"
|
||||
jobs ||--o{ applications : "receives"
|
||||
users ||--o{ applications : "submits"
|
||||
regions ||--o{ cities : "contains"
|
||||
regions ||--o{ companies : "located in"
|
||||
cities ||--o{ companies : "located in"
|
||||
regions ||--o{ jobs : "located in"
|
||||
cities ||--o{ jobs : "located in"
|
||||
users ||--o{ favorite_jobs : "saves"
|
||||
jobs ||--o{ favorite_jobs : "saved by"
|
||||
```
|
||||
|
||||
## Core Tables
|
||||
|
||||
### Users (`users`)
|
||||
Represents system users including Candidates, Recruiters, and Admins.
|
||||
- **id**: `INTEGER` (PK)
|
||||
- **identifier**: `VARCHAR` (Unique, Email or Username)
|
||||
- **password_hash**: `VARCHAR`
|
||||
- **role**: `VARCHAR` (superadmin, companyAdmin, recruiter, jobSeeker)
|
||||
- **full_name**: `VARCHAR`
|
||||
- **language**: `VARCHAR` (Default: 'pt')
|
||||
- **active**: `BOOLEAN`
|
||||
- **created_at**, **updated_at**, **last_login_at**: `TIMESTAMP`
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | Primary key |
|
||||
| identifier | VARCHAR | Unique, Email or Username |
|
||||
| password_hash | VARCHAR | Bcrypt hash |
|
||||
| role | VARCHAR | `superadmin`, `companyAdmin`, `recruiter`, `jobSeeker` |
|
||||
| full_name | VARCHAR | Display name |
|
||||
| language | VARCHAR | Default: 'pt' |
|
||||
| active | BOOLEAN | Account status |
|
||||
| created_at | TIMESTAMP | Creation time |
|
||||
| updated_at | TIMESTAMP | Last update |
|
||||
| last_login_at | TIMESTAMP | Last login |
|
||||
|
||||
---
|
||||
|
||||
### Companies (`companies`)
|
||||
Represents employer organizations.
|
||||
- **id**: `INTEGER` (PK)
|
||||
- **name**: `VARCHAR`
|
||||
- **slug**: `VARCHAR` (Unique)
|
||||
- **type**: `VARCHAR`
|
||||
- **document**: `VARCHAR` (Houjin Bangou / CNPJ)
|
||||
- **address**, **region_id**, **city_id**, **phone**, **email**, **website**: Contact info
|
||||
- **logo_url**, **description**: Branding
|
||||
- **active**, **verified**: `BOOLEAN`
|
||||
- **created_at**, **updated_at**: `TIMESTAMP`
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | Primary key |
|
||||
| name | VARCHAR | Company name |
|
||||
| slug | VARCHAR | URL-friendly identifier |
|
||||
| type | VARCHAR | Company type |
|
||||
| document | VARCHAR | Houjin Bangou / CNPJ |
|
||||
| address | VARCHAR | Physical address |
|
||||
| region_id | INTEGER | FK → regions.id |
|
||||
| city_id | INTEGER | FK → cities.id |
|
||||
| phone, email, website | VARCHAR | Contact info |
|
||||
| logo_url | VARCHAR | Logo image URL |
|
||||
| description | TEXT | Company description |
|
||||
| active | BOOLEAN | Active status |
|
||||
| verified | BOOLEAN | Verification status |
|
||||
|
||||
---
|
||||
|
||||
### Jobs (`jobs`)
|
||||
Represents job postings.
|
||||
- **id**: `INTEGER` (PK)
|
||||
- **company_id**: `INTEGER` (FK -> companies.id)
|
||||
- **created_by**: `INTEGER` (FK -> users.id)
|
||||
- **title**: `VARCHAR`
|
||||
- **description**: `TEXT`
|
||||
- **salary_min**, **salary_max**: `DECIMAL`
|
||||
- **salary_type**: `VARCHAR` (hourly, monthly, yearly)
|
||||
- **employment_type**: `VARCHAR` (full-time, part-time, etc.)
|
||||
- **work_mode**: `VARCHAR` (onsite, hybrid, remote)
|
||||
- **location**, **region_id**, **city_id**: Location details
|
||||
- **requirements**, **benefits**: `JSONB`
|
||||
- **visa_support**: `BOOLEAN`
|
||||
- **language_level**: `VARCHAR`
|
||||
- **status**: `VARCHAR` (draft, published, closed, etc.)
|
||||
- **is_featured**: `BOOLEAN`
|
||||
- **created_at**, **updated_at**: `TIMESTAMP`
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | Primary key |
|
||||
| company_id | INTEGER | FK → companies.id |
|
||||
| created_by | INTEGER | FK → users.id |
|
||||
| title | VARCHAR | Job title |
|
||||
| description | TEXT | Full job description |
|
||||
| salary_min | DECIMAL | Minimum salary |
|
||||
| salary_max | DECIMAL | Maximum salary |
|
||||
| salary_type | VARCHAR | `hourly`, `daily`, `weekly`, `monthly`, `yearly` |
|
||||
| currency | VARCHAR | `BRL`, `USD`, `EUR`, `GBP`, `JPY` |
|
||||
| employment_type | VARCHAR | `full-time`, `part-time`, `contract`, `temporary`, `training`, `voluntary`, `permanent`, `dispatch` |
|
||||
| work_mode | VARCHAR | `onsite`, `hybrid`, `remote` |
|
||||
| working_hours | VARCHAR | e.g. "9:00-18:00" |
|
||||
| location | VARCHAR | Location string |
|
||||
| region_id | INTEGER | FK → regions.id |
|
||||
| city_id | INTEGER | FK → cities.id |
|
||||
| requirements | JSONB | Skills/requirements array |
|
||||
| benefits | JSONB | Benefits array |
|
||||
| visa_support | BOOLEAN | Visa sponsorship |
|
||||
| language_level | VARCHAR | `N5`, `N4`, `N3`, `N2`, `N1`, `beginner`, `none` |
|
||||
| status | VARCHAR | `draft`, `open`, `closed`, `published`, `paused`, `expired`, `archived`, `reported`, `review` |
|
||||
| is_featured | BOOLEAN | Featured job flag |
|
||||
|
||||
---
|
||||
|
||||
### Applications (`applications`)
|
||||
Represents job applications.
|
||||
- **id**: `INTEGER` (PK)
|
||||
- **job_id**: `INTEGER` (FK -> jobs.id)
|
||||
- **user_id**: `INTEGER` (FK -> users.id, Nullable for guests)
|
||||
- **name**, **email**, **phone**, **line_id**, **whatsapp**: Applicant info
|
||||
- **message**: `TEXT`
|
||||
- **resume_url**: `VARCHAR`
|
||||
- **documents**: `JSONB`
|
||||
- **status**: `VARCHAR` (pending, reviewed, hired, etc.)
|
||||
- **notes**: `TEXT`
|
||||
- **created_at**, **updated_at**: `TIMESTAMP`
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | Primary key |
|
||||
| job_id | INTEGER | FK → jobs.id |
|
||||
| user_id | INTEGER | FK → users.id (nullable for guests) |
|
||||
| name | VARCHAR | Applicant name |
|
||||
| email | VARCHAR | Contact email |
|
||||
| phone | VARCHAR | Phone number |
|
||||
| line_id | VARCHAR | LINE ID |
|
||||
| whatsapp | VARCHAR | WhatsApp number |
|
||||
| message | TEXT | Cover message |
|
||||
| resume_url | VARCHAR | Resume file URL |
|
||||
| documents | JSONB | Additional documents |
|
||||
| status | VARCHAR | `pending`, `reviewed`, `shortlisted`, `rejected`, `hired` |
|
||||
| notes | TEXT | Recruiter notes |
|
||||
|
||||
---
|
||||
|
||||
## Reference Tables
|
||||
|
||||
### Regions (`regions`)
|
||||
- **id**: `INTEGER` (PK)
|
||||
- **name**: `VARCHAR`
|
||||
- **country_code**: `VARCHAR`
|
||||
- **code**: `VARCHAR`
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | Primary key |
|
||||
| name | VARCHAR | Region name |
|
||||
| country_code | VARCHAR | e.g. "JP", "BR" |
|
||||
| code | VARCHAR | Region code |
|
||||
|
||||
### Cities (`cities`)
|
||||
- **id**: `INTEGER` (PK)
|
||||
- **region_id**: `INTEGER` (FK -> regions.id)
|
||||
- **name**: `VARCHAR`
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | Primary key |
|
||||
| region_id | INTEGER | FK → regions.id |
|
||||
| name | VARCHAR | City name |
|
||||
|
||||
### Tags (`tags`)
|
||||
- **id**: `INTEGER` (PK)
|
||||
- **name**: `VARCHAR`
|
||||
- **category**: `VARCHAR`
|
||||
- **active**: `BOOLEAN`
|
||||
---
|
||||
|
||||
## Relations & Logs
|
||||
## Junction Tables
|
||||
|
||||
### User Companies (`user_companies`)
|
||||
Maps Users to Companies (N:M).
|
||||
- **id**: `INTEGER` (PK)
|
||||
- **user_id**: `INTEGER` (FK -> users.id)
|
||||
- **company_id**: `INTEGER` (FK -> companies.id)
|
||||
- **role**: `VARCHAR` (companyAdmin, recruiter)
|
||||
- **permissions**: `JSONB`
|
||||
Maps users to companies (N:M relationship).
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | Primary key |
|
||||
| user_id | INTEGER | FK → users.id |
|
||||
| company_id | INTEGER | FK → companies.id |
|
||||
| role | VARCHAR | `companyAdmin`, `recruiter` |
|
||||
| permissions | JSONB | Custom permissions |
|
||||
|
||||
### Favorite Jobs (`favorite_jobs`)
|
||||
- **id**: `INTEGER` (PK)
|
||||
- **user_id**: `INTEGER`
|
||||
- **job_id**: `INTEGER`
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | Primary key |
|
||||
| user_id | INTEGER | FK → users.id |
|
||||
| job_id | INTEGER | FK → jobs.id |
|
||||
|
||||
---
|
||||
|
||||
## Audit Tables
|
||||
|
||||
### Login Audits (`login_audits`)
|
||||
- **id**: `INTEGER` (PK)
|
||||
- **user_id**: `VARCHAR`
|
||||
- **identifier**: `VARCHAR`
|
||||
- **ip_address**, **user_agent**: Metadata
|
||||
- **created_at**: `TIMESTAMP`
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | Primary key |
|
||||
| user_id | VARCHAR | User identifier |
|
||||
| identifier | VARCHAR | Login identifier used |
|
||||
| ip_address | VARCHAR | Client IP |
|
||||
| user_agent | VARCHAR | Browser/client info |
|
||||
| created_at | TIMESTAMP | Login time |
|
||||
|
||||
### Password Resets (`password_resets`)
|
||||
- **id**: `INTEGER` (PK)
|
||||
- **user_id**: `INTEGER`
|
||||
- **token**: `VARCHAR`
|
||||
- **expires_at**: `TIMESTAMP`
|
||||
- **used**: `BOOLEAN`
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | Primary key |
|
||||
| user_id | INTEGER | FK → users.id |
|
||||
| token | VARCHAR | Reset token |
|
||||
| expires_at | TIMESTAMP | Token expiry |
|
||||
| used | BOOLEAN | Token used status |
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ export default function NewJobPage() {
|
|||
salaryMin: "",
|
||||
salaryMax: "",
|
||||
salaryType: "",
|
||||
currency: "BRL",
|
||||
workingHours: "",
|
||||
})
|
||||
|
||||
|
|
@ -89,6 +90,7 @@ export default function NewJobPage() {
|
|||
salaryMin: formData.salaryMin ? parseFloat(formData.salaryMin) : undefined,
|
||||
salaryMax: formData.salaryMax ? parseFloat(formData.salaryMax) : undefined,
|
||||
salaryType: formData.salaryType as CreateJobPayload['salaryType'] || undefined,
|
||||
currency: formData.currency as CreateJobPayload['currency'] || undefined,
|
||||
workingHours: formData.workingHours || undefined,
|
||||
status: "published",
|
||||
}
|
||||
|
|
@ -251,30 +253,51 @@ export default function NewJobPage() {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label>Salary Type</Label>
|
||||
<Label>Currency</Label>
|
||||
<Select value={formData.currency} onValueChange={(v) => updateField("currency", v)}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Currency" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="BRL">R$ (BRL)</SelectItem>
|
||||
<SelectItem value="USD">$ (USD)</SelectItem>
|
||||
<SelectItem value="EUR">€ (EUR)</SelectItem>
|
||||
<SelectItem value="GBP">£ (GBP)</SelectItem>
|
||||
<SelectItem value="JPY">¥ (JPY)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label>Salary Period</Label>
|
||||
<Select value={formData.salaryType} onValueChange={(v) => updateField("salaryType", v)}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select period" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="hourly">Per hour</SelectItem>
|
||||
<SelectItem value="daily">Per day</SelectItem>
|
||||
<SelectItem value="weekly">Per week</SelectItem>
|
||||
<SelectItem value="monthly">Per month</SelectItem>
|
||||
<SelectItem value="yearly">Per year</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label>Employment Type</Label>
|
||||
<Label>Contract Type</Label>
|
||||
<Select value={formData.employmentType} onValueChange={(v) => updateField("employmentType", v)}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select type" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="permanent">Permanent</SelectItem>
|
||||
<SelectItem value="full-time">Full-time</SelectItem>
|
||||
<SelectItem value="part-time">Part-time</SelectItem>
|
||||
<SelectItem value="contract">Contract</SelectItem>
|
||||
<SelectItem value="temporary">Temporary</SelectItem>
|
||||
<SelectItem value="training">Training</SelectItem>
|
||||
<SelectItem value="voluntary">Voluntary</SelectItem>
|
||||
<SelectItem value="dispatch">Dispatch</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
|
@ -348,7 +371,7 @@ export default function NewJobPage() {
|
|||
<p className="text-sm text-muted-foreground">Salary</p>
|
||||
<p className="font-medium">
|
||||
{formData.salaryMin || formData.salaryMax
|
||||
? `R$ ${formData.salaryMin || "?"} - R$ ${formData.salaryMax || "?"} ${formData.salaryType ? `(${formData.salaryType})` : ""}`
|
||||
? `${formData.currency} ${formData.salaryMin || "?"} - ${formData.salaryMax || "?"} ${formData.salaryType ? `(${formData.salaryType})` : ""}`
|
||||
: "-"}
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -290,8 +290,9 @@ export interface CreateJobPayload {
|
|||
description: string;
|
||||
salaryMin?: number;
|
||||
salaryMax?: number;
|
||||
salaryType?: 'hourly' | 'monthly' | 'yearly';
|
||||
employmentType?: 'full-time' | 'part-time' | 'dispatch' | 'contract';
|
||||
salaryType?: 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly';
|
||||
currency?: 'BRL' | 'USD' | 'EUR' | 'GBP' | 'JPY';
|
||||
employmentType?: 'full-time' | 'part-time' | 'dispatch' | 'contract' | 'temporary' | 'training' | 'voluntary' | 'permanent';
|
||||
workingHours?: string;
|
||||
location?: string;
|
||||
status: 'draft' | 'published' | 'open';
|
||||
|
|
|
|||
|
|
@ -93,15 +93,19 @@ export async function seedJobs() {
|
|||
const salaryMin = template.salaryRange[0] + getRandomInt(-2000, 2000);
|
||||
const salaryMax = template.salaryRange[1] + getRandomInt(-2000, 3000);
|
||||
|
||||
const employmentTypes = ['full-time', 'part-time', 'contract'];
|
||||
const employmentType = employmentTypes[i % employmentTypes.length]; // Deterministic variety
|
||||
const employmentTypes = ['full-time', 'part-time', 'contract', 'permanent', 'temporary', 'training'];
|
||||
const currencies = ['BRL', 'BRL', 'BRL', 'BRL', 'BRL', 'BRL', 'BRL', 'USD', 'USD', 'EUR']; // 70% BRL, 20% USD, 10% EUR
|
||||
const salaryTypes = ['hourly', 'daily', 'weekly', 'monthly', 'yearly'];
|
||||
const employmentType = employmentTypes[i % employmentTypes.length];
|
||||
const currency = currencies[i % currencies.length];
|
||||
const salaryType = salaryTypes[i % salaryTypes.length];
|
||||
const jobId = crypto.randomUUID();
|
||||
|
||||
await pool.query(`
|
||||
INSERT INTO jobs (id, company_id, created_by, title, description,
|
||||
salary_min, salary_max, salary_type, employment_type, working_hours,
|
||||
salary_min, salary_max, salary_type, currency, employment_type, working_hours,
|
||||
location, requirements, benefits, visa_support, language_level, status, work_mode)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)
|
||||
`, [
|
||||
jobId,
|
||||
company.id,
|
||||
|
|
@ -110,7 +114,8 @@ export async function seedJobs() {
|
|||
`We are looking for a talented ${title} to join our ${company.name} team. Your role as ${level} will be crucial.`,
|
||||
salaryMin,
|
||||
salaryMax,
|
||||
'monthly',
|
||||
salaryType,
|
||||
currency,
|
||||
employmentType,
|
||||
workMode === 'remote' ? 'Flexible' : '9:00-18:00',
|
||||
workMode === 'remote' ? 'Remote (Global)' : internationalLocations[i % internationalLocations.length],
|
||||
|
|
|
|||
Loading…
Reference in a new issue