Deploy stack su Proxmox / deploy (push) Failing after 3s
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
107 lines
6.2 KiB
TypeScript
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') },
|
|
],
|
|
},
|
|
]
|