dev #5

Merged
JoeKung merged 17 commits from dev into int 2026-02-09 18:43:44 +01:00
5 changed files with 132 additions and 73 deletions
Showing only changes of commit f1636d9057 - Show all commits

View File

@@ -1,73 +1,87 @@
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<!-- Request Type -->
<div class="form-group">
<label>{{ 'CONTACT.REQ_TYPE_LABEL' | translate }} *</label>
<select formControlName="requestType" class="form-control">
<option *ngFor="let type of requestTypes" [value]="type.value">
{{ type.label | translate }}
</option>
</select>
</div>
<div class="row">
<!-- Phone -->
<app-input formControlName="email" type="email" [label]="'CONTACT.LABEL_EMAIL' | translate" [placeholder]="'CONTACT.PLACEHOLDER_EMAIL' | translate" class="col"></app-input>
<!-- Phone -->
<app-input formControlName="phone" type="tel" [label]="('CONTACT.PHONE' | translate)" [placeholder]="'CONTACT.PLACEHOLDER_PHONE' | translate" class="col"></app-input>
</div>
<!-- User Type Selector (Segmented Control) -->
<div class="user-type-selector">
<div class="type-option" [class.selected]="!isCompany" (click)="setCompanyMode(false)">
{{ 'CONTACT.TYPE_PRIVATE' | translate }}
</div>
<div class="type-option" [class.selected]="isCompany" (click)="setCompanyMode(true)">
{{ 'CONTACT.TYPE_COMPANY' | translate }}
@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>
<!-- Personal Name (Only if NOT Company) -->
<app-input *ngIf="!isCompany" formControlName="name" [label]="'CONTACT.LABEL_NAME' | translate" [placeholder]="'CONTACT.PLACEHOLDER_NAME' | translate"></app-input>
<!-- Company Fields (Only if Company) -->
<div *ngIf="isCompany" class="company-fields">
<app-input formControlName="companyName" [label]="('CONTACT.COMPANY_NAME' | translate) + ' *'" [placeholder]="'CONTACT.PLACEHOLDER_COMPANY' | translate"></app-input>
<app-input formControlName="referencePerson" [label]="('CONTACT.REF_PERSON' | translate) + ' *'" [placeholder]="'CONTACT.PLACEHOLDER_REF_PERSON' | translate"></app-input>
</div>
<div class="form-group">
<label>{{ 'CONTACT.LABEL_MESSAGE' | translate }}</label>
<textarea formControlName="message" class="form-control" rows="4"></textarea>
</div>
<!-- File Upload Section -->
<div class="form-group">
<label>{{ 'CONTACT.UPLOAD_LABEL' | translate }}</label>
<p class="hint">{{ 'CONTACT.UPLOAD_HINT' | translate }}</p>
<div class="drop-zone" (click)="fileInput.click()"
(dragover)="onDragOver($event)" (drop)="onDrop($event)">
<input #fileInput type="file" multiple (change)="onFileSelected($event)" hidden
accept=".jpg,.jpeg,.png,.pdf,.stl,.step,.stp,.3mf,.obj">
<p>{{ 'CONTACT.DROP_FILES' | translate }}</p>
} @else {
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<!-- Request Type -->
<div class="form-group">
<label>{{ 'CONTACT.REQ_TYPE_LABEL' | translate }} *</label>
<select formControlName="requestType" class="form-control">
<option *ngFor="let type of requestTypes" [value]="type.value">
{{ type.label | translate }}
</option>
</select>
</div>
<div class="file-grid" *ngIf="files().length > 0">
<div class="file-item" *ngFor="let file of files(); let i = index">
<button type="button" class="remove-btn" (click)="removeFile(i)">×</button>
<img *ngIf="file.type === 'image'" [src]="file.url" class="preview-img">
<div *ngIf="file.type !== 'image'" class="file-icon">
<span *ngIf="file.type === 'pdf'">PDF</span>
<span *ngIf="file.type === '3d'">3D</span>
</div>
<div class="file-name" [title]="file.file.name">{{ file.file.name }}</div>
<div class="row">
<!-- Phone -->
<app-input formControlName="email" type="email" [label]="'CONTACT.LABEL_EMAIL' | translate" [placeholder]="'CONTACT.PLACEHOLDER_EMAIL' | translate" class="col"></app-input>
<!-- Phone -->
<app-input formControlName="phone" type="tel" [label]="('CONTACT.PHONE' | translate)" [placeholder]="'CONTACT.PLACEHOLDER_PHONE' | translate" class="col"></app-input>
</div>
<!-- User Type Selector (Segmented Control) -->
<div class="user-type-selector">
<div class="type-option" [class.selected]="!isCompany" (click)="setCompanyMode(false)">
{{ 'CONTACT.TYPE_PRIVATE' | translate }}
</div>
<div class="type-option" [class.selected]="isCompany" (click)="setCompanyMode(true)">
{{ 'CONTACT.TYPE_COMPANY' | translate }}
</div>
</div>
</div>
<div class="actions">
<app-button type="submit" [disabled]="form.invalid || sent()">
{{ sent() ? ('CONTACT.MSG_SENT' | translate) : ('CONTACT.SEND' | translate) }}
</app-button>
</div>
</form>
<!-- Personal Name (Only if NOT Company) -->
<app-input *ngIf="!isCompany" formControlName="name" [label]="'CONTACT.LABEL_NAME' | translate" [placeholder]="'CONTACT.PLACEHOLDER_NAME' | translate"></app-input>
<!-- Company Fields (Only if Company) -->
<div *ngIf="isCompany" class="company-fields">
<app-input formControlName="companyName" [label]="('CONTACT.COMPANY_NAME' | translate) + ' *'" [placeholder]="'CONTACT.PLACEHOLDER_COMPANY' | translate"></app-input>
<app-input formControlName="referencePerson" [label]="('CONTACT.REF_PERSON' | translate) + ' *'" [placeholder]="'CONTACT.PLACEHOLDER_REF_PERSON' | translate"></app-input>
</div>
<div class="form-group">
<label>{{ 'CONTACT.LABEL_MESSAGE' | translate }}</label>
<textarea formControlName="message" class="form-control" rows="4"></textarea>
</div>
<!-- File Upload Section -->
<div class="form-group">
<label>{{ 'CONTACT.UPLOAD_LABEL' | translate }}</label>
<p class="hint">{{ 'CONTACT.UPLOAD_HINT' | translate }}</p>
<div class="drop-zone" (click)="fileInput.click()"
(dragover)="onDragOver($event)" (drop)="onDrop($event)">
<input #fileInput type="file" multiple (change)="onFileSelected($event)" hidden
accept=".jpg,.jpeg,.png,.pdf,.stl,.step,.stp,.3mf,.obj">
<p>{{ 'CONTACT.DROP_FILES' | translate }}</p>
</div>
<div class="file-grid" *ngIf="files().length > 0">
<div class="file-item" *ngFor="let file of files(); let i = index">
<button type="button" class="remove-btn" (click)="removeFile(i)">×</button>
<img *ngIf="file.type === 'image'" [src]="file.url" class="preview-img">
<div *ngIf="file.type !== 'image'" class="file-icon">
<span *ngIf="file.type === 'pdf'">PDF</span>
<span *ngIf="file.type === '3d'">3D</span>
</div>
<div class="file-name" [title]="file.file.name">{{ file.file.name }}</div>
</div>
</div>
</div>
<div class="actions">
<app-button type="submit" [disabled]="form.invalid || sent()">
{{ sent() ? ('CONTACT.MSG_SENT' | translate) : ('CONTACT.SEND' | translate) }}
</app-button>
</div>
</form>
}

