feedback updates

This commit is contained in:
Cyril Joseph 2026-01-17 16:59:37 -04:00
parent 161246beda
commit ce1b722637
11 changed files with 171 additions and 112 deletions

View File

@ -86,7 +86,7 @@
<!-- Weight Column -->
<ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Weight</th>
<td mat-cell *matCellDef="let item">{{ formatDecimalDisplay(item.weight, 4) }}</td>
<td mat-cell *matCellDef="let item">{{ item.weight | number:'1.2-2' }}</td>
</ng-container>
<!-- Unit of Measure Column -->
@ -240,6 +240,14 @@
</div>
<div *ngIf="!showItemForm" class="form-actions">
<!-- Totals -->
<div class="totals-section">
<div class="total-item" *ngIf="totalGoodsValue > 0">
<span>Total Goods Value:</span>
<span class="total-value">{{totalGoodsValue | currency}}</span>
</div>
</div>
<button mat-raised-button color="primary" (click)="onSubmit()" *ngIf="!isViewMode"
[disabled]="goodsForm.invalid || changeInProgress">
Save

View File

@ -180,5 +180,22 @@
display: flex;
justify-content: flex-end;
margin-top: 0.9rem;
justify-content: space-between;
.totals-section {
display: flex;
gap: 24px;
font-size: 0.875rem;
.total-item {
display: flex;
gap: 8px;
align-items: center;
.total-value {
font-weight: 500;
}
}
}
}
}

View File

