Actualizar frontend/src/components/ConfigModal.jsx
This commit is contained in:
@@ -888,9 +888,16 @@ export default function ConfigModal({ onClose }) {
|
|||||||
<button onClick={() => setSeccion("plantillas")}
|
<button onClick={() => setSeccion("plantillas")}
|
||||||
style={{ width: "100%", textAlign: "left", padding: "10px 12px", borderRadius: 8,
|
style={{ width: "100%", textAlign: "left", padding: "10px 12px", borderRadius: 8,
|
||||||
border: "none", cursor: "pointer", fontSize: 14, fontWeight: 600, whiteSpace: "nowrap",
|
border: "none", cursor: "pointer", fontSize: 14, fontWeight: 600, whiteSpace: "nowrap",
|
||||||
|
marginBottom: 4,
|
||||||
background: seccion === "plantillas" ? "#e2e8f0" : "transparent", color: "#1e293b" }}>
|
background: seccion === "plantillas" ? "#e2e8f0" : "transparent", color: "#1e293b" }}>
|
||||||
Plantillas
|
Plantillas
|
||||||
</button>
|
</button>
|
||||||
|
<button onClick={() => setSeccion("exportar_base")}
|
||||||
|
style={{ width: "100%", textAlign: "left", padding: "10px 12px", borderRadius: 8,
|
||||||
|
border: "none", cursor: "pointer", fontSize: 14, fontWeight: 600, whiteSpace: "nowrap",
|
||||||
|
background: seccion === "exportar_base" ? "#e2e8f0" : "transparent", color: "#1e293b" }}>
|
||||||
|
Exportar Base
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{/* Contenido */}
|
{/* Contenido */}
|
||||||
<div style={{ flex: 1, display: "flex", flexDirection: "column" }}>
|
<div style={{ flex: 1, display: "flex", flexDirection: "column" }}>
|
||||||
@@ -902,6 +909,7 @@ export default function ConfigModal({ onClose }) {
|
|||||||
: seccion === "leyendas" ? "Leyenda"
|
: seccion === "leyendas" ? "Leyenda"
|
||||||
: seccion === "plantillas" ? "Plantillas"
|
: seccion === "plantillas" ? "Plantillas"
|
||||||
: seccion === "subir_base" ? "Subir Base"
|
: seccion === "subir_base" ? "Subir Base"
|
||||||
|
: seccion === "exportar_base" ? "Exportar Base"
|
||||||
: "Sedes de Anuncios"}
|
: "Sedes de Anuncios"}
|
||||||
</div>
|
</div>
|
||||||
<button onClick={onClose}
|
<button onClick={onClose}
|
||||||
@@ -912,6 +920,10 @@ export default function ConfigModal({ onClose }) {
|
|||||||
<div style={{ flex: 1, overflow: "auto", padding: "16px 22px 24px" }}>
|
<div style={{ flex: 1, overflow: "auto", padding: "16px 22px 24px" }}>
|
||||||
<SubirBase />
|
<SubirBase />
|
||||||
</div>
|
</div>
|
||||||
|
) : seccion === "exportar_base" ? (
|
||||||
|
<div style={{ flex: 1, overflow: "auto", padding: "16px 22px 24px" }}>
|
||||||
|
<ExportarBase />
|
||||||
|
</div>
|
||||||
) : seccion === "plantillas" ? (
|
) : seccion === "plantillas" ? (
|
||||||
<div style={{ flex: 1, overflow: "auto", padding: "16px 22px 24px" }}>
|
<div style={{ flex: 1, overflow: "auto", padding: "16px 22px 24px" }}>
|
||||||
<Plantillas ocultarTitulo />
|
<Plantillas ocultarTitulo />
|
||||||
@@ -1238,3 +1250,97 @@ function SubirBase() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── EXPORTAR BASE ──────────────────────────────────────────────────────────
|
||||||
|
// Elige un asesor (en vivo de Chatwoot) y descarga su base de leads deduplicada
|
||||||
|
// (teléfono más antiguo), con SEDE_ACT por asesor y última etiqueta.
|
||||||
|
function ExportarBase() {
|
||||||
|
const [asesores, setAsesores] = useState([]);
|
||||||
|
const [asesorSel, setAsesorSel] = useState("");
|
||||||
|
const [etiquetas, setEtiquetas] = useState([]);
|
||||||
|
const [etiqSel, setEtiqSel] = useState([]);
|
||||||
|
const [cargando, setCargando] = useState(false);
|
||||||
|
const [msg, setMsg] = useState("");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
api.exportarBaseAsesores().then((r) => setAsesores(r.asesores || [])).catch(() => {});
|
||||||
|
api.subirBaseEtiquetas().then((r) => setEtiquetas(r.etiquetas || [])).catch(() => {});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function toggleEtiqueta(t) {
|
||||||
|
setEtiqSel((p) => p.includes(t) ? p.filter((x) => x !== t) : [...p, t]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function exportar() {
|
||||||
|
if (!asesorSel || cargando) return;
|
||||||
|
setCargando(true); setMsg("");
|
||||||
|
try {
|
||||||
|
await api.exportarBaseDescargar(asesorSel, etiqSel);
|
||||||
|
setMsg("✓ Base descargada.");
|
||||||
|
} catch (e) {
|
||||||
|
setMsg("Error al exportar: " + e.message);
|
||||||
|
}
|
||||||
|
setCargando(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const puede = asesorSel && !cargando;
|
||||||
|
const card = { background: "#fff", border: "1px solid #e6eaf0", borderRadius: 14,
|
||||||
|
padding: 20, boxShadow: "0 1px 3px rgba(15,23,42,.04)" };
|
||||||
|
const cardHead = { display: "flex", alignItems: "center", gap: 10, marginBottom: 4 };
|
||||||
|
const step = { width: 26, height: 26, borderRadius: 8, background: "#1e3a5f", color: "#fff",
|
||||||
|
display: "flex", alignItems: "center", justifyContent: "center",
|
||||||
|
fontSize: 13, fontWeight: 800, flexShrink: 0 };
|
||||||
|
const cardTitle = { fontSize: 15, fontWeight: 700, color: "#0f172a" };
|
||||||
|
const cardSub = { fontSize: 12.5, color: "#94a3b8", margin: "2px 0 14px 36px" };
|
||||||
|
const fieldLabel = { fontSize: 12, fontWeight: 700, color: "#64748b", marginBottom: 7,
|
||||||
|
textTransform: "uppercase", letterSpacing: ".02em", display: "block" };
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: 16, maxWidth: 680 }}>
|
||||||
|
<div style={card}>
|
||||||
|
<div style={cardHead}>
|
||||||
|
<span style={step}>1</span>
|
||||||
|
<span style={cardTitle}>Elige el asesor</span>
|
||||||
|
</div>
|
||||||
|
<div style={cardSub}>
|
||||||
|
Se descargará su base de leads (un número por teléfono, el más antiguo),
|
||||||
|
con sede, programa, fecha y última etiqueta.
|
||||||
|
</div>
|
||||||
|
<label style={fieldLabel}>👤 Asesor</label>
|
||||||
|
<Select value={asesorSel}
|
||||||
|
options={[{ value: "", label: "— Elige un asesor —" },
|
||||||
|
...asesores.map((a) => ({ value: a.nombre, label: a.nombre }))]}
|
||||||
|
onChange={(v) => { setAsesorSel(v); setMsg(""); }}
|
||||||
|
minWidth={0} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={card}>
|
||||||
|
<div style={cardHead}>
|
||||||
|
<span style={step}>2</span>
|
||||||
|
<span style={cardTitle}>Etiquetas (opcional)</span>
|
||||||
|
<span style={{ marginLeft: "auto", fontSize: 12, color: "#94a3b8", fontWeight: 600 }}>
|
||||||
|
{etiqSel.length} seleccionada{etiqSel.length === 1 ? "" : "s"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div style={cardSub}>
|
||||||
|
Filtra la base por la última etiqueta de cada número. Si no eliges ninguna,
|
||||||
|
se incluyen todas.
|
||||||
|
</div>
|
||||||
|
<label style={fieldLabel}>🏷️ Etiquetas de Chatwoot</label>
|
||||||
|
<MultiSelectEtiquetas opciones={etiquetas} seleccion={etiqSel} onToggle={toggleEtiqueta} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button onClick={exportar} disabled={!puede}
|
||||||
|
style={{ width: "100%", padding: "13px", borderRadius: 11, border: "none",
|
||||||
|
background: puede ? "#1e3a5f" : "#cbd5e1", color: "#fff", fontWeight: 700, fontSize: 14.5,
|
||||||
|
cursor: puede ? "pointer" : "default" }}>
|
||||||
|
{cargando ? "Generando Excel…" : "⬇ Exportar base a Excel"}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{msg && (
|
||||||
|
<div style={{ fontSize: 13, fontWeight: 600,
|
||||||
|
color: msg.startsWith("✓") ? "#15803d" : "#b91c1c" }}>{msg}</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user