View File

@@ -131,3 +131,41 @@ app-input.col { width: 100%; }
display: flex; align-items: center; justify-content: center; line-height: 1;
&: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;
}
}

View File

@@ -161,13 +161,14 @@ export class ContactFormComponent {
console.log('Form Submit:', formData);
this.sent.set(true);
setTimeout(() => {
this.sent.set(false);
this.form.reset({ requestType: 'custom', isCompany: false });
this.files.set([]);
}, 3000);
} else {
this.form.markAllAsTouched();
}
}
resetForm() {
this.sent.set(false);
this.form.reset({ requestType: 'custom', isCompany: false });
this.files.set([]);
}
}

View File

@@ -126,6 +126,9 @@
"LABEL_EMAIL": "Email *",
"LABEL_NAME": "Name *",
"MSG_SENT": "Sent!",
"ERR_MAX_FILES": "Max 15 files limit reached."
"ERR_MAX_FILES": "Max 15 files limit reached.",
"SUCCESS_TITLE": "Message Sent Successfully",
"SUCCESS_DESC": "Thank you for contacting us. We have received your message and will send you a recap email shortly.",
"SEND_ANOTHER": "Send Another Message"
}
}

View File

@@ -105,6 +105,9 @@
"LABEL_EMAIL": "Email *",
"LABEL_NAME": "Nome *",
"MSG_SENT": "Inviato!",
"ERR_MAX_FILES": "Limite massimo di 15 file raggiunto."
"ERR_MAX_FILES": "Limite massimo di 15 file raggiunto.",
"SUCCESS_TITLE": "Messaggio Inviato con Successo",
"SUCCESS_DESC": "Grazie per averci contattato. Abbiamo ricevuto il tuo messaggio e ti invieremo una email di riepilogo a breve.",
"SEND_ANOTHER": "Invia un altro messaggio"
}
}