feat: ecosistema FRASA — apps Cotizador, Alta Clientes, Cobranza y Landing
- Cotizador (/quote): 4 propuestas con formulas validadas del Excel, comparador, combobox de unidades, vigencia, PDF ANEXO A - Alta Clientes (/client): wizard 8 pasos, validacion CURP RENAPO, OCR de INE, checklist de expediente, firma digital, 5 PDFs legales - Cobranza (/pay): planes de enganche, mora, vista cobranza del dia, recibos PDF, bitacora, dashboard con filtros - Landing (/): entrada al ecosistema - Design system StudioBlank (monocromo, acento #1B4332) en las 4 apps - 123 tests vitest
This commit is contained in:
148
apps/alta-clientes/src/hooks/useAltaCliente.ts
Normal file
148
apps/alta-clientes/src/hooks/useAltaCliente.ts
Normal file
@@ -0,0 +1,148 @@
|
||||
import { useState } from 'react'
|
||||
import type { AltaCliente } from '../types'
|
||||
import { fechaISOHoy } from '../lib/formatters'
|
||||
import { ASESOR_DEFAULT, AUTORIDAD_ID_DEFAULT } from '../data/constantes'
|
||||
import { useDocumentos } from './useDocumentos'
|
||||
|
||||
const datosGeneralesVacios = (): AltaCliente['datosGenerales'] => ({
|
||||
campaniaVenta: '',
|
||||
fecha: fechaISOHoy(),
|
||||
nombreCompleto: '',
|
||||
nacionalidad: 'MEXICANA',
|
||||
nivelEstudios: '',
|
||||
curp: '',
|
||||
rfc: '',
|
||||
nss: '',
|
||||
delegacionMunicipio: '',
|
||||
direccion: '',
|
||||
codigoPostal: '',
|
||||
antiguedadDomicilio: '',
|
||||
fechaNacimiento: '',
|
||||
lugarNacimiento: '',
|
||||
estadoCivil: '',
|
||||
regimenBienes: '',
|
||||
peso: '',
|
||||
estatura: '',
|
||||
email: '',
|
||||
telCasa: '',
|
||||
celular: '',
|
||||
viviendaAnios: '',
|
||||
tipoVivienda: '',
|
||||
tipoCompra: '',
|
||||
actividadOcupacion: '',
|
||||
})
|
||||
|
||||
const empleoVacio = (): AltaCliente['empleo'] => ({
|
||||
tipoEmpleo: '',
|
||||
tipoEconomia: '',
|
||||
compania: '',
|
||||
antiguedadAnios: '',
|
||||
antiguedadMeses: '',
|
||||
direccion: '',
|
||||
colonia: '',
|
||||
numero: '',
|
||||
codigoPostal: '',
|
||||
puesto: '',
|
||||
telefono: '',
|
||||
ext: '',
|
||||
delegacion: '',
|
||||
})
|
||||
|
||||
const economicosVacios = (): AltaCliente['economicos'] => ({
|
||||
ingresosMensuales: 0,
|
||||
otrosIngresos: 0,
|
||||
gastosLuz: 0,
|
||||
gastosOtros: 0,
|
||||
dependientes: { personas: '', parentesco: '', edad: '' },
|
||||
})
|
||||
|
||||
const estadoInicial = (): Omit<AltaCliente, 'documentos'> => ({
|
||||
datosGenerales: datosGeneralesVacios(),
|
||||
empleo: empleoVacio(),
|
||||
economicos: economicosVacios(),
|
||||
coacreditado: {
|
||||
tieneCoacreditado: false,
|
||||
generales: datosGeneralesVacios(),
|
||||
empleo: empleoVacio(),
|
||||
economicos: economicosVacios(),
|
||||
},
|
||||
referencias: [
|
||||
{ nombre: '', telefono: '', parentesco: '', direccion: '' },
|
||||
{ nombre: '', telefono: '', parentesco: '', direccion: '' },
|
||||
{ nombre: '', telefono: '', parentesco: '', direccion: '' },
|
||||
{ nombre: '', telefono: '', parentesco: '', direccion: '' },
|
||||
],
|
||||
viviendaCredito: {
|
||||
proyecto: '',
|
||||
proyectoOtro: '',
|
||||
modelo: '',
|
||||
manzana: '',
|
||||
lote: '',
|
||||
ubicacion: '',
|
||||
superficieM2: '',
|
||||
valorVenta: '',
|
||||
enganche: '',
|
||||
equipamientoAdicional: '',
|
||||
fechaPagoEnganche: '',
|
||||
firmaContrato: '',
|
||||
tiposCredito: [],
|
||||
montoCreditoInfoFovi: '',
|
||||
ahorroVoluntarioSubcuenta: '',
|
||||
tipoProducto: '',
|
||||
descuentoMensualInfoFovissste: '',
|
||||
idAutoridadEmisora: AUTORIDAD_ID_DEFAULT,
|
||||
idNumero: '',
|
||||
idVigencia: '',
|
||||
domicilioFiscal: {
|
||||
calle: '',
|
||||
numExt: '',
|
||||
numInt: '',
|
||||
colonia: '',
|
||||
municipio: '',
|
||||
estado: '',
|
||||
cp: '',
|
||||
pais: 'MEXICO',
|
||||
},
|
||||
},
|
||||
firma: { firmaDataUrl: '', asesorNombre: ASESOR_DEFAULT },
|
||||
})
|
||||
|
||||
export const PASOS = [
|
||||
'Datos generales',
|
||||
'Empleo',
|
||||
'Económicos',
|
||||
'Co-acreditado',
|
||||
'Referencias',
|
||||
'Vivienda y crédito',
|
||||
'Documentos',
|
||||
'Firmas y generar',
|
||||
] as const
|
||||
|
||||
/** Estado global del wizard de alta de clientes */
|
||||
export function useAltaCliente() {
|
||||
const [paso, setPaso] = useState(0)
|
||||
const [datos, setDatos] = useState(estadoInicial)
|
||||
const { documentos, agregarDocumento, quitarDocumento } = useDocumentos()
|
||||
|
||||
const alta: AltaCliente = { ...datos, documentos }
|
||||
|
||||
const actualizar = <K extends keyof typeof datos>(seccion: K, valores: (typeof datos)[K]) => {
|
||||
setDatos((prev) => ({ ...prev, [seccion]: valores }))
|
||||
}
|
||||
|
||||
const siguiente = () => setPaso((p) => Math.min(p + 1, PASOS.length - 1))
|
||||
const anterior = () => setPaso((p) => Math.max(p - 1, 0))
|
||||
const irAPaso = (p: number) => setPaso(p)
|
||||
|
||||
return {
|
||||
paso,
|
||||
siguiente,
|
||||
anterior,
|
||||
irAPaso,
|
||||
datos,
|
||||
alta,
|
||||
actualizar,
|
||||
agregarDocumento,
|
||||
quitarDocumento,
|
||||
}
|
||||
}
|
||||
17
apps/alta-clientes/src/hooks/useDocumentos.ts
Normal file
17
apps/alta-clientes/src/hooks/useDocumentos.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { useCallback, useState } from 'react'
|
||||
import type { DocumentoCargado, SlotDocumento } from '../types'
|
||||
|
||||
/** Maneja los documentos del expediente en memoria (uno por slot) */
|
||||
export function useDocumentos() {
|
||||
const [documentos, setDocumentos] = useState<DocumentoCargado[]>([])
|
||||
|
||||
const agregarDocumento = useCallback((doc: DocumentoCargado) => {
|
||||
setDocumentos((prev) => [...prev.filter((d) => d.slot !== doc.slot), doc])
|
||||
}, [])
|
||||
|
||||
const quitarDocumento = useCallback((slot: SlotDocumento) => {
|
||||
setDocumentos((prev) => prev.filter((d) => d.slot !== slot))
|
||||
}, [])
|
||||
|
||||
return { documentos, agregarDocumento, quitarDocumento }
|
||||
}
|
||||
Reference in New Issue
Block a user