produzione 1 #9
@@ -2,15 +2,16 @@
|
|||||||
<h1>{{ 'CALC.TITLE' | translate }}</h1>
|
<h1>{{ 'CALC.TITLE' | translate }}</h1>
|
||||||
<p class="subtitle">{{ 'CALC.SUBTITLE' | translate }}</p>
|
<p class="subtitle">{{ 'CALC.SUBTITLE' | translate }}</p>
|
||||||
|
|
||||||
@if (orderSuccess()) {
|
|
||||||
<app-alert type="success">{{ 'USER_DETAILS.ORDER_SUCCESS' | translate }}</app-alert>
|
|
||||||
}
|
|
||||||
@if (error()) {
|
@if (error()) {
|
||||||
<app-alert type="error">{{ 'CALC.ERROR_GENERIC' | translate }}</app-alert>
|
<app-alert type="error">{{ 'CALC.ERROR_GENERIC' | translate }}</app-alert>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (step() === 'details' && result()) {
|
@if (step() === 'success') {
|
||||||
|
<div class="container hero">
|
||||||
|
<app-success-state context="calc" (action)="onNewQuote()"></app-success-state>
|
||||||
|
</div>
|
||||||
|
} @else if (step() === 'details' && result()) {
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<app-user-details
|
<app-user-details
|
||||||
[quote]="result()!"
|
[quote]="result()!"
|
||||||
|
|||||||
@@ -6,20 +6,21 @@ import { AppCardComponent } from '../../shared/components/app-card/app-card.comp
|
|||||||
import { AppAlertComponent } from '../../shared/components/app-alert/app-alert.component';
|
import { AppAlertComponent } from '../../shared/components/app-alert/app-alert.component';
|
||||||
import { UploadFormComponent } from './components/upload-form/upload-form.component';
|
import { UploadFormComponent } from './components/upload-form/upload-form.component';
|
||||||
import { QuoteResultComponent } from './components/quote-result/quote-result.component';
|
import { QuoteResultComponent } from './components/quote-result/quote-result.component';
|
||||||
|
import { QuoteRequest, QuoteResult, QuoteEstimatorService } from './services/quote-estimator.service';
|
||||||
import { UserDetailsComponent } from './components/user-details/user-details.component';
|
import { UserDetailsComponent } from './components/user-details/user-details.component';
|
||||||
import { QuoteEstimatorService, QuoteRequest, QuoteResult } from './services/quote-estimator.service';
|
import { SuccessStateComponent } from '../../shared/components/success-state/success-state.component';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-calculator-page',
|
selector: 'app-calculator-page',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, TranslateModule, AppCardComponent, AppAlertComponent, UploadFormComponent, QuoteResultComponent, UserDetailsComponent],
|
imports: [CommonModule, TranslateModule, AppCardComponent, AppAlertComponent, UploadFormComponent, QuoteResultComponent, UserDetailsComponent, SuccessStateComponent],
|
||||||
templateUrl: './calculator-page.component.html',
|
templateUrl: './calculator-page.component.html',
|
||||||
styleUrl: './calculator-page.component.scss'
|
styleUrl: './calculator-page.component.scss'
|
||||||
})
|
})
|
||||||
export class CalculatorPageComponent {
|
export class CalculatorPageComponent {
|
||||||
mode = signal<any>('easy');
|
mode = signal<any>('easy');
|
||||||
step = signal<'upload' | 'quote' | 'details'>('upload');
|
step = signal<'upload' | 'quote' | 'details' | 'success'>('upload');
|
||||||
|
|
||||||
loading = signal(false);
|
loading = signal(false);
|
||||||
uploadProgress = signal(0);
|
uploadProgress = signal(0);
|
||||||
@@ -34,6 +35,7 @@ export class CalculatorPageComponent {
|
|||||||
constructor(private estimator: QuoteEstimatorService, private router: Router) {}
|
constructor(private estimator: QuoteEstimatorService, private router: Router) {}
|
||||||
|
|
||||||
onCalculate(req: QuoteRequest) {
|
onCalculate(req: QuoteRequest) {
|
||||||
|
// ... (logic remains the same, simplified for diff)
|
||||||
this.currentRequest = req;
|
this.currentRequest = req;
|
||||||
this.loading.set(true);
|
this.loading.set(true);
|
||||||
this.uploadProgress.set(0);
|
this.uploadProgress.set(0);
|
||||||
@@ -78,12 +80,14 @@ export class CalculatorPageComponent {
|
|||||||
onSubmitOrder(orderData: any) {
|
onSubmitOrder(orderData: any) {
|
||||||
console.log('Order Submitted:', orderData);
|
console.log('Order Submitted:', orderData);
|
||||||
this.orderSuccess.set(true);
|
this.orderSuccess.set(true);
|
||||||
this.step.set('upload'); // Reset to start, or show success page?
|
this.step.set('success');
|
||||||
// For now, let's show success message and reset
|
}
|
||||||
setTimeout(() => {
|
|
||||||
this.orderSuccess.set(false);
|
onNewQuote() {
|
||||||
}, 5000);
|
this.step.set('upload');
|
||||||
this.result.set(null);
|
this.result.set(null);
|
||||||
|
this.orderSuccess.set(false);
|
||||||
|
this.mode.set('easy'); // Reset to default
|
||||||
}
|
}
|
||||||
|
|
||||||
private currentRequest: QuoteRequest | null = null;
|
private currentRequest: QuoteRequest | null = null;
|
||||||
|
|||||||
@@ -1,15 +1,5 @@
|
|||||||
@if (sent()) {
|
@if (sent()) {
|
||||||
<div class="success-state">
|
<app-success-state context="contact" (action)="resetForm()"></app-success-state>
|
||||||
<div class="success-icon">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
|
|
||||||
<polyline points="22 4 12 14.01 9 11.01"></polyline>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<h3>{{ 'CONTACT.SUCCESS_TITLE' | translate }}</h3>
|
|
||||||
<p>{{ 'CONTACT.SUCCESS_DESC' | translate }}</p>
|
|
||||||
<app-button (click)="resetForm()">{{ 'CONTACT.SEND_ANOTHER' | translate }}</app-button>
|
|
||||||
</div>
|
|
||||||
} @else {
|
} @else {
|
||||||
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
||||||
<!-- Request Type -->
|
<!-- Request Type -->
|
||||||
|
|||||||
@@ -132,40 +132,4 @@ app-input.col { width: 100%; }
|
|||||||
&:hover { background: red; }
|
&:hover { background: red; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Success State */
|
/* Success State styles moved to shared component */
|
||||||
.success-state {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
text-align: center;
|
|
||||||
padding: var(--space-8) var(--space-4);
|
|
||||||
gap: var(--space-4);
|
|
||||||
min-height: 300px; /* Ensure visual balance */
|
|
||||||
|
|
||||||
.success-icon {
|
|
||||||
width: 64px;
|
|
||||||
height: 64px;
|
|
||||||
color: var(--color-success, #10b981);
|
|
||||||
margin-bottom: var(--space-2);
|
|
||||||
|
|
||||||
svg {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--color-text);
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
color: var(--color-text-muted);
|
|
||||||
max-width: 400px;
|
|
||||||
margin-bottom: var(--space-4);
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,10 +12,12 @@ interface FilePreview {
|
|||||||
type: 'image' | 'pdf' | '3d' | 'other';
|
type: 'image' | 'pdf' | '3d' | 'other';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import { SuccessStateComponent } from '../../../../shared/components/success-state/success-state.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-contact-form',
|
selector: 'app-contact-form',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, ReactiveFormsModule, TranslateModule, AppInputComponent, AppButtonComponent],
|
imports: [CommonModule, ReactiveFormsModule, TranslateModule, AppInputComponent, AppButtonComponent, SuccessStateComponent],
|
||||||
templateUrl: './contact-form.component.html',
|
templateUrl: './contact-form.component.html',
|
||||||
styleUrl: './contact-form.component.scss'
|
styleUrl: './contact-form.component.scss'
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<div class="success-state">
|
||||||
|
<div class="success-icon">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
|
||||||
|
<polyline points="22 4 12 14.01 9 11.01"></polyline>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@switch (context()) {
|
||||||
|
@case ('contact') {
|
||||||
|
<h3>{{ 'CONTACT.SUCCESS_TITLE' | translate }}</h3>
|
||||||
|
<p>{{ 'CONTACT.SUCCESS_DESC' | translate }}</p>
|
||||||
|
<app-button (click)="action.emit()">{{ 'CONTACT.SEND_ANOTHER' | translate }}</app-button>
|
||||||
|
}
|
||||||
|
@case ('calc') {
|
||||||
|
<h3>{{ 'CALC.ORDER_SUCCESS_TITLE' | translate }}</h3>
|
||||||
|
<p>{{ 'CALC.ORDER_SUCCESS_DESC' | translate }}</p>
|
||||||
|
<app-button (click)="action.emit()">{{ 'CALC.NEW_QUOTE' | translate }}</app-button>
|
||||||
|
}
|
||||||
|
@case ('shop') {
|
||||||
|
<h3>{{ 'SHOP.SUCCESS_TITLE' | translate }}</h3>
|
||||||
|
<p>{{ 'SHOP.SUCCESS_DESC' | translate }}</p>
|
||||||
|
<app-button (click)="action.emit()">{{ 'SHOP.CONTINUE' | translate }}</app-button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
.success-state {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
padding: var(--space-8) var(--space-4);
|
||||||
|
gap: var(--space-4);
|
||||||
|
min-height: 300px; /* Ensure visual balance */
|
||||||
|
|
||||||
|
.success-icon {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
color: var(--color-success, #10b981);
|
||||||
|
margin-bottom: var(--space-2);
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--color-text);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
max-width: 400px;
|
||||||
|
margin-bottom: var(--space-4);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { Component, input, output } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { AppButtonComponent } from '../app-button/app-button.component';
|
||||||
|
|
||||||
|
export type SuccessContext = 'contact' | 'calc' | 'shop';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-success-state',
|
||||||
|
standalone: true,
|
||||||
|
imports: [CommonModule, TranslateModule, AppButtonComponent],
|
||||||
|
templateUrl: './success-state.component.html',
|
||||||
|
styleUrl: './success-state.component.scss'
|
||||||
|
})
|
||||||
|
export class SuccessStateComponent {
|
||||||
|
context = input.required<SuccessContext>();
|
||||||
|
action = output<void>();
|
||||||
|
}
|
||||||
@@ -61,6 +61,9 @@
|
|||||||
"ORDER": "Order Now",
|
"ORDER": "Order Now",
|
||||||
"CONSULT": "Request Consultation",
|
"CONSULT": "Request Consultation",
|
||||||
"ERROR_GENERIC": "An error occurred while calculating the quote.",
|
"ERROR_GENERIC": "An error occurred while calculating the quote.",
|
||||||
|
"NEW_QUOTE": "Calculate New Quote",
|
||||||
|
"ORDER_SUCCESS_TITLE": "Order Submitted Successfully",
|
||||||
|
"ORDER_SUCCESS_DESC": "We have received your order details. You will receive a confirmation email shortly with the payment details.",
|
||||||
"BENEFITS_TITLE": "Why choose us?",
|
"BENEFITS_TITLE": "Why choose us?",
|
||||||
"BENEFITS_1": "Automatic quote with instant cost and time",
|
"BENEFITS_1": "Automatic quote with instant cost and time",
|
||||||
"BENEFITS_2": "Selected materials and quality control",
|
"BENEFITS_2": "Selected materials and quality control",
|
||||||
|
|||||||
@@ -40,6 +40,9 @@
|
|||||||
"ORDER": "Ordina Ora",
|
"ORDER": "Ordina Ora",
|
||||||
"CONSULT": "Richiedi Consulenza",
|
"CONSULT": "Richiedi Consulenza",
|
||||||
"ERROR_GENERIC": "Si è verificato un errore durante il calcolo del preventivo.",
|
"ERROR_GENERIC": "Si è verificato un errore durante il calcolo del preventivo.",
|
||||||
|
"NEW_QUOTE": "Calcola Nuovo Preventivo",
|
||||||
|
"ORDER_SUCCESS_TITLE": "Ordine Inviato con Successo",
|
||||||
|
"ORDER_SUCCESS_DESC": "Abbiamo ricevuto i dettagli del tuo ordine. Riceverai a breve una email di conferma con i dettagli per il pagamento.",
|
||||||
"BENEFITS_TITLE": "Perché scegliere noi?",
|
"BENEFITS_TITLE": "Perché scegliere noi?",
|
||||||
"BENEFITS_1": "Preventivo automatico con costo e tempo immediati",
|
"BENEFITS_1": "Preventivo automatico con costo e tempo immediati",
|
||||||
"BENEFITS_2": "Materiali selezionati e qualità controllata",
|
"BENEFITS_2": "Materiali selezionati e qualità controllata",
|
||||||
|
|||||||
Reference in New Issue
Block a user