const { useState, useRef, useEffect } = React;
// Parseador de Markdown a HTML elegante
function formatMarkdown(text) {
if (!text) return '';
let html = text
.replace(/&/g, "&")
.replace(//g, ">");
// Títulos y encabezados
html = html.replace(/^### (.*$)/gim, '
$1
');
html = html.replace(/^## (.*$)/gim, '
$1
');
html = html.replace(/^# (.*$)/gim, '
$1
');
// Negritas
html = html.replace(/\*\*(.*?)\*\*/g, '$1');
// Cursiva
html = html.replace(/\*(.*?)\*/g, '$1');
// Viñetas con estilo
html = html.replace(/^\s*[\-\*•]\s+(.*$)/gim, '
$1
');
// Saltos de línea
html = html.replace(/\n\n/g, '');
return html;
}
window.AdminAICopilot = function({ companyName, currentTab = 'logs' }) {
const [isOpen, setIsOpen] = useState(false);
const [messages, setMessages] = useState([
{
sender: 'ai',
text: `¡Hola! Soy **Shift Copilot AI**, tu analista de operaciones y recursos humanos para **${companyName || 'tu empresa'}**.\n\nHe sincronizado la base de datos de tu personal, horarios, contratos y bitácoras de asistencia. Selecciona un análisis rápido o hazme cualquier consulta operativa:`
}
]);
const [inputPrompt, setInputPrompt] = useState('');
const [isLoading, setIsLoading] = useState(false);
const chatEndRef = useRef(null);
useEffect(() => {
if (isOpen && chatEndRef.current) {
chatEndRef.current.scrollIntoView({ behavior: 'smooth' });
}
}, [messages, isOpen, isLoading]);
// Lista vertical de 3 Prompts Sugeridos Inteligentes
const smartPrompts = [
{
icon: "🍔",
title: "Auditoría de Almuerzos (> 60 min)",
desc: "Identifica qué colaboradores han excedido el tiempo de almuerzo en los últimos 5 días y totaliza el exceso.",
query: "¿Quiénes han tenido pausas de almuerzo superiores a 60 minutos en los últimos 5 días? Detalla el nombre del colaborador, fecha y minutos de exceso de forma organizada."
},
{
icon: "⏰",
title: "Puntualidad y Tardanzas del Mes",
desc: "Analiza el historial de llegadas tardías y ausencias de todo el personal en el mes actual.",
query: "Realiza una auditoría completa de llegadas tardías y ausencias de todo el personal en lo que va del mes. Lista los colaboradores con incidencias y la cantidad de minutos acumulados."
},
{
icon: "📄",
title: "Auditoría de Expedientes e INSS",
desc: "Revisa los contratos emitidos y detecta quiénes están pendientes de número de seguro social.",
query: "¿Cuáles son los últimos contratos individuales emitidos y qué colaboradores activos aún no tienen registrado su número de seguro social (INSS)?"
}
];
const handleSendPrompt = async (promptToSend = null) => {
const textQuery = promptToSend || inputPrompt;
if (!textQuery.trim() || isLoading) return;
const userMsg = { sender: 'user', text: textQuery };
setMessages(prev => [...prev, userMsg]);
setInputPrompt('');
setIsLoading(true);
try {
const res = await window.apiCall('ask_ai_copilot', {
prompt: textQuery,
currentTab: currentTab
});
if (res && res.success && res.response) {
setMessages(prev => [...prev, { sender: 'ai', text: res.response }]);
} else {
setMessages(prev => [...prev, { sender: 'ai', text: res?.error || "No se pudo procesar la consulta en este momento. Revisa si configuraste tu Gemini API Key en Ajustes." }]);
}
} catch (err) {
setMessages(prev => [...prev, { sender: 'ai', text: "Error de comunicación con el motor de IA: " + err.message }]);
} finally {
setIsLoading(false);
}
};
return (
{/* BOTÓN FLOTANTE SHIFT AI */}
{/* DRAWER / CHAT LATERAL */}
{isOpen && (
setIsOpen(false)}>
e.stopPropagation()}
>
{/* Cabecera Elegante */}
Shift Copilot AI
Gemini 2.5
{companyName || 'Empresa'} • Aislamiento Activo
{/* Área de Mensajes */}
{messages.map((m, idx) => (
{m.sender === 'ai' ? (
) : (
{m.text}
)}
))}
{isLoading && (
Consultando y analizando datos de {companyName || 'tu empresa'}...