fix(front-end): calculator improvements

This commit is contained in:
2026-02-27 10:43:06 +01:00
parent 219b4e127d
commit a85c57032d
7 changed files with 139 additions and 68 deletions

View File

@@ -10,15 +10,11 @@ import { StlViewerComponent } from '../../../../shared/components/stl-viewer/stl
import { ColorSelectorComponent } from '../../../../shared/components/color-selector/color-selector.component';
import { QuoteRequest, QuoteEstimatorService, OptionsResponse, SimpleOption, MaterialOption, VariantOption } from '../../services/quote-estimator.service';
import { getColorHex } from '../../../../core/constants/colors.const';
import * as THREE from 'three';
// @ts-ignore
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js';
interface FormItem {
file: File;
quantity: number;
color: string;
dimensions?: {x: number, y: number, z: number};
}
@Component({
@@ -74,35 +70,6 @@ export class UploadFormComponent implements OnInit {
return name.endsWith('.stl');
}
private async getStlDimensions(file: File): Promise<{x: number, y: number, z: number} | null> {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = (e) => {
try {
const loader = new STLLoader();
const geometry = loader.parse(e.target?.result as ArrayBuffer);
geometry.computeBoundingBox();
if (geometry.boundingBox) {
const size = new THREE.Vector3();
geometry.boundingBox.getSize(size);
resolve({
x: Math.round(size.x * 10) / 10,
y: Math.round(size.y * 10) / 10,
z: Math.round(size.z * 10) / 10
});
return;
}
resolve(null);
} catch (err) {
console.error("Error parsing STL for dimensions:", err);
resolve(null);
}
};
reader.onerror = () => resolve(null);
reader.readAsArrayBuffer(file);
});
}
constructor() {
this.form = this.fb.group({
itemsTouched: [false], // Hack to track touched state for custom items list
@@ -189,7 +156,7 @@ export class UploadFormComponent implements OnInit {
}
}
async onFilesDropped(newFiles: File[]) {
onFilesDropped(newFiles: File[]) {
const MAX_SIZE = 200 * 1024 * 1024; // 200MB
const validItems: FormItem[] = [];
let hasError = false;
@@ -198,13 +165,8 @@ export class UploadFormComponent implements OnInit {
if (file.size > MAX_SIZE) {
hasError = true;
} else {
let dimensions = undefined;
if (file.name.toLowerCase().endsWith('.stl')) {
const dims = await this.getStlDimensions(file);
if (dims) dimensions = dims;
}
// Default color is Black
validItems.push({ file, quantity: 1, color: 'Black', dimensions });
validItems.push({ file, quantity: 1, color: 'Black' });
}
}
@@ -296,16 +258,11 @@ export class UploadFormComponent implements OnInit {
});
}
async setFiles(files: File[]) {
setFiles(files: File[]) {
const validItems: FormItem[] = [];
for (const file of files) {
let dimensions = undefined;
if (file.name.toLowerCase().endsWith('.stl')) {
const dims = await this.getStlDimensions(file);
if (dims) dimensions = dims;
}
// Default color is Black or derive from somewhere if possible, but here we just init
validItems.push({ file, quantity: 1, color: 'Black', dimensions });
validItems.push({ file, quantity: 1, color: 'Black' });
}
if (validItems.length > 0) {

View File

@@ -5,7 +5,7 @@ import { map, catchError, tap } from 'rxjs/operators';
import { environment } from '../../../../environments/environment';
export interface QuoteRequest {
items: { file: File, quantity: number, color?: string, dimensions?: {x: number, y: number, z: number} }[];
items: { file: File, quantity: number, color?: string }[];
material: string;
quality: string;
notes?: string;
@@ -273,9 +273,6 @@ export class QuoteEstimatorService {
quality: easyPreset ? easyPreset.quality : request.quality,
supportsEnabled: request.supportEnabled,
color: item.color || '#FFFFFF',
boundingBoxX: item.dimensions?.x,
boundingBoxY: item.dimensions?.y,
boundingBoxZ: item.dimensions?.z,
layerHeight: easyPreset ? easyPreset.layerHeight : request.layerHeight,
infillDensity: easyPreset ? easyPreset.infillDensity : request.infillDensity,
infillPattern: easyPreset ? easyPreset.infillPattern : request.infillPattern,

View File

@@ -32,6 +32,12 @@
<h3>{{ 'CHECKOUT.BILLING_ADDR' | translate }}</h3>
</div>
<div formGroupName="billingAddress">
<!-- User Type Selector -->
<app-toggle-selector class="mb-4 user-type-selector-compact"
[options]="userTypeOptions"
[selectedValue]="checkoutForm.get('customerType')?.value"
(selectionChange)="setCustomerType($event)">
</app-toggle-selector>
<!-- Private Person Fields -->
<div *ngIf="!isCompany" class="form-row">
@@ -44,13 +50,6 @@
<app-input formControlName="companyName" [label]="'CHECKOUT.COMPANY_NAME' | translate" [required]="true" [placeholder]="'CONTACT.PLACEHOLDER_COMPANY' | translate"></app-input>
<app-input formControlName="referencePerson" [label]="'CONTACT.REF_PERSON' | translate" [required]="true" [placeholder]="'CONTACT.PLACEHOLDER_REF_PERSON' | translate"></app-input>
</div>
<!-- User Type Selector -->
<app-toggle-selector
[options]="userTypeOptions"
[selectedValue]="checkoutForm.get('customerType')?.value"
(selectionChange)="setCustomerType($event)">
</app-toggle-selector>
<app-input formControlName="addressLine1" [label]="'CHECKOUT.ADDRESS_1' | translate" [required]="true"></app-input>
<app-input formControlName="addressLine2" [label]="'CHECKOUT.ADDRESS_2' | translate"></app-input>

View File

@@ -65,6 +65,11 @@
}
/* User Type Selector CSS has been extracted to app-toggle-selector component */
app-toggle-selector.user-type-selector-compact {
display: block;
width: 100%;
max-width: 400px;
}
.company-fields {
display: flex;