Files
2026-06-12 16:08:49 -04:00

551 lines
24 KiB
TypeScript

"use client"
import { useState } from "react"
import { mockDepartments, pipelineStages } from "@/lib/mock-data"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Switch } from "@/components/ui/switch"
import { Textarea } from "@/components/ui/textarea"
import { Badge } from "@/components/ui/badge"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
import { Separator } from "@/components/ui/separator"
import {
Settings,
Building2,
Users,
Bell,
Mail,
Shield,
Workflow,
Palette,
Globe,
Clock,
Plus,
Edit,
Trash2,
GripVertical,
CheckCircle2,
AlertCircle,
Save,
RefreshCw
} from "lucide-react"
import { cn } from "@/lib/utils"
export function SettingsPage() {
const [departments, setDepartments] = useState(mockDepartments)
const [isAddDeptOpen, setIsAddDeptOpen] = useState(false)
return (
<div className="space-y-6">
{/* Header */}
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
<div>
<h1 className="text-3xl font-bold tracking-tight">Configuracion</h1>
<p className="text-muted-foreground">
Administra la configuracion del sistema
</p>
</div>
<Button className="bg-accent hover:bg-accent/90 text-accent-foreground">
<Save className="mr-2 h-4 w-4" />
Guardar Cambios
</Button>
</div>
<Tabs defaultValue="general" className="space-y-6">
<TabsList className="grid w-full grid-cols-2 md:grid-cols-6 gap-2">
<TabsTrigger value="general">General</TabsTrigger>
<TabsTrigger value="departments">Departamentos</TabsTrigger>
<TabsTrigger value="workflow">Flujos</TabsTrigger>
<TabsTrigger value="notifications">Notificaciones</TabsTrigger>
<TabsTrigger value="templates">Plantillas</TabsTrigger>
<TabsTrigger value="integrations">Integraciones</TabsTrigger>
</TabsList>
{/* General Settings */}
<TabsContent value="general" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="text-base flex items-center gap-2">
<Building2 className="h-5 w-5 text-primary" />
Informacion de la Empresa
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<Label>Nombre de la Empresa</Label>
<Input defaultValue="Gomez Lee Marketing" />
</div>
<div className="space-y-2">
<Label>RFC</Label>
<Input defaultValue="GLM123456ABC" />
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<Label>Email de Contacto</Label>
<Input defaultValue="rrhh@gomezlee.com" />
</div>
<div className="space-y-2">
<Label>Telefono</Label>
<Input defaultValue="+52 55 1234 5678" />
</div>
</div>
<div className="space-y-2">
<Label>Direccion</Label>
<Textarea defaultValue="Av. Insurgentes Sur 1234, Col. Del Valle, CDMX" />
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-base flex items-center gap-2">
<Globe className="h-5 w-5 text-primary" />
Configuracion Regional
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="space-y-2">
<Label>Idioma</Label>
<Select defaultValue="es">
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="es">Espanol (Mexico)</SelectItem>
<SelectItem value="en">English (US)</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label>Zona Horaria</Label>
<Select defaultValue="america_mexico">
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="america_mexico">America/Mexico_City (GMT-6)</SelectItem>
<SelectItem value="america_monterrey">America/Monterrey (GMT-6)</SelectItem>
<SelectItem value="america_tijuana">America/Tijuana (GMT-8)</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label>Formato de Fecha</Label>
<Select defaultValue="dd_mm_yyyy">
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="dd_mm_yyyy">DD/MM/YYYY</SelectItem>
<SelectItem value="mm_dd_yyyy">MM/DD/YYYY</SelectItem>
<SelectItem value="yyyy_mm_dd">YYYY-MM-DD</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-base flex items-center gap-2">
<Shield className="h-5 w-5 text-primary" />
Seguridad
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between p-4 border rounded-lg">
<div>
<Label>Autenticacion de Dos Factores (2FA)</Label>
<p className="text-sm text-muted-foreground">
Requerir 2FA para todos los administradores
</p>
</div>
<Switch />
</div>
<div className="flex items-center justify-between p-4 border rounded-lg">
<div>
<Label>Expiracion de Sesion</Label>
<p className="text-sm text-muted-foreground">
Cerrar sesion automaticamente despues de inactividad
</p>
</div>
<Select defaultValue="30">
<SelectTrigger className="w-[140px]">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="15">15 minutos</SelectItem>
<SelectItem value="30">30 minutos</SelectItem>
<SelectItem value="60">1 hora</SelectItem>
<SelectItem value="120">2 horas</SelectItem>
</SelectContent>
</Select>
</div>
<div className="flex items-center justify-between p-4 border rounded-lg">
<div>
<Label>Politica de Contrasenas</Label>
<p className="text-sm text-muted-foreground">
Requerir contrasenas fuertes (min 8 caracteres, mayusculas, numeros)
</p>
</div>
<Switch defaultChecked />
</div>
</CardContent>
</Card>
</TabsContent>
{/* Departments */}
<TabsContent value="departments" className="space-y-6">
<Card>
<CardHeader>
<div className="flex items-center justify-between">
<div>
<CardTitle className="text-base">Departamentos</CardTitle>
<CardDescription>Gestiona los departamentos de la organizacion</CardDescription>
</div>
<Dialog open={isAddDeptOpen} onOpenChange={setIsAddDeptOpen}>
<DialogTrigger asChild>
<Button size="sm">
<Plus className="mr-2 h-4 w-4" />
Agregar
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Nuevo Departamento</DialogTitle>
<DialogDescription>
Agrega un nuevo departamento a la organizacion
</DialogDescription>
</DialogHeader>
<div className="space-y-4 py-4">
<div className="space-y-2">
<Label>Nombre</Label>
<Input placeholder="Ej: Recursos Humanos" />
</div>
<div className="space-y-2">
<Label>Codigo</Label>
<Input placeholder="Ej: RRHH" />
</div>
<div className="space-y-2">
<Label>Responsable</Label>
<Select>
<SelectTrigger>
<SelectValue placeholder="Seleccionar responsable" />
</SelectTrigger>
<SelectContent>
<SelectItem value="user1">Maria Garcia</SelectItem>
<SelectItem value="user2">Carlos Lopez</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label>Centro de Costo</Label>
<Input placeholder="Ej: CC-001" />
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => setIsAddDeptOpen(false)}>
Cancelar
</Button>
<Button onClick={() => setIsAddDeptOpen(false)}>
Crear
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
</CardHeader>
<CardContent>
<div className="space-y-2">
{departments.map(dept => (
<div
key={dept.id}
className="flex items-center justify-between p-4 border rounded-lg hover:bg-muted/50"
>
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center">
<Building2 className="h-5 w-5 text-primary" />
</div>
<div>
<div className="font-medium">{dept.name}</div>
<div className="text-sm text-muted-foreground">
Codigo: {dept.code} | CC: {dept.costCenter}
</div>
</div>
</div>
<div className="flex items-center gap-2">
<Badge variant={dept.isActive ? "default" : "secondary"}>
{dept.isActive ? "Activo" : "Inactivo"}
</Badge>
<Button variant="ghost" size="icon">
<Edit className="h-4 w-4" />
</Button>
<Button variant="ghost" size="icon" className="text-destructive">
<Trash2 className="h-4 w-4" />
</Button>
</div>
</div>
))}
</div>
</CardContent>
</Card>
</TabsContent>
{/* Workflow Settings */}
<TabsContent value="workflow" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="text-base flex items-center gap-2">
<Workflow className="h-5 w-5 text-primary" />
Flujo de Aprobacion de Requisiciones
</CardTitle>
<CardDescription>
Configura los pasos de aprobacion para nuevas requisiciones
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-3">
{[
{ step: 1, name: "Gerente de Area", description: "Primera aprobacion por el solicitante" },
{ step: 2, name: "Recursos Humanos", description: "Validacion de perfil y compensacion" },
{ step: 3, name: "Administracion/Finanzas", description: "Aprobacion de presupuesto" },
{ step: 4, name: "Direccion General", description: "Aprobacion final (montos > $50,000)" }
].map((item, index) => (
<div key={item.step} className="flex items-center gap-4 p-4 border rounded-lg">
<div className="flex items-center justify-center w-8 h-8 rounded-full bg-primary text-primary-foreground font-bold text-sm">
{item.step}
</div>
<div className="flex-1">
<div className="font-medium">{item.name}</div>
<div className="text-sm text-muted-foreground">{item.description}</div>
</div>
<div className="flex items-center gap-2">
<Switch defaultChecked />
<Button variant="ghost" size="icon">
<GripVertical className="h-4 w-4 text-muted-foreground" />
</Button>
</div>
</div>
))}
</div>
<Button variant="outline" className="w-full">
<Plus className="mr-2 h-4 w-4" />
Agregar Paso
</Button>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-base">Etapas del Pipeline de Reclutamiento</CardTitle>
<CardDescription>
Configura las etapas del proceso de seleccion
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
{pipelineStages.map((stage, index) => (
<div key={stage.id} className="flex items-center gap-4 p-3 border rounded-lg">
<div className="flex items-center justify-center w-6 h-6 rounded-full bg-muted text-muted-foreground text-xs font-bold">
{index + 1}
</div>
<div className="flex-1">
<Input defaultValue={stage.name} className="h-8" />
</div>
<div className="flex items-center gap-2">
<Switch defaultChecked />
<Button variant="ghost" size="icon">
<Trash2 className="h-4 w-4 text-muted-foreground" />
</Button>
<Button variant="ghost" size="icon">
<GripVertical className="h-4 w-4 text-muted-foreground" />
</Button>
</div>
</div>
))}
</div>
<Button variant="outline" className="w-full">
<Plus className="mr-2 h-4 w-4" />
Agregar Etapa
</Button>
</CardContent>
</Card>
</TabsContent>
{/* Notifications */}
<TabsContent value="notifications" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="text-base flex items-center gap-2">
<Bell className="h-5 w-5 text-primary" />
Notificaciones por Email
</CardTitle>
<CardDescription>
Configura cuando se envian notificaciones por email
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{[
{ title: "Nueva requisicion creada", description: "Notificar a RR.HH. cuando se crea una nueva requisicion" },
{ title: "Requisicion pendiente de aprobacion", description: "Recordatorio a aprobadores de requisiciones pendientes" },
{ title: "Requisicion aprobada", description: "Notificar al solicitante cuando su requisicion es aprobada" },
{ title: "Requisicion rechazada", description: "Notificar al solicitante cuando su requisicion es rechazada" },
{ title: "Nuevo candidato aplicado", description: "Notificar al reclutador cuando un candidato aplica" },
{ title: "Entrevista programada", description: "Recordatorio de entrevistas proximas" },
{ title: "Candidato cambia de etapa", description: "Notificar cuando un candidato avanza en el pipeline" }
].map(item => (
<div key={item.title} className="flex items-center justify-between p-4 border rounded-lg">
<div>
<Label>{item.title}</Label>
<p className="text-sm text-muted-foreground">{item.description}</p>
</div>
<Switch defaultChecked />
</div>
))}
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-base flex items-center gap-2">
<Clock className="h-5 w-5 text-primary" />
Recordatorios Automaticos
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between p-4 border rounded-lg">
<div>
<Label>Recordatorio de requisiciones pendientes</Label>
<p className="text-sm text-muted-foreground">
Enviar recordatorio despues de X dias sin accion
</p>
</div>
<Select defaultValue="3">
<SelectTrigger className="w-[120px]">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="1">1 dia</SelectItem>
<SelectItem value="2">2 dias</SelectItem>
<SelectItem value="3">3 dias</SelectItem>
<SelectItem value="5">5 dias</SelectItem>
<SelectItem value="7">7 dias</SelectItem>
</SelectContent>
</Select>
</div>
<div className="flex items-center justify-between p-4 border rounded-lg">
<div>
<Label>Recordatorio de entrevistas</Label>
<p className="text-sm text-muted-foreground">
Enviar recordatorio antes de la entrevista
</p>
</div>
<Select defaultValue="24">
<SelectTrigger className="w-[120px]">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="1">1 hora</SelectItem>
<SelectItem value="2">2 horas</SelectItem>
<SelectItem value="24">24 horas</SelectItem>
<SelectItem value="48">48 horas</SelectItem>
</SelectContent>
</Select>
</div>
</CardContent>
</Card>
</TabsContent>
{/* Email Templates */}
<TabsContent value="templates" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="text-base flex items-center gap-2">
<Mail className="h-5 w-5 text-primary" />
Plantillas de Email
</CardTitle>
<CardDescription>
Personaliza las plantillas de correo electronico
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{[
{ name: "Confirmacion de Aplicacion", description: "Enviado a candidatos al aplicar" },
{ name: "Invitacion a Entrevista", description: "Invitacion para agendar entrevista" },
{ name: "Rechazo de Candidato", description: "Notificacion de rechazo" },
{ name: "Oferta de Trabajo", description: "Carta de oferta formal" },
{ name: "Bienvenida a Nuevo Empleado", description: "Email de onboarding" },
{ name: "Solicitud de Aprobacion", description: "Notificacion a aprobadores" }
].map(template => (
<div key={template.name} className="flex items-center justify-between p-4 border rounded-lg">
<div>
<div className="font-medium">{template.name}</div>
<div className="text-sm text-muted-foreground">{template.description}</div>
</div>
<Button variant="outline" size="sm">
<Edit className="mr-2 h-4 w-4" />
Editar
</Button>
</div>
))}
</CardContent>
</Card>
</TabsContent>
{/* Integrations */}
<TabsContent value="integrations" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="text-base">Integraciones Disponibles</CardTitle>
<CardDescription>
Conecta con servicios externos para mejorar tu flujo de trabajo
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{[
{ name: "LinkedIn Recruiter", description: "Importar candidatos desde LinkedIn", connected: true },
{ name: "Google Calendar", description: "Sincronizar entrevistas con Google Calendar", connected: true },
{ name: "Microsoft Teams", description: "Crear reuniones de Teams automaticamente", connected: false },
{ name: "Zoom", description: "Generar links de Zoom para entrevistas", connected: false },
{ name: "Slack", description: "Notificaciones en canales de Slack", connected: false },
{ name: "Indeed", description: "Publicar vacantes en Indeed", connected: false }
].map(integration => (
<div key={integration.name} className="flex items-center justify-between p-4 border rounded-lg">
<div className="flex items-center gap-4">
<div className="w-10 h-10 rounded-lg bg-muted flex items-center justify-center">
<Globe className="h-5 w-5" />
</div>
<div>
<div className="font-medium">{integration.name}</div>
<div className="text-sm text-muted-foreground">{integration.description}</div>
</div>
</div>
<div className="flex items-center gap-3">
{integration.connected && (
<Badge variant="outline" className="text-accent border-accent">
<CheckCircle2 className="mr-1 h-3 w-3" />
Conectado
</Badge>
)}
<Button variant={integration.connected ? "outline" : "default"} size="sm">
{integration.connected ? "Configurar" : "Conectar"}
</Button>
</div>
</div>
))}
</CardContent>
</Card>
</TabsContent>
</Tabs>
</div>
)
}