From 0c465b53cd6350125c224fcf209a260084193dec Mon Sep 17 00:00:00 2001 From: bisco Date: Tue, 5 May 2026 16:16:46 +0200 Subject: [PATCH] feat: add editorial homepage and show list layout --- frontend/src/app/pages/home-page.component.ts | 282 +++++++----------- .../src/app/pages/show-list-page.component.ts | 110 ++++--- 2 files changed, 173 insertions(+), 219 deletions(-) diff --git a/frontend/src/app/pages/home-page.component.ts b/frontend/src/app/pages/home-page.component.ts index 0e620ac..00210c9 100644 --- a/frontend/src/app/pages/home-page.component.ts +++ b/frontend/src/app/pages/home-page.component.ts @@ -1,33 +1,29 @@ -import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { RouterLink } from '@angular/router'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; -import { API_BASE_URL } from '../services/api-config.token'; - @Component({ standalone: true, imports: [RouterLink, MatButtonModule, MatCardModule], template: ` -
-
-

AzioneLab

-

Un luogo dove il teatro prende forma, voce e relazione.

-

- AzioneLab intreccia laboratori teatrali, produzioni audio/visive e momenti scenici costruiti con cura. Qui il pubblico trova una casa aperta: puo' scoprire gli spettacoli, prenotare con semplicita' e arrivare in sala con la leggerezza di chi sa gia' dove andare. -

-
- Entra nella programmazione - Vai all'accoglienza +
+
+
+

AZIONELAB

+

Laboratori teatrali & produzioni audio/visive

+

Direzione artistica a cura di Ernesto Estatico

+

+ Un luogo di ricerca, presenza e relazione, dove il teatro incontra la formazione e la scena si apre al pubblico con un ritmo piu' umano, piu' vicino, piu' vivo. +

+
-
-
@@ -35,273 +31,201 @@ import { API_BASE_URL } from '../services/api-config.token';
-

Perche' AzioneLab

-

Non solo prenotazioni: un invito a entrare nel lavoro, nell'ascolto e nella scena

+

Uno spazio da attraversare

+

Il sito accompagna il pubblico verso gli spettacoli senza perdere il tono di una compagnia teatrale

-

Ogni passaggio e' pensato per restare umano: guardi cosa c'e', scegli la data, ricevi conferma e arrivi in teatro senza attriti.

+

Ogni passaggio resta leggibile e misurato: si guarda, si sceglie, si prenota, si arriva in sala con la sensazione di essere attesi.

- Trova la serata che fa per te + Una programmazione da leggere con calma -

Le schede tengono vicini i dettagli che contano davvero: luogo, orario, disponibilita' e respiro dello spettacolo.

+

Le schede mettono in evidenza i dettagli utili senza appesantire la scena: titolo, sintesi, immagini e accesso alla prenotazione.

- Una conferma semplice, senza fretta + Una prenotazione semplice e rassicurante -

Ricevi un'email, confermi quando vuoi e la tua prenotazione prende forma in modo chiaro e affidabile.

+

La conferma via email mantiene il percorso leggero per chi prenota e affidabile per chi organizza la capienza.

- Accoglienza attenta all'ingresso + Un'accoglienza pensata per il lavoro in sala -

Lo staff puo' accompagnare l'arrivo del pubblico con uno strumento rapido, discreto e pensato per il lavoro in sala.

+

Dall'ingresso alla verifica del QR code, tutto resta discreto, chiaro e adatto a un contesto teatrale.

-
+

Il percorso del pubblico

-

Dalla curiosita' al posto in sala, con naturalezza

-
    -
  1. Scopri la programmazione e lasciati guidare dalla scheda di ogni spettacolo.
  2. -
  3. Richiedi i posti per la replica che preferisci e conferma dall'email ricevuta.
  4. -
  5. Conserva il QR code sul telefono oppure stampalo e portalo con te all'ingresso.
  6. -
+

Dalla scoperta dello spettacolo all'ingresso, in pochi passaggi essenziali

- - - Dietro le quinte - -

Collegamento API

- {{ apiBaseUrl }} -

La parte pubblica del sito dialoga con le API Django esistenti senza cambiare il comportamento del backend.

-
-
+
    +
  1. Esplora gli spettacoli in programma e apri la scheda che ti incuriosisce.
  2. +
  3. Invia la richiesta di prenotazione e confermala dall'email ricevuta.
  4. +
  5. Porta con te il QR code sul telefono o su carta e raggiungi la sala con semplicita'.
  6. +
`, styles: [` .hero { + width: 100%; + margin: 0 0 72px; + padding: 56px 0 72px; + background: + linear-gradient(180deg, rgba(47, 125, 87, 0.05), rgba(47, 125, 87, 0) 42%), + linear-gradient(180deg, #fcfbf8 0%, #f8f6f0 100%); + border-bottom: 1px solid var(--azionelab-border); + } + + .hero-inner { display: grid; - grid-template-columns: minmax(0, 1.3fr) minmax(280px, 0.9fr); - gap: 28px; - align-items: stretch; - padding: 12px 0 24px; + grid-template-columns: minmax(0, 1.3fr) minmax(240px, 0.7fr); + gap: 36px; + align-items: end; } .hero-copy { - padding: 34px 0 20px; + padding-top: 18px; + } + + .hero-kicker { + margin: 0 0 18px; + color: var(--azionelab-accent); + font-size: 0.9rem; + font-weight: 800; + letter-spacing: 0.18em; + text-transform: uppercase; } h1 { margin: 0; - max-width: 10.5ch; - font-size: 3.6rem; + max-width: 11ch; + font-size: 4.3rem; + line-height: 0.96; } - .supporting { + .hero-direction { margin: 20px 0 0; - font-size: 1.06rem; + color: var(--azionelab-ink-soft); + font-size: 1.05rem; + line-height: 1.5; } .hero-actions { - display: flex; - gap: 12px; - flex-wrap: wrap; - margin-top: 28px; + margin-top: 34px; } - .hero-stage { - position: relative; - overflow: hidden; - min-height: 420px; - border-radius: var(--azionelab-radius-lg); - border: 1px solid rgba(255, 250, 245, 0.16); - background: - linear-gradient(180deg, rgba(31, 18, 18, 0.1), rgba(27, 18, 14, 0.62)), - linear-gradient(135deg, #b04b40 0%, #7f251f 24%, #43261f 56%, #211b1a 100%); - box-shadow: var(--azionelab-shadow-strong); - } - - .curtain { - position: absolute; - inset: 0; - background: - linear-gradient(90deg, rgba(255, 255, 255, 0.08) 0, rgba(255, 255, 255, 0) 22%, rgba(255, 255, 255, 0.08) 48%, rgba(255, 255, 255, 0) 74%, rgba(255, 255, 255, 0.08) 100%), - repeating-linear-gradient(90deg, rgba(75, 18, 14, 0.2) 0 18px, rgba(160, 60, 52, 0.08) 18px 36px); - opacity: 0.9; - } - - .stage-glow { - position: absolute; - left: 50%; - bottom: -80px; - width: 340px; - height: 340px; - transform: translateX(-50%); - border-radius: 50%; - background: radial-gradient(circle, rgba(245, 214, 150, 0.9) 0, rgba(245, 214, 150, 0.22) 44%, rgba(245, 214, 150, 0) 72%); - } - - .stage-copy { - position: absolute; - left: 24px; - right: 24px; - bottom: 24px; + .hero-aside { display: grid; - gap: 8px; - padding: 18px 20px; - border-radius: 18px; - background: rgba(24, 17, 15, 0.52); - backdrop-filter: blur(8px); - color: rgba(255, 247, 239, 0.94); - border: 1px solid rgba(255, 247, 239, 0.12); + gap: 16px; + padding: 0 0 10px; + color: var(--azionelab-muted); } - .stage-copy span { - text-transform: uppercase; - font-size: 0.76rem; - letter-spacing: 0.08em; - color: rgba(255, 227, 192, 0.84); + .hero-aside p, + .hero-aside span { + margin: 0; + line-height: 1.75; } - .stage-copy strong { - font-family: var(--azionelab-serif); - font-size: 1.4rem; - font-weight: 700; - line-height: 1.15; + .hero-aside span { + max-width: 24ch; } .overview, - .journey-grid { - margin-top: 34px; + .journey { + margin-top: 0; + margin-bottom: 72px; } .section-heading { display: grid; - grid-template-columns: minmax(0, 1fr) minmax(260px, 420px); - gap: 24px; + grid-template-columns: minmax(0, 1fr) minmax(300px, 460px); + gap: 28px; align-items: end; - margin-bottom: 20px; + margin-bottom: 28px; } .section-heading h2, .journey-copy h2 { margin: 0; - max-width: 18ch; + max-width: 16ch; } .feature-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 18px; + gap: 20px; } - .feature-card, - .meta-card { + .feature-card { border-radius: var(--azionelab-radius-md); border: 1px solid var(--azionelab-border); - background: linear-gradient(180deg, rgba(255, 253, 250, 0.98), rgba(251, 245, 236, 0.94)); + background: var(--azionelab-surface); box-shadow: var(--azionelab-shadow); } .feature-card { - min-height: 210px; + min-height: 220px; } - .feature-card mat-card-title, - .meta-card mat-card-title { + .feature-card mat-card-title { margin-bottom: 12px; font-family: var(--azionelab-serif); - font-size: 1.18rem; - font-weight: 700; + font-size: 1.28rem; + font-weight: 600; } - .feature-card p, - .meta-card p { + .feature-card p { margin: 0; color: var(--azionelab-muted); - line-height: 1.6; - } - - .journey-grid { - display: grid; - grid-template-columns: minmax(0, 1.2fr) minmax(280px, 0.9fr); - gap: 24px; - align-items: start; + line-height: 1.72; } .journey-copy { - padding: 10px 0; + margin-bottom: 20px; } - ol { + .journey-steps { display: grid; - gap: 12px; - margin: 20px 0 0; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 20px; + margin: 0; padding-left: 22px; color: var(--azionelab-ink-soft); line-height: 1.65; } - .meta-label { - margin: 0 0 10px; - font-size: 0.8rem; - font-weight: 700; - text-transform: uppercase; - color: var(--azionelab-muted); - letter-spacing: 0.08em; - } - - code { - display: inline-block; - padding: 10px 12px; - border-radius: 12px; - background: rgba(34, 28, 24, 0.06); - color: var(--azionelab-ink-soft); - word-break: break-word; - } - - .meta-note { - margin: 18px 0 0; - } - @media (max-width: 900px) { - .hero, + .hero-inner, .section-heading, - .journey-grid, + .journey-steps, .feature-grid { grid-template-columns: 1fr; } h1 { - font-size: 2.8rem; + font-size: 3.2rem; } } @media (max-width: 640px) { + .hero { + margin-bottom: 56px; + padding: 40px 0 56px; + } + h1 { - font-size: 2.2rem; - } - - .hero-stage { - min-height: 320px; - } - - .stage-copy { - left: 16px; - right: 16px; - bottom: 16px; - padding: 16px; + font-size: 2.4rem; } } `], changeDetection: ChangeDetectionStrategy.OnPush, }) export class HomePageComponent { - protected readonly apiBaseUrl = inject(API_BASE_URL); } diff --git a/frontend/src/app/pages/show-list-page.component.ts b/frontend/src/app/pages/show-list-page.component.ts index a4286ac..6b14bea 100644 --- a/frontend/src/app/pages/show-list-page.component.ts +++ b/frontend/src/app/pages/show-list-page.component.ts @@ -16,10 +16,10 @@ import { ShowListItem, ShowsApiService } from '../services/shows-api.service'; @@ -59,21 +59,24 @@ import { ShowListItem, ShowsApiService } from '../services/shows-api.service';
@for (show of shows(); track show.slug) { - @if (show.image_url) { + @if (getShowImage(show); as showImage) {
- +
} -
- Spettacolo in evidenza +
+
+ In programma +
+ {{ show.title }} + +

{{ show.summary }}

+

Apri la scheda per vedere le prossime date e i dettagli di prenotazione.

+
+ + {{ getShowCta(show) }} +
- {{ show.title }} - -

{{ show.summary }}

-
- - Apri scheda - }
@@ -83,21 +86,21 @@ import { ShowListItem, ShowsApiService } from '../services/shows-api.service'; styles: [` .page-header { display: grid; - grid-template-columns: minmax(0, 1fr) minmax(260px, 410px); - gap: 24px; + grid-template-columns: minmax(0, 1fr) minmax(300px, 430px); + gap: 28px; align-items: end; - margin-bottom: 28px; + margin-bottom: 40px; } .supporting { margin: 0; - max-width: 34ch; + max-width: 36ch; } .show-grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); - gap: 22px; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 28px; } .status-panel, @@ -139,21 +142,19 @@ import { ShowListItem, ShowsApiService } from '../services/shows-api.service'; .show-card { display: flex; flex-direction: column; - min-height: 360px; + min-height: 520px; overflow: hidden; border-radius: var(--azionelab-radius-md); border: 1px solid var(--azionelab-border); - background: linear-gradient(180deg, rgba(255, 253, 249, 0.98), rgba(250, 243, 233, 0.94)); + background: var(--azionelab-surface); box-shadow: var(--azionelab-shadow); } .show-image-wrap { - aspect-ratio: 15 / 10; + aspect-ratio: 4 / 5; overflow: hidden; border-bottom: 1px solid var(--azionelab-border); - background: - linear-gradient(135deg, rgba(207, 71, 51, 0.14), rgba(15, 22, 36, 0.06)), - #f8f1ea; + background: var(--azionelab-bg-strong); } .show-image { @@ -165,23 +166,29 @@ import { ShowListItem, ShowsApiService } from '../services/shows-api.service'; } .show-card:hover .show-image { - transform: scale(1.03); + transform: scale(1.015); + } + + .card-body { + display: flex; + flex: 1; + flex-direction: column; + padding: 22px 22px 20px; } .card-topline { - padding: 18px 18px 0; + padding: 0 0 12px; } .card-label { display: inline-flex; align-items: center; - min-height: 28px; - padding: 0 12px; - border-radius: 999px; - background: rgba(143, 51, 45, 0.08); - color: var(--azionelab-accent-strong); - font-size: 0.78rem; + min-height: 24px; + color: var(--azionelab-accent); + font-size: 0.76rem; font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; } .show-card mat-card-content { @@ -191,28 +198,43 @@ import { ShowListItem, ShowsApiService } from '../services/shows-api.service'; .show-card mat-card-title, .show-card mat-card-content, .show-card mat-card-actions { - padding-left: 18px; - padding-right: 18px; + padding-left: 0; + padding-right: 0; } .show-card mat-card-title { - margin-top: 10px; + margin-top: 0; font-family: var(--azionelab-serif); - font-size: 1.45rem; - font-weight: 700; - line-height: 1.12; + font-size: 1.85rem; + font-weight: 600; + line-height: 1.04; } .show-card p { color: var(--azionelab-muted); - line-height: 1.6; + line-height: 1.74; margin: 0; } + .show-note { + margin-top: 18px !important; + padding-top: 18px; + border-top: 1px solid var(--azionelab-border); + font-size: 0.95rem; + } + + .show-card mat-card-actions { + padding-top: 22px; + } + @media (max-width: 860px) { .page-header { grid-template-columns: 1fr; } + + .show-grid { + grid-template-columns: 1fr; + } } `], changeDetection: ChangeDetectionStrategy.OnPush, @@ -233,6 +255,14 @@ export class ShowListPageComponent { this.loadShows(); } + protected getShowImage(show: ShowListItem): string { + return show.image_url || show.poster_image || ''; + } + + protected getShowCta(_show: ShowListItem): string { + return 'Scopri lo spettacolo'; + } + private loadShows(): void { this.isLoading.set(true); this.errorMessage.set('');