Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/lucavallini/aibar-frontend/llms.txt

Use this file to discover all available pages before exploring further.

Every data-access concern in Aibar SRL App is encapsulated in a dedicated Angular service located under src/app/core/services/. All services are decorated with @Injectable({ providedIn: 'root' }), which means Angular registers a single shared instance in the root injector — no module imports required. Each service receives HttpClient via constructor injection and builds its endpoint URLs from environment.apiUrl, making it straightforward to point the whole app at a different backend by changing a single environment file. The authInterceptor (registered in appConfig as an HTTP_INTERCEPTORS functional interceptor) automatically attaches the Authorization: Bearer <token> header to every outgoing request, so individual services never need to manage authentication headers manually.

RespuestaPaginada<T>

Every list endpoint in the Aibar backend returns a consistent paginated envelope. The TypeScript interface that models this shape lives in src/app/core/models/paginacion.model.ts:
export interface RespuestaPaginada<T> {
  items: T[];
  total: number;
  pagina: number;
  tamano_pagina: number;
  total_paginas: number;
}
FieldTypeDescription
itemsT[]The records for the requested page
totalnumberTotal number of matching records across all pages
paginanumberCurrent page number (1-based)
tamano_paginanumberNumber of records per page
total_paginasnumberTotal number of pages given the current page size
All service methods that return lists are typed as Observable<RespuestaPaginada<T>>, so consuming components can drive the Paginacion component directly from the response fields.

Auth Interceptor

The interceptor is a functional HttpInterceptorFn registered in appConfig. It reads the session token from sessionStorage and clones every outgoing request to add the Authorization header when a token is present.
// src/app/core/interceptors/auth.interceptor.ts
import { HttpInterceptorFn } from '@angular/common/http';

export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const token = sessionStorage.getItem('aibar_token');

  if (token) {
    const reqClonado = req.clone({
      setHeaders: { Authorization: `Bearer ${token}` }
    });
    return next(reqClonado);
  }

  return next(req);
};
Register authInterceptor in appConfig inside app.config.ts using provideHttpClient(withInterceptors([authInterceptor])). Without this, authenticated API calls will receive 401 Unauthorized responses.

Services

File: src/app/core/services/auth.service.tsAuthService manages login, logout, token storage, and the reactive isLoggedIn signal. The token is stored in sessionStorage under the key aibar_token, so it is cleared automatically when the browser tab is closed.
import { Injectable, signal } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { Observable, tap } from 'rxjs';
import { environment } from '../../../environments/environment';
import { LoginResponse } from '../models/usuario.model';

@Injectable({ providedIn: 'root' })
export class AuthService {
  private apiUrl = environment.apiUrl;
  private tokenKey = 'aibar_token';

  isLoggedIn = signal<boolean>(this.hayToken());

  constructor(private http: HttpClient, private router: Router) {}
}
MethodSignatureDescription
login(nombreUsuario: string, password: string): Observable<LoginResponse>POSTs to /auth/login with application/x-www-form-urlencoded body (OAuth2 password flow). On success, stores the token in sessionStorage and sets isLoggedIn to true.
logout(): voidRemoves the token from sessionStorage, sets isLoggedIn to false, and navigates to /login.
getToken(): string | nullReturns the raw JWT from sessionStorage.
getPayload(): { sub: string; rol: string } | nullDecodes the JWT payload (base64) and returns the typed object, or null if there is no valid token.
getRol(): string | nullConvenience wrapper that returns only the rol claim from the JWT payload.
File: src/app/core/services/viajes.service.tsViajesService handles all trip lifecycle operations. Trips follow a state machine: pendienteen_cursofinalizado (or cancelado).
@Injectable({ providedIn: 'root' })
export class ViajesService {
  private apiUrl = `${environment.apiUrl}/viajes`;

  constructor(private http: HttpClient) {}
}
MethodSignatureDescription
listar(estado?: string, pagina?: number, tamanoPagina?: number): Observable<RespuestaPaginada<Viaje>>Lists trips with optional estado filter. Defaults: pagina=1, tamanoPagina=20.
crear(datos: ViajeCreate): Observable<Viaje>POSTs a new trip to POST /viajes/.
iniciar(id: string): Observable<Viaje>Transitions a trip from pendiente to en_curso via POST /viajes/{id}/iniciar.
finalizar(id: string, fechaFin: string, kmsRecorridos: number): Observable<Viaje>Completes a trip via POST /viajes/{id}/finalizar, recording end date and kilometres.
cancelar(id: string, motivoCancelacion: string): Observable<Viaje>Cancels a trip via POST /viajes/{id}/cancelar, recording the cancellation reason.
File: src/app/core/services/choferes.service.tsChoferesService manages driver (chofer) CRUD. Drivers can be in one of three states: disponible, viajando, or inactivo. Soft-deletion is handled via darDeBaja.
@Injectable({ providedIn: 'root' })
export class ChoferesService {
  private apiUrl = `${environment.apiUrl}/choferes`;

  constructor(private http: HttpClient) {}
}
MethodSignatureDescription
listar(activosOnly?: boolean, pagina?: number, tamanoPagina?: number): Observable<RespuestaPaginada<Chofer>>Lists drivers. activosOnly defaults to true, filtering out soft-deleted records.
obtenerPorId(id: string): Observable<Chofer>Fetches a single driver by UUID.
crear(datos: ChoferCreate): Observable<Chofer>Creates a new driver via POST /choferes/.
cambiarEstado(id: string, estado: string): Observable<Chofer>PATCHes the driver’s status to one of disponible, viajando, or inactivo.
actualizar(id: string, datos: Partial<ChoferCreate>): Observable<Chofer>PATCHes any subset of driver fields.
darDeBaja(id: string): Observable<Chofer>Soft-deletes a driver via DELETE /choferes/{id}.
File: src/app/core/services/camiones.service.tsCamionesService manages the truck fleet. Like drivers, trucks support soft-deletion.
@Injectable({ providedIn: 'root' })
export class CamionesService {
  private apiUrl = `${environment.apiUrl}/camiones`;

