Files
iti-technology/apps/private/src/app/app.routes.ts
T
Lorenzo SanesiandClaude Opus 5.5 b83ce039fb
Deploy stack su Proxmox / deploy (push) Failing after 3s
Piattaforma ITI TECHNOLOGY: monorepo, Medusa, API, sito, area riservata e deploy
Monorepo npm con apps/public (Angular SSR), apps/private (Angular SPA),
apps/api (Fastify), packages/shared e packages/styles; Medusa 2.21 in medusa/;
infrastruttura Docker (Postgres PostGIS+pgvector, Redis, Caddy, backup) e
workflow Gitea Actions per il deploy via SSH a ogni push su master.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jQyT6dR9czzGwqb7FkG6u
2026-10-20 09:30:48 +02:00

107 lines
6.2 KiB
TypeScript

import type { Routes, UrlMatchResult, UrlSegment } from '@angular/router'
import { authGuard, guestGuard, roleGuard } from './core/auth.guards'
import { CUSTOMER_AREA_ROLES } from './core/roles'
import { AuthLayout } from './layout/auth-layout'
import { Shell } from './layout/shell'
/** Sezioni dell'area clienti: privati, aziende e installatori (che hanno anche la loro area). */
const customer = [roleGuard(...CUSTOMER_AREA_ROLES)]
const AUTH_PAGES = new Set(['login', 'registrazione', 'forgot-password', 'reset-password', 'verify-email'])
/**
* Il layout di accesso vale solo per le sue pagine. Con `path: ''` Angular lo attiverebbe anche per `/`
* (rotta vuota con figli: corrisponde all'URL vuoto anche se nessun figlio corrisponde), con una pagina vuota.
*/
function authPagesMatcher(segments: UrlSegment[]): UrlMatchResult | null {
return segments[0] && AUTH_PAGES.has(segments[0].path) ? { consumed: [] } : null
}
/**
* - Pagine di accesso nel layout semplice. Login, registrazione e password dimenticata solo da anonimi
* (`guestGuard`); reset password e verifica email anche con una sessione aperta.
* I percorsi `/forgot-password`, `/reset-password`, `/verify-email` sono quelli dei link delle email dell'API;
* `/login?redirect=` e `/registrazione?email=` sono il contratto con il sito pubblico (checkout).
* - Area autenticata nel layout con menu (`authGuard`). Ogni sezione è riservata ai ruoli che la usano
* (`roleGuard`, `canMatch`): un ruolo non ammesso viene portato alla propria pagina iniziale (`homeFor`).
* Area clienti alla radice (customer, company; le sezioni anche installer), `/installatori`, `/admin`.
*/
export const routes: Routes = [
{
matcher: authPagesMatcher,
component: AuthLayout,
children: [
{ path: 'login', canActivate: [guestGuard], loadComponent: () => import('./pages/auth/login') },
{ path: 'registrazione', canActivate: [guestGuard], loadComponent: () => import('./pages/auth/register') },
{ path: 'forgot-password', canActivate: [guestGuard], loadComponent: () => import('./pages/auth/forgot-password') },
{ path: 'reset-password', loadComponent: () => import('./pages/auth/reset-password') },
{ path: 'verify-email', loadComponent: () => import('./pages/auth/verify-email') },
],
},
{
path: '',
component: Shell,
canActivate: [authGuard],
children: [
// Area clienti (prompt 30)
{
path: '',
pathMatch: 'full',
canMatch: [roleGuard('customer', 'company')],
loadComponent: () => import('./pages/customer/dashboard'),
},
{ path: 'ordini', canMatch: customer, loadComponent: () => import('./pages/customer/orders') },
{ path: 'ordini/:numero', canMatch: customer, loadComponent: () => import('./pages/customer/order-detail') },
{ path: 'preventivi', canMatch: customer, loadComponent: () => import('./pages/customer/quotes') },
{ path: 'preventivi/:id', canMatch: customer, loadComponent: () => import('./pages/customer/quote-detail') },
{ path: 'assistenza', canMatch: customer, loadComponent: () => import('./pages/customer/tickets') },
{ path: 'assistenza/nuova', canMatch: customer, loadComponent: () => import('./pages/customer/ticket-new') },
{ path: 'assistenza/:id', canMatch: customer, loadComponent: () => import('./pages/customer/ticket-detail') },
{ path: 'documenti', canMatch: customer, loadComponent: () => import('./pages/customer/documents') },
{ path: 'profilo', canMatch: customer, loadComponent: () => import('./pages/customer/profile') },
// Area installatori (prompt 31)
{
path: 'installatori',
canMatch: [roleGuard('installer')],
children: [
{ path: '', pathMatch: 'full', loadComponent: () => import('./pages/installer/installer-home') },
{ path: 'listino', loadComponent: () => import('./pages/installer/price-list') },
{ path: 'documenti', loadComponent: () => import('./pages/installer/technical-docs') },
{ path: 'profilo', loadComponent: () => import('./pages/installer/installer-profile') },
],
},
// Pannello admin (prompt 32). I `/:id` sono anche i link delle notifiche email allo staff.
{
path: 'admin',
canMatch: [roleGuard('admin')],
children: [
{ path: '', pathMatch: 'full', loadComponent: () => import('./pages/admin/admin-dashboard') },
{ path: 'richieste', loadComponent: () => import('./pages/admin/quote-requests') },
{ path: 'richieste/:id', loadComponent: () => import('./pages/admin/quote-request-detail') },
{ path: 'preventivi', loadComponent: () => import('./pages/admin/quotes') },
{ path: 'preventivi/:id', loadComponent: () => import('./pages/admin/quote-detail') },
{ path: 'ticket', loadComponent: () => import('./pages/admin/tickets') },
{ path: 'ticket/:id', loadComponent: () => import('./pages/admin/ticket-detail') },
{ path: 'installatori', loadComponent: () => import('./pages/admin/installers') },
{ path: 'installatori/:id', loadComponent: () => import('./pages/admin/installer-detail') },
{ path: 'utenti', loadComponent: () => import('./pages/admin/users') },
{ path: 'utenti/:id', loadComponent: () => import('./pages/admin/user-detail') },
{ path: 'blog', loadComponent: () => import('./pages/admin/blog') },
{ path: 'blog/nuovo', loadComponent: () => import('./pages/admin/blog-editor') },
{ path: 'blog/categorie', loadComponent: () => import('./pages/admin/blog-categories') },
{ path: 'blog/:id', loadComponent: () => import('./pages/admin/blog-editor') },
{ path: 'documenti', loadComponent: () => import('./pages/admin/documents') },
{ path: 'contatti', loadComponent: () => import('./pages/admin/contacts') },
{ path: 'contatti/:id', loadComponent: () => import('./pages/admin/contact-detail') },
{ path: 'showroom', loadComponent: () => import('./pages/admin/showroom') },
{ path: 'showroom/:id', loadComponent: () => import('./pages/admin/booking-detail') },
],
},
{ path: '**', loadComponent: () => import('./pages/not-found') },
],
},
]