Files
FRASA-CAS/apps/alta-clientes/src/pages/AltaClientePage.tsx
Consult AS Technology 0546f35d2a feat: API Gateway (Express 5 + Prisma + Monday) y conexion de apps al API
- api-gateway: servicio Monday (retry 429/complejidad, paginacion cursor,
  column IDs por titulo), endpoints unidades/cotizaciones/clientes/planes,
  webhook con handshake challenge, Prisma SQLite dev, 55 tests
- cotizador: inventario desde /api/unidades con fallback a seed
- alta-clientes: POST /api/clientes + upload multipart de documentos
- cobranza: persistencia via API con respaldo offline en localStorage
- .env.example con board IDs del workspace Frasa-CAS
2026-08-21 23:39:17 +00:00

149 lines
5.0 KiB
TypeScript

import { useState } from 'react'
import Stepper from '../components/Stepper'
import DatosGeneralesForm from '../forms/DatosGeneralesForm'
import EmpleoForm from '../forms/EmpleoForm'
import EconomicosForm from '../forms/EconomicosForm'
import CoacreditadoForm from '../forms/CoacreditadoForm'
import ReferenciasForm from '../forms/ReferenciasForm'
import ViviendaCreditoForm from '../forms/ViviendaCreditoForm'
import DocumentosForm from '../forms/DocumentosForm'
import FirmasForm from '../forms/FirmasForm'
import { useAltaCliente, PASOS } from '../hooks/useAltaCliente'
import { crearAltaCliente, subirDocumentos } from '../services/api'
export default function AltaClientePage() {
const { paso, siguiente, anterior, irAPaso, datos, alta, actualizar, agregarDocumento, quitarDocumento } =
useAltaCliente()
const [registro, setRegistro] = useState<string>('')
const [sinConexion, setSinConexion] = useState(false)
// Registra el alta en el API al llegar al paso de firmas; si el API no
// responde, el flujo continúa solo local (los PDFs se generan igual)
const registrarAlta = async () => {
const creada = await crearAltaCliente(alta)
if (creada) {
await subirDocumentos(creada.id, alta)
setRegistro(creada.id)
setSinConexion(false)
} else {
setRegistro('')
setSinConexion(true)
}
}
return (
<div className="min-h-screen bg-white">
<header className="border-b border-neutral-200 px-4 py-6">
<div className="mx-auto flex max-w-6xl items-baseline gap-3">
<span className="text-sm font-bold uppercase tracking-widest">FRASA</span>
<h1 className="text-2xl font-light tracking-wide">Alta de Clientes</h1>
</div>
</header>
<main className="mx-auto max-w-6xl px-4 py-16">
<Stepper pasos={[...PASOS]} pasoActual={paso} onIrAPaso={irAPaso} />
<div className="mt-16">
{paso === 0 && (
<DatosGeneralesForm
valores={datos.datosGenerales}
onSiguiente={(v) => {
actualizar('datosGenerales', v)
siguiente()
}}
/>
)}
{paso === 1 && (
<EmpleoForm
valores={datos.empleo}
onAnterior={anterior}
onSiguiente={(v) => {
actualizar('empleo', v)
siguiente()
}}
/>
)}
{paso === 2 && (
<EconomicosForm
valores={datos.economicos}
onAnterior={anterior}
onSiguiente={(v) => {
actualizar('economicos', v)
siguiente()
}}
/>
)}
{paso === 3 && (
<CoacreditadoForm
valores={datos.coacreditado}
onAnterior={anterior}
onSiguiente={(v) => {
actualizar('coacreditado', v)
siguiente()
}}
/>
)}
{paso === 4 && (
<ReferenciasForm
valores={datos.referencias}
onAnterior={anterior}
onSiguiente={(v) => {
actualizar('referencias', v)
siguiente()
}}
/>
)}
{paso === 5 && (
<ViviendaCreditoForm
valores={datos.viviendaCredito}
onAnterior={anterior}
onSiguiente={(v) => {
actualizar('viviendaCredito', v)
siguiente()
}}
/>
)}
{paso === 6 && (
<DocumentosForm
documentos={alta.documentos}
firmaDataUrl={alta.firma.firmaDataUrl}
onAgregar={agregarDocumento}
onQuitar={quitarDocumento}
onAplicarDatosGenerales={(campos) =>
actualizar('datosGenerales', { ...datos.datosGenerales, ...campos })
}
onAnterior={anterior}
onSiguiente={() => {
void registrarAlta()
siguiente()
}}
/>
)}
{paso === 7 && (
<>
{registro && (
<p className="mb-8 border border-accent bg-white px-4 py-3 text-xs font-bold uppercase tracking-widest text-accent">
Alta registrada en el servidor: {registro}
</p>
)}
{sinConexion && (
<p
role="alert"
className="mb-8 border border-amber-300 bg-amber-50 px-4 py-3 text-xs font-bold uppercase tracking-widest text-amber-700"
>
Sin conexión al servidor — el expediente se generó solo localmente
</p>
)}
<FirmasForm
alta={alta}
onCambiarFirma={(f) => actualizar('firma', f)}
onAnterior={anterior}
/>
</>
)}
</div>
</main>
</div>
)
}