NEXUS / src /app /hr /page.tsx
dimensionalpulsar's picture
Upload 29 files
8457d97 verified
"use client";
import React, { useState, useEffect } from "react";
import { db } from "@/lib/firebase";
import { collection, onSnapshot, addDoc, deleteDoc, doc } from "firebase/firestore";
import Link from "next/link";
interface Employee {
id: string;
name: string;
position: string;
salary: number;
}
export default function HRPage() {
const [employees, setEmployees] = useState<Employee[]>([]);
const [isModalOpen, setIsModalOpen] = useState(false);
const [newEmp, setNewEmp] = useState({ name: "", position: "", salary: 0 });
useEffect(() => {
const unsub = onSnapshot(collection(db, "employees"), (snap) => {
const data = snap.docs.map(doc => ({ id: doc.id, ...doc.data() } as Employee));
setEmployees(data);
});
return () => unsub();
}, []);
const handleAdd = async (e: React.FormEvent) => {
e.preventDefault();
await addDoc(collection(db, "employees"), newEmp);
setIsModalOpen(false);
setNewEmp({ name: "", position: "", salary: 0 });
};
return (
<div className="min-h-screen bg-[#0f172a] text-white p-6">
<header className="flex justify-between items-center mb-10">
<div>
<Link href="/" className="text-cyan-400 hover:text-cyan-300 transition-colors flex items-center gap-2 mb-2 font-medium">
← Panel Principal
</Link>
<h1 className="text-4xl font-extrabold tracking-tight">Gestión Humana</h1>
</div>
<button
onClick={() => setIsModalOpen(true)}
className="px-8 py-3 bg-white/10 hover:bg-white/20 border border-white/10 rounded-full font-bold transition-all backdrop-blur-md"
>
➕ Registrar Personal
</button>
</header>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{employees.map((e) => (
<div key={e.id} className="bg-gradient-to-br from-[#1e293b] to-[#0f172a] border border-white/5 rounded-[2rem] p-8 hover:border-cyan-500/30 transition-all group shadow-2xl">
<div className="flex items-center gap-4 mb-6">
<div className="w-12 h-12 bg-cyan-500/20 text-cyan-400 rounded-2xl flex items-center justify-center text-xl font-bold">
{e.name.charAt(0)}
</div>
<div>
<h3 className="font-bold group-hover:text-cyan-400 transition-colors">{e.name}</h3>
<span className="text-[10px] text-gray-500 font-black uppercase tracking-widest">{e.position}</span>
</div>
</div>
<div className="flex justify-between items-center py-4 border-y border-white/5 mb-6">
<span className="text-xs text-gray-500 uppercase font-bold">Salario</span>
<span className="font-mono text-cyan-400 font-bold">${Number(e.salary).toLocaleString()}</span>
</div>
<button
onClick={() => deleteDoc(doc(db, "employees", e.id))}
className="w-full py-3 bg-red-500/5 hover:bg-red-500/20 text-red-500/60 hover:text-red-500 text-[10px] font-black uppercase tracking-widest rounded-xl transition-all border border-red-500/10"
>
Dar de Baja
</button>
</div>
))}
</div>
{isModalOpen && (
<div className="fixed inset-0 bg-[#0f172a]/95 backdrop-blur-xl flex items-center justify-center p-6 z-50">
<div className="w-full max-w-sm">
<h2 className="text-4xl font-black mb-8 text-white italic tracking-tighter">NEW STAFF /</h2>
<form onSubmit={handleAdd} className="space-y-6">
<div className="space-y-1">
<label className="text-[10px] font-black text-cyan-500 uppercase ml-2">Nombre completo</label>
<input required value={newEmp.name} onChange={v => setNewEmp({...newEmp, name: v.target.value})} className="w-full bg-white/5 border-b border-white/20 px-4 py-4 outline-none focus:border-cyan-500 transition-all font-medium text-lg"/>
</div>
<div className="space-y-1">
<label className="text-[10px] font-black text-cyan-500 uppercase ml-2">Cargo / Posición</label>
<input required value={newEmp.position} onChange={v => setNewEmp({...newEmp, position: v.target.value})} className="w-full bg-white/5 border-b border-white/20 px-4 py-4 outline-none focus:border-cyan-500 transition-all font-medium text-lg"/>
</div>
<div className="space-y-1">
<label className="text-[10px] font-black text-cyan-500 uppercase ml-2">Salario Mensual</label>
<input type="number" required value={newEmp.salary} onChange={v => setNewEmp({...newEmp, salary: Number(v.target.value)})} className="w-full bg-white/5 border-b border-white/20 px-4 py-4 outline-none focus:border-cyan-500 transition-all font-medium text-lg"/>
</div>
<div className="flex gap-4 pt-10">
<button type="button" onClick={() => setIsModalOpen(false)} className="px-6 py-4 text-gray-500 font-black text-xs uppercase hover:text-white transition-colors">Cancelar</button>
<button type="submit" className="flex-1 bg-cyan-600 hover:bg-cyan-500 py-4 rounded-full font-black text-xs uppercase tracking-widest transition-all">Contratar</button>
</div>
</form>
</div>
</div>
)}
</div>
);
}