fix(back-end): file error handling
All checks were successful
Build, Test and Deploy / test-backend (push) Successful in 34s
Build, Test and Deploy / build-and-push (push) Successful in 22s
Build, Test and Deploy / deploy (push) Successful in 7s

This commit is contained in:
2026-02-16 14:36:26 +01:00
parent 304ed942b8
commit 9feceb9b3c
5 changed files with 48 additions and 10 deletions

View File

@@ -21,16 +21,6 @@ jobs:
java-version: '21'
distribution: 'temurin'
- name: Cache Gradle
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('backend/gradle/wrapper/gradle-wrapper.properties', 'backend/**/*.gradle*', 'backend/gradle.properties') }}
restore-keys: |
gradle-${{ runner.os }}-
- name: Run Tests with Gradle
run: |
cd backend

View File

@@ -37,6 +37,7 @@
[loading]="loading()"
[uploadProgress]="uploadProgress()"
(submitRequest)="onCalculate($event)"
(itemRemoved)="onItemRemoved($event)"
></app-upload-form>
</app-card>
</div>

View File

@@ -224,6 +224,43 @@ export class CalculatorPageComponent implements OnInit {
}
}
onItemRemoved(event: {index: number, id?: string}) {
// 1. Update local result if exists to keep UI in sync
const currentRes = this.result();
if (currentRes) {
const updatedItems = [...currentRes.items];
updatedItems.splice(event.index, 1);
// Recalculate totals locally for immediate feedback
let totalTime = 0;
let totalWeight = 0;
let itemsPrice = 0;
updatedItems.forEach(i => {
totalTime += i.unitTime * i.quantity;
totalWeight += i.unitWeight * i.quantity;
itemsPrice += i.unitPrice * i.quantity;
});
this.result.set({
...currentRes,
items: updatedItems,
totalPrice: Math.round((itemsPrice + currentRes.setupCost) * 100) / 100,
totalTimeHours: Math.floor(totalTime / 3600),
totalTimeMinutes: Math.ceil((totalTime % 3600) / 60),
totalWeight: Math.ceil(totalWeight)
});
}
// 2. Delete from backend if ID exists
if (event.id && currentRes?.sessionId) {
this.estimator.deleteLineItem(currentRes.sessionId, event.id).subscribe({
next: () => console.log('Line item deleted from backend'),
error: (err) => console.error('Failed to delete line item', err)
});
}
}
onSubmitOrder(orderData: any) {
console.log('Order Submitted:', orderData);
this.orderSuccess.set(true);

View File

@@ -30,6 +30,7 @@ export class UploadFormComponent implements OnInit {
loading = input<boolean>(false);
uploadProgress = input<number>(0);
submitRequest = output<QuoteRequest>();
itemRemoved = output<{index: number, id?: string}>();
private estimator = inject(QuoteEstimatorService);
private fb = inject(FormBuilder);
@@ -252,6 +253,7 @@ export class UploadFormComponent implements OnInit {
}
removeItem(index: number) {
const itemToRemove = this.items()[index];
this.items.update(current => {
const updated = [...current];
const removed = updated.splice(index, 1)[0];
@@ -260,6 +262,7 @@ export class UploadFormComponent implements OnInit {
}
return updated;
});
this.itemRemoved.emit({ index, id: itemToRemove.id });
}
setFiles(files: File[], colors?: string[]) {

View File

@@ -139,6 +139,13 @@ export class QuoteEstimatorService {
return this.http.patch(`${environment.apiUrl}/api/quote-sessions/line-items/${lineItemId}`, changes, { headers });
}
deleteLineItem(sessionId: string, lineItemId: string): Observable<any> {
const headers: any = {};
// @ts-ignore
if (environment.basicAuth) headers['Authorization'] = 'Basic ' + btoa(environment.basicAuth);
return this.http.delete(`${environment.apiUrl}/api/quote-sessions/${sessionId}/line-items/${lineItemId}`, { headers });
}
createOrder(sessionId: string, orderDetails: any): Observable<any> {
const headers: any = {};
// @ts-ignore