From f63bac44576b8b0b90b255f49dcefd8f6eece31b Mon Sep 17 00:00:00 2001 From: Lucio Lelii Date: Mon, 9 Feb 2026 16:16:28 +0100 Subject: [PATCH] aggiunti link per navigare quadno loggati e la apgian dei producers --- angular.json | 5 ++ src/app/app.html | 9 +-- src/app/app.routes.ts | 9 +++ src/app/app.ts | 12 +-- src/app/components/header/header.html | 40 ++++----- src/app/components/header/header.scss | 7 ++ src/app/components/header/header.ts | 28 +++++-- .../producers-list/producers-list.html | 19 +++++ .../producers-list.scss} | 0 .../producers-list/producers-list.spec.ts | 23 ++++++ .../producers-list/producers-list.ts | 14 ++++ src/app/guards/auth-guard.ts | 2 +- src/app/layouts/main-layout/main-layout.html | 26 ++++++ src/app/layouts/main-layout/main-layout.scss | 42 ++++++++++ .../layouts/main-layout/main-layout.spec.ts | 23 ++++++ src/app/layouts/main-layout/main-layout.ts | 20 +++++ src/app/model/login-data.ts | 4 + src/app/model/user.ts | 9 ++- src/app/pages/home/home.html | 4 +- src/app/pages/home/home.scss | 65 +++++++++++++++ src/app/pages/home/home.ts | 14 +++- src/app/pages/login/login.css | 0 src/app/pages/login/login.html | 48 ++++++++++- src/app/pages/login/login.scss | 81 +++++++++++++++++++ src/app/pages/login/login.ts | 31 ++++++- src/app/pages/producers/producers.html | 1 + .../home.css => producers/producers.scss} | 0 src/app/pages/producers/producers.spec.ts | 23 ++++++ src/app/pages/producers/producers.ts | 12 +++ src/app/services/authentication.ts | 31 ++++--- src/styles.scss | 63 --------------- 31 files changed, 536 insertions(+), 129 deletions(-) create mode 100644 src/app/components/header/header.scss create mode 100644 src/app/components/producers-list/producers-list.html rename src/app/components/{header/header.css => producers-list/producers-list.scss} (100%) create mode 100644 src/app/components/producers-list/producers-list.spec.ts create mode 100644 src/app/components/producers-list/producers-list.ts create mode 100644 src/app/layouts/main-layout/main-layout.html create mode 100644 src/app/layouts/main-layout/main-layout.scss create mode 100644 src/app/layouts/main-layout/main-layout.spec.ts create mode 100644 src/app/layouts/main-layout/main-layout.ts create mode 100644 src/app/model/login-data.ts create mode 100644 src/app/pages/home/home.scss delete mode 100644 src/app/pages/login/login.css create mode 100644 src/app/pages/login/login.scss create mode 100644 src/app/pages/producers/producers.html rename src/app/pages/{home/home.css => producers/producers.scss} (100%) create mode 100644 src/app/pages/producers/producers.spec.ts create mode 100644 src/app/pages/producers/producers.ts diff --git a/angular.json b/angular.json index df41bf7..f35933a 100644 --- a/angular.json +++ b/angular.json @@ -5,6 +5,11 @@ "packageManager": "npm" }, "newProjectRoot": "projects", + "schematics": { + "@schematics/angular:component": { + "style": "scss" + } + }, "projects": { "validator-gui": { "projectType": "application", diff --git a/src/app/app.html b/src/app/app.html index f3ec4a9..c404bed 100644 --- a/src/app/app.html +++ b/src/app/app.html @@ -1,8 +1 @@ -
- -
- - -
- -
\ No newline at end of file + \ No newline at end of file diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 59a0299..d51eeee 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,6 +1,7 @@ import { Routes } from '@angular/router'; import { HomePage } from './pages/home/home'; import { LoginPage } from './pages/login/login'; +import { authGuard } from './guards/auth-guard'; export const routes: Routes = [ { @@ -12,6 +13,14 @@ export const routes: Routes = [ path: 'login', component: LoginPage }, + { + path: '', + canActivate: [authGuard], + children: [ + { path: '', redirectTo: 'producers', pathMatch: 'full' }, + { path: 'producers', loadComponent: () => import('./pages/producers/producers').then(m => m.ProducersComponent) }, + ] + }, { path: '**', redirectTo: '' diff --git a/src/app/app.ts b/src/app/app.ts index 2889167..84b9a25 100644 --- a/src/app/app.ts +++ b/src/app/app.ts @@ -1,19 +1,13 @@ -import { Component, inject, signal } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; -import { Header } from "./components/header/header"; -import { AuthenticationService } from './services/authentication'; +import { Component, signal } from '@angular/core'; +import { MainLayout } from "./layouts/main-layout/main-layout"; @Component({ selector: 'app-root', - imports: [ RouterOutlet, Header], + imports: [MainLayout], templateUrl: './app.html', styleUrl: './app.css' }) export class App { protected readonly title = signal('validator-gui'); - protected authService = inject(AuthenticationService); - - loggedInUser = this.authService.loggedInUser; - } diff --git a/src/app/components/header/header.html b/src/app/components/header/header.html index 890d2de..f044f21 100644 --- a/src/app/components/header/header.html +++ b/src/app/components/header/header.html @@ -1,25 +1,23 @@ + slimTitleLink="https://www.isti.cnr.it" [loginStyle]="getLoginStyle()" [smallHeader]="false" [light]="false" + [showSearch]="false" [sticky]="true" [megamenu]="false" (loginClick)="login()"> + @if(loggedInUser()) { - @if (loggedInUser()) { - - - Mario Rossi - - } @else { - -
- - Accedi all'area riservata -
-
- } +
+ } - +
Validatore Sistemi Fiscali
@@ -27,9 +25,5 @@
- - - Home - - +
\ No newline at end of file diff --git a/src/app/components/header/header.scss b/src/app/components/header/header.scss new file mode 100644 index 0000000..e428e85 --- /dev/null +++ b/src/app/components/header/header.scss @@ -0,0 +1,7 @@ +.logout-icon { + cursor: pointer; + color: white; + &:hover { + opacity: 0.85; + } +} diff --git a/src/app/components/header/header.ts b/src/app/components/header/header.ts index 6d075f4..7113658 100644 --- a/src/app/components/header/header.ts +++ b/src/app/components/header/header.ts @@ -1,18 +1,36 @@ -import { Component, inject } from '@angular/core'; +import { Component, computed, inject } from '@angular/core'; import { DesignAngularKitModule, ItTooltipDirective } from 'design-angular-kit'; import { AuthenticationService } from '../../services/authentication'; import { InitialsPipe } from '../../pipes/initials-pipe-pipe'; -import { RouterLink } from "@angular/router"; +import { Router } from "@angular/router"; @Component({ selector: 'app-header', - imports: [DesignAngularKitModule, InitialsPipe, RouterLink], + imports: [DesignAngularKitModule, InitialsPipe], templateUrl: './header.html', - styleUrl: './header.css', + styleUrl: './header.scss', }) export class Header { + private router = inject(Router); + protected authService = inject(AuthenticationService); - loggedInUser = this.authService.loggedInUser; + getLoginStyle() { + return this.authService.loggedInUser() ? 'none' : 'full'; + } + + login() { + this.router.navigate(['/login']); + } + + logout() { + this.authService.logout(); + this.router.navigate(['/home']); + } + + loggedInUser() { + return this.authService.loggedInUser(); + } + } diff --git a/src/app/components/producers-list/producers-list.html b/src/app/components/producers-list/producers-list.html new file mode 100644 index 0000000..2189a6a --- /dev/null +++ b/src/app/components/producers-list/producers-list.html @@ -0,0 +1,19 @@ + + +
+

Link lista 1

+

Lorem ipsum dolor sit amet.

+
+ + + + + + + + + + + +
+
\ No newline at end of file diff --git a/src/app/components/header/header.css b/src/app/components/producers-list/producers-list.scss similarity index 100% rename from src/app/components/header/header.css rename to src/app/components/producers-list/producers-list.scss diff --git a/src/app/components/producers-list/producers-list.spec.ts b/src/app/components/producers-list/producers-list.spec.ts new file mode 100644 index 0000000..0eaa084 --- /dev/null +++ b/src/app/components/producers-list/producers-list.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProducersList } from './producers-list'; + +describe('ProducersList', () => { + let component: ProducersList; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ProducersList] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ProducersList); + component = fixture.componentInstance; + await fixture.whenStable(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/producers-list/producers-list.ts b/src/app/components/producers-list/producers-list.ts new file mode 100644 index 0000000..9133c15 --- /dev/null +++ b/src/app/components/producers-list/producers-list.ts @@ -0,0 +1,14 @@ +import { Component } from '@angular/core'; +import { DesignAngularKitModule } from 'design-angular-kit'; + +@Component({ + selector: 'app-producers-list', + imports: [DesignAngularKitModule], + templateUrl: './producers-list.html', + styleUrl: './producers-list.scss', +}) +export class ProducersListComponent { + + + +} diff --git a/src/app/guards/auth-guard.ts b/src/app/guards/auth-guard.ts index 6ca2d74..c4af559 100644 --- a/src/app/guards/auth-guard.ts +++ b/src/app/guards/auth-guard.ts @@ -9,7 +9,7 @@ export const authGuard: CanActivateFn = (route, state) => { if (authService.isLoggedIn()) { return true; // Allow access } else { - router.navigate(['/']); + router.navigate(['/login']); return false; // Deny access } }; diff --git a/src/app/layouts/main-layout/main-layout.html b/src/app/layouts/main-layout/main-layout.html new file mode 100644 index 0000000..817c1fb --- /dev/null +++ b/src/app/layouts/main-layout/main-layout.html @@ -0,0 +1,26 @@ +
+ +
+ +
+ +
\ No newline at end of file diff --git a/src/app/layouts/main-layout/main-layout.scss b/src/app/layouts/main-layout/main-layout.scss new file mode 100644 index 0000000..b578c6b --- /dev/null +++ b/src/app/layouts/main-layout/main-layout.scss @@ -0,0 +1,42 @@ + +/* wrapper nav (opzionale se già su header) */ +.pa-nav { + background-color: #0066cc; // azzurro PA + display: flex; + padding: 0 50px; +} + +/* lista */ +.pa-nav__list { + display: flex; + gap: 0.25rem; + margin: 0; + padding: 0 0.5rem; + list-style: none; +} + +/* link base */ +.pa-nav__link { + display: inline-flex; + align-items: center; + padding: 0.55rem 0.9rem; + text-decoration: none; + font-weight: 500; + color: #ffffff; + opacity: 0.92; + transition: background-color 0.15s ease, box-shadow 0.15s ease; + + &:hover { + cursor: pointer; + } + &:focus { + opacity: 1; + background-color: rgba(255, 255, 255, 0.15); + text-decoration: none; + } +} + +.pa-nav__item.is-active > .pa-nav__link { + color: beige; + background-color: rgba(255, 255, 255, 0.25); +} \ No newline at end of file diff --git a/src/app/layouts/main-layout/main-layout.spec.ts b/src/app/layouts/main-layout/main-layout.spec.ts new file mode 100644 index 0000000..f4a5f1f --- /dev/null +++ b/src/app/layouts/main-layout/main-layout.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MainLayout } from './main-layout'; + +describe('MainLayout', () => { + let component: MainLayout; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MainLayout] + }) + .compileComponents(); + + fixture = TestBed.createComponent(MainLayout); + component = fixture.componentInstance; + await fixture.whenStable(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/layouts/main-layout/main-layout.ts b/src/app/layouts/main-layout/main-layout.ts new file mode 100644 index 0000000..5cd2335 --- /dev/null +++ b/src/app/layouts/main-layout/main-layout.ts @@ -0,0 +1,20 @@ +import { Component, inject } from '@angular/core'; +import { RouterOutlet, RouterLink, RouterLinkActive } from '@angular/router'; +import { DesignAngularKitModule } from 'design-angular-kit'; +import { Header } from '../../components/header/header'; +import { AuthenticationService } from '../../services/authentication'; + +@Component({ + selector: 'app-main-layout', + imports: [RouterOutlet, Header, DesignAngularKitModule, RouterLink, RouterLinkActive], + templateUrl: './main-layout.html', + styleUrl: './main-layout.scss', +}) +export class MainLayout { + + protected authService = inject(AuthenticationService); + + loggedInUser() { + return this.authService.loggedInUser(); + } +} diff --git a/src/app/model/login-data.ts b/src/app/model/login-data.ts new file mode 100644 index 0000000..5f40030 --- /dev/null +++ b/src/app/model/login-data.ts @@ -0,0 +1,4 @@ +export interface LoginData { + email: string; + password: string; +} \ No newline at end of file diff --git a/src/app/model/user.ts b/src/app/model/user.ts index 3d81e25..ee6c7e6 100644 --- a/src/app/model/user.ts +++ b/src/app/model/user.ts @@ -1,4 +1,7 @@ -export type User = { - username: string; - email: string; + +export type Role = 'admin' | 'user'; + +export class User { + constructor(public username: string, public email: string, public role: Role = "user") {} + }; \ No newline at end of file diff --git a/src/app/pages/home/home.html b/src/app/pages/home/home.html index 1ae983f..5956e78 100644 --- a/src/app/pages/home/home.html +++ b/src/app/pages/home/home.html @@ -15,7 +15,9 @@ attraverso regole configurabili e controlli avanzati.

+ @if(!isLoggedIn()) {

- L’accesso alle funzionalità complete è riservato agli utenti autenticati. + L’accesso alle funzionalità complete è riservato agli utenti autenticati. Accedi per iniziare a utilizzare il sistema.

+ } diff --git a/src/app/pages/home/home.scss b/src/app/pages/home/home.scss new file mode 100644 index 0000000..2e89bd7 --- /dev/null +++ b/src/app/pages/home/home.scss @@ -0,0 +1,65 @@ +// Variabili Bootstrap Italia già disponibili se importi bootstrap-italia +$primary: var(--bs-primary); +$gray-700: var(--bs-gray-700); +$gray-600: var(--bs-gray-600); +$gray-300: var(--bs-gray-300); + +.home-content { + max-width: 960px; + margin: 0 auto; + padding: 3rem 1.5rem; + + // Titolo principale + &__title { + font-family: var(--bs-font-sans-serif); + font-size: 2.25rem; + font-weight: 600; + line-height: 1.2; + color: $primary; + margin-bottom: 1.5rem; + } + + // Sottotitolo / testo introduttivo + &__lead { + font-size: 1.125rem; + line-height: 1.6; + color: $gray-700; + margin-bottom: 2rem; + } + + // Testo standard + &__text { + font-size: 1rem; + line-height: 1.6; + color: $gray-600; + margin-bottom: 1rem; + } + + // Separatore soft + &__divider { + margin: 2.5rem 0; + border-top: 1px solid $gray-300; + } + + // Link istituzionale + a { + color: $primary; + font-weight: 500; + text-decoration: underline; + + &:hover { + text-decoration: none; + } + } +} + +/* Responsive */ +@media (max-width: 768px) { + .home-content { + padding: 2rem 1rem; + + &__title { + font-size: 1.75rem; + } + } +} diff --git a/src/app/pages/home/home.ts b/src/app/pages/home/home.ts index c5b14b4..0ac22f5 100644 --- a/src/app/pages/home/home.ts +++ b/src/app/pages/home/home.ts @@ -1,11 +1,19 @@ -import { Component } from '@angular/core'; +import { Component, computed, inject } from '@angular/core'; +import { AuthenticationService } from '../../services/authentication'; +import { RouterLink } from '@angular/router'; @Component({ selector: 'app-home', - imports: [], + imports: [RouterLink], templateUrl: './home.html', - styleUrl: './home.css', + styleUrl: './home.scss', }) export class HomePage { + authService = inject(AuthenticationService); + + isLoggedIn(){ + return this.authService.isLoggedIn(); + } + } diff --git a/src/app/pages/login/login.css b/src/app/pages/login/login.css deleted file mode 100644 index e69de29..0000000 diff --git a/src/app/pages/login/login.html b/src/app/pages/login/login.html index 147cfc4..6026b6f 100644 --- a/src/app/pages/login/login.html +++ b/src/app/pages/login/login.html @@ -1 +1,47 @@ -

login works!

+ diff --git a/src/app/pages/login/login.scss b/src/app/pages/login/login.scss new file mode 100644 index 0000000..050a431 --- /dev/null +++ b/src/app/pages/login/login.scss @@ -0,0 +1,81 @@ +.it-login-wrapper { + padding-top: 40px; + display: flex; + align-items: center; + justify-content: center; +} + +.it-login-card { + width: 100%; + max-width: 420px; + background: #ffffff; + padding: 2.5rem; + border-radius: 8px; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08); +} + +.it-login-title { + font-size: 1.75rem; + font-weight: 600; + margin-bottom: 0.5rem; + color: #17324d; +} + +.it-login-subtitle { + font-size: 0.95rem; + color: #5c6f82; + margin-bottom: 2rem; +} + +.it-form-group { + display: flex; + flex-direction: column; + margin-bottom: 1.5rem; +} + +.it-label { + font-size: 0.85rem; + font-weight: 600; + margin-bottom: 0.5rem; + color: #17324d; +} + +.it-input { + height: 44px; + padding: 0 12px; + border-radius: 4px; + border: 1px solid #cbd5e1; + font-size: 0.95rem; + transition: border-color 0.2s ease; + + &:focus { + outline: none; + border-color: #0066cc; + } +} + +.it-actions { + margin-top: 2rem; +} + +.it-btn-primary { + width: 100%; + height: 46px; + border: none; + border-radius: 4px; + background: #0066cc; + color: #ffffff; + font-size: 0.95rem; + font-weight: 600; + cursor: pointer; + transition: background 0.2s ease; + + &:hover:not(:disabled) { + background: #0052a3; + } + + &:disabled { + background: #cbd5e1; + cursor: not-allowed; + } +} diff --git a/src/app/pages/login/login.ts b/src/app/pages/login/login.ts index 5e617cc..f75b8c5 100644 --- a/src/app/pages/login/login.ts +++ b/src/app/pages/login/login.ts @@ -1,13 +1,38 @@ -import { Component } from '@angular/core'; +import { Component, inject, signal, WritableSignal } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import {form, FormField} from '@angular/forms/signals'; +import { ItFormModule } from "design-angular-kit"; +import { AuthenticationService } from '../../services/authentication'; +import { LoginData } from '../../model/login-data'; +import { Router } from '@angular/router'; + + + @Component({ selector: 'app-login', - imports: [], + imports: [FormsModule, ItFormModule, FormField], templateUrl: './login.html', - styleUrl: './login.css', + styleUrl: './login.scss', }) export class LoginPage { + authService = inject(AuthenticationService); + router = inject(Router); + loginModel = signal({ + email: '', + password: '', + }); + loginForm = form(this.loginModel); + submit() { + if (this.loginForm().valid()) { + console.log('Login data:', this.loginModel()); + this.authService.login(this.loginModel()).subscribe(() => { + console.log('Login successful'); + this.router.navigate(['/home']); + }); + } + } } diff --git a/src/app/pages/producers/producers.html b/src/app/pages/producers/producers.html new file mode 100644 index 0000000..7f74b2f --- /dev/null +++ b/src/app/pages/producers/producers.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/app/pages/home/home.css b/src/app/pages/producers/producers.scss similarity index 100% rename from src/app/pages/home/home.css rename to src/app/pages/producers/producers.scss diff --git a/src/app/pages/producers/producers.spec.ts b/src/app/pages/producers/producers.spec.ts new file mode 100644 index 0000000..9701323 --- /dev/null +++ b/src/app/pages/producers/producers.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { Producers } from './producers'; + +describe('Producers', () => { + let component: Producers; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [Producers] + }) + .compileComponents(); + + fixture = TestBed.createComponent(Producers); + component = fixture.componentInstance; + await fixture.whenStable(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/pages/producers/producers.ts b/src/app/pages/producers/producers.ts new file mode 100644 index 0000000..caca59d --- /dev/null +++ b/src/app/pages/producers/producers.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; +import { ProducersListComponent } from "../../components/producers-list/producers-list"; + +@Component({ + selector: 'app-producers', + imports: [ProducersListComponent], + templateUrl: './producers.html', + styleUrls: ['./producers.scss'], +}) +export class ProducersComponent { + +} diff --git a/src/app/services/authentication.ts b/src/app/services/authentication.ts index cd46227..f1322c4 100644 --- a/src/app/services/authentication.ts +++ b/src/app/services/authentication.ts @@ -1,5 +1,7 @@ import { Injectable, signal } from '@angular/core'; import { User } from '../model/user'; +import { LoginData } from '../model/login-data'; +import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root', @@ -7,13 +9,22 @@ import { User } from '../model/user'; export class AuthenticationService { private user = signal(null); + + constructor() { + const storedUser = localStorage.getItem('loggedInUser'); + if (storedUser) { + this.user.set(JSON.parse(storedUser)); + } + } - - loggedInUser = this.user.asReadonly(); - - login(username: string, password: string) { - this.user.set({ username, email: 'test@email.it' }); // Simulate a successful login with a dummy user - localStorage.setItem('loggedInUser', JSON.stringify({ username, email: '' })); + login(loginData: LoginData): Observable { + const user = new User('John Doe', loginData.email); // Simulate a user based on login data + this.user.set(user); + localStorage.setItem('loggedInUser', JSON.stringify(user)); + return new Observable((observer) => { + observer.next(); + observer.complete(); + }); } logout() { @@ -22,8 +33,10 @@ export class AuthenticationService { } isLoggedIn(): boolean { - const storedUser = localStorage.getItem('loggedInUser'); - this.user.set(storedUser != null ? JSON.parse(storedUser) : null); - return storedUser != null; + return this.user() != null; + } + + loggedInUser(): User | null { + return this.user(); } } diff --git a/src/styles.scss b/src/styles.scss index ec066a4..85d6b11 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1,68 +1,5 @@ /* You can add global styles to this file, and also import other style files */ @use 'bootstrap-italia/src/scss/bootstrap-italia'; -// Variabili Bootstrap Italia già disponibili se importi bootstrap-italia -$primary: var(--bs-primary); -$gray-700: var(--bs-gray-700); -$gray-600: var(--bs-gray-600); -$gray-300: var(--bs-gray-300); -.home-content { - max-width: 960px; - margin: 0 auto; - padding: 3rem 1.5rem; - // Titolo principale - &__title { - font-family: var(--bs-font-sans-serif); - font-size: 2.25rem; - font-weight: 600; - line-height: 1.2; - color: $primary; - margin-bottom: 1.5rem; - } - - // Sottotitolo / testo introduttivo - &__lead { - font-size: 1.125rem; - line-height: 1.6; - color: $gray-700; - margin-bottom: 2rem; - } - - // Testo standard - &__text { - font-size: 1rem; - line-height: 1.6; - color: $gray-600; - margin-bottom: 1rem; - } - - // Separatore soft - &__divider { - margin: 2.5rem 0; - border-top: 1px solid $gray-300; - } - - // Link istituzionale - a { - color: $primary; - font-weight: 500; - text-decoration: underline; - - &:hover { - text-decoration: none; - } - } -} - -/* Responsive */ -@media (max-width: 768px) { - .home-content { - padding: 2rem 1rem; - - &__title { - font-size: 1.75rem; - } - } -}