diff --git a/frontend/src/app/features/calculator/components/upload-form/upload-form.component.ts b/frontend/src/app/features/calculator/components/upload-form/upload-form.component.ts index aa1a2f2..ed01dd0 100644 --- a/frontend/src/app/features/calculator/components/upload-form/upload-form.component.ts +++ b/frontend/src/app/features/calculator/components/upload-form/upload-form.component.ts @@ -1,4 +1,4 @@ -import { Component, input, output, signal, effect, OnInit, inject } from '@angular/core'; +import { Component, input, output, signal, OnInit, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ReactiveFormsModule, FormBuilder, FormGroup, Validators } from '@angular/forms'; import { TranslateModule } from '@ngx-translate/core'; @@ -51,6 +51,7 @@ export class UploadFormComponent implements OnInit { // Store full material options to lookup variants/colors if needed later private fullMaterialOptions: MaterialOption[] = []; + private isPatchingSettings = false; // Computed variants for valid material currentMaterialVariants = signal([]); @@ -121,6 +122,25 @@ export class UploadFormComponent implements OnInit { this.form.get('material')?.valueChanges.subscribe(() => { this.updateVariants(); }); + + this.form.get('quality')?.valueChanges.subscribe((quality) => { + if (this.mode() !== 'easy' || this.isPatchingSettings) return; + this.applyAdvancedPresetFromQuality(quality); + }); + } + + private applyAdvancedPresetFromQuality(quality: string | null | undefined) { + const normalized = (quality || 'standard').toLowerCase(); + + const presets: Record = { + standard: { nozzleDiameter: 0.4, layerHeight: 0.2, infillDensity: 15, infillPattern: 'grid' }, + extra_fine: { nozzleDiameter: 0.4, layerHeight: 0.12, infillDensity: 20, infillPattern: 'grid' }, + high: { nozzleDiameter: 0.4, layerHeight: 0.12, infillDensity: 20, infillPattern: 'grid' }, // Legacy alias + draft: { nozzleDiameter: 0.4, layerHeight: 0.24, infillDensity: 12, infillPattern: 'grid' } + }; + + const preset = presets[normalized] || presets['standard']; + this.form.patchValue(preset, { emitEvent: false }); } ngOnInit() { @@ -318,8 +338,8 @@ export class UploadFormComponent implements OnInit { // Let's try to reverse map or defaults. if (settings.layerHeightMm) { - if (settings.layerHeightMm >= 0.28) patch.quality = 'draft'; - else if (settings.layerHeightMm <= 0.12) patch.quality = 'high'; + if (settings.layerHeightMm >= 0.24) patch.quality = 'draft'; + else if (settings.layerHeightMm <= 0.12) patch.quality = 'extra_fine'; else patch.quality = 'standard'; patch.layerHeight = settings.layerHeightMm; @@ -331,7 +351,9 @@ export class UploadFormComponent implements OnInit { if (settings.supportsEnabled !== undefined) patch.supportEnabled = settings.supportsEnabled; if (settings.notes) patch.notes = settings.notes; - this.form.patchValue(patch); + this.isPatchingSettings = true; + this.form.patchValue(patch, { emitEvent: false }); + this.isPatchingSettings = false; } onSubmit() { diff --git a/frontend/src/app/features/calculator/services/quote-estimator.service.ts b/frontend/src/app/features/calculator/services/quote-estimator.service.ts index f2f7a9c..caeeaeb 100644 --- a/frontend/src/app/features/calculator/services/quote-estimator.service.ts +++ b/frontend/src/app/features/calculator/services/quote-estimator.service.ts @@ -109,6 +109,45 @@ export interface SimpleOption { }) export class QuoteEstimatorService { private http = inject(HttpClient); + + private buildEasyModePreset(quality: string | undefined): { + quality: string; + layerHeight: number; + infillDensity: number; + infillPattern: string; + nozzleDiameter: number; + } { + const normalized = (quality || 'standard').toLowerCase(); + + // Legacy alias support. + if (normalized === 'high' || normalized === 'extra_fine') { + return { + quality: 'extra_fine', + layerHeight: 0.12, + infillDensity: 20, + infillPattern: 'grid', + nozzleDiameter: 0.4 + }; + } + + if (normalized === 'draft') { + return { + quality: 'extra_fine', + layerHeight: 0.24, + infillDensity: 12, + infillPattern: 'grid', + nozzleDiameter: 0.4 + }; + } + + return { + quality: 'standard', + layerHeight: 0.2, + infillDensity: 15, + infillPattern: 'grid', + nozzleDiameter: 0.4 + }; + } getOptions(): Observable { console.log('QuoteEstimatorService: Requesting options...'); @@ -223,20 +262,24 @@ export class QuoteEstimatorService { request.items.forEach((item, index) => { const formData = new FormData(); formData.append('file', item.file); + + const easyPreset = request.mode === 'easy' + ? this.buildEasyModePreset(request.quality) + : null; const settings = { - complexityMode: request.mode.toUpperCase(), + complexityMode: request.mode === 'easy' ? 'ADVANCED' : request.mode.toUpperCase(), material: request.material, - quality: request.quality, + 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: request.mode === 'advanced' ? request.layerHeight : null, - infillDensity: request.mode === 'advanced' ? request.infillDensity : null, - infillPattern: request.mode === 'advanced' ? request.infillPattern : null, - nozzleDiameter: request.mode === 'advanced' ? request.nozzleDiameter : null + layerHeight: easyPreset ? easyPreset.layerHeight : request.layerHeight, + infillDensity: easyPreset ? easyPreset.infillDensity : request.infillDensity, + infillPattern: easyPreset ? easyPreset.infillPattern : request.infillPattern, + nozzleDiameter: easyPreset ? easyPreset.nozzleDiameter : request.nozzleDiameter }; const settingsBlob = new Blob([JSON.stringify(settings)], { type: 'application/json' });