Compare commits
No commits in common. "main" and "param-table" have entirely different histories.
main
...
param-tabl
@ -57,5 +57,3 @@ Angular CLI does not come with an end-to-end testing framework by default. You c
|
||||
## Additional Resources
|
||||
|
||||
For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
|
||||
|
||||
Test 6.
|
||||
32
angular.json
32
angular.json
@ -72,28 +72,6 @@
|
||||
"with": "src/environments/environment.development.ts"
|
||||
}
|
||||
]
|
||||
},
|
||||
"dev-1": {
|
||||
"optimization": false,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true,
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment-dev-1.ts"
|
||||
}
|
||||
]
|
||||
},
|
||||
"dev-2": {
|
||||
"optimization": false,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true,
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment-dev-2.ts"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production"
|
||||
@ -103,9 +81,7 @@
|
||||
"options": {
|
||||
"allowedHosts": [
|
||||
"localhost",
|
||||
"policy.alphaomegainfosys.com",
|
||||
"policy-1.alphaomegainfosys.com",
|
||||
"policy-2.alphaomegainfosys.com"
|
||||
"policy.alphaomegainfosys.com"
|
||||
]
|
||||
},
|
||||
"configurations": {
|
||||
@ -115,12 +91,6 @@
|
||||
"development": {
|
||||
"buildTarget": "carnet-portal-app:build:development",
|
||||
"port": 5173
|
||||
},
|
||||
"dev-1": {
|
||||
"buildTarget": "carnet-portal-app:build:dev-1"
|
||||
},
|
||||
"dev-2": {
|
||||
"buildTarget": "carnet-portal-app:build:dev-2"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
|
||||
@ -1,252 +0,0 @@
|
||||
/* Note: Color palettes are generated from primary: #607c7c, secondary: #9cb4b8 */
|
||||
html {
|
||||
/* COLOR SYSTEM VARIABLES */
|
||||
color-scheme: light;
|
||||
|
||||
/* Primary palette variables */
|
||||
--mat-sys-primary: light-dark(#607c7c, #afcccc);
|
||||
--mat-sys-on-primary: light-dark(#ffffff, #193535);
|
||||
--mat-sys-primary-container: light-dark(#ffffff, #304b4c);
|
||||
--mat-sys-on-primary-container: light-dark(#607c7c, #cae8e8);
|
||||
--mat-sys-inverse-primary: light-dark(#afcccc, #486363);
|
||||
--mat-sys-primary-fixed: light-dark(#cae8e8, #cae8e8);
|
||||
--mat-sys-primary-fixed-dim: light-dark(#afcccc, #afcccc);
|
||||
--mat-sys-on-primary-fixed: light-dark(#022020, #022020);
|
||||
--mat-sys-on-primary-fixed-variant: light-dark(#304b4c, #304b4c);
|
||||
|
||||
/* Secondary palette variables */
|
||||
--mat-sys-secondary: light-dark(#607c7c, #b3cbcf);
|
||||
--mat-sys-on-secondary: light-dark(#ffffff, #1d3437);
|
||||
--mat-sys-secondary-container: light-dark(#607c7c, #344a4e);
|
||||
--mat-sys-on-secondary-container: light-dark(#ffffff, #cee7eb);
|
||||
--mat-sys-secondary-fixed: light-dark(#cee7eb, #cee7eb);
|
||||
--mat-sys-secondary-fixed-dim: light-dark(#b3cbcf, #b3cbcf);
|
||||
--mat-sys-on-secondary-fixed: light-dark(#071f22, #071f22);
|
||||
--mat-sys-on-secondary-fixed-variant: light-dark(#344a4e, #344a4e);
|
||||
|
||||
/* Tertiary palette variables */
|
||||
--mat-sys-tertiary: light-dark(#635b72, #cdc2dd);
|
||||
--mat-sys-on-tertiary: light-dark(#ffffff, #342d42);
|
||||
--mat-sys-tertiary-container: light-dark(#e9def9, #4b4359);
|
||||
--mat-sys-on-tertiary-container: light-dark(#1f182c, #e9def9);
|
||||
--mat-sys-tertiary-fixed: light-dark(#e9def9, #e9def9);
|
||||
--mat-sys-tertiary-fixed-dim: light-dark(#cdc2dd, #cdc2dd);
|
||||
--mat-sys-on-tertiary-fixed: light-dark(#1f182c, #1f182c);
|
||||
--mat-sys-on-tertiary-fixed-variant: light-dark(#4b4359, #4b4359);
|
||||
|
||||
/* Neutral palette variables */
|
||||
--mat-sys-background: light-dark(#faf9f8, #121414);
|
||||
--mat-sys-on-background: light-dark(#1a1c1c, #e3e2e2);
|
||||
--mat-sys-surface: light-dark(#faf9f8, #121414);
|
||||
--mat-sys-surface-dim: light-dark(#dadad9, #121414);
|
||||
--mat-sys-surface-bright: light-dark(#faf9f8, #383939);
|
||||
--mat-sys-surface-container-low: light-dark(#f4f3f3, #1a1c1c);
|
||||
--mat-sys-surface-container-lowest: light-dark(#ffffff, #0d0e0e);
|
||||
--mat-sys-surface-container: light-dark(#eeeeed, #1e2020);
|
||||
--mat-sys-surface-container-high: light-dark(#e9e8e7, #292a2a);
|
||||
--mat-sys-surface-container-highest: light-dark(#e3e2e2, #343535);
|
||||
--mat-sys-on-surface: light-dark(#1a1c1c, #e3e2e2);
|
||||
--mat-sys-shadow: light-dark(#000000, #000000);
|
||||
--mat-sys-scrim: light-dark(#000000, #000000);
|
||||
--mat-sys-surface-tint: light-dark(#486363, #afcccc);
|
||||
--mat-sys-inverse-surface: light-dark(#2f3130, #e3e2e2);
|
||||
--mat-sys-inverse-on-surface: light-dark(#f1f0f0, #2f3130);
|
||||
--mat-sys-outline: light-dark(#727878, #8b9292);
|
||||
--mat-sys-outline-variant: light-dark(#c1c8c7, #414848);
|
||||
--mat-sys-neutral10: light-dark(#1a1c1c, #1a1c1c);
|
||||
/* Variable used for the form field native select option text color */
|
||||
|
||||
/* Error palette variables */
|
||||
--mat-sys-error: light-dark(#ba1a1a, #ffb4ab);
|
||||
--mat-sys-on-error: light-dark(#ffffff, #690005);
|
||||
--mat-sys-error-container: light-dark(#ffdad6, #93000a);
|
||||
--mat-sys-on-error-container: light-dark(#410002, #ffdad6);
|
||||
|
||||
/* Neutral variant palette variables */
|
||||
--mat-sys-surface-variant: light-dark(#dde4e3, #414848);
|
||||
--mat-sys-on-surface-variant: light-dark(#414848, #c1c8c7);
|
||||
--mat-sys-neutral-variant20: light-dark(#2b3232, #2b3232);
|
||||
/* Variable used for the sidenav scrim (container background shadow when opened) */
|
||||
|
||||
/* TYPOGRAPHY SYSTEM VARIABLES */
|
||||
|
||||
/* Typography variables. Only used in the different typescale system variables. */
|
||||
--mat-sys-brand-font-family: Roboto;
|
||||
/* The font-family to use for brand text. */
|
||||
--mat-sys-plain-font-family: Roboto;
|
||||
/* The font-family to use for plain text. */
|
||||
--mat-sys-bold-font-weight: 700;
|
||||
/* The font-weight to use for bold text. */
|
||||
--mat-sys-medium-font-weight: 500;
|
||||
/* The font-weight to use for medium text. */
|
||||
--mat-sys-regular-font-weight: 400;
|
||||
/* The font-weight to use for regular text. */
|
||||
|
||||
/* Typescale variables. */
|
||||
/* Warning: Risk of reduced fidelity from using the composite typography tokens (ex. --mat-sys-body-large) since
|
||||
tracking cannot be represented in the "font" property shorthand. Consider using the discrete properties instead. */
|
||||
--mat-sys-body-large: var(--mat-sys-body-large-weight) var(--mat-sys-body-large-size) / var(--mat-sys-body-large-line-height) var(--mat-sys-body-large-font);
|
||||
--mat-sys-body-large-font: var(--mat-sys-plain-font-family);
|
||||
--mat-sys-body-large-line-height: 1.5rem;
|
||||
--mat-sys-body-large-size: 1rem;
|
||||
--mat-sys-body-large-tracking: 0.031rem;
|
||||
--mat-sys-body-large-weight: var(--mat-sys-regular-font-weight);
|
||||
|
||||
/* Body medium typescale */
|
||||
--mat-sys-body-medium: var(--mat-sys-body-medium-weight) var(--mat-sys-body-medium-size) / var(--mat-sys-body-medium-line-height) var(--mat-sys-body-medium-font);
|
||||
--mat-sys-body-medium-font: var(--mat-sys-plain-font-family);
|
||||
--mat-sys-body-medium-line-height: 1.25rem;
|
||||
--mat-sys-body-medium-size: 0.875rem;
|
||||
--mat-sys-body-medium-tracking: 0.016rem;
|
||||
--mat-sys-body-medium-weight: var(--mat-sys-regular-font-weight);
|
||||
|
||||
/* Body small typescale */
|
||||
--mat-sys-body-small: var(--mat-sys-body-small-weight) var(--mat-sys-body-small-size) / var(--mat-sys-body-small-line-height) var(--mat-sys-body-small-font);
|
||||
--mat-sys-body-small-font: var(--mat-sys-plain-font-family);
|
||||
--mat-sys-body-small-line-height: 1rem;
|
||||
--mat-sys-body-small-size: 0.75rem;
|
||||
--mat-sys-body-small-tracking: 0.025rem;
|
||||
--mat-sys-body-small-weight: var(--mat-sys-regular-font-weight);
|
||||
|
||||
/* Display large typescale */
|
||||
--mat-sys-display-large: var(--mat-sys-display-large-weight) var(--mat-sys-display-large-size) / var(--mat-sys-display-large-line-height) var(--mat-sys-display-large-font);
|
||||
--mat-sys-display-large-font: var(--mat-sys-brand-font-family);
|
||||
--mat-sys-display-large-line-height: 4rem;
|
||||
--mat-sys-display-large-size: 3.562rem;
|
||||
--mat-sys-display-large-tracking: -0.016rem;
|
||||
--mat-sys-display-large-weight: var(--mat-sys-regular-font-weight);
|
||||
|
||||
/* Display medium typescale */
|
||||
--mat-sys-display-medium: var(--mat-sys-display-medium-weight) var(--mat-sys-display-medium-size) / var(--mat-sys-display-medium-line-height) var(--mat-sys-display-medium-font);
|
||||
--mat-sys-display-medium-font: var(--mat-sys-brand-font-family);
|
||||
--mat-sys-display-medium-line-height: 3.25rem;
|
||||
--mat-sys-display-medium-size: 2.812rem;
|
||||
--mat-sys-display-medium-tracking: 0;
|
||||
--mat-sys-display-medium-weight: var(--mat-sys-regular-font-weight);
|
||||
|
||||
/* Display small typescale */
|
||||
--mat-sys-display-small: var(--mat-sys-display-small-weight) var(--mat-sys-display-small-size) / var(--mat-sys-display-small-line-height) var(--mat-sys-display-small-font);
|
||||
--mat-sys-display-small-font: var(--mat-sys-brand-font-family);
|
||||
--mat-sys-display-small-line-height: 2.75rem;
|
||||
--mat-sys-display-small-size: 2.25rem;
|
||||
--mat-sys-display-small-tracking: 0;
|
||||
--mat-sys-display-small-weight: var(--mat-sys-regular-font-weight);
|
||||
|
||||
/* Headline large typescale */
|
||||
--mat-sys-headline-large: var(--mat-sys-headline-large-weight) var(--mat-sys-headline-large-size) / var(--mat-sys-headline-large-line-height) var(--mat-sys-headline-large-font);
|
||||
--mat-sys-headline-large-font: var(--mat-sys-brand-font-family);
|
||||
--mat-sys-headline-large-line-height: 2.5rem;
|
||||
--mat-sys-headline-large-size: 2rem;
|
||||
--mat-sys-headline-large-tracking: 0;
|
||||
--mat-sys-headline-large-weight: var(--mat-sys-regular-font-weight);
|
||||
|
||||
/* Headline medium typescale */
|
||||
--mat-sys-headline-medium: var(--mat-sys-headline-medium-weight) var(--mat-sys-headline-medium-size) / var(--mat-sys-headline-medium-line-height) var(--mat-sys-headline-medium-font);
|
||||
--mat-sys-headline-medium-font: var(--mat-sys-brand-font-family);
|
||||
--mat-sys-headline-medium-line-height: 2.25rem;
|
||||
--mat-sys-headline-medium-size: 1.75rem;
|
||||
--mat-sys-headline-medium-tracking: 0;
|
||||
--mat-sys-headline-medium-weight: var(--mat-sys-regular-font-weight);
|
||||
|
||||
/* Headline small typescale */
|
||||
--mat-sys-headline-small: var(--mat-sys-headline-small-weight) var(--mat-sys-headline-small-size) / var(--mat-sys-headline-small-line-height) var(--mat-sys-headline-small-font);
|
||||
--mat-sys-headline-small-font: var(--mat-sys-brand-font-family);
|
||||
--mat-sys-headline-small-line-height: 2rem;
|
||||
--mat-sys-headline-small-size: 1.5rem;
|
||||
--mat-sys-headline-small-tracking: 0;
|
||||
--mat-sys-headline-small-weight: var(--mat-sys-regular-font-weight);
|
||||
|
||||
/* Label large typescale */
|
||||
--mat-sys-label-large: var(--mat-sys-label-large-weight) var(--mat-sys-label-large-size) / var(--mat-sys-label-large-line-height) var(--mat-sys-label-large-font);
|
||||
--mat-sys-label-large-font: var(--mat-sys-plain-font-family);
|
||||
--mat-sys-label-large-line-height: 1.25rem;
|
||||
--mat-sys-label-large-size: 0.875rem;
|
||||
--mat-sys-label-large-tracking: 0.006rem;
|
||||
--mat-sys-label-large-weight: var(--mat-sys-medium-font-weight);
|
||||
--mat-sys-label-large-weight-prominent: var(--mat-sys-bold-font-weight);
|
||||
|
||||
/* Label medium typescale */
|
||||
--mat-sys-label-medium: var(--mat-sys-label-medium-weight) var(--mat-sys-label-medium-size) / var(--mat-sys-label-medium-line-height) var(--mat-sys-label-medium-font);
|
||||
--mat-sys-label-medium-font: var(--mat-sys-plain-font-family);
|
||||
--mat-sys-label-medium-line-height: 1rem;
|
||||
--mat-sys-label-medium-size: 0.75rem;
|
||||
--mat-sys-label-medium-tracking: 0.031rem;
|
||||
--mat-sys-label-medium-weight: var(--mat-sys-medium-font-weight);
|
||||
--mat-sys-label-medium-weight-prominent: var(--mat-sys-bold-font-weight);
|
||||
|
||||
/* Label small typescale */
|
||||
--mat-sys-label-small: var(--mat-sys-label-small-weight) var(--mat-sys-label-small-size) / var(--mat-sys-label-small-line-height) var(--mat-sys-label-small-font);
|
||||
--mat-sys-label-small-font: var(--mat-sys-plain-font-family);
|
||||
--mat-sys-label-small-line-height: 1rem;
|
||||
--mat-sys-label-small-size: 0.688rem;
|
||||
--mat-sys-label-small-tracking: 0.031rem;
|
||||
--mat-sys-label-small-weight: var(--mat-sys-medium-font-weight);
|
||||
|
||||
/* Title large typescale */
|
||||
--mat-sys-title-large: var(--mat-sys-title-large-weight) var(--mat-sys-title-large-size) / var(--mat-sys-title-large-line-height) var(--mat-sys-title-large-font);
|
||||
--mat-sys-title-large-font: var(--mat-sys-brand-font-family);
|
||||
--mat-sys-title-large-line-height: 1.75rem;
|
||||
--mat-sys-title-large-size: 1.375rem;
|
||||
--mat-sys-title-large-tracking: 0;
|
||||
--mat-sys-title-large-weight: var(--mat-sys-regular-font-weight);
|
||||
|
||||
/* Title medium typescale */
|
||||
--mat-sys-title-medium: var(--mat-sys-title-medium-weight) var(--mat-sys-title-medium-size) / var(--mat-sys-title-medium-line-height) var(--mat-sys-title-medium-font);
|
||||
--mat-sys-title-medium-font: var(--mat-sys-plain-font-family);
|
||||
--mat-sys-title-medium-line-height: 1.5rem;
|
||||
--mat-sys-title-medium-size: 1rem;
|
||||
--mat-sys-title-medium-tracking: 0.009rem;
|
||||
--mat-sys-title-medium-weight: var(--mat-sys-medium-font-weight);
|
||||
|
||||
/* Title small typescale */
|
||||
--mat-sys-title-small: var(--mat-sys-title-small-weight) var(--mat-sys-title-small-size) / var(--mat-sys-title-small-line-height) var(--mat-sys-title-small-font);
|
||||
--mat-sys-title-small-font: var(--mat-sys-plain-font-family);
|
||||
--mat-sys-title-small-line-height: 1.25rem;
|
||||
--mat-sys-title-small-size: 0.875rem;
|
||||
--mat-sys-title-small-tracking: 0.006rem;
|
||||
--mat-sys-title-small-weight: var(--mat-sys-medium-font-weight);
|
||||
|
||||
/* ELEVATION SYSTEM VARIABLES */
|
||||
|
||||
/* Box shadow colors. Only used in the elevation level system variables. */
|
||||
--mat-sys-umbra-color: color-mix(in srgb, var(--mat-sys-shadow), transparent 80%);
|
||||
--mat-sys-penumbra-color: color-mix(in srgb, var(--mat-sys-shadow), transparent 86%);
|
||||
--mat-sys-ambient-color: color-mix(in srgb, var(--mat-sys-shadow), transparent 88%);
|
||||
|
||||
/* Elevation level system variables. These are used as the value for box-shadow CSS property. */
|
||||
--mat-sys-level0: 0px 0px 0px 0px var(--mat-sys-umbra-color), 0px 0px 0px 0px var(--mat-sys-penumbra-color), 0px 0px 0px 0px var(--mat-sys-ambient-color);
|
||||
--mat-sys-level1: 0px 2px 1px -1px var(--mat-sys-umbra-color), 0px 1px 1px 0px var(--mat-sys-penumbra-color), 0px 1px 3px 0px var(--mat-sys-ambient-color);
|
||||
--mat-sys-level2: 0px 3px 3px -2px var(--mat-sys-umbra-color), 0px 3px 4px 0px var(--mat-sys-penumbra-color), 0px 1px 8px 0px var(--mat-sys-ambient-color);
|
||||
--mat-sys-level3: 0px 3px 5px -1px var(--mat-sys-umbra-color), 0px 6px 10px 0px var(--mat-sys-penumbra-color), 0px 1px 18px 0px var(--mat-sys-ambient-color);
|
||||
--mat-sys-level4: 0px 5px 5px -3px var(--mat-sys-umbra-color), 0px 8px 10px 1px var(--mat-sys-penumbra-color), 0px 3px 14px 2px var(--mat-sys-ambient-color);
|
||||
--mat-sys-level5: 0px 7px 8px -4px var(--mat-sys-umbra-color), 0px 12px 17px 2px var(--mat-sys-penumbra-color), 0px 5px 22px 4px var(--mat-sys-ambient-color);
|
||||
|
||||
/* SHAPE SYSTEM VARIABLES */
|
||||
--mat-sys-corner-extra-large: 28px;
|
||||
--mat-sys-corner-extra-large-top: 28px 28px 0 0;
|
||||
--mat-sys-corner-extra-small: 4px;
|
||||
--mat-sys-corner-extra-small-top: 4px 4px 0 0;
|
||||
--mat-sys-corner-full: 9999px;
|
||||
--mat-sys-corner-large: 16px;
|
||||
--mat-sys-corner-large-end: 0 16px 16px 0;
|
||||
--mat-sys-corner-large-start: 16px 0 0 16px;
|
||||
--mat-sys-corner-large-top: 16px 16px 0 0;
|
||||
--mat-sys-corner-medium: 12px;
|
||||
--mat-sys-corner-none: 0;
|
||||
--mat-sys-corner-small: 8px;
|
||||
|
||||
/* STATE SYSTEM VARIABLES */
|
||||
--mat-sys-dragged-state-layer-opacity: 0.16;
|
||||
--mat-sys-focus-state-layer-opacity: 0.12;
|
||||
--mat-sys-hover-state-layer-opacity: 0.08;
|
||||
--mat-sys-pressed-state-layer-opacity: 0.12;
|
||||
|
||||
/* CUSTOM BUTTON COLORS */
|
||||
--custom-button-color: #ffffff;
|
||||
--custom-button-background-color: #627f9a;
|
||||
--custom-hover-color: #384857;
|
||||
|
||||
/* CUSTOM NAV COLORS */
|
||||
--custom-nav-color: #ffffff;
|
||||
--custom-nav-background-color: #607c7c;
|
||||
}
|
||||
@ -1,14 +1,14 @@
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
import { RouterOutlet } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FooterComponent } from './common/footer/footer.component';
|
||||
import { SecuredHeaderComponent } from './common/secured-header/secured-header.component';
|
||||
import { UserService } from './core/services/common/user.service';
|
||||
import { FooterComponent } from './common/footer/footer.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
imports: [RouterOutlet, FooterComponent, CommonModule, SecuredHeaderComponent],
|
||||
imports: [RouterOutlet, SecuredHeaderComponent, FooterComponent, CommonModule],
|
||||
templateUrl: './app.component.html',
|
||||
styleUrl: './app.component.scss'
|
||||
})
|
||||
@ -17,7 +17,8 @@ export class AppComponent {
|
||||
isUserLoggedIn = false;
|
||||
private userSubscription!: Subscription;
|
||||
|
||||
private userService = inject(UserService);
|
||||
constructor(private userService: UserService
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
|
||||
|
||||
@ -10,7 +10,6 @@ import {
|
||||
withDefaultRegisterables,
|
||||
} from 'ng2-charts';
|
||||
import { AuthInterceptor } from './core/interceptors/auth.interceptor';
|
||||
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
|
||||
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
@ -21,7 +20,5 @@ export const appConfig: ApplicationConfig = {
|
||||
provideHttpClient(),
|
||||
provideHttpClient(withInterceptorsFromDi()),
|
||||
provideCharts(withDefaultRegisterables()),
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
|
||||
{ provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: { subscriptSizing: 'dynamic' } }
|
||||
]
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },]
|
||||
};
|
||||
|
||||
@ -11,19 +11,13 @@ import { ForgotPasswordComponent } from './forgot-password/forgot-password.compo
|
||||
import { ParamTableComponent } from './param/table/param-table.component';
|
||||
import { ManageTableRecordComponent } from './param/manage-table-record/manage-table-record.component';
|
||||
import { ManageParamRecordComponent } from './param/manage-param-record/manage-param-record.component';
|
||||
import { RegionComponent } from './region/region.component';
|
||||
import { ManageFeeComponent } from './fees/manage/manage-fee.component';
|
||||
import { ManageCountryComponent } from './param/manage-country/manage-country.component';
|
||||
|
||||
export const routes: Routes = [
|
||||
{ path: 'login', component: LoginComponent },
|
||||
{ path: 'register', component: RegisterComponent },
|
||||
{ path: 'forgot-password', component: ForgotPasswordComponent },
|
||||
{ path: 'table-record', component: ManageTableRecordComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'param-record/:id', component: ManageParamRecordComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'country-messages', component: ManageCountryComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'region', component: RegionComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'fees', component: ManageFeeComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'table-record', component: ManageTableRecordComponent },
|
||||
{ path: 'param-record/:id', component: ManageParamRecordComponent },
|
||||
{ path: 'usersettings', component: UserSettingsComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'home', component: HomeComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'service-provider/:id', component: EditServiceProviderComponent, canActivate: [AuthGuard] },
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<footer class="footer" [ngClass]="{'general': !isUserLoggedIn}">
|
||||
<footer class="footer">
|
||||
<div class="footer-content">
|
||||
<div class="footer-links">
|
||||
<a href="#">Privacy Policy</a>
|
||||
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
|
||||
<div class="copyright">
|
||||
© {{ currentYear }} Alpha Omega Infosys. All rights reserved.
|
||||
© {{ currentYear }} USCIB Carnet Portal. All rights reserved.
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
@ -1,8 +1,11 @@
|
||||
@use 'colors' as colors;
|
||||
|
||||
.footer {
|
||||
color: var(--mat-sys-on-primary);
|
||||
background: var(--mat-sys-primary);
|
||||
background-color: colors.$background-header;
|
||||
padding: 8px;
|
||||
border-top: 1px solid var(--mat-sys-outline-variant);
|
||||
border-top: 1px solid colors.$divider-color;
|
||||
backdrop-filter: blur(10px);
|
||||
background-color: rgba(colors.$background-header, 0.9);
|
||||
|
||||
/* Fixed footer styles */
|
||||
position: fixed;
|
||||
@ -19,7 +22,6 @@
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: var(--mat-sys-primary);
|
||||
}
|
||||
|
||||
.footer-links {
|
||||
@ -27,46 +29,22 @@
|
||||
gap: 24px;
|
||||
|
||||
a {
|
||||
color: var(--mat-sys-on-primary);
|
||||
background: var(--mat-sys-primary);
|
||||
color: colors.$text-secondary;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: scale(103%);
|
||||
color: colors.$primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copyright {
|
||||
color: colors.$text-secondary;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
/* footer styles - not logged in users - not applicable for this site*/
|
||||
// .footer.general {
|
||||
// color: #000000;
|
||||
// background: #ffffff;
|
||||
|
||||
// .footer-content {
|
||||
// max-width: 1200px;
|
||||
// margin: 0 auto;
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// align-items: center;
|
||||
// gap: 8px;
|
||||
// background: #ffffff;
|
||||
// }
|
||||
|
||||
// .footer-links {
|
||||
// a {
|
||||
// color: #000000;
|
||||
// background: #ffffff;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.footer {
|
||||
padding: 16px;
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
import { AngularMaterialModule } from '../../shared/module/angular-material.module';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'app-footer',
|
||||
imports: [AngularMaterialModule, CommonModule],
|
||||
imports: [AngularMaterialModule],
|
||||
templateUrl: './footer.component.html',
|
||||
styleUrl: './footer.component.scss'
|
||||
})
|
||||
export class FooterComponent {
|
||||
currentYear = new Date().getFullYear();
|
||||
@Input() isUserLoggedIn = false;
|
||||
}
|
||||
@ -5,14 +5,11 @@
|
||||
</div>
|
||||
|
||||
<div class="navbar-menu">
|
||||
<button mat-button (click)="navigateTo('home')">Home</button>
|
||||
<button mat-button [matMenuTriggerFor]="configurations">Configurations</button>
|
||||
<mat-menu #configurations="matMenu">
|
||||
<button mat-menu-item (click)="navigateTo('table-record')">Table Records</button>
|
||||
<button mat-menu-item (click)="navigateTo('country-messages')">Country Messages</button>
|
||||
<button mat-menu-item (click)="navigateTo('region')">Manage Regions</button>
|
||||
<button mat-menu-item (click)="navigateTo('fees')">Manage Fees</button>
|
||||
</mat-menu>
|
||||
<a class="nav-link" (click)="navigateTo('/home')">Home</a>
|
||||
<a class="nav-link" (click)="navigateTo('/manageusers')">Users</a>
|
||||
<a class="nav-link" (click)="navigateTo('/regions')">Regions</a>
|
||||
<a class="nav-link" (click)="navigateTo('/table-record')">Parameters</a>
|
||||
|
||||
<div class="profile-container">
|
||||
<button mat-icon-button (click)="toggleProfileMenu()" class="profile-button">
|
||||
<mat-icon>account_circle</mat-icon>
|
||||
@ -26,7 +23,7 @@
|
||||
|
||||
<button mat-menu-item (click)="navigateTo('/usersettings')">
|
||||
<mat-icon>settings</mat-icon>
|
||||
<span>User Preferences</span>
|
||||
<span>User Settings</span>
|
||||
</button>
|
||||
|
||||
<button mat-menu-item (click)="logout()">
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
@use 'colors' as colors;
|
||||
|
||||
.navbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 24px;
|
||||
height: 64px;
|
||||
color: var(--custom-nav-color);
|
||||
background: var(--custom-nav-background-color);
|
||||
border-bottom: 1px solid var(--mat-sys-outline-variant);
|
||||
background-color: colors.$primary-color;
|
||||
color: white;
|
||||
box-shadow: var(--mat-sys-level2);
|
||||
position: relative;
|
||||
z-index: 100; // Higher than footer's z-index
|
||||
|
||||
@ -31,70 +33,46 @@
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
|
||||
button {
|
||||
color: var(--custom-nav-color);
|
||||
background-color: var(--custom-nav-background-color);
|
||||
.nav-link {
|
||||
cursor: pointer;
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
color: var(--custom-nav-background-color);
|
||||
background-color: var(--custom-nav-color);
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.mat-mdc-button:hover>.mat-mdc-button-persistent-ripple::before {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
// .nav-link {
|
||||
// cursor: pointer;
|
||||
// padding: 8px 12px;
|
||||
// border-radius: 4px;
|
||||
// transition: background-color 0.3s ease;
|
||||
|
||||
// &:hover {
|
||||
// background-color: var(--mat-sys-secondary-container);
|
||||
// box-shadow: var(--mat-sys-level1);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
.profile-container {
|
||||
position: relative;
|
||||
|
||||
.profile-button {
|
||||
color: var(--custom-nav-background-color);
|
||||
background-color: var(--custom-nav-color);
|
||||
|
||||
&:hover {
|
||||
color: var(--custom-nav-color);
|
||||
background-color: var(--custom-nav-background-color);
|
||||
}
|
||||
color: white;
|
||||
}
|
||||
|
||||
.profile-menu {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 48px;
|
||||
color: var(--mat-sys-on-primary-container);
|
||||
background-color: var(--mat-sys-primary-container);
|
||||
background-color: white;
|
||||
border-radius: 4px;
|
||||
box-shadow: var(--mat-sys-level3);
|
||||
min-width: 200px;
|
||||
overflow: hidden;
|
||||
z-index: 101;
|
||||
font-size: 0.875rem;
|
||||
|
||||
.profile-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
color: var(--mat-sys-on-primary-container);
|
||||
background-color: var(--mat-sys-primary-container);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
||||
border-bottom: 1px solid colors.$divider-color;
|
||||
color: colors.$text-primary;
|
||||
|
||||
mat-icon {
|
||||
color: var(--mat-sys-on-primary-container);
|
||||
color: colors.$text-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,30 +82,18 @@
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 16px;
|
||||
color: colors.$text-primary;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: var(--mat-sys-on-primary-container);
|
||||
background-color: var(--mat-sys-primary-container);
|
||||
|
||||
// mat-icon {
|
||||
// color: var(--mat-sys-on-primary-container);
|
||||
// }
|
||||
|
||||
&:hover {
|
||||
color: var(--mat-sys-on-primary);
|
||||
background-color: var(--mat-sys-primary);
|
||||
mat-icon {
|
||||
color: colors.$text-secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mat-mdc-menu-item:not([disabled]):hover {
|
||||
color: var(--mat-sys-on-primary);
|
||||
background-color: var(--mat-sys-primary);
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.navbar {
|
||||
padding: 0 12px;
|
||||
|
||||
@ -4,7 +4,6 @@ import { AngularMaterialModule } from '../../shared/module/angular-material.modu
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { AuthService } from '../../core/services/common/auth.service';
|
||||
import { NavigationService } from '../../core/services/common/navigation.service';
|
||||
import { ThemeService } from '../../core/services/theme.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-secured-header',
|
||||
@ -19,11 +18,9 @@ export class SecuredHeaderComponent implements OnInit {
|
||||
private userService = inject(UserService);
|
||||
private authService = inject(AuthService);
|
||||
private navigationService = inject(NavigationService);
|
||||
private themeService = inject(ThemeService);
|
||||
|
||||
ngOnInit(): void {
|
||||
this.userEmail = this.userService.getSafeUser();
|
||||
this.themeService.setTheme('default');
|
||||
}
|
||||
|
||||
toggleProfileMenu(): void {
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
export interface ContactTitle {
|
||||
name: string;
|
||||
id: string;
|
||||
value: string;
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
export interface CargoRate {
|
||||
id: number,
|
||||
spid: number,
|
||||
startSets: number,
|
||||
endSets: number,
|
||||
carnetType: string,
|
||||
effectiveDate: Date,
|
||||
rate: number,
|
||||
dateCreated?: Date | null;
|
||||
createdBy?: string | null;
|
||||
expiredDate?: Date | null;
|
||||
expired?: boolean;
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
export interface HolderType {
|
||||
name: string;
|
||||
id: string;
|
||||
value: string;
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
import { ParamProperties } from "./parameters";
|
||||
|
||||
export interface CountryMessage extends ParamProperties {
|
||||
countryMessage: string | null;
|
||||
isInactive: boolean;
|
||||
}
|
||||
@ -5,18 +5,18 @@ export interface ParamProperties {
|
||||
paramType: string;
|
||||
paramDesc: string;
|
||||
paramValue: string;
|
||||
addlParamValue1?: string | null;
|
||||
addlParamValue2?: string | null;
|
||||
addlParamValue3?: string | null;
|
||||
addlParamValue4?: string | null;
|
||||
addlParamValue5?: string | null;
|
||||
addlParamValue1: string | null;
|
||||
addlParamValue2: string | null;
|
||||
addlParamValue3: string | null;
|
||||
addlParamValue4: string | null;
|
||||
addlParamValue5: string | null;
|
||||
sortSeq?: number;
|
||||
inactiveCodeFlag?: 'Y' | 'N' | null;
|
||||
inactiveDate?: string | null;
|
||||
createdBy?: string;
|
||||
dateCreated?: string;
|
||||
lastUpdatedBy?: string | null;
|
||||
lastUpdatedDate?: string | null;
|
||||
errorMesg?: string | null;
|
||||
inactiveCodeFlag: 'Y' | 'N' | null;
|
||||
inactiveDate: string | null;
|
||||
createdBy: string;
|
||||
dateCreated: string;
|
||||
lastUpdatedBy: string | null;
|
||||
lastUpdatedDate: string | null;
|
||||
errorMesg: string | null;
|
||||
userId?: string;
|
||||
}
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
export interface Region {
|
||||
id: number;
|
||||
value: string;
|
||||
name: string;
|
||||
}
|
||||
@ -7,6 +7,4 @@ export interface BasicFee {
|
||||
spid?: number;
|
||||
dateCreated?: Date | null;
|
||||
createdBy?: string | null;
|
||||
expiredDate?: Date | null;
|
||||
expired?: boolean;
|
||||
}
|
||||
@ -6,6 +6,4 @@ export interface CarnetFee {
|
||||
spid: number;
|
||||
dateCreated?: Date | null;
|
||||
createdBy?: string | null;
|
||||
expiredDate?: Date | null;
|
||||
expired?: boolean;
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
export interface ContactLogin {
|
||||
spid: number;
|
||||
emailAddress: string;
|
||||
}
|
||||
@ -16,5 +16,4 @@ export interface Contact {
|
||||
lastUpdatedDate?: Date | null;
|
||||
isInactive?: boolean | null;
|
||||
inactivatedDate?: Date | null;
|
||||
hasLogin?: boolean | null;
|
||||
}
|
||||
|
||||
@ -7,6 +7,4 @@ export interface ContinuationSheetFee {
|
||||
carnetType: string;
|
||||
dateCreated?: Date | null;
|
||||
createdBy?: string | null;
|
||||
expiredDate?: Date | null;
|
||||
expired?: boolean;
|
||||
}
|
||||
@ -9,6 +9,4 @@ export interface CounterfoilFee {
|
||||
rate: number,
|
||||
dateCreated?: Date | null;
|
||||
createdBy?: string | null;
|
||||
expiredDate?: Date | null;
|
||||
expired?: boolean;
|
||||
}
|
||||
@ -9,6 +9,4 @@ export interface ExpeditedFee {
|
||||
effectiveDate: Date;
|
||||
dateCreated?: Date | null;
|
||||
createdBy?: string | null;
|
||||
expiredDate?: Date | null;
|
||||
expired?: boolean;
|
||||
}
|
||||
@ -1,15 +1,12 @@
|
||||
export interface SecurityDeposit {
|
||||
securityDepositId: number;
|
||||
holderType: string;
|
||||
uscibMember: string;
|
||||
uscibMember: boolean;
|
||||
specialCommodity: string;
|
||||
specialCountry: string;
|
||||
rate: number;
|
||||
rateType: string;
|
||||
effectiveDate: Date;
|
||||
spid: number;
|
||||
dateCreated?: Date | null;
|
||||
createdBy?: string | null;
|
||||
expiredDate?: Date | null;
|
||||
expired?: boolean;
|
||||
}
|
||||
@ -17,5 +17,4 @@ export interface UserDetail {
|
||||
urlKey: string;
|
||||
logoName: string;
|
||||
themeName: string;
|
||||
serviceProviderName: string;
|
||||
}
|
||||
@ -36,12 +36,7 @@ export class ApiErrorHandlerService {
|
||||
return this.genericErrorMessage;
|
||||
}
|
||||
|
||||
// slice off the last pipe character only if the last character is a pipe
|
||||
if (messageString.endsWith('|')) {
|
||||
return messageString.slice(0, -1);
|
||||
}
|
||||
|
||||
return messageString;
|
||||
// .split('|')
|
||||
// .map(msg => msg.trim())
|
||||
// .filter(msg => msg.length > 0);
|
||||
|
||||
@ -13,8 +13,6 @@ import { ApiErrorHandlerService } from './api-error-handler.service';
|
||||
})
|
||||
export class AuthService {
|
||||
private apiUrl = environment.apiUrl;
|
||||
private applicationName = environment.appType;
|
||||
private apiDb = environment.apiDb;
|
||||
|
||||
private http = inject(HttpClient);
|
||||
private userService = inject(UserService);
|
||||
@ -24,16 +22,16 @@ export class AuthService {
|
||||
private errorHandler = inject(ApiErrorHandlerService);
|
||||
|
||||
login(username: string, password: string): Observable<any> {
|
||||
return this.http.post(`${this.apiUrl}/${this.apiDb}/login`, { p_emailaddr: username, p_password: password, P_APPLICATIONNAME: this.applicationName });
|
||||
return this.http.post(`${this.apiUrl}/login`, { p_emailaddr: username, p_password: password });
|
||||
}
|
||||
|
||||
refreshToken(): Observable<any> {
|
||||
return this.http.get(`${this.apiUrl}/${this.apiDb}/refresh-tokens`, {});
|
||||
return this.http.get(`${this.apiUrl}/refresh-tokens`, {});
|
||||
}
|
||||
|
||||
logout(): void {
|
||||
if (this.userService.isLoggedIn()) {
|
||||
this.http.post(`${this.apiUrl}/${this.apiDb}/logout`, {}).subscribe({
|
||||
this.http.post(`${this.apiUrl}/logout`, {}).subscribe({
|
||||
next: (response) => {
|
||||
this.userService.clearUser();
|
||||
this.storageService.clear();
|
||||
@ -51,7 +49,7 @@ export class AuthService {
|
||||
register(email: string, password: string): Observable<any> {
|
||||
|
||||
return this.http.post(
|
||||
`${this.apiUrl}/${this.apiDb}/register`,
|
||||
`${this.apiUrl}/register`,
|
||||
{ P_EMAILADDR: email, P_PASSWORD: password }
|
||||
);
|
||||
}
|
||||
@ -64,7 +62,7 @@ export class AuthService {
|
||||
}
|
||||
|
||||
return this.http.put(
|
||||
`${this.apiUrl}/${this.apiDb}/forgot-password`,
|
||||
`${this.apiUrl}/forgot-password`,
|
||||
{ P_EMAILADDR: email, P_PASSWORD: password },
|
||||
{ headers }
|
||||
);
|
||||
@ -72,7 +70,7 @@ export class AuthService {
|
||||
|
||||
sendEmail(email: string, type: string): Observable<any> {
|
||||
return this.http.post(
|
||||
`${this.apiUrl}/${this.apiDb}/sendmail`,
|
||||
`${this.apiUrl}/sendmail`,
|
||||
{ P_TO: email, P_MAIL_TYPE: type }
|
||||
);
|
||||
}
|
||||
|
||||
@ -12,9 +12,6 @@ import { CargoPolicy } from '../../models/cargo-policy';
|
||||
import { CargoSurety } from '../../models/cargo-surety';
|
||||
import { CarnetStatus } from '../../models/carnet-status';
|
||||
import { Country } from '../../models/country';
|
||||
import { UserService } from './user.service';
|
||||
import { HolderType } from '../../models/holder-type';
|
||||
import { ContactTitle } from '../../models/contact-title';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@ -24,10 +21,9 @@ export class CommonService {
|
||||
private apiDb = environment.apiDb;
|
||||
|
||||
private http = inject(HttpClient);
|
||||
private userService = inject(UserService);
|
||||
|
||||
getCountries(): Observable<Country[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=002&P_SPID=${this.userService.getUserSpid()}`).pipe(
|
||||
getCountries(spid: number = 0): Observable<Country[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=002&P_SPID=0`).pipe(
|
||||
map((response) =>
|
||||
response.map((item) => ({
|
||||
name: item.PARAMDESC,
|
||||
@ -38,8 +34,8 @@ export class CommonService {
|
||||
);
|
||||
}
|
||||
|
||||
getStates(country: string): Observable<State[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=001&P_SPID=${this.userService.getUserSpid()}`).pipe(
|
||||
getStates(country: string, spid: number = 0): Observable<State[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=001&P_SPID=0`).pipe(
|
||||
map((response) =>
|
||||
response.map((item) => ({
|
||||
name: item.PARAMDESC,
|
||||
@ -56,7 +52,7 @@ export class CommonService {
|
||||
}
|
||||
|
||||
getRegions(): Observable<Region[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetRegions/${this.userService.getUserSpid()}`).pipe(
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetRegions`).pipe(
|
||||
map((response) =>
|
||||
response.map((item) => ({
|
||||
id: item.REGIONID,
|
||||
@ -67,8 +63,8 @@ export class CommonService {
|
||||
);
|
||||
}
|
||||
|
||||
getDeliveryTypes(): Observable<DeliveryType[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=006&P_SPID=${this.userService.getUserSpid()}`).pipe(
|
||||
getDeliveryTypes(spid: number = 0): Observable<DeliveryType[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=006&P_SPID=0`).pipe(
|
||||
map((response) =>
|
||||
response.map((item) => ({
|
||||
name: item.PARAMDESC,
|
||||
@ -79,8 +75,8 @@ export class CommonService {
|
||||
);
|
||||
}
|
||||
|
||||
getTimezones(): Observable<TimeZone[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=010&P_SPID=${this.userService.getUserSpid()}`).pipe(
|
||||
getTimezones(spid: number = 0): Observable<TimeZone[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=010&P_SPID=0`).pipe(
|
||||
map((response) =>
|
||||
response.map((item) => ({
|
||||
name: item.PARAMDESC,
|
||||
@ -91,8 +87,8 @@ export class CommonService {
|
||||
);
|
||||
}
|
||||
|
||||
getFeeTypes(): Observable<FeeType[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=009&P_SPID=${this.userService.getUserSpid()}`).pipe(
|
||||
getFeeTypes(spid: number = 0): Observable<FeeType[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=009&P_SPID=0`).pipe(
|
||||
map((response) =>
|
||||
response.map((item) => ({
|
||||
name: item.PARAMDESC,
|
||||
@ -103,8 +99,8 @@ export class CommonService {
|
||||
);
|
||||
}
|
||||
|
||||
getBondSuretys(): Observable<BondSurety[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=003&P_SPID=${this.userService.getUserSpid()}`).pipe(
|
||||
getBondSuretys(spid: number = 0): Observable<BondSurety[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=003&P_SPID=0`).pipe(
|
||||
map((response) =>
|
||||
response.map((item) => ({
|
||||
name: item.PARAMDESC,
|
||||
@ -115,8 +111,8 @@ export class CommonService {
|
||||
);
|
||||
}
|
||||
|
||||
getCargoPolicies(): Observable<CargoPolicy[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=004&P_SPID=${this.userService.getUserSpid()}`).pipe(
|
||||
getCargoPolicies(spid: number = 0): Observable<CargoPolicy[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=004&P_SPID=0`).pipe(
|
||||
map((response) =>
|
||||
response.map((item) => ({
|
||||
name: item.PARAMDESC,
|
||||
@ -127,8 +123,8 @@ export class CommonService {
|
||||
);
|
||||
}
|
||||
|
||||
getCargoSuretys(): Observable<CargoSurety[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=005&P_SPID=${this.userService.getUserSpid()}`).pipe(
|
||||
getCargoSuretys(spid: number = 0): Observable<CargoSurety[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=005&P_SPID=0`).pipe(
|
||||
map((response) =>
|
||||
response.map((item) => ({
|
||||
name: item.PARAMDESC,
|
||||
@ -139,8 +135,8 @@ export class CommonService {
|
||||
);
|
||||
}
|
||||
|
||||
getCarnetStatuses(): Observable<CarnetStatus[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=011&P_SPID=${this.userService.getUserSpid()}`).pipe(
|
||||
getCarnetStatuses(spid: number = 0): Observable<CarnetStatus[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=011&P_SPID=0`).pipe(
|
||||
map((response) =>
|
||||
response.map((item) => ({
|
||||
name: item.PARAMDESC,
|
||||
@ -152,30 +148,6 @@ 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,
|
||||
}))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
getContactTitles(): Observable<ContactTitle[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=012&P_SPID=${this.userService.getUserSpid()}`).pipe(
|
||||
map((response) =>
|
||||
response.map((item) => ({
|
||||
name: item.PARAMDESC,
|
||||
id: item.PARAMID,
|
||||
value: item.PARAMVALUE,
|
||||
}))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
formatUSDate(datetime: Date): string {
|
||||
const date = new Date(datetime);
|
||||
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
|
||||
|
||||
@ -136,8 +136,7 @@ export class UserService {
|
||||
locationid: userDetails.LOCATIONID,
|
||||
urlKey: userDetails.ENCURLKEY,
|
||||
logoName: userDetails.LOGONAME,
|
||||
themeName: userDetails.THEMENAME,
|
||||
serviceProviderName: userDetails.SPNAME
|
||||
themeName: userDetails.THEMENAME
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,71 +0,0 @@
|
||||
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/fees/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,
|
||||
expiredDate: item.EXPDATE || 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}`);
|
||||
// }
|
||||
}
|
||||
@ -37,10 +37,7 @@ export class HomeService {
|
||||
issueDate: item.ISSUEDATE || null,
|
||||
expiryDate: item.EXPDATE || null,
|
||||
orderType: item.ORDERTYPE,
|
||||
carnetStatus: item.CARNETSTATUS,
|
||||
securityType: item.SECURITYTYPE,
|
||||
deliveryType: item.DELIVERYTYPE,
|
||||
clientName: item.CLIENTNAMNE
|
||||
carnetStatus: item.CARNETSTATUS
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,12 +16,6 @@ export class ParamService {
|
||||
private userService = inject(UserService);
|
||||
|
||||
getParameters(P_PARAMTYPE: string): Observable<ParamProperties[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetALLParamValues?P_SPID=${this.userService.getUserSpid()}&P_PARAMTYPE=${P_PARAMTYPE}`).pipe(
|
||||
map(response => this.mapToParamValue(response))
|
||||
)
|
||||
}
|
||||
|
||||
getValidParameters(P_PARAMTYPE: string): Observable<ParamProperties[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_SPID=${this.userService.getUserSpid()}&P_PARAMTYPE=${P_PARAMTYPE}`).pipe(
|
||||
map(response => this.mapToParamValue(response))
|
||||
)
|
||||
@ -48,6 +42,7 @@ export class ParamService {
|
||||
lastUpdatedDate: paramValue.LASTUPDATEDDATE,
|
||||
errorMesg: paramValue.ERRORMESG,
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
createTableRecord(description: string): Observable<any> {
|
||||
@ -94,6 +89,8 @@ export class ParamService {
|
||||
P_USERID: this.userService.getUser(),
|
||||
};
|
||||
|
||||
console.log(paramDetails);
|
||||
|
||||
return this.http.patch(`${this.apiUrl}/${this.apiDb}/UpdateParamRecord`, paramDetails);
|
||||
}
|
||||
|
||||
|
||||
@ -1,77 +0,0 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { map, Observable } from 'rxjs';
|
||||
// import { UserService } from '../common/user.service';
|
||||
// import { CommonService } from '../common/common.service';
|
||||
import { Region } from '../../models/region/region';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class RegionService {
|
||||
private apiUrl = environment.apiUrl;
|
||||
private apiDb = environment.apiDb;
|
||||
|
||||
private http = inject(HttpClient);
|
||||
// private userService = inject(UserService);
|
||||
// private commonService = inject(CommonService);
|
||||
|
||||
getRegions(spid: number = 0): Observable<Region[]> {
|
||||
return this.http.get<any[]>(`${this.apiUrl}/${this.apiDb}/GetRegions/${spid}`).pipe(
|
||||
map(response => this.mapToRegions(response)));
|
||||
}
|
||||
|
||||
private mapToRegions(data: any[]): Region[] {
|
||||
return data.map(item => ({
|
||||
id: item.REGIONID,
|
||||
value: item.REGION,
|
||||
name: item.REGIONNAME,
|
||||
// spid: item.SPID
|
||||
}));
|
||||
}
|
||||
|
||||
// getRegionById(regionId: number): Observable<Region> {
|
||||
// return this.http.get<any>(`${this.apiUrl}/${this.apiDb}/GetRegion/${regionId}`).pipe(
|
||||
// map(response => this.mapToRegion(response)));
|
||||
// }
|
||||
|
||||
// private mapToRegion(data: any): Region {
|
||||
// return {
|
||||
// id: data.ID,
|
||||
// Value: data.VALUE,
|
||||
// Name: data.NAME,
|
||||
// P_SPID: data.P_SPID
|
||||
// };
|
||||
// }
|
||||
|
||||
createRegion(region: Region, spid: number = 0): Observable<any> {
|
||||
const payload = {
|
||||
P_REGION: region.value,
|
||||
P_NAME: region.name,
|
||||
P_SPID: spid,
|
||||
// P_USERID: this.userService.getUser()
|
||||
};
|
||||
|
||||
return this.http.post<any>(`${this.apiUrl}/${this.apiDb}/InsertRegions`, payload);
|
||||
}
|
||||
|
||||
updateRegion(regionId: number, region: Region): Observable<any> {
|
||||
const payload = {
|
||||
P_REGIONID: regionId,
|
||||
P_NAME: region.name,
|
||||
// P_USERID: this.userService.getUser()
|
||||
};
|
||||
|
||||
return this.http.patch<any>(`${this.apiUrl}/${this.apiDb}/UpdateRegion`, payload);
|
||||
}
|
||||
|
||||
// deleteRegion(regionId: number): Observable<any> {
|
||||
// const payload = {
|
||||
// P_REGIONID: regionId,
|
||||
// P_USERID: this.userService.getUser()
|
||||
// };
|
||||
|
||||
// return this.http.delete<any>(`${this.apiUrl}/${this.apiDb}/DeleteRegion`, { body: payload });
|
||||
// }
|
||||
}
|
||||
@ -3,7 +3,7 @@ import { environment } from '../../../../environments/environment';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { map, Observable } from 'rxjs';
|
||||
import { UserService } from '../common/user.service';
|
||||
import { BasicFee } from '../../models/fees/basic-fee';
|
||||
import { BasicFee } from '../../models/service-provider/basic-fee';
|
||||
import { CommonService } from '../common/common.service';
|
||||
|
||||
@Injectable({
|
||||
@ -30,17 +30,15 @@ export class BasicFeeService {
|
||||
fees: item.FEES,
|
||||
effectiveDate: item.EFFDATE,
|
||||
createdBy: item.CREATEDBY || null,
|
||||
dateCreated: item.DATECREATED || null,
|
||||
expiredDate: item.EXPDATE || null,
|
||||
expired: item.EXPDATE ? new Date(item.EXPDATE) < new Date() : false
|
||||
dateCreated: item.DATECREATED || null
|
||||
}));
|
||||
}
|
||||
|
||||
createBasicFee(spid: number, fee: BasicFee): Observable<any> {
|
||||
const payload = {
|
||||
P_SPID: spid,
|
||||
P_STARTNUMBER: fee.startCarnetValue,
|
||||
P_ENDNUMBER: fee.endCarnetValue,
|
||||
P_STARTCARNETVALUE: fee.startCarnetValue,
|
||||
P_ENDCARNETVALUE: fee.endCarnetValue,
|
||||
P_FEES: fee.fees,
|
||||
P_EFFDATE: this.commonService.formatUSDate(fee.effectiveDate),
|
||||
P_USERID: this.userService.getUser()
|
||||
@ -51,6 +49,8 @@ export class BasicFeeService {
|
||||
updateBasicFee(feeId: number, fee: BasicFee): Observable<any> {
|
||||
const payload = {
|
||||
P_BASICFEESETUPID: feeId,
|
||||
P_STARTCARNETVALUE: fee.startCarnetValue,
|
||||
P_ENDCARNETVALUE: fee.endCarnetValue,
|
||||
P_FEES: fee.fees,
|
||||
P_EFFDATE: this.commonService.formatUSDate(fee.effectiveDate),
|
||||
P_USERID: this.userService.getUser()
|
||||
@ -2,7 +2,7 @@ import { inject, Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { map, Observable } from 'rxjs';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
import { CarnetFee } from '../../models/fees/carnet-fee';
|
||||
import { CarnetFee } from '../../models/service-provider/carnet-fee';
|
||||
import { CommonService } from '../common/common.service';
|
||||
import { UserService } from '../common/user.service';
|
||||
|
||||
@ -31,9 +31,7 @@ export class CarnetFeeService {
|
||||
effectiveDate: item.EFFDATE,
|
||||
spid: item.SPID,
|
||||
createdBy: item.CREATEDBY || null,
|
||||
dateCreated: item.DATECREATED || null,
|
||||
expiredDate: item.EXPDATE || null,
|
||||
expired: item.EXPDATE ? new Date(item.EXPDATE) < new Date() : false
|
||||
dateCreated: item.DATECREATED || null
|
||||
}));
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ import { map, Observable } from 'rxjs';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
import { Contact } from '../../models/service-provider/contact';
|
||||
import { UserService } from '../common/user.service';
|
||||
import { ContactLogin } from '../../models/service-provider/contact-login';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@ -39,8 +38,7 @@ export class ContactService {
|
||||
lastUpdatedBy: contact.LASTUPDATEDBY || null,
|
||||
lastUpdatedDate: contact.LASTUPDATEDDATE || null,
|
||||
isInactive: contact.INACTIVEFLAG === 'Y' || false,
|
||||
inactivatedDate: contact.INACTIVEDATE || null,
|
||||
hasLogin: contact.LOGINFLAG === 'Y' || false
|
||||
inactivatedDate: contact.INACTIVEDATE || null
|
||||
}));
|
||||
}
|
||||
|
||||
@ -51,7 +49,7 @@ export class ContactService {
|
||||
p_defcontactflag: data.defaultContact ? 'Y' : 'N',
|
||||
p_firstname: data.firstName,
|
||||
p_lastname: data.lastName,
|
||||
P_MIDDLEINITIAL: data.middleInitial ?? '',
|
||||
P_MIDDLEINITIAL: data.middleInitial,
|
||||
p_title: data.title,
|
||||
p_phoneno: data.phone,
|
||||
p_mobileno: data.mobile,
|
||||
@ -69,7 +67,7 @@ export class ContactService {
|
||||
p_spcontactid: spContactId,
|
||||
p_firstname: data.firstName,
|
||||
p_lastname: data.lastName,
|
||||
P_MIDDLEINITIAL: data.middleInitial ?? '',
|
||||
P_MIDDLEINITIAL: data.middleInitial,
|
||||
p_title: data.title,
|
||||
p_phoneno: data.phone,
|
||||
p_mobileno: data.mobile,
|
||||
@ -82,23 +80,7 @@ export class ContactService {
|
||||
}
|
||||
|
||||
deleteContact(spContactId: string): Observable<any> {
|
||||
return this.http.patch(`${this.apiUrl}/${this.apiDb}/InactivateSPContact/${spContactId}`, null);
|
||||
return this.http.post(`${this.apiUrl}/${this.apiDb}/InactivateSPContact/${spContactId}`, null);
|
||||
}
|
||||
|
||||
createContactLogin(data: ContactLogin): Observable<any> {
|
||||
const contact = {
|
||||
P_SPID: data.spid,
|
||||
P_EMAILADDR: data.emailAddress,
|
||||
P_ENABLEPASSWORDPOLICY: 'Y',
|
||||
P_DOMAIN: 'test',
|
||||
P_LOOKUPCODE: 'test',
|
||||
P_USERID: this.userService.getUser()
|
||||
}
|
||||
|
||||
return this.http.post(`${this.apiUrl}/${this.apiDb}/CreateSPLogins`, contact);
|
||||
}
|
||||
|
||||
setDefaultContact(spContactId: string): Observable<any> {
|
||||
return this.http.patch(`${this.apiUrl}/${this.apiDb}/SetSPDefaultContact/${spContactId}`, null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ import { inject, Injectable } from '@angular/core';
|
||||
import { map, Observable } from 'rxjs';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
import { ContinuationSheetFee } from '../../models/fees/continuation-sheet-fee';
|
||||
import { ContinuationSheetFee } from '../../models/service-provider/continuation-sheet-fee';
|
||||
import { CommonService } from '../common/common.service';
|
||||
import { UserService } from '../common/user.service';
|
||||
|
||||
@ -31,9 +31,7 @@ export class ContinuationSheetFeeService {
|
||||
effectiveDate: item.EFFDATE,
|
||||
rate: item.RATE,
|
||||
createdBy: item.CREATEDBY || null,
|
||||
dateCreated: item.DATECREATED || null,
|
||||
expiredDate: item.EXPDATE || null,
|
||||
expired: item.EXPDATE ? new Date(item.EXPDATE) < new Date() : false
|
||||
dateCreated: item.DATECREATED || null
|
||||
}));
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ import { inject, Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { map, Observable } from 'rxjs';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
import { CounterfoilFee } from '../../models/fees/counterfoil-fee';
|
||||
import { CounterfoilFee } from '../../models/service-provider/counterfoil-fee';
|
||||
import { CommonService } from '../common/common.service';
|
||||
import { UserService } from '../common/user.service';
|
||||
|
||||
@ -33,9 +33,7 @@ export class CounterfoilFeeService {
|
||||
effectiveDate: item.EFFDATE,
|
||||
rate: item.RATE,
|
||||
createdBy: item.CREATEDBY || null,
|
||||
dateCreated: item.DATECREATED || null,
|
||||
expiredDate: item.EXPDATE || null,
|
||||
expired: item.EXPDATE ? new Date(item.EXPDATE) < new Date() : false
|
||||
dateCreated: item.DATECREATED || null
|
||||
}));
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ import { inject, Injectable } from '@angular/core';
|
||||
import { map, Observable } from 'rxjs';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
import { ExpeditedFee } from '../../models/fees/expedited-fee';
|
||||
import { ExpeditedFee } from '../../models/service-provider/expedited-fee';
|
||||
import { CommonService } from '../common/common.service';
|
||||
import { UserService } from '../common/user.service';
|
||||
|
||||
@ -34,9 +34,7 @@ export class ExpeditedFeeService {
|
||||
effectiveDate: item.EFFDATE,
|
||||
spid: item.SPID,
|
||||
createdBy: item.CREATEDBY || null,
|
||||
dateCreated: item.DATECREATED || null,
|
||||
expiredDate: item.EXPDATE || null,
|
||||
expired: item.EXPDATE ? new Date(item.EXPDATE) < new Date() : false
|
||||
dateCreated: item.DATECREATED || null
|
||||
}));
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ import { HttpClient } from '@angular/common/http';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { map, Observable } from 'rxjs';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
import { SecurityDeposit } from '../../models/fees/security-deposit';
|
||||
import { SecurityDeposit } from '../../models/service-provider/security-deposit';
|
||||
import { CommonService } from '../common/common.service';
|
||||
import { UserService } from '../common/user.service';
|
||||
|
||||
@ -30,13 +30,10 @@ export class SecurityDepositService {
|
||||
specialCommodity: item.SPCLCOMMODITY,
|
||||
specialCountry: item.SPCLCOUNTRY,
|
||||
rate: item.RATE,
|
||||
rateType: item.RATE_PCT,
|
||||
effectiveDate: item.EFFDATE,
|
||||
spid: item.SPID,
|
||||
createdBy: item.CREATEDBY || null,
|
||||
dateCreated: item.DATECREATED || null,
|
||||
expiredDate: item.EXPDATE || null,
|
||||
expired: item.EXPDATE ? new Date(item.EXPDATE) < new Date() : false
|
||||
dateCreated: item.DATECREATED || null
|
||||
}));
|
||||
}
|
||||
|
||||
@ -46,11 +43,10 @@ export class SecurityDepositService {
|
||||
P_SPID: spid,
|
||||
P_EFFDATE: this.commonService.formatUSDate(data.effectiveDate),
|
||||
P_HOLDERTYPE: data.holderType,
|
||||
P_USCIBMEMBERFLAG: data.uscibMember,
|
||||
P_USCIBMEMBERFLAG: data.uscibMember ? 'Y' : 'N',
|
||||
P_SPCLCOMMODITY: data.specialCommodity,
|
||||
P_SPCLCOUNTRY: data.specialCountry,
|
||||
P_RATE: data.rate,
|
||||
P_PCT_VALUE: data.rateType,
|
||||
P_USERID: this.userService.getUser()
|
||||
}
|
||||
|
||||
@ -63,7 +59,6 @@ export class SecurityDepositService {
|
||||
P_BONDRATESETUPID: id,
|
||||
P_EFFDATE: this.commonService.formatUSDate(data.effectiveDate),
|
||||
P_RATE: data.rate,
|
||||
P_PCT_VALUE: data.rateType,
|
||||
P_USERID: this.userService.getUser()
|
||||
}
|
||||
|
||||
@ -1,44 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class StyleManagerService {
|
||||
|
||||
/**
|
||||
* Set the stylesheet with the specified key.
|
||||
*/
|
||||
setStyle(key: string, href: string) {
|
||||
getLinkElementForKey(key).setAttribute('href', href);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the stylesheet with the specified key.
|
||||
*/
|
||||
removeStyle(key: string) {
|
||||
const existingLinkElement = getExistingLinkElementByKey(key);
|
||||
if (existingLinkElement) {
|
||||
document.head.removeChild(existingLinkElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getLinkElementForKey(key: string) {
|
||||
return getExistingLinkElementByKey(key) || createLinkElementWithKey(key);
|
||||
}
|
||||
|
||||
function getExistingLinkElementByKey(key: string) {
|
||||
return document.head.querySelector(`link[rel="stylesheet"].${getClassNameForKey(key)}`);
|
||||
}
|
||||
|
||||
function createLinkElementWithKey(key: string) {
|
||||
const linkEl = document.createElement('link');
|
||||
linkEl.setAttribute('rel', 'stylesheet');
|
||||
linkEl.classList.add(getClassNameForKey(key));
|
||||
document.head.appendChild(linkEl);
|
||||
return linkEl;
|
||||
}
|
||||
|
||||
function getClassNameForKey(key: string) {
|
||||
return `style-manager-${key}`;
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { StyleManagerService } from './stylemanager.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ThemeService {
|
||||
|
||||
private styleManager = inject(StyleManagerService);
|
||||
|
||||
setTheme(themeToSet: string) {
|
||||
|
||||
this.styleManager.setStyle(
|
||||
"theme",
|
||||
`themes/${themeToSet}.css`
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,197 +0,0 @@
|
||||
<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 in %</th>
|
||||
<td mat-cell *matCellDef="let item">{{ item.rate | number:'1.0-4' }}</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>
|
||||
|
||||
<!-- Expired Date Column -->
|
||||
<ng-container matColumnDef="expiredDate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Expired Date</th>
|
||||
<td mat-cell *matCellDef="let fee">{{ fee.expiredDate | 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 in %</mat-label>
|
||||
<input matInput formControlName="rate" type="number">
|
||||
<mat-error *ngIf="cargoRateForm.get('rate')?.errors?.['required']">
|
||||
Rate is required
|
||||
</mat-error>
|
||||
<mat-error *ngIf="cargoRateForm.get('rate')?.errors?.['pattern']">
|
||||
Please enter a valid number with up to 4 decimal places
|
||||
</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>
|
||||
@ -1,191 +0,0 @@
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,247 +0,0 @@
|
||||
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/fees/cargo-rate';
|
||||
import { CargoRateService } from '../../core/services/fees/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, { static: false })
|
||||
set paginator(value: MatPaginator) {
|
||||
this.dataSource.paginator = value;
|
||||
}
|
||||
|
||||
@ViewChild(MatSort) sort!: MatSort;
|
||||
|
||||
displayedColumns: string[] = ['carnetType', 'startSets', 'endSets', 'rate', 'effectiveDate', 'expiredDate', '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,4}$/),
|
||||
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 {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
<h2 class="page-header">Manage Fees</h2>
|
||||
|
||||
<div class="manage-fees-action-buttons">
|
||||
<button mat-button (click)="accordion().openAll()">Expand All</button>
|
||||
<button mat-button (click)="accordion().closeAll()">Collapse All</button>
|
||||
</div>
|
||||
<mat-accordion class="manage-fees-headers-align" multi>
|
||||
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title> Carnet Fee & Commission Setup </mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<app-carnet-fee [spid]="spid" [isEditMode]="isEditMode" [userPreferences]="userPreferences"></app-carnet-fee>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title> Basic Fee Setup</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<app-basic-fee [spid]="spid" [isEditMode]="isEditMode" [userPreferences]="userPreferences"></app-basic-fee>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title> Counterfoil Setup</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<app-counterfoil-fee [spid]="spid" [isEditMode]="isEditMode"
|
||||
[userPreferences]="userPreferences"></app-counterfoil-fee>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title> Continuation Sheet Fee Setup </mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<app-continuation-sheet-fee [spid]="spid" [isEditMode]="isEditMode"
|
||||
[userPreferences]="userPreferences"></app-continuation-sheet-fee>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title> Expedited Fee Setup</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<app-expedited-fee [spid]="spid" [isEditMode]="isEditMode"
|
||||
[userPreferences]="userPreferences"></app-expedited-fee>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title> Security Deposit </mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<app-security-deposit [spid]="spid" [isEditMode]="isEditMode"
|
||||
[userPreferences]="userPreferences"></app-security-deposit>
|
||||
</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>
|
||||
@ -1,18 +0,0 @@
|
||||
.page-header {
|
||||
margin: 0.5rem 0px;
|
||||
color: var(--mat-sys-primary);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.manage-fees-action-buttons {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.manage-fees-headers-align .mat-expansion-panel-header-description {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.manage-fees-headers-align .mat-mdc-form-field+.mat-mdc-form-field {
|
||||
margin-left: 8px;
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
import { afterNextRender, Component, viewChild } from '@angular/core';
|
||||
import { AngularMaterialModule } from '../../shared/module/angular-material.module';
|
||||
import { MatAccordion } from '@angular/material/expansion';
|
||||
import { CarnetFeeComponent } from "../carnet-fee/carnet-fee.component";
|
||||
import { BasicFeeComponent } from "../basic-fee/basic-fee.component";
|
||||
import { CounterfoilFeeComponent } from "../counterfoil-fee/counterfoil-fee.component";
|
||||
import { ContinuationSheetFeeComponent } from "../continuation-sheet-fee/continuation-sheet-fee.component";
|
||||
import { ExpeditedFeeComponent } from "../expedited-fee/expedited-fee.component";
|
||||
import { SecurityDepositComponent } from "../security-deposit/security-deposit.component";
|
||||
import { UserPreferences } from '../../core/models/user-preference';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { UserPreferencesService } from '../../core/services/user-preference.service';
|
||||
import { CargoRateComponent } from '../cargo-rate/cargo-rate.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-manage-fee',
|
||||
imports: [AngularMaterialModule, CarnetFeeComponent, BasicFeeComponent, CounterfoilFeeComponent, ContinuationSheetFeeComponent, ExpeditedFeeComponent, SecurityDepositComponent, CommonModule, CargoRateComponent],
|
||||
templateUrl: './manage-fee.component.html',
|
||||
styleUrl: './manage-fee.component.scss'
|
||||
})
|
||||
export class ManageFeeComponent {
|
||||
accordion = viewChild.required(MatAccordion);
|
||||
isEditMode = true;
|
||||
spid = 0;
|
||||
serviceProviderName: string | null = null;
|
||||
userPreferences: UserPreferences;
|
||||
|
||||
constructor(userPrefenceService: UserPreferencesService) {
|
||||
this.userPreferences = userPrefenceService.getPreferences();
|
||||
afterNextRender(() => {
|
||||
// Open all panels
|
||||
this.accordion().openAll();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -4,7 +4,6 @@ import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { ApiErrorHandlerService } from '../core/services/common/api-error-handler.service';
|
||||
import { AuthService } from '../core/services/common/auth.service';
|
||||
import { NotificationService } from '../core/services/common/notification.service';
|
||||
import { ThemeService } from '../core/services/theme.service';
|
||||
import { AngularMaterialModule } from '../shared/module/angular-material.module';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@ -27,7 +26,6 @@ export class ForgotPasswordComponent {
|
||||
private router = inject(Router);
|
||||
private notificationService = inject(NotificationService);
|
||||
private errorHandler = inject(ApiErrorHandlerService);
|
||||
private themeService = inject(ThemeService);
|
||||
private route = inject(ActivatedRoute);
|
||||
|
||||
constructor() {
|
||||
@ -52,10 +50,6 @@ export class ForgotPasswordComponent {
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.themeService.setTheme('default');
|
||||
}
|
||||
|
||||
onRequest(): void {
|
||||
if (this.forgotPasswordRequestForm.invalid) {
|
||||
this.forgotPasswordRequestForm.markAllAsTouched();
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
@use 'colors' as colors;
|
||||
|
||||
.dashboard-chart-container {
|
||||
padding: 24px 0px;
|
||||
margin-bottom: 24px;
|
||||
@ -34,7 +36,7 @@
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: var(--mat-sys-primary);
|
||||
color: colors.$primary-color;
|
||||
}
|
||||
|
||||
.edit-icon {
|
||||
@ -42,7 +44,7 @@
|
||||
transition: color 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
color: var(--mat-sys-primary);
|
||||
color: colors.$primary-color;
|
||||
}
|
||||
|
||||
mat-icon {
|
||||
|
||||
@ -8,8 +8,7 @@
|
||||
|
||||
<!-- Chart Section -->
|
||||
<div class="chart-section">
|
||||
<app-chart [chartData]="carnetData" [carnetStatuses]="carnetStatuses"
|
||||
(carnetStatusData)="onCarnetStatusClick($event)"></app-chart>
|
||||
<app-chart [chartData]="carnetData" [carnetStatuses]="carnetStatuses" (carnetStatusData)="onCarnetStatusClick($event)"></app-chart>
|
||||
</div>
|
||||
|
||||
<!-- Carnet Details Section -->
|
||||
@ -19,34 +18,6 @@
|
||||
</div>
|
||||
|
||||
<div class="table-actions">
|
||||
<div class="filter-controls" *ngIf="dataSource.data.length > 0">
|
||||
<!-- Column Selection Dropdown -->
|
||||
<mat-form-field appearance="outline" class="filter-field">
|
||||
<mat-label>Filter By</mat-label>
|
||||
<mat-select [(value)]="selectedColumn" (selectionChange)="onColumnChange()">
|
||||
<mat-option value=""></mat-option>
|
||||
<mat-option *ngFor="let column of filterableColumns" [value]="column.value">
|
||||
{{column.displayName}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Search Input -->
|
||||
<mat-form-field appearance="outline" class="filter-field">
|
||||
<mat-label>Search Value</mat-label>
|
||||
<input matInput [(ngModel)]="filterValue" (keyup)="applyFilter()"
|
||||
placeholder="Enter search term...">
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Clear Filter Button -->
|
||||
<button mat-raised-button type="button" (click)="clearFilter()"
|
||||
[disabled]="!selectedColumn && !filterValue">
|
||||
<mat-icon>clear_all</mat-icon>
|
||||
Clear Filter
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button mat-raised-button color="accent" (click)="exportData()" *ngIf="dataSource.data.length > 0"
|
||||
matTooltip="Export to Excel" [disabled]="dataSource.data.length === 0">
|
||||
<mat-icon>download</mat-icon> Export
|
||||
@ -60,11 +31,6 @@
|
||||
<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>
|
||||
@ -75,11 +41,6 @@
|
||||
<td mat-cell *matCellDef="let item">{{ item.carnetNumber }}</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>
|
||||
@ -96,7 +57,7 @@
|
||||
|
||||
<ng-container matColumnDef="carnetValue">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Carnet Value</th>
|
||||
<td mat-cell *matCellDef="let item">{{ item.carnetValue | currency}}</td>
|
||||
<td mat-cell *matCellDef="let item">{{ item.carnetValue }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="issueDate">
|
||||
@ -132,8 +93,7 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator *ngIf="dataSource.data.length > userPreferences.pageSize!"
|
||||
[length]="dataSource.data.length" [pageSizeOptions]="[userPreferences.pageSize!]"
|
||||
<mat-paginator [length]="dataSource.data.length" [pageSizeOptions]="[userPreferences.pageSize!]"
|
||||
[hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
|
||||
|
||||
@ -12,13 +12,10 @@
|
||||
|
||||
.table-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
justify-content: end;
|
||||
|
||||
.filter-controls {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
button {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -15,11 +15,10 @@ import { ApiErrorHandlerService } from '../core/services/common/api-error-handle
|
||||
import { CommonService } from '../core/services/common/common.service';
|
||||
import { NotificationService } from '../core/services/common/notification.service';
|
||||
import * as XLSX from 'xlsx';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
imports: [AngularMaterialModule, ChartComponent, RouterLink, CommonModule, FormsModule],
|
||||
imports: [AngularMaterialModule, ChartComponent, RouterLink, CommonModule],
|
||||
templateUrl: './home.component.html',
|
||||
styleUrl: './home.component.scss',
|
||||
providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }],
|
||||
@ -31,25 +30,6 @@ export class HomeComponent {
|
||||
userPreferences: UserPreferences;
|
||||
carnetStatuses: CarnetStatus[] = [];
|
||||
|
||||
// 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: 'securityType', displayName: 'Security Type' },
|
||||
{ value: 'usSets', displayName: 'US Sets' },
|
||||
{ value: 'foreignSets', displayName: 'Foreign Sets' },
|
||||
{ value: 'transitSets', displayName: 'Transit Sets' },
|
||||
{ value: 'carnetValue', displayName: 'Carnet Value' },
|
||||
{ value: 'issueDate', displayName: 'Issue Date' },
|
||||
{ value: 'expiryDate', displayName: 'Expiry Date' },
|
||||
{ value: 'orderType', displayName: 'Order Type' },
|
||||
{ value: 'carnetStatus', displayName: 'Carnet Status' }
|
||||
];
|
||||
|
||||
dataSource = new MatTableDataSource<any>();
|
||||
|
||||
@ViewChild(MatPaginator, { static: false })
|
||||
@ -62,7 +42,7 @@ export class HomeComponent {
|
||||
this.dataSource.sort = value;
|
||||
}
|
||||
|
||||
displayedColumns: string[] = ['applicationName', 'clientName', 'holderName', 'carnetNumber', 'securityType', 'usSets', 'foreignSets', 'transitSets', 'carnetValue', 'issueDate', 'expiryDate', 'orderType', 'carnetStatus'];
|
||||
displayedColumns: string[] = ['applicationName', 'holderName', 'carnetNumber', 'usSets', 'foreignSets', 'transitSets', 'carnetValue', 'issueDate', 'expiryDate', 'orderType', 'carnetStatus'];
|
||||
|
||||
private homeService = inject(HomeService);
|
||||
private errorHandler = inject(ApiErrorHandlerService);
|
||||
@ -106,20 +86,13 @@ export class HomeComponent {
|
||||
onCarnetStatusClick(event: any): void {
|
||||
this.isLoading = true;
|
||||
this.showTable = false;
|
||||
|
||||
// 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 = carnetDetails.length > 0;
|
||||
this.showTable = true;
|
||||
this.dataSource.data = carnetDetails;
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource.sort = this.sort;
|
||||
|
||||
// Reset filter after new data is loaded
|
||||
this.dataSource.filter = '';
|
||||
},
|
||||
error: (error) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load carnet data for the selected status');
|
||||
@ -154,10 +127,8 @@ 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,
|
||||
'Security Type': item.securityType,
|
||||
'US Sets': item.usSets,
|
||||
'Foreign Sets': item.foreignSets,
|
||||
'Transit Sets': item.transitSets,
|
||||
@ -173,87 +144,4 @@ export class HomeComponent {
|
||||
const carnetStatus = this.carnetStatuses.find(t => t.value === value);
|
||||
return carnetStatus ? carnetStatus.name : value;
|
||||
}
|
||||
|
||||
applyFilter(): void {
|
||||
if (!this.dataSource) return;
|
||||
if (this.selectedColumn && this.filterValue) {
|
||||
this.dataSource.filterPredicate = (data: any, filter: string) => {
|
||||
const columnValue = data[this.selectedColumn];
|
||||
const searchTerm = filter.toLowerCase().trim();
|
||||
|
||||
// Handle different column types
|
||||
switch (this.selectedColumn) {
|
||||
case 'issueDate':
|
||||
case 'expiryDate':
|
||||
// Filter by date
|
||||
if (columnValue) {
|
||||
const formattedDate = this.formatDateForDisplay(columnValue);
|
||||
return formattedDate.toLowerCase().includes(searchTerm);
|
||||
}
|
||||
return false;
|
||||
|
||||
case 'carnetStatus':
|
||||
// Filter by status label instead of value
|
||||
const statusLabel = this.getCarnetStatusLabel(columnValue);
|
||||
return statusLabel.toLowerCase().includes(searchTerm);
|
||||
|
||||
default:
|
||||
// Default string/number filter
|
||||
if (typeof columnValue === 'string') {
|
||||
return columnValue.toLowerCase().includes(searchTerm);
|
||||
} else if (typeof columnValue === 'number') {
|
||||
return columnValue.toString().includes(searchTerm);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
this.dataSource.filter = this.filterValue.trim();
|
||||
} else if (!this.filterValue) {
|
||||
this.clearFilterData();
|
||||
}
|
||||
}
|
||||
|
||||
onColumnChange(): void {
|
||||
this.clearFilterData();
|
||||
}
|
||||
|
||||
clearFilter(): void {
|
||||
this.selectedColumn = '';
|
||||
this.clearFilterData();
|
||||
}
|
||||
|
||||
clearFilterData(): void {
|
||||
this.filterValue = '';
|
||||
|
||||
if (this.dataSource) {
|
||||
this.dataSource.filter = '';
|
||||
}
|
||||
}
|
||||
|
||||
private formatDateForDisplay(dateValue: any): string {
|
||||
if (!dateValue) return '';
|
||||
|
||||
try {
|
||||
const date = new Date(dateValue);
|
||||
|
||||
// Return in multiple formats for better filtering
|
||||
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
||||
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||
const fullMonthNames = ['January', 'February', 'March', 'April', 'May', 'June',
|
||||
'July', 'August', 'September', 'October', 'November', 'December'];
|
||||
|
||||
const month = monthNames[date.getUTCMonth()];
|
||||
const fullMonth = fullMonthNames[date.getUTCMonth()];
|
||||
const day = date.getUTCDate();
|
||||
const year = date.getUTCFullYear();
|
||||
const monthNumber = date.getUTCMonth() + 1;
|
||||
|
||||
// Return multiple formats separated by delimiter for filtering
|
||||
return `${month} ${day}, ${year}|${fullMonth} ${day}, ${year}|${monthNumber}/${day}/${year}|${year}-${monthNumber.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`;
|
||||
} catch (error) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,3 +1,5 @@
|
||||
@use 'colors' as colors;
|
||||
|
||||
.login-container {
|
||||
display: flex;
|
||||
min-height: 85vh;
|
||||
@ -24,7 +26,7 @@
|
||||
|
||||
.welcome-title {
|
||||
text-align: center;
|
||||
color: var(--mat-sys-primary);
|
||||
color: colors.$primary-color;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
@ -74,7 +76,7 @@
|
||||
.info-section {
|
||||
flex: 1;
|
||||
padding: 4rem;
|
||||
background-color: var(--mat-sys-primary);
|
||||
background-color: colors.$primary-color;
|
||||
color: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@ -7,7 +7,6 @@ import { AngularMaterialModule } from '../shared/module/angular-material.module'
|
||||
import { User } from '../core/models/user';
|
||||
import { UserService } from '../core/services/common/user.service';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { ThemeService } from '../core/services/theme.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login',
|
||||
@ -24,7 +23,6 @@ export class LoginComponent {
|
||||
private userService = inject(UserService);
|
||||
private navigationService = inject(NavigationService);
|
||||
private fb = inject(FormBuilder);
|
||||
private themeService = inject(ThemeService);
|
||||
|
||||
constructor() {
|
||||
this.loginForm = this.fb.group({
|
||||
@ -34,8 +32,6 @@ export class LoginComponent {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.themeService.setTheme('default');
|
||||
|
||||
if (this.userService.isLoggedIn()) {
|
||||
this.navigationService.navigate(['/home']);
|
||||
}
|
||||
|
||||
@ -1,81 +0,0 @@
|
||||
<h2 class="page-header">Manage Country Messages</h2>
|
||||
<div class="manage-container">
|
||||
|
||||
<!-- Country Messages Form -->
|
||||
<div class="form-container">
|
||||
<form [formGroup]="countryForm" (ngSubmit)="saveRecord()">
|
||||
<div class="form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Country</mat-label>
|
||||
<mat-select (selectionChange)="onCountrySelectionChanged($event)">
|
||||
<mat-option *ngFor="let country of countries" [value]="country.paramId">
|
||||
{{ country.paramDesc }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Message</mat-label>
|
||||
<textarea matInput formControlName="countryMessage" placeholder="Enter a message" rows="10"
|
||||
required></textarea>
|
||||
<mat-error *ngIf="countryForm.get('countryMessage')?.errors?.['required']">
|
||||
Message is required
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Type of Action</mat-label>
|
||||
<mat-select (selectionChange)="onActionTypeSelectionChanged($event)" formControlName="actionType">
|
||||
<mat-option *ngFor="let actionType of actionTypes" [value]="actionType">
|
||||
{{ actionType }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Action </mat-label>
|
||||
<input matInput formControlName="action">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<!-- <div class="readonly-section top-divider">
|
||||
<div class="readonly-fields">
|
||||
<div class="field-column">
|
||||
<div class="readonly-field">
|
||||
<label>Action Type</label>
|
||||
<div class="readonly-value">
|
||||
{{paramReadOnlyFields.actionType || 'N/A'}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field-column">
|
||||
<div class="readonly-field">
|
||||
<label>Action </label>
|
||||
<div class="readonly-value">
|
||||
{{paramReadOnlyFields.action || 'N/A'}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="form-actions">
|
||||
<button mat-raised-button color="primary" type="submit"
|
||||
[disabled]="countryForm.invalid || changeInProgress">
|
||||
Save
|
||||
</button>
|
||||
<button mat-raised-button color="primary" type="button" *ngIf="!currentCountry?.isInactive"
|
||||
(click)="inActivateParamRecord()">Inactivate
|
||||
Record</button>
|
||||
<button mat-raised-button color="primary" type="button" *ngIf="currentCountry?.isInactive"
|
||||
(click)="reActivateParamRecord()">Reactivate
|
||||
Record</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@ -1,105 +0,0 @@
|
||||
.page-header {
|
||||
margin: 0.5rem 0px;
|
||||
color: var(--mat-sys-primary);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.manage-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
margin-top: 0.5rem;
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.small-field {
|
||||
max-width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 16px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.results-section {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -1,258 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { ReactiveFormsModule, FormGroup, Validators, FormBuilder } from '@angular/forms';
|
||||
import { finalize, forkJoin } from 'rxjs';
|
||||
import { ParamProperties } from '../../core/models/param/parameters';
|
||||
import { ApiErrorHandlerService } from '../../core/services/common/api-error-handler.service';
|
||||
import { NotificationService } from '../../core/services/common/notification.service';
|
||||
import { ParamService } from '../../core/services/param/param.service';
|
||||
import { AngularMaterialModule } from '../../shared/module/angular-material.module';
|
||||
import { MatSelectChange } from '@angular/material/select';
|
||||
import { CountryMessage } from '../../core/models/param/country-message';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { ConfirmDialogComponent } from '../../shared/components/confirm-dialog/confirm-dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-manage-country',
|
||||
imports: [AngularMaterialModule, CommonModule, ReactiveFormsModule],
|
||||
templateUrl: './manage-country.component.html',
|
||||
styleUrl: './manage-country.component.scss'
|
||||
})
|
||||
export class ManageCountryComponent {
|
||||
isLoading: boolean = false;
|
||||
changeInProgress: boolean = false;
|
||||
countries: CountryMessage[] = [];
|
||||
countriesWithMessages: ParamProperties[] = [];
|
||||
currentCountryId: number = 0;
|
||||
currentCountry: CountryMessage | undefined | null = null;
|
||||
actionTypes: string[] = ['WARN', 'FYI', 'ACTION'];
|
||||
|
||||
private paramService = inject(ParamService);
|
||||
private errorHandler = inject(ApiErrorHandlerService);
|
||||
private notificationService = inject(NotificationService);
|
||||
private fb = inject(FormBuilder);
|
||||
private dialog = inject(MatDialog);
|
||||
|
||||
countryForm: FormGroup;
|
||||
|
||||
constructor() {
|
||||
this.countryForm = this.initializeForm();
|
||||
}
|
||||
|
||||
initializeForm(): FormGroup {
|
||||
return this.fb.group({
|
||||
countryMessage: ['', [Validators.required]],
|
||||
actionType: [{ value: '' }],
|
||||
action: [{ value: '', disabled: true }]
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getCountries();
|
||||
}
|
||||
|
||||
onCountrySelectionChanged(event: MatSelectChange) {
|
||||
this.renderCountry(+event.value);
|
||||
}
|
||||
|
||||
renderCountry(countryid: number): void {
|
||||
this.currentCountry = this.countries.find(c => c.paramId === countryid);
|
||||
this.currentCountryId = this.countriesWithMessages.find(c => c.paramValue === this.currentCountry?.paramValue)?.paramId ?? 0;
|
||||
this.patchCountryData();
|
||||
}
|
||||
|
||||
onActionTypeSelectionChanged(event: MatSelectChange) {
|
||||
if (event.value === 'ACTION') {
|
||||
this.countryForm.get('action')?.setValue('TRANSIT');
|
||||
}
|
||||
}
|
||||
|
||||
getCountries(): void {
|
||||
this.isLoading = true;
|
||||
|
||||
forkJoin({
|
||||
countries: this.paramService.getValidParameters('002'),
|
||||
countriesWithMessages: this.paramService.getValidParameters('014')
|
||||
}).pipe(finalize(() => {
|
||||
this.isLoading = false;
|
||||
})).subscribe({
|
||||
next: (results) => {
|
||||
this.countries = this.joinCountriesWithMessages(results.countries, results.countriesWithMessages);
|
||||
this.countriesWithMessages = results.countriesWithMessages;
|
||||
|
||||
if (this.currentCountry) {
|
||||
this.renderCountry(this.currentCountry.paramId!);
|
||||
}
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error loading countries messages data', error);
|
||||
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load countries messages data');
|
||||
this.notificationService.showError(errorMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
patchCountryData(): void {
|
||||
if (!this.currentCountry) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.countryForm.patchValue({
|
||||
countryMessage: this.currentCountry.countryMessage,
|
||||
actionType: this.currentCountry.addlParamValue1,
|
||||
action: this.currentCountry.addlParamValue2
|
||||
});
|
||||
|
||||
if (this.currentCountry.addlParamValue1 === 'ACTION') {
|
||||
this.countryForm.get('action')?.setValue('TRANSIT');
|
||||
} else {
|
||||
this.countryForm.get('action')?.setValue('');
|
||||
}
|
||||
}
|
||||
|
||||
saveRecord(): void {
|
||||
if (this.countryForm.invalid) {
|
||||
this.countryForm.markAllAsTouched();
|
||||
return;
|
||||
}
|
||||
|
||||
const paramData: ParamProperties = {
|
||||
paramDesc: this.countryForm.value.countryMessage,
|
||||
paramType: '014',
|
||||
paramValue: this.currentCountry?.paramValue ?? '',
|
||||
addlParamValue1: this.countryForm.value.actionType,
|
||||
addlParamValue2: this.countryForm.value.actionType === 'ACTION' ? 'TRANSIT' : null,
|
||||
sortSeq: 1,
|
||||
paramId: this.currentCountryId ?? 0
|
||||
};
|
||||
|
||||
const saveObservable = this.currentCountryId > 0
|
||||
? this.paramService.updateParamRecord(paramData)
|
||||
: this.paramService.createParamRecord(paramData);
|
||||
|
||||
this.changeInProgress = true;
|
||||
saveObservable.pipe(finalize(() => {
|
||||
this.changeInProgress = false;
|
||||
})).subscribe({
|
||||
next: () => {
|
||||
this.notificationService.showSuccess(`Country message updated successfully`);
|
||||
this.getCountries();
|
||||
},
|
||||
error: (error) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, `Failed to update country message`);
|
||||
this.notificationService.showError(errorMessage);
|
||||
console.error('Error saving country message:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
inActivateParamRecord(): void {
|
||||
if (this.currentCountryId === 0) {
|
||||
this.notificationService.showError('Not a valid country to inactivate');
|
||||
return;
|
||||
}
|
||||
|
||||
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
|
||||
width: '500px',
|
||||
data: {
|
||||
title: 'Inactivate Country Message',
|
||||
message: 'Are you sure you want to inactivate this message?',
|
||||
confirmText: 'Yes',
|
||||
cancelText: 'Cancel'
|
||||
}
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result) {
|
||||
this.paramService.inActivateParamRecord(this.currentCountryId).subscribe(
|
||||
{
|
||||
next: (data: any) => {
|
||||
this.notificationService.showSuccess(`Country message inactivated successfully`);
|
||||
this.getCountries();
|
||||
},
|
||||
error: (error: any) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, `Failed to inactivate country message`);
|
||||
this.notificationService.showError(errorMessage);
|
||||
console.error('Error inactivating country message:', error);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
reActivateParamRecord(): void {
|
||||
if (this.currentCountryId === 0) {
|
||||
this.notificationService.showError('Not a valid country to reactivate');
|
||||
return;
|
||||
}
|
||||
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
|
||||
width: '500px',
|
||||
data: {
|
||||
title: 'Reactivate Country Message',
|
||||
message: 'Are you sure you want to reactivate this message?',
|
||||
confirmText: 'Yes',
|
||||
cancelText: 'Cancel'
|
||||
}
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result) {
|
||||
this.paramService.reActivateParamRecord(this.currentCountryId).subscribe(
|
||||
{
|
||||
next: (data: any) => {
|
||||
this.notificationService.showSuccess(`Country message reactivated successfully`)
|
||||
this.getCountries();
|
||||
},
|
||||
error: (error: any) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, `Failed to reactivate country message`);
|
||||
this.notificationService.showError(errorMessage);
|
||||
console.error('Error reactivating country message:', error);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
joinCountriesWithMessages(countries: ParamProperties[], countryMessages: ParamProperties[]): CountryMessage[] {
|
||||
// Group messages by paramvalue
|
||||
const messagesByCountry = countryMessages.reduce((acc, message) => {
|
||||
if (!acc[message.paramValue]) {
|
||||
acc[message.paramValue] = {
|
||||
messages: [],
|
||||
// paramId: message.paramId, // Store one paramid from messages
|
||||
isInactive: message.inactiveCodeFlag === 'Y',
|
||||
addlParamValue1: message.addlParamValue1,
|
||||
addlParamValue2: message.addlParamValue2
|
||||
};
|
||||
}
|
||||
acc[message.paramValue].messages.push(message.paramDesc);
|
||||
return acc;
|
||||
}, {} as Record<string, {
|
||||
messages: string[]; //paramId?: number;
|
||||
isInactive: boolean;
|
||||
addlParamValue1?: string | null;
|
||||
addlParamValue2?: string | null;
|
||||
}>);
|
||||
|
||||
// Join countries with their messages
|
||||
return countries.map(country => {
|
||||
const countryMessages = messagesByCountry[country.paramValue] || {
|
||||
messages: [], //paramId: null,
|
||||
isInactive: false,
|
||||
addlParamValue1: null,
|
||||
addlParamValue2: null
|
||||
};
|
||||
|
||||
return {
|
||||
...country,
|
||||
countryMessage: countryMessages.messages.join(' '),
|
||||
isInactive: countryMessages.isInactive,
|
||||
addlParamValue1: countryMessages.addlParamValue1,
|
||||
addlParamValue2: countryMessages.addlParamValue2,
|
||||
paramType: '014',
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -11,12 +11,15 @@ import { ActivatedRoute } from '@angular/router';
|
||||
})
|
||||
export class ManageParamRecordComponent {
|
||||
table_mode: TABLE_MODE = 'PARAM-RECORD'
|
||||
paramHeading: string = 'Parameters';
|
||||
paramHeading: string = '';
|
||||
|
||||
private route = inject(ActivatedRoute);
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
const param = this.route.snapshot.queryParamMap.get('param');
|
||||
|
||||
this.paramHeading = param || '';
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1 +1 @@
|
||||
<app-param-table [table_mode]="table_mode" [paramHeading]="paramHeading"></app-param-table>
|
||||
<app-param-table [table_mode]="table_mode"></app-param-table>
|
||||
@ -9,6 +9,5 @@ import { TABLE_MODE } from '../../core/models/param/types';
|
||||
styleUrl: './manage-table-record.component.scss'
|
||||
})
|
||||
export class ManageTableRecordComponent {
|
||||
table_mode: TABLE_MODE = 'TABLE-RECORD';
|
||||
paramHeading: string = 'Table Records';
|
||||
table_mode: TABLE_MODE = 'TABLE-RECORD'
|
||||
}
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
<h2 class="page-header">Manage - {{paramHeading | properCase}}</h2>
|
||||
<div class="manage-container">
|
||||
|
||||
<div class="results-section">
|
||||
<div class="loading-shade" *ngIf="isLoading">
|
||||
<mat-spinner diameter="50"></mat-spinner>
|
||||
</div>
|
||||
|
||||
<div class="search-bar">
|
||||
<mat-form-field appearance="outline" floatLabel="auto" class="full-width">
|
||||
<mat-label>Search</mat-label>
|
||||
@ -8,7 +13,7 @@
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="actions-bar">
|
||||
<div class="actions-bar" [ngClass]="{ 'mb-40': !isParamRecord, 'mb-10': isParamRecord }">
|
||||
<mat-slide-toggle (change)="toggleShowInactiveData()" *ngIf="isParamRecord" [disabled]="paramData.length === 0">
|
||||
<div class="icon-text">Show Inactive Records</div>
|
||||
</mat-slide-toggle>
|
||||
@ -19,57 +24,52 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="results-section">
|
||||
<div class="loading-shade" *ngIf="isLoading">
|
||||
<mat-spinner diameter="50"></mat-spinner>
|
||||
</div>
|
||||
|
||||
<table mat-table [dataSource]="dataSource" matSort>
|
||||
<table mat-table [dataSource]="dataSource" class="results-table" matSort>
|
||||
|
||||
<!-- PARAMTYPE Column -->
|
||||
<ng-container matColumnDef="paramType">
|
||||
<ng-container matColumnDef="ParamType">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Type</th>
|
||||
<td mat-cell *matCellDef="let client">{{ client.paramType }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- PARAMDESC Column -->
|
||||
<ng-container matColumnDef="paramDesc">
|
||||
<ng-container matColumnDef="ParamDesc">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Description</th>
|
||||
<td mat-cell *matCellDef="let client">{{ client.paramDesc || '--'}}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- PARAMVALUE Column -->
|
||||
<ng-container matColumnDef="paramValue">
|
||||
<ng-container matColumnDef="paramvalue">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Value</th>
|
||||
<td mat-cell *matCellDef="let client">{{ client.paramValue }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- ADDLPARAMVALUE1 Column -->
|
||||
<ng-container matColumnDef="addlParamValue1">
|
||||
<ng-container matColumnDef="addlparamvalue1">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Additional Value 1</th>
|
||||
<td mat-cell *matCellDef="let client">{{ client.addlParamValue1 || '--' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- ADDLPARAMVALUE2 Column -->
|
||||
<ng-container matColumnDef="addlParamValue2">
|
||||
<ng-container matColumnDef="addlparamvalue2">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Additional Value 2</th>
|
||||
<td mat-cell *matCellDef="let client">{{ client.addlParamValue2 || '--'}}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- ADDLPARAMVALUE3 Column -->
|
||||
<ng-container matColumnDef="addlParamValue3">
|
||||
<ng-container matColumnDef="addlparamvalue3">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Additional Value 3</th>
|
||||
<td mat-cell *matCellDef="let client">{{ client.addlParamValue3 || '--' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- ADDLPARAMVALUE4 Column -->
|
||||
<ng-container matColumnDef="addlParamValue4">
|
||||
<ng-container matColumnDef="addlparamvalue4">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Additional Value 4</th>
|
||||
<td mat-cell *matCellDef="let client">{{ client.addlParamValue4 || '--' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- ADDLPARAMVALUE5 Column -->
|
||||
<ng-container matColumnDef="addlParamValue5">
|
||||
<ng-container matColumnDef="addlparamvalue5">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Additional Value 5</th>
|
||||
<td mat-cell *matCellDef="let client">{{ client.addlParamValue5 || '--'}}</td>
|
||||
</ng-container>
|
||||
@ -85,19 +85,18 @@
|
||||
<mat-icon>chevron_right</mat-icon>
|
||||
</button>
|
||||
|
||||
<button mat-icon-button color="primary" *ngIf="isParamRecord
|
||||
&& allowEdit" (click)="onEditParam(client)" [matTooltip]="'edit'">
|
||||
<button mat-icon-button color="primary" *ngIf="isParamRecord" (click)="onEditParam(client)"
|
||||
[matTooltip]="'edit'">
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button>
|
||||
|
||||
<button mat-icon-button color="warn"
|
||||
*ngIf="isParamRecord && (client.inactiveCodeFlag === 'N' || !client.inactiveCodeFlag) && allowEdit"
|
||||
*ngIf="isParamRecord && (client.inactiveCodeFlag === 'N' || !client.inactiveCodeFlag)"
|
||||
matTooltip="Inactivate" (click)="inActivateParamRecord(client.paramId)">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
|
||||
<button mat-icon-button color="warn"
|
||||
*ngIf="(isParamRecord) && client.inactiveCodeFlag === 'Y' && allowEdit"
|
||||
<button mat-icon-button color="warn" *ngIf="(isParamRecord) && client.inactiveCodeFlag === 'Y'"
|
||||
matTooltip="Reactivate" (click)="reActivateParamRecord(client.paramId)">
|
||||
<mat-icon>delete_outline</mat-icon>
|
||||
</button>
|
||||
@ -118,13 +117,12 @@
|
||||
|
||||
<mat-paginator [length]="dataSource.data.length" [pageSizeOptions]="[userPreferences.pageSize || 2]"
|
||||
[hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
|
||||
<!-- Contact Form -->
|
||||
<div class="form-container" *ngIf="showForm">
|
||||
<form [formGroup]="paramForm" (ngSubmit)="saveRecord()">
|
||||
<div class="form-header">
|
||||
<h3> {{ !isParamRecord ? 'Add New Table' : isEditing ? `Edit Parameter` :
|
||||
`Add New Parameter`}}
|
||||
<h3>{{ !isParamRecord ? 'Add New Table' : isEditing ? 'Edit Param' : 'Add New Param' }}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
@ -255,8 +253,7 @@
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button mat-raised-button color="primary" type="submit"
|
||||
[disabled]="paramForm.invalid || changeInProgress">
|
||||
<button mat-raised-button color="primary" type="submit" [disabled]="paramForm.invalid">
|
||||
{{ isEditing ? 'Update' : 'Save' }}
|
||||
</button>
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
|
||||
@ -4,15 +4,17 @@
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.manage-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.actions-bar {
|
||||
clear: both;
|
||||
margin-bottom: -16px;
|
||||
|
||||
&.mb-40 {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
&.mb-10 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
mat-slide-toggle {
|
||||
transform: scale(0.8);
|
||||
@ -25,6 +27,7 @@
|
||||
|
||||
.icon-text {
|
||||
padding-left: 10px !important;
|
||||
font-size: 18px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,7 +55,6 @@
|
||||
.form-row {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
|
||||
mat-form-field {
|
||||
flex: 1;
|
||||
@ -96,7 +98,7 @@
|
||||
|
||||
.readonly-value {
|
||||
padding: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
font-size: 0.9375rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
@ -105,6 +107,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.results-section {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
@ -152,7 +155,7 @@
|
||||
color: rgba(0, 0, 0, 0.54);
|
||||
|
||||
mat-icon {
|
||||
font-size: 0.875rem;
|
||||
font-size: 1rem;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
margin-bottom: -3px;
|
||||
|
||||
@ -2,7 +2,7 @@ import { Component, inject, Input, ViewChild } from '@angular/core';
|
||||
import { AngularMaterialModule } from '../../shared/module/angular-material.module';
|
||||
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
|
||||
import { MatPaginator } from '@angular/material/paginator';
|
||||
import { MatSort } from '@angular/material/sort';
|
||||
import { UserPreferences } from '../../core/models/user-preference';
|
||||
import { UserPreferencesService } from '../../core/services/user-preference.service';
|
||||
@ -15,32 +15,27 @@ import { ParamProperties } from '../../core/models/param/parameters';
|
||||
import { ApiErrorHandlerService } from '../../core/services/common/api-error-handler.service';
|
||||
import { NotificationService } from '../../core/services/common/notification.service';
|
||||
import { TABLE_MODE } from '../../core/models/param/types';
|
||||
import { ProperCasePipe } from '../../shared/pipes/proper-case.pipe';
|
||||
import { finalize } from 'rxjs';
|
||||
import { CustomPaginator } from '../../shared/custom-paginator';
|
||||
import { ProperCasePipe } from '../../shared/pipes/properCase.pipe';
|
||||
|
||||
@Component({
|
||||
selector: 'app-param-table',
|
||||
imports: [AngularMaterialModule, ReactiveFormsModule, CommonModule, MatSlideToggleModule, ProperCasePipe],
|
||||
templateUrl: './param-table.component.html',
|
||||
styleUrl: './param-table.component.scss',
|
||||
providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }],
|
||||
styleUrl: './param-table.component.scss'
|
||||
})
|
||||
export class ParamTableComponent {
|
||||
//@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||
//@ViewChild(MatSort) sort!: MatSort;
|
||||
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||
@ViewChild(MatSort) sort!: MatSort;
|
||||
|
||||
@Input() table_mode: TABLE_MODE = 'TABLE-RECORD';
|
||||
@Input() paramHeading: string = 'Table Records';
|
||||
|
||||
isLoading: boolean = false;
|
||||
changeInProgress: boolean = false;
|
||||
userPreferences: UserPreferences;
|
||||
paramType: string | null = null;
|
||||
paramData: any = [];
|
||||
showInactiveData: boolean = false;
|
||||
isEditing: boolean = false;
|
||||
allowEdit: boolean = true;
|
||||
showForm: boolean = false;
|
||||
currentParamid: number | null = null;
|
||||
|
||||
@ -56,41 +51,16 @@ export class ParamTableComponent {
|
||||
private notificationService = inject(NotificationService);
|
||||
|
||||
dataSource = new MatTableDataSource<any>([]);
|
||||
|
||||
@ViewChild(MatPaginator, { static: false })
|
||||
set paginator(value: MatPaginator) {
|
||||
this.dataSource.paginator = value;
|
||||
}
|
||||
|
||||
@ViewChild(MatSort, { static: false })
|
||||
set sort(value: MatSort) {
|
||||
if (value) {
|
||||
// 1. Assign the sort object to the data source immediately
|
||||
this.dataSource.sort = value;
|
||||
|
||||
// 2. Apply default settings inside a timeout to avoid the NG0100 error
|
||||
setTimeout(() => {
|
||||
if (this.table_mode === 'TABLE-RECORD' && !value.active) {
|
||||
// Only set default if a sort isn't already active
|
||||
value.active = 'paramValue';
|
||||
value.direction = 'asc';
|
||||
|
||||
// 3. Instead of emitting an event, manually trigger the sort logic
|
||||
// through the DataSource's internal sortingDataAccessor
|
||||
this.dataSource.sort = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
paramForm: FormGroup;
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource.sort = this.sort;
|
||||
this.dataSource.data = this.paramData;
|
||||
}
|
||||
|
||||
displayedColumns: string[] = ['paramType', 'paramDesc', 'paramValue', 'addlParamValue1', 'addlParamValue2', 'addlParamValue3',
|
||||
'addlParamValue4', 'addlParamValue5', 'actions'];
|
||||
displayedColumns: string[] = ['ParamType', 'ParamDesc', 'paramvalue', 'addlparamvalue1', 'addlparamvalue2', 'addlparamvalue3',
|
||||
'addlparamvalue4', 'addlparamvalue5', 'actions'];
|
||||
|
||||
formControls: any = {};
|
||||
|
||||
@ -144,7 +114,6 @@ export class ParamTableComponent {
|
||||
|
||||
ngOnInit(): void {
|
||||
this.paramType = this.route.snapshot.paramMap.get('id');
|
||||
this.allowEdit = this.paramType !== '014';
|
||||
this.getParameters();
|
||||
}
|
||||
|
||||
@ -211,17 +180,17 @@ export class ParamTableComponent {
|
||||
|
||||
const P_PARAMTYPE: string = this.paramType ? this.paramType : '000';
|
||||
|
||||
this.paramService.getParameters(P_PARAMTYPE).pipe(finalize(() => {
|
||||
this.isLoading = false;
|
||||
})).subscribe({
|
||||
this.paramService.getParameters(P_PARAMTYPE).subscribe({
|
||||
next: (paramData: ParamProperties[]) => {
|
||||
this.paramData = paramData;
|
||||
this.renderParamData();
|
||||
this.paramData = paramData
|
||||
this.renderParamData()
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error: any) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load parameters');
|
||||
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to search preparers');
|
||||
this.notificationService.showError(errorMessage);
|
||||
console.error('Error loading parameters:', error);
|
||||
this.isLoading = false;
|
||||
console.error('Error loading preparers:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -244,10 +213,7 @@ export class ParamTableComponent {
|
||||
? this.paramService.updateParamRecord(paramData as ParamProperties)
|
||||
: this.paramService.createParamRecord(paramData as ParamProperties);
|
||||
|
||||
this.changeInProgress = true;
|
||||
saveObservable.pipe(finalize(() => {
|
||||
this.changeInProgress = false;
|
||||
})).subscribe({
|
||||
saveObservable.subscribe({
|
||||
next: () => {
|
||||
this.notificationService.showSuccess(`Record ${this.isEditing && (this.table_mode !== 'TABLE-RECORD') ? 'updated' : 'added'} successfully`);
|
||||
this.getParameters();
|
||||
|
||||
@ -1,113 +0,0 @@
|
||||
<div class="region-container">
|
||||
<h2 class="page-header">Manage Regions</h2>
|
||||
|
||||
<div class="actions-bar">
|
||||
<!-- <mat-slide-toggle (change)="toggleShowExpiredRecords()">
|
||||
Show Expired Records
|
||||
</mat-slide-toggle> -->
|
||||
<button mat-raised-button color="primary" (click)="addNewRegion()">
|
||||
<mat-icon>add</mat-icon> Add New Region
|
||||
</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>
|
||||
<!-- Value Column -->
|
||||
<ng-container matColumnDef="value">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Region</th>
|
||||
<td mat-cell *matCellDef="let item">{{ item.value }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Name Column -->
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Region Name</th>
|
||||
<td mat-cell *matCellDef="let item">{{ item.name }}</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)="editRegion(item)" matTooltip="Edit">
|
||||
<mat-icon>edit</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 regions 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>
|
||||
|
||||
<!-- Region Form -->
|
||||
<div class="form-container" *ngIf="showForm">
|
||||
<form [formGroup]="regionForm" (ngSubmit)="saveRegion()">
|
||||
<div class="form-header">
|
||||
<h3>{{ isEditing ? 'Edit Region' : 'Add New Region' }}</h3>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Region</mat-label>
|
||||
<input matInput formControlName="value" required [readonly]="isEditing">
|
||||
<mat-error *ngIf="regionForm.get('value')?.errors?.['required']">
|
||||
Region is required
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Region Name</mat-label>
|
||||
<input matInput formControlName="name" required>
|
||||
<mat-error *ngIf="regionForm.get('name')?.errors?.['required']">
|
||||
Region Name 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]="regionForm.invalid || changeInProgress">
|
||||
{{ isEditing ? 'Update' : 'Save' }}
|
||||
</button>
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,165 +0,0 @@
|
||||
.region-container {
|
||||
padding: 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
|
||||
.page-header {
|
||||
margin: 0px;
|
||||
color: var(--mat-sys-primary);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.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 {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 16px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.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) {
|
||||
.region-container {
|
||||
padding: 16px;
|
||||
|
||||
.form-row {
|
||||
flex-direction: column;
|
||||
gap: 16px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,179 +0,0 @@
|
||||
import { AfterViewInit, 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 { Region } from '../core/models/region/region';
|
||||
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 { RegionService } from '../core/services/region/region.service';
|
||||
import { UserPreferencesService } from '../core/services/user-preference.service';
|
||||
import { finalize } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-region',
|
||||
imports: [AngularMaterialModule, CommonModule, ReactiveFormsModule],
|
||||
templateUrl: './region.component.html',
|
||||
styleUrl: './region.component.scss',
|
||||
providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }],
|
||||
})
|
||||
export class RegionComponent implements OnInit, AfterViewInit {
|
||||
@ViewChild(MatPaginator, { static: false })
|
||||
set paginator(value: MatPaginator) {
|
||||
this.dataSource.paginator = value;
|
||||
}
|
||||
|
||||
@ViewChild(MatSort) sort!: MatSort;
|
||||
|
||||
displayedColumns: string[] = ['value', 'name', 'actions'];
|
||||
dataSource = new MatTableDataSource<any>();
|
||||
regionForm: FormGroup;
|
||||
isEditing = false;
|
||||
currentRegionId: number | null = null;
|
||||
isLoading = false;
|
||||
changeInProgress = false;
|
||||
showForm = false;
|
||||
showExpiredRecords = false;
|
||||
regions: Region[] = [];
|
||||
userPreferences!: UserPreferences;
|
||||
|
||||
// readOnlyFields: any = {
|
||||
// lastChangedDate: null,
|
||||
// lastChangedBy: null
|
||||
// };
|
||||
|
||||
@Input() isEditMode = false;
|
||||
@Input() spid: number = 0;
|
||||
@Output() hasRegions = new EventEmitter<boolean>();
|
||||
|
||||
private fb = inject(FormBuilder);
|
||||
private regionService = inject(RegionService);
|
||||
private notificationService = inject(NotificationService);
|
||||
private errorHandler = inject(ApiErrorHandlerService);
|
||||
|
||||
constructor(userPrefenceService: UserPreferencesService) {
|
||||
this.userPreferences = userPrefenceService.getPreferences();
|
||||
this.regionForm = this.fb.group({
|
||||
value: ['', Validators.required],
|
||||
name: ['', Validators.required]
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadRegions();
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource.sort = this.sort;
|
||||
}
|
||||
|
||||
loadRegions(): void {
|
||||
this.isLoading = true;
|
||||
this.regionService.getRegions(this.spid).pipe(finalize(() => {
|
||||
this.isLoading = false;
|
||||
}))
|
||||
.subscribe({
|
||||
next: (regions: Region[]) => {
|
||||
this.regions = regions;
|
||||
this.dataSource.data = this.regions;
|
||||
// this.renderRecords();
|
||||
},
|
||||
error: (error: any) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load regions');
|
||||
this.notificationService.showError(errorMessage);
|
||||
console.error('Error loading regions:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// toggleShowExpiredRecords(): void {
|
||||
// this.showExpiredRecords = !this.showExpiredRecords;
|
||||
// this.renderRecords();
|
||||
// }
|
||||
|
||||
// renderRecords(): void {
|
||||
// // if (this.showExpiredRecords) {
|
||||
// // this.dataSource.data = this.regions;
|
||||
// // } else {
|
||||
// // this.dataSource.data = this.regions; // Adjust if you have expired logic
|
||||
// //}
|
||||
// }
|
||||
|
||||
addNewRegion(): void {
|
||||
this.showForm = true;
|
||||
this.isEditing = false;
|
||||
this.currentRegionId = null;
|
||||
this.regionForm.reset({
|
||||
value: '',
|
||||
name: ''
|
||||
});
|
||||
|
||||
this.regionForm.get('value')?.enable();
|
||||
this.regionForm.get('name')?.enable();
|
||||
}
|
||||
|
||||
editRegion(region: Region): void {
|
||||
this.showForm = true;
|
||||
this.isEditing = true;
|
||||
this.currentRegionId = region.id;
|
||||
this.regionForm.patchValue({
|
||||
value: region.value,
|
||||
name: region.name
|
||||
});
|
||||
|
||||
// // Set readonly fields if available
|
||||
// this.readOnlyFields.lastChangedDate = null; // Update based on your API response
|
||||
// this.readOnlyFields.lastChangedBy = null; // Update based on your API response
|
||||
|
||||
this.regionForm.get('value')?.disable();
|
||||
}
|
||||
|
||||
saveRegion(): void {
|
||||
if (this.regionForm.invalid) {
|
||||
this.regionForm.markAllAsTouched();
|
||||
return;
|
||||
}
|
||||
|
||||
const regionData: Region = {
|
||||
id: this.currentRegionId || 0,
|
||||
value: this.regionForm.get('value')?.value,
|
||||
name: this.regionForm.get('name')?.value
|
||||
};
|
||||
|
||||
const saveObservable = this.isEditing && this.currentRegionId
|
||||
? this.regionService.updateRegion(this.currentRegionId, regionData)
|
||||
: this.regionService.createRegion(regionData, this.spid);
|
||||
|
||||
this.changeInProgress = true;
|
||||
saveObservable.pipe(finalize(() => {
|
||||
this.changeInProgress = false;
|
||||
})).subscribe({
|
||||
next: () => {
|
||||
this.notificationService.showSuccess(`Region ${this.isEditing ? 'updated' : 'added'} successfully`);
|
||||
this.loadRegions();
|
||||
this.cancelEdit();
|
||||
this.hasRegions.emit(true);
|
||||
},
|
||||
error: (error) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, `Failed to ${this.isEditing ? 'update' : 'add'} region`);
|
||||
this.notificationService.showError(errorMessage);
|
||||
console.error('Error saving region:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
cancelEdit(): void {
|
||||
this.showForm = false;
|
||||
this.isEditing = false;
|
||||
this.currentRegionId = null;
|
||||
this.regionForm.reset();
|
||||
|
||||
this.regionForm.get('value')?.enable();
|
||||
this.regionForm.get('name')?.enable();
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,6 @@ import { NotificationService } from '../core/services/common/notification.servic
|
||||
import { AngularMaterialModule } from '../shared/module/angular-material.module';
|
||||
import { ApiErrorHandlerService } from '../core/services/common/api-error-handler.service';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ThemeService } from '../core/services/theme.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-register',
|
||||
@ -29,7 +28,6 @@ export class RegisterComponent {
|
||||
private route = inject(ActivatedRoute);
|
||||
private notificationService = inject(NotificationService);
|
||||
private errorHandler = inject(ApiErrorHandlerService);
|
||||
private themeService = inject(ThemeService);
|
||||
|
||||
constructor() {
|
||||
this.registrationForm = this.fb.group({
|
||||
@ -49,10 +47,6 @@ export class RegisterComponent {
|
||||
// }
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.themeService.setTheme('default');
|
||||
}
|
||||
|
||||
onSubmit(): void {
|
||||
if (this.registrationForm.invalid) {
|
||||
this.registrationForm.markAllAsTouched();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<div class="service-provider-container">
|
||||
<mat-stepper orientation="vertical" [linear]="isLinear" (selectionChange)="onStepChange($event)"
|
||||
<mat-stepper orientation="vertical" [linear]="true" (selectionChange)="onStepChange($event)"
|
||||
[selectedIndex]="currentStep">
|
||||
|
||||
<!-- Basic Details Step -->
|
||||
@ -19,16 +19,8 @@
|
||||
</app-contacts>
|
||||
</mat-step>
|
||||
|
||||
<!-- Regions Step -->
|
||||
<mat-step [completed]="regionCompleted" [editable]="!!serviceProviderId && basicDetailsCompleted">
|
||||
<ng-template matStepLabel>Regions</ng-template>
|
||||
|
||||
<app-sp-region *ngIf="serviceProviderId" [spid]="serviceProviderId" (hasRegions)="onRegionsSaved($event)">
|
||||
</app-sp-region>
|
||||
</mat-step>
|
||||
|
||||
<!-- Carnet Sequence Step -->
|
||||
<mat-step [editable]="!!serviceProviderId && basicDetailsCompleted" [completed]="carnetSequenceCompleted">
|
||||
<mat-step [editable]="!!serviceProviderId && contactsCompleted" [completed]="carnetSequenceCompleted">
|
||||
<ng-template matStepLabel>Carnet Sequence</ng-template>
|
||||
|
||||
<app-carnet-sequence *ngIf="serviceProviderId" [spid]="serviceProviderId"
|
||||
@ -37,7 +29,7 @@
|
||||
</mat-step>
|
||||
|
||||
<!-- Fees & Commission Step -->
|
||||
<mat-step [editable]="!!serviceProviderId && basicDetailsCompleted"
|
||||
<mat-step [editable]="!!serviceProviderId && carnetSequenceCompleted"
|
||||
[completed]="feeCommissionCompleted && carnetSequenceCompleted">
|
||||
<ng-template matStepLabel>Carnet Fee & Commission Setup</ng-template>
|
||||
|
||||
@ -46,7 +38,7 @@
|
||||
</mat-step>
|
||||
|
||||
<!-- Basic Fee Step -->
|
||||
<mat-step [editable]="!!serviceProviderId && basicDetailsCompleted"
|
||||
<mat-step [editable]="!!serviceProviderId && feeCommissionCompleted"
|
||||
[completed]="basicFeeCompleted && feeCommissionCompleted">
|
||||
<ng-template matStepLabel>Basic Fee Setup</ng-template>
|
||||
|
||||
@ -55,7 +47,7 @@
|
||||
</mat-step>
|
||||
|
||||
<!-- Counterfoil Fee Step -->
|
||||
<mat-step [editable]="!!serviceProviderId && basicDetailsCompleted" [completed]="counterfoilFeeCompleted">
|
||||
<mat-step [editable]="!!serviceProviderId && basicFeeCompleted" [completed]="counterfoilFeeCompleted">
|
||||
<ng-template matStepLabel>Counterfoil Setup</ng-template>
|
||||
|
||||
<app-counterfoil-fee *ngIf="serviceProviderId" [spid]="serviceProviderId"
|
||||
@ -64,7 +56,8 @@
|
||||
</mat-step>
|
||||
|
||||
<!-- Continuation Sheet Fee Step -->
|
||||
<mat-step [editable]="!!serviceProviderId && basicDetailsCompleted" [completed]="continuationSheetFeeCompleted">
|
||||
<mat-step [editable]="!!serviceProviderId && counterfoilFeeCompleted"
|
||||
[completed]="continuationSheetFeeCompleted">
|
||||
<ng-template matStepLabel>Continuation Sheet Fee Setup</ng-template>
|
||||
|
||||
<app-continuation-sheet-fee *ngIf="serviceProviderId" [spid]="serviceProviderId"
|
||||
@ -73,7 +66,7 @@
|
||||
</mat-step>
|
||||
|
||||
<!-- Expedited Fee Step -->
|
||||
<mat-step [editable]="!!serviceProviderId && basicDetailsCompleted" [completed]="expeditedFeeCompleted">
|
||||
<mat-step [editable]="!!serviceProviderId && continuationSheetFeeCompleted" [completed]="expeditedFeeCompleted">
|
||||
<ng-template matStepLabel>Expedited Fee Setup</ng-template>
|
||||
|
||||
<app-expedited-fee *ngIf="serviceProviderId" [spid]="serviceProviderId"
|
||||
@ -82,7 +75,7 @@
|
||||
</mat-step>
|
||||
|
||||
<!-- Security Deposit Step -->
|
||||
<mat-step [editable]="!!serviceProviderId && basicDetailsCompleted" [completed]="securityDepositCompleted">
|
||||
<mat-step [editable]="!!serviceProviderId && expeditedFeeCompleted" [completed]="securityDepositCompleted">
|
||||
<ng-template matStepLabel>Security Deposit</ng-template>
|
||||
|
||||
<app-security-deposit *ngIf="serviceProviderId" [spid]="serviceProviderId"
|
||||
@ -90,14 +83,5 @@
|
||||
[userPreferences]="userPreferences"></app-security-deposit>
|
||||
</mat-step>
|
||||
|
||||
<!-- Cargo Rate Step -->
|
||||
<mat-step [editable]="!!serviceProviderId && basicDetailsCompleted" [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>
|
||||
</div>
|
||||
@ -5,27 +5,24 @@ import { AngularMaterialModule } from '../../shared/module/angular-material.modu
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ContactsComponent } from '../contacts/contacts.component';
|
||||
import { CarnetSequenceComponent } from '../carnet-sequence/carnet-sequence.component';
|
||||
import { CarnetFeeComponent } from '../../fees/carnet-fee/carnet-fee.component';
|
||||
import { BasicFeeComponent } from '../../fees/basic-fee/basic-fee.component';
|
||||
import { CounterfoilFeeComponent } from '../../fees/counterfoil-fee/counterfoil-fee.component';
|
||||
import { ExpeditedFeeComponent } from '../../fees/expedited-fee/expedited-fee.component';
|
||||
import { SecurityDepositComponent } from '../../fees/security-deposit/security-deposit.component';
|
||||
import { ContinuationSheetFeeComponent } from "../../fees/continuation-sheet-fee/continuation-sheet-fee.component";
|
||||
import { CarnetFeeComponent } from '../carnet-fee/carnet-fee.component';
|
||||
import { BasicFeeComponent } from '../basic-fee/basic-fee.component';
|
||||
import { CounterfoilFeeComponent } from '../counterfoil-fee/counterfoil-fee.component';
|
||||
import { ExpeditedFeeComponent } from '../expedited-fee/expedited-fee.component';
|
||||
import { SecurityDepositComponent } from '../security-deposit/security-deposit.component';
|
||||
import { ContinuationSheetFeeComponent } from "../continuation-sheet-fee/continuation-sheet-fee.component";
|
||||
import { UserPreferences } from '../../core/models/user-preference';
|
||||
import { UserPreferencesService } from '../../core/services/user-preference.service';
|
||||
import { CargoRateComponent } from '../../fees/cargo-rate/cargo-rate.component';
|
||||
import { RegionComponent } from '../region/region.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-add-service-provider',
|
||||
imports: [BasicDetailsComponent, AngularMaterialModule, CommonModule, ContactsComponent, CarnetSequenceComponent,
|
||||
CarnetFeeComponent, BasicFeeComponent, CounterfoilFeeComponent, ExpeditedFeeComponent, SecurityDepositComponent, ContinuationSheetFeeComponent, CargoRateComponent, RegionComponent],
|
||||
CarnetFeeComponent, BasicFeeComponent, CounterfoilFeeComponent, ExpeditedFeeComponent, SecurityDepositComponent, ContinuationSheetFeeComponent],
|
||||
templateUrl: './add-service-provider.component.html',
|
||||
styleUrl: './add-service-provider.component.scss'
|
||||
})
|
||||
export class AddServiceProviderComponent {
|
||||
isEditMode = false;
|
||||
isLinear = true;
|
||||
serviceProviderId: number | null = null;
|
||||
currentStep: number = 0;
|
||||
isLoading: boolean = false;
|
||||
@ -40,8 +37,6 @@ export class AddServiceProviderComponent {
|
||||
continuationSheetFeeCompleted: boolean = false;
|
||||
expeditedFeeCompleted: boolean = false;
|
||||
securityDepositCompleted: boolean = false;
|
||||
cargoRateCompleted: boolean = false;
|
||||
regionCompleted: boolean = false;
|
||||
|
||||
constructor(userPrefenceService: UserPreferencesService) {
|
||||
this.userPreferences = userPrefenceService.getPreferences();
|
||||
@ -50,7 +45,6 @@ export class AddServiceProviderComponent {
|
||||
onBasicDetailsSaved(event: string): void {
|
||||
this.serviceProviderId = +event;
|
||||
this.basicDetailsCompleted = true;
|
||||
this.isLinear = false; // Disable linear mode after basic detail is created
|
||||
}
|
||||
|
||||
onContactsSaved(event: boolean): void {
|
||||
@ -85,14 +79,6 @@ export class AddServiceProviderComponent {
|
||||
this.securityDepositCompleted = event;
|
||||
}
|
||||
|
||||
onCargoRateSaved(event: boolean): void {
|
||||
this.cargoRateCompleted = event;
|
||||
}
|
||||
|
||||
onRegionsSaved(event: boolean): void {
|
||||
this.regionCompleted = event;
|
||||
}
|
||||
|
||||
onStepChange(event: StepperSelectionEvent): void {
|
||||
this.currentStep = event.selectedIndex;
|
||||
}
|
||||
|
||||
@ -139,37 +139,45 @@
|
||||
<div class="form-row">
|
||||
<mat-form-field appearance="outline" class="cargo-surety">
|
||||
<mat-label>Cargo Surety</mat-label>
|
||||
<mat-select formControlName="cargoSurety">
|
||||
<mat-select formControlName="cargoSurety" required>
|
||||
<mat-option *ngFor="let cargoSurety of cargoSuretys" [value]="cargoSurety.value">
|
||||
{{ cargoSurety.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="f['cargoSurety'].errors?.['required']">
|
||||
Cargo Surety is required
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="cargo-policy">
|
||||
<mat-label>Cargo Policy</mat-label>
|
||||
<mat-select formControlName="cargoPolicyNo">
|
||||
<mat-select formControlName="cargoPolicyNo" required>
|
||||
<mat-option *ngFor="let cargoPolicy of cargoPolicies" [value]="cargoPolicy.value">
|
||||
{{ cargoPolicy.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="f['cargoPolicyNo'].errors?.['required']">
|
||||
Cargo Policy is required
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="bond-surety">
|
||||
<mat-label>Bond Surety</mat-label>
|
||||
<mat-select formControlName="bondSurety">
|
||||
<mat-select formControlName="bondSurety" required>
|
||||
<mat-option *ngFor="let bondSurety of bondSuretys" [value]="bondSurety.value">
|
||||
{{ bondSurety.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="f['bondSurety'].errors?.['required']">
|
||||
Bond Surety is required
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button mat-raised-button color="primary" type="submit"
|
||||
[disabled]="basicDetailsForm.invalid || changeInProgress">
|
||||
{{ isEditMode ? 'Update' : 'Save' }}
|
||||
<button mat-raised-button color="primary" type="submit" [disabled]="basicDetailsForm.invalid">
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Component, Input, OnInit, Output, EventEmitter, OnDestroy, inject } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { Subject } from 'rxjs';
|
||||
import { finalize, takeUntil } from 'rxjs/operators';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { BasicDetail } from '../../core/models/service-provider/basic-detail';
|
||||
import { Country } from '../../core/models/country';
|
||||
import { Region } from '../../core/models/region';
|
||||
@ -38,7 +38,6 @@ export class BasicDetailsComponent implements OnInit, OnDestroy {
|
||||
cargoPolicies: CargoPolicy[] = [];
|
||||
|
||||
isLoading = true;
|
||||
changeInProgress = false;
|
||||
countriesHasStates = ['US', 'CA', 'MX'];
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
@ -58,24 +57,21 @@ export class BasicDetailsComponent implements OnInit, OnDestroy {
|
||||
// this.spidCreated.emit(this.spid?.toString());
|
||||
// Patch edit form data
|
||||
if (this.spid > 0) {
|
||||
this.isLoading = true;
|
||||
this.basicDetailService.getBasicDetailsById(this.spid).pipe(finalize(() => {
|
||||
this.isLoading = false;
|
||||
})).subscribe({
|
||||
this.basicDetailService.getBasicDetailsById(this.spid).subscribe({
|
||||
next: (basicDetail: BasicDetail) => {
|
||||
if (basicDetail?.spid > 0) {
|
||||
this.patchFormData(basicDetail);
|
||||
this.serviceProviderName.emit(basicDetail.companyName);
|
||||
}
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error: any) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load basic details');
|
||||
this.notificationService.showError(errorMessage);
|
||||
this.isLoading = false;
|
||||
console.error('Error loading basic details:', error);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.loadStates('US');
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,19 +87,19 @@ export class BasicDetailsComponent implements OnInit, OnDestroy {
|
||||
address1: ['', [Validators.required, Validators.maxLength(100)]],
|
||||
address2: ['', [Validators.maxLength(100)]],
|
||||
city: ['', [Validators.required, Validators.maxLength(50)]],
|
||||
country: ['US', Validators.required],
|
||||
country: ['', Validators.required],
|
||||
state: ['', Validators.required],
|
||||
zip: ['', [Validators.required, ZipCodeValidator('country')]],
|
||||
issuingRegion: ['', Validators.required],
|
||||
replacementRegion: ['', Validators.required],
|
||||
cargoSurety: [''],
|
||||
cargoPolicyNo: [''],
|
||||
bondSurety: ['']
|
||||
cargoSurety: ['', Validators.required],
|
||||
cargoPolicyNo: ['', Validators.required],
|
||||
bondSurety: ['', Validators.required]
|
||||
});
|
||||
}
|
||||
|
||||
loadLookupData(): void {
|
||||
this.commonService.getCountries()
|
||||
this.commonService.getCountries(this.spid)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe({
|
||||
next: (countries) => {
|
||||
@ -111,6 +107,7 @@ export class BasicDetailsComponent implements OnInit, OnDestroy {
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Failed to load countries', error);
|
||||
this.isLoading = false;
|
||||
}
|
||||
});
|
||||
|
||||
@ -126,9 +123,11 @@ export class BasicDetailsComponent implements OnInit, OnDestroy {
|
||||
.subscribe({
|
||||
next: (regions) => {
|
||||
this.regions = regions;
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Failed to load regions', error);
|
||||
this.isLoading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -136,10 +135,9 @@ export class BasicDetailsComponent implements OnInit, OnDestroy {
|
||||
loadStates(country: string): void {
|
||||
this.isLoading = true;
|
||||
country = this.countriesHasStates.includes(country) ? country : 'FN';
|
||||
this.commonService.getStates(country)
|
||||
.pipe(takeUntil(this.destroy$), finalize(() => {
|
||||
this.isLoading = false;
|
||||
})).subscribe({
|
||||
this.commonService.getStates(country, this.spid)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe({
|
||||
next: (states) => {
|
||||
this.states = states;
|
||||
const stateControl = this.basicDetailsForm.get('state');
|
||||
@ -149,9 +147,11 @@ export class BasicDetailsComponent implements OnInit, OnDestroy {
|
||||
stateControl?.disable();
|
||||
stateControl?.setValue('FN');
|
||||
}
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Failed to load states', error);
|
||||
this.isLoading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -162,9 +162,11 @@ export class BasicDetailsComponent implements OnInit, OnDestroy {
|
||||
.subscribe({
|
||||
next: (bondSuretys) => {
|
||||
this.bondSuretys = bondSuretys;
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Failed to load bond suretys', error);
|
||||
this.isLoading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -175,9 +177,11 @@ export class BasicDetailsComponent implements OnInit, OnDestroy {
|
||||
.subscribe({
|
||||
next: (cargoSuretys) => {
|
||||
this.cargoSuretys = cargoSuretys;
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Failed to load cargo suretys', error);
|
||||
this.isLoading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -188,9 +192,11 @@ export class BasicDetailsComponent implements OnInit, OnDestroy {
|
||||
.subscribe({
|
||||
next: (cargoPolicies) => {
|
||||
this.cargoPolicies = cargoPolicies;
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Failed to load cargo policies', error);
|
||||
this.isLoading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -214,8 +220,6 @@ export class BasicDetailsComponent implements OnInit, OnDestroy {
|
||||
|
||||
if (data.country) {
|
||||
this.loadStates(data.country);
|
||||
} else {
|
||||
this.loadStates('US');
|
||||
}
|
||||
|
||||
if (this.isEditMode) {
|
||||
@ -266,17 +270,12 @@ export class BasicDetailsComponent implements OnInit, OnDestroy {
|
||||
? this.basicDetailService.updateBasicDetails(this.spid, basicDetailData)
|
||||
: this.basicDetailService.createBasicDetails(basicDetailData);
|
||||
|
||||
this.changeInProgress = true;
|
||||
saveObservable.pipe(finalize(() => this.changeInProgress = false)).subscribe({
|
||||
saveObservable.subscribe({
|
||||
next: (basicData: any) => {
|
||||
this.notificationService.showSuccess(`Basic details ${this.isEditMode ? 'updated' : 'added'} successfully`);
|
||||
|
||||
if (!this.isEditMode) {
|
||||
this.spidCreated.emit(basicData.SPID);
|
||||
|
||||
// change to edit mode after creation
|
||||
this.isEditMode = true;
|
||||
this.spid = basicData.SPID;
|
||||
}
|
||||
},
|
||||
error: (error) => {
|
||||
|
||||
@ -1,9 +1,4 @@
|
||||
<div class="basic-fee-container">
|
||||
<div class="actions-bar">
|
||||
<mat-slide-toggle (change)="toggleShowExpiredRecords()">
|
||||
Show Expired Records
|
||||
</mat-slide-toggle>
|
||||
</div>
|
||||
|
||||
<div class="table-container mat-elevation-z8">
|
||||
<div class="loading-shade" *ngIf="isLoading">
|
||||
@ -37,12 +32,6 @@
|
||||
<td mat-cell *matCellDef="let fee">{{ fee.effectiveDate | date:'mediumDate':'UTC' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Expired Date Column -->
|
||||
<ng-container matColumnDef="expiredDate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Expired Date</th>
|
||||
<td mat-cell *matCellDef="let fee">{{ fee.expiredDate | date:'mediumDate':'UTC' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Actions Column -->
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>Actions</th>
|
||||
@ -64,8 +53,8 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator *ngIf="dataSource.data.length > userPreferences.pageSize!" [length]="dataSource.data.length"
|
||||
[pageSizeOptions]="[userPreferences.pageSize!]" [hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
<mat-paginator [length]="dataSource.data.length" [pageSizeOptions]="[userPreferences.pageSize!]"
|
||||
[hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
|
||||
<!-- Fee Form -->
|
||||
@ -147,11 +136,10 @@
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button mat-raised-button color="primary" type="submit"
|
||||
[disabled]="feeForm.invalid || changeInProgress">
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
<button mat-raised-button color="primary" type="submit" [disabled]="feeForm.invalid">
|
||||
{{ isEditing ? 'Update' : 'Save' }}
|
||||
</button>
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -1,19 +1,9 @@
|
||||
.basic-fee-container {
|
||||
padding: 0.5rem;
|
||||
padding: 24px;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
.table-container {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
@ -72,7 +62,7 @@
|
||||
margin-top: 16px;
|
||||
|
||||
.form-header {
|
||||
// margin-bottom: 24px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
@ -89,7 +79,6 @@
|
||||
.form-row {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
|
||||
mat-form-field {
|
||||
flex: 1;
|
||||
@ -141,7 +130,7 @@
|
||||
|
||||
.readonly-value {
|
||||
padding: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
font-size: 0.9375rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
@ -2,16 +2,16 @@ import { Component, EventEmitter, inject, Input, Output, ViewChild } from '@angu
|
||||
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
|
||||
import { MatSort } from '@angular/material/sort';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { BasicFee } from '../../core/models/fees/basic-fee';
|
||||
import { BasicFee } from '../../core/models/service-provider/basic-fee';
|
||||
import { AngularMaterialModule } from '../../shared/module/angular-material.module';
|
||||
import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CustomPaginator } from '../../shared/custom-paginator';
|
||||
import { concat, finalize } from 'rxjs';
|
||||
import { forkJoin } from 'rxjs';
|
||||
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 { BasicFeeService } from '../../core/services/fees/basic-fee.service';
|
||||
import { BasicFeeService } from '../../core/services/service-provider/basic-fee.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-basic-fee',
|
||||
@ -21,23 +21,16 @@ import { BasicFeeService } from '../../core/services/fees/basic-fee.service';
|
||||
providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }],
|
||||
})
|
||||
export class BasicFeeComponent {
|
||||
@ViewChild(MatPaginator, { static: false })
|
||||
set paginator(value: MatPaginator) {
|
||||
this.dataSource.paginator = value;
|
||||
}
|
||||
|
||||
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||
@ViewChild(MatSort) sort!: MatSort;
|
||||
|
||||
displayedColumns: string[] = ['startCarnetValue', 'endCarnetValue', 'fees', 'effectiveDate', 'expiredDate', 'actions'];
|
||||
displayedColumns: string[] = ['startCarnetValue', 'endCarnetValue', 'fees', 'effectiveDate', 'actions'];
|
||||
dataSource = new MatTableDataSource<BasicFee>();
|
||||
feeForm: FormGroup;
|
||||
isEditing = false;
|
||||
currentFeeId: number | null = null;
|
||||
isLoading = false;
|
||||
changeInProgress = false;
|
||||
showForm = false;
|
||||
showExpiredRecords = false;
|
||||
basicFees: BasicFee[] = [];
|
||||
|
||||
readOnlyFields: any = {
|
||||
lastChangedDate: null,
|
||||
@ -74,14 +67,11 @@ export class BasicFeeComponent {
|
||||
|
||||
loadBasicFees(): void {
|
||||
this.isLoading = true;
|
||||
this.basicFeeService.getBasicFees(this.spid).pipe(finalize(() => {
|
||||
this.isLoading = false;
|
||||
})).subscribe({
|
||||
this.basicFeeService.getBasicFees(this.spid).subscribe({
|
||||
next: (fees) => {
|
||||
this.basicFees = fees;
|
||||
this.dataSource.data = this.basicFees;
|
||||
this.renderRecods();
|
||||
this.dataSource.data = fees;
|
||||
this.hasBasicFees.emit(fees.length > 0);
|
||||
this.isLoading = false;
|
||||
|
||||
if (this.dataSource.data.length == 0) {
|
||||
this.initializeDefaultFees();
|
||||
@ -90,32 +80,21 @@ export class BasicFeeComponent {
|
||||
error: (error) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load basic fees');
|
||||
this.notificationService.showError(errorMessage);
|
||||
this.isLoading = false;
|
||||
console.error('Error loading basic fees:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toggleShowExpiredRecords(): void {
|
||||
this.showExpiredRecords = !this.showExpiredRecords;
|
||||
this.renderRecods();
|
||||
}
|
||||
|
||||
renderRecods(): void {
|
||||
if (this.showExpiredRecords) {
|
||||
this.dataSource.data = this.basicFees.filter(record => record.expired);
|
||||
} else {
|
||||
this.dataSource.data = this.basicFees.filter(record => !record.expired);
|
||||
}
|
||||
}
|
||||
|
||||
initializeDefaultFees(): void {
|
||||
this.isLoading = true;
|
||||
const defaultFees: BasicFee[] = [
|
||||
{ basicFeeId: 0, startCarnetValue: 1, endCarnetValue: 9999, fees: 255, effectiveDate: new Date() },
|
||||
{ basicFeeId: 0, startCarnetValue: 10000, endCarnetValue: 49999, fees: 300, effectiveDate: new Date() },
|
||||
{ basicFeeId: 0, startCarnetValue: 50000, endCarnetValue: 149999, fees: 365, effectiveDate: new Date() },
|
||||
{ basicFeeId: 0, startCarnetValue: 150000, endCarnetValue: 399999, fees: 425, effectiveDate: new Date() },
|
||||
{ basicFeeId: 0, startCarnetValue: 400000, endCarnetValue: 999999, fees: 480, effectiveDate: new Date() },
|
||||
{ basicFeeId: 0, startCarnetValue: 1000000, endCarnetValue: 99999999, fees: 545, effectiveDate: new Date() }
|
||||
{ basicFeeId: 0, startCarnetValue: 1000000, endCarnetValue: null, fees: 545, effectiveDate: new Date() }
|
||||
];
|
||||
|
||||
// Create an array of observables for each fee creation
|
||||
@ -123,21 +102,17 @@ export class BasicFeeComponent {
|
||||
this.basicFeeService.createBasicFee(this.spid, fee)
|
||||
);
|
||||
|
||||
this.changeInProgress = true;
|
||||
|
||||
// Execute all creations in sequence
|
||||
concat(...creationObservables).pipe(
|
||||
finalize(() => {
|
||||
this.changeInProgress = false;
|
||||
})
|
||||
).subscribe({
|
||||
// Execute all creations in parallel and wait for all to complete
|
||||
forkJoin(creationObservables).subscribe({
|
||||
next: () => {
|
||||
},
|
||||
complete: () => {
|
||||
this.loadBasicFees(); // Refresh the list after all creations are done
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error) => {
|
||||
this.isLoading = false;
|
||||
console.error('Error initializing default fees:', error);
|
||||
// Even if some failed, try to load what was created
|
||||
this.loadBasicFees();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -200,11 +175,7 @@ export class BasicFeeComponent {
|
||||
? this.basicFeeService.updateBasicFee(this.currentFeeId, feeData)
|
||||
: this.basicFeeService.createBasicFee(this.spid, feeData);
|
||||
|
||||
this.changeInProgress = true;
|
||||
|
||||
saveObservable.pipe(finalize(() => {
|
||||
this.changeInProgress = false;
|
||||
})).subscribe({
|
||||
saveObservable.subscribe({
|
||||
next: () => {
|
||||
this.notificationService.showSuccess(`Basic fee ${this.isEditing ? 'updated' : 'added'} successfully`);
|
||||
this.loadBasicFees();
|
||||
@ -1,9 +1,6 @@
|
||||
<div class="fee-commission-container">
|
||||
<div class="actions-bar">
|
||||
<mat-slide-toggle (change)="toggleShowExpiredRecords()">
|
||||
Show Expired Records
|
||||
</mat-slide-toggle>
|
||||
<button mat-raised-button color="primary" (click)="addNewFeeCommission()">
|
||||
<button mat-raised-button color="primary" *ngIf="!isEditMode" (click)="addNewFeeCommission()">
|
||||
<mat-icon>add</mat-icon> Add New Fee & Commission
|
||||
</button>
|
||||
</div>
|
||||
@ -23,7 +20,7 @@
|
||||
<!-- Commission Rate Column -->
|
||||
<ng-container matColumnDef="commissionRate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Commission Rate</th>
|
||||
<td mat-cell *matCellDef="let item">{{ item.commissionRate | number:'1.2-2' }}</td>
|
||||
<td mat-cell *matCellDef="let item">{{ item.commissionRate }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Effective Date Column -->
|
||||
@ -32,12 +29,6 @@
|
||||
<td mat-cell *matCellDef="let item">{{ item.effectiveDate | date:'mediumDate':'UTC' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Expired Date Column -->
|
||||
<ng-container matColumnDef="expiredDate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Expired Date</th>
|
||||
<td mat-cell *matCellDef="let fee">{{ fee.expiredDate | date:'mediumDate':'UTC' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Actions Column -->
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>Actions</th>
|
||||
@ -63,8 +54,8 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator *ngIf="dataSource.data.length > userPreferences.pageSize!" [length]="dataSource.data.length"
|
||||
[pageSizeOptions]="[userPreferences.pageSize!]" [hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
<mat-paginator [length]="dataSource.data.length" [pageSizeOptions]="[userPreferences.pageSize!]"
|
||||
[hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
|
||||
<!-- Fee & Commission Form -->
|
||||
@ -86,16 +77,15 @@
|
||||
Fee type is required
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Commission Rate</mat-label>
|
||||
<input matInput type="number" formControlName="commissionRate">
|
||||
<mat-error *ngIf="feeCommissionForm.get('commissionRate')?.errors?.['required']">
|
||||
Commission rate is required
|
||||
</mat-error>
|
||||
<mat-error *ngIf="feeCommissionForm.get('commissionRate')?.errors?.['pattern']">
|
||||
Please enter a valid number with up to 2 decimal places
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
@ -133,11 +123,10 @@
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button mat-raised-button color="primary" type="submit"
|
||||
[disabled]="feeCommissionForm.invalid || changeInProgress">
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
<button mat-raised-button color="primary" type="submit" [disabled]="feeCommissionForm.invalid">
|
||||
{{ isEditing ? 'Update' : 'Save' }}
|
||||
</button>
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -1,5 +1,5 @@
|
||||
.fee-commission-container {
|
||||
padding: 0.5rem;
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
@ -8,11 +8,6 @@
|
||||
clear: both;
|
||||
margin-bottom: -16px;
|
||||
|
||||
mat-slide-toggle {
|
||||
transform: scale(0.8);
|
||||
margin-left: -0.5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
float: right;
|
||||
}
|
||||
@ -81,7 +76,7 @@
|
||||
margin-top: 16px;
|
||||
|
||||
.form-header {
|
||||
// margin-bottom: 24px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
@ -98,7 +93,6 @@
|
||||
.form-row {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
|
||||
mat-form-field {
|
||||
flex: 1;
|
||||
@ -146,7 +140,7 @@
|
||||
|
||||
.readonly-value {
|
||||
padding: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
font-size: 0.9375rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
@ -7,14 +7,13 @@ 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 { CarnetFee } from '../../core/models/fees/carnet-fee';
|
||||
import { CarnetFee } from '../../core/models/service-provider/carnet-fee';
|
||||
import { FeeType } from '../../core/models/fee-type';
|
||||
import { UserPreferences } from '../../core/models/user-preference';
|
||||
import { ApiErrorHandlerService } from '../../core/services/common/api-error-handler.service';
|
||||
import { CommonService } from '../../core/services/common/common.service';
|
||||
import { NotificationService } from '../../core/services/common/notification.service';
|
||||
import { CarnetFeeService } from '../../core/services/fees/carnet-fee.service';
|
||||
import { finalize } from 'rxjs';
|
||||
import { CarnetFeeService } from '../../core/services/service-provider/carnet-fee.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-carnet-fee',
|
||||
@ -24,24 +23,18 @@ import { finalize } from 'rxjs';
|
||||
providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }],
|
||||
})
|
||||
export class CarnetFeeComponent implements OnInit {
|
||||
@ViewChild(MatPaginator, { static: false })
|
||||
set paginator(value: MatPaginator) {
|
||||
this.dataSource.paginator = value;
|
||||
}
|
||||
|
||||
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||
@ViewChild(MatSort) sort!: MatSort;
|
||||
|
||||
displayedColumns: string[] = ['feeType', 'commissionRate', 'effectiveDate', 'expiredDate', 'actions'];
|
||||
displayedColumns: string[] = ['feeType', 'commissionRate', 'effectiveDate', 'actions'];
|
||||
dataSource = new MatTableDataSource<CarnetFee>();
|
||||
feeCommissionForm: FormGroup;
|
||||
isEditing = false;
|
||||
currentFeeCommissionId: number | null = null;
|
||||
isLoading = false;
|
||||
changeInProgress = false;
|
||||
showForm = false;
|
||||
feeTypes: FeeType[] = [];
|
||||
showExpiredRecords = false;
|
||||
carnetFees: CarnetFee[] = [];
|
||||
|
||||
readOnlyFields: any = {
|
||||
lastChangedDate: null,
|
||||
@ -62,7 +55,7 @@ export class CarnetFeeComponent implements OnInit {
|
||||
constructor() {
|
||||
this.feeCommissionForm = this.fb.group({
|
||||
feeType: ['', Validators.required],
|
||||
commissionRate: [0, [Validators.required, Validators.pattern(/^\d+\.?\d{0,2}$/)]],
|
||||
commissionRate: [0, [Validators.required]],
|
||||
effectiveDate: ['', Validators.required]
|
||||
});
|
||||
}
|
||||
@ -79,36 +72,21 @@ export class CarnetFeeComponent implements OnInit {
|
||||
|
||||
loadFeeCommissions(): void {
|
||||
this.isLoading = true;
|
||||
this.feeCommissionService.getFeeCommissions(this.spid).pipe(finalize(() => {
|
||||
this.isLoading = false;
|
||||
})).subscribe({
|
||||
this.feeCommissionService.getFeeCommissions(this.spid).subscribe({
|
||||
next: (fees) => {
|
||||
this.carnetFees = fees;
|
||||
this.dataSource.data = this.carnetFees;
|
||||
this.renderRecods();
|
||||
this.dataSource.data = fees;
|
||||
this.hasFeeCommissions.emit(fees.length > 0);
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load fee & commission data');
|
||||
this.notificationService.showError(errorMessage);
|
||||
this.isLoading = false;
|
||||
console.error('Error loading fee & commission data:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toggleShowExpiredRecords(): void {
|
||||
this.showExpiredRecords = !this.showExpiredRecords;
|
||||
this.renderRecods();
|
||||
}
|
||||
|
||||
renderRecods(): void {
|
||||
if (this.showExpiredRecords) {
|
||||
this.dataSource.data = this.carnetFees.filter(record => record.expired);
|
||||
} else {
|
||||
this.dataSource.data = this.carnetFees.filter(record => !record.expired);
|
||||
}
|
||||
}
|
||||
|
||||
loadFeeTypes(): void {
|
||||
this.commonService.getFeeTypes().subscribe({
|
||||
next: (types) => {
|
||||
@ -173,10 +151,7 @@ export class CarnetFeeComponent implements OnInit {
|
||||
? this.feeCommissionService.updateFeeCommission(this.currentFeeCommissionId, feeCommissionData)
|
||||
: this.feeCommissionService.createFeeCommission(this.spid, feeCommissionData);
|
||||
|
||||
this.changeInProgress = true;
|
||||
saveObservable.pipe(finalize(() => {
|
||||
this.changeInProgress = false;
|
||||
})).subscribe({
|
||||
saveObservable.subscribe({
|
||||
next: () => {
|
||||
this.notificationService.showSuccess(`Fee & commission ${this.isEditing ? 'updated' : 'added'} successfully`);
|
||||
this.loadFeeCommissions();
|
||||
@ -1,6 +1,6 @@
|
||||
<div class="carnet-sequence-container">
|
||||
<div class="actions-bar">
|
||||
<button mat-raised-button color="primary" (click)="addNewSequence()">
|
||||
<button mat-raised-button color="primary" *ngIf="!isEditMode" (click)="addNewSequence()">
|
||||
<mat-icon>add</mat-icon> Add New Sequence
|
||||
</button>
|
||||
</div>
|
||||
@ -65,8 +65,8 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator *ngIf="dataSource.data.length > userPreferences.pageSize!" [length]="dataSource.data.length"
|
||||
[pageSizeOptions]="[userPreferences.pageSize!]" [hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
<mat-paginator [length]="dataSource.data.length" [pageSizeOptions]="[userPreferences.pageSize!]"
|
||||
[hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
|
||||
<!-- Sequence Form -->
|
||||
@ -138,11 +138,10 @@
|
||||
</mat-error>
|
||||
|
||||
<div class="form-actions">
|
||||
<button mat-raised-button color="primary" type="submit"
|
||||
[disabled]="sequenceForm.invalid || changeInProgress">
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
<button mat-raised-button color="primary" type="submit" [disabled]="sequenceForm.invalid">
|
||||
{{ isEditing ? 'Update' : 'Save' }}
|
||||
</button>
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
.carnet-sequence-container {
|
||||
padding: 0.5rem;
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
@ -99,7 +99,6 @@
|
||||
.form-row {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
|
||||
mat-form-field {
|
||||
flex: 1;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Component, EventEmitter, inject, Input, OnInit, Output, ViewChild } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { CarnetSequence } from '../../core/models/service-provider/carnet-sequence';
|
||||
import { finalize, Subject, takeUntil } from 'rxjs';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
import { Region } from '../../core/models/region';
|
||||
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
|
||||
import { MatSort } from '@angular/material/sort';
|
||||
@ -23,11 +23,7 @@ import { CarnetSequenceService } from '../../core/services/service-provider/carn
|
||||
providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }],
|
||||
})
|
||||
export class CarnetSequenceComponent implements OnInit {
|
||||
@ViewChild(MatPaginator, { static: false })
|
||||
set paginator(value: MatPaginator) {
|
||||
this.dataSource.paginator = value;
|
||||
}
|
||||
|
||||
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||
@ViewChild(MatSort) sort!: MatSort;
|
||||
|
||||
displayedColumns: string[] = ['carnetType', 'region', 'startNumber', 'endNumber', 'lastNumber'];
|
||||
@ -36,7 +32,6 @@ export class CarnetSequenceComponent implements OnInit {
|
||||
isEditing = false;
|
||||
currentSequenceId: string | null = null;
|
||||
isLoading = false;
|
||||
changeInProgress = false;
|
||||
showForm = false;
|
||||
|
||||
carnetTypes = [
|
||||
@ -103,9 +98,11 @@ export class CarnetSequenceComponent implements OnInit {
|
||||
.subscribe({
|
||||
next: (regions) => {
|
||||
this.regions = regions;
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Failed to load regions', error);
|
||||
this.isLoading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -116,15 +113,17 @@ export class CarnetSequenceComponent implements OnInit {
|
||||
|
||||
this.isLoading = true;
|
||||
|
||||
this.carnetSequenceService.getCarnetSequenceById(this.spid).pipe(finalize(() => {
|
||||
this.isLoading = false;
|
||||
})).subscribe({
|
||||
this.carnetSequenceService.getCarnetSequenceById(this.spid).subscribe({
|
||||
next: (carnetSequences: CarnetSequence[]) => {
|
||||
// this.sequences = carnetSequences;
|
||||
this.isLoading = false;
|
||||
this.dataSource.data = carnetSequences;
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error: any) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load sequences');
|
||||
this.notificationService.showError(errorMessage);
|
||||
this.isLoading = false;
|
||||
console.error('Error loading sequences:', error);
|
||||
}
|
||||
});
|
||||
@ -142,10 +141,7 @@ export class CarnetSequenceComponent implements OnInit {
|
||||
lastNumber: this.sequenceForm.value.startNumber
|
||||
};
|
||||
|
||||
this.changeInProgress = true;
|
||||
this.carnetSequenceService.createCarnetSequence(sequenceData).pipe(finalize(() => {
|
||||
this.changeInProgress = false;
|
||||
})).subscribe({
|
||||
this.carnetSequenceService.createCarnetSequence(sequenceData).subscribe({
|
||||
next: () => {
|
||||
this.notificationService.showSuccess('Sequence added successfully');
|
||||
this.loadSequences();
|
||||
@ -186,10 +182,7 @@ export class CarnetSequenceComponent implements OnInit {
|
||||
spid: this.spid
|
||||
};
|
||||
|
||||
this.changeInProgress = true;
|
||||
this.carnetSequenceService.createCarnetSequence(sequenceData).pipe(finalize(() => {
|
||||
this.changeInProgress = false;
|
||||
}))
|
||||
this.carnetSequenceService.createCarnetSequence(sequenceData)
|
||||
.subscribe({
|
||||
next: () => {
|
||||
this.notificationService.showSuccess('Sequence added successfully');
|
||||
|
||||
@ -4,10 +4,6 @@
|
||||
<mat-icon matPrefix>search</mat-icon>
|
||||
<input matInput (keyup)="applyFilter($event)" placeholder="Search contacts...">
|
||||
</mat-form-field> -->
|
||||
<mat-slide-toggle (change)="toggleShowInactiveContacts()">
|
||||
Show Inactive Contacts
|
||||
</mat-slide-toggle>
|
||||
|
||||
<button mat-raised-button color="primary" (click)="addNewContact()">
|
||||
<mat-icon>add</mat-icon> Add New Contact
|
||||
</button>
|
||||
@ -25,12 +21,6 @@
|
||||
<td mat-cell *matCellDef="let contact">{{ contact.firstName }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Middle Initial Column -->
|
||||
<ng-container matColumnDef="middleInitial">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Middle Initial</th>
|
||||
<td mat-cell *matCellDef="let contact">{{ contact.middleInitial }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Last Name Column -->
|
||||
<ng-container matColumnDef="lastName">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Last Name</th>
|
||||
@ -40,7 +30,7 @@
|
||||
<!-- Title Column -->
|
||||
<ng-container matColumnDef="title">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Title</th>
|
||||
<td mat-cell *matCellDef="let contact">{{ getContactTitleLabel(contact.title) }}</td>
|
||||
<td mat-cell *matCellDef="let contact">{{ contact.title }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Phone Column -->
|
||||
@ -49,18 +39,6 @@
|
||||
<td mat-cell *matCellDef="let contact">{{ contact.phone | phone }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Mobile Column -->
|
||||
<ng-container matColumnDef="mobile">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Mobile</th>
|
||||
<td mat-cell *matCellDef="let contact">{{ contact.mobile }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Fax Column -->
|
||||
<ng-container matColumnDef="fax">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Fax</th>
|
||||
<td mat-cell *matCellDef="let contact">{{ contact.fax }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Email Column -->
|
||||
<ng-container matColumnDef="email">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Email</th>
|
||||
@ -84,21 +62,15 @@
|
||||
<button mat-icon-button color="primary" (click)="editContact(contact)" matTooltip="Edit">
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button color="primary" *ngIf="!contact.isInactive || !contact.hasLogin"
|
||||
[hidden]="contact.isInactive || contact.hasLogin" (click)="createLogin(contact.email)"
|
||||
matTooltip="Login">
|
||||
<mat-icon>person</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button color="warn" *ngIf="!contact.defaultContact || !contact.isInactive" (click)="
|
||||
deleteContact(contact.spContactId)" [hidden]="contact.defaultContact || contact.isInactive"
|
||||
matTooltip="Delete">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button (click)="setDefaultContact(contact.spContactId)"
|
||||
*ngIf="!contact.defaultContact || !contact.isInactive"
|
||||
[hidden]="contact.defaultContact || contact.isInactive" matTooltip="Set as default contact">
|
||||
<!-- <button mat-icon-button (click)="setDefaultContact(contact.contactId)"
|
||||
[color]="contact.defaultContact ? 'primary' : ''" matTooltip="Set as default">
|
||||
<mat-icon>star</mat-icon>
|
||||
</button>
|
||||
</button> -->
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
@ -113,8 +85,8 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator *ngIf="dataSource.data.length > userPreferences.pageSize!" [length]="dataSource.data.length"
|
||||
[pageSizeOptions]="[userPreferences.pageSize!]" [hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
<mat-paginator [length]="dataSource.data.length" [pageSizeOptions]="[userPreferences.pageSize!]"
|
||||
[hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
|
||||
<!-- Contact Form -->
|
||||
@ -159,16 +131,17 @@
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Title</mat-label>
|
||||
<mat-select formControlName="title" required>
|
||||
<mat-option *ngFor="let contactTitle of contactTitles" [value]="contactTitle.value">
|
||||
{{ contactTitle.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<input matInput formControlName="title" required>
|
||||
<mat-icon matSuffix>work</mat-icon>
|
||||
<mat-error *ngIf="contactForm.get('title')?.errors?.['required']">
|
||||
Title is required
|
||||
</mat-error>
|
||||
<mat-error *ngIf="contactForm.get('title')?.errors?.['maxlength']">
|
||||
Maximum 100 characters allowed
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
@ -270,11 +243,10 @@
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button mat-raised-button color="primary" type="submit"
|
||||
[disabled]="contactForm.invalid || changeInProgress">
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
<button mat-raised-button color="primary" type="submit" [disabled]="contactForm.invalid">
|
||||
{{ isEditing ? 'Update' : 'Save' }}
|
||||
</button>
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
.contacts-container {
|
||||
padding: 0.5rem;
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
@ -8,11 +8,6 @@
|
||||
clear: both;
|
||||
margin-bottom: -16px;
|
||||
|
||||
mat-slide-toggle {
|
||||
transform: scale(0.8);
|
||||
margin-left: -0.5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
float: right;
|
||||
}
|
||||
@ -86,7 +81,7 @@
|
||||
margin-top: 16px;
|
||||
|
||||
.form-header {
|
||||
// margin-bottom: 24px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
@ -103,7 +98,6 @@
|
||||
.form-row {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
|
||||
mat-form-field {
|
||||
flex: 1;
|
||||
@ -147,7 +141,7 @@
|
||||
|
||||
.readonly-value {
|
||||
padding: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
font-size: 0.9375rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@ -14,10 +14,6 @@ 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 { ContactService } from '../../core/services/service-provider/contact.service';
|
||||
import { finalize, Subject, takeUntil } from 'rxjs';
|
||||
import { ContactLogin } from '../../core/models/service-provider/contact-login';
|
||||
import { CommonService } from '../../core/services/common/common.service';
|
||||
import { ContactTitle } from '../../core/models/contact-title';
|
||||
|
||||
@Component({
|
||||
selector: 'app-contacts',
|
||||
@ -27,24 +23,16 @@ import { ContactTitle } from '../../core/models/contact-title';
|
||||
providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }],
|
||||
})
|
||||
export class ContactsComponent implements OnInit {
|
||||
@ViewChild(MatPaginator, { static: false })
|
||||
set paginator(value: MatPaginator) {
|
||||
this.dataSource.paginator = value;
|
||||
}
|
||||
|
||||
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||
@ViewChild(MatSort) sort!: MatSort;
|
||||
|
||||
displayedColumns: string[] = ['firstName', 'middleInitial', 'lastName', 'title', 'phone', 'mobile', 'fax', 'email', 'defaultContact', 'actions'];
|
||||
displayedColumns: string[] = ['firstName', 'lastName', 'title', 'phone', 'email', 'defaultContact', 'actions'];
|
||||
dataSource = new MatTableDataSource<any>();
|
||||
contactForm: FormGroup;
|
||||
isEditing = false;
|
||||
currentContactId: number | null = null;
|
||||
isLoading = false;
|
||||
changeInProgress = false;
|
||||
showForm = false;
|
||||
showInactiveContacts = false;
|
||||
contacts: Contact[] = [];
|
||||
contactTitles: ContactTitle[] = [];
|
||||
|
||||
contactReadOnlyFields: any = {
|
||||
lastChangedDate: null,
|
||||
@ -57,11 +45,8 @@ export class ContactsComponent implements OnInit {
|
||||
@Input() userPreferences: UserPreferences = {};
|
||||
@Output() hasContacts = new EventEmitter<boolean>();
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
private fb = inject(FormBuilder);
|
||||
private contactService = inject(ContactService);
|
||||
private commonService = inject(CommonService);
|
||||
private notificationService = inject(NotificationService);
|
||||
private errorHandler = inject(ApiErrorHandlerService);
|
||||
private dialog = inject(MatDialog);
|
||||
@ -71,25 +56,19 @@ export class ContactsComponent implements OnInit {
|
||||
firstName: ['', [Validators.required, Validators.maxLength(50)]],
|
||||
lastName: ['', [Validators.required, Validators.maxLength(50)]],
|
||||
middleInitial: ['', [Validators.maxLength(1)]],
|
||||
title: ['', [Validators.required]],
|
||||
phone: ['', [Validators.required, Validators.pattern(/^[0-9\-\(\)]{10,15}$/)]],
|
||||
mobile: ['', [Validators.required, Validators.pattern(/^[0-9\-\(\)]{10,15}$/)]],
|
||||
fax: ['', [Validators.pattern(/^[0-9\-\(\)]{10,15}$/)]],
|
||||
title: ['', [Validators.required, Validators.maxLength(100)]],
|
||||
phone: ['', [Validators.required, Validators.pattern(/^[0-9]{10,15}$/)]],
|
||||
mobile: ['', [Validators.required, Validators.pattern(/^[0-9]{10,15}$/)]],
|
||||
fax: ['', [Validators.required, Validators.pattern(/^[0-9]{10,15}$/)]],
|
||||
email: ['', [Validators.required, Validators.email, Validators.maxLength(100)]],
|
||||
defaultContact: [false]
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadContactTitles();
|
||||
this.loadContacts();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource.sort = this.sort;
|
||||
@ -98,47 +77,20 @@ export class ContactsComponent implements OnInit {
|
||||
loadContacts(): void {
|
||||
this.isLoading = true;
|
||||
|
||||
this.contactService.getContactsById(this.spid).pipe(finalize(() => {
|
||||
this.isLoading = false;
|
||||
})).subscribe({
|
||||
this.contactService.getContactsById(this.spid).subscribe({
|
||||
next: (contacts: Contact[]) => {
|
||||
this.contacts = contacts;
|
||||
this.renderContacts();
|
||||
this.dataSource.data = contacts;
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error: any) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load contacts');
|
||||
this.notificationService.showError(errorMessage);
|
||||
this.isLoading = false;
|
||||
console.error('Error loading contacts:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loadContactTitles(): void {
|
||||
this.commonService.getContactTitles()
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe({
|
||||
next: (contactTitles) => {
|
||||
this.contactTitles = contactTitles;
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Failed to load contact titles', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toggleShowInactiveContacts(): void {
|
||||
this.showInactiveContacts = !this.showInactiveContacts;
|
||||
this.renderContacts();
|
||||
}
|
||||
|
||||
renderContacts(): void {
|
||||
if (this.showInactiveContacts) {
|
||||
this.dataSource.data = this.contacts.filter(contact => contact.isInactive);
|
||||
} else {
|
||||
this.dataSource.data = this.contacts.filter(contact => !contact.isInactive);
|
||||
}
|
||||
}
|
||||
|
||||
// applyFilter(event: Event): void {
|
||||
// const filterValue = (event.target as HTMLInputElement).value;
|
||||
// this.dataSource.filter = filterValue.trim().toLowerCase();
|
||||
@ -192,10 +144,7 @@ export class ContactsComponent implements OnInit {
|
||||
? this.contactService.updateContact(this.currentContactId!, contactData)
|
||||
: this.contactService.createContact(this.spid, contactData);
|
||||
|
||||
this.changeInProgress = true;
|
||||
saveObservable.pipe(finalize(() => {
|
||||
this.changeInProgress = false;
|
||||
})).subscribe({
|
||||
saveObservable.subscribe({
|
||||
next: () => {
|
||||
this.notificationService.showSuccess(`Contact ${this.isEditing ? 'updated' : 'added'} successfully`);
|
||||
this.loadContacts();
|
||||
@ -245,70 +194,16 @@ export class ContactsComponent implements OnInit {
|
||||
this.contactForm.reset();
|
||||
}
|
||||
|
||||
createLogin(emailAddress: string): void {
|
||||
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
|
||||
width: '450px',
|
||||
data: {
|
||||
title: 'Confirm Login Creation',
|
||||
message: 'Are you sure you want to create a login for this contact?',
|
||||
confirmText: 'Yes',
|
||||
cancelText: 'Cancel'
|
||||
}
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result) {
|
||||
const contactLoginData: ContactLogin = {
|
||||
spid: this.spid,
|
||||
emailAddress: emailAddress
|
||||
};
|
||||
this.contactService.createContactLogin(contactLoginData).subscribe({
|
||||
next: () => {
|
||||
this.notificationService.showSuccess(`Login created successfully`);
|
||||
this.loadContacts();
|
||||
this.cancelEdit();
|
||||
},
|
||||
error: (error) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, `Failed to create login`);
|
||||
this.notificationService.showError(errorMessage);
|
||||
console.error('Error saving login:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setDefaultContact(contactId: string): void {
|
||||
|
||||
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
|
||||
width: '450px',
|
||||
data: {
|
||||
title: 'Confirm Default Contact',
|
||||
message: 'Are you sure you want to set this contact as default contact?',
|
||||
confirmText: 'Yes',
|
||||
cancelText: 'Cancel'
|
||||
}
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result) {
|
||||
this.contactService.setDefaultContact(contactId).subscribe({
|
||||
next: () => {
|
||||
this.notificationService.showSuccess('Default contact updated successfully');
|
||||
this.loadContacts();
|
||||
},
|
||||
error: (error) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to set default contact');
|
||||
this.notificationService.showError(errorMessage);
|
||||
console.error('Error setting default contact:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getContactTitleLabel(value: string): string {
|
||||
const type = this.contactTitles.find(t => t.value === value);
|
||||
return type ? type.name : value;
|
||||
}
|
||||
// setDefaultContact(contactId: string): void {
|
||||
// this.contactService.setDefaultServiceProviderContact(this.spid, contactId).subscribe({
|
||||
// next: () => {
|
||||
// this.notificationService.showSuccess('Default contact updated successfully');
|
||||
// this.loadContacts();
|
||||
// },
|
||||
// error: (error) => {
|
||||
// this.notificationService.showError('Failed to set default contact');
|
||||
// console.error('Error setting default contact:', error);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
}
|
||||
@ -1,8 +1,5 @@
|
||||
<div class="continuation-sheet-container">
|
||||
<div class="actions-bar">
|
||||
<mat-slide-toggle (change)="toggleShowExpiredRecords()">
|
||||
Show Expired Records
|
||||
</mat-slide-toggle>
|
||||
<button mat-raised-button color="primary" (click)="addNewContinuationSheet()">
|
||||
<mat-icon>add</mat-icon> Add New Continuation Sheet
|
||||
</button>
|
||||
@ -44,12 +41,6 @@
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Expired Date Column -->
|
||||
<ng-container matColumnDef="expiredDate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Expired Date</th>
|
||||
<td mat-cell *matCellDef="let fee">{{ fee.expiredDate | date:'mediumDate':'UTC' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Actions Column -->
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>Actions</th>
|
||||
@ -74,8 +65,8 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator *ngIf="dataSource.data.length > userPreferences.pageSize!" [length]="dataSource.data.length"
|
||||
[pageSizeOptions]="[userPreferences.pageSize!]" [hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
<mat-paginator [length]="dataSource.data.length" [pageSizeOptions]="[userPreferences.pageSize!]"
|
||||
[hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
|
||||
<!-- Continuation Sheet Form -->
|
||||
@ -160,11 +151,10 @@
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button mat-raised-button color="primary" type="submit"
|
||||
[disabled]="continuationSheetForm.invalid || changeInProgress">
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
<button mat-raised-button color="primary" type="submit" [disabled]="continuationSheetForm.invalid">
|
||||
{{ isEditing ? 'Update' : 'Save' }}
|
||||
</button>
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -1,5 +1,5 @@
|
||||
.continuation-sheet-container {
|
||||
padding: 0.5rem;
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
@ -8,11 +8,6 @@
|
||||
clear: both;
|
||||
margin-bottom: -16px;
|
||||
|
||||
mat-slide-toggle {
|
||||
transform: scale(0.8);
|
||||
margin-left: -0.5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
float: right;
|
||||
}
|
||||
@ -81,7 +76,7 @@
|
||||
margin-top: 16px;
|
||||
|
||||
.form-header {
|
||||
// margin-bottom: 24px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
@ -98,15 +93,10 @@
|
||||
.form-row {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
|
||||
mat-form-field {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
mat-label {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
.form-error {
|
||||
@ -168,7 +158,7 @@
|
||||
|
||||
.readonly-value {
|
||||
padding: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
font-size: 0.9375rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
@ -5,12 +5,12 @@ 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 { finalize, of } from 'rxjs';
|
||||
import { of } from 'rxjs';
|
||||
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 { ContinuationSheetFeeService } from '../../core/services/fees/continuation-sheet-fee.service';
|
||||
import { ContinuationSheetFeeService } from '../../core/services/service-provider/continuation-sheet-fee.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-continuation-sheet-fee',
|
||||
@ -20,23 +20,16 @@ import { ContinuationSheetFeeService } from '../../core/services/fees/continuati
|
||||
providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }],
|
||||
})
|
||||
export class ContinuationSheetFeeComponent implements OnInit {
|
||||
@ViewChild(MatPaginator, { static: false })
|
||||
set paginator(value: MatPaginator) {
|
||||
this.dataSource.paginator = value;
|
||||
}
|
||||
|
||||
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||
@ViewChild(MatSort) sort!: MatSort;
|
||||
|
||||
displayedColumns: string[] = ['customerType', 'carnetType', 'rate', 'effectiveDate', 'expiredDate', 'actions'];
|
||||
displayedColumns: string[] = ['customerType', 'carnetType', 'rate', 'effectiveDate', 'actions'];
|
||||
dataSource = new MatTableDataSource<any>();
|
||||
continuationSheetForm: FormGroup;
|
||||
isEditing = false;
|
||||
currentContinuationSheetId: number | null = null;
|
||||
isLoading = false;
|
||||
changeInProgress = false;
|
||||
showForm = false;
|
||||
showExpiredRecords = false;
|
||||
continuationSheets: any[] = [];
|
||||
|
||||
readOnlyFields: any = {
|
||||
lastChangedDate: null,
|
||||
@ -88,36 +81,23 @@ export class ContinuationSheetFeeComponent implements OnInit {
|
||||
}
|
||||
|
||||
loadContinuationSheets(): void {
|
||||
if (!this.spid) return;
|
||||
|
||||
this.isLoading = true;
|
||||
this.continuationSheetFeeService.getContinuationSheets(this.spid).pipe(finalize(() => {
|
||||
this.isLoading = false;
|
||||
})).subscribe({
|
||||
this.continuationSheetFeeService.getContinuationSheets(this.spid).subscribe({
|
||||
next: (continuationSheets) => {
|
||||
this.continuationSheets = continuationSheets;
|
||||
this.dataSource.data = this.continuationSheets;
|
||||
this.renderRecods();
|
||||
this.dataSource.data = continuationSheets;
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load continuation sheets');
|
||||
this.notificationService.showError(errorMessage);
|
||||
this.isLoading = false;
|
||||
return of([]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toggleShowExpiredRecords(): void {
|
||||
this.showExpiredRecords = !this.showExpiredRecords;
|
||||
this.renderRecods();
|
||||
}
|
||||
|
||||
renderRecods(): void {
|
||||
if (this.showExpiredRecords) {
|
||||
this.dataSource.data = this.continuationSheets.filter(record => record.expired);
|
||||
} else {
|
||||
this.dataSource.data = this.continuationSheets.filter(record => !record.expired);
|
||||
}
|
||||
}
|
||||
|
||||
// applyFilter(event: Event): void {
|
||||
// const filterValue = (event.target as HTMLInputElement).value;
|
||||
// this.dataSource.filter = filterValue.trim().toLowerCase();
|
||||
@ -173,10 +153,7 @@ export class ContinuationSheetFeeComponent implements OnInit {
|
||||
? this.continuationSheetFeeService.updateContinuationSheet(this.currentContinuationSheetId, continuationSheetData)
|
||||
: this.continuationSheetFeeService.addContinuationSheet(this.spid, continuationSheetData);
|
||||
|
||||
this.changeInProgress = true;
|
||||
saveObservable.pipe(finalize(() => {
|
||||
this.changeInProgress = false;
|
||||
})).subscribe({
|
||||
saveObservable.subscribe({
|
||||
next: () => {
|
||||
this.notificationService.showSuccess(`Continuation Sheet ${this.isEditing ? 'updated' : 'added'} successfully`);
|
||||
this.loadContinuationSheets();
|
||||
@ -1,8 +1,5 @@
|
||||
<div class="counterfoil-container">
|
||||
<div class="actions-bar">
|
||||
<mat-slide-toggle (change)="toggleShowExpiredRecords()">
|
||||
Show Expired Records
|
||||
</mat-slide-toggle>
|
||||
<button mat-raised-button color="primary" (click)="addNewCounterfoil()">
|
||||
<mat-icon>add</mat-icon> Add New Counterfoil
|
||||
</button>
|
||||
@ -56,12 +53,6 @@
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Expired Date Column -->
|
||||
<ng-container matColumnDef="expiredDate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Expired Date</th>
|
||||
<td mat-cell *matCellDef="let fee">{{ fee.expiredDate | date:'mediumDate':'UTC' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Actions Column -->
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>Actions</th>
|
||||
@ -86,8 +77,8 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator *ngIf="dataSource.data.length > userPreferences.pageSize!" [length]="dataSource.data.length"
|
||||
[pageSizeOptions]="[userPreferences.pageSize!]" [hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
<mat-paginator [length]="dataSource.data.length" [pageSizeOptions]="[userPreferences.pageSize!]"
|
||||
[hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
|
||||
<!-- Counterfoil Form -->
|
||||
@ -206,11 +197,10 @@
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button mat-raised-button color="primary" type="submit"
|
||||
[disabled]="counterfoilForm.invalid || changeInProgress">
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
<button mat-raised-button color="primary" type="submit" [disabled]="counterfoilForm.invalid">
|
||||
{{ isEditing ? 'Update' : 'Save' }}
|
||||
</button>
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -1,5 +1,5 @@
|
||||
.counterfoil-container {
|
||||
padding: 0.5rem;
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
@ -8,11 +8,6 @@
|
||||
clear: both;
|
||||
margin-bottom: -16px;
|
||||
|
||||
mat-slide-toggle {
|
||||
transform: scale(0.8);
|
||||
margin-left: -0.5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
float: right;
|
||||
}
|
||||
@ -81,7 +76,7 @@
|
||||
margin-top: 16px;
|
||||
|
||||
.form-header {
|
||||
// margin-bottom: 24px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
@ -98,15 +93,10 @@
|
||||
.form-row {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
|
||||
mat-form-field {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
mat-label {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
.form-error {
|
||||
@ -168,7 +158,7 @@
|
||||
|
||||
.readonly-value {
|
||||
padding: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
font-size: 0.9375rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
@ -5,13 +5,12 @@ 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 { CounterfoilFee } from '../../core/models/fees/counterfoil-fee';
|
||||
import { CounterfoilFee } from '../../core/models/service-provider/counterfoil-fee';
|
||||
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 { CounterfoilFeeService } from '../../core/services/fees/counterfoil-fee.service';
|
||||
import { finalize } from 'rxjs';
|
||||
import { CounterfoilFeeService } from '../../core/services/service-provider/counterfoil-fee.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-counterfoil-fee',
|
||||
@ -21,23 +20,16 @@ import { finalize } from 'rxjs';
|
||||
providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }],
|
||||
})
|
||||
export class CounterfoilFeeComponent implements OnInit {
|
||||
@ViewChild(MatPaginator, { static: false })
|
||||
set paginator(value: MatPaginator) {
|
||||
this.dataSource.paginator = value;
|
||||
}
|
||||
|
||||
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||
@ViewChild(MatSort) sort!: MatSort;
|
||||
|
||||
displayedColumns: string[] = ['customerType', 'carnetType', 'startSets', 'endSets', 'rate', 'effectiveDate', 'expiredDate', 'actions'];
|
||||
displayedColumns: string[] = ['customerType', 'carnetType', 'startSets', 'endSets', 'rate', 'effectiveDate', 'actions'];
|
||||
dataSource = new MatTableDataSource<any>();
|
||||
counterfoilForm: FormGroup;
|
||||
isEditing = false;
|
||||
currentCounterfoilId: number | null = null;
|
||||
isLoading = false;
|
||||
changeInProgress = false;
|
||||
showForm = false;
|
||||
showExpiredRecords = false;
|
||||
counterfoilFees: CounterfoilFee[] = [];
|
||||
|
||||
readOnlyFields: any = {
|
||||
lastChangedDate: null,
|
||||
@ -105,38 +97,25 @@ export class CounterfoilFeeComponent implements OnInit {
|
||||
}
|
||||
|
||||
loadCounterfoils(): void {
|
||||
if (!this.spid) return;
|
||||
|
||||
this.isLoading = true;
|
||||
this.counterfoilFeeService.getCounterfoils(this.spid).pipe(finalize(() => {
|
||||
this.isLoading = false;
|
||||
}))
|
||||
this.counterfoilFeeService.getCounterfoils(this.spid)
|
||||
.subscribe({
|
||||
next: (
|
||||
counterfoils: CounterfoilFee[]) => {
|
||||
this.counterfoilFees = counterfoils;
|
||||
this.dataSource.data = this.counterfoilFees;
|
||||
this.renderRecods();
|
||||
this.dataSource.data = counterfoils;
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error: any) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load counterfoils');
|
||||
this.notificationService.showError(errorMessage);
|
||||
this.isLoading = false;
|
||||
console.error('Error loading counterfoils:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toggleShowExpiredRecords(): void {
|
||||
this.showExpiredRecords = !this.showExpiredRecords;
|
||||
this.renderRecods();
|
||||
}
|
||||
|
||||
renderRecods(): void {
|
||||
if (this.showExpiredRecords) {
|
||||
this.dataSource.data = this.counterfoilFees.filter(record => record.expired);
|
||||
} else {
|
||||
this.dataSource.data = this.counterfoilFees.filter(record => !record.expired);
|
||||
}
|
||||
}
|
||||
|
||||
// applyFilter(event: Event): void {
|
||||
// const filterValue = (event.target as HTMLInputElement).value;
|
||||
// this.dataSource.filter = filterValue.trim().toLowerCase();
|
||||
@ -198,10 +177,7 @@ export class CounterfoilFeeComponent implements OnInit {
|
||||
? this.counterfoilFeeService.updateCounterfoil(this.currentCounterfoilId, counterfoilData)
|
||||
: this.counterfoilFeeService.addCounterfoil(this.spid, counterfoilData);
|
||||
|
||||
this.changeInProgress = true;
|
||||
saveObservable.pipe(finalize(() => {
|
||||
this.changeInProgress = false;
|
||||
})).subscribe({
|
||||
saveObservable.subscribe({
|
||||
next: () => {
|
||||
this.notificationService.showSuccess(`Counterfoil ${this.isEditing ? 'updated' : 'added'} successfully`);
|
||||
this.loadCounterfoils();
|
||||
@ -20,13 +20,6 @@
|
||||
<app-contacts [spid]="spid" [userPreferences]="userPreferences"></app-contacts>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title> Regions </mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<app-sp-region [spid]="spid"></app-sp-region>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title> Carnet Sequence </mat-panel-title>
|
||||
@ -80,12 +73,4 @@
|
||||
<app-security-deposit [spid]="spid" [isEditMode]="isEditMode"
|
||||
[userPreferences]="userPreferences"></app-security-deposit>
|
||||
</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>
|
||||
@ -1,6 +1,8 @@
|
||||
@use 'colors' as colors;
|
||||
|
||||
.page-header {
|
||||
margin: 0.5rem 0px;
|
||||
color: var(--mat-sys-primary);
|
||||
color: colors.$primary-color;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
|
||||
@ -5,21 +5,19 @@ import { BasicDetailsComponent } from '../basic-details/basic-details.component'
|
||||
import { ContactsComponent } from '../contacts/contacts.component';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { CarnetSequenceComponent } from '../carnet-sequence/carnet-sequence.component';
|
||||
import { CarnetFeeComponent } from "../../fees/carnet-fee/carnet-fee.component";
|
||||
import { BasicFeeComponent } from "../../fees/basic-fee/basic-fee.component";
|
||||
import { CounterfoilFeeComponent } from "../../fees/counterfoil-fee/counterfoil-fee.component";
|
||||
import { ContinuationSheetFeeComponent } from "../../fees/continuation-sheet-fee/continuation-sheet-fee.component";
|
||||
import { ExpeditedFeeComponent } from "../../fees/expedited-fee/expedited-fee.component";
|
||||
import { SecurityDepositComponent } from "../../fees/security-deposit/security-deposit.component";
|
||||
import { CarnetFeeComponent } from "../carnet-fee/carnet-fee.component";
|
||||
import { BasicFeeComponent } from "../basic-fee/basic-fee.component";
|
||||
import { CounterfoilFeeComponent } from "../counterfoil-fee/counterfoil-fee.component";
|
||||
import { ContinuationSheetFeeComponent } from "../continuation-sheet-fee/continuation-sheet-fee.component";
|
||||
import { ExpeditedFeeComponent } from "../expedited-fee/expedited-fee.component";
|
||||
import { SecurityDepositComponent } from "../security-deposit/security-deposit.component";
|
||||
import { UserPreferences } from '../../core/models/user-preference';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { UserPreferencesService } from '../../core/services/user-preference.service';
|
||||
import { CargoRateComponent } from '../../fees/cargo-rate/cargo-rate.component';
|
||||
import { RegionComponent } from '../region/region.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-edit-service-provider',
|
||||
imports: [AngularMaterialModule, BasicDetailsComponent, ContactsComponent, CarnetSequenceComponent, CarnetFeeComponent, BasicFeeComponent, CounterfoilFeeComponent, ContinuationSheetFeeComponent, ExpeditedFeeComponent, SecurityDepositComponent, CommonModule, CargoRateComponent, RegionComponent],
|
||||
imports: [AngularMaterialModule, BasicDetailsComponent, ContactsComponent, CarnetSequenceComponent, CarnetFeeComponent, BasicFeeComponent, CounterfoilFeeComponent, ContinuationSheetFeeComponent, ExpeditedFeeComponent, SecurityDepositComponent, CommonModule],
|
||||
templateUrl: './edit-service-provider.component.html',
|
||||
styleUrl: './edit-service-provider.component.scss'
|
||||
})
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
<div class="expedited-fee-container">
|
||||
<div class="actions-bar">
|
||||
<mat-slide-toggle (change)="toggleShowExpiredRecords()">
|
||||
Show Expired Records
|
||||
</mat-slide-toggle>
|
||||
<button mat-raised-button color="primary" (click)="addNewFee()">
|
||||
<mat-icon>add</mat-icon> Add New Expedited Fee
|
||||
</button>
|
||||
@ -44,12 +41,6 @@
|
||||
<td mat-cell *matCellDef="let fee">{{ fee.effectiveDate | date:'mediumDate':'UTC' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Expired Date Column -->
|
||||
<ng-container matColumnDef="expiredDate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Expired Date</th>
|
||||
<td mat-cell *matCellDef="let fee">{{ fee.expiredDate | date:'mediumDate':'UTC' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Actions Column -->
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>Actions</th>
|
||||
@ -74,8 +65,8 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator *ngIf="dataSource.data.length > userPreferences.pageSize!" [length]="dataSource.data.length"
|
||||
[pageSizeOptions]="[userPreferences.pageSize!]" [hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
<mat-paginator [length]="dataSource.data.length" [pageSizeOptions]="[userPreferences.pageSize!]"
|
||||
[hidePageSize]="true" showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
|
||||
<!-- Fee Form -->
|
||||
@ -204,11 +195,10 @@
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button mat-raised-button color="primary" type="submit"
|
||||
[disabled]="feeForm.invalid || changeInProgress">
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
<button mat-raised-button color="primary" type="submit" [disabled]="feeForm.invalid">
|
||||
{{ isEditing ? 'Update' : 'Save' }}
|
||||
</button>
|
||||
<button mat-button type="button" (click)="cancelEdit()">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -1,5 +1,5 @@
|
||||
.expedited-fee-container {
|
||||
padding: 0.5rem;
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
@ -8,11 +8,6 @@
|
||||
clear: both;
|
||||
margin-bottom: -16px;
|
||||
|
||||
mat-slide-toggle {
|
||||
transform: scale(0.8);
|
||||
margin-left: -0.5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
float: right;
|
||||
}
|
||||
@ -81,7 +76,7 @@
|
||||
margin-top: 16px;
|
||||
|
||||
.form-header {
|
||||
// margin-bottom: 24px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
@ -98,15 +93,10 @@
|
||||
.form-row {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
|
||||
mat-form-field {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
mat-label {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
.form-error {
|
||||
@ -168,7 +158,7 @@
|
||||
|
||||
.readonly-value {
|
||||
padding: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
font-size: 0.9375rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
@ -6,16 +6,16 @@ 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 { ExpeditedFee } from '../../core/models/fees/expedited-fee';
|
||||
import { ExpeditedFee } from '../../core/models/service-provider/expedited-fee';
|
||||
import { DeliveryType } from '../../core/models/delivery-type';
|
||||
import { TimeZone } from '../../core/models/timezone';
|
||||
import { finalize, Subject, takeUntil } from 'rxjs';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
import { UserPreferences } from '../../core/models/user-preference';
|
||||
import { ApiErrorHandlerService } from '../../core/services/common/api-error-handler.service';
|
||||
import { CommonService } from '../../core/services/common/common.service';
|
||||
import { NotificationService } from '../../core/services/common/notification.service';
|
||||
import { TimeFormatService } from '../../core/services/common/timeformat.service';
|
||||
import { ExpeditedFeeService } from '../../core/services/fees/expedited-fee.service';
|
||||
import { ExpeditedFeeService } from '../../core/services/service-provider/expedited-fee.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-expedited-fee',
|
||||
@ -25,23 +25,16 @@ import { ExpeditedFeeService } from '../../core/services/fees/expedited-fee.serv
|
||||
providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }],
|
||||
})
|
||||
export class ExpeditedFeeComponent implements OnInit, OnDestroy {
|
||||
@ViewChild(MatPaginator, { static: false })
|
||||
set paginator(value: MatPaginator) {
|
||||
this.dataSource.paginator = value;
|
||||
}
|
||||
|
||||
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||
@ViewChild(MatSort) sort!: MatSort;
|
||||
|
||||
displayedColumns: string[] = ['customerType', 'deliveryType', 'time', 'fee', 'effectiveDate', 'expiredDate', 'actions'];
|
||||
displayedColumns: string[] = ['customerType', 'deliveryType', 'time', 'fee', 'effectiveDate', 'actions'];
|
||||
dataSource = new MatTableDataSource<any>();
|
||||
feeForm: FormGroup;
|
||||
isEditing = false;
|
||||
currentFeeId: number | null = null;
|
||||
isLoading = false;
|
||||
changeInProgress = false;
|
||||
showForm = false;
|
||||
showExpiredRecords = false;
|
||||
expeditedFees: ExpeditedFee[] = [];
|
||||
|
||||
readOnlyFields: any = {
|
||||
lastChangedDate: null,
|
||||
@ -106,35 +99,20 @@ export class ExpeditedFeeComponent implements OnInit, OnDestroy {
|
||||
loadExpeditedFees(): void {
|
||||
this.isLoading = true;
|
||||
|
||||
this.expeditedFeeService.getExpeditedFees(this.spid).pipe(finalize(() => {
|
||||
this.isLoading = false;
|
||||
})).subscribe({
|
||||
this.expeditedFeeService.getExpeditedFees(this.spid).subscribe({
|
||||
next: (fees: ExpeditedFee[]) => {
|
||||
this.expeditedFees = fees;
|
||||
this.dataSource.data = this.expeditedFees;
|
||||
this.renderRecods();
|
||||
this.dataSource.data = fees;
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error: any) => {
|
||||
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load expedited fees');
|
||||
this.notificationService.showError(errorMessage);
|
||||
this.isLoading = false;
|
||||
console.error('Error loading expedited fees:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toggleShowExpiredRecords(): void {
|
||||
this.showExpiredRecords = !this.showExpiredRecords;
|
||||
this.renderRecods();
|
||||
}
|
||||
|
||||
renderRecods(): void {
|
||||
if (this.showExpiredRecords) {
|
||||
this.dataSource.data = this.expeditedFees.filter(record => record.expired);
|
||||
} else {
|
||||
this.dataSource.data = this.expeditedFees.filter(record => !record.expired);
|
||||
}
|
||||
}
|
||||
|
||||
loadLookupData(): void {
|
||||
this.loadDeliveryTypes();
|
||||
this.loadTimeZones();
|
||||
@ -146,15 +124,17 @@ export class ExpeditedFeeComponent implements OnInit, OnDestroy {
|
||||
.subscribe({
|
||||
next: (timeZones) => {
|
||||
this.timeZones = timeZones;
|
||||
this.isLoading = false;
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Failed to load time zones', error);
|
||||
this.isLoading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loadDeliveryTypes(): void {
|
||||
this.commonService.getDeliveryTypes()
|
||||
this.commonService.getDeliveryTypes(this.spid)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe({
|
||||
next: (deliveryTypes) => {
|
||||
@ -162,6 +142,7 @@ export class ExpeditedFeeComponent implements OnInit, OnDestroy {
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Failed to load delivery types', error);
|
||||
this.isLoading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -226,10 +207,7 @@ export class ExpeditedFeeComponent implements OnInit, OnDestroy {
|
||||
? this.expeditedFeeService.updateExpeditedFee(this.currentFeeId, feeData)
|
||||
: this.expeditedFeeService.createExpeditedFee(this.spid, feeData);
|
||||
|
||||
this.changeInProgress = true;
|
||||
saveObservable.pipe(finalize(() => {
|
||||
this.changeInProgress = false;
|
||||
})).subscribe({
|
||||
saveObservable.subscribe({
|
||||
next: () => {
|
||||
this.notificationService.showSuccess(`Expedited fee ${this.isEditing ? 'updated' : 'added'} successfully`);
|
||||
this.loadExpeditedFees();
|
||||
@ -1,55 +0,0 @@
|
||||
<div class="region-container">
|
||||
<div class="loading-shade" *ngIf="isLoading">
|
||||
<mat-spinner diameter="50"></mat-spinner>
|
||||
</div>
|
||||
<div class="region-selection-container">
|
||||
<!-- Available Regions Listbox -->
|
||||
<div class="available-regions">
|
||||
<h3>Available Regions</h3>
|
||||
|
||||
<mat-selection-list [multiple]="false" hideSingleSelectionIndicator>
|
||||
<mat-list-option *ngFor="let region of regions" [value]="region" [disabled]="isRegionSelected(region)"
|
||||
(click)="onAvailableRegionSelection(availableoption)" #availableoption>
|
||||
{{region.name}}
|
||||
</mat-list-option>
|
||||
</mat-selection-list>
|
||||
</div>
|
||||
|
||||
<!-- Controls -->
|
||||
<div class="controls">
|
||||
<div class="action-buttons">
|
||||
<button mat-raised-button color="primary" type="button" (click)="addRegion()" class="icon-end">
|
||||
<mat-icon>keyboard_double_arrow_right</mat-icon>
|
||||
<span> Add</span>
|
||||
</button>
|
||||
<button mat-raised-button type="button" (click)="removeRegion()">
|
||||
<mat-icon>keyboard_double_arrow_left</mat-icon>
|
||||
<span> Remove</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Selected Regions -->
|
||||
<div class="selected-regions">
|
||||
<div class="regions">
|
||||
<h3>Selected Regions</h3>
|
||||
<mat-selection-list [multiple]="false" hideSingleSelectionIndicator>
|
||||
<mat-list-option *ngFor="let region of selectedRegions" [value]="region"
|
||||
(click)="onRegionSelection(selectedoption)" #selectedoption>
|
||||
{{region.name}}
|
||||
</mat-list-option>
|
||||
<mat-list-item *ngIf="selectedRegions.length === 0">
|
||||
<span class="empty-message">No regions selected</span>
|
||||
</mat-list-item>
|
||||
</mat-selection-list>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button mat-raised-button color="primary" type="submit" (click)="onSubmit()"
|
||||
[disabled]="changeInProgress || selectedRegions.length === 0">
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,90 +0,0 @@
|
||||
.region-container {
|
||||
padding: 0.75rem 0 0 0;
|
||||
margin: 0 auto;
|
||||
|
||||
.region-selection-container {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
margin-bottom: 12px;
|
||||
// border: 1px solid;
|
||||
// border-radius: 4px;
|
||||
// padding: 20px;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.available-regions,
|
||||
.selected-regions {
|
||||
flex: 1;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
padding: 16px;
|
||||
overflow: hidden;
|
||||
|
||||
h3 {
|
||||
margin: 0 0 16px 0;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
mat-selection-list {
|
||||
height: 150px;
|
||||
overflow-y: auto;
|
||||
padding: 0;
|
||||
|
||||
mat-list-item {
|
||||
.empty-message {
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
width: 150px;
|
||||
padding: 16px;
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
// gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
mat-icon {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button.icon-end {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.selected-regions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
|
||||
.regions {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user