154 lines
5.7 KiB
JavaScript
154 lines
5.7 KiB
JavaScript
import React from 'react';
|
|
import { Users, CreditCard, Calendar, GraduationCap, FileText, Bell, UserPlus, Heart, Fingerprint } from 'lucide-react';
|
|
import { AppLayout } from '@/components/layout';
|
|
import { StatsGrid, DataTable } from '@/components/shared';
|
|
import { Button } from '@/components/ui/button';
|
|
import { TableRow, TableCell } from '@/components/ui/table';
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogDescription,
|
|
DialogTrigger,
|
|
} from "@/components/ui/dialog";
|
|
import { useEmployees } from '../hooks/useEmployees';
|
|
import { EmployeeForm } from './EmployeeForm';
|
|
|
|
import { rhService } from '../services/rhService';
|
|
import { useNavigate } from 'react-router-dom';
|
|
|
|
export const HRDashboard = () => {
|
|
const navigate = useNavigate();
|
|
const { employees, addEmployeeRequest, updateEmployeeRequest, setEmployees } = useEmployees([]);
|
|
const [isDialogOpen, setIsDialogOpen] = React.useState(false);
|
|
const [editingRequest, setEditingRequest] = React.useState(null);
|
|
const [stats, setStats] = React.useState([]);
|
|
|
|
React.useEffect(() => {
|
|
const fetchData = async () => {
|
|
const dashboardStats = await rhService.getDashboardStats();
|
|
const requests = await rhService.getPendingRequests();
|
|
setStats(dashboardStats);
|
|
setEmployees(requests);
|
|
};
|
|
fetchData();
|
|
}, [setEmployees]);
|
|
|
|
const sidebar = (
|
|
<nav className="space-y-1">
|
|
<Button variant="ghost" className="w-full justify-start gap-3 bg-emerald-50 text-emerald-700 font-semibold shadow-sm">
|
|
<FileText size={20} /> Painel de Controle
|
|
</Button>
|
|
<Button
|
|
variant="ghost"
|
|
className="w-full justify-start gap-3 text-muted-foreground"
|
|
onClick={() => navigate('/plataforma/hr/ponto')}
|
|
>
|
|
<Fingerprint size={20} /> Ponto Eletrônico
|
|
</Button>
|
|
<Button variant="ghost" className="w-full justify-start gap-3 text-muted-foreground">
|
|
<Users size={20} /> Colaboradores
|
|
</Button>
|
|
<Button variant="ghost" className="w-full justify-start gap-3 text-muted-foreground">
|
|
<CreditCard size={20} /> Finanças & Folha
|
|
</Button>
|
|
</nav>
|
|
);
|
|
|
|
return (
|
|
<AppLayout
|
|
title="Gestão de Pessoas"
|
|
sidebar={sidebar}
|
|
userName="Gestor de RH"
|
|
brandName="Integra RH"
|
|
brandIcon={Users}
|
|
metadataType="rh"
|
|
brandColorClass="bg-emerald-600 shadow-emerald-600/20"
|
|
>
|
|
<div className="space-y-8">
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h2 className="text-2xl font-bold tracking-tight">Bem-vindo, Gestor</h2>
|
|
<p className="text-muted-foreground">Temos novas solicitações aguardando sua revisão.</p>
|
|
</div>
|
|
<Button className="gap-2">
|
|
<UserPlus size={18} /> Novo Colaborador
|
|
</Button>
|
|
</div>
|
|
|
|
<StatsGrid stats={stats} />
|
|
|
|
<div className="space-y-4">
|
|
<div className="flex items-center justify-between">
|
|
<h2 className="text-xl font-bold">Solicitações Pendentes</h2>
|
|
<Dialog open={isDialogOpen} onOpenChange={(open) => {
|
|
setIsDialogOpen(open);
|
|
if (!open) setEditingRequest(null);
|
|
}}>
|
|
<DialogTrigger asChild>
|
|
<Button size="sm" className="bg-emerald-600 hover:bg-emerald-700">Nova Solicitação</Button>
|
|
</DialogTrigger>
|
|
<DialogContent className="sm:max-w-[500px]">
|
|
<DialogHeader>
|
|
<DialogTitle>{editingRequest ? 'Editar Solicitação' : 'Nova Solicitação de RH'}</DialogTitle>
|
|
<DialogDescription>
|
|
{editingRequest ? 'Atualize os dados da solicitação abaixo.' : 'Preencha os dados para criar uma nova solicitação de RH.'}
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
<EmployeeForm
|
|
initialData={editingRequest}
|
|
onSubmit={(data) => {
|
|
if (editingRequest) {
|
|
updateEmployeeRequest(editingRequest.id, data);
|
|
} else {
|
|
addEmployeeRequest(data);
|
|
}
|
|
setIsDialogOpen(false);
|
|
}}
|
|
onCancel={() => setIsDialogOpen(false)}
|
|
/>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</div>
|
|
|
|
<DataTable
|
|
columns={['Colaborador', 'Tipo', 'Data', 'Status', 'Ações']}
|
|
data={employees}
|
|
searchKey="name"
|
|
renderRow={(item, index) => (
|
|
<TableRow key={index}>
|
|
<TableCell className="font-medium">{item.name}</TableCell>
|
|
<TableCell>{item.type}</TableCell>
|
|
<TableCell className="text-muted-foreground">{item.date}</TableCell>
|
|
<TableCell>
|
|
<span className={`px-2 py-1 rounded-full text-xs font-bold ${
|
|
item.status === 'Pendente' ? 'bg-amber-100 text-amber-700' :
|
|
item.status === 'Recusado' ? 'bg-rose-100 text-rose-700' :
|
|
'bg-emerald-100 text-emerald-700'
|
|
}`}>
|
|
{item.status}
|
|
</span>
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="text-primary font-bold"
|
|
onClick={() => {
|
|
setEditingRequest(item);
|
|
setIsDialogOpen(true);
|
|
}}
|
|
>
|
|
Gerenciar
|
|
</Button>
|
|
</TableCell>
|
|
</TableRow>
|
|
)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</AppLayout>
|
|
);
|
|
};
|