const { useState, useEffect, useMemo } = React; window.AdminSaaS = function({ activeViewTab = 'saas_clients', refreshData }) { const [saasData, setSaasData] = useState({ clients: [], invoices: [], masterGeminiApiKey: '' }); const [selectedClient, setSelectedClient] = useState(null); const [showModuleModal, setShowModuleModal] = useState(false); const [showInvoiceModal, setShowInvoiceModal] = useState(false); // Modal de Nueva / Editar Empresa const [showCompanyModal, setShowCompanyModal] = useState(false); const [editingCompany, setEditingCompany] = useState(null); const [masterKeyInput, setMasterKeyInput] = useState(''); const [isSaving, setIsSaving] = useState(false); const [showKey, setShowKey] = useState(false); const [saveFeedback, setSaveFeedback] = useState(''); const loadMasterData = async () => { const res = await window.apiCall('get_master_dashboard_data', {}, 0); if (res && res.success) { setSaasData(res); setMasterKeyInput(res.masterGeminiApiKey || ''); } }; useEffect(() => { loadMasterData(); }, []); const metrics = useMemo(() => { const totalClients = saasData.clients.length; const activeClients = saasData.clients.filter(c => c.service_status === 'active').length; const suspendedClients = saasData.clients.filter(c => c.service_status === 'suspended').length; let mrrUSD = 0; saasData.clients.forEach(c => { if (c.service_status === 'active') { mrrUSD += parseFloat(c.monthly_fee || 0); } }); const today = new Date().toISOString().split('T')[0]; const overdueInvoices = saasData.invoices.filter(inv => { if (inv.status !== 'unpaid') return false; const diffDays = Math.floor((new Date(today) - new Date(inv.due_date)) / (1000 * 60 * 60 * 24)); return diffDays >= 5; }); return { totalClients, activeClients, suspendedClients, mrrUSD, overdueInvoices }; }, [saasData]); const handleSaveMasterKey = async () => { if (!masterKeyInput.trim()) return alert("Ingresa la API Key Maestra de Google Gemini."); setIsSaving(true); setSaveFeedback(''); try { const res = await window.apiCall('save_master_gemini_key', { gemini_api_key: masterKeyInput.trim() }, 0); if (res && res.success) { setSaveFeedback('API Key Maestra guardada correctamente en el servidor.'); await loadMasterData(); } else { setSaveFeedback('Error: ' + (res?.error || 'No se pudo guardar')); } } catch (err) { setSaveFeedback('Error de conexión: ' + err.message); } finally { setIsSaving(false); } }; const handleOpenNewCompany = () => { setEditingCompany(null); setShowCompanyModal(true); }; const handleOpenEditCompany = (cl) => { setEditingCompany(cl); setShowCompanyModal(true); }; const handleSaveCompanySubmit = async (e) => { e.preventDefault(); const fd = new FormData(e.target); const payload = { id: editingCompany ? editingCompany.id : null, company_name: fd.get('company_name'), shift_subdomain: fd.get('shift_subdomain'), contact_name: fd.get('contact_name'), contact_email: fd.get('contact_email'), contact_phone: fd.get('contact_phone'), admin_password: fd.get('admin_password'), tax_regime: fd.get('tax_regime'), ruc_number: fd.get('ruc_number'), owner_name: fd.get('owner_name'), legal_rep_id: fd.get('legal_rep_id'), business_address: fd.get('business_address'), municipality: fd.get('municipality'), module_shift: 1 }; setIsSaving(true); const res = await window.apiCall('save_master_client', payload, 0); setIsSaving(false); if (res && res.success) { setShowCompanyModal(false); await loadMasterData(); if (refreshData) await refreshData(0); } else { alert("Error al guardar empresa: " + (res?.error || "")); } }; const handleOpenModules = (cl) => { setSelectedClient(cl); setShowModuleModal(true); }; const handleSaveModulesAndBilling = async (e) => { e.preventDefault(); const fd = new FormData(e.target); const payload = { id: selectedClient.id, account_type: fd.get('account_type'), monthly_fee: fd.get('monthly_fee'), currency: fd.get('currency'), billing_day: fd.get('billing_day'), service_status: fd.get('service_status'), service_paid_until: fd.get('service_paid_until'), module_asistencia: fd.get('module_asistencia') ? 1 : 0, module_personal: fd.get('module_personal') ? 1 : 0, module_contratos: fd.get('module_contratos') ? 1 : 0, module_planilla: fd.get('module_planilla') ? 1 : 0, module_vacaciones: fd.get('module_vacaciones') ? 1 : 0, module_ausencias: fd.get('module_ausencias') ? 1 : 0, module_ai: fd.get('module_ai') ? 1 : 0, module_facial: fd.get('module_facial') ? 1 : 0 }; setIsSaving(true); const res = await window.apiCall('save_client_modules_and_billing', payload, 0); setIsSaving(false); if (res && res.success) { setShowModuleModal(false); await loadMasterData(); if (refreshData) await refreshData(0); } }; const handleToggleSuspension = async (client, currentStatus) => { const nextStatus = currentStatus === 'suspended' ? 'active' : 'suspended'; const msg = nextStatus === 'suspended' ? `¿Deseas SUSPENDER el acceso al portal de ${client.company_name}?` : `¿Deseas REACTIVAR el acceso al portal de ${client.company_name}?`; if (!confirm(msg)) return; const res = await window.apiCall('toggle_service_suspension', { client_id: client.id, status: nextStatus }, 0); if (res && res.success) { await loadMasterData(); if (refreshData) await refreshData(0); } }; const handleMarkPaid = async (inv) => { const ref = prompt("Referencia bancaria o método de pago (ej. Transferencia BAC #9482):", "Transferencia BAC"); if (ref === null) return; const res = await window.apiCall('mark_invoice_paid', { invoice_id: inv.id, payment_method: 'Transferencia Bancaria', payment_reference: ref }, 0); if (res && res.success) { alert(`Factura ${inv.invoice_number} marcada como PAGADA.`); await loadMasterData(); } }; const handleCreateInvoice = async (e) => { e.preventDefault(); const fd = new FormData(e.target); const clId = fd.get('client_id'); const cl = saasData.clients.find(c => Number(c.id) === Number(clId)); const payload = { client_id: clId, company_name: cl ? cl.company_name : 'Empresa Cliente', amount: fd.get('amount'), currency: fd.get('currency'), issue_date: fd.get('issue_date'), due_date: fd.get('due_date'), period_start: fd.get('period_start'), period_end: fd.get('period_end'), status: 'unpaid' }; setIsSaving(true); const res = await window.apiCall('create_client_invoice', payload, 0); setIsSaving(false); if (res && res.success) { setShowInvoiceModal(false); await loadMasterData(); } }; return (
Administración central de empresas, cobros recurrentes y motor de Inteligencia Artificial
Aplica suspensión o registra el cobro de estas empresas.
Total Empresas
Empresas Activas
Suspendidas
Facturación Proyectada
Gestión de portales, subdominios y planes
{c.shift_subdomain}.shift.marcasnicaragua.com • Contacto: {c.contact_name} ({c.contact_email})
Tarifa: {c.currency} ${parseFloat(c.monthly_fee || 0).toFixed(2)}/mes • Día de Cobro: {c.billing_day} • Pagado hasta: {c.service_paid_until || 'Sin registrar'}
Control mensual de facturas generadas a las empresas clientes
No hay facturas emitidas aún.
) : ( saasData.invoices.map(inv => { const isPaid = inv.status === 'paid'; return (Periodo: {inv.period_start} al {inv.period_end} • Vence: {inv.due_date}
{isPaid &&Pagado con: {inv.payment_method} ({inv.payment_reference})
}Esta clave central abastece el asistente de inteligencia artificial para todas las empresas de tu SaaS con aislamiento de datos.
{saveFeedback}
)}Información corporativa, fiscal y credenciales de acceso administrativo
Activa o desactiva las secciones según el plan contratado