Passa al contenuto principale

Frontend Overview

The Flo frontend is an Angular 21 SPA using standalone components, signals, OnPush change detection, and PrimeNG for UI.

Tech Stack​

TechnologyVersionPurpose
Angular21Framework (standalone components, signals)
PrimeNG21UI component library (Lara theme)
Tailwind CSS3.4Utility-first styling
NGRX ComponentStore21State management
Transloco7.6Internationalization (Italian + English)
TipTap2.24Rich text editor (WYSIWYG)
Leaflet1.9Interactive maps
Chart.js4.5Data visualization
GSAP3.13Animations (sidebar, mobile tab bar)
Vitevia @angular/buildBuild tool

App Structure​

src/app/
├── features/ # Feature modules (lazy-loaded)
│ ├── auth/ # Login, register, OTP, password reset
│ ├── dashboard/ # Main authenticated app
│ │ ├── prenotazioni/ # Booking management
│ │ ├── orari/ # Scheduling
│ │ ├── account/ # User profile & settings
│ │ └── amministrazione/ # Admin panel
│ │ ├── utenti/ # User management
│ │ ├── professionisti/ # Staff management
│ │ ├── servizi/ # Service/activity management
│ │ ├── locazioni/ # Locations
│ │ ├── chiusure/ # Studio closures
│ │ ├── blogs/ # Blog management (Strapi)
│ │ ├── newsletter/ # Newsletter management
│ │ ├── gallery/ # Media gallery
│ │ └── settings/ # App settings (SuperAdmin)
│ ├── immobili/ # Dynamic entity management
│ └── home/ # Privacy policy, terms
├── components/ # 33 shared components
├── services/ # API clients, stores, utilities
├── guards/ # Auth, role, feature flag guards
├── pipes/ # Custom pipes (branding, formatting)
├── directives/ # Custom directives
├── utils/ # Helper utilities
└── assets/i18n/ # Translation files (it.json, en.json)

Key Patterns​

Standalone Components​

All components are standalone (no NgModules):

@Component({
selector: 'app-feature',
standalone: true,
imports: [CommonModule, TranslocoModule, ButtonModule],
changeDetection: ChangeDetectionStrategy.OnPush
})

Signal-Based Reactivity​

// Local component state
protected readonly loading = signal(false);
protected readonly searchTerm = signal('');

// Derived state
protected readonly hasFilters = computed(() => this.searchTerm().length > 0);

Thin Components​

All business logic lives in stores/services. Components only handle:

  • Template bindings
  • UI event delegation to stores
  • Local UI state (signals)

Dependency Injection​

Use inject() function, never constructor injection:

private readonly store = inject(GlobalStore);
private readonly messageService = inject(MessageService);

Template Control Flow​

Use new Angular control flow syntax:

@if (loading()) {
<p-progressSpinner />
} @else {
@for (item of items(); track item.id) {
<app-item [data]="item" />
}
}

Icons​

Material Symbols only. PrimeIcons are forbidden:

<!-- Correct -->
<span class="material-symbols-outlined">add</span>

<!-- Forbidden -->
<i class="pi pi-plus"></i>

API Clients​

Auto-generated from backend OpenAPI spec using NSwag:

npm run generate-proxies

Produces:

  • src/app/services/client.ts — Private API client
  • src/app/services/public-api-client.ts — Public API client

PWA​

  • Service worker enabled in production builds
  • Separate manifests per brand
  • Auto-update checks every 6 hours
  • Install prompts via @khmyznikov/pwa-install

Internationalization​

Uses @jsverse/transloco with Italian as default:

  • Translations pre-loaded during APP_INITIALIZER
  • Language preference persisted in localStorage
  • PrimeNG component translations updated on language change
  • CI check validates both translation files have matching keys

All user-facing text must use the Transloco pipe:

{{ 'feature.title' | transloco }}

Translations must be added to both it.json and en.json.