fix(cancelar): botones Cancelación Apartado y Cancelo funcionan con motivo
- ModalDescarteGenerico restaurado (motivo + comentario) - Cancelación Apartado: abre modal → confirma → cambia estado - Cancelo en Escrituración: abre modal → confirma → cambia estado - onFase intercepta ambas fases y abre el modal de cancelación
This commit is contained in:
@@ -233,6 +233,73 @@ function FilaOportunidad({
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Fila de apartado con botones de fase del pipeline Enkontrol */
|
/** Fila de apartado con botones de fase del pipeline Enkontrol */
|
||||||
|
function ModalDescarteGenerico({
|
||||||
|
item,
|
||||||
|
titulo,
|
||||||
|
onCancelar,
|
||||||
|
onConfirmar,
|
||||||
|
enviando,
|
||||||
|
}: {
|
||||||
|
item: { id: string; nombre: string }
|
||||||
|
titulo: string
|
||||||
|
onCancelar: () => void
|
||||||
|
onConfirmar: (motivo: string, subcategoria: string | undefined, comentario: string) => void
|
||||||
|
enviando: boolean
|
||||||
|
}) {
|
||||||
|
const [motivo, setMotivo] = useState<string>('Timing')
|
||||||
|
const [subcategoria] = useState('')
|
||||||
|
const [comentario, setComentario] = useState('')
|
||||||
|
return (
|
||||||
|
<div className="fixed inset-0 z-10 flex items-center justify-center bg-black/40 px-4" role="dialog" aria-modal="true">
|
||||||
|
<div className="w-full max-w-md rounded-2xl border border-[#E5E7EB] bg-white p-6 dark:border-[#1E293B] dark:bg-[#1E293B] shadow-xl">
|
||||||
|
<p className="text-xs font-semibold uppercase tracking-wider text-[#64748B] dark:text-[#94A3B8]">{titulo}</p>
|
||||||
|
<p className="mt-2 text-lg font-medium text-[#111827] dark:text-[#E2E8F0]">{item.nombre}</p>
|
||||||
|
<form
|
||||||
|
className="mt-6 space-y-4"
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
onConfirmar(motivo, subcategoria === '' ? undefined : subcategoria, comentario.trim())
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="motivo-cancel" className="block mb-2 text-xs font-medium text-[#4B5563] dark:text-[#CBD5E1]">Motivo</label>
|
||||||
|
<select
|
||||||
|
id="motivo-cancel"
|
||||||
|
value={motivo}
|
||||||
|
onChange={(e) => setMotivo(e.target.value)}
|
||||||
|
className="w-full rounded-lg border border-[#D1D5DB] bg-white px-3 dark:border-[#334155] dark:bg-[#0F172A] dark:text-[#E2E8F0] py-2.5 text-sm"
|
||||||
|
>
|
||||||
|
{['Timing', 'Cliente', 'Competencia', 'Financiamiento', 'Ubicación', 'Producto', 'Precio'].map((m) => (
|
||||||
|
<option key={m} value={m}>{m}</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="comentario-cancel" className="block mb-2 text-xs font-medium text-[#4B5563] dark:text-[#CBD5E1]">Comentario (opcional)</label>
|
||||||
|
<textarea
|
||||||
|
id="comentario-cancel"
|
||||||
|
value={comentario}
|
||||||
|
onChange={(e) => setComentario(e.target.value)}
|
||||||
|
rows={3}
|
||||||
|
className="w-full rounded-lg border border-[#D1D5DB] bg-white px-3 dark:border-[#334155] dark:bg-[#0F172A] dark:text-[#E2E8F0] py-2.5 text-sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-end gap-3">
|
||||||
|
<button type="button" onClick={onCancelar} disabled={enviando}
|
||||||
|
className="rounded-lg border border-[#D1D5DB] bg-white px-5 py-2 text-sm font-medium text-[#374151] dark:border-[#334155] dark:bg-[#0F172A] dark:text-[#E2E8F0] hover:bg-[#F9FAFB] disabled:opacity-50">
|
||||||
|
Cancelar
|
||||||
|
</button>
|
||||||
|
<button type="submit" disabled={enviando}
|
||||||
|
className="rounded-lg bg-red-600 px-5 py-2 text-sm font-medium text-white shadow-sm hover:bg-red-700 disabled:opacity-50">
|
||||||
|
{enviando ? 'Procesando…' : 'Confirmar'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function FilaApartado({
|
function FilaApartado({
|
||||||
apartado,
|
apartado,
|
||||||
onFase,
|
onFase,
|
||||||
@@ -290,6 +357,7 @@ function FilaApartado({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (fase === 'Cancelacion Apartado') {
|
if (fase === 'Cancelacion Apartado') {
|
||||||
|
onFase(fase)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
onFase(fase)
|
onFase(fase)
|
||||||
@@ -593,6 +661,7 @@ export default function MiDiaPage({ accionesSesion }: { accionesSesion: Acciones
|
|||||||
} | null>(null)
|
} | null>(null)
|
||||||
const [tabCrm, setTabCrm] = useState<TabCrm>('leads')
|
const [tabCrm, setTabCrm] = useState<TabCrm>('leads')
|
||||||
const [leadSeleccionado, setLeadSeleccionado] = useState<LeadMiDia | OportunidadMiDia | ApartadoMiDia | null>(null)
|
const [leadSeleccionado, setLeadSeleccionado] = useState<LeadMiDia | OportunidadMiDia | ApartadoMiDia | null>(null)
|
||||||
|
const [apartadoCancelando, setApartadoCancelando] = useState<{ id: string; nombre: string } | null>(null)
|
||||||
const [filtros, setFiltros] = useState<FiltrosCRM>({ texto: '', desarrollo: '', origen: '', fechaDesde: '', fechaHasta: '' })
|
const [filtros, setFiltros] = useState<FiltrosCRM>({ texto: '', desarrollo: '', origen: '', fechaDesde: '', fechaHasta: '' })
|
||||||
const [offline, setOffline] = useState(!navigator.onLine)
|
const [offline, setOffline] = useState(!navigator.onLine)
|
||||||
const [offlineFecha, setOfflineFecha] = useState<string | null>(null)
|
const [offlineFecha, setOfflineFecha] = useState<string | null>(null)
|
||||||
@@ -1153,6 +1222,7 @@ export default function MiDiaPage({ accionesSesion }: { accionesSesion: Acciones
|
|||||||
disabled={enviando}
|
disabled={enviando}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (fase === 'Cancelo') {
|
if (fase === 'Cancelo') {
|
||||||
|
setApartadoCancelando({ id: apartado.id, nombre: apartado.nombre })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
void ejecutar(() => cambiarEstadoApartado(apartado.id, fase), 'No se pudo actualizar')
|
void ejecutar(() => cambiarEstadoApartado(apartado.id, fase), 'No se pudo actualizar')
|
||||||
@@ -1496,6 +1566,23 @@ export default function MiDiaPage({ accionesSesion }: { accionesSesion: Acciones
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{apartadoCancelando && (
|
||||||
|
<ModalDescarteGenerico
|
||||||
|
item={apartadoCancelando}
|
||||||
|
titulo="Cancelar apartado"
|
||||||
|
enviando={enviando}
|
||||||
|
onCancelar={() => setApartadoCancelando(null)}
|
||||||
|
onConfirmar={(motivo, subcategoria, comentario) => {
|
||||||
|
const item = apartadoCancelando
|
||||||
|
setApartadoCancelando(null)
|
||||||
|
void ejecutar(
|
||||||
|
() => cambiarEstadoApartado(item.id, 'Cancelacion Apartado', motivo, subcategoria, comentario),
|
||||||
|
'No se pudo cancelar el apartado',
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{leadSeleccionado && (
|
{leadSeleccionado && (
|
||||||
<DetalleLeadModal
|
<DetalleLeadModal
|
||||||
item={leadSeleccionado}
|
item={leadSeleccionado}
|
||||||
|
|||||||
Reference in New Issue
Block a user