fix(front-end): improvements
This commit is contained in:
@@ -46,14 +46,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- User Type Selector -->
|
<!-- User Type Selector -->
|
||||||
<div class="user-type-selector">
|
<app-toggle-selector
|
||||||
<div class="type-option" [class.selected]="!isCompany" (click)="setCustomerType(false)">
|
[options]="userTypeOptions"
|
||||||
{{ 'CONTACT.TYPE_PRIVATE' | translate }}
|
[selectedValue]="checkoutForm.get('customerType')?.value"
|
||||||
</div>
|
(selectionChange)="setCustomerType($event)">
|
||||||
<div class="type-option" [class.selected]="isCompany" (click)="setCustomerType(true)">
|
</app-toggle-selector>
|
||||||
{{ 'CONTACT.TYPE_COMPANY' | translate }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<app-input formControlName="addressLine1" [label]="'CHECKOUT.ADDRESS_1' | translate" [required]="true"></app-input>
|
<app-input formControlName="addressLine1" [label]="'CHECKOUT.ADDRESS_1' | translate" [required]="true"></app-input>
|
||||||
<app-input formControlName="addressLine2" [label]="'CHECKOUT.ADDRESS_2' | translate"></app-input>
|
<app-input formControlName="addressLine2" [label]="'CHECKOUT.ADDRESS_2' | translate"></app-input>
|
||||||
|
|||||||
@@ -64,39 +64,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* User Type Selector - Matching Contact Form Style */
|
/* User Type Selector CSS has been extracted to app-toggle-selector component */
|
||||||
.user-type-selector {
|
|
||||||
display: flex;
|
|
||||||
background-color: var(--color-neutral-100);
|
|
||||||
border-radius: var(--radius-md);
|
|
||||||
padding: 4px;
|
|
||||||
margin: var(--space-6) 0;
|
|
||||||
gap: 4px;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.type-option {
|
|
||||||
flex: 1;
|
|
||||||
text-align: center;
|
|
||||||
padding: 8px 16px;
|
|
||||||
border-radius: var(--radius-sm);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--color-text-muted);
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
user-select: none;
|
|
||||||
|
|
||||||
&:hover { color: var(--color-text); }
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
background-color: var(--color-brand);
|
|
||||||
color: #000;
|
|
||||||
font-weight: 600;
|
|
||||||
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.company-fields {
|
.company-fields {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { QuoteEstimatorService } from '../calculator/services/quote-estimator.se
|
|||||||
import { AppInputComponent } from '../../shared/components/app-input/app-input.component';
|
import { AppInputComponent } from '../../shared/components/app-input/app-input.component';
|
||||||
import { AppButtonComponent } from '../../shared/components/app-button/app-button.component';
|
import { AppButtonComponent } from '../../shared/components/app-button/app-button.component';
|
||||||
import { AppCardComponent } from '../../shared/components/app-card/app-card.component';
|
import { AppCardComponent } from '../../shared/components/app-card/app-card.component';
|
||||||
|
import { AppToggleSelectorComponent, ToggleOption } from '../../shared/components/app-toggle-selector/app-toggle-selector.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-checkout',
|
selector: 'app-checkout',
|
||||||
@@ -17,7 +18,8 @@ import { AppCardComponent } from '../../shared/components/app-card/app-card.comp
|
|||||||
TranslateModule,
|
TranslateModule,
|
||||||
AppInputComponent,
|
AppInputComponent,
|
||||||
AppButtonComponent,
|
AppButtonComponent,
|
||||||
AppCardComponent
|
AppCardComponent,
|
||||||
|
AppToggleSelectorComponent
|
||||||
],
|
],
|
||||||
templateUrl: './checkout.component.html',
|
templateUrl: './checkout.component.html',
|
||||||
styleUrls: ['./checkout.component.scss']
|
styleUrls: ['./checkout.component.scss']
|
||||||
@@ -35,6 +37,11 @@ export class CheckoutComponent implements OnInit {
|
|||||||
isSubmitting = signal(false); // Add signal for submit state
|
isSubmitting = signal(false); // Add signal for submit state
|
||||||
quoteSession = signal<any>(null); // Add signal for session details
|
quoteSession = signal<any>(null); // Add signal for session details
|
||||||
|
|
||||||
|
userTypeOptions: ToggleOption[] = [
|
||||||
|
{ label: 'CONTACT.TYPE_PRIVATE', value: 'PRIVATE' },
|
||||||
|
{ label: 'CONTACT.TYPE_COMPANY', value: 'BUSINESS' }
|
||||||
|
];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.checkoutForm = this.fb.group({
|
this.checkoutForm = this.fb.group({
|
||||||
email: ['', [Validators.required, Validators.email]],
|
email: ['', [Validators.required, Validators.email]],
|
||||||
@@ -73,9 +80,9 @@ export class CheckoutComponent implements OnInit {
|
|||||||
return this.checkoutForm.get('customerType')?.value === 'BUSINESS';
|
return this.checkoutForm.get('customerType')?.value === 'BUSINESS';
|
||||||
}
|
}
|
||||||
|
|
||||||
setCustomerType(isCompany: boolean) {
|
setCustomerType(type: string) {
|
||||||
const type = isCompany ? 'BUSINESS' : 'PRIVATE';
|
|
||||||
this.checkoutForm.patchValue({ customerType: type });
|
this.checkoutForm.patchValue({ customerType: type });
|
||||||
|
const isCompany = type === 'BUSINESS';
|
||||||
|
|
||||||
const billingGroup = this.checkoutForm.get('billingAddress') as FormGroup;
|
const billingGroup = this.checkoutForm.get('billingAddress') as FormGroup;
|
||||||
const companyControl = billingGroup.get('companyName');
|
const companyControl = billingGroup.get('companyName');
|
||||||
|
|||||||
@@ -107,6 +107,12 @@ export class OrderComponent implements OnInit {
|
|||||||
if (lang === 'de') {
|
if (lang === 'de') {
|
||||||
return 'https://go.twint.ch/static/img/button_dark_de.svg';
|
return 'https://go.twint.ch/static/img/button_dark_de.svg';
|
||||||
}
|
}
|
||||||
|
if (lang === 'it'){
|
||||||
|
return 'https://go.twint.ch/static/img/button_dark_it.svg';
|
||||||
|
}
|
||||||
|
if (lang === 'fr'){
|
||||||
|
return 'https://go.twint.ch/static/img/button_dark_fr.svg';
|
||||||
|
}
|
||||||
// Default to EN for everything else (it, fr, en) as instructed or if not DE
|
// Default to EN for everything else (it, fr, en) as instructed or if not DE
|
||||||
return 'https://go.twint.ch/static/img/button_dark_en.svg';
|
return 'https://go.twint.ch/static/img/button_dark_en.svg';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,18 +8,11 @@
|
|||||||
<div class="locations-grid">
|
<div class="locations-grid">
|
||||||
<div class="locations-controls">
|
<div class="locations-controls">
|
||||||
<div class="location-tabs">
|
<div class="location-tabs">
|
||||||
<button
|
<app-toggle-selector
|
||||||
class="tab-btn"
|
[options]="locationOptions"
|
||||||
[class.active]="selectedLocation === 'ticino'"
|
[selectedValue]="selectedLocation"
|
||||||
(click)="selectLocation('ticino')">
|
(selectionChange)="selectLocation($event)">
|
||||||
{{ 'LOCATIONS.TICINO' | translate }}
|
</app-toggle-selector>
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="tab-btn"
|
|
||||||
[class.active]="selectedLocation === 'bienne'"
|
|
||||||
(click)="selectLocation('bienne')">
|
|
||||||
{{ 'LOCATIONS.BIENNE' | translate }}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="location-details">
|
<div class="location-details">
|
||||||
@@ -43,12 +36,12 @@
|
|||||||
<div class="map-container">
|
<div class="map-container">
|
||||||
<iframe
|
<iframe
|
||||||
*ngIf="selectedLocation === 'ticino'"
|
*ngIf="selectedLocation === 'ticino'"
|
||||||
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d177305.41680509657!2d8.826330925208468!3d46.00511195679905!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x4784407817452d5b%3A0x6a0c0e86b976660!2sTicino%2C%20Svizzera!5e0!3m2!1sit!2sit!4v1700000000000!5m2!1sit!2sit"
|
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2753.843657475132!2d8.96627047671755!3d46.35265507912163!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x4785ca88d01d4a03%3A0xc312484ab7592fb!2sVia%20Giov.Bta.%20Pioda%2029A%2C%206710%20Biasca%2C%20Switzerland!5e0!3m2!1sen!2sch!4v1700000000000!5m2!1sen!2sch"
|
||||||
width="100%" height="450" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade">
|
width="100%" height="450" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade">
|
||||||
</iframe>
|
</iframe>
|
||||||
<iframe
|
<iframe
|
||||||
*ngIf="selectedLocation === 'bienne'"
|
*ngIf="selectedLocation === 'bienne'"
|
||||||
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d43521.94247549427!2d7.211756262451172!3d47.13677764958641!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x478e192760f384f9%3A0xcb281f622956f4e6!2sBiel%2C%20Svizzera!5e0!3m2!1sit!2sit!4v1700000000000!5m2!1sit!2sit"
|
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2729.0438104193587!2d7.240752176735282!3d47.126435979155985!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x478e1eb84efba295%3A0x95924d5ba8b6f3b0!2sLyss-Strasse%2071%2C%202560%20Nidau%2C%20Switzerland!5e0!3m2!1sen!2sch!4v1700000000000!5m2!1sen!2sch"
|
||||||
width="100%" height="450" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade">
|
width="100%" height="450" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade">
|
||||||
</iframe>
|
</iframe>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -34,36 +34,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.location-tabs {
|
.location-tabs {
|
||||||
display: flex;
|
|
||||||
gap: 1rem;
|
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
background: var(--color-bg);
|
width: 100%;
|
||||||
padding: 0.5rem;
|
|
||||||
border-radius: var(--radius-md);
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-btn {
|
|
||||||
flex: 1;
|
|
||||||
padding: 0.75rem;
|
|
||||||
border: none;
|
|
||||||
background: transparent;
|
|
||||||
border-radius: var(--radius-sm);
|
|
||||||
color: var(--color-text-muted);
|
|
||||||
font-weight: 600;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: var(--color-text-main);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
background: var(--color-primary-500);
|
|
||||||
color: var(--color-neutral-900);
|
|
||||||
box-shadow: var(--shadow-sm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.location-details {
|
.location-details {
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
|
|||||||
@@ -2,18 +2,24 @@ import { Component } from '@angular/core';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { RouterLink } from '@angular/router';
|
import { RouterLink } from '@angular/router';
|
||||||
|
import { AppToggleSelectorComponent, ToggleOption } from '../app-toggle-selector/app-toggle-selector.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-locations',
|
selector: 'app-locations',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, TranslateModule, RouterLink],
|
imports: [CommonModule, TranslateModule, RouterLink, AppToggleSelectorComponent],
|
||||||
templateUrl: './app-locations.component.html',
|
templateUrl: './app-locations.component.html',
|
||||||
styleUrl: './app-locations.component.scss'
|
styleUrl: './app-locations.component.scss'
|
||||||
})
|
})
|
||||||
export class AppLocationsComponent {
|
export class AppLocationsComponent {
|
||||||
selectedLocation: 'ticino' | 'bienne' = 'ticino';
|
selectedLocation: 'ticino' | 'bienne' = 'ticino';
|
||||||
|
|
||||||
selectLocation(location: 'ticino' | 'bienne') {
|
locationOptions: ToggleOption[] = [
|
||||||
|
{ label: 'LOCATIONS.TICINO', value: 'ticino' },
|
||||||
|
{ label: 'LOCATIONS.BIENNE', value: 'bienne' },
|
||||||
|
];
|
||||||
|
|
||||||
|
selectLocation(location: any) {
|
||||||
this.selectedLocation = location;
|
this.selectedLocation = location;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<div class="user-type-selector">
|
||||||
|
@for (option of options(); track option.value) {
|
||||||
|
<div class="type-option"
|
||||||
|
[class.selected]="selectedValue() === option.value"
|
||||||
|
(click)="selectOption(option.value)">
|
||||||
|
{{ option.label | translate }}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-type-selector {
|
||||||
|
display: flex;
|
||||||
|
background-color: var(--color-neutral-100);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
padding: 4px;
|
||||||
|
gap: 4px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type-option {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
&:hover { color: var(--color-text); }
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
background-color: var(--color-brand);
|
||||||
|
color: #000;
|
||||||
|
font-weight: 600;
|
||||||
|
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { Component, input, output } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
export interface ToggleOption {
|
||||||
|
label: string;
|
||||||
|
value: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-toggle-selector',
|
||||||
|
standalone: true,
|
||||||
|
imports: [CommonModule, TranslateModule],
|
||||||
|
templateUrl: './app-toggle-selector.component.html',
|
||||||
|
styleUrl: './app-toggle-selector.component.scss'
|
||||||
|
})
|
||||||
|
export class AppToggleSelectorComponent {
|
||||||
|
options = input.required<ToggleOption[]>();
|
||||||
|
selectedValue = input.required<any>();
|
||||||
|
|
||||||
|
selectionChange = output<any>();
|
||||||
|
|
||||||
|
selectOption(value: any) {
|
||||||
|
this.selectionChange.emit(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -107,8 +107,8 @@
|
|||||||
"SUBTITLE": "We have two locations to serve you better. Select a location to see details.",
|
"SUBTITLE": "We have two locations to serve you better. Select a location to see details.",
|
||||||
"TICINO": "Ticino",
|
"TICINO": "Ticino",
|
||||||
"BIENNE": "Bienne",
|
"BIENNE": "Bienne",
|
||||||
"ADDRESS_TICINO": "Ticino Office, Switzerland",
|
"ADDRESS_TICINO": "Via G. Pioda 29a, 6710 Biasca (TI)",
|
||||||
"ADDRESS_BIENNE": "Bienne Office, Switzerland",
|
"ADDRESS_BIENNE": "Lyss-strasse 71, Nidau 2560 Bienne",
|
||||||
"CONTACT_US": "Contact Us"
|
"CONTACT_US": "Contact Us"
|
||||||
},
|
},
|
||||||
"LEGAL": {
|
"LEGAL": {
|
||||||
|
|||||||
@@ -102,7 +102,7 @@
|
|||||||
"PROCESSING": "Elaborazione...",
|
"PROCESSING": "Elaborazione...",
|
||||||
"NOTES_PLACEHOLDER": "Istruzioni specifiche...",
|
"NOTES_PLACEHOLDER": "Istruzioni specifiche...",
|
||||||
"SETUP_NOTE": "* Include {{cost}} Costo di Setup",
|
"SETUP_NOTE": "* Include {{cost}} Costo di Setup",
|
||||||
"STEP_WARNING": "La visualizzazione 3D non è compatibile con i file step e 3mf, ma il calcolatore funziona."
|
"STEP_WARNING": "La visualizzazione 3D non è compatibile con i file step e 3mf"
|
||||||
},
|
},
|
||||||
"QUOTE": {
|
"QUOTE": {
|
||||||
"PROCEED_ORDER": "Procedi con l'ordine",
|
"PROCEED_ORDER": "Procedi con l'ordine",
|
||||||
@@ -170,8 +170,8 @@
|
|||||||
"SUBTITLE": "Siamo presenti in due sedi per coprire meglio il territorio. Seleziona la sede per vedere i dettagli.",
|
"SUBTITLE": "Siamo presenti in due sedi per coprire meglio il territorio. Seleziona la sede per vedere i dettagli.",
|
||||||
"TICINO": "Ticino",
|
"TICINO": "Ticino",
|
||||||
"BIENNE": "Bienne",
|
"BIENNE": "Bienne",
|
||||||
"ADDRESS_TICINO": "Sede Ticino, Svizzera",
|
"ADDRESS_TICINO": "Via G. Pioda 29a, 6710 Biasca (TI)",
|
||||||
"ADDRESS_BIENNE": "Sede Bienne, Svizzera",
|
"ADDRESS_BIENNE": "Lyss-strasse 71, Nidau 2560 Bienne",
|
||||||
"CONTACT_US": "Contattaci"
|
"CONTACT_US": "Contattaci"
|
||||||
},
|
},
|
||||||
"LEGAL": {
|
"LEGAL": {
|
||||||
|
|||||||
Reference in New Issue
Block a user