import React, { useState } from ‘react’;
import {
LayoutDashboard,
Users,
KanbanSquare,
CheckCircle2,
Circle,
Calendar,
PhoneCall,
Mail,
Plus,
X,
Search,
Building,
MapPin,
ExternalLink,
Briefcase,
ChevronRight
} from ‘lucide-react’;
// — CONFIGURACIÓN Y CONSTANTES —
const PIPELINE_STAGES = [
«Sin Contactar»,
«Contactado»,
«Reunión / Diagnóstico»,
«Propuesta Enviada»,
«Seguimiento / Negociación»,
«Cerrado – Ganado»,
«Cerrado – Perdido»
];
const SERVICES = [«ISO 9001», «ISO 14001», «ISO 45001», «Certificación de Producto», «Comercio Exterior»];
const SOURCES = [«LinkedIn», «Expo / Evento», «Google / Web», «Referido», «Base Fría»];
const INITIAL_COMPANIES = [
{ id: 1, name: ‘Metalúrgica Sur S.A.’, contact: ‘Carlos Gómez’, role: ‘Gte. Calidad’, mail: ‘cgomez@metalsur.com’, phone: ‘341-555-0123’, city: ‘Rosario’, province: ‘Santa Fe’, industry: ‘Metalúrgica’, interest: ‘ISO 9001’, source: ‘LinkedIn’, stage: ‘Reunión / Diagnóstico’, notes: ‘Quieren certificar antes de diciembre.’ },
{ id: 2, name: ‘Logística Avanzada’, contact: ‘María Silva’, role: ‘Directora’, mail: ‘msilva@logavanzada.com’, phone: ’11-444-9988′, city: ‘CABA’, province: ‘Buenos Aires’, industry: ‘Logística’, interest: ‘ISO 45001’, source: ‘Referido’, stage: ‘Propuesta Enviada’, notes: ‘Comparando presupuestos.’ },
{ id: 3, name: ‘Agro Export SRL’, contact: ‘Diego López’, role: ‘Comercio Ext.’, mail: ‘dlopez@agroexport.com.ar’, phone: ‘351-222-3344’, city: ‘Córdoba’, province: ‘Córdoba’, industry: ‘Agro’, interest: ‘Comercio Exterior’, source: ‘Google’, stage: ‘Sin Contactar’, notes: ‘Dejaron consulta en la web.’ }
];
const getTodayDateString = () => new Date().toISOString().split(‘T’)[0];
const INITIAL_TASKS = [
{ id: 1, companyId: 1, date: getTodayDateString(), type: ‘Reunión Virtual’, status: ‘Pendiente’, notes: ‘Relevar cantidad de empleados.’, assignedTo: ‘Vendedor 1’ },
{ id: 2, companyId: 2, date: ‘2023-10-01’, type: ‘Llamada’, status: ‘Pendiente’, notes: ‘Seguimiento de presupuesto.’, assignedTo: ‘Vendedor 2’ }
];
// COMPONENTE PRINCIPAL (Debe llamarse App para la vista previa)
export default function App() {
const [activeTab, setActiveTab] = useState(‘dashboard’);
const [companies, setCompanies] = useState(INITIAL_COMPANIES);
const [tasks, setTasks] = useState(INITIAL_TASKS);
// Filtros
const [filterInterest, setFilterInterest] = useState(‘Todos’);
const [filterStage, setFilterStage] = useState(‘Todos’);
const [searchTerm, setSearchTerm] = useState(»);
// Modales
const [isCompanyModalOpen, setIsCompanyModalOpen] = useState(false);
const [isTaskModalOpen, setIsTaskModalOpen] = useState(false);
const [selectedCompanyId, setSelectedCompanyId] = useState(null);
const today = getTodayDateString();
// — LÓGICA DE GOOGLE CALENDAR —
const generateGoogleCalendarLink = (task) => {
const company = companies.find(c => c.id === task.companyId);
const title = encodeURIComponent(`${task.type}: ${company?.name || ‘Cliente’}`);
const details = encodeURIComponent(`Acción: ${task.notes}nContacto: ${company?.contact}nTel: ${company?.phone}`);
const date = task.date.replace(/-/g, »);
// Formato YYYYMMDD/YYYYMMDD
return `https://www.google.com/calendar/render?action=TEMPLATE&text=${title}&details=${details}&dates=${date}/${date}`;
};
// — FILTRADO DE DATOS —
const filteredCompanies = companies.filter(c => {
const matchInterest = filterInterest === ‘Todos’ || c.interest === filterInterest;
const matchStage = filterStage === ‘Todos’ || c.stage === filterStage;
const searchLow = searchTerm.toLowerCase();
const matchSearch = c.name.toLowerCase().includes(searchLow) ||
c.city.toLowerCase().includes(searchLow) ||
c.province.toLowerCase().includes(searchLow);
return matchInterest && matchStage && matchSearch;
});
const toggleTaskStatus = (taskId) => {
setTasks(tasks.map(t => t.id === taskId ? { …t, status: t.status === ‘Pendiente’ ? ‘Completada’ : ‘Pendiente’ } : t));
};
const changeCompanyStage = (companyId, newStage) => {
setCompanies(companies.map(c => c.id === companyId ? { …c, stage: newStage } : c));
};
// — VISTAS INTERNAS —
const DashboardView = () => {
const pending = tasks.filter(t => t.status === ‘Pendiente’);
const vencidas = pending.filter(t => t.date < today);
const hoy = pending.filter(t => t.date === today);
const futuras = pending.filter(t => t.date > today);
return (
);
};
const TaskColumn = ({ title, tasks, color }) => {
const colorClasses = {
red: «bg-red-50 border-red-200 text-red-700»,
amber: «bg-amber-50 border-amber-200 text-amber-700»,
slate: «bg-slate-50 border-slate-200 text-slate-700»
};
return (
);
};
const PipelineView = () => (
);
const DirectorioView = () => (
{/* FILTROS MEJORADOS */}
setSearchTerm(e.target.value)}
placeholder=»Nombre, ciudad o provincia…»
className=»w-full pl-10 pr-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl text-sm outline-none focus:ring-2 focus:ring-blue-500 focus:bg-white transition-all»
/>
{filteredCompanies.length === 0 && (
)}
);
// — MODALES —
const CompanyModal = () => {
const handleSubmit = (e) => {
e.preventDefault();
const fd = new FormData(e.target);
const newC = {
id: Date.now(),
name: fd.get(‘name’),
city: fd.get(‘city’),
province: fd.get(‘province’),
contact: fd.get(‘contact’),
mail: fd.get(‘mail’),
phone: fd.get(‘phone’),
interest: fd.get(‘interest’),
stage: ‘Sin Contactar’,
source: fd.get(‘source’),
notes: fd.get(‘notes’)
};
setCompanies(prev => […prev, newC]);
setIsCompanyModalOpen(false);
};
return (
);
};
const TaskModal = () => {
const handleSubmit = (e) => {
e.preventDefault();
const fd = new FormData(e.target);
const newT = {
id: Date.now(),
companyId: parseInt(fd.get(‘companyId’)),
date: fd.get(‘date’),
type: fd.get(‘type’),
status: ‘Pendiente’,
notes: fd.get(‘notes’),
assignedTo: ‘Comercial’
};
setTasks(prev => […prev, newT]);
setIsTaskModalOpen(false);
};
return (
);
};
return (
Panel de Control
{title} ({tasks.length})
{tasks.map(task => {
const comp = companies.find(c => c.id === task.companyId);
return (
);
})}
{tasks.length === 0 &&
Sin tareas pendientes
}Pipeline Comercial
{PIPELINE_STAGES.map(stage => {
const stageCompanies = companies.filter(c => c.stage === stage);
return (
);
})}
{stage}
{stageCompanies.length}
{stageCompanies.map(c => (
{c.city}, {c.province}
))}
{stageCompanies.length === 0 && }
{c.name}
{c.interest}
Directorio de Empresas
| Empresa / Contacto | Ubicación | Servicio | Etapa Comercial | Gestión |
|---|---|---|---|---|
|
{c.name}
{c.contact} • {c.mail}
|
{c.province}
|
{c.interest} |
No se encontraron empresas con los filtros actuales.
Nueva Empresa
Programar Seguimiento
{/* SIDEBAR */}
{/* MAIN CONTENT */}
{/* MODALS */}
{isCompanyModalOpen && }
{isTaskModalOpen && }
);
}
// Sub-componente de Botón de Navegación
const NavBtn = ({ active, onClick, icon, label }) => (
);
Gestión Comercial de Certificaciones • {new Date().toLocaleDateString()}
AD
{activeTab === ‘dashboard’ && }
{activeTab === ‘directorio’ && }
{activeTab === ‘pipeline’ && }
