feedback updates
This commit is contained in:
parent
7f79cc6d57
commit
4fee83707a
5
src/app/core/models/holder-type.ts
Normal file
5
src/app/core/models/holder-type.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export interface HolderType {
|
||||||
|
name: string;
|
||||||
|
id: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
12
src/app/core/models/service-provider/cargo-rate.ts
Normal file
12
src/app/core/models/service-provider/cargo-rate.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export interface CargoRate {
|
||||||
|
id: number,
|
||||||
|
spid: number,
|
||||||
|
startSets: number,
|
||||||
|
endSets: number,
|
||||||
|
carnetType: string,
|
||||||
|
effectiveDate: Date,
|
||||||
|
rate: number,
|
||||||
|
dateCreated?: Date | null;
|
||||||
|
createdBy?: string | null;
|
||||||
|
expired?: boolean;
|
||||||
|
}
|
||||||
@ -5,6 +5,7 @@ export interface SecurityDeposit {
|
|||||||
specialCommodity: string;
|
specialCommodity: string;
|
||||||
specialCountry: string;
|
specialCountry: string;
|
||||||
rate: number;
|
rate: number;
|
||||||
|
rateInPercentage: number;
|
||||||
effectiveDate: Date;
|
effectiveDate: Date;
|
||||||
spid: number;
|
spid: number;
|
||||||
dateCreated?: Date | null;
|
dateCreated?: Date | null;
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import { CargoSurety } from '../../models/cargo-surety';
|
|||||||
import { CarnetStatus } from '../../models/carnet-status';
|
import { CarnetStatus } from '../../models/carnet-status';
|
||||||
import { Country } from '../../models/country';
|
import { Country } from '../../models/country';
|
||||||
import { UserService } from './user.service';
|
import { UserService } from './user.service';
|
||||||
|
import { HolderType } from '../../models/holder-type';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -150,6 +151,18 @@ export class CommonService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getHolderTypes(): Observable<HolderType[]> {
|
||||||
|
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=017&P_SPID=${this.userService.getUserSpid()}`).pipe(
|
||||||
|
map((response) =>
|
||||||
|
response.map((item) => ({
|
||||||
|
name: item.PARAMDESC,
|
||||||
|
id: item.PARAMID,
|
||||||
|
value: item.PARAMVALUE,
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
formatUSDate(datetime: Date): string {
|
formatUSDate(datetime: Date): string {
|
||||||
const date = new Date(datetime);
|
const date = new Date(datetime);
|
||||||
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
|
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
|
||||||
|
|||||||
70
src/app/core/services/service-provider/cargo-rate.service.ts
Normal file
70
src/app/core/services/service-provider/cargo-rate.service.ts
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import { inject, Injectable } from '@angular/core';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { map, Observable } from 'rxjs';
|
||||||
|
import { environment } from '../../../../environments/environment';
|
||||||
|
import { CommonService } from '../common/common.service';
|
||||||
|
import { UserService } from '../common/user.service';
|
||||||
|
import { CargoRate } from '../../models/service-provider/cargo-rate';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class CargoRateService {
|
||||||
|
private apiUrl = environment.apiUrl;
|
||||||
|
private apiDb = environment.apiDb;
|
||||||
|
|
||||||
|
private http = inject(HttpClient);
|
||||||
|
private userService = inject(UserService);
|
||||||
|
private commonService = inject(CommonService);
|
||||||
|
|
||||||
|
getCargoRates(spid: number): Observable<CargoRate[]> {
|
||||||
|
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetCargoRates/${spid}/ACTIVE`).pipe(
|
||||||
|
map(response => this.mapToCargoRates(response)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private mapToCargoRates(data: any[]): CargoRate[] {
|
||||||
|
return data.map(item => ({
|
||||||
|
id: item.CARGORATESETUPID,
|
||||||
|
spid: item.SPID,
|
||||||
|
startSets: item.STARTSETS,
|
||||||
|
endSets: item.ENDSETS,
|
||||||
|
carnetType: item.CARNETTYPE,
|
||||||
|
effectiveDate: item.EFFDATE,
|
||||||
|
rate: item.RATE,
|
||||||
|
createdBy: item.CREATEDBY || null,
|
||||||
|
dateCreated: item.DATECREATED || null,
|
||||||
|
expired: item.EXPDATE ? new Date(item.EXPDATE) < new Date() : false
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
addCargoRate(spid: number, data: CargoRate): Observable<any> {
|
||||||
|
|
||||||
|
const cargoRate = {
|
||||||
|
P_SPID: spid,
|
||||||
|
P_STARTSETS: data.startSets,
|
||||||
|
P_ENDSETS: data.endSets,
|
||||||
|
P_EFFDATE: this.commonService.formatUSDate(data.effectiveDate),
|
||||||
|
P_CARNETTYPE: data.carnetType,
|
||||||
|
P_RATE: data.rate,
|
||||||
|
P_USERID: this.userService.getUser()
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.http.post<any>(`${this.apiUrl}/${this.apiDb}/CreateCargoRate`, cargoRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCargoRate(id: number, data: CargoRate): Observable<any> {
|
||||||
|
|
||||||
|
const cargoRate = {
|
||||||
|
P_CARGORATESETUPID: id,
|
||||||
|
P_EFFDATE: this.commonService.formatUSDate(data.effectiveDate),
|
||||||
|
P_RATE: data.rate,
|
||||||
|
P_USERID: this.userService.getUser()
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.http.patch<any>(`${this.apiUrl}/${this.apiDb}//UpdateCargoRate`, cargoRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleteCargo(id: string): Observable<void> {
|
||||||
|
// return this.http.delete<void>(`${this.apiUrl}/${this.apiDb}/InactivateSPContact/${id}`);
|
||||||
|
// }
|
||||||
|
}
|
||||||
@ -30,6 +30,7 @@ export class SecurityDepositService {
|
|||||||
specialCommodity: item.SPCLCOMMODITY,
|
specialCommodity: item.SPCLCOMMODITY,
|
||||||
specialCountry: item.SPCLCOUNTRY,
|
specialCountry: item.SPCLCOUNTRY,
|
||||||
rate: item.RATE,
|
rate: item.RATE,
|
||||||
|
rateInPercentage: item.RATE * 100,
|
||||||
effectiveDate: item.EFFDATE,
|
effectiveDate: item.EFFDATE,
|
||||||
spid: item.SPID,
|
spid: item.SPID,
|
||||||
createdBy: item.CREATEDBY || null,
|
createdBy: item.CREATEDBY || null,
|
||||||
@ -48,6 +49,7 @@ export class SecurityDepositService {
|
|||||||
P_SPCLCOMMODITY: data.specialCommodity,
|
P_SPCLCOMMODITY: data.specialCommodity,
|
||||||
P_SPCLCOUNTRY: data.specialCountry,
|
P_SPCLCOUNTRY: data.specialCountry,
|
||||||
P_RATE: data.rate,
|
P_RATE: data.rate,
|
||||||
|
P_PCT_VALUE: data.rateInPercentage.toString(),
|
||||||
P_USERID: this.userService.getUser()
|
P_USERID: this.userService.getUser()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +62,7 @@ export class SecurityDepositService {
|
|||||||
P_BONDRATESETUPID: id,
|
P_BONDRATESETUPID: id,
|
||||||
P_EFFDATE: this.commonService.formatUSDate(data.effectiveDate),
|
P_EFFDATE: this.commonService.formatUSDate(data.effectiveDate),
|
||||||
P_RATE: data.rate,
|
P_RATE: data.rate,
|
||||||
|
P_PCT_VALUE: data.rateInPercentage.toString(),
|
||||||
P_USERID: this.userService.getUser()
|
P_USERID: this.userService.getUser()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -86,18 +86,18 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button mat-icon-button color="primary" *ngIf="isParamRecord
|
<button mat-icon-button color="primary" *ngIf="isParamRecord
|
||||||
&& allowEdit"
|
&& allowEdit" (click)="onEditParam(client)" [matTooltip]="'edit'">
|
||||||
(click)="onEditParam(client)" [matTooltip]="'edit'">
|
|
||||||
<mat-icon>edit</mat-icon>
|
<mat-icon>edit</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button mat-icon-button color="warn"
|
<button mat-icon-button color="warn"
|
||||||
*ngIf="isParamRecord && (client.inactiveCodeFlag === 'N' || !client.inactiveCodeFlag)"
|
*ngIf="isParamRecord && (client.inactiveCodeFlag === 'N' || !client.inactiveCodeFlag) && allowEdit"
|
||||||
matTooltip="Inactivate" (click)="inActivateParamRecord(client.paramId)">
|
matTooltip="Inactivate" (click)="inActivateParamRecord(client.paramId)">
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button mat-icon-button color="warn" *ngIf="(isParamRecord) && client.inactiveCodeFlag === 'Y'"
|
<button mat-icon-button color="warn"
|
||||||
|
*ngIf="(isParamRecord) && client.inactiveCodeFlag === 'Y' && allowEdit"
|
||||||
matTooltip="Reactivate" (click)="reActivateParamRecord(client.paramId)">
|
matTooltip="Reactivate" (click)="reActivateParamRecord(client.paramId)">
|
||||||
<mat-icon>delete_outline</mat-icon>
|
<mat-icon>delete_outline</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -83,5 +83,14 @@
|
|||||||
[userPreferences]="userPreferences"></app-security-deposit>
|
[userPreferences]="userPreferences"></app-security-deposit>
|
||||||
</mat-step>
|
</mat-step>
|
||||||
|
|
||||||
|
<!-- Cargo Rate Step -->
|
||||||
|
<mat-step [editable]="!!serviceProviderId && securityDepositCompleted" [completed]="cargoRateCompleted">
|
||||||
|
<ng-template matStepLabel>Cargo Rate Setup</ng-template>
|
||||||
|
|
||||||
|
<app-cargo-rate *ngIf="serviceProviderId" [spid]="serviceProviderId"
|
||||||
|
(hasCargoRates)="onCargoRateSaved($event)" [userPreferences]="userPreferences">
|
||||||
|
</app-cargo-rate>
|
||||||
|
</mat-step>
|
||||||
|
|
||||||
</mat-stepper>
|
</mat-stepper>
|
||||||
</div>
|
</div>
|
||||||
@ -13,11 +13,12 @@ import { SecurityDepositComponent } from '../security-deposit/security-deposit.c
|
|||||||
import { ContinuationSheetFeeComponent } from "../continuation-sheet-fee/continuation-sheet-fee.component";
|
import { ContinuationSheetFeeComponent } from "../continuation-sheet-fee/continuation-sheet-fee.component";
|
||||||
import { UserPreferences } from '../../core/models/user-preference';
|
import { UserPreferences } from '../../core/models/user-preference';
|
||||||
import { UserPreferencesService } from '../../core/services/user-preference.service';
|
import { UserPreferencesService } from '../../core/services/user-preference.service';
|
||||||
|
import { CargoRateComponent } from '../cargo-rate/cargo-rate.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-add-service-provider',
|
selector: 'app-add-service-provider',
|
||||||
imports: [BasicDetailsComponent, AngularMaterialModule, CommonModule, ContactsComponent, CarnetSequenceComponent,
|
imports: [BasicDetailsComponent, AngularMaterialModule, CommonModule, ContactsComponent, CarnetSequenceComponent,
|
||||||
CarnetFeeComponent, BasicFeeComponent, CounterfoilFeeComponent, ExpeditedFeeComponent, SecurityDepositComponent, ContinuationSheetFeeComponent],
|
CarnetFeeComponent, BasicFeeComponent, CounterfoilFeeComponent, ExpeditedFeeComponent, SecurityDepositComponent, ContinuationSheetFeeComponent, CargoRateComponent],
|
||||||
templateUrl: './add-service-provider.component.html',
|
templateUrl: './add-service-provider.component.html',
|
||||||
styleUrl: './add-service-provider.component.scss'
|
styleUrl: './add-service-provider.component.scss'
|
||||||
})
|
})
|
||||||
@ -37,6 +38,7 @@ export class AddServiceProviderComponent {
|
|||||||
continuationSheetFeeCompleted: boolean = false;
|
continuationSheetFeeCompleted: boolean = false;
|
||||||
expeditedFeeCompleted: boolean = false;
|
expeditedFeeCompleted: boolean = false;
|
||||||
securityDepositCompleted: boolean = false;
|
securityDepositCompleted: boolean = false;
|
||||||
|
cargoRateCompleted: boolean = false;
|
||||||
|
|
||||||
constructor(userPrefenceService: UserPreferencesService) {
|
constructor(userPrefenceService: UserPreferencesService) {
|
||||||
this.userPreferences = userPrefenceService.getPreferences();
|
this.userPreferences = userPrefenceService.getPreferences();
|
||||||
@ -79,6 +81,10 @@ export class AddServiceProviderComponent {
|
|||||||
this.securityDepositCompleted = event;
|
this.securityDepositCompleted = event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onCargoRateSaved(event: boolean): void {
|
||||||
|
this.cargoRateCompleted = event;
|
||||||
|
}
|
||||||
|
|
||||||
onStepChange(event: StepperSelectionEvent): void {
|
onStepChange(event: StepperSelectionEvent): void {
|
||||||
this.currentStep = event.selectedIndex;
|
this.currentStep = event.selectedIndex;
|
||||||
}
|
}
|
||||||
|
|||||||
192
src/app/service-provider/cargo-rate/cargo-rate.component.html
Normal file
192
src/app/service-provider/cargo-rate/cargo-rate.component.html
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
<div class="cargorate-container">
|
||||||
|
<div class="actions-bar">
|
||||||
|
<mat-slide-toggle (change)="toggleShowExpiredRecords()">
|
||||||
|
Show Expired Records
|
||||||
|
</mat-slide-toggle>
|
||||||
|
<button mat-raised-button color="primary" (click)="addNewCargoRate()">
|
||||||
|
<mat-icon>add</mat-icon> Add New Cargo Rate
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-container mat-elevation-z8">
|
||||||
|
<div class="loading-shade" *ngIf="isLoading">
|
||||||
|
<mat-spinner diameter="50"></mat-spinner>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table mat-table [dataSource]="dataSource" matSort>
|
||||||
|
|
||||||
|
<!-- Carnet Type Column -->
|
||||||
|
<ng-container matColumnDef="carnetType">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header>Carnet Type</th>
|
||||||
|
<td mat-cell *matCellDef="let item">
|
||||||
|
{{ getOptionLabel(carnetTypes, item.carnetType) }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Start Sets Column -->
|
||||||
|
<ng-container matColumnDef="startSets">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header>Start Sets</th>
|
||||||
|
<td mat-cell *matCellDef="let item">{{ item.startSets }}</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- End Sets Column -->
|
||||||
|
<ng-container matColumnDef="endSets">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header>End Sets</th>
|
||||||
|
<td mat-cell *matCellDef="let item">{{ item.endSets }}</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Rate Column -->
|
||||||
|
<ng-container matColumnDef="rate">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header>Rate</th>
|
||||||
|
<td mat-cell *matCellDef="let item">{{ item.rate | currency }}</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Effective Date Column -->
|
||||||
|
<ng-container matColumnDef="effectiveDate">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header>Effective Date</th>
|
||||||
|
<td mat-cell *matCellDef="let item">
|
||||||
|
{{ item.effectiveDate | date:'mediumDate':'UTC' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Actions Column -->
|
||||||
|
<ng-container matColumnDef="actions">
|
||||||
|
<th mat-header-cell *matHeaderCellDef>Actions</th>
|
||||||
|
<td mat-cell *matCellDef="let item">
|
||||||
|
<button mat-icon-button color="primary" (click)="editCargoRate(item)" matTooltip="Edit">
|
||||||
|
<mat-icon>edit</mat-icon>
|
||||||
|
</button>
|
||||||
|
<!-- <button mat-icon-button color="warn" (click)="deleteCargoRate(item.id)" matTooltip="Delete">
|
||||||
|
<mat-icon>delete</mat-icon>
|
||||||
|
</button> -->
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||||
|
|
||||||
|
<tr matNoDataRow *matNoDataRow>
|
||||||
|
<td [colSpan]="displayedColumns.length" class="no-data-message">
|
||||||
|
<mat-icon>info</mat-icon>
|
||||||
|
<span>No cargo rate setups available</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<mat-paginator *ngIf="dataSource.data.length > userPreferences.pageSize!" [length]="dataSource.data.length"
|
||||||
|
[pageSizeOptions]="[userPreferences.pageSize!]" [hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- CargoRate Form -->
|
||||||
|
<div class="form-container" *ngIf="showForm">
|
||||||
|
<form [formGroup]="cargoRateForm" (ngSubmit)="saveCargoRate()">
|
||||||
|
<div class="form-header">
|
||||||
|
<h3>{{ isEditing ? 'Edit Cargo Rate Setup' : 'Add New Cargo Rate Setup' }}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<mat-label>Carnet Type</mat-label>
|
||||||
|
<mat-radio-group formControlName="carnetType" required class="horizontal-group">
|
||||||
|
<mat-radio-button *ngFor="let type of carnetTypes" [value]="type.value" class="radio-button">
|
||||||
|
{{ type.label }}
|
||||||
|
</mat-radio-button>
|
||||||
|
</mat-radio-group>
|
||||||
|
<mat-error *ngIf="cargoRateForm.get('carnetType')?.errors?.['required']">
|
||||||
|
Carnet type is required
|
||||||
|
</mat-error>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Start Sets</mat-label>
|
||||||
|
<input matInput formControlName="startSets" type="number" required>
|
||||||
|
<mat-error *ngIf="cargoRateForm.get('startSets')?.errors?.['required']">
|
||||||
|
Start sets is required
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="cargoRateForm.get('startSets')?.errors?.['pattern']">
|
||||||
|
Must be a valid number
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="cargoRateForm.get('startSets')?.errors?.['min']">
|
||||||
|
Must be greater than 0
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>End Sets</mat-label>
|
||||||
|
<input matInput formControlName="endSets" type="number" required>
|
||||||
|
<mat-error *ngIf="cargoRateForm.get('endSets')?.errors?.['required']">
|
||||||
|
End sets is required
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="cargoRateForm.get('endSets')?.errors?.['pattern']">
|
||||||
|
Must be a valid number
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="cargoRateForm.get('endSets')?.errors?.['min']">
|
||||||
|
Must be greater than 0
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<mat-error *ngIf="cargoRateForm?.errors?.['invalidRange']" class="form-error">
|
||||||
|
End sets must be greater than start sets
|
||||||
|
</mat-error>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Rate</mat-label>
|
||||||
|
<input matInput formControlName="rate" type="number" step="1" required>
|
||||||
|
<span class="dollar-prefix" matPrefix>$ </span>
|
||||||
|
<mat-error *ngIf="cargoRateForm.get('rate')?.errors?.['required']">
|
||||||
|
Rate is required
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="cargoRateForm.get('rate')?.errors?.['pattern']">
|
||||||
|
Must be a valid dollar amount
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="cargoRateForm.get('rate')?.errors?.['min']">
|
||||||
|
Must be 0 or greater
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Effective Date</mat-label>
|
||||||
|
<input matInput [matDatepicker]="picker" formControlName="effectiveDate" required>
|
||||||
|
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
|
||||||
|
<mat-datepicker #picker></mat-datepicker>
|
||||||
|
<mat-error *ngIf="cargoRateForm.get('effectiveDate')?.errors?.['required']">
|
||||||
|
Effective date is required
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="isEditing" class="readonly-section">
|
||||||
|
<div class="readonly-fields">
|
||||||
|
<div class="field-column">
|
||||||
|
<!-- Last Changed By -->
|
||||||
|
<div class="readonly-field">
|
||||||
|
<label>Last Changed By</label>
|
||||||
|
<div class="readonly-value">
|
||||||
|
{{readOnlyFields.lastChangedBy || 'N/A'}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field-column">
|
||||||
|
<!-- Last Changed Date -->
|
||||||
|
<div class="readonly-field">
|
||||||
|
<label>Last Changed Date</label>
|
||||||
|
<div class="readonly-value">
|
||||||
|
{{(readOnlyFields.lastChangedDate | date:'mediumDate':'UTC') || 'N/A'}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-actions">
|
||||||
|
<button mat-raised-button color="primary" type="submit"
|
||||||
|
[disabled]="cargoRateForm.invalid || changeInProgress">
|
||||||
|
{{ isEditing ? 'Update' : 'Save' }}
|
||||||
|
</button>
|
||||||
|
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
191
src/app/service-provider/cargo-rate/cargo-rate.component.scss
Normal file
191
src/app/service-provider/cargo-rate/cargo-rate.component.scss
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
.cargorate-container {
|
||||||
|
padding: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 24px;
|
||||||
|
|
||||||
|
.actions-bar {
|
||||||
|
clear: both;
|
||||||
|
margin-bottom: -16px;
|
||||||
|
|
||||||
|
mat-slide-toggle {
|
||||||
|
transform: scale(0.8);
|
||||||
|
margin-left: -0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
position: relative;
|
||||||
|
overflow: auto;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
.loading-shade {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-table {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-column-actions {
|
||||||
|
width: 120px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-data-message {
|
||||||
|
text-align: center;
|
||||||
|
padding: 0.9rem;
|
||||||
|
color: rgba(0, 0, 0, 0.54);
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
font-size: 1rem;
|
||||||
|
width: 1rem;
|
||||||
|
height: 1rem;
|
||||||
|
margin-bottom: -3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-paginator {
|
||||||
|
border-top: 1px solid rgba(0, 0, 0, 0.12);
|
||||||
|
border-radius: 0 0 8px 8px;
|
||||||
|
padding-top: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-container {
|
||||||
|
background-color: white;
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-top: 16px;
|
||||||
|
|
||||||
|
.form-header {
|
||||||
|
// margin-bottom: 24px;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--mat-sys-primary);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
.form-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
align-items: start;
|
||||||
|
|
||||||
|
mat-form-field {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-label {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-error {
|
||||||
|
margin-top: -16px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
display: block;
|
||||||
|
color: var(--mat-form-field-error-text-color, var(--mat-sys-error));
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 16px;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontal-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep .mat-radio-button.mat-accent .mat-radio-outer-circle {
|
||||||
|
border-color: #3f51b5;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep .mat-radio-button.mat-accent .mat-radio-inner-circle {
|
||||||
|
background-color: #3f51b5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dollar-prefix {
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.readonly-section {
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
|
||||||
|
.readonly-fields {
|
||||||
|
display: flex;
|
||||||
|
gap: 2rem;
|
||||||
|
|
||||||
|
.field-column {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.readonly-field {
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.readonly-value {
|
||||||
|
padding: 0.25rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Responsive adjustments
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.cargorate-container {
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
.form-row {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
244
src/app/service-provider/cargo-rate/cargo-rate.component.ts
Normal file
244
src/app/service-provider/cargo-rate/cargo-rate.component.ts
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
import { Component, EventEmitter, inject, Input, OnInit, Output, ViewChild } from '@angular/core';
|
||||||
|
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
|
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
|
||||||
|
import { MatSort } from '@angular/material/sort';
|
||||||
|
import { MatTableDataSource } from '@angular/material/table';
|
||||||
|
import { AngularMaterialModule } from '../../shared/module/angular-material.module';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { CustomPaginator } from '../../shared/custom-paginator';
|
||||||
|
import { UserPreferences } from '../../core/models/user-preference';
|
||||||
|
import { ApiErrorHandlerService } from '../../core/services/common/api-error-handler.service';
|
||||||
|
import { NotificationService } from '../../core/services/common/notification.service';
|
||||||
|
import { finalize } from 'rxjs';
|
||||||
|
import { CargoRate } from '../../core/models/service-provider/cargo-rate';
|
||||||
|
import { CargoRateService } from '../../core/services/service-provider/cargo-rate.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-cargo-rate',
|
||||||
|
imports: [AngularMaterialModule, CommonModule, ReactiveFormsModule],
|
||||||
|
templateUrl: './cargo-rate.component.html',
|
||||||
|
styleUrl: './cargo-rate.component.scss',
|
||||||
|
providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }],
|
||||||
|
})
|
||||||
|
export class CargoRateComponent implements OnInit {
|
||||||
|
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||||
|
@ViewChild(MatSort) sort!: MatSort;
|
||||||
|
|
||||||
|
displayedColumns: string[] = ['carnetType', 'startSets', 'endSets', 'rate', 'effectiveDate', 'actions'];
|
||||||
|
dataSource = new MatTableDataSource<any>();
|
||||||
|
cargoRateForm: FormGroup;
|
||||||
|
isEditing = false;
|
||||||
|
currentCargoRateId: number | null = null;
|
||||||
|
isLoading = false;
|
||||||
|
changeInProgress = false;
|
||||||
|
showForm = false;
|
||||||
|
showExpiredRecords = false;
|
||||||
|
cargoRates: CargoRate[] = [];
|
||||||
|
|
||||||
|
readOnlyFields: any = {
|
||||||
|
lastChangedDate: null,
|
||||||
|
lastChangedBy: null
|
||||||
|
};
|
||||||
|
|
||||||
|
carnetTypes = [
|
||||||
|
{ label: 'Original', value: 'ORIGINAL' },
|
||||||
|
{ label: 'Re-order', value: 'REORDER' },
|
||||||
|
{ label: 'Replacement', value: 'REPLACE' }
|
||||||
|
];
|
||||||
|
|
||||||
|
@Input() isEditMode = false;
|
||||||
|
@Input() spid: number = 0;
|
||||||
|
@Input() userPreferences!: UserPreferences;
|
||||||
|
@Output() hasCargoRates = new EventEmitter<boolean>();
|
||||||
|
|
||||||
|
private fb = inject(FormBuilder);
|
||||||
|
private cargoRateService = inject(CargoRateService);
|
||||||
|
private notificationService = inject(NotificationService);
|
||||||
|
private errorHandler = inject(ApiErrorHandlerService);
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.cargoRateForm = this.fb.group({
|
||||||
|
carnetType: ['ORIGINAL', Validators.required],
|
||||||
|
startSets: ['', [
|
||||||
|
Validators.required,
|
||||||
|
Validators.pattern('^[0-9]*$'),
|
||||||
|
Validators.min(1)
|
||||||
|
]],
|
||||||
|
endSets: ['', [
|
||||||
|
Validators.required,
|
||||||
|
Validators.pattern('^[0-9]*$'),
|
||||||
|
Validators.min(1)
|
||||||
|
]],
|
||||||
|
rate: ['', [
|
||||||
|
Validators.required,
|
||||||
|
Validators.pattern(/^\d+\.?\d{0,2}$/),
|
||||||
|
Validators.min(0)
|
||||||
|
]],
|
||||||
|
effectiveDate: ['', Validators.required]
|
||||||
|
}, { validator: this.validateSetsRange });
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.loadCargoRates();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
this.dataSource.paginator = this.paginator;
|
||||||
|
this.dataSource.sort = this.sort;
|
||||||
|
}
|
||||||
|
|
||||||
|
private validateSetsRange(group: FormGroup): { [key: string]: any } | null {
|
||||||
|
const start = +group.get('startSets')?.value;
|
||||||
|
const end = +group.get('endSets')?.value;
|
||||||
|
return start && end && start >= end ? { invalidRange: true } : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadCargoRates(): void {
|
||||||
|
if (!this.spid) return;
|
||||||
|
|
||||||
|
this.isLoading = true;
|
||||||
|
this.cargoRateService.getCargoRates(this.spid).pipe(finalize(() => {
|
||||||
|
this.isLoading = false;
|
||||||
|
}))
|
||||||
|
.subscribe({
|
||||||
|
next: (
|
||||||
|
cargoRates: CargoRate[]) => {
|
||||||
|
this.cargoRates = cargoRates;
|
||||||
|
this.dataSource.data = this.cargoRates;
|
||||||
|
this.renderRecods();
|
||||||
|
},
|
||||||
|
error: (error: any) => {
|
||||||
|
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load cargo rates');
|
||||||
|
this.notificationService.showError(errorMessage);
|
||||||
|
console.error('Error loading cargo rates:', error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleShowExpiredRecords(): void {
|
||||||
|
this.showExpiredRecords = !this.showExpiredRecords;
|
||||||
|
this.renderRecods();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderRecods(): void {
|
||||||
|
if (this.showExpiredRecords) {
|
||||||
|
this.dataSource.data = this.cargoRates.filter(record => record.expired);
|
||||||
|
} else {
|
||||||
|
this.dataSource.data = this.cargoRates.filter(record => !record.expired);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// applyFilter(event: Event): void {
|
||||||
|
// const filterValue = (event.target as HTMLInputElement).value;
|
||||||
|
// this.dataSource.filter = filterValue.trim().toLowerCase();
|
||||||
|
|
||||||
|
// if (this.dataSource.paginator) {
|
||||||
|
// this.dataSource.paginator.firstPage();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
addNewCargoRate(): void {
|
||||||
|
this.showForm = true;
|
||||||
|
this.isEditing = false;
|
||||||
|
this.currentCargoRateId = null;
|
||||||
|
this.cargoRateForm.reset({
|
||||||
|
carnetType: 'ORIGINAL'
|
||||||
|
});
|
||||||
|
|
||||||
|
this.cargoRateForm.get('carnetType')?.enable();
|
||||||
|
this.cargoRateForm.get('startSets')?.enable();
|
||||||
|
this.cargoRateForm.get('endSets')?.enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
editCargoRate(cargoRate: any): void {
|
||||||
|
this.showForm = true;
|
||||||
|
this.isEditing = true;
|
||||||
|
this.currentCargoRateId = cargoRate.id;
|
||||||
|
this.cargoRateForm.patchValue({
|
||||||
|
carnetType: cargoRate.carnetType,
|
||||||
|
startSets: cargoRate.startSets,
|
||||||
|
endSets: cargoRate.endSets,
|
||||||
|
rate: cargoRate.rate,
|
||||||
|
effectiveDate: new Date(cargoRate.effectiveDate)
|
||||||
|
});
|
||||||
|
|
||||||
|
this.readOnlyFields.lastChangedDate = cargoRate.dateCreated;
|
||||||
|
this.readOnlyFields.lastChangedBy = cargoRate.createdBy;
|
||||||
|
|
||||||
|
this.cargoRateForm.get('carnetType')?.disable();
|
||||||
|
this.cargoRateForm.get('startSets')?.disable();
|
||||||
|
this.cargoRateForm.get('endSets')?.disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
saveCargoRate(): void {
|
||||||
|
if (this.cargoRateForm.invalid) {
|
||||||
|
this.cargoRateForm.markAllAsTouched();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cargoRateData = {
|
||||||
|
...this.cargoRateForm.value,
|
||||||
|
spid: this.spid
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveObservable = this.isEditing && this.currentCargoRateId
|
||||||
|
? this.cargoRateService.updateCargoRate(this.currentCargoRateId, cargoRateData)
|
||||||
|
: this.cargoRateService.addCargoRate(this.spid, cargoRateData);
|
||||||
|
|
||||||
|
this.changeInProgress = true;
|
||||||
|
saveObservable.pipe(finalize(() => {
|
||||||
|
this.changeInProgress = false;
|
||||||
|
})).subscribe({
|
||||||
|
next: () => {
|
||||||
|
this.notificationService.showSuccess(`Cargo Rate ${this.isEditing ? 'updated' : 'added'} successfully`);
|
||||||
|
this.loadCargoRates();
|
||||||
|
this.cancelEdit();
|
||||||
|
this.hasCargoRates.emit(true);
|
||||||
|
},
|
||||||
|
error: (error) => {
|
||||||
|
let errorMessage = this.errorHandler.handleApiError(error, `Failed to ${this.isEditing ? 'update' : 'add'} cargo rate`);
|
||||||
|
this.notificationService.showError(errorMessage);
|
||||||
|
console.error('Error saving cargo rate:', error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleteCargoRate(cargoRateId: string): void {
|
||||||
|
// const dialogRef = this.dialog.open(ConfirmDialogComponent, {
|
||||||
|
// width: '350px',
|
||||||
|
// data: {
|
||||||
|
// title: 'Confirm Delete',
|
||||||
|
// message: 'Are you sure you want to delete this cargoRate setup?',
|
||||||
|
// confirmText: 'Delete',
|
||||||
|
// cancelText: 'Cancel'
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// dialogRef.afterClosed().subscribe(result => {
|
||||||
|
// if (result) {
|
||||||
|
// this.cargoRateService.deleteCargoRate(cargoRateId).subscribe({
|
||||||
|
// next: () => {
|
||||||
|
// this.notificationService.showSuccess('CargoRate deleted successfully');
|
||||||
|
// this.loadCargoRates();
|
||||||
|
// },
|
||||||
|
// error: (error) => {
|
||||||
|
// this.notificationService.showError('Failed to delete cargoRate');
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
cancelEdit(): void {
|
||||||
|
this.showForm = false;
|
||||||
|
this.isEditing = false;
|
||||||
|
this.currentCargoRateId = null;
|
||||||
|
this.cargoRateForm.reset({
|
||||||
|
carnetType: 'ORIGINAL'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getOptionLabel(options: any[], value: string): string {
|
||||||
|
return options.find(opt => opt.value === value)?.label || value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -73,4 +73,12 @@
|
|||||||
<app-security-deposit [spid]="spid" [isEditMode]="isEditMode"
|
<app-security-deposit [spid]="spid" [isEditMode]="isEditMode"
|
||||||
[userPreferences]="userPreferences"></app-security-deposit>
|
[userPreferences]="userPreferences"></app-security-deposit>
|
||||||
</mat-expansion-panel>
|
</mat-expansion-panel>
|
||||||
|
|
||||||
|
<mat-expansion-panel>
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title> Cargo Rate Setup </mat-panel-title>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
<app-cargo-rate [spid]="spid" [isEditMode]="isEditMode" [userPreferences]="userPreferences">
|
||||||
|
</app-cargo-rate>
|
||||||
|
</mat-expansion-panel>
|
||||||
</mat-accordion>
|
</mat-accordion>
|
||||||
@ -14,10 +14,11 @@ import { SecurityDepositComponent } from "../security-deposit/security-deposit.c
|
|||||||
import { UserPreferences } from '../../core/models/user-preference';
|
import { UserPreferences } from '../../core/models/user-preference';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { UserPreferencesService } from '../../core/services/user-preference.service';
|
import { UserPreferencesService } from '../../core/services/user-preference.service';
|
||||||
|
import { CargoRateComponent } from '../cargo-rate/cargo-rate.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-edit-service-provider',
|
selector: 'app-edit-service-provider',
|
||||||
imports: [AngularMaterialModule, BasicDetailsComponent, ContactsComponent, CarnetSequenceComponent, CarnetFeeComponent, BasicFeeComponent, CounterfoilFeeComponent, ContinuationSheetFeeComponent, ExpeditedFeeComponent, SecurityDepositComponent, CommonModule],
|
imports: [AngularMaterialModule, BasicDetailsComponent, ContactsComponent, CarnetSequenceComponent, CarnetFeeComponent, BasicFeeComponent, CounterfoilFeeComponent, ContinuationSheetFeeComponent, ExpeditedFeeComponent, SecurityDepositComponent, CommonModule, CargoRateComponent],
|
||||||
templateUrl: './edit-service-provider.component.html',
|
templateUrl: './edit-service-provider.component.html',
|
||||||
styleUrl: './edit-service-provider.component.scss'
|
styleUrl: './edit-service-provider.component.scss'
|
||||||
})
|
})
|
||||||
|
|||||||
@ -48,6 +48,12 @@
|
|||||||
<td mat-cell *matCellDef="let deposit">{{ deposit.rate | currency }}</td>
|
<td mat-cell *matCellDef="let deposit">{{ deposit.rate | currency }}</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Rate In Percentage Column -->
|
||||||
|
<ng-container matColumnDef="rateInPercentage">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header>Rate In Percentage</th>
|
||||||
|
<td mat-cell *matCellDef="let deposit">{{ deposit.rateInPercentage | percent }}</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<!-- Effective Date Column -->
|
<!-- Effective Date Column -->
|
||||||
<ng-container matColumnDef="effectiveDate">
|
<ng-container matColumnDef="effectiveDate">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Effective Date</th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header>Effective Date</th>
|
||||||
@ -97,7 +103,7 @@
|
|||||||
<mat-label>Holder Type</mat-label>
|
<mat-label>Holder Type</mat-label>
|
||||||
<mat-radio-group formControlName="holderType" required class="horizontal-group">
|
<mat-radio-group formControlName="holderType" required class="horizontal-group">
|
||||||
<mat-radio-button *ngFor="let type of holderTypes" [value]="type.value" class="radio-button">
|
<mat-radio-button *ngFor="let type of holderTypes" [value]="type.value" class="radio-button">
|
||||||
{{ type.label }}
|
{{ type.name }}
|
||||||
</mat-radio-button>
|
</mat-radio-button>
|
||||||
</mat-radio-group>
|
</mat-radio-group>
|
||||||
<mat-error *ngIf="depositForm.get('holderType')?.errors?.['required']">
|
<mat-error *ngIf="depositForm.get('holderType')?.errors?.['required']">
|
||||||
@ -147,6 +153,18 @@
|
|||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Rate %</mat-label>
|
||||||
|
<input matInput type="number" formControlName="rateInPercentage" required min="0" step="1">
|
||||||
|
<span class="percent-suffix" matSuffix>% </span>
|
||||||
|
<mat-error *ngIf="depositForm.get('rateInPercentage')?.errors?.['required']">
|
||||||
|
Rate % is required
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="depositForm.get('rateInPercentage')?.errors?.['min']">
|
||||||
|
Rate % must be positive
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field appearance="outline">
|
<mat-form-field appearance="outline">
|
||||||
<mat-label>Effective Date</mat-label>
|
<mat-label>Effective Date</mat-label>
|
||||||
<input matInput [matDatepicker]="picker" formControlName="effectiveDate" required>
|
<input matInput [matDatepicker]="picker" formControlName="effectiveDate" required>
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import { CommonService } from '../../core/services/common/common.service';
|
|||||||
import { NotificationService } from '../../core/services/common/notification.service';
|
import { NotificationService } from '../../core/services/common/notification.service';
|
||||||
import { SecurityDepositService } from '../../core/services/service-provider/security-deposit.service';
|
import { SecurityDepositService } from '../../core/services/service-provider/security-deposit.service';
|
||||||
import { finalize } from 'rxjs';
|
import { finalize } from 'rxjs';
|
||||||
|
import { HolderType } from '../../core/models/holder-type';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-security-deposit',
|
selector: 'app-security-deposit',
|
||||||
@ -26,7 +27,7 @@ export class SecurityDepositComponent implements OnInit {
|
|||||||
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||||
@ViewChild(MatSort) sort!: MatSort;
|
@ViewChild(MatSort) sort!: MatSort;
|
||||||
|
|
||||||
displayedColumns: string[] = ['holderType', 'uscibMember', 'specialCommodity', 'specialCountry', 'rate', 'effectiveDate', 'actions'];
|
displayedColumns: string[] = ['holderType', 'uscibMember', 'specialCommodity', 'specialCountry', 'rate', 'rateInPercentage', 'effectiveDate', 'actions'];
|
||||||
dataSource = new MatTableDataSource<any>();
|
dataSource = new MatTableDataSource<any>();
|
||||||
depositForm: FormGroup;
|
depositForm: FormGroup;
|
||||||
isEditing = false;
|
isEditing = false;
|
||||||
@ -43,18 +44,13 @@ export class SecurityDepositComponent implements OnInit {
|
|||||||
};
|
};
|
||||||
|
|
||||||
countries: Country[] = [];
|
countries: Country[] = [];
|
||||||
|
holderTypes: HolderType[] = [];
|
||||||
|
|
||||||
@Input() isEditMode = false;
|
@Input() isEditMode = false;
|
||||||
@Input() spid: number = 0;
|
@Input() spid: number = 0;
|
||||||
@Input() userPreferences!: UserPreferences;
|
@Input() userPreferences!: UserPreferences;
|
||||||
@Output() hasSecurityDeposits = new EventEmitter<boolean>();
|
@Output() hasSecurityDeposits = new EventEmitter<boolean>();
|
||||||
|
|
||||||
holderTypes = [
|
|
||||||
{ value: 'CORP', label: 'Corporation' },
|
|
||||||
{ value: 'INDIVIDUAL', label: 'Individual' },
|
|
||||||
{ value: 'GOVERNMENT', label: 'Government Agency' }
|
|
||||||
];
|
|
||||||
|
|
||||||
yesNoOptions = [
|
yesNoOptions = [
|
||||||
{ value: 'Y', label: 'Yes' },
|
{ value: 'Y', label: 'Yes' },
|
||||||
{ value: 'N', label: 'No' }
|
{ value: 'N', label: 'No' }
|
||||||
@ -73,6 +69,7 @@ export class SecurityDepositComponent implements OnInit {
|
|||||||
specialCommodity: [''],
|
specialCommodity: [''],
|
||||||
specialCountry: [''],
|
specialCountry: [''],
|
||||||
rate: [0, [Validators.required, Validators.min(0)]],
|
rate: [0, [Validators.required, Validators.min(0)]],
|
||||||
|
rateInPercentage: [0, [Validators.required, Validators.min(0)]],
|
||||||
effectiveDate: ['', Validators.required]
|
effectiveDate: ['', Validators.required]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -80,6 +77,7 @@ export class SecurityDepositComponent implements OnInit {
|
|||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.loadSecurityDeposits();
|
this.loadSecurityDeposits();
|
||||||
this.loadCountries();
|
this.loadCountries();
|
||||||
|
this.loadHolderTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
@ -129,6 +127,16 @@ export class SecurityDepositComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadHolderTypes(): void {
|
||||||
|
this.commonService.getHolderTypes().subscribe({
|
||||||
|
next: (holderTypes) => {
|
||||||
|
this.holderTypes = holderTypes;
|
||||||
|
},
|
||||||
|
error: (error) => {
|
||||||
|
console.error('Error loading holder types:', error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
// applyFilter(event: Event): void {
|
// applyFilter(event: Event): void {
|
||||||
// const filterValue = (event.target as HTMLInputElement).value;
|
// const filterValue = (event.target as HTMLInputElement).value;
|
||||||
// this.dataSource.filter = filterValue.trim().toLowerCase();
|
// this.dataSource.filter = filterValue.trim().toLowerCase();
|
||||||
@ -147,7 +155,7 @@ export class SecurityDepositComponent implements OnInit {
|
|||||||
uscibMember: 'N',
|
uscibMember: 'N',
|
||||||
specialCountry: '',
|
specialCountry: '',
|
||||||
});
|
});
|
||||||
this.depositForm.patchValue({ rate: 0 });
|
this.depositForm.patchValue({ rate: 0, rateInPercentage: 0 });
|
||||||
|
|
||||||
this.depositForm.get('holderType')?.enable();
|
this.depositForm.get('holderType')?.enable();
|
||||||
this.depositForm.get('uscibMember')?.enable();
|
this.depositForm.get('uscibMember')?.enable();
|
||||||
@ -165,6 +173,7 @@ export class SecurityDepositComponent implements OnInit {
|
|||||||
specialCommodity: deposit.specialCommodity,
|
specialCommodity: deposit.specialCommodity,
|
||||||
specialCountry: deposit.specialCountry,
|
specialCountry: deposit.specialCountry,
|
||||||
rate: deposit.rate,
|
rate: deposit.rate,
|
||||||
|
rateInPercentage: deposit.rateInPercentage,
|
||||||
effectiveDate: deposit.effectiveDate
|
effectiveDate: deposit.effectiveDate
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -251,7 +260,7 @@ export class SecurityDepositComponent implements OnInit {
|
|||||||
|
|
||||||
getHolderTypeLabel(value: string): string {
|
getHolderTypeLabel(value: string): string {
|
||||||
const type = this.holderTypes.find(t => t.value === value);
|
const type = this.holderTypes.find(t => t.value === value);
|
||||||
return type ? type.label : value;
|
return type ? type.name : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCountryName(code: string): string {
|
getCountryName(code: string): string {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user