dev #5

Merged
JoeKung merged 17 commits from dev into int 2026-02-09 18:43:44 +01:00
10 changed files with 109 additions and 62 deletions
Showing only changes of commit 05e1c224f0 - Show all commits

View File

@@ -2,15 +2,16 @@
<h1>{{ 'CALC.TITLE' | translate }}</h1>
<p class="subtitle">{{ 'CALC.SUBTITLE' | translate }}</p>
@if (orderSuccess()) {
<app-alert type="success">{{ 'USER_DETAILS.ORDER_SUCCESS' | translate }}</app-alert>
}
@if (error()) {
<app-alert type="error">{{ 'CALC.ERROR_GENERIC' | translate }}</app-alert>
}
</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">
<app-user-details
[quote]="result()!"

View File

@@ -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 { UploadFormComponent } from './components/upload-form/upload-form.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 { QuoteEstimatorService, QuoteRequest, QuoteResult } from './services/quote-estimator.service';
import { SuccessStateComponent } from '../../shared/components/success-state/success-state.component';
import { Router } from '@angular/router';
@Component({
selector: 'app-calculator-page',
standalone: true,
imports: [CommonModule, TranslateModule, AppCardComponent, AppAlertComponent, UploadFormComponent, QuoteResultComponent, UserDetailsComponent],
imports: [CommonModule, TranslateModule, AppCardComponent, AppAlertComponent, UploadFormComponent, QuoteResultComponent, UserDetailsComponent, SuccessStateComponent],
templateUrl: './calculator-page.component.html',
styleUrl: './calculator-page.component.scss'
})
export class CalculatorPageComponent {
mode = signal<any>('easy');
step = signal<'upload' | 'quote' | 'details'>('upload');
step = signal<'upload' | 'quote' | 'details' | 'success'>('upload');
loading = signal(false);
uploadProgress = signal(0);
@@ -34,6 +35,7 @@ export class CalculatorPageComponent {
constructor(private estimator: QuoteEstimatorService, private router: Router) {}
onCalculate(req: QuoteRequest) {
// ... (logic remains the same, simplified for diff)
this.currentRequest = req;
this.loading.set(true);
this.uploadProgress.set(0);
@@ -78,12 +80,14 @@ export class CalculatorPageComponent {
onSubmitOrder(orderData: any) {
console.log('Order Submitted:', orderData);
this.orderSuccess.set(true);
this.step.set('upload'); // Reset to start, or show success page?
// For now, let's show success message and reset
setTimeout(() => {
this.orderSuccess.set(false);
}, 5000);
this.step.set('success');
}
onNewQuote() {
this.step.set('upload');
this.result.set(null);
this.orderSuccess.set(false);
this.mode.set('easy'); // Reset to default
}
private currentRequest: QuoteRequest | null = null;

View File

@@ -1,15 +1,5 @@
@if (sent()) {
<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>
<h3>{{ 'CONTACT.SUCCESS_TITLE' | translate }}</h3>
<p>{{ 'CONTACT.SUCCESS_DESC' | translate }}</p>
<app-button (click)="resetForm()">{{ 'CONTACT.SEND_ANOTHER' | translate }}</app-button>
</div>
<app-success-state context="contact" (action)="resetForm()"></app-success-state>
} @else {
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<!-- Request Type -->

View File

@@ -132,40 +132,4 @@ app-input.col { width: 100%; }
&:hover { background: red; }
}
/* Success State */
.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;
}
}
/* Success State styles moved to shared component */

View File

@@ -12,10 +12,12 @@ interface FilePreview {
type: 'image' | 'pdf' | '3d' | 'other';
}
import { SuccessStateComponent } from '../../../../shared/components/success-state/success-state.component';
@Component({
selector: 'app-contact-form',
standalone: true,
imports: [CommonModule, ReactiveFormsModule, TranslateModule, AppInputComponent, AppButtonComponent],
imports: [CommonModule, ReactiveFormsModule, TranslateModule, AppInputComponent, AppButtonComponent, SuccessStateComponent],
templateUrl: './contact-form.component.html',
styleUrl: './contact-form.component.scss'
})

View File

@@ -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>

View File

@@ -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;
}
}

View File

@@ -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>();
}

View File

@@ -61,6 +61,9 @@
"ORDER": "Order Now",
"CONSULT": "Request Consultation",
"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_1": "Automatic quote with instant cost and time",
"BENEFITS_2": "Selected materials and quality control",

View File

@@ -40,6 +40,9 @@
"ORDER": "Ordina Ora",
"CONSULT": "Richiedi Consulenza",
"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_1": "Preventivo automatico con costo e tempo immediati",
"BENEFITS_2": "Materiali selezionati e qualità controllata",