diff --git a/frontend/src/app/features/about/about-page.component.html b/frontend/src/app/features/about/about-page.component.html index 41adea1..20e8f97 100644 --- a/frontend/src/app/features/about/about-page.component.html +++ b/frontend/src/app/features/about/about-page.component.html @@ -10,27 +10,61 @@

{{ 'ABOUT.HOW_TEXT' | translate }}

+
+

{{ 'ABOUT.PASSIONS_TITLE' | translate }}

- {{ 'ABOUT.PILL_1' | translate }} - {{ 'ABOUT.PILL_2' | translate }} - {{ 'ABOUT.PILL_3' | translate }} - {{ 'ABOUT.SERVICE_1' | translate }} - {{ 'ABOUT.SERVICE_2' | translate }} + @for (passion of passions; track passion.id) { + + {{ passion.labelKey | translate }} + + }
-
-
+
+
+ Joe Küng +
Joe Küng Studente Ingegneria Informatica
-
-
+
+
+ Matteo Caletti +
Matteo Caletti Studente Ingegneria Elettronica diff --git a/frontend/src/app/features/about/about-page.component.scss b/frontend/src/app/features/about/about-page.component.scss index 1a926a5..9e3920d 100644 --- a/frontend/src/app/features/about/about-page.component.scss +++ b/frontend/src/app/features/about/about-page.component.scss @@ -29,7 +29,7 @@ text-transform: uppercase; letter-spacing: 0.15em; font-size: 0.875rem; - color: var(--color-primary-500); + color: var(--color-secondary-600); font-weight: 700; margin-bottom: var(--space-2); display: block; @@ -69,7 +69,15 @@ h1 { font-size: 1.1rem; line-height: 1.7; color: var(--color-text-main); - margin-bottom: var(--space-8); + margin-bottom: var(--space-4); +} + +.passions-title { + font-size: 1rem; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--color-secondary-600); + margin-bottom: var(--space-4); } .tags-container { @@ -92,13 +100,14 @@ h1 { font-weight: 500; font-size: 0.9rem; box-shadow: var(--shadow-sm); - transition: all 0.2s ease; + transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease; } -.tag:hover { - transform: translateY(-2px); - border-color: var(--color-primary-500); - color: var(--color-primary-500); +.tag.is-active { + background: var(--color-primary-500); + border-color: var(--color-primary-600); + color: var(--color-neutral-900); + font-weight: 600; box-shadow: var(--shadow-md); } @@ -119,13 +128,37 @@ h1 { } .photo-card { - background: var(--color-surface-card); + background: #ffffff; padding: 1rem; border-radius: var(--radius-lg); - box-shadow: var(--shadow-lg); + border: 1px solid var(--color-border); + box-shadow: var(--shadow-sm); width: 100%; max-width: 260px; position: relative; + transition: box-shadow 0.2s ease, transform 0.2s ease, border-color 0.2s ease, outline-color 0.2s ease; + cursor: pointer; + outline: 2px solid transparent; + outline-offset: 2px; +} + +.photo-card:hover { + transform: translateY(-3px); + box-shadow: var(--shadow-md); + border-color: var(--color-neutral-300); +} + +.photo-card:focus-visible { + outline-color: var(--color-primary-600); +} + +.photo-card.is-active { + border-color: var(--color-primary-600); + box-shadow: 0 0 0 3px rgb(250 207 10 / 30%), var(--shadow-md); +} + +.photo-card.is-selected { + border-color: var(--color-primary-700); } .placeholder-img { @@ -134,6 +167,15 @@ h1 { background: linear-gradient(45deg, var(--color-neutral-200), var(--color-neutral-100)); border-radius: var(--radius-md); margin-bottom: 1rem; + border-bottom: 1px solid var(--color-neutral-300); + overflow: hidden; +} + +.placeholder-img img { + width: 100%; + height: 100%; + display: block; + object-fit: cover; } .member-info { diff --git a/frontend/src/app/features/about/about-page.component.ts b/frontend/src/app/features/about/about-page.component.ts index dcb93f8..15f22da 100644 --- a/frontend/src/app/features/about/about-page.component.ts +++ b/frontend/src/app/features/about/about-page.component.ts @@ -2,6 +2,27 @@ import { Component } from '@angular/core'; import { TranslateModule } from '@ngx-translate/core'; import { AppLocationsComponent } from '../../shared/components/app-locations/app-locations.component'; +type MemberId = 'joe' | 'matteo'; +type PassionId = + | 'bike-trial' + | 'mountain' + | 'ski' + | 'self-hosting' + | 'print-3d' + | 'travel' + | 'snowboard' + | 'snowboard-instructor' + | 'electronics' + | 'woodworking' + | 'van-life' + | 'coffee' + | 'software-development'; + +interface PassionChip { + id: PassionId; + labelKey: string; +} + @Component({ selector: 'app-about-page', standalone: true, @@ -9,5 +30,71 @@ import { AppLocationsComponent } from '../../shared/components/app-locations/app templateUrl: './about-page.component.html', styleUrl: './about-page.component.scss' }) -export class AboutPageComponent {} +export class AboutPageComponent { + selectedMember: MemberId | null = null; + hoveredMember: MemberId | null = null; + readonly passions: ReadonlyArray = [ + { id: 'mountain', labelKey: 'ABOUT.PASSION_MOUNTAIN' }, + { id: 'coffee', labelKey: 'ABOUT.PASSION_COFFEE' }, + { id: 'bike-trial', labelKey: 'ABOUT.PASSION_BIKE_TRIAL' }, + { id: 'electronics', labelKey: 'ABOUT.PASSION_ELECTRONICS' }, + { id: 'travel', labelKey: 'ABOUT.PASSION_TRAVEL' }, + { id: 'woodworking', labelKey: 'ABOUT.PASSION_WOODWORKING' }, + { id: 'print-3d', labelKey: 'ABOUT.PASSION_PRINT_3D' }, + { id: 'ski', labelKey: 'ABOUT.PASSION_SKI' }, + { id: 'software-development', labelKey: 'ABOUT.PASSION_SOFTWARE_DEVELOPMENT' }, + { id: 'snowboard', labelKey: 'ABOUT.PASSION_SNOWBOARD' }, + { id: 'van-life', labelKey: 'ABOUT.PASSION_VAN_LIFE' }, + { id: 'self-hosting', labelKey: 'ABOUT.PASSION_SELF_HOSTING' }, + { id: 'snowboard-instructor', labelKey: 'ABOUT.PASSION_SNOWBOARD_INSTRUCTOR' } + ]; + + private readonly memberPassions: Readonly>> = { + joe: [ + 'bike-trial', + 'mountain', + 'ski', + 'self-hosting', + 'print-3d', + 'travel', + 'coffee', + 'software-development' + ], + matteo: [ + 'bike-trial', + 'mountain', + 'snowboard', + 'snowboard-instructor', + 'electronics', + 'print-3d', + 'woodworking', + 'van-life' + ] + }; + + get activeMember(): MemberId | null { + return this.hoveredMember ?? this.selectedMember; + } + + toggleSelectedMember(member: MemberId): void { + this.selectedMember = this.selectedMember === member ? null : member; + } + + setHoveredMember(member: MemberId | null): void { + this.hoveredMember = member; + } + + isMemberActive(member: MemberId): boolean { + return this.activeMember === member; + } + + isMemberSelected(member: MemberId): boolean { + return this.selectedMember === member; + } + + isPassionActive(passionId: PassionId): boolean { + const member = this.activeMember; + return member !== null && this.memberPassions[member].includes(passionId); + } +} diff --git a/frontend/src/app/features/home/home.component.scss b/frontend/src/app/features/home/home.component.scss index c5fe5fa..67fb9e8 100644 --- a/frontend/src/app/features/home/home.component.scss +++ b/frontend/src/app/features/home/home.component.scss @@ -2,7 +2,7 @@ .home-page { --home-bg: #faf9f6; - --color-bg-card: #f7f7f7; + --color-bg-card: #ffffff; background: var(--home-bg); } @@ -228,12 +228,12 @@ .card-image-placeholder { width: 100%; height: 160px; - background: var(--color-neutral-100); + background: #f5f5f5; margin: -1.5rem -1.5rem 1.5rem -1.5rem; /* Negative margins to bleed to edge */ width: calc(100% + 3rem); border-top-left-radius: var(--radius-lg); border-top-right-radius: var(--radius-lg); - border-bottom: 1px solid var(--color-border); + border-bottom: 1px solid var(--color-neutral-300); display: flex; align-items: center; justify-content: center; diff --git a/frontend/src/app/shared/components/app-card/app-card.component.scss b/frontend/src/app/shared/components/app-card/app-card.component.scss index c0e7484..f394ac1 100644 --- a/frontend/src/app/shared/components/app-card/app-card.component.scss +++ b/frontend/src/app/shared/components/app-card/app-card.component.scss @@ -9,11 +9,13 @@ border: 1px solid var(--color-border); box-shadow: var(--shadow-sm); padding: var(--space-6); - transition: box-shadow 0.2s; + transition: box-shadow 0.2s ease, transform 0.2s ease, border-color 0.2s ease; height: 100%; box-sizing: border-box; &:hover { + transform: translateY(-3px); box-shadow: var(--shadow-md); + border-color: var(--color-neutral-300); } } diff --git a/frontend/src/app/shared/components/app-locations/app-locations.component.html b/frontend/src/app/shared/components/app-locations/app-locations.component.html index e008327..6551a4d 100644 --- a/frontend/src/app/shared/components/app-locations/app-locations.component.html +++ b/frontend/src/app/shared/components/app-locations/app-locations.component.html @@ -8,7 +8,7 @@
- @@ -17,14 +17,14 @@
-

{{ 'LOCATIONS.TICINO' | translate }}

+

{{ 'LOCATIONS.BIASCA' | translate }}

{{ 'LOCATIONS.ADDRESS_TICINO' | translate }}

{{ 'LOCATIONS.BIENNE' | translate }}

{{ 'LOCATIONS.ADDRESS_BIENNE' | translate }}

- +
- -
diff --git a/frontend/src/app/shared/components/app-locations/app-locations.component.scss b/frontend/src/app/shared/components/app-locations/app-locations.component.scss index 1b7f704..8c6a666 100644 --- a/frontend/src/app/shared/components/app-locations/app-locations.component.scss +++ b/frontend/src/app/shared/components/app-locations/app-locations.component.scss @@ -29,10 +29,16 @@ align-items: start; @media(min-width: 992px) { - grid-template-columns: 1fr 2fr; + grid-template-columns: repeat(2, minmax(320px, 420px)); + justify-content: center; } } +.locations-controls { + width: 100%; + max-width: 420px; +} + .location-tabs { margin-bottom: 2rem; width: 100%; @@ -81,7 +87,15 @@ border: 1px solid var(--color-border); box-shadow: var(--shadow-lg); background: var(--color-bg); - height: 450px; + width: 100%; + max-width: 420px; + justify-self: stretch; + height: 320px; + + @media (max-width: 991px) { + max-width: 100%; + height: 300px; + } iframe { width: 100%; diff --git a/frontend/src/assets/i18n/en.json b/frontend/src/assets/i18n/en.json index fc76bd3..0cad9a2 100644 --- a/frontend/src/assets/i18n/en.json +++ b/frontend/src/assets/i18n/en.json @@ -91,6 +91,20 @@ "SUBTITLE": "Transparency on price, quality and time. Technical and CAD consultation for businesses and individuals.", "HOW_TITLE": "How we work", "HOW_TEXT": "We offer an automatic quote for those who already have the 3D file, and a consultation path for those who need to design or optimize the model.", + "PASSIONS_TITLE": "Our passions", + "PASSION_BIKE_TRIAL": "Bike trial", + "PASSION_MOUNTAIN": "Mountain", + "PASSION_SKI": "Ski", + "PASSION_SELF_HOSTING": "Self hosting", + "PASSION_PRINT_3D": "3D printing", + "PASSION_TRAVEL": "Travel", + "PASSION_SNOWBOARD": "Snowboard", + "PASSION_SNOWBOARD_INSTRUCTOR": "Snowboard instructor", + "PASSION_ELECTRONICS": "Electronics", + "PASSION_WOODWORKING": "Woodworking", + "PASSION_VAN_LIFE": "Van life", + "PASSION_COFFEE": "Coffee", + "PASSION_SOFTWARE_DEVELOPMENT": "Software development", "PILL_1": "Instant Quote", "PILL_2": "Technical Consultation", "PILL_3": "Small series up to 500 pcs", @@ -108,7 +122,7 @@ "SUBTITLE": "We have two locations to serve you better. Select a location to see details.", "TICINO": "Ticino", "BIENNE": "Bienne", - "ADDRESS_TICINO": "Via G. Pioda 29a, 6710 Biasca (TI)", + "ADDRESS_TICINO": "Via G. Pioda 29a, Biasca", "ADDRESS_BIENNE": "Lyss-strasse 71, Nidau 2560 Bienne", "CONTACT_US": "Contact Us" }, diff --git a/frontend/src/assets/i18n/it.json b/frontend/src/assets/i18n/it.json index 79f2b31..e31e990 100644 --- a/frontend/src/assets/i18n/it.json +++ b/frontend/src/assets/i18n/it.json @@ -41,19 +41,19 @@ "CAP_4_TEXT": "Non hai il file 3D? Ti aiutiamo a progettarlo, ottimizzarlo per la stampa e scegliere il materiale giusto insieme.", "SEC_SHOP_TITLE": "Shop", "SEC_SHOP_TEXT": "Prodotti selezionati, e pronti all'uso.", - "SEC_SHOP_LIST_1": "Accessori funzionali per officine e laboratori", + "SEC_SHOP_LIST_1": "Prodotti disegnati da noi", "SEC_SHOP_LIST_2": "Ricambi e componenti difficili da reperire", "SEC_SHOP_LIST_3": "Supporti e organizzatori per migliorare i flussi di lavoro", "BTN_DISCOVER": "Scopri i prodotti", "BTN_REQ_SOLUTION": "Richiedi una soluzione", - "CARD_SHOP_1_TITLE": "Best seller tecnici", - "CARD_SHOP_1_TEXT": "Soluzioni provate sul campo e già pronte alla spedizione.", + "CARD_SHOP_1_TITLE": "Selezione di prodotti verificati", + "CARD_SHOP_1_TEXT": "Controllati per garantire funzionalità e stabilità nel lungo periodo.", "CARD_SHOP_2_TITLE": "Kit pronti all'uso", "CARD_SHOP_2_TEXT": "Componenti compatibili e facili da montare senza sorprese.", "CARD_SHOP_3_TITLE": "Su richiesta", "CARD_SHOP_3_TEXT": "Non trovi quello che serve? Lo progettiamo e lo produciamo per te.", "SEC_ABOUT_TITLE": "Su di noi", - "SEC_ABOUT_TEXT": "3D fab è un laboratorio tecnico di stampa 3D. Seguiamo progetti dalla consulenza iniziale alla produzione, con tempi chiari e supporto diretto.", + "SEC_ABOUT_TEXT": "Siamo due studenti di ingegneria: la stampa 3D ci ha conquistati per un motivo semplice, vedere un problema e costruire la soluzione. Da questa idea prendono forma prototipi, componenti oggetti pensati per funzionare nella quotidianità. ", "FOUNDERS_PHOTO": "Foto Founders" }, "CALC": { @@ -152,17 +152,23 @@ "ABOUT": { "TITLE": "Chi Siamo", "EYEBROW": "Laboratorio di stampa 3D", - "SUBTITLE": "Trasparenza su prezzo, qualità e tempi. Consulenza tecnica e CAD per aziende e privati.", - "HOW_TITLE": "Come lavoriamo", - "HOW_TEXT": "Offriamo un preventivo automatico per chi ha già il file 3D, e un percorso di consulenza per chi deve progettare o ottimizzare il modello.", - "PILL_1": "Preventivo immediato", - "PILL_2": "Consulenza tecnica", - "PILL_3": "Piccole serie fino a 500 pz", + "SUBTITLE": "Siamo due studenti con tanta voglia di fare e di imparare.", + "HOW_TEXT": "3D fab nasce dall'interesse iniziale di matteo ", + "PASSIONS_TITLE": "Le nostre passioni", + "PASSION_BIKE_TRIAL": "Bike trial", + "PASSION_MOUNTAIN": "Montagna", + "PASSION_SKI": "Ski", + "PASSION_SELF_HOSTING": "Self hosting", + "PASSION_PRINT_3D": "Stampa 3D", + "PASSION_TRAVEL": "Travel", + "PASSION_SNOWBOARD": "Snowboard", + "PASSION_SNOWBOARD_INSTRUCTOR": "Istruttore snowboard", + "PASSION_ELECTRONICS": "Elettronica", + "PASSION_WOODWORKING": "Lavorazione del legno", + "PASSION_VAN_LIFE": "Van life", + "PASSION_COFFEE": "Caffè", + "PASSION_SOFTWARE_DEVELOPMENT": "Sviluppo software", "SERVICES_TITLE": "Servizi principali", - "SERVICE_1": "Stampa 3D FDM per prototipi e piccole serie", - "SERVICE_2": "Materiali tecnici su richiesta", - "SERVICE_3": "Supporto CAD e post-processing", - "SERVICE_4": "Verifica file e ottimizzazione per la stampa", "TARGET_TITLE": "Per chi è", "TARGET_TEXT": "Piccole aziende, freelance, smanettoni e clienti che cercano un prodotto già pronto dallo shop.", "TEAM_TITLE": "Il Nostro Team" @@ -171,8 +177,9 @@ "TITLE": "Le Nostre Sedi", "SUBTITLE": "Siamo presenti in due sedi. Seleziona la sede per vedere i dettagli.", "TICINO": "Ticino", + "BIASCA": "Biasca", "BIENNE": "Bienne", - "ADDRESS_TICINO": "Via G. Pioda 29a, 6710 Biasca (TI)", + "ADDRESS_TICINO": "Via G. Pioda 29a, Biasca", "ADDRESS_BIENNE": "Lyss-strasse 71, Nidau 2560 Bienne", "CONTACT_US": "Contattaci" }, diff --git a/frontend/src/assets/images/joe.jpg b/frontend/src/assets/images/joe.jpg new file mode 100644 index 0000000..45d4f48 Binary files /dev/null and b/frontend/src/assets/images/joe.jpg differ diff --git a/frontend/src/assets/images/matteo.jpg b/frontend/src/assets/images/matteo.jpg new file mode 100644 index 0000000..96234fe Binary files /dev/null and b/frontend/src/assets/images/matteo.jpg differ