feat(i18n): internationalize sidebar and dashboards
This commit is contained in:
parent
3e81ae40e7
commit
33e7bbb334
9 changed files with 508 additions and 268 deletions
|
|
@ -1,110 +0,0 @@
|
||||||
export const dashboardTranslations = {
|
|
||||||
pt: {
|
|
||||||
title: "Dashboard",
|
|
||||||
subtitle: "Visão geral do portal de vagas",
|
|
||||||
stats: {
|
|
||||||
activeJobs: "Vagas Ativas",
|
|
||||||
activeJobsDesc: "Total de vagas publicadas",
|
|
||||||
candidates: "Candidatos",
|
|
||||||
candidatesDesc: "Usuários registrados",
|
|
||||||
applications: "Candidaturas",
|
|
||||||
applicationsDesc: "Em andamento",
|
|
||||||
hiringRate: "Taxa de Contratação",
|
|
||||||
hiringRateDesc: "Candidaturas por vaga"
|
|
||||||
},
|
|
||||||
jobs: {
|
|
||||||
title: "Gerenciamento de Vagas",
|
|
||||||
add: "Nova Vaga",
|
|
||||||
table: {
|
|
||||||
title: "Título",
|
|
||||||
company: "Empresa",
|
|
||||||
status: "Status",
|
|
||||||
created: "Criado em",
|
|
||||||
actions: "Ações"
|
|
||||||
},
|
|
||||||
empty: "Nenhuma vaga encontrada."
|
|
||||||
},
|
|
||||||
candidates: {
|
|
||||||
title: "Gerenciamento de Candidatos",
|
|
||||||
table: {
|
|
||||||
name: "Nome",
|
|
||||||
email: "Email",
|
|
||||||
location: "Localização",
|
|
||||||
actions: "Ações"
|
|
||||||
},
|
|
||||||
empty: "Nenhum candidato encontrado."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
en: {
|
|
||||||
title: "Dashboard",
|
|
||||||
subtitle: "Overview of the jobs portal",
|
|
||||||
stats: {
|
|
||||||
activeJobs: "Active Jobs",
|
|
||||||
activeJobsDesc: "Total posted jobs",
|
|
||||||
candidates: "Total Candidates",
|
|
||||||
candidatesDesc: "Registered users",
|
|
||||||
applications: "Active Applications",
|
|
||||||
applicationsDesc: "Current pipeline",
|
|
||||||
hiringRate: "Hiring Rate",
|
|
||||||
hiringRateDesc: "Applications per job"
|
|
||||||
},
|
|
||||||
jobs: {
|
|
||||||
title: "Job Management",
|
|
||||||
add: "Add Job",
|
|
||||||
table: {
|
|
||||||
title: "Title",
|
|
||||||
company: "Company",
|
|
||||||
status: "Status",
|
|
||||||
created: "Created At",
|
|
||||||
actions: "Actions"
|
|
||||||
},
|
|
||||||
empty: "No jobs found."
|
|
||||||
},
|
|
||||||
candidates: {
|
|
||||||
title: "Candidate Management",
|
|
||||||
table: {
|
|
||||||
name: "Name",
|
|
||||||
email: "Email",
|
|
||||||
location: "Location",
|
|
||||||
actions: "Actions"
|
|
||||||
},
|
|
||||||
empty: "No candidates found."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
es: {
|
|
||||||
title: "Panel de Control",
|
|
||||||
subtitle: "Visión general del portal de empleos",
|
|
||||||
stats: {
|
|
||||||
activeJobs: "Empleos Activos",
|
|
||||||
activeJobsDesc: "Total publicados",
|
|
||||||
candidates: "Candidatos Total",
|
|
||||||
candidatesDesc: "Usuarios registrados",
|
|
||||||
applications: "Aplicaciones Activas",
|
|
||||||
applicationsDesc: "En proceso",
|
|
||||||
hiringRate: "Tasa de Contratación",
|
|
||||||
hiringRateDesc: "Aplicaciones por empleo"
|
|
||||||
},
|
|
||||||
jobs: {
|
|
||||||
title: "Gestión de Empleos",
|
|
||||||
add: "Nuevo Empleo",
|
|
||||||
table: {
|
|
||||||
title: "Título",
|
|
||||||
company: "Empresa",
|
|
||||||
status: "Estado",
|
|
||||||
created: "Creado en",
|
|
||||||
actions: "Acciones"
|
|
||||||
},
|
|
||||||
empty: "No se encontraron empleos."
|
|
||||||
},
|
|
||||||
candidates: {
|
|
||||||
title: "Gestión de Candidatos",
|
|
||||||
table: {
|
|
||||||
name: "Nombre",
|
|
||||||
email: "Correo",
|
|
||||||
location: "Ubicación",
|
|
||||||
actions: "Acciones"
|
|
||||||
},
|
|
||||||
empty: "No se encontraron candidatos."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -249,7 +249,7 @@ export default function AdminUsersPage() {
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl sm:text-3xl font-bold text-foreground">{t('admin.users.title')} (v2)</h1>
|
<h1 className="text-2xl sm:text-3xl font-bold text-foreground">{t('admin.users.title')}</h1>
|
||||||
<p className="text-sm sm:text-base text-muted-foreground mt-1">{t('admin.users.subtitle')}</p>
|
<p className="text-sm sm:text-base text-muted-foreground mt-1">{t('admin.users.subtitle')}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
|
|
|
||||||
|
|
@ -23,14 +23,12 @@ import { Briefcase, Users, TrendingUp, FileText, Plus, MoreHorizontal, Loader2 }
|
||||||
import { motion } from "framer-motion"
|
import { motion } from "framer-motion"
|
||||||
import { adminJobsApi, adminCandidatesApi, type AdminJob, type AdminCandidate, type AdminCandidateStats } from "@/lib/api"
|
import { adminJobsApi, adminCandidatesApi, type AdminJob, type AdminCandidate, type AdminCandidateStats } from "@/lib/api"
|
||||||
import { toast } from "sonner"
|
import { toast } from "sonner"
|
||||||
import { useLanguageStore } from "@/lib/store/language-store"
|
import { useTranslation } from "@/lib/i18n"
|
||||||
import { dashboardTranslations } from "@/app/dashboard/translations"
|
|
||||||
|
|
||||||
export function AdminDashboardContent() {
|
export function AdminDashboardContent() {
|
||||||
const [isDialogOpen, setIsDialogOpen] = useState(false)
|
const [isDialogOpen, setIsDialogOpen] = useState(false)
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
const { language } = useLanguageStore()
|
const { t } = useTranslation()
|
||||||
const t = dashboardTranslations[language]
|
|
||||||
|
|
||||||
const [stats, setStats] = useState({
|
const [stats, setStats] = useState({
|
||||||
activeJobs: 0,
|
activeJobs: 0,
|
||||||
|
|
@ -104,8 +102,8 @@ export function AdminDashboardContent() {
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 0.5 }}
|
transition={{ duration: 0.5 }}
|
||||||
>
|
>
|
||||||
<h1 className="text-3xl font-bold mb-2">{t.title}</h1>
|
<h1 className="text-3xl font-bold mb-2">{t('admin.dashboard.title')}</h1>
|
||||||
<p className="text-muted-foreground">{t.subtitle}</p>
|
<p className="text-muted-foreground">{t('admin.dashboard.subtitle')}</p>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Stats */}
|
{/* Stats */}
|
||||||
|
|
@ -116,28 +114,28 @@ export function AdminDashboardContent() {
|
||||||
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6"
|
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6"
|
||||||
>
|
>
|
||||||
<StatsCard
|
<StatsCard
|
||||||
title={t.stats.activeJobs}
|
title={t('admin.dashboard.stats.activeJobs')}
|
||||||
value={stats.activeJobs}
|
value={stats.activeJobs}
|
||||||
icon={Briefcase}
|
icon={Briefcase}
|
||||||
description={t.stats.activeJobsDesc}
|
description={t('admin.dashboard.stats.activeJobsDesc')}
|
||||||
/>
|
/>
|
||||||
<StatsCard
|
<StatsCard
|
||||||
title={t.stats.candidates}
|
title={t('admin.dashboard.stats.candidates')}
|
||||||
value={stats.totalCandidates}
|
value={stats.totalCandidates}
|
||||||
icon={Users}
|
icon={Users}
|
||||||
description={t.stats.candidatesDesc}
|
description={t('admin.dashboard.stats.candidatesDesc')}
|
||||||
/>
|
/>
|
||||||
<StatsCard
|
<StatsCard
|
||||||
title={t.stats.applications}
|
title={t('admin.dashboard.stats.applications')}
|
||||||
value={stats.newApplications}
|
value={stats.newApplications}
|
||||||
icon={FileText}
|
icon={FileText}
|
||||||
description={t.stats.applicationsDesc}
|
description={t('admin.dashboard.stats.applicationsDesc')}
|
||||||
/>
|
/>
|
||||||
<StatsCard
|
<StatsCard
|
||||||
title={t.stats.hiringRate}
|
title={t('admin.dashboard.stats.hiringRate')}
|
||||||
value={`${stats.conversionRate.toFixed(1)}%`}
|
value={`${stats.conversionRate.toFixed(1)}%`}
|
||||||
icon={TrendingUp}
|
icon={TrendingUp}
|
||||||
description={t.stats.hiringRateDesc}
|
description={t('admin.dashboard.stats.hiringRateDesc')}
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
|
|
@ -149,12 +147,12 @@ export function AdminDashboardContent() {
|
||||||
>
|
>
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader className="flex flex-row items-center justify-between">
|
<CardHeader className="flex flex-row items-center justify-between">
|
||||||
<CardTitle>{t.jobs.title}</CardTitle>
|
<CardTitle>{t('admin.dashboard.jobs.title')}</CardTitle>
|
||||||
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
|
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button>
|
<Button>
|
||||||
<Plus className="mr-2 h-4 w-4" />
|
<Plus className="mr-2 h-4 w-4" />
|
||||||
{t.jobs.add}
|
{t('admin.dashboard.jobs.add')}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className="max-w-2xl">
|
<DialogContent className="max-w-2xl">
|
||||||
|
|
@ -199,17 +197,17 @@ export function AdminDashboardContent() {
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>{t.jobs.table.title}</TableHead>
|
<TableHead>{t('admin.dashboard.jobs.table.title')}</TableHead>
|
||||||
<TableHead>{t.jobs.table.company}</TableHead>
|
<TableHead>{t('admin.dashboard.jobs.table.company')}</TableHead>
|
||||||
<TableHead>{t.jobs.table.status}</TableHead>
|
<TableHead>{t('admin.dashboard.jobs.table.status')}</TableHead>
|
||||||
<TableHead>{t.jobs.table.created}</TableHead>
|
<TableHead>{t('admin.dashboard.jobs.table.created')}</TableHead>
|
||||||
<TableHead className="text-right">{t.jobs.table.actions}</TableHead>
|
<TableHead className="text-right">{t('admin.dashboard.jobs.table.actions')}</TableHead>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{recentJobs.length === 0 ? (
|
{recentJobs.length === 0 ? (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={5} className="text-center text-muted-foreground">{t.jobs.empty}</TableCell>
|
<TableCell colSpan={5} className="text-center text-muted-foreground">{t('admin.dashboard.jobs.empty')}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
) : (
|
) : (
|
||||||
recentJobs.map((job) => (
|
recentJobs.map((job) => (
|
||||||
|
|
@ -242,22 +240,22 @@ export function AdminDashboardContent() {
|
||||||
>
|
>
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>{t.candidates.title}</CardTitle>
|
<CardTitle>{t('admin.dashboard.candidates.title')}</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>{t.candidates.table.name}</TableHead>
|
<TableHead>{t('admin.dashboard.candidates.table.name')}</TableHead>
|
||||||
<TableHead>{t.candidates.table.email}</TableHead>
|
<TableHead>{t('admin.dashboard.candidates.table.email')}</TableHead>
|
||||||
<TableHead>{t.candidates.table.location}</TableHead>
|
<TableHead>{t('admin.dashboard.candidates.table.location')}</TableHead>
|
||||||
<TableHead className="text-right">{t.candidates.table.actions}</TableHead>
|
<TableHead className="text-right">{t('admin.dashboard.candidates.table.actions')}</TableHead>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{recentCandidates.length === 0 ? (
|
{recentCandidates.length === 0 ? (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={4} className="text-center text-muted-foreground">No candidates found.</TableCell>
|
<TableCell colSpan={4} className="text-center text-muted-foreground">{t('admin.dashboard.candidates.empty')}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
) : (
|
) : (
|
||||||
recentCandidates.map((candidate) => (
|
recentCandidates.map((candidate) => (
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,10 @@ import {
|
||||||
} from "lucide-react"
|
} from "lucide-react"
|
||||||
import { motion } from "framer-motion"
|
import { motion } from "framer-motion"
|
||||||
import { getCurrentUser } from "@/lib/auth"
|
import { getCurrentUser } from "@/lib/auth"
|
||||||
|
import { useTranslation } from "@/lib/i18n"
|
||||||
|
|
||||||
export function CandidateDashboardContent() {
|
export function CandidateDashboardContent() {
|
||||||
|
const { t } = useTranslation()
|
||||||
const user = getCurrentUser()
|
const user = getCurrentUser()
|
||||||
const recommendedJobs = mockJobs.slice(0, 3)
|
const recommendedJobs = mockJobs.slice(0, 3)
|
||||||
const unreadNotifications = mockNotifications.filter((n) => !n.read)
|
const unreadNotifications = mockNotifications.filter((n) => !n.read)
|
||||||
|
|
@ -37,35 +39,35 @@ export function CandidateDashboardContent() {
|
||||||
return (
|
return (
|
||||||
<Badge variant="secondary">
|
<Badge variant="secondary">
|
||||||
<Clock className="h-3 w-3 mr-1" />
|
<Clock className="h-3 w-3 mr-1" />
|
||||||
Under review
|
{t('candidate.dashboard.status.under_review')}
|
||||||
</Badge>
|
</Badge>
|
||||||
)
|
)
|
||||||
case "reviewing":
|
case "reviewing":
|
||||||
return (
|
return (
|
||||||
<Badge variant="secondary">
|
<Badge variant="secondary">
|
||||||
<AlertCircle className="h-3 w-3 mr-1" />
|
<AlertCircle className="h-3 w-3 mr-1" />
|
||||||
Under review
|
{t('candidate.dashboard.status.under_review')}
|
||||||
</Badge>
|
</Badge>
|
||||||
)
|
)
|
||||||
case "interview":
|
case "interview":
|
||||||
return (
|
return (
|
||||||
<Badge className="bg-blue-500 hover:bg-blue-600">
|
<Badge className="bg-blue-500 hover:bg-blue-600">
|
||||||
<CheckCircle className="h-3 w-3 mr-1" />
|
<CheckCircle className="h-3 w-3 mr-1" />
|
||||||
Interview
|
{t('candidate.dashboard.status.interview')}
|
||||||
</Badge>
|
</Badge>
|
||||||
)
|
)
|
||||||
case "accepted":
|
case "accepted":
|
||||||
return (
|
return (
|
||||||
<Badge className="bg-green-500 hover:bg-green-600">
|
<Badge className="bg-green-500 hover:bg-green-600">
|
||||||
<CheckCircle className="h-3 w-3 mr-1" />
|
<CheckCircle className="h-3 w-3 mr-1" />
|
||||||
Accepted
|
{t('candidate.dashboard.status.accepted')}
|
||||||
</Badge>
|
</Badge>
|
||||||
)
|
)
|
||||||
case "rejected":
|
case "rejected":
|
||||||
return (
|
return (
|
||||||
<Badge variant="destructive">
|
<Badge variant="destructive">
|
||||||
<XCircle className="h-3 w-3 mr-1" />
|
<XCircle className="h-3 w-3 mr-1" />
|
||||||
Rejected
|
{t('candidate.dashboard.status.rejected')}
|
||||||
</Badge>
|
</Badge>
|
||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
|
|
@ -85,12 +87,12 @@ export function CandidateDashboardContent() {
|
||||||
<CardContent className="pt-6">
|
<CardContent className="pt-6">
|
||||||
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-6">
|
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-6">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h1 className="text-2xl font-bold mb-2">Hi, {user?.name || "Candidate"}!</h1>
|
<h1 className="text-2xl font-bold mb-2">{t('candidate.dashboard.welcome', { name: user?.name || "Candidate" })}</h1>
|
||||||
<p className="text-muted-foreground">{user?.area || "Engineering"}</p>
|
<p className="text-muted-foreground">{user?.area || "Engineering"}</p>
|
||||||
</div>
|
</div>
|
||||||
<Button className="cursor-pointer">
|
<Button className="cursor-pointer">
|
||||||
<Edit className="mr-2 h-4 w-4" />
|
<Edit className="mr-2 h-4 w-4" />
|
||||||
Edit profile
|
{t('candidate.dashboard.edit_profile')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|
@ -105,26 +107,26 @@ export function CandidateDashboardContent() {
|
||||||
className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8"
|
className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8"
|
||||||
>
|
>
|
||||||
<StatsCard
|
<StatsCard
|
||||||
title="Applications"
|
title={t('candidate.dashboard.stats.applications')}
|
||||||
value={mockApplications.length}
|
value={mockApplications.length}
|
||||||
icon={FileText}
|
icon={FileText}
|
||||||
description="Total jobs applied to"
|
description={t('candidate.dashboard.stats.applications_desc')}
|
||||||
/>
|
/>
|
||||||
<StatsCard
|
<StatsCard
|
||||||
title="In progress"
|
title={t('candidate.dashboard.stats.in_progress')}
|
||||||
value={
|
value={
|
||||||
mockApplications.filter(
|
mockApplications.filter(
|
||||||
(a) => a.status === "reviewing" || a.status === "interview"
|
(a) => a.status === "reviewing" || a.status === "interview"
|
||||||
).length
|
).length
|
||||||
}
|
}
|
||||||
icon={Clock}
|
icon={Clock}
|
||||||
description="Awaiting a response"
|
description={t('candidate.dashboard.stats.in_progress_desc')}
|
||||||
/>
|
/>
|
||||||
<StatsCard
|
<StatsCard
|
||||||
title="Notifications"
|
title={t('candidate.dashboard.stats.notifications')}
|
||||||
value={unreadNotifications.length}
|
value={unreadNotifications.length}
|
||||||
icon={Bell}
|
icon={Bell}
|
||||||
description="New updates"
|
description={t('candidate.dashboard.stats.notifications_desc')}
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
|
|
@ -139,7 +141,7 @@ export function CandidateDashboardContent() {
|
||||||
>
|
>
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Recommended jobs</CardTitle>
|
<CardTitle>{t('candidate.dashboard.recommended.title')}</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-4">
|
<CardContent className="space-y-4">
|
||||||
{recommendedJobs.map((job) => (
|
{recommendedJobs.map((job) => (
|
||||||
|
|
@ -157,16 +159,16 @@ export function CandidateDashboardContent() {
|
||||||
>
|
>
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>My applications</CardTitle>
|
<CardTitle>{t('candidate.dashboard.applications.title')}</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>Role</TableHead>
|
<TableHead>{t('candidate.dashboard.applications.table.role')}</TableHead>
|
||||||
<TableHead>Company</TableHead>
|
<TableHead>{t('candidate.dashboard.applications.table.company')}</TableHead>
|
||||||
<TableHead>Status</TableHead>
|
<TableHead>{t('candidate.dashboard.applications.table.status')}</TableHead>
|
||||||
<TableHead>Date</TableHead>
|
<TableHead>{t('candidate.dashboard.applications.table.date')}</TableHead>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,14 @@ import { jobsApi, applicationsApi, ApiJob } from "@/lib/api"
|
||||||
import { User } from "@/lib/auth"
|
import { User } from "@/lib/auth"
|
||||||
import { formatDistanceToNow } from "date-fns"
|
import { formatDistanceToNow } from "date-fns"
|
||||||
import { ptBR } from "date-fns/locale"
|
import { ptBR } from "date-fns/locale"
|
||||||
|
import { useTranslation } from "@/lib/i18n"
|
||||||
|
|
||||||
interface CompanyDashboardContentProps {
|
interface CompanyDashboardContentProps {
|
||||||
user: User
|
user: User
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CompanyDashboardContent({ user }: CompanyDashboardContentProps) {
|
export function CompanyDashboardContent({ user }: CompanyDashboardContentProps) {
|
||||||
|
const { t } = useTranslation()
|
||||||
const [stats, setStats] = useState({
|
const [stats, setStats] = useState({
|
||||||
activeJobs: 0,
|
activeJobs: 0,
|
||||||
totalApplications: 0,
|
totalApplications: 0,
|
||||||
|
|
@ -102,16 +104,16 @@ export function CompanyDashboardContent({ user }: CompanyDashboardContentProps)
|
||||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl sm:text-3xl font-bold text-foreground mb-2">
|
<h1 className="text-2xl sm:text-3xl font-bold text-foreground mb-2">
|
||||||
Dashboard
|
{t('company.dashboard.title')}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-muted-foreground">
|
<p className="text-muted-foreground">
|
||||||
Olá, {user.name}! 👋
|
{t('company.dashboard.welcome', { name: user.name })} 👋
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Link href="/dashboard/my-jobs">
|
<Link href="/dashboard/my-jobs">
|
||||||
<Button size="lg" className="w-full sm:w-auto">
|
<Button size="lg" className="w-full sm:w-auto">
|
||||||
<Plus className="h-5 w-5 mr-2" />
|
<Plus className="h-5 w-5 mr-2" />
|
||||||
Nova Vaga
|
{t('company.dashboard.new_job')}
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -121,7 +123,7 @@ export function CompanyDashboardContent({ user }: CompanyDashboardContentProps)
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium">
|
<CardTitle className="text-sm font-medium">
|
||||||
Vagas Ativas
|
{t('company.dashboard.stats.active_jobs')}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<Briefcase className="h-4 w-4 text-muted-foreground" />
|
<Briefcase className="h-4 w-4 text-muted-foreground" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
@ -130,7 +132,7 @@ export function CompanyDashboardContent({ user }: CompanyDashboardContentProps)
|
||||||
{stats.activeJobs}
|
{stats.activeJobs}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-muted-foreground mt-1">
|
<p className="text-xs text-muted-foreground mt-1">
|
||||||
Publicadas
|
{t('company.dashboard.stats.posted')}
|
||||||
</p>
|
</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -138,7 +140,7 @@ export function CompanyDashboardContent({ user }: CompanyDashboardContentProps)
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium">
|
<CardTitle className="text-sm font-medium">
|
||||||
Candidaturas
|
{t('company.dashboard.stats.applications')}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<Users className="h-4 w-4 text-muted-foreground" />
|
<Users className="h-4 w-4 text-muted-foreground" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
@ -147,7 +149,7 @@ export function CompanyDashboardContent({ user }: CompanyDashboardContentProps)
|
||||||
{stats.totalApplications}
|
{stats.totalApplications}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-muted-foreground mt-1">
|
<p className="text-xs text-muted-foreground mt-1">
|
||||||
+{stats.thisMonth} este mês
|
{t('company.dashboard.stats.this_month', { count: stats.thisMonth })}
|
||||||
</p>
|
</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -155,7 +157,7 @@ export function CompanyDashboardContent({ user }: CompanyDashboardContentProps)
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium">
|
<CardTitle className="text-sm font-medium">
|
||||||
Visualizações
|
{t('company.dashboard.stats.views')}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<Eye className="h-4 w-4 text-muted-foreground" />
|
<Eye className="h-4 w-4 text-muted-foreground" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
@ -164,7 +166,7 @@ export function CompanyDashboardContent({ user }: CompanyDashboardContentProps)
|
||||||
-
|
-
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-muted-foreground mt-1">
|
<p className="text-xs text-muted-foreground mt-1">
|
||||||
Em breve
|
{t('company.dashboard.stats.soon')}
|
||||||
</p>
|
</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -172,14 +174,14 @@ export function CompanyDashboardContent({ user }: CompanyDashboardContentProps)
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium">
|
<CardTitle className="text-sm font-medium">
|
||||||
Conversão
|
{t('company.dashboard.stats.conversion')}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<TrendingUp className="h-4 w-4 text-muted-foreground" />
|
<TrendingUp className="h-4 w-4 text-muted-foreground" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">-</div>
|
<div className="text-2xl font-bold">-</div>
|
||||||
<p className="text-xs text-muted-foreground mt-1">
|
<p className="text-xs text-muted-foreground mt-1">
|
||||||
Em breve
|
{t('company.dashboard.stats.soon')}
|
||||||
</p>
|
</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -192,21 +194,21 @@ export function CompanyDashboardContent({ user }: CompanyDashboardContentProps)
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<CardTitle>Vagas Recentes</CardTitle>
|
<CardTitle>{t('company.dashboard.recent_jobs.title')}</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
Suas últimas vagas publicadas
|
{t('company.dashboard.recent_jobs.subtitle')}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</div>
|
</div>
|
||||||
<Link href="/dashboard/my-jobs">
|
<Link href="/dashboard/my-jobs">
|
||||||
<Button variant="ghost" size="sm">
|
<Button variant="ghost" size="sm">
|
||||||
Ver todas
|
{t('company.dashboard.recent_jobs.view_all')}
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-4">
|
<CardContent className="space-y-4">
|
||||||
{recentJobs.length === 0 ? (
|
{recentJobs.length === 0 ? (
|
||||||
<p className="text-muted-foreground text-sm">Nenhuma vaga encontrada.</p>
|
<p className="text-muted-foreground text-sm">{t('company.dashboard.recent_jobs.empty')}</p>
|
||||||
) : recentJobs.map((job) => (
|
) : recentJobs.map((job) => (
|
||||||
<div
|
<div
|
||||||
key={job.id}
|
key={job.id}
|
||||||
|
|
@ -239,7 +241,7 @@ export function CompanyDashboardContent({ user }: CompanyDashboardContentProps)
|
||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1">
|
||||||
<Users className="h-4 w-4" />
|
<Users className="h-4 w-4" />
|
||||||
{/* Mocking app count if not available */}
|
{/* Mocking app count if not available */}
|
||||||
{job.applicationCount || 0} applications
|
{t('company.dashboard.recent_jobs.applications_count', { count: job.applicationCount || 0 })}
|
||||||
</span>
|
</span>
|
||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1">
|
||||||
<Calendar className="h-4 w-4" />
|
<Calendar className="h-4 w-4" />
|
||||||
|
|
@ -267,19 +269,19 @@ export function CompanyDashboardContent({ user }: CompanyDashboardContentProps)
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<CardTitle>Candidaturas</CardTitle>
|
<CardTitle>{t('company.dashboard.recent_applications.title')}</CardTitle>
|
||||||
<CardDescription>Candidatos recentes</CardDescription>
|
<CardDescription>{t('company.dashboard.recent_applications.subtitle')}</CardDescription>
|
||||||
</div>
|
</div>
|
||||||
<Link href="/dashboard/candidates">
|
<Link href="/dashboard/candidates">
|
||||||
<Button variant="ghost" size="sm">
|
<Button variant="ghost" size="sm">
|
||||||
Ver todas
|
{t('company.dashboard.recent_applications.view_all')}
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-4">
|
<CardContent className="space-y-4">
|
||||||
{recentApplications.length === 0 ? (
|
{recentApplications.length === 0 ? (
|
||||||
<p className="text-muted-foreground text-sm">Nenhuma candidatura recente.</p>
|
<p className="text-muted-foreground text-sm">{t('company.dashboard.recent_applications.empty')}</p>
|
||||||
) : recentApplications.map((application) => (
|
) : recentApplications.map((application) => (
|
||||||
<div
|
<div
|
||||||
key={application.id}
|
key={application.id}
|
||||||
|
|
@ -308,7 +310,7 @@ export function CompanyDashboardContent({ user }: CompanyDashboardContentProps)
|
||||||
{application.name}
|
{application.name}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs text-muted-foreground truncate">
|
<p className="text-xs text-muted-foreground truncate">
|
||||||
{application.jobTitle || "Vaga desconhecida"}
|
{application.jobTitle || t('company.dashboard.recent_applications.unknown_job')}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs text-muted-foreground mt-1">
|
<p className="text-xs text-muted-foreground mt-1">
|
||||||
{formatDistanceToNow(new Date(application.created_at), { addSuffix: true, locale: ptBR })}
|
{formatDistanceToNow(new Date(application.created_at), { addSuffix: true, locale: ptBR })}
|
||||||
|
|
|
||||||
|
|
@ -6,99 +6,110 @@ import { usePathname } from "next/navigation"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { LayoutDashboard, Briefcase, Users, MessageSquare, Building2, FileText, HelpCircle, Ticket } from "lucide-react"
|
import { LayoutDashboard, Briefcase, Users, MessageSquare, Building2, FileText, HelpCircle, Ticket } from "lucide-react"
|
||||||
import { getCurrentUser, isAdminUser } from "@/lib/auth"
|
import { getCurrentUser, isAdminUser } from "@/lib/auth"
|
||||||
|
import { useTranslation } from "@/lib/i18n"
|
||||||
|
|
||||||
const adminItems = [
|
const Sidebar = () => {
|
||||||
{
|
const { t } = useTranslation()
|
||||||
title: "Dashboard",
|
|
||||||
href: "/dashboard",
|
|
||||||
icon: LayoutDashboard,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Jobs",
|
|
||||||
href: "/dashboard/jobs",
|
|
||||||
icon: Briefcase,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Candidates",
|
|
||||||
href: "/dashboard/candidates",
|
|
||||||
icon: Users,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Users",
|
|
||||||
href: "/dashboard/users",
|
|
||||||
icon: Users,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Companies",
|
|
||||||
href: "/dashboard/companies",
|
|
||||||
icon: Building2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Backoffice",
|
|
||||||
href: "/dashboard/backoffice",
|
|
||||||
icon: FileText,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Messages",
|
|
||||||
href: "/dashboard/messages",
|
|
||||||
icon: MessageSquare,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Tickets",
|
|
||||||
href: "/dashboard/tickets",
|
|
||||||
icon: Ticket,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const companyItems = [
|
|
||||||
{
|
|
||||||
title: "Dashboard",
|
|
||||||
href: "/dashboard",
|
|
||||||
icon: LayoutDashboard,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "My jobs",
|
|
||||||
href: "/dashboard/my-jobs",
|
|
||||||
icon: Briefcase,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Applications",
|
|
||||||
href: "/dashboard/applications",
|
|
||||||
icon: Users,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const candidateItems = [
|
|
||||||
{
|
|
||||||
title: "Dashboard",
|
|
||||||
href: "/dashboard",
|
|
||||||
icon: LayoutDashboard,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Jobs",
|
|
||||||
href: "/jobs", // Public search
|
|
||||||
icon: Briefcase,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "My applications",
|
|
||||||
href: "/dashboard/my-applications",
|
|
||||||
icon: FileText,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Support",
|
|
||||||
href: "/dashboard/support/tickets",
|
|
||||||
icon: HelpCircle,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
export function Sidebar() {
|
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
const user = getCurrentUser()
|
const user = getCurrentUser()
|
||||||
const isSuperadmin = user?.role === "superadmin"
|
const isSuperadmin = user?.role === "superadmin"
|
||||||
|
|
||||||
|
const adminItems = [
|
||||||
|
{
|
||||||
|
title: t('sidebar.dashboard'),
|
||||||
|
href: "/dashboard",
|
||||||
|
icon: LayoutDashboard,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('sidebar.jobs'),
|
||||||
|
href: "/dashboard/jobs",
|
||||||
|
icon: Briefcase,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('sidebar.candidates'),
|
||||||
|
href: "/dashboard/candidates",
|
||||||
|
icon: Users,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('sidebar.users'),
|
||||||
|
href: "/dashboard/users",
|
||||||
|
icon: Users,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('sidebar.companies'),
|
||||||
|
href: "/dashboard/companies",
|
||||||
|
icon: Building2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('sidebar.backoffice'),
|
||||||
|
href: "/dashboard/backoffice",
|
||||||
|
icon: FileText,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('sidebar.messages'),
|
||||||
|
href: "/dashboard/messages",
|
||||||
|
icon: MessageSquare,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('sidebar.tickets'),
|
||||||
|
href: "/dashboard/tickets",
|
||||||
|
icon: Ticket,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const companyItems = [
|
||||||
|
{
|
||||||
|
title: t('sidebar.dashboard'),
|
||||||
|
href: "/dashboard",
|
||||||
|
icon: LayoutDashboard,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('sidebar.my_jobs'),
|
||||||
|
href: "/dashboard/my-jobs",
|
||||||
|
icon: Briefcase,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('sidebar.applications'),
|
||||||
|
href: "/dashboard/applications",
|
||||||
|
icon: Users,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('sidebar.messages'),
|
||||||
|
href: "/dashboard/messages",
|
||||||
|
icon: MessageSquare,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('sidebar.support'),
|
||||||
|
href: "/dashboard/support",
|
||||||
|
icon: HelpCircle,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const candidateItems = [
|
||||||
|
{
|
||||||
|
title: t('sidebar.dashboard'),
|
||||||
|
href: "/dashboard",
|
||||||
|
icon: LayoutDashboard,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('sidebar.jobs'),
|
||||||
|
href: "/jobs",
|
||||||
|
icon: Briefcase,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('sidebar.my_applications'),
|
||||||
|
href: "/dashboard/my-applications",
|
||||||
|
icon: FileText,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('sidebar.support'),
|
||||||
|
href: "/dashboard/support/tickets",
|
||||||
|
icon: HelpCircle,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
let items = candidateItems
|
let items = candidateItems
|
||||||
if (isAdminUser(user)) {
|
if (isAdminUser(user)) {
|
||||||
// For Admin (not Superadmin), filter out Backoffice
|
|
||||||
items = isSuperadmin
|
items = isSuperadmin
|
||||||
? adminItems
|
? adminItems
|
||||||
: adminItems.filter(item => item.href !== "/dashboard/backoffice" && item.href !== "/dashboard/companies")
|
: adminItems.filter(item => item.href !== "/dashboard/backoffice" && item.href !== "/dashboard/companies")
|
||||||
|
|
@ -108,7 +119,6 @@ export function Sidebar() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className="w-64 shrink-0 border-r border-border bg-muted/30 min-h-screen flex flex-col">
|
<aside className="w-64 shrink-0 border-r border-border bg-muted/30 min-h-screen flex flex-col">
|
||||||
{/* Branding Header with CORRECT Padding (pl-6) */}
|
|
||||||
<div className="flex h-16 shrink-0 items-center px-6 gap-3 border-b border-border">
|
<div className="flex h-16 shrink-0 items-center px-6 gap-3 border-b border-border">
|
||||||
<Link href="/" className="flex items-center gap-3 hover:opacity-80 transition-opacity">
|
<Link href="/" className="flex items-center gap-3 hover:opacity-80 transition-opacity">
|
||||||
<Image
|
<Image
|
||||||
|
|
@ -122,7 +132,6 @@ export function Sidebar() {
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Navigation */}
|
|
||||||
<nav className="flex-1 p-4 space-y-2 overflow-y-auto">
|
<nav className="flex-1 p-4 space-y-2 overflow-y-auto">
|
||||||
{items.map((item) => {
|
{items.map((item) => {
|
||||||
const Icon = item.icon
|
const Icon = item.icon
|
||||||
|
|
@ -146,7 +155,6 @@ export function Sidebar() {
|
||||||
})}
|
})}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
{/* Footer / User Info could go here */}
|
|
||||||
<div className="p-4 border-t border-border mt-auto">
|
<div className="p-4 border-t border-border mt-auto">
|
||||||
<div className="text-xs text-muted-foreground text-center">
|
<div className="text-xs text-muted-foreground text-center">
|
||||||
v1.0.0
|
v1.0.0
|
||||||
|
|
@ -155,3 +163,6 @@ export function Sidebar() {
|
||||||
</aside>
|
</aside>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { Sidebar }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,18 @@
|
||||||
{
|
{
|
||||||
|
"sidebar": {
|
||||||
|
"dashboard": "Dashboard",
|
||||||
|
"jobs": "Jobs",
|
||||||
|
"candidates": "Candidates",
|
||||||
|
"users": "Users",
|
||||||
|
"companies": "Companies",
|
||||||
|
"backoffice": "Backoffice",
|
||||||
|
"messages": "Messages",
|
||||||
|
"tickets": "Tickets",
|
||||||
|
"my_jobs": "My Jobs",
|
||||||
|
"applications": "Applications",
|
||||||
|
"my_applications": "My Applications",
|
||||||
|
"support": "Support"
|
||||||
|
},
|
||||||
"nav": {
|
"nav": {
|
||||||
"jobs": "Jobs",
|
"jobs": "Jobs",
|
||||||
"about": "About",
|
"about": "About",
|
||||||
|
|
@ -662,6 +676,42 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
|
"dashboard": {
|
||||||
|
"title": "Dashboard",
|
||||||
|
"subtitle": "Overview of the jobs portal",
|
||||||
|
"stats": {
|
||||||
|
"activeJobs": "Active Jobs",
|
||||||
|
"activeJobsDesc": "Total posted jobs",
|
||||||
|
"candidates": "Total Candidates",
|
||||||
|
"candidatesDesc": "Registered users",
|
||||||
|
"applications": "Active Applications",
|
||||||
|
"applicationsDesc": "Current pipeline",
|
||||||
|
"hiringRate": "Hiring Rate",
|
||||||
|
"hiringRateDesc": "Applications per job"
|
||||||
|
},
|
||||||
|
"jobs": {
|
||||||
|
"title": "Job Management",
|
||||||
|
"add": "Add Job",
|
||||||
|
"table": {
|
||||||
|
"title": "Title",
|
||||||
|
"company": "Company",
|
||||||
|
"status": "Status",
|
||||||
|
"created": "Created At",
|
||||||
|
"actions": "Actions"
|
||||||
|
},
|
||||||
|
"empty": "No jobs found."
|
||||||
|
},
|
||||||
|
"candidates": {
|
||||||
|
"title": "Candidate Management",
|
||||||
|
"table": {
|
||||||
|
"name": "Name",
|
||||||
|
"email": "Email",
|
||||||
|
"location": "Location",
|
||||||
|
"actions": "Actions"
|
||||||
|
},
|
||||||
|
"empty": "No candidates found."
|
||||||
|
}
|
||||||
|
},
|
||||||
"users": {
|
"users": {
|
||||||
"title": "User management",
|
"title": "User management",
|
||||||
"subtitle": "Manage all platform users",
|
"subtitle": "Manage all platform users",
|
||||||
|
|
@ -718,5 +768,67 @@
|
||||||
"load_error": "Failed to load users"
|
"load_error": "Failed to load users"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"company": {
|
||||||
|
"dashboard": {
|
||||||
|
"title": "Dashboard",
|
||||||
|
"welcome": "Hello, {name}!",
|
||||||
|
"new_job": "New Job",
|
||||||
|
"stats": {
|
||||||
|
"active_jobs": "Active Jobs",
|
||||||
|
"posted": "Posted",
|
||||||
|
"applications": "Applications",
|
||||||
|
"this_month": "+{count} this month",
|
||||||
|
"views": "Views",
|
||||||
|
"conversion": "Conversion",
|
||||||
|
"soon": "Coming soon"
|
||||||
|
},
|
||||||
|
"recent_jobs": {
|
||||||
|
"title": "Recent Jobs",
|
||||||
|
"subtitle": "Your latest posted jobs",
|
||||||
|
"view_all": "View all",
|
||||||
|
"empty": "No jobs found.",
|
||||||
|
"applications_count": "{count} applications"
|
||||||
|
},
|
||||||
|
"recent_applications": {
|
||||||
|
"title": "Applications",
|
||||||
|
"subtitle": "Recent candidates",
|
||||||
|
"view_all": "View all",
|
||||||
|
"empty": "No recent applications.",
|
||||||
|
"unknown_job": "Unknown job"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"candidate": {
|
||||||
|
"dashboard": {
|
||||||
|
"welcome": "Hi, {name}!",
|
||||||
|
"edit_profile": "Edit profile",
|
||||||
|
"stats": {
|
||||||
|
"applications": "Applications",
|
||||||
|
"applications_desc": "Total jobs applied to",
|
||||||
|
"in_progress": "In progress",
|
||||||
|
"in_progress_desc": "Awaiting a response",
|
||||||
|
"notifications": "Notifications",
|
||||||
|
"notifications_desc": "New updates"
|
||||||
|
},
|
||||||
|
"recommended": {
|
||||||
|
"title": "Recommended jobs"
|
||||||
|
},
|
||||||
|
"applications": {
|
||||||
|
"title": "My applications",
|
||||||
|
"table": {
|
||||||
|
"role": "Role",
|
||||||
|
"company": "Company",
|
||||||
|
"status": "Status",
|
||||||
|
"date": "Date"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"under_review": "Under review",
|
||||||
|
"interview": "Interview",
|
||||||
|
"accepted": "Accepted",
|
||||||
|
"rejected": "Rejected"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,18 @@
|
||||||
{
|
{
|
||||||
|
"sidebar": {
|
||||||
|
"dashboard": "Panel de Control",
|
||||||
|
"jobs": "Empleos",
|
||||||
|
"candidates": "Candidatos",
|
||||||
|
"users": "Usuarios",
|
||||||
|
"companies": "Empresas",
|
||||||
|
"backoffice": "Backoffice",
|
||||||
|
"messages": "Mensajes",
|
||||||
|
"tickets": "Tickets",
|
||||||
|
"my_jobs": "Mis Empleos",
|
||||||
|
"applications": "Postulaciones",
|
||||||
|
"my_applications": "Mis Postulaciones",
|
||||||
|
"support": "Soporte"
|
||||||
|
},
|
||||||
"nav": {
|
"nav": {
|
||||||
"jobs": "Empleos",
|
"jobs": "Empleos",
|
||||||
"about": "Sobre",
|
"about": "Sobre",
|
||||||
|
|
@ -662,6 +676,43 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
|
"dashboard": {
|
||||||
|
"title": "Panel de Control",
|
||||||
|
"subtitle": "Visión general del portal de empleos",
|
||||||
|
"stats": {
|
||||||
|
"activeJobs": "Empleos Activos",
|
||||||
|
"activeJobsDesc": "Total publicados",
|
||||||
|
"candidates": "Candidatos Total",
|
||||||
|
"candidatesDesc": "Usuarios registrados",
|
||||||
|
"applications": "Aplicaciones Activas",
|
||||||
|
"applicationsDesc": "En proceso",
|
||||||
|
"hiringRate": "Tasa de Contratación",
|
||||||
|
"hiringRateDesc": "Aplicaciones por empleo"
|
||||||
|
},
|
||||||
|
"jobs": {
|
||||||
|
"title": "Gestión de Empleos",
|
||||||
|
"add": "Nuevo Empleo",
|
||||||
|
"table": {
|
||||||
|
"title": "Título",
|
||||||
|
"company": "Empresa",
|
||||||
|
"status": "Estado",
|
||||||
|
"created": "Creado en",
|
||||||
|
"actions": "Acciones"
|
||||||
|
},
|
||||||
|
"empty": "No se encontraron empleos."
|
||||||
|
},
|
||||||
|
"candidates": {
|
||||||
|
"title": "Gestión de Candidatos",
|
||||||
|
"table": {
|
||||||
|
"title": "Nombre",
|
||||||
|
"name": "Nombre",
|
||||||
|
"email": "Correo",
|
||||||
|
"location": "Ubicación",
|
||||||
|
"actions": "Acciones"
|
||||||
|
},
|
||||||
|
"empty": "No se encontraron candidatos."
|
||||||
|
}
|
||||||
|
},
|
||||||
"users": {
|
"users": {
|
||||||
"title": "Gestión de Usuarios",
|
"title": "Gestión de Usuarios",
|
||||||
"subtitle": "Gestione todos los usuarios de la plataforma",
|
"subtitle": "Gestione todos los usuarios de la plataforma",
|
||||||
|
|
@ -718,5 +769,67 @@
|
||||||
"load_error": "Error al cargar usuarios"
|
"load_error": "Error al cargar usuarios"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"company": {
|
||||||
|
"dashboard": {
|
||||||
|
"title": "Panel de Control",
|
||||||
|
"welcome": "¡Hola, {name}!",
|
||||||
|
"new_job": "Nuevo Empleo",
|
||||||
|
"stats": {
|
||||||
|
"active_jobs": "Empleos Activos",
|
||||||
|
"posted": "Publicados",
|
||||||
|
"applications": "Postulaciones",
|
||||||
|
"this_month": "+{count} este mes",
|
||||||
|
"views": "Vistas",
|
||||||
|
"conversion": "Conversión",
|
||||||
|
"soon": "Próximamente"
|
||||||
|
},
|
||||||
|
"recent_jobs": {
|
||||||
|
"title": "Empleos Recientes",
|
||||||
|
"subtitle": "Tus últimos empleos publicados",
|
||||||
|
"view_all": "Ver todos",
|
||||||
|
"empty": "No se encontraron empleos.",
|
||||||
|
"applications_count": "{count} postulaciones"
|
||||||
|
},
|
||||||
|
"recent_applications": {
|
||||||
|
"title": "Postulaciones",
|
||||||
|
"subtitle": "Candidatos recientes",
|
||||||
|
"view_all": "Ver todas",
|
||||||
|
"empty": "No hay postulaciones recientes.",
|
||||||
|
"unknown_job": "Empleo desconocido"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"candidate": {
|
||||||
|
"dashboard": {
|
||||||
|
"welcome": "¡Hola, {name}!",
|
||||||
|
"edit_profile": "Editar perfil",
|
||||||
|
"stats": {
|
||||||
|
"applications": "Postulaciones",
|
||||||
|
"applications_desc": "Total de empleos aplicados",
|
||||||
|
"in_progress": "En proceso",
|
||||||
|
"in_progress_desc": "Esperando respuesta",
|
||||||
|
"notifications": "Notificaciones",
|
||||||
|
"notifications_desc": "Nuevas actualizaciones"
|
||||||
|
},
|
||||||
|
"recommended": {
|
||||||
|
"title": "Empleos recomendados"
|
||||||
|
},
|
||||||
|
"applications": {
|
||||||
|
"title": "Mis postulaciones",
|
||||||
|
"table": {
|
||||||
|
"role": "Puesto",
|
||||||
|
"company": "Empresa",
|
||||||
|
"status": "Estado",
|
||||||
|
"date": "Fecha"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"under_review": "En revisión",
|
||||||
|
"interview": "Entrevista",
|
||||||
|
"accepted": "Aceptado",
|
||||||
|
"rejected": "Rechazado"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,18 @@
|
||||||
{
|
{
|
||||||
|
"sidebar": {
|
||||||
|
"dashboard": "Dashboard",
|
||||||
|
"jobs": "Vagas",
|
||||||
|
"candidates": "Candidatos",
|
||||||
|
"users": "Usuários",
|
||||||
|
"companies": "Empresas",
|
||||||
|
"backoffice": "Backoffice",
|
||||||
|
"messages": "Mensagens",
|
||||||
|
"tickets": "Tickets",
|
||||||
|
"my_jobs": "Minhas Vagas",
|
||||||
|
"applications": "Candidaturas",
|
||||||
|
"my_applications": "Minhas Candidaturas",
|
||||||
|
"support": "Suporte"
|
||||||
|
},
|
||||||
"nav": {
|
"nav": {
|
||||||
"jobs": "Vagas",
|
"jobs": "Vagas",
|
||||||
"about": "Sobre",
|
"about": "Sobre",
|
||||||
|
|
@ -662,6 +676,42 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
|
"dashboard": {
|
||||||
|
"title": "Dashboard",
|
||||||
|
"subtitle": "Visão geral do portal de vagas",
|
||||||
|
"stats": {
|
||||||
|
"activeJobs": "Vagas Ativas",
|
||||||
|
"activeJobsDesc": "Total de vagas publicadas",
|
||||||
|
"candidates": "Candidatos",
|
||||||
|
"candidatesDesc": "Usuários registrados",
|
||||||
|
"applications": "Candidaturas",
|
||||||
|
"applicationsDesc": "Em andamento",
|
||||||
|
"hiringRate": "Taxa de Contratação",
|
||||||
|
"hiringRateDesc": "Candidaturas por vaga"
|
||||||
|
},
|
||||||
|
"jobs": {
|
||||||
|
"title": "Gerenciamento de Vagas",
|
||||||
|
"add": "Nova Vaga",
|
||||||
|
"table": {
|
||||||
|
"title": "Título",
|
||||||
|
"company": "Empresa",
|
||||||
|
"status": "Status",
|
||||||
|
"created": "Criado em",
|
||||||
|
"actions": "Ações"
|
||||||
|
},
|
||||||
|
"empty": "Nenhuma vaga encontrada."
|
||||||
|
},
|
||||||
|
"candidates": {
|
||||||
|
"title": "Gerenciamento de Candidatos",
|
||||||
|
"table": {
|
||||||
|
"name": "Nome",
|
||||||
|
"email": "Email",
|
||||||
|
"location": "Localização",
|
||||||
|
"actions": "Ações"
|
||||||
|
},
|
||||||
|
"empty": "Nenhum candidato encontrado."
|
||||||
|
}
|
||||||
|
},
|
||||||
"users": {
|
"users": {
|
||||||
"title": "Gestão de Usuários",
|
"title": "Gestão de Usuários",
|
||||||
"subtitle": "Gerencie todos os usuários da plataforma",
|
"subtitle": "Gerencie todos os usuários da plataforma",
|
||||||
|
|
@ -718,5 +768,67 @@
|
||||||
"load_error": "Falha ao carregar usuários"
|
"load_error": "Falha ao carregar usuários"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"company": {
|
||||||
|
"dashboard": {
|
||||||
|
"title": "Dashboard",
|
||||||
|
"welcome": "Olá, {name}!",
|
||||||
|
"new_job": "Nova Vaga",
|
||||||
|
"stats": {
|
||||||
|
"active_jobs": "Vagas Ativas",
|
||||||
|
"posted": "Publicadas",
|
||||||
|
"applications": "Candidaturas",
|
||||||
|
"this_month": "+{count} este mês",
|
||||||
|
"views": "Visualizações",
|
||||||
|
"conversion": "Conversão",
|
||||||
|
"soon": "Em breve"
|
||||||
|
},
|
||||||
|
"recent_jobs": {
|
||||||
|
"title": "Vagas Recentes",
|
||||||
|
"subtitle": "Suas últimas vagas publicadas",
|
||||||
|
"view_all": "Ver todas",
|
||||||
|
"empty": "Nenhuma vaga encontrada.",
|
||||||
|
"applications_count": "{count} candidaturas"
|
||||||
|
},
|
||||||
|
"recent_applications": {
|
||||||
|
"title": "Candidaturas",
|
||||||
|
"subtitle": "Candidatos recentes",
|
||||||
|
"view_all": "Ver todas",
|
||||||
|
"empty": "Nenhuma candidatura recente.",
|
||||||
|
"unknown_job": "Vaga desconhecida"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"candidate": {
|
||||||
|
"dashboard": {
|
||||||
|
"welcome": "Olá, {name}!",
|
||||||
|
"edit_profile": "Editar perfil",
|
||||||
|
"stats": {
|
||||||
|
"applications": "Candidaturas",
|
||||||
|
"applications_desc": "Total de vagas aplicadas",
|
||||||
|
"in_progress": "Em andamento",
|
||||||
|
"in_progress_desc": "Aguardando resposta",
|
||||||
|
"notifications": "Notificações",
|
||||||
|
"notifications_desc": "Novas atualizações"
|
||||||
|
},
|
||||||
|
"recommended": {
|
||||||
|
"title": "Vagas recomendadas"
|
||||||
|
},
|
||||||
|
"applications": {
|
||||||
|
"title": "Minhas candidaturas",
|
||||||
|
"table": {
|
||||||
|
"role": "Vaga",
|
||||||
|
"company": "Empresa",
|
||||||
|
"status": "Status",
|
||||||
|
"date": "Data"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"under_review": "Em análise",
|
||||||
|
"interview": "Entrevista",
|
||||||
|
"accepted": "Aprovado",
|
||||||
|
"rejected": "Reprovado"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue