Overview
The StateService manages the global application state using Angular signals. It handles user authentication, shift management, system configuration, and maintains stores for users, roles, and machines.
Location: src/services/state.service.ts
Provider: Root (singleton)
State Properties
Signals
Global system configuration including shift times, password policies, plant name, and operator messages.
Currently authenticated user object or null if not logged in.
Current shift selection: ‘Turno Día’, ‘Turno Noche’, or null.
Sidebar collapsed state for UI layout management.
Current synchronization status: ‘online’, ‘offline’, ‘syncing’, or ‘conflict’.
Number of pending items awaiting synchronization.
Complete list of application users with credentials and roles.
Role definitions with permissions: Jefatura, Supervisor, Operario, Sistemas.
All machines in the plant (Impresión, Troquelado, Acabado) with status and location.
Computed Signals
Computed from currentUser - returns true if user is authenticated.
Computed user display name, returns ‘Invitado’ if not logged in.
Computed user role, returns empty string if not logged in.
Types
UserRole
type UserRole = 'Jefatura' | 'Supervisor' | 'Asistente' | 'Operario' | 'Encargado' | 'Sistemas';
Shift
type Shift = 'Turno Día' | 'Turno Noche' | string | null;
SyncStatus
type SyncStatus = 'online' | 'offline' | 'syncing' | 'conflict';
User Interface
interface User {
id: string;
name: string;
role: UserRole;
avatar?: string;
}
Machine Interface
interface Machine {
id: string;
code: string;
name: string;
type: string;
area: string;
status: 'Operativa' | 'Mantenimiento' | 'Detenida' | 'Sin Operador';
active: boolean;
}
Methods
login
Authenticates a user and sets the current shift.
login(username: string, shift: Shift): void
Username to authenticate. Matches against adminUsers or uses predefined mappings.
Selected shift: ‘Turno Día’, ‘Turno Noche’, or custom shift name.
Behavior:
- Searches for user in
adminUsers() by username (case-insensitive)
- Falls back to predefined mappings: ‘admin’ → Sistemas, ‘jefe’ → Jefatura, ‘operario’ → Operario
- Sets
currentUser and currentShift signals
- Logs authentication event via AuditService
// Inject service
import { inject } from '@angular/core';
import { StateService } from './services/state.service';
const stateService = inject(StateService);
// Login as supervisor in day shift
stateService.login('jperez', 'Turno Día');
// Login as admin in night shift
stateService.login('admin', 'Turno Noche');
logout
Logs out the current user and clears authentication state.
Behavior:
- Logs logout event with current user info
- Sets
currentUser to null
- Sets
currentShift to null
stateService.logout();
console.log(stateService.isLoggedIn()); // false
console.log(stateService.userName()); // 'Invitado'
Toggles the sidebar collapsed state.
Behavior:
- Inverts the current value of
isSidebarCollapsed signal
stateService.toggleSidebar();
const isCollapsed = stateService.isSidebarCollapsed(); // true/false
setSyncStatus
Updates the synchronization status.
setSyncStatus(status: SyncStatus): void
New sync status: ‘online’, ‘offline’, ‘syncing’, or ‘conflict’.
// Set to syncing during background sync
stateService.setSyncStatus('syncing');
// Set to online when complete
stateService.setSyncStatus('online');
// Handle offline state
stateService.setSyncStatus('offline');
updateMachine
Updates a machine’s status or properties.
updateMachine(updatedMachine: Machine): void
Complete machine object with updated properties.
Behavior:
- Updates machine in
adminMachines signal by matching ID
- Logs operational update via AuditService
const machines = stateService.adminMachines();
const machine = machines.find(m => m.code === 'IMP-01');
if (machine) {
stateService.updateMachine({
...machine,
status: 'Mantenimiento'
});
}
Usage Examples
Reactive Authentication Check
import { Component, inject, effect } from '@angular/core';
import { StateService } from './services/state.service';
@Component({
selector: 'app-protected',
template: `
@if (state.isLoggedIn()) {
<h1>Welcome {{ state.userName() }}</h1>
<p>Role: {{ state.userRole() }}</p>
} @else {
<p>Please log in</p>
}
`
})
export class ProtectedComponent {
state = inject(StateService);
constructor() {
// React to authentication changes
effect(() => {
if (!this.state.isLoggedIn()) {
console.log('User logged out');
}
});
}
}
Monitor Sync Status
import { Component, inject, computed } from '@angular/core';
import { StateService } from './services/state.service';
@Component({
selector: 'app-sync-indicator',
template: `
<div class="sync-status" [class]="statusClass()">
{{ syncMessage() }}
</div>
`
})
export class SyncIndicatorComponent {
state = inject(StateService);
statusClass = computed(() => {
return `status-${this.state.syncStatus()}`;
});
syncMessage = computed(() => {
const status = this.state.syncStatus();
const count = this.state.pendingSyncCount();
switch(status) {
case 'online': return 'Sincronizado';
case 'offline': return 'Sin conexión';
case 'syncing': return `Sincronizando (${count} pendientes)`;
case 'conflict': return 'Conflicto de sincronización';
}
});
}
Access System Configuration
import { inject } from '@angular/core';
import { StateService } from './services/state.service';
const state = inject(StateService);
const config = state.config();
console.log('Plant:', config.plantName);
console.log('Day shift starts:', config.shiftTime1);
console.log('Night shift starts:', config.shiftTime2);
console.log('Auto logout:', config.autoLogoutMinutes, 'minutes');
Filter Active Machines by Type
import { computed, inject } from '@angular/core';
import { StateService } from './services/state.service';
const state = inject(StateService);
// Get all active printing machines
const printingMachines = computed(() =>
state.adminMachines()
.filter(m => m.type === 'Impresión' && m.active)
);
// Get machines in maintenance
const maintenanceMachines = computed(() =>
state.adminMachines()
.filter(m => m.status === 'Mantenimiento')
);
Integration with AuditService
The StateService automatically logs the following events:
- Login: User authentication with username and shift
- Logout: Session termination
- Machine Updates: Status changes (Operativa, Mantenimiento, etc.)
All audit logs include:
- User name and role (from current session)
- Module: ‘ACCESO’ or ‘OPERACIONES’
- Action description
- Timestamp and simulated IP address
Notes
- All state is managed using Angular signals for fine-grained reactivity
- The service is a singleton provided at root level
- Machine data includes 35+ machines across Impresión, Troquelado, and Acabado areas
- Default users include Jefatura, Supervisor, Operario, and Sistemas roles
- Authentication is simplified for demonstration - integrate real backend in production