Módulo Banco de Sangre
Análisis de rutas, componentes y flujos del módulo de Banco de Sangre, definidas en
src/app/pages/page.routes.ts.
{ path: 'banco/sangre', component: ReceptoresComponent },
{ path: 'documentos/paciente/:id', component: DocspacienteComponent },
{ path: 'productos', component: ProductosComponent },
{ path: 'reacciones/adversas/:id', component: ReaccionesAdversasComponent },
{ path: 'reacciones/transfucionales', component: ReaccionesTransfucionalesComponent },
1. banco/sangre → ReceptoresComponent
Ruta
Ubicación: src/app/pages/receptores/
Qué hace:
- Lista los pacientes/receptores de la sede actual (
localStorage.getItem('cede')). - Carga inicial vía
PacientesService.getPacientesSede(sede). - Buscador por nombre (
getPacientePorNombre), activo cuando el texto tiene más de 3 caracteres. - Paginación con
ngx-pagination(paginaAnterior/siguentePaginausangetPacientes(intervalo), un endpoint distinto al degetPacientesSede).
Componentes / servicios involucrados:
app-titulos— header genérico de la vista.PacientesService(getPacientesSede,getPacientePorNombre,getPacientes).NgxSpinnerService.- Navegación:
/registro/pacientes(alta de paciente),/paciente/:id(detalle, click en fila).
2. documentos/paciente/:id → DocspacienteComponent
Ruta
Ubicación: src/app/pages/docspaciente/
Qué hace:
- Pantalla para adjuntar los 4 documentos obligatorios del receptor:
- Consentimiento informado de transfusión
- Resumen médico
- Últimos laboratorios
- Solicitud de componentes sanguíneos
- Obtiene el paciente con
PacientesService.getPacienteBtID(id). - Permite subir archivos con
ngx-dropzone, convertidos a base64 (fileToBase64). - Al guardar (
agregarDocumentosReceptor):- Valida que existan ≥ 4 archivos; si no, muestra alerta de error (Swal).
generaridCensur()→BancodesangreService.agregarReceptor()crea el registro en CENSUR y guardaidCensurenlocalStorage.enviarDoc(id)→BancodesangreService.agregarDocumentosReceptor()sube los documentos.- Navega a
/productos.
Componentes / servicios involucrados:
ficha-info-user— muestra ficha del paciente, recibepacienteInfo.BancodesangreService(agregarReceptor,agregarDocumentosReceptor).sweetalert/sweetalert2— notificaciones.NgxSpinnerService.
3. productos → ProductosComponent
Ruta
Ubicación: src/app/pages/censur-productos/productos/
Qué hace:
- Es solo un wrapper vacío (
<app-pedidos></app-pedidos>); toda la lógica real vive enPedidosComponent.
Componente real: PedidosComponent (src/app/components/censur-pedido/pedidos/)
- Carga el catálogo de productos vía
BancodesangreService.allproductosAlmacen(). - Maneja un "carrito" persistido en
localStoragemediante la claseCarritoCensur(src/app/clases/carrito-censur/censur-carrito). - Acciones del carrito:
agregarCarrito,eliminar,validarCarrito. - Al enviar la solicitud (
enviarSolicitud):- Usa
idCensurdelocalStorage(generado en el paso anterior,DocspacienteComponent). generarTypeCruce()→ genera orden de "TIPE Y CRUCE" para laboratorio.generarOrdenReceptor()→ genera la orden del pedido en CENSUR.- Limpia
localStorage(idCensur,censur-carrito) y navega a/dashboard.
- Usa
Componentes / servicios involucrados:
CarritoCensur(src/app/clases/carrito-censur/censur-carrito).- Funciones de
src/app/functions/storage/pacienteIntegrados. BancodesangreService(allproductosAlmacen,generarTypeCruce,generarOrdenReceptor).sweetalert,NgxSpinnerService.
4. reacciones/adversas/:id → ReaccionesAdversasComponent
Ruta
Ubicación: src/app/pages/reacciones-adversas/
Qué hace:
- Registro post-transfusión: confirma si hubo reacción adversa y permite cargar la documentación.
- Obtiene el pedido/receptor con
BancodesangreService.getOrdenPedidoReceptor(id)y muestra los datos del paciente. - Switch para marcar si hubo reacción adversa (
huboReaccionAdversa, valores'si'/ vacío). - Sube un PDF de "Reacción Transfusional" (dropzone + base64).
- Al guardar (
guardarDocumentos):cambioEstadoRecpetor(id, { estado: 'FINALIZADO' })cierra el caso del receptor.agregarDocumetosReaccionesTransfucionales(id, { reaccionestransfucionales, huboReaccionAdversa })adjunta el documento y la respuesta del switch.- Navega a
/dashboard.
Componentes / servicios involucrados:
ficha-info-user.BancodesangreService(getOrdenPedidoReceptor,cambioEstadoRecpetor,agregarDocumetosReaccionesTransfucionales).NgxSpinnerService.
5. reacciones/transfucionales → ReaccionesTransfucionalesComponent
Ruta
Ubicación: src/app/pages/admin/reacciones-transfucionales/
Qué hace:
- Bitácora/listado de todas las reacciones transfusionales registradas.
BancodesangreService.bitacoraReaccionesTransfucionales()trae la lista, filtrando solo registros conpaciente != null.- Buscador por nombre usando el helper
buscarReceptor(src/app/helpers/filterReceptor.ts). - Cada fila enlaza a
/reacciones/adversas/:id→ alimenta directamente la ruta #4.
Componentes / servicios involucrados:
app-titulos.BancodesangreService(bitacoraReaccionesTransfucionales).- Interfaces
Reacciones/Paciente(reaciones.interface.ts). NgxSpinnerService.
Pendiente: comentario // TODO: AGREGAR EL PAGINADOR — la lista no está paginada.
Servicios y dependencias compartidas
| Elemento | Ubicación | Usado por |
|---|---|---|
PacientesService | src/app/services/pacientes/ | ReceptoresComponent, DocspacienteComponent |
BancodesangreService | src/app/services/bancodeSangre/ | DocspacienteComponent, PedidosComponent, ReaccionesAdversasComponent, ReaccionesTransfucionalesComponent |
ficha-info-user | src/app/components/ficha-identificacion/ficha-info-user/ | DocspacienteComponent, ReaccionesAdversasComponent |
app-titulos | src/app/components/ficha-identificacion/titulos/ | ReceptoresComponent, ReaccionesTransfucionalesComponent |
app-pedidos (PedidosComponent) | src/app/components/censur-pedido/pedidos/ | ProductosComponent |
CarritoCensur | src/app/clases/carrito-censur/censur-carrito | PedidosComponent |
buscarReceptor | src/app/helpers/filterReceptor.ts | ReaccionesTransfucionalesComponent |
NgxSpinnerService | librería ngx-spinner | todos los componentes |
sweetalert / sweetalert2 | librerías externas | DocspacienteComponent, PedidosComponent |
localStorage como puente de estado
En lugar de pasar datos entre rutas mediante un servicio o estado de Angular, el flujo se apoya en localStorage:
| Clave | Escrita en | Leída en |
|---|---|---|
cede | (login / sesión) | ReceptoresComponent |
idCensur | DocspacienteComponent (generaridCensur) | PedidosComponent (enviarSolicitud), luego se elimina |
censur-carrito | PedidosComponent (CarritoCensur) | PedidosComponent, luego se elimina |
usuario | (login / sesión) | PedidosComponent (setPedido) |
Flujo end-to-end (camino feliz)
Casos de uso
Registrar documentos de un receptor nuevo
Actor: Personal de banco de sangre.
Disparador: El receptor fue dado de alta (o ya existe) y necesita iniciar el proceso de solicitud de hemoderivados.
- El usuario entra a
/banco/sangrey busca/selecciona al paciente. - Navega a
/documentos/paciente/:id. - La ficha del paciente se carga automáticamente (
ficha-info-user). - El usuario adjunta los 4 documentos requeridos vía dropzone.
- Presiona "Guardar":
- Si hay menos de 4 archivos → se muestra alerta indicando los documentos faltantes (caso de error, ver CU-1a).
- Si hay 4 o más → se genera el registro en CENSUR (
idCensur) y se suben los documentos.
- El sistema redirige a
/productos.
Documentación incompleta:
- El usuario intenta guardar con menos de 4 archivos.
- Se muestra un modal (
Swal.fire) listando los documentos obligatorios faltantes. - El usuario permanece en la misma pantalla para completar la carga.
Generar pedido de productos sanguíneos
Actor: Personal de banco de sangre.
Precondición: Existe un idCensur válido en localStorage (generado en CU-1).
- Tras ser redirigido a
/productos, el sistema (PedidosComponent) carga el catálogo de productos disponibles desde el almacén. - El usuario agrega productos al carrito (
agregarCarrito), pudiendo eliminar ítems (eliminar). - Presiona "Enviar solicitud":
- Si el carrito está vacío → alerta de error "Necesitas agregar un producto al carrito" (caso de error, ver CU-2a).
- Si tiene ítems → se arma el
pedido(incluyevendedorysededesdelocalStorage.usuario) y elpedidoLab(orden de tipo y cruce).
- Se llaman en paralelo
generarTypeCruce()ygenerarOrdenReceptor(). - Se muestra alerta de éxito, se limpia
localStorage(idCensur,censur-carrito) y se redirige a/dashboard.
Carrito vacío:
- El usuario presiona "Enviar solicitud" sin productos en el carrito.
- Se muestra
swal("Necesitas agregar un producto al carrito", {icon:"error"}). - El flujo no continúa (no se generan órdenes ni se limpia el storage).
Consultar bitácora de reacciones transfusionales
Actor: Personal médico / supervisor.
Disparador: Necesita revisar el estado de los pedidos/receptores y dar seguimiento a posibles reacciones.
- El usuario entra a
/reacciones/transfucionales. - El sistema carga la bitácora completa (
bitacoraReaccionesTransfucionales), filtrando registros sin paciente asociado. - El usuario puede filtrar por nombre del paciente (búsqueda con ≥3 caracteres usando
buscarReceptor). - El usuario hace click en un registro → navega a
/reacciones/adversas/:id.
Registrar reacción adversa y cerrar el caso del receptor
Actor: Personal médico.
Precondición: Existe un pedido/orden asociado al id del receptor (originado en CU-2).
- Desde
/reacciones/adversas/:id, el sistema carga los datos del paciente víagetOrdenPedidoReceptor(id). - El usuario activa el switch "¿Hubo reacción adversa después de la transfusión?" si aplica (
huboReaccion = 'si'). - El usuario adjunta el documento "Reacción Transfusional" (dropzone, un solo archivo usado:
imagenes[0]). - Presiona "Guardar":
- Se cambia el estado del receptor a
FINALIZADO(cambioEstadoRecpetor). - Se adjunta el documento junto con el indicador de reacción adversa (
agregarDocumetosReaccionesTransfucionales).
- Se cambia el estado del receptor a
- El sistema redirige a
/dashboard.
Nota: No hay un caso alterno de validación visible — a diferencia deDocspacienteComponent, aquí se permite guardar aunque no se haya adjuntado ningún archivo (imagenes[0]podría serundefined).
Observaciones / posibles riesgos detectados
- Estado compartido vía
localStorage(idCensur,censur-carrito,usuario,cede): si el usuario navega fuera del flujo o abre otra pestaña, el estado puede quedar inconsistente o perderse. ReaccionesTransfucionalesComponentno pagina resultados (TODO pendiente en el código), lo que puede impactar el rendimiento con bitácoras grandes.ReceptoresComponent:paginaAnterior/siguentePaginallaman aPacientesService.getPacientes(intervalo), un endpoint distinto al usado en la carga inicial (getPacientesSede); esto podría producir resultados inconsistentes con la sede filtrada.ReaccionesAdversasComponent.guardarDocumentosno valida que se haya subido un documento antes de enviar (this.imagenes[0]puede serundefined).- Código comentado / bloques muertos presentes en
DocspacienteComponent(agregarDocumentos, sección de "Documentos Adjuntos" en el HTML) que podrían limpiarse.