diff --git a/src/app/carnet/add/add-carnet.component.html b/src/app/carnet/add/add-carnet.component.html index 431e46c..504b353 100644 --- a/src/app/carnet/add/add-carnet.component.html +++ b/src/app/carnet/add/add-carnet.component.html @@ -41,7 +41,7 @@ Shipping & Payment + [applicationName]="applicationName" [missingSectionMessage]="missingSectionMessage"> diff --git a/src/app/carnet/add/add-carnet.component.ts b/src/app/carnet/add/add-carnet.component.ts index 85277e5..21c56db 100644 --- a/src/app/carnet/add/add-carnet.component.ts +++ b/src/app/carnet/add/add-carnet.component.ts @@ -27,7 +27,7 @@ export class AddCarnetComponent { headerid: number = 0; applicationName: string = ''; userPreferences: UserPreferences; - allSectionsCompleted: boolean = false; + missingSectionMessage: string = ''; // Track completion of each step stepsCompleted = { @@ -38,6 +38,9 @@ export class AddCarnetComponent { shipping: false }; + @ViewChild(HolderComponent, { static: false }) + private holderComponent!: HolderComponent; + @ViewChild(ShippingComponent, { static: false }) private shippingComponent!: ShippingComponent; @@ -54,6 +57,8 @@ export class AddCarnetComponent { this.applicationName = data.applicationName; this.stepsCompleted.applicationDetail = true; this.isLinear = false; // Disable linear mode after application detail is created + + this.holderComponent.refreshHolder(); } onHolderSelectionSaved(completed: boolean): void { @@ -83,8 +88,38 @@ export class AddCarnetComponent { } isAllSectionsCompleted(): void { - this.allSectionsCompleted = this.stepsCompleted.applicationDetail + let allSectionsCompleted = this.stepsCompleted.applicationDetail && this.stepsCompleted.holderSelection && this.stepsCompleted.goodsSection && this.stepsCompleted.shipping && this.stepsCompleted.travelPlan; + + if (allSectionsCompleted) { + this.missingSectionMessage = ''; + } + else { + let message = 'Missing details in: '; + + if (!this.stepsCompleted.applicationDetail) { + message += 'Application Name, '; + } + + if (!this.stepsCompleted.holderSelection) { + message += 'Holder Selection, '; + } + + if (!this.stepsCompleted.goodsSection) { + message += 'Goods Section, '; + } + + if (!this.stepsCompleted.travelPlan) { + message += 'Travel Plan, '; + } + + if (!this.stepsCompleted.shipping) { + message += 'Shipping & Payment, '; + } + + // Remove trailing comma and space + this.missingSectionMessage = message.replace(/, $/, ''); + } } } diff --git a/src/app/carnet/edit/edit-carnet.component.html b/src/app/carnet/edit/edit-carnet.component.html index 06f8b53..d09e89c 100644 --- a/src/app/carnet/edit/edit-carnet.component.html +++ b/src/app/carnet/edit/edit-carnet.component.html @@ -51,7 +51,7 @@ Shipping & Payment + [missingSectionMessage]="missingSectionMessage"> diff --git a/src/app/carnet/edit/edit-carnet.component.ts b/src/app/carnet/edit/edit-carnet.component.ts index c25822a..b1fc1d0 100644 --- a/src/app/carnet/edit/edit-carnet.component.ts +++ b/src/app/carnet/edit/edit-carnet.component.ts @@ -28,7 +28,8 @@ export class EditCarnetComponent { headerid: number = 0; userPreferences: UserPreferences; applicationName: string = ''; - allSectionsCompleted: boolean = false; + missingSectionMessage: string = ''; + @ViewChild(ShippingComponent, { static: false }) private shippingComponent!: ShippingComponent; @@ -125,9 +126,43 @@ export class EditCarnetComponent { } isAllSectionsCompleted() { - this.allSectionsCompleted = this.stepsCompleted.applicationDetail + let allSectionsCompleted = this.stepsCompleted.applicationDetail && this.stepsCompleted.holderSelection && this.stepsCompleted.goodsSection && this.stepsCompleted.shipping && this.stepsCompleted.travelPlan && (this.applicationType !== 'extend' || this.stepsCompleted.extension); + + if (allSectionsCompleted) { + this.missingSectionMessage = ''; + } + else { + let message = 'Missing details in: '; + + if(this.applicationType === 'extend' && !this.stepsCompleted.extension) { + message += 'Extension Application, '; + } + + if (!this.stepsCompleted.applicationDetail) { + message += 'Application Name, '; + } + + if (!this.stepsCompleted.holderSelection) { + message += 'Holder Selection, '; + } + + if (!this.stepsCompleted.goodsSection) { + message += 'Goods Section, '; + } + + if (!this.stepsCompleted.travelPlan) { + message += 'Travel Plan, '; + } + + if (!this.stepsCompleted.shipping) { + message += 'Shipping & Payment, '; + } + + // Remove trailing comma and space + this.missingSectionMessage = message.replace(/, $/, ''); + } } } diff --git a/src/app/carnet/holder/holder.component.ts b/src/app/carnet/holder/holder.component.ts index ff852d7..edb4326 100644 --- a/src/app/carnet/holder/holder.component.ts +++ b/src/app/carnet/holder/holder.component.ts @@ -21,7 +21,7 @@ export class HolderComponent { @Output() completed = new EventEmitter(); @Output() updated = new EventEmitter(); - selectedHolderId: number = 0; + selectedHolderId: number | undefined = 0; private holdersService = inject(HolderService); private notificationService = inject(NotificationService); @@ -45,6 +45,10 @@ export class HolderComponent { } } + public refreshHolder(): void { + this.selectedHolderId = undefined; + } + onHolderSelectionSaved(completed: boolean): void { this.completed.emit(completed); this.updated.emit(true); // to update dependent data diff --git a/src/app/carnet/shipping/shipping.component.html b/src/app/carnet/shipping/shipping.component.html index 082d440..30ff7e1 100644 --- a/src/app/carnet/shipping/shipping.component.html +++ b/src/app/carnet/shipping/shipping.component.html @@ -343,29 +343,36 @@
- +
+ error + {{ missingSectionMessage }} +
- +
+ - + - + - + + + +
\ No newline at end of file diff --git a/src/app/carnet/shipping/shipping.component.scss b/src/app/carnet/shipping/shipping.component.scss index 543ca56..8c835e3 100644 --- a/src/app/carnet/shipping/shipping.component.scss +++ b/src/app/carnet/shipping/shipping.component.scss @@ -63,9 +63,32 @@ .form-actions { display: flex; - justify-content: flex-end; + justify-content: space-between; + align-items: center; gap: 16px; margin-top: 0.9rem; + + .error-message { + display: flex; + align-items: center; + color: var(--mat-form-field-error-text-color, var(--mat-sys-error)); + -webkit-font-smoothing: antialiased; + font-family: var(--mat-form-field-subscript-text-font, var(--mat-sys-body-small-font)); + line-height: var(--mat-form-field-subscript-text-line-height, var(--mat-sys-body-small-line-height)); + font-size: var(--mat-form-field-subscript-text-size, var(--mat-sys-body-small-size)); + letter-spacing: var(--mat-form-field-subscript-text-tracking, var(--mat-sys-body-small-tracking)); + font-weight: var(--mat-form-field-subscript-text-weight, var(--mat-sys-body-small-weight)); + + mat-icon { + margin-right: 4px; + } + } + + .action-buttons { + display: flex; + align-items: center; + gap: 16px; + } } .presaved-address { diff --git a/src/app/carnet/shipping/shipping.component.ts b/src/app/carnet/shipping/shipping.component.ts index 60f6297..c7ef7c6 100644 --- a/src/app/carnet/shipping/shipping.component.ts +++ b/src/app/carnet/shipping/shipping.component.ts @@ -1,5 +1,5 @@ import { CommonModule } from '@angular/common'; -import { Component, EventEmitter, inject, Input, Output } from '@angular/core'; +import { Component, EventEmitter, inject, Input, Output, SimpleChanges } from '@angular/core'; import { ReactiveFormsModule, FormBuilder, FormGroup, Validators } from '@angular/forms'; import { NotificationService } from '../../core/services/common/notification.service'; import { AngularMaterialModule } from '../../shared/module/angular-material.module'; @@ -38,7 +38,7 @@ export class ShippingComponent { @Input() headerid: number = 0; @Input() isEditMode = false; @Input() isViewMode = false; - @Input() enableSubmitButton = false; + @Input() missingSectionMessage = ''; @Input() applicationName: string = ''; @Input() applicationType: 'new' | 'edit' | 'additional' | 'duplicate' | 'extend' | null = 'edit'; @@ -62,6 +62,7 @@ export class ShippingComponent { showAddressForm = false; showContactForm = false; deliveryEstimate: string = ''; + enableSubmitButton: boolean = false; needsInsurance = true; holderid: number = 0; holder: Holder | undefined | null = null; @@ -142,6 +143,12 @@ export class ShippingComponent { } } + ngOnChanges(changes: SimpleChanges): void { + if (changes['missingSectionMessage']) { + this.enableSubmitButton = this.missingSectionMessage === ''; + } + } + ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); @@ -426,7 +433,7 @@ export class ShippingComponent { ).subscribe({ next: (results) => { - if (!results && !this.shippingFromDB) { // do nothing if empty + if (!results || !this.shippingFromDB) { // do nothing if empty return; } diff --git a/src/app/holder/search/search-holder.component.ts b/src/app/holder/search/search-holder.component.ts index 585e366..993f54c 100644 --- a/src/app/holder/search/search-holder.component.ts +++ b/src/app/holder/search/search-holder.component.ts @@ -80,12 +80,15 @@ export class SearchHolderComponent { }); } - ngOnChanges(changes: SimpleChanges): void { if (changes['selectedHolderId']) { if (this.selectedHolderId) { this.showSelectedHolder(this.selectedHolderId); } + + if (this.selectedHolderId === undefined) { + this.autoSelectHolder(); + } } if (changes['isViewMode'] && this.isViewMode) { @@ -93,6 +96,30 @@ export class SearchHolderComponent { } } + // If only one holder is returned, auto select it + autoSelectHolder(): void { + this.isLoading = true; + const filterData: HolderFilter = {}; + + this.holderService.getHolders(filterData).pipe(finalize(() => { + this.isLoading = false; + })).subscribe({ + next: (holders: BasicDetail[]) => { + if (holders && holders.length === 1) { + this.selectedHolderId = holders[0].holderid!; + this.saveHolderSelection(); + this.showSelectedHolder(this.selectedHolderId); + + } + }, + error: (error: any) => { + let errorMessage = this.errorHandler.handleApiError(error, 'Failed to get holders'); + this.notificationService.showError(errorMessage); + console.error('Error loading holders:', error); + } + }); + } + onSearch(): void { this.searchHolders(); } diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html index ba1bd3d..775d67a 100644 --- a/src/app/home/home.component.html +++ b/src/app/home/home.component.html @@ -12,41 +12,51 @@
Do you need a new carnet? - Yes - No +
+ Yes + No +
Do you need additional sets? - Yes - No +
+ Yes + No +
Did you misplace your carnet? - Yes - No +
+ Yes + No +
- Are you looking for + Are you looking for duplicates? - Yes - No +
+ Yes + No +
Do you need to extend the carnet? - Yes - No +
+ Yes + No +
diff --git a/src/app/home/home.component.scss b/src/app/home/home.component.scss index c4b083e..242f623 100644 --- a/src/app/home/home.component.scss +++ b/src/app/home/home.component.scss @@ -33,7 +33,9 @@ mat-radio-group { display: flex; - gap: 8px; + justify-content: space-between; + align-items: center; + width: 51%; .question { color: var(--mat-sys-on-surface); @@ -44,8 +46,8 @@ font-weight: var(--mat-sys-medium-font-weight); } - mat-radio-button { - margin-top: -5px; + .sub-question { + padding-left: 1.5em; } } } diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts index d95b819..ae0db3c 100644 --- a/src/app/home/home.component.ts +++ b/src/app/home/home.component.ts @@ -438,8 +438,8 @@ export class HomeComponent { next: (applicationData: any) => { this.notificationService.showSuccess('Carnet copied successfully'); let route: string = this.editActionRoute(item); - this.navigateTo([route, data.headerid], { - queryParams: { applicationname: data.applicationName } + this.navigateTo([route, applicationData.HEADERID], { + queryParams: { applicationname: applicationData.APPLICATIONNAME } }); }, error: (error) => {