@ -59,11 +59,11 @@ export class GoodsComponent {
showItemForm = false;
fileToUpload: File | null = null;
isProcessing = false;
totalGoodsValue: number = 0;
// Data
countries: Country[] = [];
unitsOfMeasures: UnitOfMeasure[] = [];
goodsItems: GoodsItem[] = [];
private destroy$ = new Subject<void>();
@ -136,7 +136,8 @@ export class GoodsComponent {
this.isLoading = false;
})).subscribe({
next: (items: GoodsItem[]) => {
this.dataSource.data = this.goodsItems = items;
this.dataSource.data = items;
this.totalGoodsValue = items.reduce((total, item) => total + Number(item.value || 0), 0);
this.completed.emit((this.goodsForm.valid || this.goodsForm.disabled) && this.dataSource.data.length > 0);
},
error: (error: any) => {
@ -301,7 +302,7 @@ export class GoodsComponent {
dialogRef.afterClosed().subscribe(result => {
if (result) {
this.changeInProgress = true;
this.goodsService.deleteAllGoodsItems(this.headerid, this.goodsItems).pipe(finalize(() => {
this.goodsService.deleteAllGoodsItems(this.headerid).pipe(finalize(() => {
this.changeInProgress = false;
})).subscribe({
next: () => {

View File

@ -16,16 +16,16 @@ import { NotificationService } from '../../core/services/common/notification.ser
<mat-dialog-content>
<p> The following fees apply:</p>
<ul>
<li *ngIf="estimatedFees.basicFee">Basic fee <span> {{estimatedFees.basicFee | currency}} </span></li>
<li *ngIf="estimatedFees.counterFoilFee">Counterfoil Fee <span> {{estimatedFees.counterFoilFee | currency}}
<li *ngIf="estimatedFees.basicFee">Basic fee: <span> {{estimatedFees.basicFee | currency}} </span></li>
<li *ngIf="estimatedFees.counterFoilFee">Counterfoil Fee: <span> {{estimatedFees.counterFoilFee | currency}}
</span></li>
<li *ngIf="estimatedFees.continuationSheetFee">Continuation sheet fee
<li *ngIf="estimatedFees.continuationSheetFee">Continuation sheet fee:
<span> {{estimatedFees.continuationSheetFee | currency}}</span></li>
<li *ngIf="estimatedFees.expeditedFee">Expedited fee <span> {{estimatedFees.expeditedFee | currency}}</span></li>
<li *ngIf="estimatedFees.shippingFee">Shipping fee <span> {{estimatedFees.shippingFee | currency}}</span></li>
<li *ngIf="estimatedFees.bondPremium">{{bondPremiumLabel}} <span> {{estimatedFees.bondPremium | currency}}</span></li>
<li *ngIf="estimatedFees.cargoPremium">Cargo Premium <span> {{estimatedFees.cargoPremium | currency}}</span></li>
<li *ngIf="estimatedFees.ldiPremium">LDI Premium <span> {{estimatedFees.ldiPremium | currency}}</span></li>
<li *ngIf="estimatedFees.expeditedFee">Expedited fee: <span> {{estimatedFees.expeditedFee | currency}}</span></li>
<li *ngIf="estimatedFees.shippingFee">Shipping fee: <span> {{estimatedFees.shippingFee | currency}}</span></li>
<li *ngIf="estimatedFees.bondPremium">{{bondPremiumLabel}}: <span> {{estimatedFees.bondPremium | currency}}</span></li>
<li *ngIf="estimatedFees.cargoPremium">Cargo Premium: <span> {{estimatedFees.cargoPremium | currency}}</span></li>
<li *ngIf="estimatedFees.ldiPremium">LDI Premium: <span> {{estimatedFees.ldiPremium | currency}}</span></li>
</ul>
<hr/>
<ul>
@ -33,8 +33,8 @@ import { NotificationService } from '../../core/services/common/notification.ser
</ul>
<hr/>
<ul>
<li *ngIf="estimatedFees.securityAmount">Security Amount <span>{{estimatedFees.securityAmount | currency}}</span></li>
<li *ngIf="estimatedFees.insuredValue">Insured Value <span>{{estimatedFees.insuredValue | currency}}</span></li>
<li *ngIf="estimatedFees.securityAmount">Security Amount: <span>{{estimatedFees.securityAmount | currency}}</span></li>
<li *ngIf="estimatedFees.insuredValue">Insured Value: <span>{{estimatedFees.insuredValue | currency}}</span></li>
</ul>
</mat-dialog-content>
<mat-dialog-actions>

View File

@ -480,7 +480,6 @@ export class ShippingComponent {
this.onDeliveryMethodChange(this.shippingFromDB.deliveryMethod);
}
this.calculateDeliveryEstimate();
this.shippingForm.markAsUntouched();
this.completed.emit(this.shippingForm.valid);
@ -520,7 +519,6 @@ export class ShippingComponent {
formOfSecurityControl?.enable();
}
this.calculateDeliveryEstimate();
this.updateAddressContactValidation(this.shippingFromDB.shipTo);
if (this.shippingFromDB.shipTo === '3RDPARTY') {

View File

@ -10,36 +10,73 @@
<p>Agreement language will go here</p>
<h3>Fees and Charges</h3>
<p> The following fees apply:</p>
<ul>
<li *ngIf="estimatedFees.basicFee">Basic fee <span> {{estimatedFees.basicFee | currency}} </span></li>
<li *ngIf="estimatedFees.counterFoilFee">Counterfoil Fee <span> {{estimatedFees.counterFoilFee |
currency}}
</span></li>
<li *ngIf="estimatedFees.continuationSheetFee">Continuation sheet fee
<span> {{estimatedFees.continuationSheetFee | currency}}</span>
</li>
<li *ngIf="estimatedFees.expeditedFee">Expedited fee <span> {{estimatedFees.expeditedFee |
currency}}</span></li>
<li *ngIf="estimatedFees.shippingFee">Shipping fee <span> {{estimatedFees.shippingFee |
currency}}</span></li>
<li *ngIf="estimatedFees.bondPremium">{{bondPremiumLabel}} <span> {{estimatedFees.bondPremium |
currency}}</span></li>
<li *ngIf="estimatedFees.cargoPremium">Cargo Premium <span> {{estimatedFees.cargoPremium |
currency}}</span></li>
<li *ngIf="estimatedFees.ldiPremium">LDI Premium <span> {{estimatedFees.ldiPremium | currency}}</span>
</li>
</ul>
<!-- Fee List with Table-like Structure -->
<div class="fee-table">
<div class="fee-row" *ngIf="estimatedFees.basicFee">
<span class="fee-label">Basic fee:</span>
<span class="fee-value">{{ estimatedFees.basicFee | currency }}</span>
</div>
<div class="fee-row" *ngIf="estimatedFees.counterFoilFee">
<span class="fee-label">Counterfoil Fee:</span>
<span class="fee-value">{{ estimatedFees.counterFoilFee | currency }}</span>
</div>
<div class="fee-row" *ngIf="estimatedFees.continuationSheetFee">
<span class="fee-label">Continuation sheet fee:</span>
<span class="fee-value">{{ estimatedFees.continuationSheetFee | currency }}</span>
</div>
<div class="fee-row" *ngIf="estimatedFees.expeditedFee">
<span class="fee-label">Expedited fee:</span>
<span class="fee-value">{{ estimatedFees.expeditedFee | currency }}</span>
</div>
<div class="fee-row" *ngIf="estimatedFees.shippingFee">
<span class="fee-label">Shipping fee:</span>
<span class="fee-value">{{ estimatedFees.shippingFee | currency }}</span>
</div>
<div class="fee-row" *ngIf="estimatedFees.bondPremium">
<span class="fee-label">{{ bondPremiumLabel }}:</span>
<span class="fee-value">{{ estimatedFees.bondPremium | currency }}</span>
</div>
<div class="fee-row" *ngIf="estimatedFees.cargoPremium">
<span class="fee-label">Cargo Premium:</span>
<span class="fee-value">{{ estimatedFees.cargoPremium | currency }}</span>
</div>
<div class="fee-row" *ngIf="estimatedFees.ldiPremium">
<span class="fee-label">LDI Premium:</span>
<span class="fee-value">{{ estimatedFees.ldiPremium | currency }}</span>
</div>
</div>
<hr />
<ul>
<li class="total">Total: <span>{{total | currency}}</span></li>
</ul>
<!-- Total -->
<div class="fee-table">
<div class="fee-row total">
<span class="fee-label">Total:</span>
<span class="fee-value">{{ total | currency }}</span>
</div>
</div>
<hr />
<ul>
<li *ngIf="estimatedFees.securityAmount">Security Amount <span>{{estimatedFees.securityAmount |
currency}}</span></li>
<li *ngIf="estimatedFees.insuredValue">Insured Value <span>{{estimatedFees.insuredValue |
currency}}</span></li>
</ul>
<!-- Security & Insurance -->
<div class="fee-table">
<div class="fee-row" *ngIf="estimatedFees.securityAmount">
<span class="fee-label">Security Amount:</span>
<span class="fee-value">{{ estimatedFees.securityAmount | currency }}</span>
</div>
<div class="fee-row" *ngIf="estimatedFees.insuredValue">
<span class="fee-label">Insured Value:</span>
<span class="fee-value">{{ estimatedFees.insuredValue | currency }}</span>
</div>
</div>
<mat-checkbox [(ngModel)]="hasReadAllTerms" color="primary" class="read-checkbox">
I have read and agree to all terms and conditions above
</mat-checkbox>

View File

@ -32,14 +32,28 @@ mat-card-header {
padding-left: 16px;
}
ul {
padding-left: 56px;
.fee-table {
width: 100%;
max-width: 325px;
}
li {
margin-bottom: 8px;
.fee-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
padding-left: 2rem;
}
.fee-label {
text-align: left;
padding-right: 20px;
}
.fee-value {
text-align: right;
min-width: 120px;
white-space: nowrap;
}
strong {

View File

@ -3,7 +3,7 @@ import { environment } from '../../../../environments/environment';
import { HttpClient } from '@angular/common/http';
import { UserService } from '../common/user.service';
import { Goods, GoodsItem } from '../../models/carnet/goods';
import { catchError, from, map, mergeMap, Observable, of, toArray } from 'rxjs';
import { map, Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
@ -118,33 +118,14 @@ export class GoodsService {
return this.http.delete(`${this.apiUrl}/${this.apiDb}/DeleteGenerallistItems`, { body: goodsItemsObj });
}
deleteAllGoodsItems(headerid: number, items: GoodsItem[]): Observable<any[]> {
return from(items).pipe(
mergeMap(item => {
const goodsItemsObj = {
P_HEADERID: headerid,
P_ITEMNO: item.itemNumber,
P_USERID: this.userService.getUser(),
};
deleteAllGoodsItems(headerid: number): Observable<any> {
const goodsItemsObj = {
P_HEADERID: headerid,
P_ITEMNO: 99999, // special value to indicate all items
P_USERID: this.userService.getUser(),
};
return this.http.delete(
`${this.apiUrl}/${this.apiDb}/DeleteGenerallistItems`,
{ body: goodsItemsObj }
).pipe(
catchError(error => {
console.error(`Failed to delete item ${item.itemNumber}:`, error);
// Return error result instead of failing the whole stream
return of({
success: false,
item: item.itemNumber,
error: error.message
});
})
);
}, 5),
// Collect all results into an array
toArray()
);
// delete request with body
return this.http.delete(`${this.apiUrl}/${this.apiDb}/DeleteGenerallistItems`, { body: goodsItemsObj });
}
}

View File

@ -41,7 +41,10 @@ export class HomeService {
headerid: item.HEADERID,
clientid: item.CLIENTID,
locationid: item.LOCATIONID,
printGLStatus: item.PRINTGLSTATUS
printGLStatus: item.PRINTGLSTATUS,
securityType: item.SECURITYTYPE,
deliveryType: item.DELIVERYTYPE,
clientName: item.CLIENTNAMNE
}));
}
}

View File

@ -59,6 +59,11 @@
<td mat-cell *matCellDef="let item">{{ item.applicationName }}</td>
</ng-container>
<ng-container matColumnDef="clientName">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Client Name</th>
<td mat-cell *matCellDef="let item">{{ item.clientName }}</td>
</ng-container>
<ng-container matColumnDef="holderName">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Holder Name</th>
<td mat-cell *matCellDef="let item">{{ item.holderName }}</td>
@ -69,6 +74,16 @@
<td mat-cell *matCellDef="let item">{{ item.carnetNumber }}</td>
</ng-container>
<ng-container matColumnDef="deliveryType">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Delivery Type</th>
<td mat-cell *matCellDef="let item">{{ item.deliveryType }}</td>
</ng-container>
<ng-container matColumnDef="securityType">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Security Type</th>
<td mat-cell *matCellDef="let item">{{ item.securityType }}</td>
</ng-container>
<ng-container matColumnDef="usSets">
<th mat-header-cell *matHeaderCellDef mat-sort-header>US Sets</th>
<td mat-cell *matCellDef="let item">{{ item.usSets }}</td>
@ -114,12 +129,6 @@
<th mat-header-cell *matHeaderCellDef>Actions</th>
<td mat-cell *matCellDef="let item">
<div class="action-buttons">
<!-- <button mat-icon-button color="primary" (click)="processCarnet(item)"
*ngIf="getCarnetStatusLabel(item.carnetStatus) === 'Submitted'"
[hidden]="getCarnetStatusLabel(item.carnetStatus) !== 'Submitted'"
matTooltip="Process">
<mat-icon>pending_actions</mat-icon>
</button> -->
<button matIconButton [matMenuTriggerFor]="carnetActions">
<mat-icon>more_horiz</mat-icon>
</button>
@ -161,31 +170,6 @@
<span>Void</span>
</button>
</mat-menu>
<!-- <button mat-icon-button color="primary" (click)="viewCarnet(item)" matTooltip="View">
<mat-icon>article</mat-icon>
</button>
<button mat-icon-button color="primary" (click)="resetClient(item.headerid)"
*ngIf="getCarnetStatusLabel(item.carnetStatus) === 'Submitted'"
[hidden]="getCarnetStatusLabel(item.carnetStatus) !== 'Submitted'"
matTooltip="Reset to Client">
<mat-icon>assignment_return</mat-icon>
</button>
<button mat-icon-button color="primary" (click)="deleteCarnet(item.headerid)" *ngIf="getCarnetStatusLabel(item.carnetStatus) === 'Submitted' ||
getCarnetStatusLabel(item.carnetStatus) === 'Not Submitted'" matTooltip="Delete">
<mat-icon>delete</mat-icon>
</button>
<button mat-icon-button color="primary" (click)="printGeneralList(item.headerid)"
matTooltip="Print General List">
<mat-icon>print</mat-icon>
</button>
<button mat-icon-button color="primary" (click)="printCarnet(item.headerid)"
*ngIf="getCarnetStatusLabel(item.carnetStatus) === 'Valid'" matTooltip="Print">
<mat-icon>print</mat-icon>
</button>
<button mat-icon-button color="primary" (click)="voidCarnet(item.headerid)"
*ngIf="getCarnetStatusLabel(item.carnetStatus) === 'Valid'" matTooltip="Void">
<mat-icon>delete_forever</mat-icon>
</button> -->
</div>
</td>
</ng-container>

View File

@ -20,6 +20,7 @@ import { MatDialog } from '@angular/material/dialog';
import { StorageService } from '../core/services/common/storage.service';
import { CarnetService } from '../core/services/carnet/carnet.service';
import { FormsModule } from '@angular/forms';
import { UserService } from '../core/services/common/user.service';
@Component({
selector: 'app-home',
@ -34,14 +35,18 @@ export class HomeComponent {
showTable = false;
userPreferences: UserPreferences;
carnetStatuses: CarnetStatus[] = [];
currentCarnetStatus: any = {};
// table filter variables
selectedColumn: string = '';
filterValue: string = '';
filterableColumns: any[] = [
{ value: 'applicationName', displayName: 'Application Name' },
{ value: 'clientName', displayName: 'Client Name' },
{ value: 'holderName', displayName: 'Holder Name' },
{ value: 'carnetNumber', displayName: 'Carnet Number' },
{ value: 'deliveryType', displayName: 'Delivery Type' },
{ value: 'securityType', displayName: 'Security Type' },
{ value: 'usSets', displayName: 'US Sets' },
{ value: 'foreignSets', displayName: 'Foreign Sets' },
{ value: 'transitSets', displayName: 'Transit Sets' },
@ -64,7 +69,7 @@ export class HomeComponent {
this.dataSource.sort = value;
}
displayedColumns: string[] = ['applicationName', 'holderName', 'carnetNumber', 'usSets', 'foreignSets', 'transitSets', 'carnetValue', 'issueDate', 'expiryDate', 'orderType', 'carnetStatus', 'actions'];
displayedColumns: string[] = ['applicationName', 'clientName', 'holderName', 'carnetNumber', 'deliveryType', 'securityType', 'usSets', 'foreignSets', 'transitSets', 'carnetValue', 'issueDate', 'expiryDate', 'orderType', 'carnetStatus', 'actions'];
private homeService = inject(HomeService);
private carnetService = inject(CarnetService);
@ -73,6 +78,7 @@ export class HomeComponent {
private commonService = inject(CommonService);
private navigationService = inject(NavigationService);
private storageService = inject(StorageService);
private userService = inject(UserService);
private dialog = inject(MatDialog);
constructor(userPrefenceService: UserPreferencesService) {
@ -101,7 +107,12 @@ export class HomeComponent {
next: (data) => {
this.carnetData = data;
this.isLoading = false;
this.defaultCarnetStatusData();
if (!this.currentCarnetStatus?.spid) {
this.defaultCarnetStatusData();
} else {
this.onCarnetStatusClick(this.currentCarnetStatus);
}
},
error: (error) => {
console.error('Error loading carnet data:', error);
@ -114,13 +125,15 @@ export class HomeComponent {
this.isLoading = true;
this.showTable = false;
this.currentCarnetStatus = event;
// Clear any existing filters when loading new data
this.clearFilter();
this.homeService.getCarnetDataByStatus(event.spid, event.carnetStatus).subscribe({
next: (carnetDetails) => {
this.isLoading = false;
this.showTable = true;
this.showTable = carnetDetails.length > 0;;
this.dataSource.data = carnetDetails;
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
@ -142,7 +155,7 @@ export class HomeComponent {
const inProgressData = this.carnetData?.[0]?.CARNETSTATUS?.includes('T');
if (inProgressData) {
let spid = this.carnetData[0].SPID;
let spid = this.carnetData[0].SPID ?? this.userService.getUserSpid();
var carentData = {
spid: spid,
carnetStatus: 'T'
@ -175,8 +188,11 @@ export class HomeComponent {
prepareDownloadData(): any[] {
return this.dataSource.data.map(item => ({
'Application Name': item.applicationName,
'Client Name': item.clientName,
'Holder Name': item.holderName,
'Carnet Number': item.carnetNumber,
'Delivery Type': item.deliveryType,
'Security Type': item.securityType,
'US Sets': item.usSets,
'Foreign Sets': item.foreignSets,
'Transit Sets': item.transitSets,