Arquitectura general
Aplicación Angular 18 monolítica en un único proyecto (backoffice), organizada con NgModules: los schematics de angular.json generan componentes, directivas y pipes con standalone: false. Excepciones standalone: true: DateTimePickerComponent, los componentes de mensajes programados (ScheduledMessagesFilterComponent, ScheduledMessagesTableComponent) y los del chat PostponeDialogComponent, ScheduleMessageDialogComponent, ScheduledMessageStripComponent y ScheduleSendButtonComponent. El builder es @angular-devkit/build-angular:browser y la salida va a dist/backoffice.
Estructura de src/
src/
├── main.ts # bootstrapModule(AppModule); enableProdMode si environment.production
├── index.html, styles.scss # estilos globales y variables CSS (--zg-chat-*)
├── environments/ # ignorado por git (ver Entornos)
├── assets/
│ ├── i18n/ # es.json, en.json
│ ├── scss/, fonts/, images/, svg/, audio/, mocks/
└── app/
├── app.module.ts, app-routing.module.ts, app.component.ts
├── core/ # singleton: guards, interceptores, servicios, estado, interfaces, helpers
├── shared/ # componentes, directivas, pipes, validadores y rutas de layout
└── features/ # un módulo lazy por área de negocio
El alias src/app/... se usa en imports (por baseUrl: "./" en tsconfig.json).
Arranque (AppModule)
src/app/app.module.ts configura:
StoreModule.forRoot(ROOT_REDUCERS)yEffectsModule.forRoot(ROOT_EFFECTS);StoreDevtoolsModule.instrument({ maxAge: 25, logOnly: !isDevMode() }).TranslateModule.forRootconTranslateHttpLoaderapuntando a./assets/i18n/y extensión.json.ToastrModule.forRoot(DEFAULT_GLOBAL_TOASTR_CONFIG),NgbModule,OverlayModule(CDK), barras de carga (LoadingBarHttpClientModule,LoadingBarRouterModule,LoadingBarModule).- Providers HTTP:
AUTH_TOKEN_INTERCEPTOR_PROVIDERS,ERROR_INTERCEPTOR_PROVIDERS,DEVICE_TOKEN_INTERCEPTOR_PROVIDERS(ver Auth e interceptores). provideHighchartscon importación diferida dehighcharts/highstock.
AppComponent (app.component.ts), al construirse, despacha UserActions.loadUserSession() y loadPreviewLanguage(), y aplica el idioma del store salvo que la URL traiga ?lang=.
core/
| Carpeta | Contenido |
|---|---|
guards/ | auth.guard.ts, loggedIn.guard.ts, admin.guard.ts, permission.guard.ts |
interceptors/ | auth-token, http-error, device-token |
services/api/ | Clientes HTTP por recurso (ver Servicios) |
services/ui/ | Servicios de UI, sockets, sesión, permisos |
states/ | NgRx: app.state.ts y una carpeta por slice (ver Estado) |
interfaces/api, interfaces/ui | Tipos del dominio y de UI |
helpers/global, helpers/ui | Constantes (API_URLS, PAGE_URLS, SOCKET_EVENTS, ...), utilidades y el menú lateral (nav.constant.ts) |
:::note Constantes heredadas
helpers/global contiene constantes de otros dominios (casino.constants.ts, sport-manaments.constant.ts, virtualBets.constans.ts, affiliates.constants.ts, ...). Ningún otro archivo de src/app las importa: parecen restos de una base de backoffice anterior.
:::
shared/
Un único SharedModule (shared/shared.module.ts) declara y exporta componentes, directivas y pipes reutilizables. Detalle en Compartido. Las rutas de los dos layouts viven en shared/routes/content.routes.ts y shared/routes/full.routes.ts (ver Rutas).
features/
Cada carpeta es un NgModule con su *-routing.module.ts, pages/ (contenedores) y components/ (presentacionales: filtro, tabla, modal). El patrón repetido en los CRUD es pagina → filtro + tabla + modal-formulario. Ver Features.
Convenciones observadas en el código
- Contenedor / presentacional: las páginas (
*-page.component.ts) solo componen; la lógica vive en las tablas, modales y servicios. - Plantillas con control flow nuevo (
@if,@for) en los componentes recientes, como las conexiones. - Selectores con prefijo de feature, por ejemplo
connections-connections-table. - Estado local vs NgRx: el estado de tickets, autenticación, idioma, tema, departamentos, chat interno, mensajes programados y settings va a NgRx; el resto (conexiones, contactos, etc.) se carga por HTTP desde el componente.