diff --git a/src/app/carnet/add/add-carnet.component.html b/src/app/carnet/add/add-carnet.component.html
index 2e6da70..431e46c 100644
--- a/src/app/carnet/add/add-carnet.component.html
+++ b/src/app/carnet/add/add-carnet.component.html
@@ -41,8 +41,7 @@
Shipping & Payment
+ [applicationName]="applicationName" [enableSubmitButton]="allSectionsCompleted">
diff --git a/src/app/carnet/add/add-carnet.component.ts b/src/app/carnet/add/add-carnet.component.ts
index c092d38..85277e5 100644
--- a/src/app/carnet/add/add-carnet.component.ts
+++ b/src/app/carnet/add/add-carnet.component.ts
@@ -1,4 +1,4 @@
-import { Component, inject } from '@angular/core';
+import { Component, inject, ViewChild } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { AngularMaterialModule } from '../../shared/module/angular-material.module';
import { CommonModule } from '@angular/common';
@@ -27,7 +27,6 @@ export class AddCarnetComponent {
headerid: number = 0;
applicationName: string = '';
userPreferences: UserPreferences;
- refreshShippingData: boolean = false;
allSectionsCompleted: boolean = false;
// Track completion of each step
@@ -39,6 +38,9 @@ export class AddCarnetComponent {
shipping: false
};
+ @ViewChild(ShippingComponent, { static: false })
+ private shippingComponent!: ShippingComponent;
+
constructor(userPrefenceService: UserPreferencesService) {
this.userPreferences = userPrefenceService.getPreferences();
}
@@ -60,7 +62,9 @@ export class AddCarnetComponent {
}
onHolderSelectionUpdated(updated: boolean): void {
- this.refreshShippingData = updated;
+ if (updated) {
+ this.shippingComponent?.refreshShippingData();
+ }
}
onGoodsSectionSaved(completed: boolean): void {
diff --git a/src/app/carnet/edit/edit-carnet.component.html b/src/app/carnet/edit/edit-carnet.component.html
index 10901ec..d9aabc0 100644
--- a/src/app/carnet/edit/edit-carnet.component.html
+++ b/src/app/carnet/edit/edit-carnet.component.html
@@ -41,8 +41,7 @@
Shipping & Payment
+ [applicationName]="applicationName" [enableSubmitButton]="allSectionsCompleted">
diff --git a/src/app/carnet/edit/edit-carnet.component.ts b/src/app/carnet/edit/edit-carnet.component.ts
index 6cd0bf4..5cb1750 100644
--- a/src/app/carnet/edit/edit-carnet.component.ts
+++ b/src/app/carnet/edit/edit-carnet.component.ts
@@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common';
-import { Component, inject } from '@angular/core';
+import { Component, inject, ViewChild } from '@angular/core';
import { AngularMaterialModule } from '../../shared/module/angular-material.module';
import { ReactiveFormsModule } from '@angular/forms';
import { ApplicationComponent } from '../application/application.component';
@@ -27,9 +27,11 @@ export class EditCarnetComponent {
headerid: number = 0;
userPreferences: UserPreferences;
applicationName: string = '';
- refreshShippingData: boolean = false;
allSectionsCompleted: boolean = false;
+ @ViewChild(ShippingComponent, { static: false })
+ private shippingComponent!: ShippingComponent;
+
// Track completion of each step
stepsCompleted = {
applicationDetail: true,
@@ -75,7 +77,10 @@ export class EditCarnetComponent {
}
onHolderSelectionUpdated(updated: boolean): void {
- this.refreshShippingData = updated;
+ if (updated) {
+ this.shippingComponent?.refreshShippingData();
+ }
+
this.isAllSectionsCompleted();
}
diff --git a/src/app/carnet/goods/goods.component.html b/src/app/carnet/goods/goods.component.html
index 9dc83db..efe4539 100644
--- a/src/app/carnet/goods/goods.component.html
+++ b/src/app/carnet/goods/goods.component.html
@@ -219,7 +219,8 @@
+
+
+
+
diff --git a/src/app/carnet/shipping/shipping.component.ts b/src/app/carnet/shipping/shipping.component.ts
index 488950b..65d9815 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, SimpleChanges } from '@angular/core';
+import { Component, EventEmitter, inject, Input, Output } 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';
@@ -34,7 +34,6 @@ import { FormOfSecurity } from '../../core/models/formofsecurity';
export class ShippingComponent {
@Input() headerid: number = 0;
@Input() isEditMode = false;
- @Input() refreshShippingData = false;
@Input() enableSubmitButton = false;
@Input() applicationName: string = '';
@@ -53,6 +52,7 @@ export class ShippingComponent {
shippingForm: FormGroup;
isLoading = false;
+ changeInProgress = false;
showAddressForm = false;
showContactForm = false;
deliveryEstimate: string = '';
@@ -91,7 +91,7 @@ export class ShippingComponent {
address2: [''],
city: [''],
state: [''],
- country: [''],
+ country: ['US'],
zip: [''],
}),
contact: this.fb.group({
@@ -142,7 +142,7 @@ export class ShippingComponent {
return;
}
- this.isLoading = true;
+ this.changeInProgress = true;
const shippingData: Shipping = this.shippingForm.value;
if (shippingData.shipTo !== '3RDPARTY') {
@@ -150,16 +150,16 @@ export class ShippingComponent {
shippingData.contact = shippingData.shipTo === 'PREPARER' ? this.preparerContact ?? undefined : this.holderContact ?? undefined;
}
- this.shippingService.saveShippingDetails(this.headerid, shippingData).subscribe({
+ this.shippingService.saveShippingDetails(this.headerid, shippingData).pipe(finalize(() => {
+ this.changeInProgress = false;
+ })).subscribe({
next: () => {
this.notificationService.showSuccess('Shipping & payments information saved successfully');
this.completed.emit(true);
- this.isLoading = false;
},
error: (error) => {
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to save shipping and payment information');
this.notificationService.showError(errorMessage);
- this.isLoading = false;
}
});
}
@@ -188,8 +188,8 @@ export class ShippingComponent {
this.shippingForm.get('address.zip')?.updateValueAndValidity();
}
- ngOnChanges(changes: SimpleChanges) {
- if (changes['refreshShippingData'] && this.headerid > 0) {
+ public refreshShippingData(): void {
+ if (this.headerid > 0) {
this.loadShippingData();
}
}
@@ -209,7 +209,8 @@ export class ShippingComponent {
cancelEditAddressForm(): void {
this.showAddressForm = false;
- this.shippingForm.get('address')?.reset();
+ this.shippingForm.get('address')?.reset({ country: 'US' });
+ this.loadStates('US');
}
onShipToChange(event: any): void {
@@ -221,14 +222,15 @@ export class ShippingComponent {
if (shipTo === '3RDPARTY') {
this.shippingForm.get('contact')?.reset();
- this.shippingForm.get('address')?.reset();
+ this.shippingForm.get('address')?.reset({ country: 'US' });
+ this.loadStates('US');
this.showAddressForm = true;
this.showContactForm = true;
}
}
loadCountries(): void {
- this.commonService.getCountries(0)
+ this.commonService.getCountries()
.pipe(takeUntil(this.destroy$))
.subscribe({
next: (countries) => {
@@ -236,13 +238,12 @@ export class ShippingComponent {
},
error: (error) => {
console.error('Failed to load countries', error);
- this.isLoading = false;
}
});
}
loadDeliveryTypes(): void {
- this.commonService.getDeliveryTypes(0)
+ this.commonService.getDeliveryTypes()
.pipe(takeUntil(this.destroy$))
.subscribe({
next: (deliveryTypes) => {
@@ -250,13 +251,12 @@ export class ShippingComponent {
},
error: (error) => {
console.error('Failed to load delivery types', error);
- this.isLoading = false;
}
});
}
loadDeliveryMethods(): void {
- this.commonService.getDeliveryMethods(0)
+ this.commonService.getDeliveryMethods()
.pipe(takeUntil(this.destroy$))
.subscribe({
next: (deliveryMethods) => {
@@ -264,13 +264,12 @@ export class ShippingComponent {
},
error: (error) => {
console.error('Failed to load delivery methods', error);
- this.isLoading = false;
}
});
}
loadPaymentTypes(): void {
- this.commonService.getPaymentTypes(0)
+ this.commonService.getPaymentTypes()
.pipe(takeUntil(this.destroy$))
.subscribe({
next: (paymentTypes) => {
@@ -278,7 +277,6 @@ export class ShippingComponent {
},
error: (error) => {
console.error('Failed to load payment types', error);
- this.isLoading = false;
}
});
}
@@ -286,29 +284,29 @@ export class ShippingComponent {
loadStates(country: string): void {
this.isLoading = true;
country = this.countriesHasStates.includes(country) ? country : 'FN';
- this.commonService.getStates(country, 0)
- .pipe(takeUntil(this.destroy$))
- .subscribe({
- next: (states) => {
- this.states = states;
- const stateControl = this.shippingForm.get('contact.state');
- if (this.countriesHasStates.includes(country)) {
- stateControl?.enable();
- } else {
- stateControl?.disable();
- stateControl?.setValue('FN');
+ this.commonService.getStates(country)
+ .pipe(takeUntil(this.destroy$),
+ finalize(() => {
+ this.isLoading = false;
+ })).subscribe({
+ next: (states) => {
+ this.states = states;
+ const stateControl = this.shippingForm.get('contact.state');
+ if (this.countriesHasStates.includes(country)) {
+ stateControl?.enable();
+ } else {
+ stateControl?.disable();
+ stateControl?.setValue('FN');
+ }
+ },
+ error: (error) => {
+ console.error('Failed to load states', error);
}
- this.isLoading = false;
- },
- error: (error) => {
- console.error('Failed to load states', error);
- this.isLoading = false;
- }
- });
+ });
}
loadFormOfSecurities(): void {
- this.commonService.getFormOfSecurities(0)
+ this.commonService.getFormOfSecurities()
.pipe(takeUntil(this.destroy$))
.subscribe({
next: (fos) => {
@@ -483,11 +481,11 @@ export class ShippingComponent {
} else if (key === 'title') {
contactGroup.get(key)?.setValidators([Validators.required, Validators.maxLength(100)]);
} else if (key === 'phone') {
- contactGroup.get(key)?.setValidators([Validators.required, Validators.pattern(/^[0-9]{10,15}$/)]);
+ contactGroup.get(key)?.setValidators([Validators.required, Validators.pattern(/^[0-9\-\(\)]{10,15}$/)]);
} else if (key === 'mobile') {
- contactGroup.get(key)?.setValidators([Validators.required, Validators.pattern(/^[0-9]{10,15}$/)]);
+ contactGroup.get(key)?.setValidators([Validators.required, Validators.pattern(/^[0-9\-\(\)]{10,15}$/)]);
} else if (key === 'fax') {
- contactGroup.get(key)?.setValidators([Validators.pattern(/^[0-9]{10,15}$/)]);
+ contactGroup.get(key)?.setValidators([Validators.pattern(/^[0-9\-\(\)]{10,15}$/)]);
} else if (key === 'email') {
contactGroup.get(key)?.setValidators([Validators.required, Validators.email, Validators.maxLength(100)]);
}
diff --git a/src/app/carnet/terms-conditions/terms-conditions.component.html b/src/app/carnet/terms-conditions/terms-conditions.component.html
index 9bc63ac..e18b6ba 100644
--- a/src/app/carnet/terms-conditions/terms-conditions.component.html
+++ b/src/app/carnet/terms-conditions/terms-conditions.component.html
@@ -102,7 +102,8 @@
-
diff --git a/src/app/carnet/travel-plan/travel-plan.component.ts b/src/app/carnet/travel-plan/travel-plan.component.ts
index 66b60d3..bace1b3 100644
--- a/src/app/carnet/travel-plan/travel-plan.component.ts
+++ b/src/app/carnet/travel-plan/travel-plan.component.ts
@@ -1,6 +1,6 @@
import { Component, EventEmitter, inject, Input, Output, SimpleChanges } from '@angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
-import { forkJoin } from 'rxjs';
+import { finalize, forkJoin } from 'rxjs';
import { TravelPlanService } from '../../core/services/carnet/travel-plan.service';
import { ApiErrorHandlerService } from '../../core/services/common/api-error-handler.service';
import { NotificationService } from '../../core/services/common/notification.service';
@@ -30,6 +30,7 @@ export class TravelPlanComponent {
travelForm: FormGroup;
isLoading = false;
+ changeInProgress = false;
visitsCount = 1;
transitsCount = 1;
@@ -253,17 +254,17 @@ export class TravelPlanComponent {
forkJoin({
countries: this.travelPlanService.getCountriesAndMessages(),
travelPlanData: this.travelPlanService.getTravelPlan(this.headerid)
- }).subscribe({
+ }).pipe(finalize(() => {
+ this.isLoading = false;
+ })).subscribe({
next: (results) => {
this.countries = results.countries as Country[];
this.patchTravelPlanData(results.travelPlanData);
- this.isLoading = false;
},
error: (error) => {
console.error('Error loading travel plan data', error);
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load travel plan data');
this.notificationService.showError(errorMessage);
- this.isLoading = false;
}
});
}
@@ -295,18 +296,19 @@ export class TravelPlanComponent {
transits: this.selectedTransitCountries
};
- this.isLoading = true;
- this.travelPlanService.saveTravelPlan(this.headerid, travelPlan).subscribe({
+ this.changeInProgress = true;
+
+ this.travelPlanService.saveTravelPlan(this.headerid, travelPlan).pipe(finalize(() => {
+ this.changeInProgress = false;
+ })).subscribe({
next: () => {
this.notificationService.showSuccess('Travel plan saved successfully');
this.completed.emit(true);
- this.isLoading = false;
},
error: (error) => {
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to save travel plan');
this.notificationService.showError(errorMessage);
console.error('Error saving travel plan data : ', error);
- this.isLoading = false;
}
});
}
diff --git a/src/app/common/footer/footer.component.html b/src/app/common/footer/footer.component.html
index 0a8b626..01d4752 100644
--- a/src/app/common/footer/footer.component.html
+++ b/src/app/common/footer/footer.component.html
@@ -7,7 +7,7 @@
- © {{ currentYear }} USCIB Carnet Portal. All rights reserved.
+ © {{ currentYear }} {{currentServiceProviderName}}. All rights reserved.
\ No newline at end of file
diff --git a/src/app/common/footer/footer.component.ts b/src/app/common/footer/footer.component.ts
index 2f94b31..ba744bb 100644
--- a/src/app/common/footer/footer.component.ts
+++ b/src/app/common/footer/footer.component.ts
@@ -1,6 +1,8 @@
-import { Component, Input } from '@angular/core';
+import { Component, effect, inject, Input } from '@angular/core';
import { AngularMaterialModule } from '../../shared/module/angular-material.module';
import { CommonModule } from '@angular/common';
+import { User } from '../../core/models/user';
+import { UserService } from '../../core/services/common/user.service';
@Component({
selector: 'app-footer',
@@ -10,5 +12,20 @@ import { CommonModule } from '@angular/common';
})
export class FooterComponent {
currentYear = new Date().getFullYear();
+ currentServiceProviderName: string = '';
+ userDetails: User | null = {};
+
@Input() isUserLoggedIn = false;
+
+ private userService = inject(UserService);
+
+ constructor(
+ ) {
+ effect(() => {
+ this.userDetails = this.userService.userDetailsSignal();
+ if (this.userDetails?.userDetails) {
+ this.currentServiceProviderName = this.userDetails.userDetails.serviceProviderName || '';
+ }
+ });
+ }
}
\ No newline at end of file
diff --git a/src/app/common/secured-header/secured-header.component.html b/src/app/common/secured-header/secured-header.component.html
index b9c6d42..354784e 100644
--- a/src/app/common/secured-header/secured-header.component.html
+++ b/src/app/common/secured-header/secured-header.component.html
@@ -6,18 +6,7 @@
diff --git a/src/app/holder/basic-details/basic-details.component.ts b/src/app/holder/basic-details/basic-details.component.ts
index 9400cad..3af8d21 100644
--- a/src/app/holder/basic-details/basic-details.component.ts
+++ b/src/app/holder/basic-details/basic-details.component.ts
@@ -8,7 +8,7 @@ import { NotificationService } from '../../core/services/common/notification.ser
import { ApiErrorHandlerService } from '../../core/services/common/api-error-handler.service';
import { ZipCodeValidator } from '../../shared/validators/zipcode-validator';
import { CommonService } from '../../core/services/common/common.service';
-import { Subject, takeUntil } from 'rxjs';
+import { finalize, Subject, takeUntil } from 'rxjs';
import { Country } from '../../core/models/country';
import { BasicDetailService } from '../../core/services/holder/basic-detail.service';
import { BasicDetail } from '../../core/models/holder/basic-detail';
@@ -27,7 +27,6 @@ export class BasicDetailComponent implements OnInit, OnDestroy {
@Input() holderid: number = 0;
@Output() holderIdCreated = new EventEmitter