  constructor(private http: HttpClient) {}
}
MethodSignatureDescription
listar(activosOnly?: boolean, pagina?: number, tamanoPagina?: number): Observable<RespuestaPaginada<Camion>>Lists trucks. activosOnly defaults to true.
crear(datos: CamionCreate): Observable<Camion>Creates a new truck via POST /camiones/.
actualizar(id: string, datos: Partial<CamionCreate>): Observable<Camion>PATCHes any subset of truck fields.
darDeBaja(id: string): Observable<Camion>Soft-deletes a truck via DELETE /camiones/{id}.
File: src/app/core/services/multas.service.tsMultasService handles traffic fines (multas). Fines are registered with a fecha that can be set retroactively, since physical notification from the municipality may arrive days after the infraction.
@Injectable({ providedIn: 'root' })
export class MultasService {
  private apiUrl = `${environment.apiUrl}/multas`;

  constructor(private http: HttpClient) {}
}
MethodSignatureDescription
listar(pagina?: number, tamanoPagina?: number): Observable<RespuestaPaginada<Multa>>Lists all fines, paginated. Defaults: pagina=1, tamanoPagina=20.
crear(datos: MultaCreate): Observable<Multa>Records a new fine via POST /multas/.
File: src/app/core/services/combustible.service.tsCombustibleService tracks fuel loads per truck. The gastoTotalPorCamion aggregation endpoint is used to display total litres, total cost, and number of loads per truck.
@Injectable({ providedIn: 'root' })
export class CombustibleService {
  private apiUrl = `${environment.apiUrl}/combustible`;

  constructor(private http: HttpClient) {}
}
MethodSignatureDescription
listar(camionId?: string, pagina?: number, tamanoPagina?: number, soloUltimos30Dias?: boolean): Observable<RespuestaPaginada<CargaCombustible>>Lists fuel loads. Optional filter by truck UUID. soloUltimos30Dias defaults to true.
crear(datos: CargaCombustibleCreate): Observable<CargaCombustible>Records a new fuel load via POST /combustible/.
gastoTotalPorCamion(camionId: string): Observable<{ camion_id: string; total_litros: number; total_monto: number; cantidad_cargas: number }>Returns the aggregated fuel spend for a specific truck via GET /combustible/{camionId}/gasto-total.
File: src/app/core/services/auditoria.service.tsAuditoriaService provides read-only access to the audit log. This endpoint is restricted to administrators on the backend.
@Injectable({ providedIn: 'root' })
export class AuditoriaService {
  private apiUrl = `${environment.apiUrl}/auditoria`;

  constructor(private http: HttpClient) {}
}
MethodSignatureDescription
listar(entidad?: string, pagina?: number, tamanoPagina?: number): Observable<RespuestaPaginada<Auditoria>>Lists audit log entries. Optional entidad filter (e.g. "viajes", "choferes"). Defaults: pagina=1, tamanoPagina=50.
File: src/app/core/services/usuarios.service.tsUsuariosService manages system users. Two interfaces are defined directly in this service file — UsuarioCreate and UsuarioUpdate — since they are used only here.
export interface UsuarioCreate {
  nombre_completo: string;
  dni: string;
  password: string;
  rol: 'administrador' | 'empleado';
}

export interface UsuarioUpdate {
  nombre_completo?: string;
  dni?: string;
  rol?: 'administrador' | 'empleado';
}

@Injectable({ providedIn: 'root' })
export class UsuariosService {
  private apiUrl = `${environment.apiUrl}/usuarios`;

  constructor(private http: HttpClient) {}
}
MethodSignatureDescription
listar(pagina?: number, tamanoPagina?: number): Observable<RespuestaPaginada<Usuario>>Lists all users, paginated. Defaults: pagina=1, tamanoPagina=20.
crear(datos: UsuarioCreate): Observable<Usuario>Creates a new user via POST /usuarios/.
actualizar(id: string, datos: UsuarioUpdate): Observable<Usuario>PATCHes a user’s profile fields via PATCH /usuarios/{id}.
darDeBaja(id: string): Observable<Usuario>Soft-deletes a user via DELETE /usuarios/{id}.
File: src/app/core/services/theme.service.tsThemeService does not make any HTTP calls. It manages the application’s dark/light theme using Angular signals and persists the user’s preference in localStorage under the key aibar_theme. An Angular effect() runs whenever the esOscuro signal changes, toggling the .tema-oscuro CSS class on document.body and syncing to storage.
import { Injectable, signal, effect } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class ThemeService {
  private storageKey = 'aibar_theme';

  esOscuro = signal<boolean>(this.leerPreferenciaGuardada());

  constructor() {
    effect(() => {
      document.body.classList.toggle('tema-oscuro', this.esOscuro());
      localStorage.setItem(this.storageKey, this.esOscuro() ? 'oscuro' : 'claro');
    });
  }

  alternar(): void {
    this.esOscuro.set(!this.esOscuro());
  }

  private leerPreferenciaGuardada(): boolean {
    return localStorage.getItem(this.storageKey) === 'oscuro';
  }
}
MemberTypeDescription
esOscuroSignal<boolean>Reactive signal — true when dark mode is active. Read in templates as themeService.esOscuro().
alternar()voidFlips the signal, which triggers the effect() and updates the DOM + localStorage.

Build docs developers (and LLMs) love