|
|
|
|
@@ -1,10 +1,8 @@
|
|
|
|
|
import { useCallback, useEffect, useState, type FormEvent } from 'react'
|
|
|
|
|
import KpiCard from '../components/KpiCard'
|
|
|
|
|
import BannerModoLocal from '../components/BannerModoLocal'
|
|
|
|
|
import DarkModeToggle from '../components/DarkModeToggle'
|
|
|
|
|
import { SkeletonList } from "../components/Skeleton"
|
|
|
|
|
import toast from "react-hot-toast"
|
|
|
|
|
import ChipPendienteSync from '../components/ChipPendienteSync'
|
|
|
|
|
import type { AccionesSesion } from '../components/AuthGate'
|
|
|
|
|
import {
|
|
|
|
|
esActividadVencida,
|
|
|
|
|
@@ -338,9 +336,9 @@ function FilaOportunidad({
|
|
|
|
|
enviando: boolean
|
|
|
|
|
acciones?: string[]
|
|
|
|
|
}) {
|
|
|
|
|
const [conCita, setConCita] = useState(false)
|
|
|
|
|
const [fechaCita, setFechaCita] = useState('')
|
|
|
|
|
const fases = ['Agendo Cita', 'Afluencia', 'Cotizador'] as const
|
|
|
|
|
const [conCita, setConCita] = useState(!!op.fechaCita)
|
|
|
|
|
const [fechaCita, setFechaCita] = useState(op.fechaCita ?? '')
|
|
|
|
|
const fases = ['Agendo Cita', 'Afluencia', 'Cotizador', 'Aparto'] as const
|
|
|
|
|
return (
|
|
|
|
|
<li className="rounded-xl border border-[#E5E7EB] bg-white p-4 dark:border-[#1E293B] dark:bg-[#1E293B] shadow-sm">
|
|
|
|
|
<div className="flex flex-wrap items-center justify-between gap-3">
|
|
|
|
|
@@ -353,7 +351,7 @@ function FilaOportunidad({
|
|
|
|
|
>
|
|
|
|
|
{op.nombre}
|
|
|
|
|
</button>
|
|
|
|
|
{op.pendienteSync === true && <ChipPendienteSync />}
|
|
|
|
|
|
|
|
|
|
</p>
|
|
|
|
|
<p className="mt-1 text-xs text-[#64748B] dark:text-[#94A3B8]">
|
|
|
|
|
{op.telefono || 'Sin teléfono'}
|
|
|
|
|
@@ -469,7 +467,7 @@ function FilaApartado({
|
|
|
|
|
>
|
|
|
|
|
{apartado.nombre}
|
|
|
|
|
</button>
|
|
|
|
|
{apartado.pendienteSync === true && <ChipPendienteSync />}
|
|
|
|
|
|
|
|
|
|
{apartado.unidadCodigo ? (
|
|
|
|
|
<span className="text-xs font-normal text-[#94A3B8]">{apartado.unidadCodigo}</span>
|
|
|
|
|
) : null}
|
|
|
|
|
@@ -732,7 +730,7 @@ function FilaLead({
|
|
|
|
|
{lead.nombre}
|
|
|
|
|
</button>
|
|
|
|
|
<ScoreBadge score={calcularScore(lead)} />
|
|
|
|
|
{lead.pendienteSync === true && <ChipPendienteSync />}
|
|
|
|
|
|
|
|
|
|
{/* Insignia de procedencia: gris = tablero Leads, azul = Oportunidades */}
|
|
|
|
|
<span
|
|
|
|
|
className={
|
|
|
|
|
@@ -816,7 +814,6 @@ export default function MiDiaPage({ accionesSesion }: { accionesSesion: Acciones
|
|
|
|
|
fuente: 'lead' | 'oportunidad'
|
|
|
|
|
} | null>(null)
|
|
|
|
|
const [tabCrm, setTabCrm] = useState<TabCrm>('leads')
|
|
|
|
|
const [nota, setNota] = useState<string | null>(null)
|
|
|
|
|
const [apartadoSeleccionado, setApartadoSeleccionado] = useState<ApartadoMiDia | null>(null)
|
|
|
|
|
const [leadSeleccionado, setLeadSeleccionado] = useState<LeadMiDia | OportunidadMiDia | ApartadoMiDia | null>(null)
|
|
|
|
|
const [apartadoCancelando, setApartadoCancelando] = useState<{
|
|
|
|
|
@@ -993,13 +990,11 @@ export default function MiDiaPage({ accionesSesion }: { accionesSesion: Acciones
|
|
|
|
|
async function convertir(lead: LeadMiDia) {
|
|
|
|
|
setEnviando(true)
|
|
|
|
|
setAviso(null)
|
|
|
|
|
setNota(null)
|
|
|
|
|
try {
|
|
|
|
|
await convertirLead(lead.id)
|
|
|
|
|
await cargar()
|
|
|
|
|
setNota(`${lead.nombre} pasó a Mis oportunidades (Agendo Cita).`)
|
|
|
|
|
} catch (err) {
|
|
|
|
|
setAviso(err instanceof Error ? err.message : 'No se pudo convertir el lead')
|
|
|
|
|
toast.error(err instanceof Error ? err.message : 'No se pudo convertir el lead')
|
|
|
|
|
} finally {
|
|
|
|
|
setEnviando(false)
|
|
|
|
|
}
|
|
|
|
|
@@ -1017,7 +1012,7 @@ export default function MiDiaPage({ accionesSesion }: { accionesSesion: Acciones
|
|
|
|
|
try {
|
|
|
|
|
await cambiarEtapaOportunidad(op.id, 'Cotizador')
|
|
|
|
|
} catch {
|
|
|
|
|
setAviso('No se pudo actualizar la etapa en Monday; el cotizador se abrirá de todos modos.')
|
|
|
|
|
toast.error('No se pudo actualizar la etapa en Monday; el cotizador se abrirá de todos modos.')
|
|
|
|
|
}
|
|
|
|
|
window.location.href = urlCotizadorParaOportunidad(op)
|
|
|
|
|
}
|
|
|
|
|
@@ -1079,7 +1074,7 @@ export default function MiDiaPage({ accionesSesion }: { accionesSesion: Acciones
|
|
|
|
|
← Menú
|
|
|
|
|
</a>
|
|
|
|
|
<p className="shrink-0 text-xs font-semibold uppercase tracking-wider text-accent">
|
|
|
|
|
FRASA <span aria-hidden="true" className="text-[#F97316]">·</span> Mi día
|
|
|
|
|
CRM360 FRASA <span aria-hidden="true" className="text-[#F97316]">·</span> Mi día
|
|
|
|
|
</p>
|
|
|
|
|
<span aria-hidden="true" className="hidden h-4 w-px bg-[#E5E7EB] sm:block" />
|
|
|
|
|
<div className="flex min-w-0 items-center gap-2">
|
|
|
|
|
@@ -1120,7 +1115,7 @@ export default function MiDiaPage({ accionesSesion }: { accionesSesion: Acciones
|
|
|
|
|
</div>
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<BannerModoLocal />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{offline && (
|
|
|
|
|
<div className="px-4 pt-4 sm:px-6 lg:px-8">
|
|
|
|
|
@@ -1146,11 +1141,6 @@ export default function MiDiaPage({ accionesSesion }: { accionesSesion: Acciones
|
|
|
|
|
{aviso}
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
|
|
|
|
{nota && (
|
|
|
|
|
<p role="status" className="mb-6 rounded-lg border border-green-200 bg-green-50 px-4 py-3 text-sm font-medium text-green-700">
|
|
|
|
|
{nota}
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
|
|
|
|
{resumen?.sinMapeoMonday && (
|
|
|
|
|
<p className="mb-6 rounded-lg border border-[#E5E7EB] bg-white px-4 py-3 text-sm font-medium text-[#64748B] dark:text-[#94A3B8] shadow-sm dark:bg-[#1E293B] dark:border-[#1E293B]">
|
|
|
|
|
Tu usuario aún no está vinculado a Monday; las acciones siguen funcionando
|
|
|
|
|
@@ -1457,7 +1447,7 @@ export default function MiDiaPage({ accionesSesion }: { accionesSesion: Acciones
|
|
|
|
|
<div>
|
|
|
|
|
<p className="flex items-center gap-2 text-sm font-medium">
|
|
|
|
|
{c.nombre}
|
|
|
|
|
{c.pendienteSync === true && <ChipPendienteSync />}
|
|
|
|
|
|
|
|
|
|
</p>
|
|
|
|
|
<p className="mt-1 text-xs text-[#64748B] dark:text-[#94A3B8]">
|
|
|
|
|
{c.telefono || 'Sin teléfono'}
|
|
|
|
|
|