Commit faf1a29a authored by Sai Krishna Jonnala 's avatar Sai Krishna Jonnala

chnges

parent 52dcbec8

<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<ng-container *menuButton="'9Jjg3M'">
<button *ngIf="!loading && assessmentType && assessmentType.length" type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateWord)"><i class="fe-plus mr-1"></i> Add Assessment Type</button>
</ng-container>
<!--<button *ngIf="!loading && !filters.applied && generalAdvices && generalAdvices.length" type="button" class="btn btn-secondary btn-sm ml-1" (click)="onShowFilters()"><i class="fe-filter mr-1"></i> Filters</button>-->
</div>
<h4 class="page-title">Assessment Type</h4>
</div>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading Assessment Type ...</span>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && (!assessmentType || !assessmentType.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<h4 class="title">Oops! No Assessment Type found<span *ngIf="filters.applied"> based on your filters criteria</span>.</h4>
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateWord)"><i class="fe-plus mr-1"></i> Add Assessment Type</button>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && assessmentType && assessmentType.length">
<div class="col-12">
<div class="card mb-0">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-centered table-sm table-striped table-borderless mb-0">
<thead>
<tr>
<th>Assessment Type Name</th>
<th>Created Date</th>
<!--<th>Modified By</th>-->
<th>Modified Date & Time</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of assessmentType;">
<td [textContent]="item.name"></td>
<td [textContent]="item.createdDate | date:'dd-MM-yyyy, hh:mm a'"></td>
<!--<td [textContent]="item.modifiedByName"></td>-->
<td [textContent]="(item.modifiedDate | date:'dd-MM-yyyy, hh:mm a') || '---'"></td>
<td>
<div class="d-flex align-items-center justify-content-end">
<a href="javascript:;" class="action-icon text-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenModel(templateWord, item)"><i class="fe-edit"></i></a>
<a href="javascript:;" class="action-icon text-danger" placement="left" ngbTooltip="Delete" (click)="onDelete(item)"><i class="fe-trash-2"></i></a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<nav class="d-flex align-items-center justify-content-between p-2" *ngIf="pagination.totalPages > 1">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - assessmentType.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> Assessment Type )</span>
</span>
</p>
<!--<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>-->
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateWord>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-mother-nurse mr-1"></i>{{assessmentTypeForm.value.assessmentTypeId === 0 ? 'Add' : 'Edit'}} Assessment Type</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<form [formGroup]="assessmentTypeForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1">Assessment Type Name <code>*</code></label>
<div class="form-group">
<input tabindex="1" type="text" block maxlength="150" autofocus formControlName="name" autocomplete="nope" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.name.errors) }" placeholder="Enter assessment name" />
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { HttpErrorResponse } from "@angular/common/http";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, Validators, FormBuilder } from "@angular/forms";
import { Page, IUserAccount, Pagination, } from "@shared/models";
import { AssessmentType } from "@shared/entities/assessment-type.entity";
import { WhiteSpaceValidator } from "../../../../../shared/validators";
class TrackBy {
assessmentType(item: AssessmentType) {
return item.assessmentTypeId;
}
}
class FilterOptions {
name: string = null;
assessmentTypeId: number;
}
class Filters {
options: FilterOptions;
applied: boolean;
constructor() {
this.init();
}
init() {
this.options = new FilterOptions();
this.applied = undefined;
}
}
@Component({
templateUrl: "./assessment-type.html",
encapsulation: ViewEncapsulation.None
})
export class AssessmentTypePage implements OnInit, OnDestroy {
page: Page;
filters: Filters;
trackBy: TrackBy;
pagination: Pagination;
assessmentTypeForm: FormGroup;
loading: boolean;
assessmentType: Array<AssessmentType>;
selectedAssessmentType: AssessmentType
modalRef: NgbModalRef;
submitting: boolean;
submitted: boolean;
modifying: boolean;
modifyingContent: string;
constructor(
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly httpService: HttpService
) {
this.loading = true;
this.page = new Page();
this.filters = new Filters();
this.trackBy = new TrackBy();
this.initPagination();
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
private buildForm() {
this.assessmentTypeForm = this.formBuilder.group({
assessmentTypeId: 0,
name: [null, [Validators.required, WhiteSpaceValidator.isValid]]
});
}
onOpenModel(content: TemplateRef<any>, assessmentType?: AssessmentType) {
this.buildForm();
if (assessmentType) {
this.selectedAssessmentType = assessmentType;
this.updateForm();
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
fetchAddAssessmentType() {
this.loading = true;
const request = Object.assign(UtilHelper.clone(this.filters.options), UtilHelper.clone(this.pagination));
this.httpService
.post<Array<AssessmentType>>(ApiResources.getURI(ApiResources.assessmentType.base, ApiResources.assessmentType.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<AssessmentType>) => {
this.assessmentType = response;
UtilHelper.applyPagination(this.assessmentType, this.pagination);
},
() => {
this.assessmentType = [];
}
);
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetchAddAssessmentType();
}
onSubmit() {
this.submitted = true;
if (!this.assessmentTypeForm.valid) {
return;
}
this.submitting = true;
const request = Object.assign(UtilHelper.clone(this.assessmentTypeForm.getRawValue()));
if (Number(this.assessmentTypeForm.value.assessmentTypeId) === 0) {
request.createdBy = this.page.userAccount.accountId;
request.createdByName = this.page.userAccount.fullName;
this.httpService.post(ApiResources.getURI(ApiResources.assessmentType.base, ApiResources.assessmentType.add), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchAddAssessmentType();
this.notifyService.success("Assessment Type has been added successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
} else {
request.modifiedBy = this.page.userAccount.accountId;
request["modifiedByName"] = this.page.userAccount.fullName;
request["createdBy"] = this.page.userAccount.accountId;
delete request.type;
this.httpService.put(ApiResources.getURI(ApiResources.assessmentType.base, ApiResources.assessmentType.update), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchAddAssessmentType();
this.notifyService.success("Assessment Type details has been updated successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
}
}
get form() {
return this.assessmentTypeForm.controls;
}
private updateForm() {
this.assessmentTypeForm.patchValue({
assessmentTypeId: this.selectedAssessmentType.assessmentTypeId,
name: this.selectedAssessmentType.name
});
}
onDelete(assessmentType: AssessmentType) {
this.notifyService.delete(() => {
this.httpService
.post(ApiResources.getURI(ApiResources.assessmentType.base, ApiResources.assessmentType.delete), {
assessmentTypeId: assessmentType.assessmentTypeId, modifiedByName: this.page.userAccount.fullName,
createdBy: this.page.userAccount.accountId,
modifiedBy: this.page.userAccount.accountId })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { }))
.subscribe(
() => {
this.notifyService.success("Assessment Type deleted successfully.");
this.fetchAddAssessmentType();
}
);
}, () => { });
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.loading = false;
this.submitting = undefined;
this.submitted = undefined;
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetchAddAssessmentType();
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
}
\ No newline at end of file

<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<ng-container *menuButton="'6AUzkb'">
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(caseTypeTemplate)"><i class="fe-plus mr-1"></i> Add </button>
</ng-container>
</div>
<h4 class="page-title">Case Type</h4>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card-box p-0">
<div class="row p-2" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading ...</span>
</div>
</div>
</div>
<div class="row p-2" *ngIf="!loading && (!records || !records.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(caseTypeTemplate)"><i class="fe-plus mr-1"></i> Add </button>
</div>
</div>
</div>
<div class="table-responsive" *ngIf="!loading && records.length > 0">
<table class="table table-sm">
<thead class="table-info">
<tr>
<th>Case Name</th>
<th>Case Code</th>
<th>CreatedBy</th>
<th>Created Date</th>
<th>Modified By</th>
<th>Modified Date</th>
<!--<th>Status</th>-->
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of records;index as i;">
<td>
<span [textContent]="item.caseTypeName"></span>
</td>
<td>
<span [textContent]="item.code"></span>
</td>
<td>
<h5 class="font-13 mb-0" [textContent]="item.createdByName"></h5>
<span class="badge badge-outline-info font-11" [textContent]="item.createdByRole"></span>
</td>
<td>
<span [textContent]="item.createdDate | date:'dd-MM-yyyy, hh:mm a'"></span>
</td>
<td>
<div *ngIf="item.modifiedBy">
<h5 class="font-13 mb-0" [textContent]="item.modifiedByName"></h5>
<span class="badge badge-outline-secondary font-11" [textContent]="item.modifiedByRole"></span>
</div>
<span *ngIf="!item.modifiedBy">-----</span>
</td>
<td>
<span *ngIf="item.modifiedDate" [textContent]="item.modifiedDate | date:'dd-MM-yyyy, hh:mm a'"></span>
<span *ngIf="!item.modifiedDate">----</span>
</td>
<!--<td>
<span [textContent]="item.active"></span>
</td>-->
<td>
<div class="d-flex align-items-center justify-content-end">
<a href="javascript:;" class="action-icon text-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenModel(caseTypeTemplate, item)"><i class="fe-edit"></i></a>
<button type="button" class="btn btn-xs btn-outline-danger mr-1" *ngIf="item.active" (click)="changeStatus(item,false)">
<i class="mdi mdi-account-cancel"></i>
</button>
<button type="button" class="btn btn-xs btn-outline-success mr-1" *ngIf="!item.active" (click)="changeStatus(item,true)">
<i class="mdi mdi-account-check"></i>
</button>
</div>
</td>
</tr>
</tbody>
<!--<tfoot>
<tr>
<td colspan="7">
<nav class="d-flex align-items-center justify-content-between">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - records.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> Records )</span>
</span>
</p>
<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="true" [ellipses]="true" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>
</nav>
</td>
</tr>
</tfoot>-->
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #caseTypeTemplate>
<form [formGroup]="caseTypeForm" (ngSubmit)="onSubmit()">
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-human-edit mr-1"></i>{{caseTypeForm.value.caseTypeId === 0 ? 'Add' : 'Edit'}} Case Type</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-12">
<div class="form-group">
<label class="mb-1">Case Type Name <code>*</code></label>
<input type="text" class="form-control" placeholder="Enter Case Type Name." formControlName="caseTypeName"
[ngClass]="{ 'is-invalid': submitted && form.caseTypeName.errors }" />
<div class="text-danger" *ngIf="submitted && form.caseTypeName.errors">
<p *ngIf="form.caseTypeName.errors.required">Case Type Name is required.</p>
<p *ngIf="form.caseTypeName.errors.maxlength">Only 250 characters are allowed.</p>
<p *ngIf="form.caseTypeName.errors.whiteSpaces">Please remove white space...</p>
<p *ngIf="form.caseTypeName.errors.pattern">Case Type allows alphabets only...</p>
</div>
</div>
</div>
<div class="col-12">
<div class="form-group">
<label class="mb-1">Case Type Code <code>*</code></label>
<input type="text" class="form-control" placeholder="Enter Case Type Name." formControlName="code"
[ngClass]="{ 'is-invalid': submitted && form.code.errors }" />
<div class="text-danger" *ngIf="submitted && form.code.errors">
<p *ngIf="form.code.errors.required">Case Type code is required.</p>
<p *ngIf="form.code.errors.maxlength">Only 250 characters are allowed.</p>
<p *ngIf="form.code.errors.whiteSpaces">Please remove white space...</p>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
\ No newline at end of file
import { OnInit, OnDestroy, TemplateRef, Component, ViewEncapsulation } from "@angular/core";
import { Page, IUserAccount } from "../../../../../shared/models";
import { FormBuilder, Validators, FormGroup } from "@angular/forms";
import { WhiteSpaceValidator } from "../../../../../shared/validators";
import { NgbModalRef, NgbModal } from "@ng-bootstrap/ng-bootstrap";
import { AppData } from "../../../../../app.data";
import { takeUntil, finalize } from "rxjs/operators";
import { ApiResources } from "../../../../../shared/helpers";
import { CaseType } from "../../../../../shared/entities/case-type.entity";
import { HttpErrorResponse } from "@angular/common/http";
import { HttpService, NotifyService } from "../../../../../shared/services";
@Component({
templateUrl: "./case-type.html",
encapsulation: ViewEncapsulation.None
})
export class CaseTypePage implements OnInit, OnDestroy{
page: Page;
modalRef: NgbModalRef;
submitting: boolean;
submitted: boolean;
caseTypeForm: FormGroup;
loading: boolean;
records: Array<CaseType>;
constructor(
private readonly formBuilder: FormBuilder,
private readonly modalService: NgbModal,
private readonly appData: AppData,
private readonly httpService: HttpService,
private readonly notifyService: NotifyService,
) {
this.page = new Page();
this.loading = true;
this.records = new Array<CaseType>();
}
private buildForm() {
this.caseTypeForm = this.formBuilder.group({
caseTypeId:0,
caseTypeName: [null, [Validators.required, Validators.maxLength(250), WhiteSpaceValidator.isValid, Validators.pattern('^[a-zA-Z]*$')]],
code: [null, [Validators.required, Validators.maxLength(250), WhiteSpaceValidator.isValid]],
})
}
changeStatus(item: CaseType, status: boolean) {
this.notifyService.confirm(`You want to ${status ? 'Activate' : 'Deactivate'} this cast type?`, () => {
const request = {
caseTypeId: item.caseTypeId,
caseTypeName: item.caseTypeName,
code: item.code,
modifiedBy: this.page.userAccount.accountId,
loginRoleId: this.page.userAccount.roleId,
modifiedByName: this.page.userAccount.fullName,
active: status
};
var url = ApiResources.getURI(ApiResources.caseType.base, ApiResources.caseType.modifyStatus);
this.httpService.post(url, request)
.subscribe(
(response: number) => {
if (response > 0) {
this.notifyService.successToast(`Record ${request["caseTypeId"] > 0 ? 'updated' : 'added'} successfully.`);
this.fetchAll();
}
if (response === -1) {
this.notifyService.warningToast("This caseType Name already exists.");
return;
}
},
(error: HttpErrorResponse) => {
this.notifyService.errorToast(error.error);
}
);
})
}
onOpenModel(content: TemplateRef<any>, record?: CaseType) {
this.buildForm();
if (record) {
this.caseTypeForm.patchValue({
caseTypeId: record.caseTypeId,
caseTypeName: record.caseTypeName,
code: record.code,
});
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: false,
size: 'lg',
windowClass: "custom-modal effect-scale"
});
}
get form() { return this.caseTypeForm.controls; }
onSubmit() {
this.submitted = true;
if (this.caseTypeForm.invalid) {
return;
}
this.submitting = true;
const request = {
...this.caseTypeForm.getRawValue(),
createdBy: this.page.userAccount.accountId,
loginRoleId: this.page.userAccount.roleId,
createdByName: this.page.userAccount.fullName
};
console.log("The case type request is : " + JSON.stringify(request));
var url = ApiResources.getURI(ApiResources.caseType.base, ApiResources.caseType.insert);
if (request["caseTypeId"] > 0) {
url = ApiResources.getURI(ApiResources.caseType.base, ApiResources.caseType.update);
}
this.httpService.post(url, request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitted = this.submitting = false))
.subscribe(
(response: number) => {
if (response > 0) {
this.notifyService.successToast(`Record ${request["caseTypeId"] > 0 ? 'updated' : 'added'} successfully.`);
this.fetchAll();
}
if (response === -1) {
this.notifyService.warningToast("This caseType Name already exists.");
return;
}
this.onCloseModal();
},
//(error: HttpErrorResponse) => {
// // this.onError(error);
//}
);
}
private fetchAll() {
this.loading = true;
const request = {
};
this.httpService.post(ApiResources.getURI(ApiResources.caseType.base, ApiResources.caseType.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<CaseType>) => {
this.records = response;
//UtilHelper.applyPagination(this.records);
},
//(error: HttpErrorResponse) => {
// this.onError(error)
//}
);
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetchAll();
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.page.unsubscribeAll();
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.loading = false;
this.submitting = undefined;
this.submitted = undefined;
}
}
\ No newline at end of file
<div class="content top1">
<div class="container-fluid">
<div>
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<ng-container *menuButton="'euKUJJ'">
<button *ngIf="!loadingCategories && categories && categories.length" type="button" class="btn btn-primary btn-sm" (click)="onOpenChargeCategoryModel(templateChargeCategory)"><i class="fe-plus mr-1"></i> Add Charge Category</button>
</ng-container>
</div>
<h4 class="page-title">Charge Category</h4>
</div>
</div>
</div>
<div>
<div class="card-box mb-1 p-1 pb-2">
<div class="col-lg-12">
<div class="row">
<div class="col-6 col-md-4 col-lg-4 col-xl-2">
<div class="form-group mb-0">
<label class="mb-1">Charge Category</label>
<ng-select class="ng-select-sm text-uppercase" [items]="filterchargeCategoryNames"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Search by charge Category"
[multiple]="false"
[(ngModel)]="filters.options.chargeCategoryId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No charge Category found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</div>
<div class="align-items-center col-6 col-lg-4 col-md-4 col-xl-2 d-flex">
<div style="margin-top: 25px;" class="d-flex justify-content-start mb-0">
<button type="button" (click)="onApplyFilters()" class="btn btn-sm btn-outline-primary mb-0">Search</button>
<button type="button" (click)="onResetFilters()" class="btn btn-sm btn-outline-danger ml-1 mb-0">Reset</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row" *ngIf="loadingCategories">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading charge category ...</span>
</div>
</div>
</div>
<div class="row" *ngIf="!loadingCategories && (!categories || !categories.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<h4 class="title">Oops! No Charge Category found<span *ngIf="filters.applied"> based on your filters criteria</span>.</h4>
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenChargeCategoryModel(templateChargeCategory)"><i class="fe-plus mr-1"></i> Add Charge Category</button>
</div>
</div>
</div>
<div class="card mg-b-0" *ngIf="!loadingCategories && categories && categories.length">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-centered table-sm table-striped table-borderless mb-0">
<thead>
<tr>
<th>Category Name</th>
<th>CreatedBy</th>
<th>Created Date</th>
<th>ModifiedBy</th>
<th>Modified Date</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of categories;" [ngClass]="{'table-success' : item.default}">
<td [textContent]="item.chargeCategoryName"></td>
<td [textContent]="item.createdByName"></td>
<td [textContent]="item.createdDate | date:'dd-MM-yyyy, hh:mm a'"></td>
<td [textContent]="item.modifiedByName||'---'"></td>
<td [textContent]="(item.modifiedDate | date:'dd-MM-yyyy, hh:mm a') ||'---'"></td>
<td>
<div class="d-flex align-items-center justify-content-end">
<a href="javascript:;" class="btn btn-xs btn-outline-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenChargeCategoryModel(templateChargeCategory,item)"><i class="fe-edit"></i></a>
<button type="button" class="btn btn-xs btn-outline-danger mr-1" *ngIf="item.active" (click)="onModifyStatus(item,false)">
<i class="mdi mdi-account-cancel"></i>
</button>
<button type="button" class="btn btn-xs btn-outline-success mr-1" *ngIf="!item.active" (click)="onModifyStatus(item,true)">
<i class="mdi mdi-account-check"></i>
</button>
<a href="javascript:;" *ngIf="!item.default" class="btn btn-xs btn-outline-secondary" placement="left" ngbTooltip="Set Default" (click)="setDefault(item)"><i class="fe-check"></i></a>
</div>
</td>
</tr>
</tbody>
</table>
<div>
</div>
</div>
<nav class="d-flex align-items-center justify-content-between p-2" *ngIf="pagination.totalPages > 1">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - categories.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> Charge Categories)</span>
</span>
</p>
<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>
</nav>
</div>
</div>
</div>
</div>
<ng-template #templateChargeCategory>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-mother-nurse mr-1"></i>{{categoryManagementForm.value.chargeCategoryId === 0 ? 'Add' : 'Edit'}} Charge Category</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<form [formGroup]="categoryManagementForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1">Charge Category Name <code>*</code></label>
<div class="form-group">
<input tabindex="1" type="text" block maxlength="150" autofocus formControlName="chargeCategoryName" autocomplete="nope" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.chargeCategoryName.errors) }" placeholder="Enter charge category name" />
</div>
</div>
<!--<div class="form-group mb-3">
<label class="mb-1">Locations</label>
<ng-select class="ng-select-sm text-uppercase" [items]="locations"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select locations"
[ngClass]="{ 'is-invalid': submitted && form.locationIds.errors }"
[multiple]="true"
formControlName="locationIds">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No locations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>-->
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
\ No newline at end of file
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService, ResourceService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { HttpErrorResponse } from "@angular/common/http";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, Validators, FormBuilder } from "@angular/forms";
import { Page, IUserAccount, Pagination, IResource } from "@shared/models";
import { ChargeCategory } from "@shared/entities/charge-category.entity";
import { WhiteSpaceValidator } from "../../../../../shared/validators";
class TrackBy {
chargeCategory(item: ChargeCategory) {
return item.chargeCategoryId;
}
}
class FilterOptions {
wardName: string = null;
departmentId: number;
chargeGroupId: number;
repeatTypeId: number;
chargeCategoryName: string = null;
chargeCategoryId: number = null;
//locationId: number;
}
class Filters {
options: FilterOptions;
applied: boolean;
constructor() {
this.init();
}
init() {
this.options = new FilterOptions();
this.applied = undefined;
}
}
@Component({
templateUrl: "./charge-category.html",
encapsulation: ViewEncapsulation.None
})
export class ChargeCategoryPage implements OnInit, OnDestroy {
page: Page;
filters: Filters;
trackBy: TrackBy;
pagination: Pagination;
loading: boolean;
modalRef: NgbModalRef;
submitting: boolean;
submitted: boolean;
locations: Array<IResource>;
selectedChargeCategory: ChargeCategory;
loadingCategories: boolean;
categories: Array<ChargeCategory>;
category: ChargeCategory;
categoryManagementForm: FormGroup;
filterchargeCategoryNames = [];
constructor(
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly httpService: HttpService,
private readonly resourceService: ResourceService
) {
this.loading = true;
this.page = new Page();
this.filters = new Filters();
this.trackBy = new TrackBy();
this.loading = true;
this.initPagination();
this.selectedChargeCategory = new ChargeCategory;
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
onApplyFilters() {
this.filters.applied = UtilHelper.isFiltersApplied(this.filters.options);
this.initPagination();
this.loading = true;
this.fetchChargeCategory();
}
onResetFilters() {
this.filters.init();
this.initPagination();
this.loading = true;
this.fetchChargeCategory();
}
private fetchLocations() {
this.resourceService.locations()
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.locations = response;
});
}
private filterChargeCategory() {
this.resourceService.chargeCategory()
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.filterchargeCategoryNames = response;
});
}
fetchChargeCategory() {
this.loadingCategories = true;
const request = Object.assign(UtilHelper.clone(this.filters.options), UtilHelper.clone(this.pagination));
this.httpService.post<Array<ChargeCategory>>(ApiResources.getURI(ApiResources.chargeCategory.base, ApiResources.chargeCategory.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loadingCategories = false))
.subscribe((response: Array<ChargeCategory>) => {
this.categories = response;
UtilHelper.applyPagination(this.categories, this.pagination);
});
}
setDefault(item: ChargeCategory) {
this.notifyService.confirm("Are you sure to change applied charge to this?", () => {
this.httpService.post(ApiResources.getURI(ApiResources.chargeCategory.base, ApiResources.chargeCategory.setDefaultCharge), item)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.loading = false;
}))
.subscribe((response: number) => {
if (response > 0) {
this.notifyService.successToast("Charge category is in use now.");
this.fetchChargeCategory();
}
else {
switch (response) {
case -2:
this.notifyService.warningToast("Charge category is in Deactive now, Make It as Active And then MAke It Default. ");
break;
}
}
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warningToast(errorMessage);
} else {
this.notifyService.defaultErrorToast();
}
});
});
}
private chargeCategoryForm() {
this.categoryManagementForm = this.formBuilder.group({
chargeCategoryId: 0,
chargeCategoryName: [null, [Validators.required, WhiteSpaceValidator.isValid]],
active: [true],
locationIds: [null],
default: [false]
});
}
onOpenChargeCategoryModel(content: TemplateRef<any>, category?: ChargeCategory) {
this.chargeCategoryForm();
if (category) {
this.category = category;
this.updateChargeCategoryForm();
if (category.locationIds) {
let location = new Array<number>();
category.locationIds.split(",").forEach((item) => { location.push(parseInt(item)) });
this.categoryManagementForm.patchValue({
locationIds: location
});
}
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
private updateChargeCategoryForm() {
this.categoryManagementForm.patchValue({
chargeCategoryId: this.category.chargeCategoryId,
chargeCategoryName: this.category.chargeCategoryName,
});
}
onSubmit() {
this.submitted = true;
if (!this.categoryManagementForm.valid) {
return;
}
this.submitting = true;
const request = Object.assign(UtilHelper.clone(this.categoryManagementForm.getRawValue()));
request["loginRoleId"] = this.page.userAccount.roleId,
request["createdByName"] = this.page.userAccount.fullName
request["modifiedByName"] = this.page.userAccount.fullName;
if (request.locationIds) {
request.locationIds = request.locationIds.join(",")
}
if (this.categoryManagementForm.value.chargeCategoryId === 0) {
request.createdBy = this.page.userAccount.accountId;
this.httpService.post(ApiResources.getURI(ApiResources.chargeCategory.base, ApiResources.chargeCategory.add), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchChargeCategory();
this.filterChargeCategory();
this.notifyService.success("Charge Categories has been added successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
} else {
request["modifiedByName"] = this.page.userAccount.fullName;
request["createdBy"] = this.page.userAccount.accountId;
request.modifiedBy = this.page.userAccount.accountId;
this.httpService.put(ApiResources.getURI(ApiResources.chargeCategory.base, ApiResources.chargeCategory.update), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchChargeCategory();
this.filterChargeCategory();
this.notifyService.success("Charge Categories details has been updated successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
}
}
get form() {
return this.categoryManagementForm.controls;
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.submitting = undefined;
this.submitted = undefined;
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetchChargeCategory();
}
onModifyStatus(charge: ChargeCategory, status: boolean) {
this.notifyService.confirm(`You want to ${status ? 'Activate' : 'Deactivate'} this charge category?`, () => {
const request = {
createdBy: this.page.userAccount.accountId,
active: status,
chargeCategoryId: charge.chargeCategoryId,
createdByName: this.page.userAccount.fullName,
createdByRole: this.page.userAccount.roleName,
loginRoleId: this.page.userAccount.roleId,
chargeCategoryName: charge.chargeCategoryName
};
this.httpService.post(ApiResources.getURI(ApiResources.chargeCategory.base, ApiResources.chargeCategory.modifyStatus), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loading = false }))
.subscribe((response: number) => {
if (response > 0) {
this.notifyService.successToast(`${status ? 'Activated' : 'Deactivated'} successfully.`);
this.fetchChargeCategory();
this.filterChargeCategory();
}
else {
switch (response) {
case -2:
this.notifyService.warningToast("Charge category is in Default now, You cannot make it as InActive, Make Some Other Charge Cat as Default Active And then MAke It as InActive. ");
break;
}
}
}, (error: HttpErrorResponse) => {
this.notifyService.errorToast(error.error);
});
});
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetchChargeCategory();
this.fetchLocations();
this.filterChargeCategory();
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button type="button" class="btn btn-primary btn-sm ml-1" (click)="onOpenModel(templateAddModifyCharges)">
<span *ngIf="!loading"><i class="fe-plus mr-1"></i> Add Charge</span>
</button>
</div>
<h4 class="page-title">Charge Management</h4>
</div>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading charges ...</span>
</div>
</div>
</div>
<div class="row" *ngIf="!loading">
<div class="col-12">
<div class="row">
<div class="col-lg-12">
<form [formGroup]="chargeFilterForm">
<div class="appointment-form bg-light bg-pattern py-0">
<div class="row">
<div class="col-lg-3"></div>
<div class="col-lg-2">
<div class="form-group">
<label class="mb-1">Charges</label>
<select class="form-control" formControlName="department" (change)="chargeFilter()">
<option selected [ngValue]="null">Select All</option>
<option *ngFor="let item of departments" [value]="item.name" [textContent]="item.name"></option>
</select>
</div>
</div>
<div class="col-lg-2">
<div class="form-group">
<label class="mb-1">Service Department</label>
<select class="form-control" formControlName="chargeGroup" (change)="chargeFilter()">
<option selected [ngValue]="null">Select All</option>
<option *ngFor="let item of chargeGroups" [value]="item.name" [textContent]="item.name"></option>
</select>
</div>
</div>
<div class="col-lg-2">
<div class="form-group">
<label class="mb-1">Service</label>
<select class="form-control" formControlName="charge" (change)="chargeFilter()">
<option selected [ngValue]="null">Select All</option>
<option *ngFor="let item of charges" [value]="item.name" [textContent]="item.name"></option>
</select>
</div>
</div>
<div class="col-lg-3 d-flex align-items-center justify-content-end">
<div>
<button type="button" (click)="clearChargeFilter()" class="btn btn-secondary btn-sm">
<i class="fe-x mr-1"></i> Clear
</button>
<button type="button" (click)="chargeFilter()" class="btn btn-primary btn-sm ml-1">
<i class="fe-filter mr-1"></i> Search
</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
<div class="card mb-0">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-centered table-sm table-striped table-bordered mb-0">
<thead>
<tr>
<th>S No</th>
<th>Charges</th>
<th>Service Department</th>
<th>Service</th>
<th>Charged</th>
<!--<th>IP Cost</th>
<th>OP Cost</th>-->
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let record of records; let i = index;">
<td [textContent]="i + 1"></td>
<td [textContent]="record.departmentName"></td>
<td [textContent]="record.chargeGroupName"></td>
<td>
<i *ngIf="record.automaticTypeId === 1" class="mdi mdi-bed mr-1"></i>
<i *ngIf="record.automaticTypeId === 2 || record.chargeTypeId === 1" class="mdi mdi-doctor mr-1"></i>
<i *ngIf="record.chargeTypeId === 2" class="mdi mdi-virus mr-1"></i>
<span [textContent]="record.chargeName"></span>
</td>
<td class="py-0">
<span *ngIf="record.repeatTypeId == repeatType.Once"><i class="mdi mdi-repeat-once mr-1 fs-22"></i>Charged Once</span>
<span *ngIf="record.repeatTypeId == repeatType.Day"><i class="mdi mdi-hours-24 mr-1 fs-22"></i>Charged Per Day</span>
<span *ngIf="record.repeatTypeId == repeatType.Hour"><i class="mdi mdi-timer-sand mr-1 fs-22"></i>Charged Every Hour</span>
</td>
<!--<td>
<span *ngIf="!record.automaticTypeId && !record.chargeTypeId" [textContent]="record.cost | currency: 'INR'"></span>
<span *ngIf="record.automaticTypeId || record.chargeTypeId">
<span placement="left" ngbTooltip="Cost depends on selected bed" *ngIf="record.automaticTypeId === automaticType.BedCharges">
<i class="mdi mdi-information text-primary mr-1"></i>
</span>
<span placement="left" ngbTooltip="Cost depends on doctor charges" *ngIf="record.automaticTypeId === automaticType.DoctorCharges">
<i class="mdi mdi-information text-primary mr-1"></i>
</span>
<span placement="left" ngbTooltip="Cost depends on selected special doctor" *ngIf="record.chargeTypeId === chargeType.Special">
<i class="mdi mdi-information text-primary mr-1"></i>
</span>
<span placement="left" ngbTooltip="Cost depends on doctor covid charges" *ngIf="record.chargeTypeId === chargeType.Covid">
<i class="mdi mdi-information text-primary mr-1"></i>
</span>
<span>---</span>
</span>
</td>
<td>
<span *ngIf="!record.automaticTypeId && !record.chargeTypeId" [textContent]="record.opCost | currency: 'INR'"></span>
<span *ngIf="record.automaticTypeId || record.chargeTypeId">
<span placement="left" ngbTooltip="Cost depends on selected bed" *ngIf="record.automaticTypeId === automaticType.BedCharges">
<i class="mdi mdi-information text-primary mr-1"></i>
</span>
<span placement="left" ngbTooltip="Cost depends on doctor charges" *ngIf="record.automaticTypeId === automaticType.DoctorCharges">
<i class="mdi mdi-information text-primary mr-1"></i>
</span>
<span placement="left" ngbTooltip="Cost depends on selected special doctor" *ngIf="record.chargeTypeId === chargeType.Special">
<i class="mdi mdi-information text-primary mr-1"></i>
</span>
<span placement="left" ngbTooltip="Cost depends on doctor covid charges" *ngIf="record.chargeTypeId === chargeType.Covid">
<i class="mdi mdi-information text-primary mr-1"></i>
</span>
<span>---</span>
</span>
</td>-->
<td>
<span class="badge badge-success" *ngIf="record.active">Active</span>
<span class="badge badge-soft-danger" *ngIf="!record.active">Inactive</span>
</td>
<td>
<div class="d-flex align-items-center justify-content-end">
<a *ngIf="!record.automaticTypeId && !record.chargeTypeId" href="javascript:;" class="action-icon text-primary" (click)="onOpenModel(templateAddModifyCharges, record)" placement="left" ngbTooltip="Edit Charge"><i class="fe-edit"></i></a>
</div>
</td>
</tr>
</tbody>
<tfoot *ngIf="pagination.totalPages > 1">
<tr>
<td colspan="9">
<nav class="d-flex align-items-center justify-content-between p-2">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - records.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> packages)</span>
</span>
</p>
<!--<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>-->
</nav>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateAddModifyCharges>
<form [formGroup]="mainForm" (submit)="onSubmit()">
<div class="modal-header">
<h4 class="modal-title">
<i class="mdi mdi-file-document-outline mr-1"></i><span *ngIf="selectedRecord">Update</span>
<span *ngIf="!selectedRecord">Add</span> New Charge
</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-12">
<div class="form-group">
<label class="mb-1">Charges Name(Department) <code>*</code></label>
<input list="autoSelectDepartments" (input)="onFilterDepartment(form.department.value)" type="text" class="form-control" formControlName="department" autocomplete="nope" [ngClass]="{ 'is-invalid': submitted && form.department.errors }" placeholder="Enter charges name">
<datalist id="autoSelectDepartments">
<option *ngFor="let record of departments" [value]="record.name">
</datalist>
<div *ngIf="form.department.errors" class="invalid-feedback">
<div *ngIf="form.department.errors.required">Please enter department name field</div>
</div>
</div>
<!--<div class="alert alert-info small p-1 mt-1"><i class="mdi mdi-information mr-1"></i>Eg: Consultation Charges, Investigation Charges, Hospitality Charges ...etc</div>-->
</div>
<div class="col-12">
<div class="form-group">
<label list="autoSelectChargeGroup" class="mb-1">Service Department Name <code>*</code></label>
<input list="autoSelectChargeGroup" (input)="onFilterChargeGroup(form.chargeGroup.value)" type="text" class="form-control" formControlName="chargeGroup" autocomplete="nope" [ngClass]="{ 'is-invalid': submitted && form.chargeGroup.errors }" placeholder="Enter service department name">
<datalist id="autoSelectChargeGroup">
<option *ngFor="let record of chargeGroups" [value]="record.name">
</datalist>
<div *ngIf="form.chargeGroup.errors" class="invalid-feedback">
<div *ngIf="form.chargeGroup.errors.required">Please enter service department name field</div>
</div>
</div>
<!--<div class="alert alert-info small p-1 mt-1"><i class="mdi mdi-information mr-1"></i>Eg: General Medicine, Hospital Services, Hospitality Services, BioChemistry, Haematology ...etc</div>-->
</div>
<div class="col-12">
<div class="form-group">
<label class="mb-1">Service Name <code>*</code></label>
<input list="autoSelectcharges" (input)="onFilterCharge(form.charge.value)" type="text" class="form-control" formControlName="charge" autocomplete="nope" [ngClass]="{ 'is-invalid': submitted && form.charge.errors }" placeholder="Enter service name">
<datalist id="autoSelectcharges">
<option *ngFor="let record of charges" [value]="record.name">
</datalist>
<div *ngIf="form.charge.errors" class="invalid-feedback">
<div *ngIf="form.charge.errors.required">Please enter service name field</div>
</div>
</div>
</div>
<div class="col-12">
<div class="form-group">
<label class="mb-1">Charged <code>*</code></label>
<select formControlName="repeatTypeId" [ngClass]="{ 'is-invalid': submitted && form.repeatTypeId.errors }" class="form-control">
<option selected hidden [ngValue]="null">Select</option>
<option [ngValue]="repeatType.Once">Charged Once</option>
<option [ngValue]="repeatType.Day">Charged Per Day</option>
<option [ngValue]="repeatType.Hour">Charged Every Hour</option>
</select>
<div *ngIf="form.repeatTypeId.errors" class="invalid-feedback">
<div *ngIf="form.repeatTypeId.errors.required">Please select Charged field</div>
</div>
</div>
</div>
</div>
<!--<div class="row mt-2">
<div class="col-lg-4">
<div class="form-group mb-0">
<label class="mb-1">IP Cost <code>*</code></label>
<input type="number" min="0" class="form-control" formControlName="cost" autocomplete="nope" numbersOnly [ngClass]="{ 'is-invalid': submitted && form.cost.errors }" placeholder="Enter ip cost">
<div *ngIf="form.cost.errors" class="invalid-feedback">
<div *ngIf="form.cost.errors.required">Please enter ip cost field</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="form-group mb-0">
<label class="mb-1">OP Cost</label>
<input type="number" min="0" class="form-control" formControlName="opCost" autocomplete="nope" numbersOnly [ngClass]="{ 'is-invalid': submitted && form.opCost.errors }" placeholder="Enter op cost">
<div *ngIf="form.opCost.errors" class="invalid-feedback">
<div *ngIf="form.opCost.errors.required">Please enter op cost field</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="form-group mb-0">
<label class="mb-1">Charged <code>*</code></label>
<select formControlName="repeatTypeId" [ngClass]="{ 'is-invalid': submitted && form.repeatTypeId.errors }" class="form-control">
<option selected hidden [ngValue]="null">Select</option>
<option [ngValue]="repeatType.Once">Charged Once</option>
<option [ngValue]="repeatType.Day">Charged Per Day</option>
<option [ngValue]="repeatType.Hour">Charged Every Hour</option>
</select>
<div *ngIf="form.repeatTypeId.errors" class="invalid-feedback">
<div *ngIf="form.repeatTypeId.errors.required">Please select Charged field</div>
</div>
</div>
</div>
</div>-->
</div>
<div class="modal-footer">
<button type="button" [disabled]="submitting" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">
<span *ngIf="selectedRecord">Update</span>
<span *ngIf="!selectedRecord">Add</span>
</span>
</button>
</div>
</form>
</ng-template>
import { Component, OnDestroy, OnInit, TemplateRef, ViewEncapsulation } from "@angular/core";
import { takeUntil, finalize } from "rxjs/operators";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { IUserAccount, Page, GenericResponse, GenericStatus, Pagination } from "@shared/models";
import { AppData, HttpService, NotifyService } from "@shared/services";
import { ApiResources, UtilHelper, LinqHelper } from "../../../../../shared/helpers";
import { FormGroup, FormBuilder, Validators } from "@angular/forms";
import { Subscription } from "rxjs";
import { IChargeModel } from "./models/charge.model";
import { RepeatType } from "../../../services/models/repeat-type.model";
import { IFilterModel } from "./models/filter.model";
import { AutomaticType } from "../../../services/models/automatic-type.model";
import { ChargeType } from "../../../../../shared/enums";
import { WhiteSpaceValidator } from "../../../../../shared/validators";
import { ModuleMaster } from "../../../../../shared/entities";
@Component({
templateUrl: "./charge-management.html",
encapsulation: ViewEncapsulation.None,
styleUrls: ['./charge-management.css']
})
export class ChargeManagementPage implements OnInit, OnDestroy {
page: Page;
repeatType = RepeatType;
automaticType = AutomaticType;
chargeType = ChargeType;
loading: boolean;
selectedRecord: IChargeModel;
records: Array<IChargeModel>;
submitting: boolean;
submitted: boolean;
departments: Array<IFilterModel>;
chargeGroups: Array<IFilterModel>;
charges: Array<IFilterModel>;
departmentsOriginal: Array<IFilterModel>;
chargeGroupsOriginal: Array<IFilterModel>;
chargesOriginal: Array<IFilterModel>;
chargeFilterForm: FormGroup;
mainForm: FormGroup;
modalRef: NgbModalRef;
pagination: Pagination;
departmentSubscription: Subscription;
chargeGroupSubscription: Subscription;
chargeSubscription: Subscription;
servicesmodules: Array<ModuleMaster>;
servicesmodulesMasterId: number=0;
constructor(
private readonly httpService: HttpService,
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService
) {
this.initPagination();
this.departments = new Array<IFilterModel>();
this.chargeGroups = new Array<IFilterModel>();
this.charges = new Array<IFilterModel>();
this.departmentsOriginal = new Array<IFilterModel>();
this.chargeGroupsOriginal = new Array<IFilterModel>();
this.chargesOriginal = new Array<IFilterModel>();
this.loading = true;
this.page = new Page();
this.servicesmodules = new Array<ModuleMaster>();
this.buildFilterForm();
this.buildMainForm();
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.findServicesModuleMasterId();
this.fetchMasters(() => {
this.fetch();
});
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.page.unsubscribeAll();
this.page.unSubscribe.complete();
this.departmentSubscription.unsubscribe();
this.chargeGroupSubscription.unsubscribe();
this.chargeSubscription.unsubscribe();
this.servicesmodules = null;
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
private buildFilterForm() {
this.chargeFilterForm = this.formBuilder.group({
department: [null],
chargeGroup: [null],
charge: [null]
});
this.departmentSubscription = this.chargeFilterForm.get("department").valueChanges.subscribe((value: string | null) => {
this.onFilterDepartment(value);
});
this.chargeGroupSubscription = this.chargeFilterForm.get("chargeGroup").valueChanges.subscribe((value: string | null) => {
this.onFilterChargeGroup(value);
});
this.chargeSubscription = this.chargeFilterForm.get("charge").valueChanges.subscribe((value: string | null) => {
this.onFilterCharge(value);
});
}
get form() { return this.mainForm.controls; };
private buildMainForm() {
this.mainForm = this.formBuilder.group({
department: [null, [Validators.required, WhiteSpaceValidator.isValid]],
chargeGroup: [null, [Validators.required, WhiteSpaceValidator.isValid]],
charge: [null, [Validators.required, WhiteSpaceValidator.isValid]],
repeatTypeId: [null, [Validators.required]],
//modulesMasterId: [null,[Validators.required]]
//cost: [null, [Validators.required]],
//opCost: [null]
});
}
onOpenModel(content: TemplateRef<any>, record?: IChargeModel) {
this.resetAutocomplete();
if (record) {
this.selectedRecord = record;
this.mainForm.patchValue({
department: record.departmentName,
chargeGroup: record.chargeGroupName,
charge: record.chargeName,
repeatTypeId: record.repeatTypeId,
//modulesMasterId: this.servicesmodulesMasterId.modulesMasterId
//cost: record.cost,
//opCost: record.opCost || 0
});
} else {
this.mainForm.reset();
this.selectedRecord = null;
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
/*size: "lg",*/
size:"modal-sm",
windowClass: "custom-modal slots-modal effect-scale"
});
return;
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.submitting = undefined;
this.submitted = undefined;
this.selectedRecord = null;
this.resetAutocomplete();
}
clearChargeFilter = () => {
this.chargeFilterForm.patchValue({
department: null,
chargeGroup: null,
charge: null,
});
this.initPagination();
this.fetch();
this.resetAutocomplete();
}
resetAutocomplete = () => {
this.departments = LinqHelper.cloneDeepArray<IFilterModel>(this.departmentsOriginal.filter(LinqHelper.uniqueOnlyBy));
this.chargeGroups = LinqHelper.cloneDeepArray<IFilterModel>(this.chargeGroupsOriginal.filter(LinqHelper.uniqueOnlyBy));
this.charges = LinqHelper.cloneDeepArray<IFilterModel>(this.chargesOriginal.filter(LinqHelper.uniqueOnlyBy));
}
chargeFilter = () => {
this.initPagination();
this.fetch();
}
onNextPage() {
this.fetch();
}
fetch = () => {
const data = {
...this.chargeFilterForm.value,
pageIndex: this.pagination.pageIndex,
pageSize: this.pagination.pageSize
}
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.chargeManagement.base, ApiResources.chargeManagement.fetch), data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: GenericResponse) => {
const data = response.data as Array<IChargeModel>;
this.records = data;
UtilHelper.applyPagination(this.records, this.pagination);
},
() => {
this.records = new Array<IChargeModel>();
}
);
}
fetchMasters = (callback?: Function) => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.chargeManagement.base, ApiResources.chargeManagement.masters), {})
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: GenericResponse) => {
const data = response.data as Array<IChargeModel>;
this.departmentsOriginal = data.map((x) => ({ chargeGroupName: x.chargeGroupName, chargeName: x.chargeName, id: x.departmentId, name: x.departmentName })) as Array<IFilterModel>;
this.departments = LinqHelper.cloneDeepArray<IFilterModel>(this.departmentsOriginal.filter(LinqHelper.uniqueOnlyBy));
this.chargeGroupsOriginal = data.map((x) => ({ departmentId: x.departmentId, departmentName: x.departmentName, chargeName: x.chargeName, id: x.chargeGroupId, name: x.chargeGroupName })) as Array<IFilterModel>;
this.chargeGroups = LinqHelper.cloneDeepArray<IFilterModel>(this.chargeGroupsOriginal.filter(LinqHelper.uniqueOnlyBy));
this.chargesOriginal = data.map((x) => ({ departmentName: x.departmentName, chargeGroupId: x.chargeGroupId, chargeGroupName: x.chargeGroupName, id: x.chargeId, name: x.chargeName })) as Array<IFilterModel>;
this.charges = LinqHelper.cloneDeepArray<IFilterModel>(this.chargesOriginal.filter(LinqHelper.uniqueOnlyBy));
callback();
},
() => {
callback();
}
);
}
onSubmit = () => {
this.submitted = true;
if (this.mainForm.invalid) return;
//const moduleMasterId = this.servicesmodulesMasterId;
const moduleMasterId = this.servicesmodules[0].modulesMasterId;
this.submitting = true;
var department = this.departmentsOriginal.find(x => x.name === this.mainForm.value.department);
var chargeGroup = department
? this.chargeGroupsOriginal.find(x => x.departmentId === department.id && x.name === this.mainForm.value.chargeGroup)
: null;
var data = {
departmentId: department ? department.id : 0,
departmentName: this.mainForm.value.department,
chargeGroupId: chargeGroup ? chargeGroup.id : 0,
chargeGroupName: this.mainForm.value.chargeGroup,
chargeName: this.mainForm.value.charge,
modulesMasterId: moduleMasterId,
//cost: this.mainForm.value.cost,
//opCost: this.mainForm.value.opCost,
repeatTypeId: this.mainForm.value.repeatTypeId,
createdBy: this.page.userAccount.accountId,
modifiedByName: this.page.userAccount.fullName
}
if (this.selectedRecord) {
data["chargeId"] = this.selectedRecord.chargeId;
data["oldChargeGroupId"] = this.selectedRecord.chargeGroupId;
}
const subUrl = this.selectedRecord
? ApiResources.chargeManagement.update
: ApiResources.chargeManagement.insert;
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.chargeManagement.base, subUrl), data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitting = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.onCloseModal();
this.clearChargeFilter();
this.notifyService.info(`Charge has been ${data["chargeId"] ? 'Updated' : 'Added'} successfully`,
() => {
this.selectedRecord = null;
this.fetchMasters(() => {
this.fetch();
});
});
}
if (response.status === GenericStatus[GenericStatus.Error]) {
this.notifyService.defaultError();
}
if (response.status === GenericStatus[GenericStatus.Info]) {
this.notifyService.warning("Charge is already exists, please enter different charge and try again");
}
},
() => {
this.notifyService.defaultError();
}
);
}
onFilterDepartment = (record: string) => {
this.chargeGroups = LinqHelper.cloneDeepArray<IFilterModel>(this.chargeGroupsOriginal.filter(x => !record ? true : x.departmentName.indexOf(record) !== -1).filter(LinqHelper.uniqueOnlyBy));
this.charges = LinqHelper.cloneDeepArray<IFilterModel>(this.chargesOriginal.filter(x => !record ? true : x.departmentName.indexOf(record) !== -1).filter(LinqHelper.uniqueOnlyBy));
}
onFilterChargeGroup = (record: string) => {
this.charges = LinqHelper.cloneDeepArray<IFilterModel>(this.chargesOriginal.filter(x => !record ? true : x.chargeGroupName.indexOf(record) !== -1).filter(LinqHelper.uniqueOnlyBy));
this.departments = LinqHelper.cloneDeepArray<IFilterModel>(this.departmentsOriginal.filter(x => !record ? true : x.chargeGroupName.indexOf(record) !== -1).filter(LinqHelper.uniqueOnlyBy));
}
onFilterCharge = (record: string) => {
this.chargeGroups = LinqHelper.cloneDeepArray<IFilterModel>(this.chargeGroupsOriginal.filter(x => !record ? true : x.chargeName.indexOf(record) !== -1).filter(LinqHelper.uniqueOnlyBy));
this.departments = LinqHelper.cloneDeepArray<IFilterModel>(this.departmentsOriginal.filter(x => !record ? true : x.chargeName.indexOf(record) !== -1).filter(LinqHelper.uniqueOnlyBy));
}
private findServicesModuleMasterId() {
this.loading = true;
const request = {
moduleName: "Services"
};
this.httpService.post(ApiResources.getURI(ApiResources.modulesMaster.base, ApiResources.modulesMaster.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe((response: Array<ModuleMaster>) => {
this.servicesmodules = response;
});
}
}
\ No newline at end of file
import { RepeatType } from "../../../../services/models/repeat-type.model";
import { AutomaticType } from "../../../../services/models/automatic-type.model";
export interface IChargeModel {
chargeId: number;
chargeName: string;
chargeGroupId: number;
chargeGroupName: string;
departmentId: number;
departmentName: string;
cost: number;
opCost: number;
modulesMasterId?: number;
unit: number;
repeatTypeId: RepeatType;
repeatTypeName: string;
automaticTypeId: AutomaticType;
automaticTypeName: string;
chargeTypeId: AutomaticType;
chargeTypeName: string;
chargeTypeMainId: number;
chargeTypeMainName: number;
active: boolean;
status: boolean;
deleting: boolean;
totalItems: number;
}
\ No newline at end of file
export interface IFilterModel {
id: number;
name: string;
departmentId?: number;
chargeGroupId?: number;
departmentName?: string;
chargeGroupName?: string;
chargeName?: string;
}
\ No newline at end of file

<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<ng-container *menuButton="'WAl8J5'">
<button *ngIf="!loading && chargeTypes && chargeTypes.length" type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateWord)"><i class="fe-plus mr-1"></i> Add Charge Type</button>
<!--<button *ngIf="!loading && !filters.applied && generalAdvices && generalAdvices.length" type="button" class="btn btn-secondary btn-sm ml-1" (click)="onShowFilters()"><i class="fe-filter mr-1"></i> Filters</button>-->
</ng-container>
</div>
<h4 class="page-title">Charge Type</h4>
</div>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading Charge Types ...</span>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && (!chargeTypes || !chargeTypes.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<h4 class="title">Oops! No Charge Types found<span *ngIf="filters.applied"> based on your filters criteria</span>.</h4>
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateWord)"><i class="fe-plus mr-1"></i> Add Charge Type</button>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && chargeTypes && chargeTypes.length">
<div class="col-12">
<div class="card mb-0">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-centered table-sm table-striped table-borderless mb-0">
<thead>
<tr>
<th>Charge Name</th>
<th>Created Date</th>
<!--<th>Modified By</th>-->
<th>Modified Date & Time</th>
<th>Active</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of chargeTypes; ">
<td [textContent]="item.chargeName"></td>
<td [textContent]="item.createdDate | date:'short'"></td>
<!--<td [textContent]="item.modifiedByName"></td>-->
<td [textContent]="(item.modifiedDate | date:'dd-MM-yyyy, hh:mm a') || '---'"></td>
<td>
<span class="badge badge-soft-success" *ngIf="item.active == true">Active</span>
<span class="badge badge-soft-danger" *ngIf="item.active == false">Inactive</span>
</td>
<td>
<div class="d-flex align-items-center justify-content-end">
<a href="javascript:;" class="action-icon text-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenModel(templateWord, item)"><i class="fe-edit"></i></a>
<a href="javascript:;" class="action-icon text-danger" placement="left" ngbTooltip="Delete" (click)="onDelete(item)"><i class="fe-trash-2"></i></a>
<a href="javascript:;" class="btn btn-sm btn-outline-success" *ngIf="item.active == true" title="Active" (click)=" onModifyStatus(item, false)">
<i class="fe-check-square"></i>
</a>
<a href="javascript:;" class="btn btn-sm btn-outline-warning" *ngIf="item.active == false" title="Inactive" (click)="onModifyStatus(item, true)">
<i class="fe-x-square"></i>
</a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<nav class="d-flex align-items-center justify-content-between p-2" *ngIf="pagination.totalPages > 1">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - chargeTypes.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> Charge Types )</span>
</span>
</p>
<!--<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>-->
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateWord>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-mother-nurse mr-1"></i>{{chargeTypesForm.value.chargeTypesId === 0 ? 'Add' : 'Edit'}} Charge Type</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<form [formGroup]="chargeTypesForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1">Charge Name <code>*</code></label>
<div class="form-group">
<input tabindex="1" type="text" block maxlength="150" autofocus formControlName="chargeName" autocomplete="nope" textOnly class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.chargeName.errors) }" placeholder="Enter charge name" />
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { HttpErrorResponse } from "@angular/common/http";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, Validators, FormBuilder } from "@angular/forms";
import { Page, IUserAccount, Pagination } from "@shared/models";
import { ChargeTypes } from "@shared/entities/charge-types.entity";
import { WhiteSpaceValidator } from "../../../../../shared/validators";
class TrackBy {
chargeTypes(item: ChargeTypes) {
return item.chargeTypesId;
}
}
class FilterOptions {
chargeName: string = null;
chargeTypesId: number;
}
class Filters {
options: FilterOptions;
applied: boolean;
constructor() {
this.init();
}
init() {
this.options = new FilterOptions();
this.applied = undefined;
}
}
@Component({
templateUrl: "./charge-types.html",
encapsulation: ViewEncapsulation.None
})
export class ChargeTypesPage implements OnInit, OnDestroy {
page: Page;
filters: Filters;
trackBy: TrackBy;
pagination: Pagination;
chargeTypesForm: FormGroup;
loading: boolean;
chargeTypes: Array<ChargeTypes>;
selectedChargeTypes: ChargeTypes;
modalRef: NgbModalRef;
submitting: boolean;
submitted: boolean;
modifying: boolean;
modifyingContent: string;
constructor(
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly httpService: HttpService
) {
this.loading = true;
this.page = new Page();
this.filters = new Filters();
this.trackBy = new TrackBy();
this.initPagination();
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
private buildForm() {
this.chargeTypesForm = this.formBuilder.group({
chargeTypesId: 0,
chargeName: [null, [Validators.required, WhiteSpaceValidator.isValid]],
active: [true],
});
}
onOpenModel(content: TemplateRef<any>, chargeTypes?: ChargeTypes) {
this.buildForm();
if (chargeTypes) {
this.selectedChargeTypes = chargeTypes;
this.updateForm();
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
fetchAddChargeTypes() {
this.loading = true;
const request = Object.assign(UtilHelper.clone(this.filters.options), UtilHelper.clone(this.pagination));
this.httpService
.post<Array<ChargeTypes>>(ApiResources.getURI(ApiResources.chargeTypes.base, ApiResources.chargeTypes.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<ChargeTypes>) => {
this.chargeTypes = response;
UtilHelper.applyPagination(this.chargeTypes, this.pagination);
},
() => {
this.chargeTypes = [];
}
);
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetchAddChargeTypes();
}
onSubmit() {
this.submitted = true;
if (!this.chargeTypesForm.valid) {
return;
}
console.log(this.chargeTypesForm.value);
this.submitting = true;
const request = Object.assign(UtilHelper.clone(this.chargeTypesForm.getRawValue()));
request["modifiedByName"] = this.page.userAccount.fullName;
if (Number (this.chargeTypesForm.value.chargeTypesId) === 0) {
request.createdBy = this.page.userAccount.accountId;
this.httpService.post(ApiResources.getURI(ApiResources.chargeTypes.base, ApiResources.chargeTypes.add), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchAddChargeTypes();
this.notifyService.success("Charge Type has been added successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
} else {
request.modifiedBy = this.page.userAccount.accountId;
request["modifiedByName"] = this.page.userAccount.fullName;
request["createdBy"] = this.page.userAccount.accountId;
delete request.type;
this.httpService.put(ApiResources.getURI(ApiResources.chargeTypes.base, ApiResources.chargeTypes.update), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchAddChargeTypes();
this.notifyService.success("Charge Type details has been updated successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
}
}
get form() {
return this.chargeTypesForm.controls;
}
private updateForm() {
this.chargeTypesForm.patchValue({
chargeTypesId: this.selectedChargeTypes.chargeTypesId,
chargeName: this.selectedChargeTypes.chargeName,
active: this.selectedChargeTypes.active
});
}
onDelete(chargeTypes: ChargeTypes) {
this.notifyService.delete(() => {
this.httpService
.post(ApiResources.getURI(ApiResources.chargeTypes.base, ApiResources.chargeTypes.delete), {
chargeTypesId: chargeTypes.chargeTypesId, modifiedByName: this.page.userAccount.fullName,
createdBy: this.page.userAccount.accountId,
modifiedBy: this.page.userAccount.accountId })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { }))
.subscribe(
() => {
this.notifyService.success("Charge Type deleted successfully.");
this.fetchAddChargeTypes();
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
}
);
}, () => { });
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.loading = false;
this.submitting = undefined;
this.submitted = undefined;
}
onModifyStatus(item: ChargeTypes, status: boolean) {
this.notifyService.confirm(`You want to ${status ? 'Activate' : 'Deactivate'} this Charge Type?`, () => {
const request = {
createdBy: this.page.userAccount.accountId,
active: status,
chargeTypesId: item.chargeTypesId,
createdByName: this.page.userAccount.fullName,
createdByRole: this.page.userAccount.roleName,
loginRoleId: this.page.userAccount.roleId,
chargeName: item.chargeName
};
this.httpService.post(ApiResources.getURI(ApiResources.chargeTypes.base, ApiResources.chargeTypes.modifyStatus), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loading = false }))
.subscribe((response: string) => {
if (response) {
status ? this.notifyService.successToast(`${status ? 'Activated' : 'Deactivated'} successfully.`) : this.notifyService.warningToast(`${status ? 'Activated' : 'Deactivated'} successfully.`)
}
this.fetchAddChargeTypes();
}, (error: HttpErrorResponse) => {
this.notifyService.errorToast(error.error);
});
});
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetchAddChargeTypes();
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
}
\ No newline at end of file

<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button *ngIf="!loading && consultationType && consultationType.length" type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateWord)"><i class="fe-plus mr-1"></i> Add Consultation Type</button>
<!--<button *ngIf="!loading && !filters.applied && generalAdvices && generalAdvices.length" type="button" class="btn btn-secondary btn-sm ml-1" (click)="onShowFilters()"><i class="fe-filter mr-1"></i> Filters</button>-->
</div>
<h4 class="page-title">Consultation Type</h4>
</div>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading Consultation Types ...</span>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && (!consultationType || !consultationType.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<h4 class="title">Oops! No Consultation Types found<span *ngIf="filters.applied"> based on your filters criteria</span>.</h4>
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateWord)"><i class="fe-plus mr-1"></i> Add Consultation Type</button>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && consultationType && consultationType.length">
<div class="col-12">
<div class="card mb-0">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-centered table-sm table-striped table-borderless mb-0">
<thead>
<tr>
<th>Name</th>
<th>Created By</th>
<th>Created Date</th>
<th>Modified By</th>
<th>Modified Date </th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of consultationType">
<td [textContent]="item.name"></td>
<td [textContent]="item.createdByName"></td>
<td [textContent]="item.createdDate | date:'dd-MM-yyyy, hh:mm a'"></td>
<td [textContent]="item.modifiedByName"></td>
<td [textContent]="(item.modifiedDate | date:'dd-MM-yyyy, hh:mm a') || '---'"></td>
<td>
<div class="d-flex align-items-center justify-content-end">
<a href="javascript:;" class="action-icon text-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenModel(templateWord, item)"><i class="fe-edit"></i></a>
<a href="javascript:;" class="action-icon text-danger" placement="left" ngbTooltip="Delete" (click)="onDelete(item)"><i class="fe-trash-2"></i></a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<nav class="d-flex align-items-center justify-content-between p-2" *ngIf="pagination.totalPages > 1">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - consultationType.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> consultationType )</span>
</span>
</p>
<!--<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>-->
<!--<ngb-pagination class="pagination justify-content-end"
[maxSize]="5"
[rotate]="false"
[ellipses]="false"
[(page)]="pagination.pageIndex"
[pageSize]="pagination.pageSize"
(pageChange)="onNextPage()"
[collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious>
<i class="fe-arrow-left"></i>
</ng-template>
<ng-template ngbPaginationNext>
<i class="fe-arrow-right"></i>
</ng-template>
</ngb-pagination>-->
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateWord>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-mother-nurse mr-1"></i>{{consultationTypeForm.value.consultationTypeId === 0 ? 'Add' : 'Edit'}} Consultation Type</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<form [formGroup]="consultationTypeForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1">Consultation Type Name <code>*</code></label>
<div class="form-group">
<input tabindex="1" type="text" block maxlength="150" autofocus formControlName="name" autocomplete="nope" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.name.errors) }" placeholder="Enter Consultation name" />
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { HttpErrorResponse } from "@angular/common/http";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, Validators, FormBuilder } from "@angular/forms";
import { Page, IUserAccount, Pagination } from "@shared/models";
import { ConsultationType } from "@shared/entities/consultation-type.entity";
class TrackBy {
consultationType(item: ConsultationType) {
return item.consultationTypeId;
}
}
class FilterOptions {
name: string = null;
consultationTypeId: number;
}
class Filters {
options: FilterOptions;
applied: boolean;
constructor() {
this.init();
}
init() {
this.options = new FilterOptions();
this.applied = undefined;
}
}
@Component({
templateUrl: "./consultation-type.html",
encapsulation: ViewEncapsulation.None
})
export class ConsultationTypePage implements OnInit, OnDestroy {
page: Page;
filters: Filters;
trackBy: TrackBy;
pagination: Pagination;
consultationTypeForm: FormGroup;
loading: boolean;
consultationType: Array<ConsultationType>;
selectedConsultationType: ConsultationType;
modalRef: NgbModalRef;
submitting: boolean;
submitted: boolean;
modifying: boolean;
modifyingContent: string;
constructor(
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly httpService: HttpService
) {
this.loading = true;
this.page = new Page();
this.filters = new Filters();
this.trackBy = new TrackBy();
this.initPagination();
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
private buildForm() {
this.consultationTypeForm = this.formBuilder.group({
consultationTypeId: 0,
name: [null, [Validators.required]],
active: [true],
});
}
onOpenModel(content: TemplateRef<any>, consultationType?: ConsultationType) {
this.buildForm();
if (consultationType) {
this.selectedConsultationType = consultationType;
this.updateForm();
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
fetchAddConsultationTypes() {
this.loading = true;
const request = Object.assign(UtilHelper.clone(this.filters.options), UtilHelper.clone(this.pagination));
this.httpService
.post<Array<ConsultationType>>(ApiResources.getURI(ApiResources.consultationType.base, ApiResources.consultationType.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<ConsultationType>) => {
this.consultationType = response;
UtilHelper.applyPagination(this.consultationType, this.pagination);
},
() => {
this.consultationType = [];
}
);
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetchAddConsultationTypes();
}
onSubmit() {
this.submitted = true;
if (!this.consultationTypeForm.valid) {
return;
}
console.log(this.consultationTypeForm.value);
this.submitting = true;
const request = Object.assign(UtilHelper.clone(this.consultationTypeForm.getRawValue()));
request["modifiedByName"] = this.page.userAccount.fullName;
request.createdBy = this.page.userAccount.accountId;
this.httpService.post(ApiResources.getURI(ApiResources.consultationType.base, ApiResources.consultationType.add), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchAddConsultationTypes();
if (Number(this.consultationTypeForm.value.consultationTypeId) === 0) {
this.notifyService.success("Consultation Type has been added successfully.");
} else {
this.notifyService.success("Consultaion Type details has been updated successfully.");
}
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
}
get form() {
return this.consultationTypeForm.controls;
}
private updateForm() {
this.consultationTypeForm.patchValue({
consultationTypeId: this.selectedConsultationType.consultationTypeId,
name: this.selectedConsultationType.name,
active: this.selectedConsultationType.active
});
}
onDelete(consultationType: ConsultationType) {
this.notifyService.delete(() => {
this.httpService
.post(ApiResources.getURI(ApiResources.consultationType.base, ApiResources.consultationType.delete), {
consultationTypeId: consultationType.consultationTypeId, modifiedByName: this.page.userAccount.fullName,
createdBy: this.page.userAccount.accountId,
modifiedBy: this.page.userAccount.accountId
})
.pipe(takeUntil(this.page.unSubscribe))
.subscribe(
() => {
this.notifyService.success("Consultation Type deleted successfully.");
this.fetchAddConsultationTypes();
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
}
);
}, () => {
this.notifyService.defaultError();
});
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.loading = false;
this.submitting = undefined;
this.submitted = undefined;
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetchAddConsultationTypes();
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<ng-container *menuButton="'mxn8Ug'">
<button *ngIf="!loadingDepartments && departments && departments.length" type="button" class="btn btn-primary btn-sm" (click)="onOpenDepartmentModel(templateDepartment)"><i class="fe-plus mr-1"></i> Add Department</button>
</ng-container>
</div>
<h4 class="page-title">Departments</h4>
</div>
</div>
</div>
<div class="row" *ngIf="loadingDepartments">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading departments ...</span>
</div>
</div>
</div>
<div class="col-12 p-0">
<div class="card-box mb-1 p-1">
<table class="table table-borderless table-sm mb-0">
<tr class="myFlex">
<td class="col-6 col-md-2">
<div class="form-group mb-0" style="font-size:12px;">
<label class="mb-1">Locations </label>
<ng-select class="ng-select-sm text-uppercase" [items]="locations"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select locations"
[(ngModel)]="filters.options.locationIds">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No locations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</td>
<td class="col-6 col-md-2">
<div class="form-group mb-0" style="font-size:12px;">
<label class="mb-1">From Date</label>
<input class="form-control date-picker" type="text" block placeholder="Select from date" [(ngModel)]="filters.options.fromDate" readonly autocomplete="nope" ngbDatepicker #fromDate="ngbDatepicker" (click)="fromDate.toggle(); $event.stopPropagation();" [maxDate]="setMaxDate" (dateSelect)="getMinDate()">
</div>
</td>
<td class="col-6 col-md-2">
<div class="form-group mb-0 position-relative" style="font-size:12px;">
<label class="mb-1">To Date</label>
<input class="form-control date-picker" type="text" block placeholder="Select to date" [(ngModel)]="filters.options.toDate" readonly autocomplete="nope" ngbDatepicker #toDate="ngbDatepicker" (click)="toDate.toggle(); $event.stopPropagation();" [minDate]="setMinDate" (dateSelect)="getMaxDate()">
</div>
</td>
<td class="col-6 col-md-2">
<div class="form-group mb-0" style="font-size:12px;">
<label class="mb-1">Department</label>
<ng-select class="ng-select-sm text-uppercase" [items]="dept"
bindLabel="value"
bindValue="id"
autocomplete="nope"
placeholder="Select Department"
[(ngModel)]="filters.options.departmentId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No department found <span *ngIf="searchTerm">for '{{searchTerm}}'</span>
</div>
</ng-template>
</ng-select>
</div>
</td>
<td class="col-12 col-md-2">
<div class="d-flex justify-content-center bellow767MarTop">
<button type="button" (click)="onApplyFilters()" class="btn btn-sm btn-outline-primary">Search</button>
<button type="button" (click)="onResetFilters()" class="btn btn-sm btn-outline-danger ml-1">Reset</button>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="row" *ngIf="!loadingDepartments && (!departments || !departments.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<h4 class="title">Oops! No departments found<span *ngIf="filters.applied"> based on your filters criteria</span>.</h4>
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenDepartmentModel(templateDepartment)"><i class="fe-plus mr-1"></i> Add Department</button>
</div>
</div>
</div>
<div class="card mg-b-0" *ngIf="!loadingDepartments && departments && departments.length">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-centered table-sm table-striped table-borderless">
<thead>
<tr>
<th>Department</th>
<th>Location</th>
<th>Created Date</th>
<th>Modified Date</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of departments;">
<td [textContent]="item.departmentName"></td>
<td [textContent]="item.locationNames || '----'"></td>
<td [textContent]="item.createdDate | date:'dd-MM-yyyy, hh:mm a'"></td>
<td [textContent]="(item.modifiedDate | date:'dd-MM-yyyy, hh:mm a') ||'---'"></td>
<td>
<div class="d-flex align-items-center justify-content-end">
<a href="javascript:;" class="action-icon text-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenDepartmentModel(templateDepartment,item)"><i class="fe-edit"></i></a>
<a href="javascript:;" *ngIf="item.departmentName != 'Pathology'" class="action-icon text-danger" placement="left" ngbTooltip="Delete" (click)="onDeleteDepartment(item)"><i class="fe-trash-2"></i></a>
</div>
</td>
</tr>
</tbody>
</table>
<div>
</div>
</div>
<nav class="d-flex align-items-center justify-content-between p-2" *ngIf="pagination.totalPages > 1">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - departments.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> department)</span>
</span>
</p>
<!--<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>-->
</nav>
</div>
</div>
</div>
</div>
<ng-template #templateDepartment>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-mother-nurse mr-1"></i>{{departmentManagementForm.value.departmentId === 0 ? 'Add' : 'Edit'}} Department</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<form [formGroup]="departmentManagementForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="row">
<div class="col-12" *ngIf="department && department.departmentName && department.departmentName === 'Pathology'">
<div class="alert alert-info">
<p><i class="mdi mdi-information mr-1"></i>Can not modify department name and department type for <strong>Pathology</strong> since its an internal department type.</p>
</div>
</div>
<div class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1">Department Name <code>*</code></label>
<div class="form-group">
<input tabindex="1" type="text" block maxlength="150" autofocus formControlName="departmentName" autocomplete="nope" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.departmentName.errors)}" placeholder="Enter department name" />
</div>
</div>
<div class="form-group mb-3">
<label class="mb-1">Locations</label><code>*</code>
<ng-select class="ng-select-sm text-uppercase" [items]="locations"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select locations"
[ngClass]="{ 'is-invalid': submitted && form.locationIds.errors }"
[multiple]="true"
formControlName="locationIds">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No locations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
<div class="form-group mb-3">
<label class="mb-1">Department Type <code>*</code></label>
<select class="form-control custom-select text-uppercase" formControlName="deptType" [ngClass]="{'is-invalid': submitted && form.deptType.errors }">
<option [ngValue]="null" disabled>Select</option>
<option [ngValue]="'Providers'">Providers</option>
<option [ngValue]="'Other'">Others</option>
</select>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
\ No newline at end of file
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService, ResourceService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { HttpErrorResponse } from "@angular/common/http";
import { NgbModal, NgbModalRef, NgbDate } from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, Validators, FormBuilder } from "@angular/forms";
import { Page, IUserAccount, Pagination, IResource } from "@shared/models";
import { ChargeManagement } from "../../../../../shared/entities/charge-management.entity";
import { WhiteSpaceValidator } from "../../../../../shared/validators";
class TrackBy {
charge(item: ChargeManagement) {
return item.chargeGroupId;
}
}
class FilterOptions {
wardName: string = null;
departmentId?: number;
chargeGroupId: number;
repeatTypeId: number;
locationIds?: number;
fromDate: string = null;
toDate: string = null;
}
class Filters {
options: FilterOptions;
applied: boolean;
constructor() {
this.init();
}
init() {
this.options = new FilterOptions();
this.applied = undefined;
}
}
@Component({
templateUrl: "./department.html",
encapsulation: ViewEncapsulation.None
})
export class DepartmentPage implements OnInit, OnDestroy {
page: Page;
filters: Filters;
trackBy: TrackBy;
pagination: Pagination;
showCharge: boolean;
loading: boolean;
departmentManagements: Array<ChargeManagement>;
chargeGroupManagements: Array<ChargeManagement>;
chargeManagements: Array<ChargeManagement>;
selectedbedManagements: ChargeManagement;
selectedChargeManagement: ChargeManagement;
showDepartments: boolean = false;
showChargeGroups: boolean = false;
showCharges: boolean = false;
modifying: boolean;
modifyingContent: string;
loadingDepartments: boolean;
loadingChargeGroups: boolean;
loadingCharges: boolean;
departments: Array<ChargeManagement>;
chargeGroups: Array<ChargeManagement>;
charges: Array<ChargeManagement>;
selectedDepartment: ChargeManagement;
selectedChargeGroup: ChargeManagement;
selectedCharges: ChargeManagement;
selectedbedRooms: ChargeManagement;
chargeManagement: ChargeManagement;
department: ChargeManagement;
chargeGroup: ChargeManagement;
charge: ChargeManagement;
modalRef: NgbModalRef;
departmentManagementForm: FormGroup;
chargeGroupManagementForm: FormGroup;
chargeManagementForm: FormGroup;
submitting: boolean;
submitted: boolean;
departmentTypeId: number;
chargeGroupTypeId: number;
locations: Array<IResource>;
loadingDepts: boolean;
dept: Array<IResource>;
setMaxDate: NgbDate;
setMinDate: NgbDate;
pathologyEdit: boolean=true;
constructor(
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly httpService: HttpService,
private readonly resourceService: ResourceService
) {
this.loading = true;
this.page = new Page();
this.filters = new Filters();
this.trackBy = new TrackBy();
this.loading = true;
this.initPagination();
this.selectedChargeManagement = new ChargeManagement();
this.department = new ChargeManagement();
}
private fetchDeptAll() {
this.loadingDepts = true;
this.resourceService.department()
.pipe(finalize(() => { this.loadingDepts = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.dept = response;
});
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
private fetchLocations() {
this.resourceService.locations()
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.locations = response;
});
}
fetchDeparments() {
this.loadingDepartments = true;
this.showDepartments = true;
this.showChargeGroups = false;
this.showCharges = false;
const request = Object.assign(UtilHelper.clone(this.filters.options), UtilHelper.clone(this.pagination));
this.httpService.post<Array<ChargeManagement>>(ApiResources.getURI(ApiResources.department.base, ApiResources.department.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loadingDepartments = false))
.subscribe((response: Array<ChargeManagement>) => {
this.departments = response;
UtilHelper.applyPagination(this.departments, this.pagination);
});
}
private departmentForm() {
this.departmentManagementForm = this.formBuilder.group({
departmentId: 0,
departmentName: [null, [Validators.required, WhiteSpaceValidator.isValid]],
deptType: [null, [Validators.required, WhiteSpaceValidator.isValid]],
active: [true],
locationIds: [null, [Validators.required]]
});
}
onOpenDepartmentModel(content: TemplateRef<any>, department?: ChargeManagement) {
this.departmentForm();
var deptId = this.departmentManagementForm.get("departmentId").value;
if (deptId == 0) {
this.pathologyEdit = true;
}
if (department) {
this.department = department;
this.updateDepartmentForm();
if (department.locationIds) {
let location = new Array<number>();
department.locationIds.split(",").forEach((item) => { location.push(parseInt(item)) });
this.departmentManagementForm.patchValue({
locationIds: location
});
}
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
private updateDepartmentForm() {
this.departmentManagementForm.patchValue({
departmentId: this.department.departmentId,
departmentName: this.department.departmentName,
deptType:this.department.deptType,
});
var getControl = this.departmentManagementForm.controls["departmentName"];
var getControlofDepartmentType = this.departmentManagementForm.controls["deptType"];
if (this.department && this.department.departmentName === "Pathology") {
getControl.disable();
getControlofDepartmentType.disable();
} else {
getControl.enable();
getControlofDepartmentType.enable();
}
}
onSubmit() {
this.submitted = true;
if (!this.departmentManagementForm.valid) {
return;
}
this.submitting = true;
const request = Object.assign(UtilHelper.clone(this.departmentManagementForm.getRawValue()));
request["modifiedByName"] = this.page.userAccount.fullName;
if (request.locationIds) {
request.locationIds = request.locationIds.join(",")
}
if (this.departmentManagementForm.value.departmentId === 0) {
request.createdBy = this.page.userAccount.accountId;
this.httpService.post(ApiResources.getURI(ApiResources.department.base, ApiResources.department.add), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchDeparments();
this.fetchDeptAll();
this.notifyService.success("Department has been added successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
} else {
request["modifiedByName"] = this.page.userAccount.fullName;
request["createdBy"] = this.page.userAccount.accountId;
request.modifiedBy = this.page.userAccount.accountId;
delete request.type;
this.httpService.put(ApiResources.getURI(ApiResources.department.base, ApiResources.department.update), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchDeparments();
this.fetchDeptAll();
this.notifyService.success("Department details has been updated successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
}
}
get form() {
return this.departmentManagementForm.controls;
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.submitting = undefined;
this.submitted = undefined;
this.department = new ChargeManagement();
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetchDeparments();
}
onDeleteDepartment(department: ChargeManagement) {
this.notifyService.delete(() => {
this.httpService
.post(ApiResources.getURI(ApiResources.department.base, ApiResources.department.delete), {
departmentId: department.departmentId, modifiedByName: this.page.userAccount.fullName,
createdBy: this.page.userAccount.accountId,
modifiedBy: this.page.userAccount.accountId })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { }))
.subscribe(
() => {
this.notifyService.success("Department deleted successfully.");
this.fetchDeparments();
this.fetchDeptAll();
}
);
}, () => { });
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetchDeparments();
// this.fetchChargeGroup();
//this.fetchCharges();
this.fetchLocations();
this.fetchDeptAll();
} else {
this.page.userAccount = undefined;
}
});
}
onApplyFilters() {
this.filters.applied = UtilHelper.isFiltersApplied(this.filters.options);
this.loading = true;
this.setMaxDate = null;
this.setMinDate = null;
this.fetchDeparments();
}
onResetFilters() {
this.filters.init();
this.setMaxDate = null;
this.setMinDate = null;
this.fetchDeparments();
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
getMinDate() {
const date = this.filters.options.fromDate.split("-");
const year = Number(date[0]);
const month = Number(date[1]);
const day = Number(date[2]);
this.setMinDate = new NgbDate(year, month, day);
}
getMaxDate() {
const date = this.filters.options.toDate.split("-");
const year = Number(date[0]);
const month = Number(date[1]);
const day = Number(date[2]);
this.setMaxDate = new NgbDate(year, month, day);
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<ng-container *menuButton="'4Jf6eU'">
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModal(templateUploadDocument, modalType.Add)"><i class="fe-plus mr-1"></i> Add </button>
</ng-container>
</div>
<h4 class="page-title">Diet GuideLines</h4>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card-box p-0">
<div class="row p-2" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading ...</span>
</div>
</div>
</div>
<div class="row p-2" *ngIf="!loading && (!documents || !documents.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModal(templateUploadDocument, modalType.Add)"><i class="fe-plus mr-1"></i> Add </button>
</div>
</div>
</div>
<div class="table-responsive" *ngIf="!loading && documents.length > 0">
<table class="table table-sm">
<thead class="table-info">
<tr>
<th>Diet Name</th>
<th>Diet Type</th>
<th>CreatedBy</th>
<th>Created Date</th>
<!--<th>Modified By</th>
<th>Modified Date</th>-->
<th>Status</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of documents;index as i;">
<td>
<div class="document-container">
<div class="document-thumbnail">
<a href="javascript:;" (click)="onOpenModal(templateViewDocument, modalType.View, item)"><img src="assets/images/documentImage1.png" [alt]="item.documentName" /></a>
</div>
<div class="media-body">
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="item.dietGuidLinesName"></h5>
</div>
</div>
<!--<h4><a href="javascript:;" (click)="onOpenModal(templateViewDocument, modalType.View, item)" class="text-dark" [textContent]="item.dietGuidLinesName"></a></h4>
<span [textContent]="item.dietGuidLinesName"></span>-->
</td>
<td>
<span [textContent]="item.dietTypeName"></span>
</td>
<td>
<h5 class="font-13 mb-0" [textContent]="item.createdByName"></h5>
<span class="badge badge-outline-info font-11" [textContent]="item.createdByRole"></span>
</td>
<td>
<span [textContent]="item.createdDate | date:'dd-MM-yyyy, hh:mm a'"></span>
</td>
<!--<td>
<div *ngIf="item.modifiedBy">
<h5 class="font-13 mb-0" [textContent]="item.modifiedByName"></h5>
<span class="badge badge-outline-secondary font-11" [textContent]="item.modifiedByRole"></span>
</div>
<span *ngIf="!item.modifiedBy">-----</span>
</td>
<td>
<span *ngIf="item.modifiedDate" [textContent]="item.modifiedDate | date:'dd-MM-yyyy, hh:mm a'"></span>
<span *ngIf="!item.modifiedDate">----</span>
</td>-->
<td>
<span class="badge badge-soft-success" *ngIf="item.active == true">Active</span>
<span class="badge badge-soft-danger" *ngIf="item.active == false">Inactive</span>
</td>
<td>
<div class="d-flex align-items-center justify-content-end">
<a href="javascript:;" class="mdi mdi-eye" (click)="onOpenModal(templateViewDocument, modalType.View, item)"></a>
<a href="javascript:;" class="btn btn-sm btn-outline-success" *ngIf="item.active == true" title="Active" (click)=" onModifyStatus(item, false)">
<i class="fe-check-square"></i>
</a>
<a href="javascript:;" class="btn btn-sm btn-outline-warning" *ngIf="item.active == false" title="Inactive" (click)="onModifyStatus(item, true)">
<i class="fe-x-square"></i>
</a>
<a href="javascript:;" title="Delete" (click)="onDelete(item)"><i class="mdi mdi-trash-can-outline"></i></a>
</div>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="8">
<nav class="d-flex align-items-center justify-content-between p-2" *ngIf="pagination.totalPages > 1">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - documents.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> Documents)</span>
</span>
</p>
<!--<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>-->
</nav>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateUploadDocument>
<form [formGroup]="uploadForm" (ngSubmit)="onSubmit()">
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-file-multiple mr-1"></i>Upload Diet Guideline</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<div class="row appointment-form bg-pattern bg-light mb-3">
<div class="col-md-4">
<div class="form-group mb-0">
<label class="mb-1">Diet Name <code>*</code></label>
<input type="text" autofocus formControlName="dietGuidLinesName" maxlength="100" block autocomplete="nope" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.dietGuidLinesName.errors) }" placeholder="Enter document name" />
</div>
</div>
<div class="col-md-4">
<div class="form-group mb-0">
<label class="mb-1">Diet Type <code>*</code></label>
<select class="form-control custom-select" formControlName="dietTypeId" [ngClass]="{ 'is-invalid': submitted && form.dietTypeId.errors }">
<option [ngValue]="null" *ngIf="!loadingDietTypes">Select</option>
<option selected *ngIf="loadingDietTypes">Loading...</option>
<option *ngFor="let item of dietTypes" [textContent]="item.name" [ngValue]="item.id"></option>
</select>
</div>
</div>
</div>
<file-dropper [expandable]="true"
[maxFiles]="maxFiles"
[maxFileSize]="10000"
[accept]="'application/pdf, image/jpeg, image/pjpeg, image/png, image/gif, video/mp4'"
(onSelectEmitter)="onFileSelect($event)">
</file-dropper>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default btn-sm" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm ml-1">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
<ng-template #templateEditDocument>
<form [formGroup]="uploadForm" (ngSubmit)="onSubmit()">
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-file-multiple mr-1"></i>Edit Documents</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<div class="row appointment-form bg-pattern bg-light mb-3">
<div class="col-md-12">
<div class="form-group">
<label class="mb-1">Document Name <code>*</code></label>
<input type="text" autofocus formControlName="dietGuidLinesName" maxlength="100" block autocomplete="nope" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.dietGuidLinesName.errors) }" placeholder="Enter document name" />
</div>
</div>
<!--<div class="col-md-12">
<div class="form-group mb-0">
<label class="mb-1">Description</label>
<textarea rows="1" cols="20" formControlName="description" block maxlength="250" autocomplete="nope" class="form-control" placeholder="Enter document description"></textarea>
</div>
</div>-->
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default btn-sm" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm ml-1">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
<ng-template #templateViewDocument>
<div class="modal-header">
<h4 class="modal-title"><span [textContent]="document.dietGuidLinesName"></span></h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<a href="javascript:;" (click)="onPrevious()" class="previous-document" title="Previous document" *ngIf="showPrevious"><i class="mdi mdi-arrow-left-bold"></i></a>
<a href="javascript:;" (click)="onNext()" class="next-document" title="Next document" *ngIf="showNext"><i class="mdi mdi-arrow-right-bold"></i></a>
<div class="p-3" *ngIf="loadingDocument">
<div class="d-flex align-items-center">
<span class="spinner-border text-primary" role="status" aria-hidden="true"></span>
<span class="ml-3">Please wait while loading Document ...</span>
</div>
</div>
<div *ngIf="!loadingDocument && documentError">
<div class="position-relative mh-400">
<no-data title="Document"></no-data>
</div>
</div>
<ng-container *ngIf="document.isImage">
<img [src]="document.formedUrl" [hidden]="loadingDocument || documentError" (load)="onDocumentLoad()" (error)="onDocumentError()" [alt]="document.dietGuidLinesName" />
</ng-container>
<ng-container *ngIf="document.isVideo">
<video style="width: 100%; height: 100%" controls (click)="toggleVideo()" #videoPlayer autoplay>
<source [src]="document.formedUrl" (load)="onDocumentLoad()" [type]="document.contentType">
</video>
</ng-container>
<ng-container *ngIf="!document.isImage && !document.isVideo">
<pdf-viewer [src]="document.formedUrl['changingThisBreaksApplicationSecurity']"
[render-text]="true"
[autoresize]="true"
[original-size]="false"
[fit-to-page]="false"
(on-progress)="onProgress($event)"
(error)="onDocumentError()"
style="width: 100%; height: 500px">
</pdf-viewer>
</ng-container>
</div>
</ng-template>
\ No newline at end of file
import { HttpErrorResponse } from "@angular/common/http";
import { Component, OnDestroy, OnInit, TemplateRef, ViewEncapsulation, ViewChild, ElementRef } from "@angular/core";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { DietGuidlinesModel } from "@shared/entities";
import { ModalType } from "@shared/enums";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { IUserAccount, Page, ProgressData, Pagination, IResource } from "@shared/models";
import { AppData, HttpService, NotifyService, ResourceService } from "@shared/services";
import { finalize, takeUntil } from "rxjs/operators";
import { DomSanitizer } from '@angular/platform-browser';
import { WhiteSpaceValidator } from "../../../../../shared/validators";
import { PdfViewerModule } from 'ng2-pdf-viewer';
@Component({
templateUrl: "./diet-guidlines.html",
encapsulation: ViewEncapsulation.None
})
export class DietGuidLinesPage implements OnInit, OnDestroy {
@ViewChild("videoPlayer", { static: false }) videoPlayer: ElementRef;
page: Page;
modalType = ModalType;
pagination: Pagination;
loading: boolean;
documents: Array<DietGuidlinesModel>;
document: DietGuidlinesModel;
modalRef: NgbModalRef;
uploadForm: FormGroup;
maxFiles = 1;
files: Array<File>;
submitting: boolean;
submitted: boolean;
errorMessage: string;
warningMessage: string;
modifyingContent: string;
loadingDocument: boolean;
documentError: boolean;
showPrevious: boolean;
showNext: boolean;
modifying: boolean;
loadingDietTypes: boolean;
dietTypes: Array<IResource>;
constructor(
private readonly httpService: HttpService,
private readonly modalService: NgbModal,
private readonly notifyService: NotifyService,
private readonly formBuilder: FormBuilder,
private readonly appData: AppData,
private readonly sanitizer: DomSanitizer,
private readonly resourceService: ResourceService,
) {
this.page = new Page();
this.initPagination();
this.documents = new Array<DietGuidlinesModel>();
this.dietTypes = new Array<IResource>();
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 12;
}
private fetchDocuments() {
this.loading = true;
const request = Object.assign(UtilHelper.clone(this.pagination));
this.httpService.post(ApiResources.getURI(ApiResources.dietGuidlines.base, ApiResources.dietGuidlines.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loading = false }))
.subscribe((response: Array<DietGuidlinesModel>) => {
console.log(response);
this.documents = response;
UtilHelper.applyPagination(this.documents, this.pagination);
});
}
private buildForm(document?: DietGuidlinesModel) {
this.uploadForm = this.formBuilder.group({
dietGuidLinesId: [document && document.dietGuidLinesId ? document.dietGuidLinesId : 0, [Validators.required]],
dietGuidLinesName: [document && document.dietGuidLinesName ? document.dietGuidLinesName : "", [Validators.required, WhiteSpaceValidator.isValid]],
dietTypeId: [document && document.dietTypeId ? document.dietTypeId : null, [Validators.required]]
});
}
get form() { return this.uploadForm.controls }
private prepareDocument(document: DietGuidlinesModel) {
this.loadingDocument = true;
this.document = document;
this.documentError = false;
this.document.isImage = this.document.contentType.indexOf("pdf") < 0 && this.document.contentType.indexOf("video") < 0;
this.document.isVideo = this.document.contentType.indexOf("video") >= 0;
if (this.document.isImage || this.document.isVideo) {
this.document.formedUrl = this.sanitizer.bypassSecurityTrustResourceUrl(`${ApiResources.getURI(ApiResources.dietGuidlines.base, ApiResources.dietGuidlines.downloadFileGet)}?id=${this.document.dietGuidLinesId}&url=${this.document.documentUrl}`);
}
if (!this.document.isImage && !this.document.isVideo) {
this.httpService
.post(ApiResources.getURI(ApiResources.dietGuidlines.base, ApiResources.dietGuidlines.downloadFile), { ...document })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loadingDocument = false; }))
.subscribe(
(response: DietGuidlinesModel) => {
this.document.formedUrl = this.sanitizer.bypassSecurityTrustResourceUrl(`data:application/pdf;base64, ${response.base64}`);
}
);
} else {
this.loadingDocument = false;
}
}
toggleVideo() {
this.videoPlayer.nativeElement.play();
}
onDocumentLoad() {
this.loadingDocument = false;
}
onDocumentError() {
this.loadingDocument = false;
this.documentError = true;
}
onOpenModal(content: TemplateRef<any>, type: ModalType, document?: DietGuidlinesModel) {
if (type === ModalType.View) {
this.prepareDocument(document);
const index = this.documents.findIndex((m => m.dietGuidLinesId === this.document.dietGuidLinesId) as any);
if (index === 0 && this.documents.length === 1) {
this.showPrevious = false;
this.showNext = false;
} else if (index === 0) {
this.showPrevious = false;
this.showNext = true;
} else if (index === this.documents.length - 1) {
this.showPrevious = true;
this.showNext = false;
} else {
this.showPrevious = true;
this.showNext = true;
}
this.modalRef = this.modalService.open(content, {
keyboard: false,
centered: true,
windowClass: "document-view-modal custom-modal effect-scale"
});
} else if (type === ModalType.Edit) {
this.document = document;
this.buildForm(document);
this.modalRef = this.modalService.open(content, {
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale",
backdrop: "static"
});
} else {
this.buildForm();
this.modalRef = this.modalService.open(content, {
keyboard: false,
centered: true,
size: "lg",
windowClass: "custom-modal effect-scale",
backdrop: "static"
});
}
}
onModifyStatus(item: DietGuidlinesModel, status: boolean) {
this.notifyService.confirm(`You want to ${status ? 'Activate' : 'Deactivate'} this diet Type?`, () => {
const request = {
modifiedBy: this.page.userAccount.accountId,
active: status,
dietGuidLinesId: item.dietGuidLinesId,
modifiedByName: this.page.userAccount.fullName,
createdByRole: this.page.userAccount.roleName,
loginRoleId: this.page.userAccount.roleId,
dietGuidLinesName: item.dietGuidLinesName
};
this.httpService.post(ApiResources.getURI(ApiResources.dietGuidlines.base, ApiResources.dietGuidlines.modifyStatus), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loading = false }))
.subscribe((response: string) => {
if (response) {
this.notifyService.successToast(`${status ? 'Activated' : 'Deactivated'} successfully.`);
}
this.fetchDocuments();
}, (error: HttpErrorResponse) => {
this.notifyService.errorToast(error.error);
});
});
}
onPrevious() {
let index = this.documents.findIndex((m => m.dietGuidLinesId === this.document.dietGuidLinesId) as any);
index = index - 1;
this.showPrevious = index !== 0;
this.showNext = true;
this.document = undefined;
this.prepareDocument(this.documents[index]);
}
onNext() {
let index = this.documents.findIndex((m => m.dietGuidLinesId === this.document.dietGuidLinesId) as any);
index = index + 1;
this.showNext = index !== this.documents.length - 1;
this.showPrevious = true;
this.document = undefined;
this.prepareDocument(this.documents[index]);
}
onProgress(progressData: ProgressData) {
if (progressData.loaded === progressData.total) {
this.loadingDocument = false;
}
}
onCloseModal() {
if (this.modalRef) {
this.modalRef.close();
this.modalRef = undefined;
this.submitted = undefined;
this.submitting = undefined;
this.errorMessage = undefined;
this.warningMessage = undefined;
this.files = [];
this.document = undefined;
this.loadingDocument = undefined;
this.documentError = undefined;
this.showNext = undefined;
this.showPrevious = undefined;
this.modifying = undefined;
this.modifyingContent = undefined;
}
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetchDocuments();
}
onFileSelect(files: Array<File>) {
this.files = files;
}
onDelete(document: DietGuidlinesModel) {
this.notifyService.delete(() => {
const request = {
dietGuidLinesId: document.dietGuidLinesId,
modifiedBy: this.page.userAccount.accountId,
modifiedByName: this.page.userAccount.fullName,
documentUrl: document.documentUrl,
dietGuidLinesName: document.dietGuidLinesName
};
this.httpService.post(ApiResources.getURI(ApiResources.dietGuidlines.base, ApiResources.dietGuidlines.delete), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: number) => {
if (response > 0) {
this.notifyService.successToast("Record deleted successfully.");
}
if (response === -3) {
this.notifyService.warningToast("The record you tried to delete can't be deleted because it is being used.");
}
this.fetchDocuments();
},
);
})
}
onSubmit() {
this.submitted = true;
if (!this.uploadForm.valid || this.warningMessage) {
return;
}
this.errorMessage = undefined;
this.submitting = true;
const model = UtilHelper.clone(this.uploadForm.value);
if (model["dietGuidLinesId"] === 0) {
const formData = new FormData();
formData.append("CreatedBy", this.page.userAccount.accountId.toString());
formData.append("CreatedByName", this.page.userAccount.fullName);
formData.append("DietGuidLinesName", model["dietGuidLinesName"]);
formData.append("DietTypeId", model["dietTypeId"]);
const files = this.files;
if (!files || !files.length) {
this.submitting = false;
this.notifyService.info("Please select at least one file");
return;
}
const n = files.length;
if (n > this.maxFiles) {
files.splice(this.maxFiles, files.length);
}
files.forEach((file: File, index: number) => {
formData.append(`File${index + 1}`, file, file.name);
});
this.httpService
.postFile(ApiResources.getURI(ApiResources.dietGuidlines.base, ApiResources.dietGuidlines.insert), formData)
.pipe(finalize(() => { this.submitted = false; this.submitting = false; }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe(
(response: any) => {
if (response.length > 0) {
this.files = new Array();
this.notifyService.successToast("Document uploaded successfully.");
}
if (response <= 0) {
this.notifyService.warningToast("Document name exists already.");
}
this.onCloseModal();
this.fetchDocuments();
},
(error: HttpErrorResponse) => {
this.errorMessage = UtilHelper.handleError(error);
this.notifyService.warning(this.errorMessage);
}
);
} else {
model["modifiedBy"] = this.page.userAccount.accountId;
model["modifiedByName"] = this.page.userAccount.fullName;
delete model["file"];
this.httpService
.put(ApiResources.getURI(ApiResources.dietGuidlines.base, ApiResources.dietGuidlines.update), model)
.pipe(finalize(() => { this.submitted = false, this.submitting = false; }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe(
() => {
this.notifyService.successToast("Document details updated successfully.");
this.onCloseModal();
this.fetchDocuments();
},
(error: HttpErrorResponse) => {
this.errorMessage = UtilHelper.handleError(error);
this.notifyService.warning(this.errorMessage);
}
);
}
}
private fetchDietTypes() {
this.loadingDietTypes = true;
this.resourceService.dietTypes()
.pipe(finalize(() => { this.loadingDietTypes = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.dietTypes = response;
})
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((account: IUserAccount) => {
if (account) {
this.page.userAccount = account;
this.fetchDietTypes();
this.fetchDocuments();
}
});
}
ngOnDestroy() {
this.page.unsubscribeAll();
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<ng-container *menuButton="'OqdcT9'">
<button type="button" *ngIf="!loading && discharges && discharges.length" class="btn btn-primary btn-sm" (click)="onOpenModel(templateModify)"><i class="fe-plus mr-1"></i> Add Discharge Instructions</button>
<!--<button *ngIf="!loading && !filters.applied && generalAdvices && generalAdvices.length" type="button" class="btn btn-secondary btn-sm ml-1" (click)="onShowFilters()"><i class="fe-filter mr-1"></i> Filters</button>-->
</ng-container>
</div>
<h4 class="page-title">Discharge Instructions</h4>
</div>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading discharge instructions ...</span>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && (!discharges || !discharges.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<h4 class="title">Oops! No discharge instructions found<span *ngIf="filters.applied"> based on your filters criteria</span>.</h4>
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateModify)"><i class="fe-plus mr-1"></i> Add Discharge Instructions</button>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && discharges && discharges.length">
<div class="col-12">
<div class="card mb-0">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-centered table-sm table-striped table-borderless">
<thead>
<tr>
<th>Discharge Instructions</th>
<th>Status</th>
<th>Created By</th>
<th>Modified By</th>
<th>Status</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of discharges; trackBy: trackBy.role">
<td [textContent]="item.dischargeInstructionName"></td>
<td [textContent]="item.active === true ? 'Active' : 'InActive'"></td>
<td>
<p class="mb-0" [textContent]="item.createdByName || '-----'"></p>
<p class="mb-0" [textContent]="item.createdByRole"></p>
<p class="mb-0" [textContent]="item.createdDate | date:'dd-MM-yyyy, hh:mm a'"></p>
</td>
<td>
<p class="mb-0" [textContent]="item.modifiedByName || '-----'"></p>
<p class="mb-0" [textContent]="item.modifiedByRole"></p>
<p class="mb-0" [textContent]="(item.modifiedDate | date:'dd-MM-yyyy, hh:mm a')"></p>
</td>
<td>
<div class="media">
<span class="badge badge-success" *ngIf="item.active">Active</span>
<span class="badge badge-soft-danger" *ngIf="!item.active">Inactive</span>
</div>
</td>
<td>
<div class="d-flex align-items-center justify-content-end">
<span *ngIf="item.active">
<a href="javascript:;" class="action-icon text-primary" placement="left" ngbTooltip="Edit" (click)="onOpenModel(templateModify, item)"><i class="fe-edit"></i></a>
</span>
<span *ngIf="item.active">
<a (click)="onModifyStatus(item,false)" href="javascript:;" class="action-icon text-danger" placement="left" ngbTooltip="To Deactivate" style="margin-right:6px;">
<i class="fe-delete"></i>
</a>
</span>
<span *ngIf="!item.active">
<a (click)="onModifyStatus(item,true)" href="javascript:;" class="action-icon text-success mr-1" placement="left" ngbTooltip="To Activated">
<i class="mdi mdi-check-all"></i>
</a>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<nav class="d-flex align-items-center justify-content-between p-2" *ngIf="pagination.totalPages > 1">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - discharges.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> Discharge Instructions )</span>
</span>
</p>
<!--<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>-->
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateModify>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-mother-nurse mr-1"></i>{{dischargeForm.value.dischargeInstructionId === 0 ? 'Add' : 'Edit'}} Discharge Instructions</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<form [formGroup]="dischargeForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1">Discharge Instruction <code>*</code></label>
<div class="form-group">
<input tabindex="1" type="text" block maxlength="150" autofocus formControlName="dischargeInstructionName" autocomplete="nope" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.dischargeInstructionName.errors) }" placeholder="Discharge instructions" />
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
\ No newline at end of file
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { DischargeInstructions } from "@shared/entities";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { HttpErrorResponse } from "@angular/common/http";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, Validators, FormBuilder } from "@angular/forms";
import { Page, IUserAccount, Pagination } from "@shared/models";
import { WhiteSpaceValidator } from "../../../../../shared/validators";
class TrackBy {
role(item: DischargeInstructions) {
return item.dischargeInstructionId;
}
}
class FilterOptions {
dischargeInstructionName: string = null;
dischargeInstructionId: number;
}
class Filters {
options: FilterOptions;
applied: boolean;
constructor() {
this.init();
}
init() {
this.options = new FilterOptions();
this.applied = undefined;
}
}
@Component({
templateUrl: "./discharge-instructions.html",
encapsulation: ViewEncapsulation.None
})
export class DischargeInstructionsPage implements OnInit, OnDestroy {
page: Page;
filters: Filters;
trackBy: TrackBy;
pagination: Pagination;
loading: boolean;
discharges: Array<DischargeInstructions>;
selectedDischarges: DischargeInstructions;
modalRef: NgbModalRef;
dischargeForm: FormGroup;
submitting: boolean;
submitted: boolean;
loadingDischarges: boolean;
modifying: boolean;
modifyingContent: string;
constructor(
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly httpService: HttpService
) {
this.loading = true;
this.page = new Page();
this.filters = new Filters();
this.trackBy = new TrackBy();
this.loading = true;
this.initPagination();
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
private fetchDischargeInstuctions() {
const request = Object.assign(UtilHelper.clone(this.filters.options), UtilHelper.clone(this.pagination));
this.httpService.post<Array<DischargeInstructions>>(ApiResources.getURI(ApiResources.discharges.base, ApiResources.discharges.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe((response: Array<DischargeInstructions>) => {
this.discharges = response;
UtilHelper.applyPagination(this.discharges, this.pagination);
});
}
private buildForm() {
this.dischargeForm = this.formBuilder.group({
dischargeInstructionId: 0,
dischargeInstructionName: [null, [Validators.required, WhiteSpaceValidator.isValid]],
active: [ true ],
});
}
private updateForm() {
this.dischargeForm.patchValue({
dischargeInstructionId: this.selectedDischarges.dischargeInstructionId,
dischargeInstructionName: this.selectedDischarges.dischargeInstructionName,
active: this.selectedDischarges.active
});
}
onOpenModel(content: TemplateRef<any>, discharge?: DischargeInstructions) {
this.buildForm();
if (discharge) {
this.selectedDischarges = discharge;
this.updateForm();
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
onSubmit() {
this.submitted = true;
if (!this.dischargeForm.valid) {
return;
}
console.log(this.dischargeForm.value);
this.submitting = true;
const request = Object.assign(UtilHelper.clone(this.dischargeForm.getRawValue()));
request["modifiedByName"] = this.page.userAccount.fullName;
request.modifiedBy = this.page.userAccount.accountId;
if (Number(this.dischargeForm.value.dischargeInstructionId) === 0) {
request.createdBy = this.page.userAccount.accountId;
this.httpService.post(ApiResources.getURI(ApiResources.discharges.base, ApiResources.discharges.add), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchDischargeInstuctions();
this.notifyService.success("Discharge instructions Added successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
} else {
request.modifiedBy = this.page.userAccount.accountId;
request["modifiedByName"] = this.page.userAccount.fullName;
request["createdBy"] = this.page.userAccount.accountId;
delete request.type;
this.httpService.put(ApiResources.getURI(ApiResources.discharges.base, ApiResources.discharges.update), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchDischargeInstuctions();
this.notifyService.success("Discharge instructions details has been updated successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
}
}
//onDelete(discharge: DischargeInstructions) {
// this.notifyService.delete(() => {
// this.httpService
// .post(ApiResources.getURI(ApiResources.discharges.base, ApiResources.discharges.delete), { dischargeInstructionId: discharge.dischargeInstructionId })
// .pipe(takeUntil(this.page.unSubscribe))
// .pipe(finalize(() => { }))
// .subscribe(
// () => {
// this.notifyService.success("Discharge instructions deleted successfully.");
// this.fetchDischargeInstuctions();
// }
// );
// }, () => { });
//}
onModifyStatus(item: DischargeInstructions, status: boolean) {
this.notifyService.confirm(`You want to ${status ? 'Activate' : 'Deactivate'} this Discharge Instructions ?`, () => {
const request = {
modifiedBy: this.page.userAccount.accountId,
active: status,
dischargeInstructionId: item.dischargeInstructionId,
modifiedByName: this.page.userAccount.fullName,
createdByRole: this.page.userAccount.roleName,
loginRoleId: this.page.userAccount.roleId,
dischargeInstructionName: item.dischargeInstructionName
};
this.httpService.post(ApiResources.getURI(ApiResources.discharges.base, ApiResources.discharges.modifyStatus), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loading = false }))
.subscribe((response: number) => {
if (response > 0) {
this.notifyService.successToast(`${status ? 'Activated' : 'Deactivated'} successfully.`);
}
this.fetchDischargeInstuctions();
}, (error: HttpErrorResponse) => {
this.notifyService.errorToast(error.error);
});
});
}
get form() {
return this.dischargeForm.controls;
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.submitting = undefined;
this.submitted = undefined;
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetchDischargeInstuctions();
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetchDischargeInstuctions();
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
}
\ No newline at end of file
<style>
.badge-extras {
padding: 8px !important;
font-size: 90% !important;
font-weight: bolder !important;
margin-bottom: 3px !important;
border: 1px solid;
border-radius: 20px;
width: auto;
}
</style>
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button type="button" class="btn btn-sm btn-outline-primary" (click)="onModuleFormOpen(moduleAddition)">
<span class="btn-label btn-label-sm"><i class="mdi mdi-folder-plus-outline"></i></span>
Add Module
</button>
</div>
<h4 class="page-title">Discount Management</h4>
</div>
</div>
<div class="col-12 mt-2" *ngIf="loading">
<div class="row">
<div class="card col-12" style="height: 130px;">
<div class="card-body mb-0">
<div class="card-disabled" style="opacity: 0.375655;">
<div class="card-portlets-loader"></div>
</div>
<div class="text-center" style="margin-top: 60px;">Please wait while loading..</div>
</div>
</div>
</div>
</div>
<div class="col-12 mt-2" *ngIf="!loading && modules.length === 0">
<div class="card-box">
<div class="row">
<div class="col-12 mh-400">
<no-data [applied]="false" [title]="'Modules'"></no-data>
</div>
</div>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && modules.length > 0">
<div class="col-12">
<div class="card-box p-0">
<div class="table-responsive">
<table class="table table-centered table-sm mb-0">
<thead class="table-info">
<tr>
<th>Module Name</th>
<th>Roles</th>
<th>Created By</th>
<th>Created Date</th>
<th>Modified By</th>
<th>Modified Date</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let module of modules;let i = index;">
<td>
<div class="media">
<div class="avatar-sm mr-2">
<span class="avatar-title rounded-circle font-18 font-weight-bold text-primary bg-soft-primary"><i class="{{module.icon || 'mdi mdi-form-select'}}"></i></span>
</div>
<div class="media-body">
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="module.moduleName"></h5>
</div>
</div>
</td>
<td>
<div class="badge badge-outline-blue badge-extras ml-1" *ngFor="let role of module.allowedRoles;let j = index;"
#d="ngbPopover" popoverTitle="Disount Per Role {{role.value}}" (click)="onRoleSelected(module,role)" [ngbPopover]="moduleDiscountPerRole" [autoClose]="'outside'"
container="body" style="cursor:pointer;">
<ng-template #moduleDiscountPerRole>
<form [formGroup]="discountForm" (submit)="onDiscountModuleSubmit(d)">
<div class="row">
<div class="col-12">
<div class="form-group">
<label class="mb-0">Allowed Discount Percentage <code>*</code></label>
<input type="number" numbersOnly min="0" class="form-control" formControlName="allowedPercentage" placeholder="Enter allowed percentage."
[ngClass]="{ 'is-invalid': (submitted && forms.discount.allowedPercentage.errors) }" />
<div class="show-must is-invalid" *ngIf="submitted && forms.discount.allowedPercentage.errors">
<p *ngIf="forms.discount.allowedPercentage.errors.max">Maximum percentage can be 100 only.</p>
<p *ngIf="forms.discount.allowedPercentage.errors.min">Minimumn value can be 1.</p>
<p *ngIf="forms.discount.allowedPercentage.errors.required">This field is required.</p>
</div>
</div>
</div>
<div class="col-12 mt-1">
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting"><i class="mdi mdi-file mr-1"></i> Submit</span>
</button>
<button type="button" class="btn btn-sm btn-danger" (click)="d.toggle()">
<i class="mdi mdi-close mr-1"></i> Close
</button>
</div>
</div>
</div>
</form>
</ng-template>
<span [textContent]="role.value"></span>&nbsp;&nbsp;<span *ngIf="role.optionalText" class="badge bg-light text-dark ms-1" [textContent]="role.optionalText + '%'"></span>
</div>
</td>
<td>
<p class="mb-0" [textContent]="module.createdByName"></p>
<small><span class="badge badge-outline-success" [textContent]="module.createdByRole"></span></small>
</td>
<td><span [textContent]="module.createdDate | date:'dd-MM-yyyy, hh:mm a'"></span></td>
<td>
<p class="mb-0" [textContent]="module.modifiedByName || '--'"></p>
<small><span class="badge badge-outline-blue" [textContent]="module.modifiedByRole"></span></small>
</td>
<td><span [textContent]="(module.modifiedDate | date:'dd-MM-yyyy, hh:mm a') || '--'"></span></td>
<td>
<div class="d-flex align-items-center justify-content-center">
<a href="javascript:;" class="action-icon text-primary pr-2" placement="left" ngbTooltip="Edit" (click)="onModuleFormOpen(moduleAddition,module)"><i class="fe-edit"></i></a>
<button type="button" class="btn btn-xs btn-outline-danger" placement="left" ngbTooltip="Deactivate" *ngIf="module.active" (click)="onModifyStatus(module,false)">
<i class="fe-delete"></i>
</button>
<button type="button" class="btn btn-xs btn-outline-success" placement="left" ngbTooltip="Activate" *ngIf="!module.active" (click)="onModifyStatus(module,true)">
<i class="fe-check"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #moduleAddition>
<form [formGroup]="moduleForm" (submit)="onModuleFormSubmit()">
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-fireplace-off mr-1"></i>Modules</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-12">
<div class="form-group">
<label class="mb-0">Module Name <code>*</code></label>
<!--<ng-select [items]="discounts"
bindLabel="value"
bindValue="id"
placeholder="Select Module"
[ngClass]="{ 'is-invalid': (submitted && forms.module.moduleName.errors) }"
formControlName="discountModuleId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled" *ngIf="searchTerm">
No Module found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>-->
<select class="form-control" formControlName="moduleName" [ngClass]="{ 'is-invalid': (submitted && forms.module.moduleName.errors) }">
<option value="">--Please Select--</option>
<option value="Pharmacy">Pharmacy</option>
<option value="Laboratory">Laboratory</option>
<option value="Services">Services</option>
<option value="Appointments">Appointment/OutPatient</option>
<option value="Labs">Labs</option>
<option value="Scan">Scan</option>
</select>
</div>
</div>
<div class="col-12">
<div class="form-group">
<label class="mb-0">Icon</label>
<input type="text" class="form-control" formControlName="icon" placeholder="Enter icon."
[ngClass]="{ 'is-invalid': (submitted && forms.module.icon.errors) }" />
</div>
</div>
<div class="col-12">
<div class="form-group">
<label class="mb-0">Role <code>*</code></label>
<ng-select class="ng-select-sm" [items]="roles"
[loading]="loadingRoles"
bindLabel="value"
bindValue="id"
placeholder="Select roles"
formControlName="roles"
[ngClass]="{ 'is-invalid': submitted && forms.module.roles.errors }"
[multiple]="true">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled" *ngIf="searchTerm">
No role found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting"><i class="mdi mdi-file mr-1"></i> Submit</span>
</button>
<button type="button" class="btn btn-sm btn-danger" (click)="onCloseModal()">
<i class="mdi mdi-close mr-1"></i> Close
</button>
</div>
</form>
</ng-template>
\ No newline at end of file
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { AppData, ResourceService, HttpService, NotifyService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { Page, IUserAccount, IResource } from "@shared/models";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { NgbPopover, NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { DiscountModule } from "@shared/entities";
@Component({
templateUrl: "./discount-management.html",
encapsulation: ViewEncapsulation.None
})
export class DiscountManagementPage implements OnInit, OnDestroy {
page: Page;
loading: boolean;
modalRef: NgbModalRef;
loadingRoles: boolean;
roles: Array<IResource>;
discounts: Array<IResource>;
submitted: boolean;
submitting: boolean;
moduleForm: FormGroup;
modules: Array<DiscountModule>;
discountForm: FormGroup;
constructor(
private readonly appData: AppData,
private readonly resourceService: ResourceService,
private readonly formBuilder: FormBuilder,
private readonly modalService: NgbModal,
private readonly httpService: HttpService,
private readonly notifyService: NotifyService
) {
this.page = new Page();
this.modules = new Array<DiscountModule>();
}
private buildModuleForm() {
this.moduleForm = this.formBuilder.group({
discountModuleId: 0,
moduleName: [null, [Validators.required]],
icon: [""],
roles: [null, [Validators.required]],
createdBy: 0
});
}
private buildDiscountForm() {
this.discountForm = this.formBuilder.group({
discountsPerModuleId: 0,
discountModuleId: [null, [Validators.required]],
roleId: [null, [Validators.required]],
createdBy: [null],
allowedPercentage: [null, [Validators.required, Validators.max(100), Validators.min(1)]]
});
}
onModuleFormOpen(content: TemplateRef<any>, module?: DiscountModule) {
this.buildModuleForm();
if (module) {
let role = new Array<number>();
module.roles.split(",").forEach((item) => {
role.push(parseInt(item));
});
this.moduleForm.patchValue({
discountModuleId: module.discountModuleId,
active: true,
moduleName: module.moduleName,
icon: module.icon,
roles: role
});
const control = this.moduleForm.controls["moduleName"];
control.disable();
}
this.onOpenModel(content);
}
onModuleFormSubmit() {
this.submitted = true;
if (!this.moduleForm.valid) {
return;
}
this.submitting = true;
const request = this.moduleForm.getRawValue();
request["roles"] = this.moduleForm.value.roles.toString();
request["createdBy"] = this.page.userAccount.accountId;
request["CreatedByName"] = this.page.userAccount.fullName;
this.httpService.post<number>(ApiResources.getURI(ApiResources.discountManagement.base, ApiResources.discountManagement.modifyModule), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.submitted = this.submitting = false }))
.subscribe((response: number) => {
if (response > 0) {
this.notifyService.successToast(`Discount module ${request["discountModuleId"] > 0 ? 'updated' : 'created'} successfully.`);
}
if (response === -1) {
this.notifyService.warningToast("This module already exists.");
}
if (response === -2) {
this.notifyService.warningToast("Unable to update roles.");
}
this.fetchAllModules();
this.onCloseModal();
});
}
onDiscountModuleSubmit(popover: NgbPopover) {
this.submitted = true;
if (this.discountForm.invalid) {
return;
}
this.submitting = true;
const request = this.discountForm.getRawValue();
this.httpService.post<number>(ApiResources.getURI(ApiResources.discountManagement.base, ApiResources.discountManagement.modifyDiscountsPerModule), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.submitted = this.submitting = false }))
.subscribe((response: number) => {
if (response > 0) {
this.notifyService.successToast(`Discount for role ${request["discountsPerModuleId"] > 0 ? 'updated' : 'created'} successfully.`);
}
this.fetchAllModules();
popover.toggle();
});
}
onRoleSelected(module: DiscountModule, role: IResource) {
this.buildDiscountForm();
this.submitted = this.submitting = false;
let discountsPerModuleId = 0;
let allowedDiscount = null;
if (module.roleDiscounts.length > 0) {
const filteredRecord = module.roleDiscounts.filter(m => m.roleId === role.id);
if (filteredRecord.length > 0) {
discountsPerModuleId = filteredRecord[0].discountsPerModuleId;
allowedDiscount = filteredRecord[0].allowedPercentage;
}
}
this.discountForm.patchValue({
discountsPerModuleId: discountsPerModuleId,
discountModuleId: module.discountModuleId,
roleId: role.id,
createdBy: this.page.userAccount.accountId,
allowedPercentage: allowedDiscount
});
}
private fetchAllModules() {
this.loading = true;
const request = {};
this.httpService.post<Array<DiscountModule>>(ApiResources.getURI(ApiResources.discountManagement.base, ApiResources.discountManagement.fetchModules), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loading = false }))
.subscribe((response: Array<DiscountModule>) => {
this.modules = response;
this.modules.forEach((item) => {
item.allowedRoles = new Array<IResource>();
item.roles.split(",").forEach((i) => {
var id = parseInt(i);
var findRole = UtilHelper.clone(this.roles.find(m => m.id === id));
var findDiscounted = item.roleDiscounts.find(x => x.roleId === id);
if (findDiscounted) {
findRole.optionalText = findDiscounted.allowedPercentage.toString();
}
item.allowedRoles.push(findRole);
});
});
});
}
onModifyStatus(item: DiscountModule, status: boolean) {
this.notifyService.confirm(`You want to ${status ? 'Activate' : 'Deactivate'} this module?`, () => {
const request = {
modifiedBy: this.page.userAccount.accountId,
active: status,
moduleName: item.moduleName,
discountModuleId: item.discountModuleId,
modifiedByName: this.page.userAccount.fullName,
createdByRole: this.page.userAccount.roleName,
loginRoleId: this.page.userAccount.roleId,
};
this.httpService.post(ApiResources.getURI(ApiResources.discountManagement.base, ApiResources.discountManagement.modifyStatus), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loading = false }))
.subscribe((response: number) => {
if (response > 0) {
this.notifyService.successToast(`${status ? 'Activated' : 'Deactivated'} successfully.`);
}
this.fetchAllModules();
});
});
}
get forms() {
return {
module: this.moduleForm ? this.moduleForm.controls : {},
discount: this.discountForm ? this.discountForm.controls : {}
}
}
private fetchRoles() {
this.loadingRoles = true;
this.resourceService.roles()
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loadingRoles = false))
.subscribe((response: Array<IResource>) => {
this.roles = response;
var indexOfPatient = this.roles.findIndex((item) => { return item.value === "Patient" });
if (indexOfPatient >= 0) {
this.roles.splice(indexOfPatient, 1);
}
var indexOfProvider = this.roles.findIndex((item) => { return (item.value === "Provider" || item.value === "Doctor") });
if (indexOfProvider >= 0) {
this.roles.splice(indexOfProvider, 1);
}
this.fetchAllModules();
});
}
onOpenModel(content: TemplateRef<any>) {
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
}
//private fetchDiscounts() {
// this.resourceService.discountNames()
// .pipe(takeUntil(this.page.unSubscribe))
// .subscribe((response: Array<IResource>) => {
// this.discounts = response;
// });
//}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetchRoles();
//this.fetchDiscounts();
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button *ngIf="!loadingNotice && allDoctorAppointmentNotices.length > 0" [useExistingCss]="true" printSectionId="doctor_notice_print" ngxPrint class="btn btn-primary btn-sm mr-1 d-print-none"><i class="fe-printer mr-1"></i>Print</button>
<ng-container *menuButton="'sujBYZ'">
<button *ngIf="!loading && allDoctorAppointmentNotices && allDoctorAppointmentNotices.length" type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateDoctorAppointmentNotice)"><i class="fe-plus mr-1"></i> Add Doctor Appointment Notice</button>
<!--<button *ngIf="!loading && !filters.applied && generalAdvices && generalAdvices.length" type="button" class="btn btn-secondary btn-sm ml-1" (click)="onShowFilters()"><i class="fe-filter mr-1"></i> Filters</button>-->
</ng-container>
</div>
<h4 class="page-title">Doctor Appointment Notice</h4>
</div>
</div>
</div>
<div class="col-12 p-0">
<div class="card-box mb-1 p-1">
<table class="table table-borderless table-sm mb-0">
<tr style="font-size:12px;" class="myFlex">
<td class="col-6 col-sm-4 col-lg-2">
<div class="form-group mb-0">
<label class="mb-1">Location</label>
<ng-select tabindex="0" class="ng-select-sm text-uppercase" [items]="locations"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select location"
(change)="onChangeLocation($event)"
[(ngModel)]="filters.options.locationId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No locations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</td>
<td class="col-6 col-sm-4 col-lg-2">
<div class="form-group mb-0">
<label class="mb-1">Doctor Name</label>
<ng-select tabindex="0" [items]="providerSpecialization"
[loading]="loading"
[clearable]="true"
bindLabel="fullName"
bindValue="providerId"
[searchFn]="customSearch"
placeholder="Enter Doctor Name/Specialization"
[(ngModel)]="filters.options.providerId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled" *ngIf="searchTerm && searchTerm.length >= 1">
No Doctor found for '{{searchTerm}}'
</div>
<div class="ng-option disabled" *ngIf="(!searchTerm || searchTerm.length < 1)">
Search Doctor
</div>
</ng-template>
<ng-template ng-option-tmp let-item="item" let-i="index">
<div class="media">
<div class="avatar-xs mr-1">
<span class="avatar-title rounded-circle font-11 font-weight-bold bg-soft-warning text-primary"><i class="fe-map-pin"></i></span>
</div>
<div class="media-body">
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="item.fullName"></h5>
<span class="d-block font-13" [textContent]="item.specializationName || '-----'"></span>
</div>
</div>
</ng-template>
</ng-select>
</div>
</td>
<td class="col-6 col-sm-4 col-lg-2">
<div class="form-group mb-0">
<label class="mb-1">From Date</label>
<input type="date" [(ngModel)]="filters.options.fromDate" [max]="maxDate" id="fromDate" #fromDate [value]="filters.options.fromDate" class="form-control overflow-hidden"
(input)="changeMinDateTime(fromDate.value)">
</div>
</td>
<td class="col-6 col-sm-4 col-lg-2">
<div class="form-group mb-0">
<label class="mb-1">To Date</label>
<input type="date" [(ngModel)]="filters.options.toDate" [min]="minDate" id="toDate" #toDate [value]="filters.options.toDate" class="form-control overflow-hidden"
(input)="changeMaxDateTime(toDate.value)">
</div>
</td>
<td class="col-6 col-sm-4 col-lg-2">
<div class="form-group mb-0">
<label class="mb-1">Created By</label>
<ng-select class="ng-select-sm" [items]="accounts"
[loading]="loadingRoles"
[clearable]="true"
bindLabel="value"
bindValue="id"
placeholder="Select User"
[(ngModel)]="filters.options.createdBy">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
No User found<span *ngIf="searchTerm"> for '{{searchTerm}}'</span>.
</ng-template>
<ng-template ng-option-tmp let-item="item" let-i="index">
<h5 class="mb-1 mt-0 font-weight-normal" [textContent]="item.value"></h5>
<small><label class="badge badge-outline-primary" [textContent]="item.optionalText2"></label></small>
</ng-template>
<ng-template ng-label-tmp let-item="item">
<div class="media">
<div class="avatar-xs mr-1">
<span class="avatar-title rounded-circle font-11 font-weight-bold bg-soft-primary text-primary"><i class="fe-map-pin"></i></span>
</div>
<div class="media-body">
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="item.value"></h5>
<small><label class="badge badge-outline-primary" [textContent]="item.optionalText2"></label></small>
</div>
</div>
</ng-template>
</ng-select>
</div>
</td>
<td class="col-6 col-sm-4 col-lg-2">
<div class="form-group mb-0">
<label class="mb-1">Status</label>
<select class="form-control form-control-md" [(ngModel)]="filters.options.active">
<option [ngValue]="null">All</option>
<option [ngValue]="true">Active</option>
<option [ngValue]="false">Inactive</option>
</select>
</div>
</td>
<td class="col-12">
<div class="d-flex justify-content-center lessThan1468 flex-grow-1">
<button type="button" (click)="onApplyFilters()" class="btn btn-sm btn-outline-primary">Search</button>
<button type="button" (click)="onResetFilters()" class="btn btn-sm btn-outline-danger ml-1">Reset</button>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="row" *ngIf="loadingNotice">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading Doctor Appointment Notice ...</span>
</div>
</div>
</div>
<div class="row" *ngIf="!loadingNotice && (!allDoctorAppointmentNotices || !allDoctorAppointmentNotices.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<h4 class="title">Oops! No Doctor Appointment Notice found<span *ngIf="filters.applied"> based on your filters criteria</span>.</h4>
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateDoctorAppointmentNotice)"><i class="fe-plus mr-1"></i> Add Doctor Appointment Notice</button>
</div>
</div>
</div>
<div class="row" id="doctor_notice_print" *ngIf="!loadingNotice && allDoctorAppointmentNotices && allDoctorAppointmentNotices.length">
<div class="col-12">
<div class="card mb-0">
<div class="card-body p-0">
<div class="table-responsive">
<div class="noprint">
<!--<div *ngIf="isPrintLogo">
<banner-setting></banner-setting>
</div>-->
<h2 class="text-center">Doctor Appointment Notice</h2>
<p class="font-17 text-center" *ngIf="filters.options.fromDate && filters.options.toDate"><b>{{filters.options.fromDate | date:'dd-MM-yyyy'}} - {{filters.options.toDate | date:'dd-MM-yyyy'}} PM</b></p>
</div>
<table class="table table-centered table-sm table-striped table-borderless mb-0">
<thead>
<tr>
<th>Location Name</th>
<th>Doctor Name</th>
<th>Description</th>
<th>From Date</th>
<th>To Date</th>
<th>Created By</th>
<!--<th>Modified By</th>-->
<th>Modified By</th>
<th class="d-print-none">Active</th>
<th class="d-print-none text-right">Actions</th>
</tr>
</thead>
<tbody>
<!--trackBy: trackBy.doctorAppointmentNotice-->
<tr *ngFor="let item of allDoctorAppointmentNotices; ">
<td [textContent]="item.locationName"></td>
<td [textContent]="item.providerName"></td>
<td [textContent]="item.description"></td>
<td [textContent]="item.fromDate | date:'dd-MM-yyyy'"></td>
<td [textContent]="item.toDate | date:'dd-MM-yyyy'"></td>
<td>
<div class="media-body">
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="item.createdByName"></h5>
<small class="tx-13" [textContent]="item.createdDate | date:'dd-MM-yyyy, hh:mm a'"></small>
</div>
</td>
<td>
<div class="media-body">
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="item.modifiedByName"></h5>
<small class="tx-13" [textContent]="(item.modifiedDate | date:'dd-MM-yyyy, hh:mm a') || '---'"></small>
</div>
</td>
<td class="d-print-none">
<span class="badge badge-soft-success" *ngIf="item.active == true">Active</span>
<span class="badge badge-soft-danger" *ngIf="item.active == false">Inactive</span>
</td>
<td class="d-print-none">
<div class="d-flex align-items-center justify-content-end">
<a *ngIf="item.active" href="javascript:;" class="action-icon text-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenModel(templateDoctorAppointmentNotice, item)"><i class="fe-edit"></i></a>
<a href="javascript:;" class="action-icon text-danger" placement="left" ngbTooltip="Delete" (click)="onDelete(item)"><i class="fe-trash-2"></i></a>
<a href="javascript:;" class="btn btn-sm btn-outline-success" *ngIf="item.active == true" title="Active" (click)=" onModifyStatus(item, false)">
<i class="fe-check-square"></i>
</a>
<a href="javascript:;" class="btn btn-sm btn-outline-warning" *ngIf="item.active == false" title="Inactive" (click)="onModifyStatus(item, true)">
<i class="fe-x-square"></i>
</a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<nav class="d-flex align-items-center justify-content-between p-2" *ngIf="pagination.totalPages > 1">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - allDoctorAppointmentNotices.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> Doctor Appointment Notice )</span>
</span>
</p>
<!--<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>-->
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateDoctorAppointmentNotice>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-mother-nurse mr-1"></i>{{doctorAppointmentNoticeForm.value.doctorAppointmentNoticeId === 0 ? 'Add' : 'Edit'}} Doctor Appointment Notice</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<form [formGroup]="doctorAppointmentNoticeForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="row">
<div class="col-md-6">
<div class="form-group mb-3">
<label class="mb-1"> Location <code>*</code></label>
<div class="form-group">
<ng-select tabindex="0" class="ng-select-sm text-uppercase" [items]="locations"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select location"
[ngClass]="{ 'is-invalid': (submitted && form.locationId.errors) }"
(change)="onChangeLocation($event)"
formControlName="locationId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No locations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group mb-3">
<label class="mb-1"> Doctor <code>*</code></label>
<div class="form-group">
<ng-select #select (focus)="setFocus(select)" tabindex="0" [items]="providerSpecialization"
[loading]="loading"
[clearable]="true"
bindLabel="fullName"
bindValue="providerId"
[searchFn]="customSearch"
placeholder="Enter Doctor Name/Specialization"
(search)="fetchDoctorSpecializationHelper($event)"
[ngClass]="{ 'is-invalid': (submitted && form.providerId.errors) }"
formControlName="providerId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled" *ngIf="searchTerm && searchTerm.length >= 1">
No Doctor found for '{{searchTerm}}'
</div>
<div class="ng-option disabled" *ngIf="(!searchTerm || searchTerm.length < 1)">
Search Doctor
</div>
</ng-template>
<ng-template ng-option-tmp let-item="item" let-i="index">
<div class="media">
<div class="avatar-xs mr-1">
<span class="avatar-title rounded-circle font-11 font-weight-bold bg-soft-warning text-primary"><i class="fe-map-pin"></i></span>
</div>
<div class="media-body">
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="item.fullName"></h5>
<span class="d-block font-13" [textContent]="item.specializationName || '-----'"></span>
</div>
</div>
</ng-template>
</ng-select>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group mb-3">
<label class="mb-1"> From Date <code>*</code></label>
<div class="form-group">
<input type="date" class="form-control" formControlName="fromDate" id="dt" (change)="onChangeFromDate(this)" autocomplete="nope" min="{{todayDate | date: 'yyyy-MM-dd'}}" max="2999-12-31" [ngClass]="{ 'is-invalid': (submitted && form.fromDate.errors) }" />
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group mb-3">
<label class="mb-1"> To Date <code>*</code></label>
<div class="form-group">
<input type="date" class="form-control" formControlName="toDate" autocomplete="nope" min="{{greaterThanToday | date: 'yyyy-MM-dd'}}" max="2999-12-31" [ngClass]="{ 'is-invalid': (submitted && form.toDate.errors) }" />
</div>
</div>
</div>
<div class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1"> Description <code>*</code></label>
<div class="form-group">
<input tabindex="1" type="text" block maxlength="250" autofocus formControlName="description" autocomplete="nope" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.description.errors) }" placeholder="Enter Description" />
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService, ResourceService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { HttpErrorResponse } from "@angular/common/http";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, Validators, FormBuilder } from "@angular/forms";
import { Page, IUserAccount, Pagination, IResource } from "@shared/models";
import { DoctorAppointmentNotices } from "@shared/entities/doctor-appointment-notice.entity";
import { NgSelectComponent } from "@ng-select/ng-select";
import { ProviderSpecialization } from "../../../../../shared/entities/provider-specialization.entity";
//import moment = require("moment");
import { DatePipe } from "@angular/common";
import { Role } from "@shared/enums";
import moment from "moment";
class TrackBy {
doctorAppointmentNotice(item: DoctorAppointmentNotices) {
return item.doctorAppointmentNoticeId;
}
}
class DoctorAppointmentNoticeDetails {
doctorAppointmentNoticeId: number;
providerId: number;
machineName: string;
locationId: number;
locationName: string;
fromDate: Date;
toDate: Date;
active: boolean;
description: string;
providerName: string;
createdByName: string;
modifiedByName: string;
modifiedDate: string;
createdDate: string;
}
class FilterOptions {
description: string = null;
doctorAppointmentNoticeId: number;
createdBy: number = null;
locationId: number;
providerId: number;
fromDate: string = null;
toDate: string = null;
active?: boolean = true;
}
class Filters {
options: FilterOptions;
applied: boolean;
constructor() {
this.init();
}
init() {
this.options = new FilterOptions();
this.applied = undefined;
}
}
@Component({
templateUrl: "./doctor-appointment-notice.html",
encapsulation: ViewEncapsulation.None
})
export class DoctorAppointmentNotice implements OnInit, OnDestroy {
page: Page;
filters: Filters;
trackBy: TrackBy;
pagination: Pagination;
loading: boolean;
loadingNotice: boolean;
modalRef: NgbModalRef;
doctorAppointmentNoticeForm: FormGroup;
selectedDoctorAppointmentNotice: DoctorAppointmentNotices;
submitted: boolean;
submitting: boolean;
doctorAppointmentNotice: DoctorAppointmentNoticeDetails[];
allDoctorAppointmentNotices: DoctorAppointmentNoticeDetails[];
todayDate: Date;
greaterThanToday: Date;
providerSpecialization: ProviderSpecialization[];
locations: IResource[];
currentLocation: number;
minDate: string;
maxDate: string;
loadingRoles: boolean;
accounts: Array<IResource>;
constructor(
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly resourceService: ResourceService,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly httpService: HttpService,
private readonly datePipe: DatePipe,
) {
this.loading = true;
this.page = new Page();
this.filters = new Filters();
this.initPagination();
this.trackBy = new TrackBy();
this.todayDate = new Date();
this.buildForm();
this.allDoctorAppointmentNotices = new Array<DoctorAppointmentNoticeDetails>();
this.filters.options.fromDate = this.datePipe.transform(new Date(), 'yyyy-MM-dd');
this.filters.options.toDate = this.datePipe.transform(new Date(), 'yyyy-MM-dd');
}
changeMaxDateTime(value: string) {
this.maxDate = value;
this.filters.options.toDate = value;
}
changeMinDateTime(value: string) {
this.minDate = value;
this.filters.options.fromDate = value;
}
onApplyFilters() {
this.filters.applied = UtilHelper.isFiltersApplied(this.filters.options);
this.initPagination();
//this.loading = true;
this.fetchDoctorAppointmentNotice();
}
onResetFilters() {
this.filters.init();
this.initPagination();
this.filters.options.locationId = this.page.userAccount.locationId;
//this.loading = true;
this.filters.options.fromDate = this.datePipe.transform(new Date(), 'yyyy-MM-dd');
this.filters.options.toDate = this.datePipe.transform(new Date(), 'yyyy-MM-dd');
this.fetchDoctorAppointmentNotice();
this.filters.options.createdBy = null;
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
private buildForm() {
this.doctorAppointmentNoticeForm = this.formBuilder.group({
doctorAppointmentNoticeId: 0,
description: [null, [Validators.required]],
providerId: [null, [Validators.required]],
locationId: [this.currentLocation ? this.currentLocation : null, [Validators.required]],
fromDate: [null, [Validators.required]],
toDate: [null, [Validators.required]],
active: [true],
});
//this.doctorAppointmentNoticeForm.get("fromDate").valueChanges.subscribe((value: string) => {
// if (value) {
// this.greaterThanToday = new Date(value);
// if (this.doctorAppointmentNoticeForm.get("toDate").disabled) {
// this.doctorAppointmentNoticeForm.get("toDate").setValue(null);
// }
// }
//});
//this.doctorAppointmentNoticeForm.get("locationId").valueChanges.subscribe((value: number) => {
// if (value) {
// this.fetchDoctorSpecialization(null, value, null, null)
// this.doctorAppointmentNoticeForm.get("providerId").setValue(null);
// }
//});
}
get form() {
return this.doctorAppointmentNoticeForm.controls;
}
onChangeFromDate(event: any) {
if (event.doctorAppointmentNoticeForm.value.fromDate) {
this.greaterThanToday = new Date(event.doctorAppointmentNoticeForm.value.fromDate);
if (this.doctorAppointmentNoticeForm.get("toDate").disabled) {
this.doctorAppointmentNoticeForm.get("toDate").setValue(null);
}
}
}
onChangeLocation(event: IResource) {
if (event) {
this.fetchDoctorSpecialization(null, event.id, null, null)
this.filters.options.providerId = null
}
}
setFocus = (select: NgSelectComponent) => {
select.open();
}
fetchDoctorSpecializationHelper($event: any) {
if ($event && $event.term && $event.term.length > 1) {
const locationId = this.doctorAppointmentNoticeForm.get("locationId").value;
this.fetchDoctorSpecialization($event.term, locationId, null, null);
} else {
this.providerSpecialization = new Array<ProviderSpecialization>();
}
}
private fetchDoctorSpecialization(providerId?: string, locationId?: number, consultationTypeId?: number, appointmentDate?: any) {
var request = {
filter: providerId,
locationId: locationId,
consultationTypeId: consultationTypeId,
appointmentDate: appointmentDate
}
this.loading = true;
this.httpService
.post<Array<ProviderSpecialization>>(ApiResources.getURI(ApiResources.appointments.base, ApiResources.appointments.fetchDoctorSpecializationOp), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<ProviderSpecialization>) => {
if (response.length > 0) {
this.providerSpecialization = response;
}
},
() => {
this.providerSpecialization = new Array<ProviderSpecialization>();
}
);
}
customSearch(term: string, item) {
term = term.toLocaleLowerCase();
return item['fullName'].toLocaleLowerCase().indexOf(term) > -1 || item['specializationName'].toLocaleLowerCase().indexOf(term) > -1;
}
onOpenModel(content: TemplateRef<any>, doctorAppointmentNotice?: DoctorAppointmentNotices) {
this.buildForm();
//this.fetchLocations();
if (doctorAppointmentNotice) {
this.selectedDoctorAppointmentNotice = doctorAppointmentNotice;
this.updateForm();
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.loading = false;
this.submitting = undefined;
this.submitted = undefined;
}
private updateForm() {
this.doctorAppointmentNoticeForm.patchValue({
doctorAppointmentNoticeId: this.selectedDoctorAppointmentNotice.doctorAppointmentNoticeId,
description: this.selectedDoctorAppointmentNotice.description,
providerId: this.selectedDoctorAppointmentNotice.providerId,
locationId: this.selectedDoctorAppointmentNotice.locationId,
fromDate: moment(this.selectedDoctorAppointmentNotice.fromDate).format('YYYY-MM-DD'),
toDate: moment(this.selectedDoctorAppointmentNotice.toDate).format('YYYY-MM-DD')
});
this.fetchDoctorSpecialization(null, this.selectedDoctorAppointmentNotice.locationId, null, null);
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetchDoctorAppointmentNotice();
}
fetchDoctorAppointmentNotice() {
this.loadingNotice = true;
const request = Object.assign(UtilHelper.clone(this.filters.options), UtilHelper.clone(this.pagination));
if (new Date(request.fromDate).getTime() > new Date(request.toDate).getTime()) {
this.notifyService.warning("To Date must be greater than From Date!");
this.loadingNotice = false;
return;
}
this.httpService
.post<Array<DoctorAppointmentNoticeDetails>>(ApiResources.getURI(ApiResources.doctorAppointmentNotice.base, ApiResources.doctorAppointmentNotice.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loadingNotice = false))
.subscribe(
(response: Array<DoctorAppointmentNoticeDetails>) => {
this.doctorAppointmentNotice = response;
request.active == null ? this.allDoctorAppointmentNotices = response : this.allDoctorAppointmentNotices = response.filter(x => x.active == request.active);
UtilHelper.applyPagination(this.doctorAppointmentNotice, this.pagination);
},
() => {
this.doctorAppointmentNotice = [];
}
);
}
check(doctorAppointmentNoticeId: number) {
var isError = false;
var formValue = this.doctorAppointmentNoticeForm.getRawValue();
let a = (formValue.fromDate).split('-');
var fromDate = new Date(a[0], a[1] - 1, a[2]).getTime();
let b = (formValue.toDate).split('-');
var toDate = new Date(b[0], b[1] - 1, b[2]).getTime();
if (doctorAppointmentNoticeId == 0) {
var testRecords = this.doctorAppointmentNotice.filter(x => x.locationId === formValue.locationId && x.providerId === formValue.providerId);
}
else if (doctorAppointmentNoticeId > 0) {
var testRecords = this.doctorAppointmentNotice.filter(x => x.locationId === formValue.locationId && x.providerId === formValue.providerId && x.doctorAppointmentNoticeId != formValue.doctorAppointmentNoticeId);
}
for (var i = 0; i < testRecords.length; i++) {
var x = testRecords[i];
var givenFromDate = new Date(x.fromDate).getTime();
var givenToDate = new Date(x.toDate).getTime();
var c1 = givenFromDate >= fromDate && givenFromDate <= toDate;
var c2 = givenToDate >= fromDate && givenToDate <= toDate;
var c3 = fromDate >= givenFromDate && fromDate <= givenToDate;
var c4 = toDate >= givenFromDate && toDate <= givenToDate;
if ((c1 && c2) || (c2 && c3) || (c3 && c4) || (c1 && c4)) {
if ((!c1 && c3 && c4) || (!c2 && c3 && c4) || (c1 && c2 && c3 && c4)) {
this.notifyService.warning('Given Dates already exists with us.');
}
else {
this.notifyService.warning(`Given Dates are duplicating the existing dates.`);
}
isError = true;
break;
}
}
return isError;
}
onSubmit() {
this.submitted = true;
if (!this.doctorAppointmentNoticeForm.valid) {
return;
}
const request = Object.assign(UtilHelper.clone(this.doctorAppointmentNoticeForm.getRawValue()));
if (new Date(request.fromDate).getTime() > new Date(request.toDate).getTime()) {
this.notifyService.warning("To Date must be greater than From Date!");
return;
}
if (this.check(request.doctorAppointmentNoticeId)) {
return;
}
this.submitting = true;
request["modifiedByName"] = this.page.userAccount.fullName;
if (Number(this.doctorAppointmentNoticeForm.value.doctorAppointmentNoticeId) === 0) {
request.createdBy = this.page.userAccount.accountId;
this.httpService.post(ApiResources.getURI(ApiResources.doctorAppointmentNotice.base, ApiResources.doctorAppointmentNotice.add), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchDoctorAppointmentNotice();
this.notifyService.success("Doctor Appointment Notice has been added successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
} else {
request.modifiedBy = this.page.userAccount.accountId;
request["modifiedByName"] = this.page.userAccount.fullName;
request["createdBy"] = this.page.userAccount.accountId;
delete request.type;
this.httpService.put(ApiResources.getURI(ApiResources.doctorAppointmentNotice.base, ApiResources.doctorAppointmentNotice.edit), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchDoctorAppointmentNotice();
this.notifyService.success("Doctor Appointment Notice has been updated successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
}
}
private fetchLocations() {
this.resourceService.locations()
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.locations = response;
if (!this.selectedDoctorAppointmentNotice) {
this.doctorAppointmentNoticeForm.patchValue({
locationId: this.currentLocation
});
}
this.filters.options.locationId = this.currentLocation;
this.fetchDoctorSpecialization(null, this.doctorAppointmentNoticeForm.get("locationId").value, null, null);
this.fetchDoctorAppointmentNotice();
});
}
onModifyStatus(item: DoctorAppointmentNotices, status: boolean) {
this.notifyService.confirm(`You want to ${status ? 'Activate' : 'Deactivate'} this Doctor Appointment Notice?`, () => {
const request = {
createdBy: this.page.userAccount.accountId,
active: status,
doctorAppointmentNoticeId: item.doctorAppointmentNoticeId,
description: item.description,
providerId: item.providerId,
locationId: item.locationId,
fromDate: item.fromDate,
toDate: item.toDate,
createdByName: this.page.userAccount.fullName,
createdByRole: this.page.userAccount.roleName,
loginRoleId: this.page.userAccount.roleId,
};
this.loading = true;
this.httpService.post(ApiResources.getURI(ApiResources.doctorAppointmentNotice.base, ApiResources.doctorAppointmentNotice.modifyStatus), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loading = false }))
.subscribe((response: string) => {
if (response) {
status ? this.notifyService.successToast(`${status ? 'Activated' : 'Deactivated'} successfully.`) : this.notifyService.warningToast(`${status ? 'Activated' : 'Deactivated'} successfully.`)
}
this.fetchDoctorAppointmentNotice();
}, (error: HttpErrorResponse) => {
this.notifyService.errorToast(error.error);
});
});
}
onDelete(item: DoctorAppointmentNotices) {
this.notifyService.delete(() => {
this.httpService
.post(ApiResources.getURI(ApiResources.doctorAppointmentNotice.base, ApiResources.doctorAppointmentNotice.delete), {
doctorAppointmentNoticeId: item.doctorAppointmentNoticeId, modifiedByName: this.page.userAccount.fullName,
createdBy: this.page.userAccount.accountId,
modifiedBy: this.page.userAccount.accountId
})
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { }))
.subscribe(
() => {
this.notifyService.success("Doctor Appointment Notice deleted successfully.");
this.fetchDoctorAppointmentNotice();
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
}
);
}, () => { });
}
private fetchAccounts() {
this.loadingRoles = true;
const roleId = Role.Patient.toString();
this.resourceService.getAllAccountsExpectPassedRoleId(roleId)
.pipe(finalize(() => { this.loadingRoles = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.accounts = response;
});
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.currentLocation = userAccount.locationId;
//this.fetchDoctorAppointmentNotice();
this.fetchLocations();
this.fetchAccounts();
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(doctorUnitTemplate)"><i class="fe-plus mr-1"></i> Add </button>
</div>
<h4 class="page-title">Doctor Unit</h4>
</div>
</div>
</div>
<div class="col-12 p-0">
<div class="card-box mb-1 p-1">
<table class="table table-borderless table-sm mb-0">
<tr style="font-size:12px;" class="myFlex">
<td class="col-6 col-sm-3">
<div class="form-group mb-0">
<label class="mb-1">Locations </label>
<ng-select class="ng-select-sm text-uppercase" [items]="locations"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select locations"
(change)="onChangeLocation($event)"
[(ngModel)]="filters.options.locationId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No locations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</td>
<td class="col-6 col-sm-3">
<div class="form-group mb-0">
<label class="mb-1">Unit Name</label>
<ng-select class="ng-select-sm text-uppercase" [items]="filterUnitName"
[loading]="loadingUnitNames"
bindLabel="value"
bindValue="id"
appendTo="body"
autocomplete="nope"
placeholder="Select unit Name"
[(ngModel)]="filters.options.doctorUnitMasterId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No unit name found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</td>
<td class="col-6 col-sm-3">
<div class="form-group mb-0">
<label class="mb-1">Code</label>
<input type="text" class="form-control form-control-sm" [(ngModel)]="filters.options.code" block autocomplete="nope" maxlength="100" placeholder="Enter code" />
</div>
</td>
<td class="col-6 col-sm-3 align-middle">
<div style="margin-top: 25px;" class="d-flex justify-content-center justify-content-lg-start">
<button type="button" (click)="onApplyFilters()" class="btn btn-sm btn-outline-primary m-0">Search</button>
<button type="button" (click)="onResetFilters()" class="btn btn-sm btn-outline-danger ml-1 mb-0">Reset</button>
</div>
</td>
</table>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card-box p-0">
<div class="row p-2" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading ...</span>
</div>
</div>
</div>
<div class="row p-2" *ngIf="!loading && (!records || !records.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(doctorUnitTemplate)"><i class="fe-plus mr-1"></i> Add </button>
</div>
</div>
</div>
<div class="table-responsive" *ngIf="!loading && records.length > 0">
<table class="table table-sm">
<thead class="table-info">
<tr>
<th> Unit Name</th>
<th>Code</th>
<th>Location</th>
<th>Doctors</th>
<th>CreatedBy</th>
<th>Created Date</th>
<th>Modified By</th>
<th>Modified Date</th>
<th>Status</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of records;index as i;">
<td>
<span [textContent]="item.unitName"></span>
</td>
<td>
<span [textContent]="item.code"></span>
</td>
<td>
<span [textContent]="item.location"></span>
</td>
<td>
<div *ngFor="let doctor of item.tagDoctor">
<span [textContent]="doctor.providerName"></span>
</div>
</td>
<td>
<h5 class="font-13 mb-0" [textContent]="item.createdByName"></h5>
</td>
<td>
<span [textContent]="item.createdDate | date:'dd-MM-yyyy, hh:mm a'"></span>
</td>
<td>
<div *ngIf="item.modifiedByName">
<h5 class="font-13 mb-0" [textContent]="item.modifiedByName"></h5>
</div>
<span *ngIf="!item.modifiedByName">-----</span>
</td>
<td>
<span *ngIf="item.modifiedDate" [textContent]="item.modifiedDate | date:'dd-MM-yyyy, hh:mm a'"></span>
<span *ngIf="!item.modifiedDate">----</span>
</td>
<td>
<span class="badge badge-soft-success" *ngIf="item.active == true">Active</span>
<span class="badge badge-soft-danger" *ngIf="item.active == false">Inactive</span>
</td>
<td>
<nav class="nav">
<a href="javascript:;" class="action-icon text-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenModel(doctorUnitTemplate, item)"><i class="fe-edit"></i></a>
<button type="button" class="btn btn-sm btn-outline-success" *ngIf="item.active == false" title="Active" (click)="onModifyStatus(item, true)">
<i class="fe-check-square"></i>
</button>
<button type="button" class="btn btn-sm btn-outline-warning" *ngIf="item.active == true" title="Inactive" (click)="onModifyStatus(item, false)">
<i class="fe-x-square"></i>
</button>
</nav>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #doctorUnitTemplate>
<form [formGroup]="doctorunitForm" (ngSubmit)="onSubmit()">
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-human-edit mr-1"></i>{{doctorunitForm.value.doctorUnitMasterId === 0 ? 'Add' : 'Edit'}} Doctor Unit</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-12">
<div class="form-group">
<label class="mb-1">UnitName <code>*</code></label>
<input type="text" class="form-control" autofocus placeholder="Enter Unit Name." formControlName="unitName" [ngClass]="{ 'is-invalid': submitted && form.unitName.errors }" />
</div>
</div>
<div class="col-12">
<div class="form-group">
<label class="mb-1">Code <code>*</code></label>
<input type="text" class="form-control" placeholder="Enter Unit Code." formControlName="code" [ngClass]="{ 'is-invalid': submitted && form.code.errors }"/>
</div>
</div>
<div class="col-12">
<div class="form-group">
<label class="mb-1">Location <code>*</code></label>
<ng-select tabindex="0" class="ng-select-sm text-uppercase" [items]="locations"
[loading]="loadlocation"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select location"
[ngClass]="{ 'is-invalid': submitted && form.locationId.errors }"
formControlName="locationId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No locations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</div>
</div>
<div class="text-right mb-1"><a href="javascript:;" class="font-14" anchorFocusonly (click)="onAddTagDoctor()"><i class="fe-plus mr-1"></i>Add</a></div>
<div class="row w-100">
<div class="w-100">
<div class="col-12 d-flex w-100">
<table class="w-100">
<tbody *ngFor="let tagDoctor of tagForm.controls; let i = index" [formGroup]="tagDoctor">
<tr>
<th>
<label>Tag Doctor<code>*</code> </label>
</th>
<th>
<label>Designation<code>*</code></label>
</th>
<th></th>
</tr>
<tr>
<td>
<ng-select class="ng-select-sm text-uppercase w-100" [items]="providers"
[loading]="loadProvider"
bindLabel="value"
bindValue="id"
autocomplete="nope"
formControlName="providerId"
(change)="onChangeProvider1(tagDoctor)"
[ngClass]="{ 'is-invalid': submitted && tagDoctor.controls['providerId'].errors }"
[hideSelected]="true"
placeholder="Select Doctor">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No Doctor found <span *ngIf="searchTerm">for '{{searchTerm}}'</span>
</div>
</ng-template>
</ng-select>
</td>
<td>
<select class="form-control custom-select w-100" autocomplete="nope" formControlName="designation" [ngClass]="{ 'is-invalid': submitted && tagDoctor.controls['designation'].errors }">
<option value="null">select</option>
<option value="Consultation">Consultation</option>
<option value="Senior">Senior</option>
<option value="Junior">Junior</option>
<option value="Duty">Duty</option>
<option value="Assistant">Assistant</option>
</select>
</td>
<td class="text-right">
<div>
<a *ngIf="tagDoctorArray.value.length > 1 && i != 0" href="javaScript:;" class="text-danger" (click)="onRemoveTagDoctor(i)" title="Remove"><i class="fe-x"></i></a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
\ No newline at end of file
import { Component, OnInit, OnDestroy, TemplateRef } from "@angular/core";
import { takeUntil, finalize } from "rxjs/operators";
import { Page, IUserAccount, IResource } from "@shared/models";
import { AppData, ResourceService, HttpService, NotifyService } from "@shared/services";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, FormBuilder, FormArray, Validators } from "@angular/forms";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { HttpErrorResponse } from "@angular/common/http";
import { DoctorUnits, TagDoctors } from "@shared/entities";
import { Observable } from "rxjs";
class FilterOptions {
code: string = null;
doctorUnitMasterId: number;
locationId: number = null;
}
class Filters {
options: FilterOptions;
applied: boolean;
constructor() {
this.init();
}
init() {
this.options = new FilterOptions();
this.applied = undefined;
}
}
@Component({
templateUrl: "./doctor-unit.html",
})
export class DoctorUnitPage implements OnInit, OnDestroy {
page: Page;
submitting: boolean;
modalRef: NgbModalRef;
loading: boolean;
submitted: boolean;
doctorunitForm: FormGroup;
locations: Array<IResource>;
currenrLocation: number;
departments: Array<IResource>;
loadDepartments: boolean;
loadProvider: boolean;
providers: Array<IResource>;
loadlocation: boolean;
addSlotTimingsArrayForm: FormGroup;
records: Array<DoctorUnits>
filters: Filters;
loadingUnitNames: boolean;
filterUnitName: Array<IResource>
selectedDoctor: Array<IResource>;
doctors: Observable<Array<IResource>>;
constructor(
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly resourceService: ResourceService,
private readonly httpService: HttpService,
private readonly notifyService: NotifyService,
) {
this.page = new Page();
this.buildForm();
this.filters = new Filters();
this.records = new Array<DoctorUnits>();
}
private buildForm() {
this.doctorunitForm = this.formBuilder.group({
doctorUnitMasterId: 0,
unitName: [null, [Validators.required]],
code: [null, [Validators.required]],
locationId: [null, [Validators.required]],
departmentId: 0,
tagDoctor: this.formBuilder.array([]),
})
this.doctorunitForm.get("locationId").valueChanges.subscribe((value: number)=> {
this.fetchProviders(value)
})
//this.doctorunitForm.get("providerId").valueChanges.subscribe((value?: number) => {
// this.selectedDoctor = new Array<IResource>();
// if (value) {
// this.selectedDoctor = UtilHelper.cloneList(this.providers);
// var getIndexOfSelectedPatient = this.selectedDoctor.findIndex(x => x.id === value);
// if (getIndexOfSelectedPatient >= 0) {
// this.selectedDoctor.splice(getIndexOfSelectedPatient, 1);
// }
// } else {
// this.selectedDoctor = new Array<IResource>();
// }
//});
}
private buildTagDoctorForm(tagDoctor?: TagDoctors) {
if (this.tagDoctorArray.length <= 0) {
return this.formBuilder.group({
providerId: [tagDoctor ? tagDoctor.providerId : null, [Validators.required]],
designation: [tagDoctor ? tagDoctor.designation : "Senior", [Validators.required]],
tagDoctorId: [tagDoctor ? tagDoctor.tagDoctorId : null],
//doctorUnitMasterId: [tagDoctor ? tagDoctor.doctorUnitMasterId:0]
});
}
else {
return this.formBuilder.group({
providerId: [tagDoctor ? tagDoctor.providerId : null, [Validators.required]],
designation: [tagDoctor ? tagDoctor.designation : null, [Validators.required]],
tagDoctorId: [tagDoctor ? tagDoctor.tagDoctorId : null],
//doctorUnitMasterId: [tagDoctor ? tagDoctor.doctorUnitMasterId:0]
});
}
}
onAddTagDoctor() {
this.tagDoctorArray.push(this.buildTagDoctorForm());
}
get tagDoctorArray() { return this.doctorunitForm.controls["tagDoctor"] as FormArray }
get tagForm() {
return this.tagDoctorArray;
}
get form() {
return this.doctorunitForm.controls;
}
onRemoveTagDoctor(index: number) {
this.tagDoctorArray.removeAt(index);
}
onChangeProvider(data: any) {
//if (data) {
// let index = this.providers.findIndex(s => s.id == data.id);
// this.providers.splice(index, 1);
//}
if (data) {
this.doctorunitForm.patchValue({
providerId: null
});
let docArray = this.doctorunitForm.value.tagDoctor as Array<any>;
let ifExists = docArray.filter(l => l.providerId === data.id);
if (ifExists.length > 1) {
this.notifyService.warningToast("This Doctor is already added.,Please change the Doctor");
// this.doctorunitForm.get("tagDoctor").patchValue({ providerId: null })
return;
}
// let form = this.buildLabArrayForm(lab);
}
}
onChangeProvider1(control: FormGroup) {
const providerIdValue = control.controls["providerId"].value;
const providerId = control.controls["providerId"];
let docArray = this.doctorunitForm.value.tagDoctor as Array<any>;
let ifExists = docArray.filter(l => l.providerId === providerIdValue);
if (ifExists.length > 1) {
this.notifyService.warningToast("This Doctor is already added.,Please change the Doctor");
providerId.setValue(null);
providerId.updateValueAndValidity();
control.updateValueAndValidity();
return;
}
}
//onAddLabToForm(lab: LabMainDetail) {
// if (lab) {
// this.billForm.patchValue({
// term: null
// });
// let labArray = this.billForm.value.labs as Array<any>;
// let ifExists = labArray.filter(l => l.labMainDetailId === lab.labMainDetailId);
// if (ifExists.length > 0) {
// this.notifyService.warningToast("This lab already added.");
// return;
// }
// let form = this.buildLabArrayForm(lab);
// form.patchValue({
// charges: lab.charges
// });
// this.forms.labsFormArray.push(form);
// }
//}
onApplyFilters() {
this.filters.applied = UtilHelper.isFiltersApplied(this.filters.options);
this.loading = true;
this.fetchAll();
}
onResetFilters() {
this.loading = true;
this.filters.init();
this.fetchAll();
this.fetchFilterUnitNames(null);
}
private fetchLocations() {
this.loadlocation = true;
this.resourceService.locations()
.pipe(finalize(() => { this.loadlocation = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.locations = response;
//this.doctorunitForm.patchValue({
// locationId: this.currenrLocation
//})
});
}
//private fetchDepartments() {
// this.loadDepartments = true;
// this.resourceService.department()
// .pipe(finalize(() => { this.loadDepartments = false }))
// .pipe(takeUntil(this.page.unSubscribe))
// .subscribe((response: Array<IResource>) => {
// this.departments = response;
// });
//}
private fetchProviders(id?: number) {
this.loadProvider = true;
this.resourceService.providerAccountLocationMap(id)
.pipe(finalize(() => { this.loadProvider = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.providers = response;
});
}
onChangeLocation(data: any) {
if (data) {
this.fetchFilterUnitNames(data.id);
}
else {
this.fetchFilterUnitNames(null);
}
}
onOpenModel(content: TemplateRef<any>, record?: DoctorUnits) {
this.buildForm();
//this.fetchProviders(null);
if (record) {
this.doctorunitForm.patchValue({
doctorUnitMasterId: record.doctorUnitMasterId,
unitName: record.unitName,
code: record.code,
locationId: record.locationId,
departmentId: record.departmentId
})
record.tagDoctor.forEach((item) => {
var each = this.buildTagDoctorForm(item);
this.tagDoctorArray.push(each);
//this.providers.splice(item.tagDoctorId, 1);
})
}
else {
this.onAddTagDoctor();
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: false,
windowClass: "custom-modal effect-scale"
});
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
}
catch(e) {
}
this.loading = false;
this.submitting = undefined;
this.submitted = undefined;
}
onSubmit() {
this.submitted = true;
if (this.doctorunitForm.invalid) {
return;
}
this.submitting = true;
const request = {
...this.doctorunitForm.getRawValue(),
createdBy: this.page.userAccount.accountId,
createdByName: this.page.userAccount.fullName,
loginRoleId: this.page.userAccount.roleId,
active: true,
};
var url = ApiResources.getURI(ApiResources.doctorUnit.base, ApiResources.doctorUnit.insert);
if (request["doctorUnitMasterId"] > 0) {
url = ApiResources.getURI(ApiResources.doctorUnit.base, ApiResources.doctorUnit.update);
}
this.httpService.post(url, request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitted = this.submitting = false))
.subscribe(
(response: string) => {
this.notifyService.successToast(response);
this.onCloseModal();
this.fetchAll();
},
(error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warningToast(errorMessage);
} else {
this.notifyService.defaultError();
}
}
);
}
onModifyStatus(test: DoctorUnits, status: boolean) {
this.notifyService.confirm(`You want to ${status ? 'Activate' : 'Deactivate'} this unit name?`, () => {
const request = {
modifiedBy: this.page.userAccount.accountId,
active: status,
doctorUnitMasterId: test.doctorUnitMasterId,
modifiedByName: this.page.userAccount.fullName,
createdByRole: this.page.userAccount.roleName,
loginRoleId: this.page.userAccount.roleId,
unitName: test.unitName
};
this.httpService.post(ApiResources.getURI(ApiResources.doctorUnit.base, ApiResources.doctorUnit.modifyStatus), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loading = false }))
.subscribe((response: number) => {
if (response > 0) {
this.notifyService.successToast(`${status ? 'Activated' : 'Deactivated'} successfully.`);
}
this.fetchAll();
}, (error: HttpErrorResponse) => {
this.notifyService.errorToast(error.error);
});
});
}
fetchFilterUnitNames(locationId: number) {
this.loadingUnitNames = true;
this.resourceService.doctorUnit(locationId)
.pipe(finalize(() => { this.loadingUnitNames = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.filterUnitName = response;
});
}
private fetchAll() {
this.loading = true;
const request = {
...this.filters.options
};
this.httpService.post(ApiResources.getURI(ApiResources.doctorUnit.base, ApiResources.doctorUnit.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe((response: Array<DoctorUnits>) => {
this.records = response;
(error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warningToast(errorMessage);
} else {
this.notifyService.defaultError();
}
}
});
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.currenrLocation = userAccount.locationId;
this.fetchLocations();
this.fetchAll();
this.fetchFilterUnitNames(null);
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button type="button" class="btn btn-sm btn-primary" (click)="onOpenModel(templateModify);">
<i class="mdi mdi-plus-thick mr-1"></i> Add
</button>
</div>
<h4 class="page-title">Dynamic Template</h4>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card-box p-0">
<div class="row p-2" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading Dynamic templates ...</span>
</div>
</div>
</div>
<div class="row p-2" *ngIf="!loading && (!template || !template.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<h4 class="title">Oops! No Templates found.</h4>
<p class="sub-title">There is no data to show you right now.</p>
</div>
</div>
</div>
<div class="table-responsive" *ngIf="!loading && template.length > 0">
<table class="table table-centered table-sm table-striped table-borderless">
<tr class="table-info">
<th>Template Name</th>
<th>Created By</th>
<th>Created Date</th>
<th>Modified By</th>
<th>Modified Date</th>
<th>Action</th>
</tr>
<tbody>
<ng-template ngFor let-item [ngForOf]="template" let-i="index">
<tr>
<td>
<p class="text-truncate-line mb-0" [textContent]="item.templateName || '----'"></p>
</td>
<td>
<p class="mb-0" [textContent]="item.createdByName"></p>
<!--<small><span class="badge badge-outline-success" [textContent]="item.createdByRole"></span></small>-->
</td>
<td><span [textContent]="item.createdDate | date:'dd-MM-yyyy, hh:mm a'"></span></td>
<td>
<p class="mb-0" [textContent]="item.modifiedByName || '--'"></p>
<!--<small><span class="badge badge-outline-blue" [textContent]="item.modifiedByRole"></span></small>-->
</td>
<td><span [textContent]="(item.modifiedDate | date:'dd-MM-yyyy, hh:mm a') || '--'"></span></td>
<td>
<div class="d-flex align-items-center justify-content-center">
<a href="javascript:;" (click)="onOpenModel(templateModify, item)" title="Edit"><i class="fe-edit"></i></a>
<a href="javascript:;" title="Delete" (click)="onDeleteTemplate(item)"><i class="fe-trash-2 ml-2"></i></a>
</div>
</td>
</tr>
</ng-template>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateModify>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-onenote mr-1"></i>Template Creation</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onClose();">×</button>
</div>
<div class="ml-1">
<div *ngFor="let item of rawData; let i=index">
<label class="mb-1" [textContent]="item" (click)="bindData(item)"></label>
</div>
<div *ngIf="page.loading">
<div class="card-box notes-editor card-box-sm">
<ckeditor [editor]="notesEditor" [(ngModel)]="htmlData"></ckeditor>
</div>
<div class="row">
<div class="col-6">
<div class="form-group">
<label class="mb-1">Template Name<code>*</code></label>
<input type="text" class="form-control" placeholder="Please enter Template name." [(ngModel)]="templateName" />
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-primary" (click)="onSubmit()">
<span *ngIf="!submitting">Submit</span>
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Submitting
</span>
</button>
<button type="button" class="ml-1 btn btn-sm btn-danger" (click)="onClose()">Cancel</button>
</div>
</ng-template>
<!--<div class="row mb-3">
<form>
<div class="form-group has-feedback">
<ckeditor [(ngModel)]="mycontent"
#myckeditor
id="myckeditor"
name="myckeditor"
required
[config]="ckeConfig"
debounce="500">
</ckeditor>
<div class="help-block">Required field.</div>
</div>
</form>
</div>
<div class="row mb-3">
<button class="btn btn-secondary mr-2 ml-2" (click)="addValue('chandana')">CustomerNo</button>
</div>-->
import { Component, ViewEncapsulation, OnInit, OnDestroy, TemplateRef } from "@angular/core";
import { Page, IUserAccount } from "@shared/models";
import { AppData, HttpService, NotifyService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import * as ClassicEditor from "@ckeditor/ckeditor5-build-classic";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { DynamicTemplate } from "@shared/entities";
import { NgbModalRef, NgbModal } from "@ng-bootstrap/ng-bootstrap";
import { HttpErrorResponse } from "@angular/common/http";
@Component({
templateUrl: "./dynamic-template.html",
encapsulation: ViewEncapsulation.None
})
export class DynamicTemplatePage implements OnInit, OnDestroy {
page: Page;
submitting: boolean;
submitted: boolean;
notesEditor = ClassicEditor;
rawData = ["CC", "HPI", "Vitals", "History", "ROS", "Physical", "Diagnosis", "Patient", "Provider", "Location"]
textVariable: [];
htmlData: string;
template: Array<DynamicTemplate>;
loading: boolean;
modalRef: NgbModalRef;
templateName: string;
dynamicTemplateId: number;
constructor(
private readonly appData: AppData,
private readonly httpService: HttpService,
private readonly notifyService: NotifyService,
private readonly modalService: NgbModal
) {
this.page = new Page();
this.template = new Array<DynamicTemplate>();
}
bindData(value: any) {
this.htmlData = (this.htmlData || '') + '<span id="dynamic-word">' + value + '</span>' + ' ';
}
private onError(error: HttpErrorResponse) {
if (error) {
this.notifyService.errorToast(UtilHelper.handleError(error));
}
}
fetchTemplate() {
this.loading = true;
const request = {};
this.httpService
.post(ApiResources.getURI(ApiResources.dynamicTemplate.base, ApiResources.dynamicTemplate.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe((response: Array<DynamicTemplate>) => {
this.template = response;
}, () => {
this.notifyService.error("Error occured in fetching Template.");
}
);
}
onSubmit() {
this.submitted = true;
if (this.templateName === "" || this.templateName === undefined || this.templateName === null || this.templateName.trim() === "") {
this.notifyService.warning("Template name is required.");
return;
}
if (this.htmlData === "" || this.htmlData === undefined || this.htmlData === null || this.htmlData.trim() === "") {
this.notifyService.warning("Template data is required.");
return;
}
const request = Object.assign(UtilHelper.clone({ templateName: this.templateName, dynamicTemplateId: this.dynamicTemplateId, value: this.htmlData, createdBy: this.page.userAccount.accountId, createdByName: this.page.userAccount.fullName, loginRoleId: this.page.userAccount.roleId }));
this.submitting = true
var url = ApiResources.getURI(ApiResources.dynamicTemplate.base, ApiResources.dynamicTemplate.add);
if (request["dynamicTemplateId"] > 0) {
url = ApiResources.getURI(ApiResources.dynamicTemplate.base, ApiResources.dynamicTemplate.update);
}
this.httpService.post(url, request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitted = this.submitting = false))
.subscribe(
(response: number) => {
if (response > 0) {
this.notifyService.successToast(`Record ${request["DynamicTemplateId"] > 0 ? 'updated' : 'added'} successfully.`);
}
if (response === -1) {
this.notifyService.warningToast("This Template Name already exists.");
return;
}
this.onClose();
this.fetchTemplate();
},
(error: HttpErrorResponse) => {
this.onError(error);
}
);
}
onDeleteTemplate(item: DynamicTemplate) {
this.notifyService.delete(() => {
const request = {
dynamicTemplateId: item.dynamicTemplateId,
createdBy: this.page.userAccount.accountId,
loginRoleId: this.page.userAccount.roleId,
templateName: item.templateName,
createdByName: this.page.userAccount.fullName,
};
this.httpService.post(ApiResources.getURI(ApiResources.dynamicTemplate.base, ApiResources.dynamicTemplate.delete), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.loading = false;
}))
.subscribe((response: number) => {
if (response > 0) {
this.notifyService.successToast("Deleted successfully.");
}
this.fetchTemplate();
}, () => {
this.notifyService.warning("This Template can't be deleted.");
});
});
}
onClose() {
try {
this.modalRef.close();
this.modalRef = undefined;
this.templateName = null;
this.htmlData = null;
this.dynamicTemplateId = 0;
} catch (e) {
// ignored;
}
this.submitted = this.submitting = false;
}
onOpenModel(content: TemplateRef<any>, item?: DynamicTemplate) {
this.templateName = null;
if (item) {
this.templateName = item.templateName;
this.htmlData = item.value;
this.dynamicTemplateId = item.dynamicTemplateId
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: false,
size: "lg",
windowClass: "custom-modal effect-scale"
});
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((account: IUserAccount) => {
if (account) {
this.page.userAccount = account;
this.fetchTemplate();
}
else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.page.unsubscribeAll();
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button *ngIf="!loading && record && record.length" type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateForm)"><i class="fe-plus mr-1"></i> Add</button>
</div>
<h4 class="page-title">Order Prescription</h4>
</div>
</div>
</div>
<div>
<div class="card-box mb-1 p-1 pb-2">
<div class="col-lg-12">
<div class="row">
<div class="col-6 col-md-4 col-lg-4 col-xl-2">
<div class="form-group mb-0">
<label class="mb-1">Encounter Type</label>
<ng-select class="ng-select-sm text-uppercase" [items]="encounterType"
bindLabel="name"
bindValue="id"
typeToSearchText="Search encounterType"
autocomplete="nope"
placeholder="Select Encounter Type"
[(ngModel)]="filters.options.encounterTypeId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No encounter type found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
<!-- <input type="text" class="form-control" placeholder="enter the Encounter Type" [(ngModel)]="filters.options.encounterName" />-->
</div>
</div>
<div class="col-6 col-md-4 col-lg-4 col-xl-2">
<div class="form-group mb-0">
<label class="mb-1">Doctor</label>
<ng-select class="ng-select-sm" [items]="providerResources"
[loading]="loading"
bindLabel="value"
bindValue="id"
[minTermLength]="2"
typeToSearchText="Search doctor"
[virtualScroll]="true"
placeholder="Enter 2 or more characters"
[(ngModel)]="filters.options.providerId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled" *ngIf="searchTerm && searchTerm.length >= 2">
No Doctor found for '{{searchTerm}}'
</div>
<div class="ng-option disabled" *ngIf="(!searchTerm || searchTerm.length < 2)">
Search Doctor
</div>
</ng-template>
</ng-select>
<!-- <input type="text" placeholder="enter the DocterName" class="form-control" [(ngModel)]="filters.options.providerName" />-->
</div>
</div>
<div class="col-6 col-md-4 col-lg-4 col-xl-2">
<div class="form-group mb-0">
<label class="mb-1">Name</label>
<input type="text" class="form-control" autocomplete="nope" placeholder="Enter the name" [(ngModel)]="filters.options.name" />
</div>
</div>
<div class="col-12 col-lg-4 col-md-4 col-xl-2 d-flex justify-content-center ">
<div class="align-items-center d-flex justify-content-center justify-content-lg-start mb-0 w-100 marTop767size">
<button type="button" (click)="onApplyFilters()" class="btn btn-sm btn-outline-primary mb-0">Search</button>
<button type="button" (click)="onResetFilters()" class="btn btn-sm btn-outline-danger ml-1 mb-0">Reset</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="row">
<div class="col-12" *ngIf="!loading && record && record.length">
<div class="card mb-0">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-centered table-sm table-striped table-borderless mb-0">
<thead>
<tr>
<th>Name</th>
<th>Encounter Type</th>
<th>Doctor</th>
<th>Created By</th>
<th>Created Date</th>
<th>Modified By</th>
<th>Modified Date</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of record;">
<td [textContent]="item.name"></td>
<td [textContent]="item.encounterName"></td>
<td [textContent]="item.providerName"></td>
<td [textContent]="item.createdByName"></td>
<td [textContent]="item.createdDate | date:'dd-MM-yyyy, hh:mm a'"></td>
<td [textContent]="item.modifiedByName || '---'"></td>
<td [textContent]="(item.modifiedDate | date:'dd-MM-yyyy, hh:mm a') || '---'"></td>
<td>
<div class="d-flex align-items-center justify-content-end">
<a href="javascript:;" class="action-icon text-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenModel(templateForm,item)"><i class="fe-edit"></i></a>
<a href="javascript:;" class="action-icon text-danger" placement="left" ngbTooltip="Delete" (click)="onDelete(item)"><i class="fe-trash-2"></i></a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<nav class="d-flex align-items-center justify-content-between p-2" *ngIf="pagination.totalPages > 1">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - record.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> record )</span>
</span>
</p>
<!--<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>-->
</nav>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading orders ...</span>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && (!record || !record.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateForm)"><i class="fe-plus mr-1"></i> Add</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateForm>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-mother-nurse mr-1"></i>{{orderMasterForm.value.orderPrescriptionMasterId === 0 ? 'Add' : 'Edit'}} Order Prescription</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<form [formGroup]="orderMasterForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1">Name <code>*</code></label>
<div class="form-group">
<input autofocus type="text" block maxlength="150" formControlName="name" autocomplete="nope" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.name.errors) }" placeholder="Enter name" />
</div>
</div>
</div>
<div class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1">Encounter Type <code>*</code></label>
<ng-select class="ng-select-sm text-uppercase" [items]="encounterType"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select Encounter Type"
[ngClass]="{ 'is-invalid': submitted && form.encounterTypeId.errors }"
formControlName="encounterTypeId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No encounter type found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</div>
<div class="col-md-12">
<div class="form-group">
<label class="mb-1">Doctor</label>
<ng-select class="ng-select-sm" [items]="providerResources"
[loading]="loading"
bindLabel="value"
bindValue="id"
[minTermLength]="2"
typeToSearchText="Search doctor"
[virtualScroll]="true"
placeholder="Enter 2 or more characters"
formControlName="providerId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled" *ngIf="searchTerm && searchTerm.length >= 2">
No Doctor found for '{{searchTerm}}'
</div>
<div class="ng-option disabled" *ngIf="(!searchTerm || searchTerm.length < 2)">
Search Doctor
</div>
</ng-template>
</ng-select>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { OrderPrescription } from "@shared/entities";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService, ResourceService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { HttpErrorResponse } from "@angular/common/http";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, Validators, FormBuilder } from "@angular/forms";
import { Page, IUserAccount, IResource, Pagination } from "@shared/models";
import * as ClassicEditor from "@ckeditor/ckeditor5-build-classic";
class FilterOptions {
encounterTypeId: number;
providerId: number;
name: string;
}
class Filters {
options: FilterOptions;
applied: boolean;
constructor() {
this.init();
}
init() {
this.options = new FilterOptions();
this.applied = undefined;
}
}
@Component({
templateUrl: "./encounter-order-master.html",
encapsulation: ViewEncapsulation.None
})
export class EncounterOrderMasterPage implements OnInit, OnDestroy {
page: Page;
pagination: Pagination;
orderMasterForm: FormGroup;
loading: boolean;
record: Array<OrderPrescription>;
orders: Array<OrderPrescription>;
selectedOrder: OrderPrescription;
filters: Filters;
modalRef: NgbModalRef;
submitting: boolean;
submitted: boolean;
modifying: boolean;
modifyingContent: string;
notesEditor = ClassicEditor;
encounterType: IResource[];
providerResources: Array<IResource>;
loadingproviderResources: boolean;
constructor(
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly httpService: HttpService,
private readonly resourceService: ResourceService
) {
this.loading = true;
this.page = new Page();
this.initPagination();
this.record = new Array<OrderPrescription>();
this.providerResources = new Array<IResource>();
this.filters = new Filters();
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
private buildForm() {
this.orderMasterForm = this.formBuilder.group({
name: [null],
encounterTypeId: [null, [Validators.required]],
providerId: [null],
orderPrescriptionMasterId:0
});
}
onOpenModel(content: TemplateRef<any>, record?: OrderPrescription) {
this.buildForm();
if (record) {
this.selectedOrder = record;
this.updateForm();
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
private fetchEncounterType() {
this.resourceService.encounterType()
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.encounterType = response;
});
}
private fetchProviderResources() {
this.loadingproviderResources = true;
this.resourceService.providers()
.pipe(finalize(() => { this.loadingproviderResources = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.providerResources = response;
});
}
onSubmit() {
this.submitted = true;
if (!this.orderMasterForm.valid) {
return;
}
this.submitting = true;
const request = Object.assign(UtilHelper.clone(this.orderMasterForm.getRawValue()));
request["modifiedByName"] = this.page.userAccount.fullName;
if (this.orderMasterForm.value.orderPrescriptionMasterId === 0) {
request.createdBy = this.page.userAccount.accountId;
this.httpService.post(ApiResources.getURI(ApiResources.orders.base, ApiResources.orders.addOrderMaster), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe((response: number) => {
if (response > 0) {
this.onCloseModal();
this.fetch();
this.notifyService.success("Orders details has been added successfully.");
}
else if (response < 0) {
this.notifyService.info("Order detail already exists. Please try with different name");
}
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
} else {
request.modifiedBy = this.page.userAccount.accountId;
request["modifiedByName"] = this.page.userAccount.fullName;
request["modifiedBy"] = this.page.userAccount.accountId;
request["name"] = this.orderMasterForm.value.name;
request["providerId"] = this.orderMasterForm.value.providerId;
request["encounterTypeId"] = this.orderMasterForm.value.encounterTypeId;
request["orderPrescriptionMasterId"] = this.orderMasterForm.value.orderPrescriptionMasterId;
this.httpService.put(ApiResources.getURI(ApiResources.orders.base, ApiResources.orders.updateOrderMaster), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe((response: number) => {
if (response > 0) {
this.onCloseModal();
this.fetch();
this.notifyService.success("Orders details has been updated successfully.");
}
else if (response <0) {
this.notifyService.info("Order detail already exists. Please try with different name");
}
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
}
}
get form() {
return this.orderMasterForm.controls;
}
private updateForm() {
this.orderMasterForm.patchValue({
name: this.selectedOrder.name,
providerId: this.selectedOrder.providerId,
encounterTypeId: this.selectedOrder.encounterTypeId,
orderPrescriptionMasterId: this.selectedOrder.orderPrescriptionMasterId
});
}
onDelete(record: OrderPrescription) {
this.notifyService.confirm(
`Are you sure to Delete <span class='font-weight-bold'>${record.valueName}</span>`,
() => {
const request = {
orderPrescriptionMasterId: record.orderPrescriptionMasterId,
modifiedByName: this.page.userAccount.fullName,
createdBy: this.page.userAccount.accountId,
modifiedBy: this.page.userAccount.accountId
};
this.httpService
.post(ApiResources.getURI(ApiResources.orders.base, ApiResources.orders.deleteOrderMaster), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { }))
.subscribe(
() => {
this.notifyService.success("Orders deleted successfully.");
this.fetch();
},
() => {
this.notifyService.defaultError();
});
});
}
fetch() {
this.loading = true;
const request = {
...this.pagination,
...this.filters.options
}
this.httpService
.post<Array<OrderPrescription>>(ApiResources.getURI(ApiResources.orders.base, ApiResources.orders.fetchOrderMaster), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<OrderPrescription>) => {
this.record = response;
UtilHelper.applyPagination(this.record, this.pagination);
},
() => {
this.record = [];
}
);
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.loading = false;
this.submitting = undefined;
this.submitted = undefined;
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetchEncounterType();
this.fetchProviderResources();
this.fetch();
} else {
this.page.userAccount = undefined;
}
});
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetch();
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
onApplyFilters() {
this.filters.applied = UtilHelper.isFiltersApplied(this.filters.options);
this.initPagination();
this.fetch();
}
onResetFilters() {
this.filters.init()
this.fetch();
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button type="button" class="btn btn-primary btn-sm" (click)="onAdd(templateEncounter)"><i class="fe-plus mr-1"></i> Add </button>
</div>
<h4 class="page-title">Encounter Order Templates</h4>
</div>
</div>
</div>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading Encounter Order Templates...</span>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && (!encounterOrderTemplatesdata || !encounterOrderTemplatesdata.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onAdd(templateEncounter)"><i class="fe-plus mr-1"></i> Add </button>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && encounterOrderTemplatesdata && encounterOrderTemplatesdata.length">
<div class="col-12">
<div class="card mb-0">
<div class="card-body p-0">
<div class="table-responsive">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-centered table-sm table-striped table-borderless">
<thead class="table-info">
<tr>
<th>S.No</th>
<th>EncounterTypeName</th>
<th>TemplateName</th>
<!--<th>Description</th>-->
<th>Created By</th>
<th>Created Date</th>
<th>Modified By</th>
<th>Modified Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of encounterOrderTemplatesdata , index as i">
<td>
<span>#{{(pagination.pageIndex -1)*10 + (i+1)}}</span>
</td>
<td [textContent]="item.encounterTypeName"></td>
<td [textContent]="item.templateName"></td>
<!--<td [textContent]="item.description"></td>-->
<td [textContent]="item.createdByName"></td>
<td [textContent]="item.createdDate | date:'dd-MM-yyyy, hh:mm a'"></td>
<td [textContent]="item.modifiedByName || '---'"></td>
<td [textContent]="(item.modifiedDate | date:'dd-MM-yyyy, hh:mm a') || '---'"></td>
<td>
<span class="badge badge-soft-success" *ngIf="item.active == true">Active</span>
<span class="badge badge-soft-danger" *ngIf="item.active == false">Inactive</span>
</td>
<td>
<div class="d-flex align-items-center justify-content-end">
<a href="javascript:;" class="action-icon text-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenModel(templateEncounter, item)"><i class="fe-edit"></i></a>
<button type="button" class="btn btn-sm btn-outline-success" *ngIf="item.active == false" title="Active" (click)="onChangeStatus(item)">
<i class="fe-check-square"></i>
</button>
<button type="button" class="btn btn-sm btn-outline-warning" *ngIf="item.active == true" title="Inactive" (click)="onChangeStatus(item)">
<i class="fe-x-square"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<nav class="d-flex align-items-center justify-content-between p-2" *ngIf="pagination.totalPages > 1">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - encounterOrderTemplatesdata.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> Encounter Order Templates )</span>
</span>
</p>
<!--<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>-->
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateEncounter>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-mother-nurse mr-1"></i>{{encounterOrderTemplateForm.value.encounterTemplateId === 0 ? 'Add' : 'Edit'}} Encounter Order Template</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<form [formGroup]="encounterOrderTemplateForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1">Encounter Type</label>
<ng-select class="ng-select-sm text-uppercase" [items]="encounterType"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select Encounter Type"
(change)="onChangeEncounter($event)"
[ngClass]="{ 'is-invalid': submitted && form.encounterTypeId.errors }"
formControlName="encounterTypeId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No encounter type found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</div>
<div class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1">Template Name <code>*</code></label>
<div class="form-group">
<input tabindex="1" type="text" block maxlength="100" formControlName="templateName" autocomplete="nope" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.templateName.errors) }" placeholder="Enter Template Name" />
<div *ngIf="submitted && form.templateName.errors" class="invalid-feedback show-must">
<p *ngIf="form.templateName.errors.required">Template Name is required.</p>
<p *ngIf="form.templateName.errors.whiteSpaces">Please remove white spaces.</p>
</div>
</div>
</div>
</div>
<div class="col-md-12">
<div class="form-group">
<label class="mb-1">Comments <code>*</code></label>
<ckeditor [editor]="notesEditor" [config]="config" formControlName="description"></ckeditor>
<div *ngIf="submitted && form.description.errors" class="invalid-feedback show-must">
<p *ngIf="form.description.errors.required">Description is required.</p>
<p *ngIf="form.description.errors.whiteSpaces">Please remove white spaces.</p>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService, ResourceService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, Validators, FormBuilder } from "@angular/forms";
import { Page, IUserAccount, IResource, Pagination } from "@shared/models";
import { WhiteSpaceValidator } from "@shared/validators";
import { HttpErrorResponse } from "@angular/common/http";
import { EncounterOrderTemplatesList } from "../../../../../shared/entities/encounter-order-templates.entity";
import * as ClassicEditor from "@ckeditor/ckeditor5-build-classic";
@Component({
templateUrl: "./encounter-order-templates.html",
encapsulation: ViewEncapsulation.None
})
export class EncounterOrderTemplatesPage implements OnInit, OnDestroy {
page: Page;
modalRef: NgbModalRef;
encounterOrderTemplateForm: FormGroup;
submitting: boolean;
submitted: boolean;
pagination: Pagination;
loading: boolean;
encounterType: IResource[];
notesEditor = ClassicEditor;
config = {
placeholder: "Enter method text here!",
toolbar: ["heading", "|", "bold", "italic", "link", "bulletedList", "numberedList", "blockQuote"]
};
encounterOrderTemplatesdata: Array<EncounterOrderTemplatesList>;
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetch();
this.fetchEncounterType();
} else {
this.page.userAccount = undefined;
}
});
}
private fetchEncounterType() {
this.resourceService.encounterType()
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.encounterType = response;
});
}
private buildForm() {
this.encounterOrderTemplateForm = this.formBuilder.group({
encounterTemplateId :0,
encounterTypeId: null,
templateName: [null, [Validators.required, WhiteSpaceValidator.isValid]],
description: [null, [Validators.required, WhiteSpaceValidator.isValid]]
});
}
constructor(
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly httpService: HttpService,
private readonly resourceService: ResourceService
) {
this.loading = true;
this.page = new Page();
this.initPagination();
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetch();
}
fetch() {
this.loading = true;
const request = {
...this.pagination
};
this.httpService
.post<Array<EncounterOrderTemplatesList>>(ApiResources.getURI(ApiResources.orders.base, ApiResources.orders.fetchencounterOrderTemplates), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<EncounterOrderTemplatesList>) => {
this.encounterOrderTemplatesdata = response;
UtilHelper.applyPagination(this.encounterOrderTemplatesdata, this.pagination);
},
() => {
this.encounterOrderTemplatesdata = [];
}
);
}
onAdd(content: TemplateRef<any>) {
this.buildForm();
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
onChangeEncounter(event: IResource) {
this.encounterOrderTemplateForm.patchValue({
encounterTypeId: event.id
})
}
onSubmit() {
this.submitted = true;
if (this.encounterOrderTemplateForm.invalid) {
return
}
this.submitting = true;
this.loading = true;
const request = Object.assign(UtilHelper.clone(this.encounterOrderTemplateForm.getRawValue()));
if (this.encounterOrderTemplateForm.value.encounterTemplateId === 0) {
request["createdBy"] = this.page.userAccount.accountId;
request["createdByName"] = this.page.userAccount.fullName;
this.httpService.post(ApiResources.getURI(ApiResources.orders.base, ApiResources.orders.modifyencounterOrderTemplates), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
this.loading = false;
}))
.subscribe((response: number) => {
if (response > 0) {
this.fetch();
this.onCloseModal();
this.notifyService.successToast("EncounterOrderTemplate has been added successfully.");
}
else if (response == -1) {
this.notifyService.warningToast("This EncounterOrderTemplate is Not Added");
}
else if (response == -2) {
this.notifyService.warningToast("This EncounterOrderTemplate is Already Existed");
}
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
} else {
if (this.encounterOrderTemplateForm.invalid) {
return
}
request.modifiedBy = this.page.userAccount.accountId;
request['active'] = this.encounterOrderTemplateForm.value.active;
request["modifiedBy"] = this.page.userAccount.accountId;
request["modifiedByName"] = this.page.userAccount.fullName;
this.httpService.post(ApiResources.getURI(ApiResources.orders.base, ApiResources.orders.modifyencounterOrderTemplates), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
this.loading = false;
}))
.subscribe((response: number) => {
if (response > 0) {
this.fetch();
this.onCloseModal();
this.notifyService.successToast("EncounterOrderTemplate has been Updated successfully.");
}
else if (response == -1) {
this.notifyService.warningToast("This EncounterOrderTemplate is Not Updated");
}
else if (response == -2) {
this.notifyService.warningToast("This EncounterOrderTemplate is Already Existed");
}
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
}
}
onApplyFilters() {
this.loading = true;
this.initPagination();
this.fetch()
}
onResetFilters() {
this.loading = true;
this.initPagination();
this.fetch()
}
onOpenModel(content: TemplateRef<any>, EncounterOrderTemplate?: EncounterOrderTemplatesList) {
this.buildForm();
if (EncounterOrderTemplate) {
this.encounterOrderTemplateForm.patchValue({
encounterTemplateId: EncounterOrderTemplate.encounterTemplateId,
encounterTypeId: EncounterOrderTemplate.encounterTypeId,
templateName: EncounterOrderTemplate.templateName,
description: EncounterOrderTemplate.description
})
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
get form() {
return this.encounterOrderTemplateForm.controls;
}
onChangeStatus(data: EncounterOrderTemplatesList) {
this.notifyService.confirm(`You want to ${data.active ? 'Deactivate' : 'Activate'} this EncounterOrder Templates?`, () => {
data["modifiedBy"] = this.page.userAccount.accountId;
this.httpService.post(ApiResources.getURI(ApiResources.orders.base, ApiResources.orders.changestatusencounterOrderTemplates), data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loading = false }))
.subscribe((response: number) => {
if (response > 0) {
this.notifyService.successToast(`${data.active ? 'Deactivate' : 'Activate'} successfully.`);
}
this.fetch();
this.onCloseModal();
}, (error: HttpErrorResponse) => {
this.notifyService.errorToast(error.error);
});
});
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.loading = false;
this.submitting = undefined;
this.submitted = undefined;
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
}

<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button *ngIf="!loading && encounterTypes && encounterTypes.length" type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateWord)"><i class="fe-plus mr-1"></i> Add Encounter Type</button>
<!--<button *ngIf="!loading && !filters.applied && generalAdvices && generalAdvices.length" type="button" class="btn btn-secondary btn-sm ml-1" (click)="onShowFilters()"><i class="fe-filter mr-1"></i> Filters</button>-->
</div>
<h4 class="page-title">Encounter Type</h4>
</div>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading Encounter Types ...</span>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && (!encounterTypes || !encounterTypes.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<h4 class="title">Oops! No Encounter Types found<span *ngIf="filters.applied"> based on your filters criteria</span>.</h4>
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateWord)"><i class="fe-plus mr-1"></i> Add Encounter Type</button>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && encounterTypes && encounterTypes.length">
<div class="col-12">
<div class="card mb-0">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-centered table-sm table-striped table-borderless mb-0">
<thead>
<tr>
<th>Encounter Name</th>
<th>Created Date</th>
<!--<th>Modified By</th>-->
<th>Modified Date & Time</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<!--trackBy: trackBy.encounterTypes-->
<tr *ngFor="let item of encounterTypes; ">
<td [textContent]="item.encounterName"></td>
<td [textContent]="item.createdDate | date:'short'"></td>
<!--<td [textContent]="item.modifiedByName"></td>-->
<td [textContent]="(item.modifiedDate | date:'dd-MM-yyyy, hh:mm a') || '---'"></td>
<td>
<div class="d-flex align-items-center justify-content-end">
<a href="javascript:;" class="action-icon text-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenModel(templateWord, item)"><i class="fe-edit"></i></a>
<a href="javascript:;" class="action-icon text-danger" placement="left" ngbTooltip="Delete" (click)="onDelete(item)"><i class="fe-trash-2"></i></a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<nav class="d-flex align-items-center justify-content-between p-2" *ngIf="pagination.totalPages > 1">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - encounterTypes.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> Encounter Types )</span>
</span>
</p>
<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateWord>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-mother-nurse mr-1"></i>{{encounterTypeForm.value.encounterTypeId === 0 ? 'Add' : 'Edit'}} Encounter Type</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<form [formGroup]="encounterTypeForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1">Encounter Name <code>*</code></label>
<div class="form-group">
<input tabindex="1" type="text" block maxlength="150" autofocus formControlName="encounterName" autocomplete="nope" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.encounterName.errors) }" placeholder="Enter encounter name" />
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { HttpErrorResponse } from "@angular/common/http";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, Validators, FormBuilder } from "@angular/forms";
import { Page, IUserAccount, Pagination } from "@shared/models";
import { EncounterType } from "@shared/entities/encounter-type.entity";
import { WhiteSpaceValidator } from "../../../../../shared/validators";
class TrackBy {
encounterTypes(item: EncounterType) {
return item.encounterTypeId;
}
}
class FilterOptions {
encounterName: string = null;
encounterTypeId: number;
}
class Filters {
options: FilterOptions;
applied: boolean;
constructor() {
this.init();
}
init() {
this.options = new FilterOptions();
this.applied = undefined;
}
}
@Component({
templateUrl: "./encounter-type.html",
encapsulation: ViewEncapsulation.None
})
export class EncounterTypePage implements OnInit, OnDestroy {
page: Page;
filters: Filters;
trackBy: TrackBy;
pagination: Pagination;
encounterTypeForm: FormGroup;
loading: boolean;
encounterTypes: Array<EncounterType>;
selectedEncounterType: EncounterType;
modalRef: NgbModalRef;
submitting: boolean;
submitted: boolean;
modifying: boolean;
modifyingContent: string;
constructor(
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly httpService: HttpService
) {
this.loading = true;
this.page = new Page();
this.filters = new Filters();
this.trackBy = new TrackBy();
this.initPagination();
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
private buildForm() {
this.encounterTypeForm = this.formBuilder.group({
encounterTypeId: 0,
encounterName: [null, [Validators.required, WhiteSpaceValidator.isValid]],
active: [true],
});
}
onOpenModel(content: TemplateRef<any>, encounterTypes?: EncounterType) {
this.buildForm();
if (encounterTypes) {
this.selectedEncounterType = encounterTypes;
this.updateForm();
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
fetchAddEncounterType() {
this.loading = true;
const request = Object.assign(UtilHelper.clone(this.filters.options), UtilHelper.clone(this.pagination));
this.httpService
.post<Array<EncounterType>>(ApiResources.getURI(ApiResources.encounterType.base, ApiResources.encounterType.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<EncounterType>) => {
this.encounterTypes = response;
UtilHelper.applyPagination(this.encounterTypes, this.pagination);
},
() => {
this.encounterTypes = [];
}
);
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetchAddEncounterType();
}
onSubmit() {
this.submitted = true;
if (!this.encounterTypeForm.valid) {
return;
}
console.log(this.encounterTypeForm.value);
this.submitting = true;
const request = Object.assign(UtilHelper.clone(this.encounterTypeForm.getRawValue()));
request["modifiedByName"] = this.page.userAccount.fullName;
if (Number (this.encounterTypeForm.value.encounterTypeId) === 0) {
request.createdBy = this.page.userAccount.accountId;
this.httpService.post(ApiResources.getURI(ApiResources.encounterType.base, ApiResources.encounterType.add), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchAddEncounterType();
this.notifyService.success("Encounter Type has been added successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
} else {
request.modifiedBy = this.page.userAccount.accountId;
request["modifiedByName"] = this.page.userAccount.fullName;
request["createdBy"] = this.page.userAccount.accountId;
delete request.type;
this.httpService.put(ApiResources.getURI(ApiResources.encounterType.base, ApiResources.encounterType.update), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchAddEncounterType();
this.notifyService.success("Encounter Type details has been updated successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
}
}
get form() {
return this.encounterTypeForm.controls;
}
private updateForm() {
this.encounterTypeForm.patchValue({
encounterTypeId: this.selectedEncounterType.encounterTypeId,
encounterName: this.selectedEncounterType.encounterName,
active: this.selectedEncounterType.active
});
}
onDelete(encounterTypes: EncounterType) {
this.notifyService.delete(() => {
this.httpService
.post(ApiResources.getURI(ApiResources.encounterType.base, ApiResources.encounterType.delete), {
encounterTypeId: encounterTypes.encounterTypeId, modifiedByName: this.page.userAccount.fullName,
createdBy: this.page.userAccount.accountId,
modifiedBy: this.page.userAccount.accountId })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { }))
.subscribe(
() => {
this.notifyService.success("Encounter Type deleted successfully.");
this.fetchAddEncounterType();
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
}
);
}, () => { });
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.loading = false;
this.submitting = undefined;
this.submitted = undefined;
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetchAddEncounterType();
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
}
\ No newline at end of file
@-webkit-keyframes stripes {
from {
background-position: 0 0
}
to {
background-position: 60px 30px
}
}
@keyframes stripes {
from {
background-position: 0 0
}
to {
background-position: 60px 30px
}
}
.image-cropper {
border-radius: 0.25rem !important;
padding: 0 !important;
}
.image-cropper-no-visible {
height: 0 !important;
}
.img-crop-upload {
width: 100%;
height: 400px;
background: #f5f8fa;
border-radius: 0.25rem;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 0;
border: 1px solid #e9ecef;
flex-flow: column;
}
.img-crop-upload i {
font-size: 60px;
color: #aaa;
margin-bottom: 1rem;
opacity: 0.75;
}
.img-crop-upload p {
color: #aaa;
font-size: 20pt;
}
.img-crop-upload .custom-file {
max-width: 350px;
}
.img-crop-upload:hover {
background-size: 20px 20px;
background-image: -webkit-linear-gradient(135deg, #fff 25%, transparent 25%, transparent 50%, #fff 50%, #fff 75%, transparent 75%, transparent);
background-image: linear-gradient(-45deg, #fff 25%, transparent 25%, transparent 50%, #fff 50%, #fff 75%, transparent 75%, transparent);
-webkit-animation: stripes 2s linear infinite;
animation: stripes 2s linear infinite;
}
.btn-icon {
border-radius: 100%;
width: 25px;
height: 25px;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
padding: 0;
}
.btn-icon i:before {
margin: 0;
}
.t-0 {
top: 0 !important;
}
.r-0 {
right: 0 !important;
}
.l-0 {
left: 0 !important;
}
.b-0 {
bottom: 0 !important;
}
fieldset {
border: 1px solid #ddd !important;
margin: 0;
xmin-width: 0;
padding: 10px;
position: relative;
border-radius: 4px;
/* background-color: #f5f5f5;*/
padding-left: 10px !important;
}
legend {
font-size: 14px;
font-weight: bold;
margin-bottom: 0px;
width: 35%;
border: 1px solid #ddd;
border-radius: 4px;
padding: 5px 5px 5px 10px;
background-color: #f5f5f5;
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box text-right">
<div class="page-title-right">
<button type="button" class="btn btn-sm waves-effect waves-light btn-secondary mr-1" (click)="onOpenModel(templateSampleSheet,'xl')">
<i class="mdi mdi-download mr-1"></i>Download Sample Sheets
</button>
<button type="button" class="btn btn-sm btn-blue waves-effect waves-light" (click)="onOpenModel(templateUploadPatient,'xxl');">
<i class="mdi mdi-cloud-upload-outline mr-1"></i> Upload Sheet
</button>
</div>
<h4 class="page-title">Patient Import Excel</h4>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card-box p-0">
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while reading the excel sheet....</span>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && (!excelHistory || !excelHistory.length)">
<div class="col-12 mh-400">
<no-data [applied]="filters.applied" [title]="'Upload History'"></no-data>
</div>
</div>
<div class="table-responsive myheight" *ngIf="!loading && excelHistory.length > 0">
<table class="table table-sm table-bordered table-striped table-hover mb-0">
<thead class="table-info">
<tr>
<th>S.No</th>
<th>Sheet Name</th>
<th>Uploaded By</th>
<th>Uploaded Date</th>
<th>Uploaded At</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of excelHistory;let i= index;">
<td><span [textContent]="i+1"></span></td>
<td><span [textContent]="item.sheetName"></span></td>
<td><span [textContent]="item.uploadedByName"></span></td>
<td><span [textContent]="item.createdDate | date:'dd-MM-yyyy, hh:mm a'"></span></td>
<td><span [textContent]="item.locationName || '----'"></span></td>
<td>
<nav class="nav">
<button type="button" class="btn btn-sm btn-outline-info mr-1" (click)="onOpenPatientView(templateViewUploadedPatients,item)" title="View"><i class="mdi mdi-eye-outline"></i></button>
</nav>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="7">
<nav class="d-flex align-items-center justify-content-between p-2" style="flex-wrap:wrap;">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - excelHistory.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> records)</span>
</span>
</p>
<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="fetchUploadHistory()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>
</nav>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateViewUploadedPatients>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-file-upload-outline mr-1"></i>Uploaded Patients</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-12" *ngIf="loadingPatients">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while reading the excel sheet....</span>
</div>
</div>
<div class="col-12 mh-400" *ngIf="!loadingPatients && (!patient || !patient.length)">
<no-data [applied]="filters.applied" [title]="'Uploaded Patients'"></no-data>
</div>
<div class="col-12" *ngIf="!loadingPatients && patient.length > 0">
<div class="table-responsive" style="max-height:500px;overflow:auto;">
<table class="table table-hover m-0 table-bordered table-striped">
<thead class="table-info">
<tr role="row">
<th>Umr No</th>
<th>FullName</th>
<th>Mobile</th>
<th>Email</th>
<th>Gender</th>
<!--<th>Address</th>-->
</tr>
</thead>
<tbody>
<tr *ngFor="let record of patient;let index = i;">
<td>
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="record.umrNo"></h5>
</td>
<td>
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="record.fullName"></h5>
</td>
<td *ngIf="record.mobile" [textContent]="'(+' + record.countryCode + ') ' + record.mobile">
</td>
<td [textContent]="record.email || '-----'"></td>
<td [textContent]="record.gender | gender"></td>
<!--<td>
<span [textContent]="record.addressLine2 || '-----'"></span> &nbsp;
</td>-->
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</ng-template>
<ng-template #templateUploadPatient>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-file-upload-outline mr-1"></i>Upload Sheet</h4>
<button type="button" class="closeBtn" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-12" style="box-sizing:border-box" *ngIf="!loadingFile && rawPatients.length === 0 && !isUploading && rawRecords.length === 0">
<div class="form-group mb-1">
<p class="text-justify font-weight-bold">Upload Instructions</p>
<ul>
<li>Only <strong>.xlsx</strong> format are accepted.</li>
<li>Please upload file with similar column as in Sample Sheet.</li>
<li>File with max <b>2500 rows</b> are allowed.</li>
<li>Fields marked with <b><code>*</code></b> are required fields in excel sheet.</li>
<li>Gender should be either <b>M</b> or <b>F</b></li>
</ul>
</div>
<div class="form-group img-crop-upload" style="height:auto !important; box-sizing:border-box">
<i class="fe-upload-cloud"></i>
<p>Choose a excel file below</p>
<div class="pb-3">
<div class="custom-file">
<input type="file" class="custom-file-input" id="choose-file" [accept]="'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'" (change)="onFileUpload($event)"
[ngClass]="{ 'is-invalid': fileUploadFail}">
<label class="custom-file-label" data-browse="Browse" for="choose-file">Choose your file</label>
</div>
</div>
<div class="invalid-feedback show-must p-2" *ngIf="fileUploadFail">Invalid file chosen or there is a problem with file.<br />Please select another excel and try again.</div>
</div>
</div>
<div class="col-12" *ngIf="loadingFile">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while reading the excel sheet....</span>
</div>
</div>
<!--Salutation(*)", "FirstName(*)", "LastName(*)", "Mobile(*)", "Gender(*)", "DateOfBirth(*)",
"Age(*)","Email","Address(*)","PinCode","Relation","RelativeName","RelativeMobile" ];-->
<ng-container *ngIf="!loadingFile && rawRecords.length && isUploadingPatientSheet">
<div class="col-12">
<div class="row" style="max-height:550px !important;overflow-x:auto;">
<div class="col-12">
<div class="table-responsive">
<table class="table table-sm table-striped table-bordered">
<thead class="table-info">
<tr class="white-space-nowrap">
<th>UMR No/MR No</th>
<th>Salutation</th>
<th>First Name</th>
<th>Last Name</th>
<th style="min-width:110px;">Mobile<code>&nbsp;*</code></th>
<th class="min-width85px">DOB
(DD-MM-YYYY)</th>
<th>Age<code>&nbsp;*</code></th>
<th style="min-width:85px">Gender<code>&nbsp;*</code></th>
<th class="min-width150px">Email</th>
<th class="min-width85px">Address<code>&nbsp;*</code></th>
<th>PinCode</th>
<th>Relation</th>
<th>RelativeName</th>
<th>RelativeMobile</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of rawPatientProcessed;index as i;">
<td>
<input type="text" class="form-control form-control-sm mt-1" style="padding: 0.28rem 0.28rem !important;" [(ngModel)]="item.umrNo" />
</td>
<td style="padding-top: 16px;">
<select class="form-control custom-select mt-1" style="padding: 0.28rem 0.28rem !important;" [(ngModel)]="item.salutation">
<option selected hidden [ngValue]="null">Select</option>
<option [ngValue]="'Mr'">Mr.</option>
<option [ngValue]="'Miss'">Miss.</option>
<option [ngValue]="'Mrs'">Mrs.</option>
<option [ngValue]="'Dr'">Dr.</option>
<option [ngValue]="'Baby'">Baby.</option>
</select>
</td>
<td style="padding-top: 16px;">
<span [textContent]="item.firstName"></span>
</td>
<td style="padding-top: 16px;">
<span [textContent]="item.lastName"></span>
</td>
<td>
<input type="text" numbersOnly class="form-control form-control-sm mt-1" style="padding: 0.28rem 0.28rem !important;" [(ngModel)]="item.mobile" maxlength="10" />
<span style="color:red" *ngIf="item.mobile?.length != 10">
please enter valid mobile no.
</span>
</td>
<td style="padding-top: 16px;">
<span [textContent]="item.dateOfBirth"></span>
</td>
<!--<td>
<input type="text" class="form-control form-control-sm mt-1" style="padding: 0.28rem 0.28rem !important;" [(ngModel)]="item.dateOfBirth" />
<span style="color:red" *ngIf="item.dateOfBirth?.length ==0">
please enter date Of birth.
</span>
</td>-->
<!--<td>
<input type="text" class="form-control form-control-sm mt-1" style="padding: 0.28rem 0.28rem !important;" [(ngModel)]="item.age" />
<span style="color:red" *ngIf="item.age?.length ==0">
please enter age.
</span>
</td>-->
<td style="padding-top: 16px;">
<span [textContent]="item.age"></span>
</td>
<td class="pl-1 pr-0 ">
<select class="form-control custom-select mt-1" style="padding: 0.28rem 0.28rem !important;" [(ngModel)]="item.gender">
<option [ngValue]="null">Select</option>
<option [ngValue]="'M'">Male</option>
<option [ngValue]="'F'">Female</option>
<option [ngValue]="'O'">Others</option>
</select>
</td>
<td>
<input type="text" class="form-control form-control-sm mt-1" style="padding: 0.28rem 0.28rem !important;" [(ngModel)]="item.email" />
</td>
<!--(keypress)="space($event)"-->
<td>
<input type="text" class="form-control form-control-sm mt-1" style="padding: 0.28rem 0.28rem !important;" (input)="checkText(item)" [(ngModel)]="item.address" />
<span style="color:red" *ngIf="item.address?.length ==0">
please enter address no.
</span>
</td>
<td>
<input type="text" class="form-control form-control-sm mt-1" style="padding: 0.28rem 0.28rem !important;" [(ngModel)]="item.pinCode" />
</td>
<td class="pl-0 pr-0">
<select class="form-control custom-select mt-1" style="padding: 0.28rem 0.28rem !important;" [(ngModel)]="item.relationType">
<option [ngValue]="null" *ngIf="!loadingRelations">Select relation</option>
<option selected *ngIf="loadingRelations">Loading...</option>
<option *ngFor="let item of relations" [textContent]="item.value" [ngValue]="item.value"></option>
</select>
<div class="show-must invalid-feedback" *ngIf="!item.isMatchRole">
<p><i class="mdi mdi-information mr-1"></i>Please select role.</p>
</div>
</td>
<td>
<input type="text" class="form-control form-control-sm mt-1" style="padding: 0.28rem 0.28rem !important;" [(ngModel)]="item.relativeName" />
</td>
<td>
<input type="text" class="form-control form-control-sm mt-1" style="padding: 0.28rem 0.28rem !important;" [(ngModel)]="item.relativeMobile" />
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="col-12">
<div class="d-flex justify-content-center">
<div class="badge font-13 mr-1">Sheet consists {{rawRecords.length}} record</div>
<button class="btn btn-sm btn-outline-success" type="button" (click)="onThreadingPatientUpload(0)" [disabled]="submitting">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Proceed</span>
</button>
</div>
</div>
</ng-container>
</div>
</div>
</ng-template>
<ng-template #templateReturnedData>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-file-upload-outline mr-1"></i>Duplicate Data</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="table-responsive myheight" *ngIf="returnedData.length > 0">
<table class="table table-sm table-bordered table-striped table-hover mb-0">
<thead class="table-info">
<tr>
<th>FullName</th>
<th>Gender</th>
<th>Mobile</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let record of returnedData;let i= index;">
<td>
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="record.fullName"></h5>
</td>
<td [textContent]="record.gender | gender"></td>
<td [textContent]="record.mobile">
</td>
<td [textContent]="record.email || '-----'"></td>
</tr>
</tbody>
</table>
</div>
</ng-template>
<ng-template #templateSampleSheet>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-file-excel-outline mr-1"></i>Download Sample Excel Sheets</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-12 alert alert-info">
<h5>Instructions to fill excel sheets</h5>
<ol>
<li>Field marked with <b>Asterisk</b>&nbsp;<code>or</code>&nbsp;<b>*</b>&nbsp;are required fields and must be filled.</li>
<li>Excel sheet should not have more than <b>2500</b> rows</li>
<li>
While filling the form need to be focused on these points
<ul>
<li>Field <b>Gender</b> must be filled either (F/M)</li>
<li>Field <b>DateOfBirth</b> must be filled with format <b>"MM-DD-YYYY"</b>.</li>
</ul>
</li>
</ol>
</div>
<div class="col-12 mt-1">
<div class="row">
<div class="col-auto">
<div class="card mb-1 shadow-none border">
<div class="p-2">
<div class="row align-items-center">
<div class="col-auto">
<div class="avatar-sm">
<a href="assets/files/PatientImport.xlsx" (click)="onCloseDownloadModel()" download="assets/files/PatientImport.xlsx">
<span class="avatar-title badge-soft-primary text-primary rounded">
.xlsx
</span>
</a>
</div>
</div>
<div class="col ps-0">
<a href="assets/files/PatientImport.xlsx" (click)="onCloseDownloadModel()" download="assets/files/PatientImport.xlsx" class="text-muted fw-bold">PatientImport.xlsx</a>
<p class="mb-0 font-12">5 KB</p>
</div>
<div class="col-auto">
<a href="assets/files/PatientImport.xlsx" (click)="onCloseDownloadModel()" download="assets/files/PatientImport.xlsx" ngbTooltip="Click to download sample sheet" tooltipClass="tooltip-primary" placement="top" class="btn btn-link font-16 text-muted">
<i class="dripicons-download"></i>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-template>
import { Component, OnInit, OnDestroy, TemplateRef, ViewChild } from "@angular/core";
import { Page, IUserAccount, Pagination, IResource } from "@shared/models";
import { AppData, HttpService, NotifyService, ResourceService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { NgbModalRef, NgbModal } from "@ng-bootstrap/ng-bootstrap";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { UserImportHistory, PatientRawImport, PateintImportHistory } from "@shared/entities";
//import readXlsxFile from "read-excel-file";
import readXlsxFile from 'xlsx/xlsx.js';
import { HttpErrorResponse } from "@angular/common/http";
import { Patient } from "@shared/entities";
import * as moment from "moment";
class PreDefinedHeaders {
patientHeader: Array<string>;
constructor() {
this.patientHeader = ["UmrNo","Salutation(*)", "FirstName(*)", "LastName(*)", "Mobile(*)", "Gender(*)(F/M)", "DateOfBirth(DD/MM/YYYY)", "Age(*)", "Email", "Address(*)", "PinCode", "Relation", "RelativeName", "RelativeMobile"];
// Salutation(*) FirstName(*) LastName(*) Mobile(*) Gender(*) DateOfBirth(*)(DD / MM / YYYY) Age(*) Email Address(*) PinCode Relation  RelativeName RelativeMobile
}
}
class Threading {
totalRecord: number = 0;
inUploading: number = 0;
percentage: number = 0;
currentlyUploaded: number = 0;
}
class FilterOption {
}
class Filter {
options: FilterOption;
applied: boolean;
constructor() {
this.init();
}
init() {
this.applied = false;
this.options = new FilterOption();
}
}
class ReturnTuples {
item1: any;
item2: Array<any>;
}
@Component({
templateUrl: "./patient-import.html",
styleUrls: ['./patient-import-excel.css']
})
export class PatientImportPage implements OnInit, OnDestroy {
@ViewChild("templateReturnedData", { static: true }) templateReturnedData: TemplateRef<any>;
page: Page;
loading: boolean;
modalRef: NgbModalRef;
pagination: Pagination;
excelHistory: Array<PateintImportHistory>;
filters: Filter;
headerClass: PreDefinedHeaders;
isUploading: boolean;
fileUploadFail: boolean;
loadingFile: boolean;
uploadedFile: File;
sheetName: string;
rawRecords: Array<any>;
rawPatients: Array<PatientRawImport>;
isUploadingPatientSheet: boolean;
submitting: boolean;
threading: Threading;
rawPatientProcessed: Array<any>;
loadingLocations: boolean;
locations: Array<IResource>;
loadingRoles: boolean;
roles: Array<IResource>;
recordsPerThread: number;
selectedHistory: UserImportHistory;
loadingPatients: boolean;
patient: Array<Patient>;
isDuplicate: boolean;
isDuplicatePatient: boolean;
returnedData: Array<ReturnTuples>;
mobNumberPattern = "^((\\+91-?)|0)?[0-9]{10}$";
emailPattern: "/^[\w-]+(?:\.[\w-]+)*@(?:[\w-]+\.)+[a-zA-Z]{2,7}$/";
mobileFilter: any;
EmailFilter: any;
whiteSpace: any;
dateFilter: any;
isEmail: boolean;
loadingRelations: boolean;
relations: Array<IResource>;
isValidFormSubmitted = false;
checkEmail: any;
checkMobileValid: any;
date: any;
checkEmailInfo: number;
patients: Array<Patient>;
flag: boolean;
constructor(
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly httpService: HttpService,
private readonly notifyService: NotifyService,
private readonly resourceService: ResourceService
) {
this.dateFilter = new RegExp( /^(((0[1-9]|[12]\d|3[01])\/(0[13578]|1[02])\/((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\/(0[13456789]|1[012])\/((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\/02\/((19|[2-9]\d)\d{2}))|(29\/02\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g);
this.whiteSpace = new RegExp(/^[\s]{1,}|[\s]{2,}|[\s]{1,}$/);
this.mobileFilter = new RegExp(/^\b\d{10}?\b$/);
this.EmailFilter = new RegExp(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/);
this.page = new Page();
this.initPagination();
this.filters = new Filter();
this.excelHistory = new Array<PateintImportHistory>();
this.headerClass = new PreDefinedHeaders();
this.rawRecords = new Array<any>();
this.rawPatients = new Array<PatientRawImport>();
this.threading = new Threading();
this.rawPatientProcessed = new Array<any>();
this.locations = new Array<IResource>();
this.roles = new Array<IResource>();
this.recordsPerThread = 50;
this.selectedHistory = new UserImportHistory();
this.patient = new Array<Patient>();
this.returnedData = new Array<ReturnTuples>();
this.date = new Date().toLocaleDateString();
}
initPagination() {
this.pagination = new Pagination();
this.pagination.pageSize = 12;
this.pagination.pageIndex = 1;
}
checkText(record) {
if (this.whiteSpace.test(record.address)) {
record.isAddress = true;
}
else {
record.isAddress = false;
}
}
matchPatientRole(record) {
if (!record.role) {
record.isMatchRole = false;
return;
}
let find = this.roles.find(x => x.value.toLowerCase() === record.role.toLowerCase());
if (find != null) {
record.role = find.value;
record.isMatchRole = true;
record.roleId = find.id;
}
else {
record.role = null;
record.isMatchRole = false;
}
}
matchPatientMail(record) {
if (!record.email) {
record.isEmail = false;
return;
}
let find = this.roles.find(x => x.value.toLowerCase() === record.role.toLowerCase());
if (find != null) {
record.role = find.value;
record.isMatchRole = true;
record.roleId = find.id;
}
else {
record.role = null;
record.isMatchRole = false;
}
}
onMatchRoles() {
this.rawPatientProcessed.forEach((item) => {
this.matchPatientRole(item);
});
}
matchPatientLocation(record) {
if (!record.location) {
record.isMatchLocation = false;
return;
}
let find = this.locations.find(x => x.name.toLowerCase() === record.location.toLowerCase());
if (find != null) {
record.location = find.name;
record.isMatchLocation = true;
record.locationIds = find.id;
let myInt = find.id;
// Getting the string as a parameter
// and typecasting it into an integer
let myFunc = num => Number(num);
let intArr = Array.from(String(myInt), myFunc);
record.locationIds = intArr;
record.locationId = intArr;
}
else {
record.location = null;
record.isMatchLocation = false;
}
}
onMatchLocation() {
this.rawRecords.forEach((item) => {
this.matchPatientLocation(item);
});
}
fetchUploadHistory() {
this.loading = true;
const request = Object.assign(UtilHelper.clone(this.filters.options), this.pagination);
this.httpService.post(ApiResources.getURI(ApiResources.patientImport.base, ApiResources.patientImport.fetchUploadHistory), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe((response: Array<PateintImportHistory>) => {
this.excelHistory = response
UtilHelper.applyPagination(this.excelHistory, this.pagination);
}, () => {
this.excelHistory = new Array<PateintImportHistory>();
this.notifyService.error("Error occured in fetching upload history.");
});
}
onFileUpload(event) {
this.loadingFile = true;
this.uploadedFile = event.target.files[0];
this.fileUploadFail = false;
this.sheetName = this.uploadedFile.name;
let extension = this.uploadedFile.name.split(".").pop();
if (extension === "xlsx" || extension === "xls") {
this.fileChangeEvent();
}
else {
this.loadingFile = false;
this.uploadedFile = null;
this.fileUploadFail = true;
}
}
private fetchRelations() {
this.loadingRelations = true;
this.resourceService.relationships()
.pipe(finalize(() => { this.loadingRelations = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.relations = response;
});
}
fileChangeEvent() {
let records = [];
setTimeout(() => {
readXlsxFile(this.uploadedFile).then((rows) => {
let index = 0;
for (let row of rows) {
if (index === 0) {
let checkArray = new Array<string>();
for (let single of row) {
checkArray.push((single as any).toString());
}
let headerAsArray = JSON.stringify(checkArray);
let patientHeader = JSON.stringify(this.headerClass.patientHeader);
if (headerAsArray === patientHeader) {
this.isUploadingPatientSheet = true;
}
else {
this.notifyService.warning("Sheet Cannot be Uploaded, Sheet might not Match with Sample Sheet provided!");
break;
}
}
else {
var x = this.checkNull(row[6] as any) ? row[6].toString().trim() : "";
this.checkEmail = this.EmailFilter.test(x);
if (this.EmailFilter.test(x)) {
this.isEmail = true;
}
else {
this.isEmail = false;
}
records.push({
umrNo: this.checkNull(row[0] as any) ? row[0].toString().trim() : "",
salutation: this.checkNull(row[1] as any) ? row[1].toString().trim() : "",
firstName: this.checkNull(row[2] as any) ? row[2].toString().trim() : "",
lastName: this.checkNull(row[3] as any) ? row[3].toString().trim() : "",
mobile: this.checkNull(row[4] as any) ? row[4].toString().trim() : "",
dateOfBirth: UtilHelper.isEmpty(row[6] as any) ? moment(new Date(row[6].toString().trim())).format("DD-MM-YYYY") : null,
age: this.checkNull(row[7] as any) ? row[7].toString().trim() : "",
email: this.checkNull(row[8] as any) ? row[8].toString().trim() : "",
address: this.checkNull(row[9] as any) ? row[9].toString().trim() : "",
gender: this.checkNull(row[5] as any) ? row[5].toString()[0].trim() : "",
pinCode: this.checkNull(row[10] as any) ? row[10].toString().trim() : "",
relationType: this.checkNull(row[11] as any) ? row[11].toString().trim() : "",
relativeName: this.checkNull(row[12] as any) ? row[12].toString().trim() : "",
relativeMobile: this.checkNull(row[13] as any) ? row[13].toString().trim() : "",
isMatchLocation: true,
isMatchRole: true,
isEmail: this.isEmail,
isAddress:this.whiteSpace
})
}
index++;
}
if (this.isUploadingPatientSheet) {
this.rawRecords = records;
this.rawPatientProcessed = records
this.threading.totalRecord = this.rawRecords.length;
this.fetchRelations();
setTimeout(() => {
this.onPatientSheet();
}, 1000)
}
this.loadingFile = false;
});
}, 1000);
}
onPatientSheet() {
this.rawPatientProcessed = new Array<any>();
this.rawRecords.forEach((patient) => {
let patientModel = {
umrNo: patient.umrNo,
salutation: patient.salutation,
firstName: patient.firstName,
lastName: patient.lastName,
mobile: patient.mobile,
dateOfBirth: patient.dateOfBirth,
age: patient.age,
email: patient.email,
address: patient.address,
pinCode: patient.pinCode,
relationType: patient.relationType,
gender: patient.gender,
relativeName: patient.relativeName,
relativeMobile: patient.relativeMobile,
isMatchRole: patient.isMatchRole,
isMatchLocation: patient.isMatchLocation,
isEmail: patient.isEmail
}
this.rawPatientProcessed.push(patientModel);
});
this.threading.totalRecord = this.rawPatientProcessed.length;
}
onThreadingPatientUpload(uploadId: number) {
if (this.isUploadingPatientSheet) {
//let checkEmail = this.rawPatientProcessed.filter(x => !(this.EmailFilter.test(x.email)));
let checkMobileValid = this.rawPatientProcessed.filter(x => !(this.mobileFilter.test(x.mobile)));
let checkAddress = this.rawPatientProcessed.filter(x => (this.whiteSpace.test(x.address)));
//let checkDOB = this.rawPatientProcessed.filter(x => (this.whiteSpace.test(x.dateOfBirth)));
let checkAge = this.rawPatientProcessed.filter(x => (this.whiteSpace.test(x.age)));
let checkDateFormat = this.rawPatientProcessed.filter(x => (this.dateFilter.test(x.dateOfBirth)));
this.rawPatientProcessed.forEach((item) => {
this.matchPatientRole(item);
this.httpService
.post<Array<Patient>>(ApiResources.getURI(ApiResources.patients.base, ApiResources.patients.fetch), {})
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<Patient>) => {
this.patients = response;
var res1 = this.patients.filter(x => x.email.toLowerCase().toString().trim() == item.email.toLowerCase().toString().trim());
var res = this.patients.filter(x => x.patientId == 6001)
if (res1.length > 0) {
this.flag = true;
}
if (res.length > 0) {
//return;
}
},
() => {
this.patients = [];
}
);
});
if (checkDateFormat.length > 0) {
this.notifyService.warning("Please enter valid Date of Birth format.");
return;
}
//if (checkDOB.length > 0) {
// this.notifyService.warning("Please enter valid Date of Birth.");
// return;
//}
if (checkAge.length > 0) {
this.notifyService.warning("Please enter valid Age.");
return;
}
if (checkAddress.length > 0) {
this.notifyService.warning("Please enter valid Address.");
return;
}
//if (checkEmail.length > 0) {
// this.notifyService.warning("Please enter valid Email.");
// return;
//}
if (checkMobileValid.length > 0) {
this.notifyService.warning("Please enter 10 digit valid Mobile number.");
return;
}
let findGender = this.rawPatientProcessed.filter(x => !UtilHelper.isEmpty(x.gender));
if (findGender.length > 0) {
this.notifyService.warning("Please fill gender field in <b>M</b> or <b>F</b>.");
return;
}
this.isUploading = true;
const record = this.rawPatientProcessed.splice(0, this.recordsPerThread);
this.threading.inUploading = record.length;
const request = {
patientExcelHistoryId: 0,
patients: record,
createdBy: this.page.userAccount.accountId,
roleId: this.page.userAccount.roleId,
sheetName: this.sheetName
};
if (uploadId > 0) {
this.threading.currentlyUploaded += this.threading.inUploading;
if (this.rawPatients.length === 0 && record.length === 0) {
this.isUploading = false;
this.fetchUploadHistory();
this.onCloseModal();
if (this.returnedData.length > 0) {
this.onOpenModel(this.templateReturnedData, "xl")
}
this.notifyService.successToast("Excel sheet uploaded successfully");
}
else if (this.rawPatients.length === 0 && record.length > 0) {
request["patientExcelHistoryId"] = uploadId;
this.onUploadPatientSheet(request);
}
else {
request["patientExcelHistoryId"] = uploadId;
this.onUploadPatientSheet(request);
}
}
else {
//this.checkEmail(request);
this.onUploadPatientSheet(request);
}
}
}
private onUploadPatientSheet(requestedData: any) {
this.submitting = true;
const request = requestedData;
request["roleId"] = this.page.userAccount.roleId;
request["uploadedByName"] = this.page.userAccount.fullName;
let url = ApiResources.getURI(ApiResources.patientImport.base, ApiResources.patientImport.addPatientSheet);
this.httpService
.post(url, request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitting = false))
.subscribe((response: ReturnTuples) => {
console.log(response.item2);
if (response.item2.length > 0) {
this.notifyService.warningToast("Data is already existed");
this.onCloseModal();
}
else {
this.returnedData = response.item1
this.onThreadingPatientUpload(response.item1 as number);
//return;
}
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
this.onCloseModal();
}
);
}
private fetchUploadedPatients() {
const request = this.selectedHistory;
this.httpService.post(ApiResources.getURI(ApiResources.patientImport.base, ApiResources.patientImport.fetchUplodedPatients), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.loadingPatients = false;
}))
.subscribe((response: Array<Patient>) => {
this.patient = response;
}, () => {
this.patient = new Array<Patient>();
this.notifyService.warning("Error occured while fetching products.");
});
}
onOpenPatientView(content: TemplateRef<any>, item: UserImportHistory) {
this.selectedHistory = item;
this.onOpenModel(content, "xxl");
this.fetchUploadedPatients();
}
onOpenModel(content: TemplateRef<any>, size: string) {
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: false,
size: size,
windowClass: "custom-modal effect-scale"
});
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
}
catch (e) {
//ignore;
}
this.sheetName = null;
this.loadingFile = false
this.selectedHistory = new UserImportHistory();
this.rawPatients = new Array<PatientRawImport>();
this.threading = new Threading();
this.rawRecords = new Array<any>();
this.isUploading = false;
this.rawPatientProcessed = new Array<any>();
}
onCloseDownloadModel() {
setTimeout(() => {
this.onCloseModal();
}, 500);
}
checkNull(values: string) {
if (values !== undefined)
if (values !== null) {
if (values !== "") {
return true;
} else {
return false;
}
} else
return false;
else {
return false;
}
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetchUploadHistory();
}
else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.page.unsubscribeAll();
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(chargeTemplate)"><i class="fe-plus mr-1"></i> Add </button>
</div>
<h4 class="page-title">Patient Registration Charges</h4>
</div>
</div>
<div class="col-12">
<div class="card-box p-0">
<div class="row p-2" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading ...</span>
</div>
</div>
</div>
<div class="row p-2" *ngIf="!loading && (!records || !records.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(chargeTemplate)"><i class="fe-plus mr-1"></i> Add </button>
</div>
</div>
</div>
<div class="table-responsive" *ngIf="!loading && records.length > 0">
<table class="table table-sm">
<thead class="table-info">
<tr>
<th>Charge</th>
<th>CreatedBy</th>
<th>Created Date</th>
<th>Modified By</th>
<th>Modified Date</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of records;index as i;">
<td>
<span [textContent]="item.charge | currency:'INR'"></span>
</td>
<td>
<h5 class="font-13 mb-0" [textContent]="item.createdByName"></h5>
<span class="badge badge-outline-info font-11" [textContent]="item.createdByRole"></span>
</td>
<td>
<span [textContent]="item.createdDate | date:'dd-MM-yyyy, hh:mm a'"></span>
</td>
<td>
<div *ngIf="item.modifiedBy">
<h5 class="font-13 mb-0" [textContent]="item.modifiedByName"></h5>
<span class="badge badge-outline-secondary font-11" [textContent]="item.modifiedByRole"></span>
</div>
<span *ngIf="!item.modifiedBy">-----</span>
</td>
<td>
<span *ngIf="item.modifiedDate" [textContent]="item.modifiedDate | date:'dd-MM-yyyy, hh:mm a'"></span>
<span *ngIf="!item.modifiedDate">----</span>
</td>
<td>
<span *ngIf="!item.active" class="badge badge-outline-secondary">Not in use</span>
<span *ngIf="item.active" class="badge badge-outline-success">In Use</span>
</td>
<td>
<div class="d-flex align-items-center justify-content-end">
<a href="javascript:;" class="action-icon text-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenModel(chargeTemplate, item)"><i class="fe-edit"></i></a>
<a href="javascript:;" *ngIf="!item.active" class="action-icon text-danger" placement="left" ngbTooltip="Apply" (click)="onApply(item)"><i class="mdi mdi-check"></i></a>
</div>
</td>
</tr>
</tbody>
<!--<tfoot>
<tr>
<td colspan="7">
<nav class="d-flex align-items-center justify-content-between">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - records.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> Records )</span>
</span>
</p>
<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="true" [ellipses]="true" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>
</nav>
</td>
</tr>
</tfoot>-->
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #chargeTemplate>
<form [formGroup]="chargeForm" (ngSubmit)="onSubmit()">
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-account-cash-outline mr-1"></i>{{chargeForm.value.patientRegistrationChargeId === 0 ? 'Add' : 'Edit'}} Registration Charge</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-12">
<div class="form-group">
<label class="mb-1">Charge <code>*</code></label>
<input type="number" min="0" class="form-control" placeholder="Enter amount." formControlName="charge"
[ngClass]="{ 'is-invalid': submitted && form.charge.errors }" />
<div class="text-danger" *ngIf="submitted && form.charge.errors">
<p *ngIf="form.charge.errors.required">Charge Name is required.</p>
<p *ngIf="form.charge.errors.min">Minimum value must be 1.</p>
</div>
</div>
</div>
<div *ngIf="chargeForm.value.patientRegistrationChargeId === 0" class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1">Charge Type <code>*</code></label>
<select class="form-control custom-select" formControlName="chargeCategoryId" autocomplete="nope" [ngClass]="{ 'is-invalid': submitted && form.chargeCategoryId.errors }">
<option [ngValue]="null">Select Charge Type</option>
<option *ngFor="let item of chargeType" [textContent]="item.name" [ngValue]="item.id"></option>
</select>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
\ No newline at end of file
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, Validators, FormBuilder } from "@angular/forms";
import { Page, IUserAccount, Pagination, IResource } from "@shared/models";
import { AppData, HttpService, NotifyService, ResourceService } from "@shared/services";
import { finalize, takeUntil } from "rxjs/operators";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { HttpErrorResponse } from "@angular/common/http";
class PatientChargeModel {
patientRegistrationChargeId: number;
charge: number;
locationId: number;
active: boolean;
createdBy: number;
createdDate: Date;
modifiedBy?: number;
modifiedDate?: Date;
createdByName: string;
createdByRole: string;
modifiedByName: string;
modifiedByRole: string;
totalItems: number;
chargeCategoryId: number;
}
@Component({
templateUrl: "./patient-registration.html",
encapsulation: ViewEncapsulation.None
})
export class PatientRegistrationChargePage implements OnInit, OnDestroy {
page: Page;
pagination: Pagination;
loading: boolean;
modalRef: NgbModalRef;
submitting: boolean;
submitted: boolean;
chargeForm: FormGroup;
records: Array<PatientChargeModel>;
chargeType: IResource[];
constructor(
private readonly appData: AppData,
private readonly httpService: HttpService,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly resourceService: ResourceService
) {
this.loading = true;
this.page = new Page();
this.records = new Array<PatientChargeModel>();
this.initPagination();
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
private buildForm() {
this.chargeForm = this.formBuilder.group({
patientRegistrationChargeId: 0,
charge: [null, [Validators.required, Validators.min(1)]],
chargeCategoryId: [null, Validators.required]
});
}
get form() { return this.chargeForm.controls; }
onSubmit() {
this.submitted = true;
if (this.chargeForm.invalid) {
return;
}
this.submitting = true;
const request = {
...this.chargeForm.getRawValue(),
createdBy: this.page.userAccount.accountId,
loginRoleId: this.page.userAccount.roleId,
createdByName: this.page.userAccount.fullName
};
this.httpService.post(ApiResources.getURI(ApiResources.patients.base, ApiResources.patients.modifyRegistrationCharge), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitted = this.submitting = false))
.subscribe(
(response: number) => {
if (response > 0) {
this.notifyService.successToast(`Record ${request["patientRegistrationChargeId"] > 0 ? 'updated' : 'added'} successfully.`);
}
if (response === -1) {
this.notifyService.warningToast("Given Charge already exists.");
return;
}
this.onCloseModal();
this.fetchAll();
},
(error: HttpErrorResponse) => {
this.onError(error);
}
);
}
private fetchAll() {
this.loading = true;
const request = { ...this.pagination };
this.httpService.post(ApiResources.getURI(ApiResources.patients.base, ApiResources.patients.fetchRegistrationCharge), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<PatientChargeModel>) => {
this.records = response;
},
(error: HttpErrorResponse) => {
this.onError(error)
}
);
}
private fetchChargeCategory() {
this.resourceService.chargeCategory()
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.chargeType = response;
if (this.chargeType.length > 0) {
const patientRegistrationCharge = this.chargeType.filter(m => m.name.toLowerCase() === 'patient registration')
this.chargeType = patientRegistrationCharge;
}
});
}
onNextPage() {
this.fetchAll();
}
private onError(error: HttpErrorResponse) {
if (error) {
this.notifyService.errorToast(UtilHelper.handleError(error));
}
}
onApply(record: PatientChargeModel) {
this.notifyService.confirm("you want to apply this charge",() => {
const request = {
id: record.patientRegistrationChargeId
};
this.httpService.get(ApiResources.getURI(ApiResources.patients.base, ApiResources.patients.applyRegistrationCharge), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: number) => {
if (response > 0) {
this.notifyService.successToast("Record applied successfully.");
}
if (response === -3) {
this.notifyService.warningToast("The record you tried to delete can't be deleted because it is being used.");
}
this.fetchAll();
},
(error: HttpErrorResponse) => {
this.onError(error)
}
);
})
}
onOpenModel(content: TemplateRef<any>, record?: PatientChargeModel) {
this.buildForm();
this.fetchChargeCategory();
if (record) {
this.chargeForm.patchValue({
patientRegistrationChargeId: record.patientRegistrationChargeId,
charge: record.charge,
chargeCategoryId: record.chargeCategoryId
});
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: false,
windowClass: "custom-modal effect-scale"
});
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.loading = false;
this.submitting = undefined;
this.submitted = undefined;
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetchAll();
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateAdd)"><i class="fe-plus mr-1"></i> Add PayType</button>
</div>
<h4 class="page-title">Pay Category</h4>
</div>
</div>
</div>
<div>
<div class="card-box mb-1 p-1 pb-2">
<div class="col-lg-12">
<div class="row">
<div class="col-6 col-md-4 col-lg-4 col-xl-2">
<div class="form-group mb-0">
<label class="mb-1">Pay Category </label>
<ng-select class="ng-select-sm text-uppercase" [items]="payCategoryNames"
bindLabel="value"
bindValue="id"
autocomplete="nope"
placeholder="Select PayCategory"
[(ngModel)]="filters.options.payCategoryId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No Pay Category found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</div>
<div class="col-6 col-md-4 col-lg-4 col-xl-2">
<div class="form-group mb-0">
<label class="mb-1">Status</label>
<select class="form-control form-control-md" [(ngModel)]="filters.options.active">
<option [ngValue]="null">All</option>
<option [ngValue]="true">Active</option>
<option [ngValue]="false">Inactive</option>
</select>
</div>
</div>
<div class="col-12 col-lg-4 col-md-4 col-xl-2 d-flex justify-content-center ">
<div class="align-items-center d-flex justify-content-center justify-content-lg-start mb-0 w-100 marTop767size">
<button type="button" (click)="onApplyFilters()" class="btn btn-sm btn-outline-primary mb-0">Search</button>
<button type="button" (click)="onResetFilters()" class="btn btn-sm btn-outline-danger ml-1 mb-0">Reset</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading pay categories ...</span>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && (!paycategories || !paycategories.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<!-- <h4 class="title">Oops! No roles found<span *ngIf="filters.applied"> based on your filters criteria</span>.</h4>-->
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateAdd)"><i class="fe-plus mr-1"></i> Add PayType</button>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && paycategories && paycategories.length">
<div class="col-12">
<div class="card mb-0">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-centered table-sm table-striped table-borderless">
<thead>
<tr>
<th>Pay Categories</th>
<th>Created By</th>
<th>Created Date</th>
<th>Modified By</th>
<th>Modified Date</th>
<th>Status</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of paycategories;">
<td [textContent]="item.payCategoryName"></td>
<td [textContent]="item.createdByName || '--'"></td>
<td [textContent]="item.createdDate | date: 'dd/MM/yyyy'"></td>
<td [textContent]="item.modifiedByName || '--'"></td>
<td [textContent]="item.modifiedDate | date: 'dd/MM/yyyy' || '--' "></td>
<td>
<div class="media">
<span class="badge badge-success" *ngIf="item.active">Active</span>
<span class="badge badge-soft-danger" *ngIf="!item.active">Inactive</span>
</div>
</td>
<td>
<div class="d-flex align-items-center justify-content-end">
<button *ngIf="item.active" type="button" class="btn btn-xs btn-outline-blue mr-1" ngbTooltip="Edit" (click)="onOpenModel(templateAdd,item)">
<i class="fe-edit"></i>
</button>
<button type="button" class="btn btn-xs btn-outline-success" *ngIf="item.active == true" title="Active" (click)="onModifyStatus(item,false)">
<i class="fe-delete"></i>
</button>
<button type="button" class="btn btn-xs btn-outline-danger" *ngIf="item.active == false" title="Inactive" (click)="onModifyStatus(item,true)">
<i class="fe-check"></i>
</button>
</div>
</td>
<td></td>
</tr>
</tbody>
</table>
</div>
<nav class="d-flex align-items-center justify-content-between p-2" *ngIf="pagination.totalPages > 1">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - paycategories.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> pay categories )</span>
</span>
</p>
<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateAdd>
<div class="modal-header">
<h4 class="modal-title">Pay Category</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<form [formGroup]="payForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1">Pay Category <code>*</code></label>
<input type="text" autofocus formControlName="payCategoryName" textOnly maxlength="100" autocomplete="nope" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.payCategoryName.errors) }" placeholder="Enter New Pay Category" />
<div *ngIf="submitted && form.payCategoryName.errors" class="invalid-feedback">
<span *ngIf="form.payCategoryName.errors.required">Pay Category name is required</span>
<span *ngIf="form.payCategoryName.errors.minlength">Name minimum 2 words required</span>
<span *ngIf="form.payCategoryName.errors.whiteSpaces">Don't enter space</span>
<span *ngIf="alreadyExists"> <b></b> has already been exist</span>
</div>
</div>
<div class="alert alert-solid alert-danger mg-b-0 mg-t-20" role="alert" *ngIf="alreadyExists">
<h6 class="alert-heading"> conflict!</h6>
<hr />
The Given Category has already been exists with the same <strong>PayCategory name</strong>.
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
\ No newline at end of file
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { PayTypes, PayCategory } from "@shared/entities";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService, ResourceService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { Page, IUserAccount, Pagination, IResource } from "@shared/models";
//import { HttpErrorResponse } from "@angular/common/http";
import { FormGroup, Validators, FormBuilder } from "@angular/forms";
import { NgbModalRef, NgbModal } from "@ng-bootstrap/ng-bootstrap";
import { HttpErrorResponse } from "@angular/common/http";
import { WhiteSpaceValidator } from "../../../../../shared/validators";
class FilterOptions {
payCategoryId: number = null;
active?: boolean = null;
}
class Filters {
options: FilterOptions;
applied: boolean;
constructor() {
this.init();
}
init() {
this.options = new FilterOptions();
this.applied = undefined;
}
}
@Component({
templateUrl: "./pay-categories.html",
encapsulation: ViewEncapsulation.None
})
export class PayCategoryPage implements OnInit, OnDestroy {
page: Page;
pagination: Pagination;
filters: Filters;
loading: boolean;
paycategories: Array<PayCategory>;
payForm: FormGroup;
selected: PayTypes
modalRef: NgbModalRef;
payCategoryNames: Array<IResource>;
submitting: boolean;
submitted: boolean;
alreadyExists: boolean;
constructor(
private readonly appData: AppData,
private readonly httpService: HttpService,
private readonly notifyService: NotifyService,
private readonly formBuilder: FormBuilder,
private readonly modalService: NgbModal,
private readonly resourceService: ResourceService
) {
this.loading = true;
this.page = new Page();
this.filters = new Filters();
this.initPagination();
}
private buildForm() {
this.payForm = this.formBuilder.group({
payCategoryId: 0,
payCategoryName: [null, [Validators.required, Validators.minLength(2), WhiteSpaceValidator.isValid]],
})
this.payForm.get("payCategoryName").valueChanges.subscribe((value: string) => { if (value) { this.alreadyExists = false } });
}
get form() {
return this.payForm.controls;
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
private fetchPayCats() {
this.loading = true;
const request = Object.assign(UtilHelper.clone(this.filters.options), UtilHelper.clone(this.pagination));
this.httpService.post<Array<PayCategory>>(ApiResources.getURI(ApiResources.payCategories.base, ApiResources.payCategories.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe((response: Array<PayCategory>) => {
this.paycategories = response;
UtilHelper.applyPagination(this.paycategories, this.pagination);
});
}
private fetchpayCategoryNames() {
this.resourceService.payCategories()
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.payCategoryNames = response;
});
}
onSubmit() {
this.submitted = true;
if (this.payForm.invalid) {
return;
}
this.submitting = true;
const request = this.payForm.getRawValue()
request["createdBy"] = this.page.userAccount.accountId
request["modifiedBy"] = this.page.userAccount.accountId
request["loginRoleId"] = this.page.userAccount.roleId
request["createdByName"] = this.page.userAccount.fullName,
request["modifiedByName"] = this.page.userAccount.fullName
var url = ApiResources.getURI(ApiResources.payCategories.base, ApiResources.payCategories.insert);
if (request["payCategoryId"] > 0) {
url = ApiResources.getURI(ApiResources.payCategories.base, ApiResources.payCategories.update);
}
this.httpService.post(url, request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitted = this.submitting = false))
.subscribe(
(response: number) => {
if (response > 0) {
this.notifyService.successToast(`Record ${request["payCategoryId"] > 0 ? 'updated' : 'added'} successfully.`);
}
this.onCloseModal();
this.fetchpayCategoryNames();
this.fetchPayCats();
},
(error: HttpErrorResponse) => {
if (error.status === 409) {
this.alreadyExists = true;
}
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
}
);
}
onModifyStatus(item: PayCategory, status: boolean) {
this.notifyService.confirm(`You want to ${status ? 'Activate' : 'Deactivate'} this Pay Category?`, () => {
const request = {
modifiedBy: this.page.userAccount.accountId,
active: status,
payCategoryId: item.payCategoryId,
payCategoryName: item.payCategoryName,
loginRoleId: this.page.userAccount.roleId,
modifiedByName: this.page.userAccount.fullName
};
this.httpService.post(ApiResources.getURI(ApiResources.payCategories.base, ApiResources.payCategories.modifyPayTypeStatus), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loading = false }))
.subscribe((response: number) => {
if (response > 0) {
this.notifyService.successToast(`${status ? 'Activated' : 'Deactivated'} successfully.`);
}
this.fetchPayCats();
}, (error: HttpErrorResponse) => {
this.notifyService.errorToast(error.error);
});
});
}
onOpenModel(content: TemplateRef<any>, item?: PayCategory) {
this.buildForm();
if (item) {
this.payForm.patchValue({
payCategoryId: item.payCategoryId,
payCategoryName: item.payCategoryName,
});
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetchPayCats();
}
onApplyFilters() {
this.filters.applied = UtilHelper.isFiltersApplied(this.filters.options);
this.initPagination();
this.loading = true;
this.fetchPayCats();
this.onCloseFilters();
}
onResetFilters() {
this.filters.init();
this.loading = true;
this.fetchPayCats();
this.onCloseFilters();
}
onCloseFilters() {
$("body").removeClass("right-bar-enabled");
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetchpayCategoryNames();
this.fetchPayCats();
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.page.unsubscribeAll();
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateAdd)"><i class="fe-plus mr-1"></i> Add PayType</button>
</div>
<h4 class="page-title">PayTypes</h4>
</div>
</div>
</div>
<div class="col-12 p-0">
<div class="card-box mb-1 p-1">
<table class="table table-borderless table-sm mb-0">
<tr class="myFlex">
<td class="col-6 col-md-3">
<div class="form-group mb-0">
<label class="mb-1">Pay Type Name </label>
<ng-select class="ng-select-sm text-uppercase" [items]="dropdownPaytypes"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select Name"
[(ngModel)]="filters.options.payTypeId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No Name found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</td>
<td class="col-6 col-md-3">
<div class="form-group mb-0">
<label class="mb-1"> Value </label>
<ng-select class="ng-select-sm text-uppercase" [items]="dropdownPaytypes"
bindLabel="value"
bindValue="value"
autocomplete="nope"
placeholder="Select value"
[(ngModel)]="filters.options.payTypeValue">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No Value found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</td>
<td class="col-6 col-md-3">
<div class="form-group mb-0">
<label class="mb-1">Salucro</label>
<select class="form-control form-control-md" [(ngModel)]="filters.options.salucroPayType">
<option [ngValue]="null">All</option>
<option [ngValue]="true">True</option>
<option [ngValue]="false">False</option>
</select>
</div>
</td>
<td class="col-6 col-md-3">
<div class="form-group mb-0">
<label class="mb-1">Status</label>
<select class="form-control form-control-md" [(ngModel)]="filters.options.isActive">
<option [ngValue]="null">All</option>
<option [ngValue]="true">Active</option>
<option [ngValue]="false">Inactive</option>
</select>
</div>
</td>
<td class="col-12 align-middle">
<div class="d-flex justify-content-center lessThan1468 flex-grow-1">
<button type="button" (click)="onApplyFilters()" class="btn btn-sm btn-outline-primary mb-0">Search</button>
<button type="button" (click)="onResetFilters()" class="btn btn-sm btn-outline-danger ml-1 mb-0">Reset</button>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading paytypes ...</span>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && (!paytypes || !paytypes.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<!-- <h4 class="title">Oops! No roles found<span *ngIf="filters.applied"> based on your filters criteria</span>.</h4>-->
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateAdd)"><i class="fe-plus mr-1"></i> Add PayType</button>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && paytypes && paytypes.length">
<div class="col-12">
<div class="card mb-0">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-centered table-sm table-striped table-borderless">
<thead>
<tr>
<th>PayTypes</th>
<th>PayType Value</th>
<th>Is Salucro</th>
<th>Status</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of paytypes;">
<td [textContent]="item.payTypeName"></td>
<td [textContent]="item.payTypeValue"></td>
<td>
<div class="media">
<span class="badge badge-light" *ngIf="item.salucroPayType">True</span>
<span class="badge badge-light" *ngIf="!item.salucroPayType">False</span>
</div>
</td>
<td>
<div class="media">
<span class="badge badge-success" *ngIf="item.isActive">Active</span>
<span class="badge badge-soft-danger" *ngIf="!item.isActive">Inactive</span>
</div>
</td>
<td>
<div class="d-flex align-items-center justify-content-end">
<button *ngIf="item.isActive" type="button" class="btn btn-xs btn-outline-blue mr-1" ngbTooltip="Edit" (click)="onOpenModel(templateAdd,item)">
<i class="fe-edit"></i>
</button>
<button type="button" class="btn btn-xs btn-outline-danger" *ngIf="item.isActive" ngbTooltip="To DeActivate" (click)="onModifyStatus(item,false)">
<i class="fe-delete"></i>
</button>
<button type="button" class="btn btn-xs btn-outline-success" *ngIf="!item.isActive" ngbTooltip="To Activate" (click)="onModifyStatus(item,true)">
<i class="fe-check"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<nav class="d-flex align-items-center justify-content-between p-2" *ngIf="pagination.totalPages > 1">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - paytypes.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> pay types )</span>
</span>
</p>
<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateAdd>
<div class="modal-header">
<h4 class="modal-title">Pay Type</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<form [formGroup]="payTypeForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1">Pay Type <code>*</code></label>
<div class="form-group">
<input type="text" autofocus textOnly formControlName="payTypeName" autocomplete="nope" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.payTypeName.errors) }" placeholder="Enter New Payment mode" />
<div class="text-danger" *ngIf="submitted && form.payTypeName.errors">
<p *ngIf="form.payTypeName.errors.required">PayType Name is required.</p>
<p *ngIf="form.payTypeName.errors.whiteSpaces">Please remove white space...</p>
</div>
<label class="mb-1">Pay Type Value</label>
<div class="form-group">
<input type="text" formControlName="payTypeValue" autocomplete="nope" class="form-control" />
</div>
<div>
<input type="checkbox" formControlName="salucroPayType" />Is Salucro applicable
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
\ No newline at end of file
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { PayTypes } from "@shared/entities";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService, ResourceService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { Page, IUserAccount, Pagination, IResource } from "@shared/models";
import { HttpErrorResponse } from "@angular/common/http";
import { FormBuilder, Validators, FormGroup, FormControl } from "@angular/forms";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { WhiteSpaceValidator } from "../../../../../shared/validators";
class FilterOptions {
payTypeId: number = null;
payTypeName: string = null;
payTypeValue: string = null;
salucroPayType: boolean = null;
isActive: boolean = null;
}
class Filters {
options: FilterOptions;
applied: boolean;
constructor() {
this.init();
}
init() {
this.options = new FilterOptions();
this.applied = undefined;
}
}
@Component({
templateUrl: "./pay-type.html",
encapsulation: ViewEncapsulation.None
})
export class PayTypePage implements OnInit, OnDestroy {
page: Page;
pagination: Pagination;
loading: boolean;
paytypes: Array<PayTypes>;
dropdownPaytypes: Array<IResource>;
payTypeForm: FormGroup;
selected: PayTypes
modalRef: NgbModalRef;
filters: Filters;
submitting: boolean;
submitted: boolean;
salucroPayType: boolean;
constructor(
private readonly appData: AppData,
private readonly httpService: HttpService,
private readonly notifyService: NotifyService,
private readonly formBuilder: FormBuilder,
private readonly modalService: NgbModal,
private readonly resourceService: ResourceService
) {
this.loading = true;
this.page = new Page();
this.filters = new Filters();
this.initPagination();
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
private buildForm() {
this.payTypeForm = this.formBuilder.group({
payTypeId: new FormControl(null),
payTypeName: [null, [Validators.required, WhiteSpaceValidator.isValid]],
payTypeValue: [null],
salucroPayType: new FormControl(false)
})
}
get form() {
return this.payTypeForm.controls;
}
private fetchPayTypes() {
this.loading = true;
const request = {
...this.pagination,
...this.filters.options
};
console.log(request);
this.httpService.post(ApiResources.getURI(ApiResources.payTypes.base, ApiResources.payTypes.fetch),request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe((response: Array<PayTypes>) => {
this.paytypes = response;
UtilHelper.applyPagination(this.paytypes, this.pagination);
});
}
private filterPayTypes() {
this.resourceService.allPayTypes(false)
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.dropdownPaytypes = response;
});
}
onSubmit() {
//debugger;
this.submitted = true;
if (this.payTypeForm.invalid) {
return;
}
this.submitting = true;
const request = {
...this.payTypeForm.getRawValue(),
createdBy: this.page.userAccount.accountId,
loginRoleId: this.page.userAccount.roleId,
createdByName: this.page.userAccount.fullName,
modifiedBy: this.page.userAccount.accountId,
modifiedByName: this.page.userAccount.fullName,
};
// alert(JSON.stringify(this.payTypeForm.value))
//alert(JSON.stringify(request))
var url = ApiResources.getURI(ApiResources.payTypes.base, ApiResources.payTypes.insert);
if (request["payTypeId"] > 0) {
url = ApiResources.getURI(ApiResources.payTypes.base, ApiResources.payTypes.update);
}
this.httpService.post(url, request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitted = this.submitting = false))
.subscribe(
(response: number) => {
if (response > 0) {
this.notifyService.successToast(`Record ${request["payTypeId"] > 0 ? 'updated' : 'added'} successfully.`);
}
if (response === -1) {
this.notifyService.warningToast("This Pay Type Name already exists.");
return;
}
this.onCloseModal();
this.filterPayTypes();
this.fetchPayTypes();
},
(error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warningToast(errorMessage);
} else {
this.notifyService.defaultErrorToast();
}
}
);
}
onModifyStatus(item: PayTypes, status: boolean) {
this.notifyService.confirm(`You want to ${status ? 'Activate' : 'Deactivate'} this pay type?`, () => {
const request = {
createdBy: this.page.userAccount.accountId,
loginRoleId: this.page.userAccount.roleId,
createdByName: this.page.userAccount.fullName,
modifiedBy: this.page.userAccount.accountId,
modifiedByName: this.page.userAccount.fullName,
isActive: status,
payTypeId: item.payTypeId,
payTypeName: item.payTypeName,
payTypeValue: item.payTypeValue,
salucroPayType: item.salucroPayType
};
this.httpService.post(ApiResources.getURI(ApiResources.payTypes.base, ApiResources.payTypes.modifyPayTypeStatus), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loading = false }))
.subscribe((response: number) => {
if (response > 0) {
this.notifyService.successToast(`${status ? 'Activated' : 'Deactivated'} successfully.`);
}
this.filterPayTypes();
this.fetchPayTypes();
}, (error: HttpErrorResponse) => {
this.notifyService.errorToast(error.error);
});
});
}
onOpenModel(content: TemplateRef<any>, item?: PayTypes) {
this.buildForm();
if (item) {
this.payTypeForm.patchValue({
payTypeId: item.payTypeId,
payTypeName: item.payTypeName,
payTypeValue: item.payTypeValue,
salucroPayType: item.salucroPayType
});
this.payTypeForm.get("payTypeValue").disable();
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
}
//public onSalicroChanged(value: boolean) {
// console.log()
// this.salucroPayType = value;
//}
onApplyFilters() {
this.filters.applied = UtilHelper.isFiltersApplied(this.filters.options);
this.initPagination();
this.loading = true;
this.fetchPayTypes();
this.onCloseFilters();
}
onResetFilters() {
this.filters.init();
this.loading = true;
this.fetchPayTypes();
this.onCloseFilters();
}
onCloseFilters() {
$("body").removeClass("right-bar-enabled");
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetchPayTypes();
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.filterPayTypes();
this.fetchPayTypes();
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.page.unsubscribeAll();
}
}
\ No newline at end of file

<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(doctorChargeTemplate)"><i class="fe-plus mr-1"></i> Add </button>
</div>
<h4 class="page-title">Doctor Schedule Charges</h4>
</div>
</div>
<div class="col-12 p-0">
<div class="card-box mb-1 p-1" style="font-size: 12px;">
<div class="row p-2" >
<div class="col-lg-1 col-md-3 col-sm-4 col-xl-1 min-width200px p-1">
<label class="mb-1">Locations<code>*</code></label>
<ng-select class="ng-select-sm" [items]="locations"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select locations"
[(ngModel)]="filters.options.locationId"
(change)="onChangeFilterLocation($event)">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No locations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
<div class="col-lg-1 col-md-3 col-sm-4 col-xl-1 min-width180px p-1">
<label class="mb-1">From Date</label>
<input class="form-control date-picker" type="text" block placeholder="Select from date" [(ngModel)]="filters.options.fromDate" readonly autocomplete="nope" ngbDatepicker #fromDate="ngbDatepicker" (click)="fromDate.toggle(); $event.stopPropagation();" (dateSelect)="getMinDate()">
</div>
<div class="col-lg-1 col-md-3 col-sm-4 col-xl-1 min-width150px p-1">
<label class="mb-1">To Date</label>
<input class="form-control date-picker" type="text" block placeholder="Select to date" [(ngModel)]="filters.options.toDate" readonly autocomplete="nope" ngbDatepicker #toDate="ngbDatepicker" (click)="toDate.toggle(); $event.stopPropagation();" [minDate]="setMinDate" (dateSelect)="getMaxDate()">
</div>
<div class="col-lg-2 col-md-3 col-sm-4 col-xl-2 min-width200px p-1">
<label class="mb-1">Doctor</label>
<select class="form-control custom-select" (keyup.enter)="onApplyFilters()" autocomplete="nope" [(ngModel)]="filters.options.providerId" (click)="providerChange()">
<option [ngValue]="null" *ngIf="!loadingproviderResources">All</option>
<option selected *ngIf="loadingproviderResources">Loading...</option>
<option *ngFor="let item of providerResources" [textContent]="item.value" [ngValue]="item.id"></option>
</select>
</div>
<div class="col-lg-1 col-md-3 col-sm-4 col-xl-1 p-1" style="min-width: 160px;">
<label class="mb-1">Specialization</label>
<select class="form-control custom-select" (keyup.enter)="onApplyFilters()" autocomplete="nope" [(ngModel)]="filters.options.specializationId">
<option [ngValue]="null" *ngIf="!loadingSpecializationResources">All</option>
<option selected *ngIf="loadingSpecializationResources">Loading...</option>
<option *ngFor="let item of specializationResources; trackBy:trackBy.resource" [textContent]="item.value" [ngValue]="item.id"></option>
</select>
</div>
<div class="col-lg-1 col-md-3 col-sm-4 col-xl-1 min-width200px p-1">
<label class="mb-1">Consultation Type </label>
<select class="form-control custom-select" (keyup.enter)="onApplyFilters()" autocomplete="nope" [(ngModel)]="filters.options.consultationTypeId">
<option [ngValue]="null" *ngIf="!loadingconsultationTypes">All</option>
<option selected *ngIf="loadingconsultationTypes">Loading...</option>
<option *ngFor="let item of consultationType; trackBy:trackBy.resource" [textContent]="item.value" [ngValue]="item.id"></option>
</select>
</div>
<div class="col-5 col-lg-1 col-md-3 col-sm-4 col-xl-1 min-width120px p-1" style="margin-top: -3px;">
<label class="mb-1 font-13">Status</label>
<select class="form-control custom-select" autocomplete="nope" [(ngModel)]="filters.options.active">
<option [ngValue]="true">Active</option>
<option [ngValue]="false">InActive</option>
</select>
</div>
<div style="min-width: 180px; margin-top: 25px;" class="col-6 col-lg-2 col-md-3 col-sm-4 col-xl-1 p-1">
<button type="button" (click)="onApplyFilters()" class="btn btn-sm btn-outline-primary">Search</button>
<button type="button" (click)="onResetFilters()" class="btn btn-sm btn-outline-danger ml-1">Reset</button>
</div>
</div>
<!--<table class="table table-borderless table-sm mb-0">
<tr style="font-size:12px;" class="myFlex">-->
<!--<td class="col-6 col-md-3">
<div class="form-group mb-0" style="font-size:12px;">-->
<!--<td class="col-6 col-sm-4 col-xl-2">
<div class="form-group mb-0">
<label class="mb-1">Locations<code>*</code></label>
<ng-select class="ng-select-sm" [items]="locations"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select locations"
[(ngModel)]="filters.options.locationId"
(change)="onChangeFilterLocation($event)">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No locations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</td>
<td class="min-width150px">
<div class="form-group mb-0">
<label class="mb-1">From Date</label>-->
<!--[minDate]="setMaxDate"-->
<!--<input class="form-control date-picker" type="text" block placeholder="Select from date" [(ngModel)]="filters.options.fromDate" readonly autocomplete="nope" ngbDatepicker #fromDate="ngbDatepicker" (click)="fromDate.toggle(); $event.stopPropagation();" (dateSelect)="getMinDate()">-->
<!--<input class="form-control date-picker" type="text" block placeholder="Select from date" [(ngModel)]="filters.options.fromDate" readonly autocomplete="nope" ngbDatepicker #fromDate="ngbDatepicker" (click)="fromDate.toggle(); $event.stopPropagation();" (dateSelect)="getMinDate()">
</div>
</td>-->
<!--<td class="col-6 col-md-3">
<div class="form-group mb-0 position-relative" style="font-size:12px;">-->
<!--<td class="min-width150px">
<div class="form-group mb-0">
<label class="mb-1">To Date</label>
<input class="form-control date-picker" type="text" block placeholder="Select to date" [(ngModel)]="filters.options.toDate" readonly autocomplete="nope" ngbDatepicker #toDate="ngbDatepicker" (click)="toDate.toggle(); $event.stopPropagation();" [minDate]="setMinDate" (dateSelect)="getMaxDate()">-->
<!--<input class="form-control date-picker" type="text" block placeholder="Select to date" [(ngModel)]="filters.options.toDate" readonly autocomplete="nope" ngbDatepicker #toDate="ngbDatepicker" (click)="toDate.toggle(); $event.stopPropagation();" [minDate]="setMinDate" (dateSelect)="getMaxDate()">-->
<!--</div>
</td>
<td style="width:14%;">
<div class="form-group mb-0">
<label class="mb-1">Doctor</label>
<select class="form-control custom-select" (keyup.enter)="onApplyFilters()" autocomplete="nope" [(ngModel)]="filters.options.providerId" (click)="providerChange()">
<option [ngValue]="null" *ngIf="!loadingproviderResources">All</option>
<option selected *ngIf="loadingproviderResources">Loading...</option>-->
<!--specializationName-->
<!--<option *ngFor="let item of providerResources" [textContent]="item.value" [ngValue]="item.id"></option>-->
<!--<option *ngFor="let item of providerSchedulerCharges; trackBy:trackBy.resource" [textContent]="item.providerName" [ngValue]="item.providerId"></option>-->
<!--</select>
</div>
</td>
<td style="width:14%;">
<div class="form-group mb-0">
<label class="mb-1">Specialization</label>
<select class="form-control custom-select" (keyup.enter)="onApplyFilters()" autocomplete="nope" [(ngModel)]="filters.options.specializationId">
<option [ngValue]="null" *ngIf="!loadingSpecializationResources">All</option>
<option selected *ngIf="loadingSpecializationResources">Loading...</option>
<option *ngFor="let item of specializationResources; trackBy:trackBy.resource" [textContent]="item.value" [ngValue]="item.id"></option>-->
<!--<option *ngFor="let item of providerSchedulerCharges; trackBy:trackBy.resource" [textContent]="item.specializationName" [ngValue]="item.specializationId"></option>-->
<!--</select>
</div>
</td>
<td style="width:14%;">
<div class="form-group mb-0">
<label class="mb-1">Consultation Type </label>-->
<!--<ng-select class="ng-select-sm text-uppercase" [items]="consultationType"
bindLabel="value"
bindValue="id"
autocomplete="nope"
placeholder="Select Consultation Type"
[ngClass]="{ 'is-invalid': submitted && forms.form.consultationTypeId.errors }"
formControlName="consultationTypeId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No Consultation Type found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>-->
<!--<select class="form-control custom-select" (keyup.enter)="onApplyFilters()" autocomplete="nope" [(ngModel)]="filters.options.consultationTypeId">
<option [ngValue]="null" *ngIf="!loadingconsultationTypes">All</option>
<option selected *ngIf="loadingconsultationTypes">Loading...</option>
<option *ngFor="let item of consultationType; trackBy:trackBy.resource" [textContent]="item.value" [ngValue]="item.id"></option>-->
<!--<option *ngFor="let item of providerSchedulerCharges; trackBy:trackBy.resource" [textContent]="item.specializationName" [ngValue]="item.specializationId"></option>-->
<!--</select>
</div>
</td>
<td class="col-4 col-sm-4 col-lg-2">
<div class="form-group">
<label class="mb-1 font-13">Status</label>
<select class="form-control custom-select" autocomplete="nope" [(ngModel)]="filters.options.active">
<option [ngValue]="true">Active</option>
<option [ngValue]="false">InActive</option>
</select>
</div>
</td>
<td class="col-6 col-sm-4 col-lg-2">
<div style="margin-top: 25px;">
<button type="button" (click)="onApplyFilters()" class="btn btn-sm btn-outline-primary">Search</button>
<button type="button" (click)="onResetFilters()" class="btn btn-sm btn-outline-danger ml-1">Reset</button>
</div>
</td>-->
<!--<td>
<div class="col-6">
<div class="form-group">
<label class="mb-1">Doctor <code>*</code></label>
<ng-select [autofocus]="isSearchPatient" #select tabindex="0" [items]="providerSpecialization"
[loading]="loading"
[clearable]="true"
bindLabel="fullName"
bindValue="providerId"
[searchFn]="customSearch"
placeholder="Enter Doctor Name/Specialization"
(search)="fetchDoctorSpecializationHelper($event)"
(change)="onChangeProvider($event)"
[(ngModel)]="filters.options.providerId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled" *ngIf="searchTerm && searchTerm.length >= 1">
No Doctor found for '{{searchTerm}}'
</div>
<div class="ng-option disabled" *ngIf="(!searchTerm || searchTerm.length < 1)">
Search Doctor
</div>
</ng-template>
<ng-template ng-option-tmp let-item="item" let-i="index">
<div class="media">
<div class="avatar-xs mr-1">
<span class="avatar-title rounded-circle font-11 font-weight-bold bg-soft-warning text-primary"><i class="fe-map-pin"></i></span>
</div>
<div class="media-body">
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="item.fullName"></h5>
<span class="d-block font-13" [textContent]="item.specializationName || '-----'"></span>
</div>
</div>
</ng-template>
</ng-select>
</div>
</div>
</td>-->
<!--</tr>
</table>-->
</div>
</div>
<div class="col-12">
<div class="card-box p-0">
<div class="row p-2" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading ...</span>
</div>
</div>
</div>
<div class="row p-2" *ngIf="!loading && (!providerSchedulerCharges || !providerSchedulerCharges.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(doctorChargeTemplate)"><i class="fe-plus mr-1"></i> Add </button>
</div>
</div>
</div>
<div class="table-responsive" *ngIf="!loading && providerSchedulerCharges.length > 0">
<table class="table table-sm">
<thead class="table-info">
<tr>
<th>Location</th>
<th>Doctor</th>
<th>Specialization Name</th>
<th>Consultation Type</th>
<th>Follow Up Days</th>
<th>No of Visits</th>
<th>Charges</th>
<th>CreatedBy</th>
<th>Modified By</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of providerSchedulerCharges;index as i;">
<td [textContent]="item.locationName"></td>
<td [textContent]="item.providerName"></td>
<td [textContent]="item.specializationName"></td>
<td [textContent]="item.consultationName"></td>
<td [textContent]="item.followUpDays"></td>
<td [textContent]="item.followUpDaysLimit"></td>
<td><span [textContent]="item.chargeNames"></span></td>
<td>
<h5 class="font-13 mb-0" [textContent]="item.createdByName"></h5>
<small class="tx-13" [textContent]="item.createdDate | date:'dd-MM-yyyy'"></small>
</td>
<td>
<h5 class="font-13 mb-0" [textContent]="item.modifiedByName"></h5>
<small class="tx-13" [textContent]="item.modifiedDate | date:'dd-MM-yyyy'"></small>
</td>
<td>
<nav class="nav">
<a href="javascript:;" class="action-icon text-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenModel(templateWord, item)"><i class="fe-edit"></i></a>
<button type="button" class="btn btn-sm btn-outline-success" *ngIf="item.active == false" title="Active" (click)="onChangeStatus(item, true)">
<i class="fe-check-square"></i>
</button>
<button type="button" class="btn btn-sm btn-outline-warning" *ngIf="item.active == true" title="Inactive" (click)="onChangeStatus(item, false)">
<i class="fe-x-square"></i>
</button>
</nav>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="8">
<nav class="d-flex align-items-center justify-content-between">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - providerSchedulerCharges.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> Records )</span>
</span>
</p>
<ngb-pagination *ngIf="pagination.totalItems > 10" class="pagination justify-content-end" [maxSize]="5" [rotate]="true" [ellipses]="true" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>
</nav>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #doctorChargeTemplate class="overflow-auto">
<form [formGroup]="providerScheduleChargeForm" class="overflow-auto" (ngSubmit)="onSubmit()">
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-human-edit mr-1"></i> Doctor Schedule Charge</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-12">
<label class="mb-1">Locations<code>*</code></label>
<ng-select class="ng-select-sm" [items]="locations"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select locations"
[ngClass]="{ 'is-invalid': submitted && forms.form.locationId.errors }"
formControlName="locationId"
(change)="onChangeLocation($event)">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No locations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
<div class="col-12">
<div class="form-group">
<label class="mb-0">Doctor</label>
<ng-select [items]="providers"
class="ng-select-sm"
[loading]="loadingProviders"
bindLabel="value"
bindValue="id"
placeholder="Select Doctor"
[ngClass]="{ 'is-invalid': (submitted && forms.form.providerId.errors) }"
formControlName="providerId"
(change)="onProviderSelect($event)">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
No providers found<span *ngIf="searchTerm"> for '{{searchTerm}}'</span>.
</ng-template>
<ng-template ng-option-tmp let-item="item" let-i="index">
<h5 class="mb-1 mt-0 font-weight-normal" [textContent]="item.value"></h5>
</ng-template>
<ng-template ng-label-tmp let-item="item">
<div class="media">
<div class="avatar-xs mr-1">
<span class="avatar-title rounded-circle font-11 font-weight-bold bg-soft-primary text-primary"><i class="fe-map-pin"></i></span>
</div>
<div class="media-body">
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="item.value"></h5>
</div>
</div>
</ng-template>
</ng-select>
</div>
</div>
<div class="col-12">
<div class="form-group">
<label class="mb-0">Specialization</label>
<ng-select class="ng-select-sm" [items]="specializations"
[loading]="loadingSpecialization"
bindLabel="value"
bindValue="id"
autocomplete="nope"
placeholder="Select specialization"
[ngClass]="{ 'is-invalid': submitted && forms.form.specializationId.errors }"
formControlName="specializationId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
No specialization found<span *ngIf="searchTerm"> for '{{searchTerm}}'</span>.
</ng-template>
</ng-select>
</div>
</div>
<!--<div class="col-12">
<label class="mb-1">Parts of day<code>*</code></label>
<ng-select class="ng-select-sm text-uppercase" [items]="days"
bindLabel="partsOfDayName"
bindValue="partsOfDayId"
autocomplete="nope"
placeholder="Select day type"
[ngClass]="{ 'is-invalid': submitted && forms.form.partsOfDayId.errors }"
formControlName="partsOfDayId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No day type found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>-->
<div class="col-12">
<div class="form-group">
<label class="mb-1">Consultation Type <code>*</code></label>
<ng-select class="ng-select-sm text-uppercase" [items]="consultationType"
bindLabel="value"
bindValue="id"
autocomplete="nope"
placeholder="Select Consultation Type"
[ngClass]="{ 'is-invalid': submitted && forms.form.consultationTypeId.errors }"
formControlName="consultationTypeId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No Consultation Type found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</div>
<div class="col-6">
<div class="form-group">
<label class="mb-1">Follow Up Days </label>
<input type="number" min="0" numbersOnly placeholder="Enter Follow Up Days" class="form-control" formControlName="followUpDays" />
</div>
</div>
<div class="col-6">
<div class="form-group">
<label class="mb-1"> No of Visits </label>
<input type="number" min="0" numbersOnly placeholder="Follow Up Days Limit" class="form-control" formControlName="followUpDaysLimit" />
</div>
</div>
<div class="col-6">
<div class="form-group">
<label class="mb-1">Start Date<span class="text-danger">*</span></label>
<input class="form-control date-picker" type="text" block [minDate]="todayDate"
formControlName="startDate" autocomplete="nope" placeholder="Select start date"
[ngClass]="{ 'is-invalid': submitted && forms.form.startDate.errors }"
ngbDatepicker #startDate="ngbDatepicker"
(click)="startDate.toggle(); $event.stopPropagation();" (dateSelect)="getEndDate()" />
<!--<input class="form-control" type="date" placeholder="select start date" formControlName="startDate" (change)="getEndDate()" autocomplete="nope" [min]="currentDate" max="2023-01-01" [ngClass]="{ 'is-invalid': submitted && forms.form.startDate.errors }" />-->
</div>
</div>
<div class="col-6">
<div class="form-group">
<label class="mb-1">End Date<span class="text-danger">*</span></label>
<input class="form-control date-picker" type="text" block [minDate]="setDate1"
formControlName="endDate" autocomplete="nope" placeholder="Select end date"
[ngClass]="{ 'is-invalid': submitted && forms.form.endDate.errors }" (dateSelect)="dateValidation()"
ngbDatepicker #endDate="ngbDatepicker"
(click)="endDate.toggle(); $event.stopPropagation();" />
<!--<input class="form-control" type="date" (dateSelect)="setEndDate()" placeholder="select end date" formControlName="endDate" autocomplete="nope" [min]="setDate" max="2023-01-01" [ngClass]="{ 'is-invalid': submitted && forms.form.endDate.errors }" />-->
</div>
</div>
<div class="col-lg-12">
<h4 class="mb-1">Charges</h4>
<table class="table table-centered table-nowrap table-sm table-bordered mb-0">
<thead>
<tr>
<th>Name</th>
<th>Charge Amount</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let charge of forms.chargeArray.controls;let i = index;" [formGroup]="charge">
<td>
<input type="text" class="form-control-plaintext" readonly formControlName="name" placeholder="Charge Name">
</td>
<td>
<div class="form-group">
<input class="form-control" type="number" numbersOnly formControlName="value" min="0" [placeholder]="'Enter Amount'" />
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
<ng-template #templateWord>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-mother-nurse mr-1"></i>{{providerScheduleChargeForm.value.providerAvailabilityChargeTypeId === 0 ? 'Add' : 'Edit'}} Charge & Duration</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<form [formGroup]="providerScheduleChargeForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="row">
<div class="col-12">
<label class="mb-1">Consultation Type <code>*</code></label>
<ng-select class="ng-select-sm text-uppercase" [items]="consultationType"
bindLabel="value"
bindValue="id"
autocomplete="nope"
placeholder="Select Consultation Type"
[ngClass]="{ 'is-invalid': submitted && forms.form.consultationTypeId.errors }"
formControlName="consultationTypeId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No Consultation Type found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
<div class="col-6">
<div class="form-group">
<label class="mb-1">Follow Up Days </label>
<input type="number" min="0" numbersOnly placeholder="Enter Follow Up Days" class="form-control" formControlName="followUpDays" />
</div>
</div>
<div class="col-6">
<div class="form-group">
<label class="mb-1"> No of Visits</label>
<input type="number" min="0" numbersOnly placeholder="Follow Up Days Limit" class="form-control" formControlName="followUpDaysLimit" />
</div>
</div>
<div class="col-12">
<div class="form-group">
<label class="mb-1">Start Date<span class="text-danger">*</span></label>
<input class="form-control date-picker" type="text" block [minDate]="todayDate"
formControlName="startDate" autocomplete="nope" (dateSelect)="getEndDate()"
[ngClass]="{ 'is-invalid': submitted && forms.form.startDate.errors }"
ngbDatepicker #startDate="ngbDatepicker"
(click)="startDate.toggle(); $event.stopPropagation();" />
</div>
</div>
<div class="col-12">
<div class="form-group">
<label class="mb-1">End Date<span class="text-danger">*</span></label>
<input class="form-control date-picker" type="text" block [minDate]="setDate1"
formControlName="endDate" autocomplete="nope" (dateSelect)="dateValidation()"
[ngClass]="{ 'is-invalid': submitted && forms.form.endDate.errors }"
ngbDatepicker #endDate="ngbDatepicker"
(click)="endDate.toggle(); $event.stopPropagation();" />
</div>
</div>
<div class="col-lg-12">
<h4 class="mb-1">Charges</h4>
<table class="table table-centered table-nowrap table-sm table-bordered mb-0">
<thead>
<tr>
<th>Name</th>
<th>Charge Amount</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let charge of forms.chargeArray.controls;let i = index;" [formGroup]="charge">
<td>
<input type="text" class="form-control-plaintext" readonly formControlName="name" placeholder="Charge Name">
</td>
<td>
<div class="form-group">
<input class="form-control" type="number" numbersOnly formControlName="value" min="0" [placeholder]="'Enter Amount'" />
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { ApiResources, UtilHelper, DateHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService, ResourceService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { HttpErrorResponse } from "@angular/common/http";
import { NgbModal, NgbModalRef, NgbDate} from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, Validators, FormBuilder, FormArray } from "@angular/forms";
import { Page, IUserAccount, Pagination, IResource, GenericResponse } from "@shared/models";
import { ProviderScheduleCharges } from "@shared/entities/provider-schedule-charges.entity";
import { LookUpModel } from "../../../services/models/look-up.model";
import { ProviderSpecialization } from "../../../../../shared/entities/provider-specialization.entity";
import { NgSelectComponent } from '@ng-select/ng-select';
import moment from "moment";
class TrackBy {
providerSchedulerCharges(item: ProviderScheduleCharges) {
return item.providerId;
}
resource(item: IResource) {
return item.id;
}
}
class FilterOptions {
locationId: number = null;
providerId: number = null;
specializationId: number = null;
departmentId: number = null;
consultationTypeId: number = null;
fromDate: string = null;// = moment().format("YYYY-MM-DD");
toDate: string = null; //= moment().format("YYYY-MM-DD");
active: boolean = true;
}
class Filters {
options: FilterOptions;
applied: boolean;
constructor() {
this.init();
}
init() {
this.options = new FilterOptions();
this.applied = undefined;
}
}
class partsOfDay {
partsOfDayId: number;
partsOfDayName: string;
active: boolean;
createdBy: number;
createdDate: string;
modifiedBy: number;
modifiedDate: string;
}
@Component({
templateUrl: "./provider-schedule-charges.html",
encapsulation: ViewEncapsulation.None
})
export class ProviderScheduleChargesPage implements OnInit, OnDestroy {
page: Page;
filters: Filters;
trackBy: TrackBy;
pagination: Pagination;
providerScheduleChargeForm: FormGroup;
loading: boolean;
providerSchedulerCharges: Array<ProviderScheduleCharges>;
setDatesForCharges: Array<ProviderScheduleCharges>;
providerSchedulerChargeType: Array<ProviderScheduleCharges>;
modalRef: NgbModalRef;
submitting: boolean;
submitted: boolean;
modifying: boolean;
modifyingContent: string;
locations: Array<IResource>;
visitors: Array<LookUpModel>;
charges: Array<LookUpModel>;
currencySymbol = "₹";
providerSpecialization: Array<ProviderSpecialization>
isVisitTypeloading: boolean;
chargeDurationForm: FormGroup;
doctorCharges: Array<ProviderScheduleCharges>;
minDate = DateHelper.minDate;
consultationType: Array<IResource>;
loadingProviders: boolean;
providers: Array<IResource>;
loadingSpecialization: boolean;
specializations: Array<IResource>;
days: Array<partsOfDay>;
locationId: number;
providerResources: Array<IResource>;
specializationResources: Array<IResource>;
loadingproviderResources: boolean;
loadingSpecializationResources: boolean;
loadingconsultationTypes: boolean;
todayDate = DateHelper.ngbToday;
greaterThanToday=DateHelper.ngbToday;
//setDate = DateHelper.ngbToday;
setDate = NgbDate;
setDate1: NgbDate;
// today = DateHelper.ngbToday;
setMaxDate: NgbDate;
setMinDate: NgbDate;
isSearchPatient: boolean = true;
constructor(
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly httpService: HttpService,
private readonly resourceService: ResourceService,
) {
this.buildForm();
this.page = new Page();
this.filters = new Filters();
this.trackBy = new TrackBy();
this.initPagination();
this.providers = new Array<IResource>();
this.doctorCharges = new Array<ProviderScheduleCharges>();
this.providerSchedulerCharges = new Array<ProviderScheduleCharges>();
this.providerSchedulerChargeType = new Array<ProviderScheduleCharges>();
this.locations = new Array<IResource>();
this.specializations = new Array<IResource>();
//this.todayDate = new Date();
}
//getMinDate() {
// const date = this.filters.options.fromDate.split("-");
// const year = Number(date[0]);
// const month = Number(date[1]);
// const day = Number(date[2]);
// this.setMinDate = new NgbDate(year, month, day);
//}
setFocus = (select: NgSelectComponent) => {
select.open();
}
//getMaxDate() {
// const date = this.filters.options.toDate.split("-");
// const year = Number(date[0]);
// const month = Number(date[1]);
// const day = Number(date[2]);getMinDate
// this.setMaxDate = new NgbDate(year, month, day);
//}
getMinDate() {
const date = this.filters.options.fromDate.split("-");
const year = Number(date[0]);
const month = Number(date[1]);
const day = Number(date[2]);
this.setMinDate = new NgbDate(year, month, day);
}
getMaxDate() {
const date = this.filters.options.toDate.split("-");
const year = Number(date[0]);
const month = Number(date[1]);
const day = Number(date[2]);
this.setMaxDate = new NgbDate(year, month, day);
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
private fetchProviderResources(departmentId?: number) {
this.loadingproviderResources = true;
this.resourceService.providerForSchdule(departmentId)
.pipe(finalize(() => { this.loadingproviderResources = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.providerResources = response;
});
}
private fetchspecializationForProviderAvialability() {
this.loadingSpecializationResources = true;
this.resourceService.specializationForSchdule()
.pipe(finalize(() => { this.loadingSpecializationResources = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.specializationResources = response;
});
}
providerChange(provider?: IResource) {
if (provider != undefined) {
this.fetchProviderSpecializations(provider.id);
} if (provider == undefined) {
this.fetchLocationSpecialization(this.page.userAccount.locationId);
}
}
private buildForm() {
this.providerScheduleChargeForm = this.formBuilder.group({
providerAvailabilityChargeTypeId: 0,
locationId: [null, [Validators.required]],
specializationId: [null],
providerId: [null],
active: [true],
consultationTypeId: [null, [Validators.required]],
//partsOfDayId: [null, [Validators.required]],
startDate: [null, [Validators.required]],
endDate: [null, [Validators.required]],
charges: this.formBuilder.array([]),
followUpDays: 0,
followUpDaysLimit: 0
});
//this.providerScheduleChargeForm.get("startDate").valueChanges.subscribe((value: any) => {
// debugger;
// const endDate = this.providerScheduleChargeForm.get("endDate").value
// const foundExist = this.providerSchedulerCharges.filter(x => x.startDate <= value && x.endDate >= endDate )
// if (foundExist.length > 0) {
// return this.notifyService.warningToast("Charges already exists");
// }
//}
//);
//this.providerScheduleChargeForm.get("endDate").valueChanges.subscribe((value: any) => {
// debugger;
// const endDate = this.providerScheduleChargeForm.get("startDate").value
// const foundExist = this.providerSchedulerCharges.filter(x => x.startDate <= value && x.endDate >= endDate)
// if (foundExist.length > 0) {
// return this.notifyService.warningToast("Charges already exists");
// }
//});
}
onProviderSelect(provider?: IResource) {
if (provider != undefined) {
this.fetchProviderSpecializations(provider.id);
} if (provider == undefined) {
this.fetchLocationSpecialization(this.locationId);
}
if (provider) {
this.providerScheduleChargeForm.patchValue({
providerId: provider.id
});
//this.httpService
// .post<Array<ProviderScheduleCharges>>(ApiResources.getURI(ApiResources.providerScheduleCharges.base, ApiResources.providerScheduleCharges.fetch), provider.id)
// .pipe(takeUntil(this.page.unSubscribe))
// .pipe(finalize(() => this.loading = false))
// .subscribe(
// (response: any) => {
// this.setDatesForCharges = response;
// this.setDatesForCharges.forEach((item) => {
// if (this.filters.options.fromDate <=item.startDate.toString()) {
// this.providerScheduleChargeForm.patchValue({ endDate: this.providerScheduleChargeForm.value.startDate });
// }
// })
// },
// () => {
// this.providerSchedulerCharges = [];
// }
// );
} else {
this.providerScheduleChargeForm.patchValue({
providerId: null
});
}
}
get chargeType() {
return this.chargeDurationForm.controls;
}
get chargeTypeFormArray() { return this.chargeDurationForm.controls["charges"] as FormArray }
get chargeForm() {
return this.chargeTypeFormArray;
}
addChargesToArray(typeId?: number, value?: number) {
return this.formBuilder.group({
chargeTypesId: [typeId ? typeId : null],
chargeTypeCharge: [value ? value : null]
});
}
addChargeTypeToArray(mainItem: LookUpModel, chargeValue?: string) {
return this.formBuilder.group({
typeId: [mainItem.id],
name: [mainItem.name],
value: [chargeValue ? chargeValue : 0]
});
}
onOpenModel(content: TemplateRef<any>, providerScheduleCharge?: ProviderScheduleCharges) {
this.buildForm();
this.providerScheduleChargeForm.patchValue({ startDate: moment(this.todayDate).toString() });
if (providerScheduleCharge != undefined) {
this.fetchDoctorCharge(providerScheduleCharge);
}
if (providerScheduleCharge == undefined || providerScheduleCharge == null) {
this.fetchAddChargeTypes();
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
fetchDoctorCharge(providerScheduleCharge?: ProviderScheduleCharges) {
const request = {}
if (providerScheduleCharge != undefined) {
request["providerId"] = providerScheduleCharge.providerId;
request["specializationId"] = providerScheduleCharge.specializationId;
request["startDate"] = providerScheduleCharge.startDate;
request["endDate"] = providerScheduleCharge.endDate;
request["consultationTypeId"] = providerScheduleCharge.consultationTypeId;
request["active"] = providerScheduleCharge.active;
}
this.httpService
.post<Array<ProviderScheduleCharges>>(ApiResources.getURI(ApiResources.providerScheduleCharges.base, ApiResources.providerScheduleCharges.doctorCharge), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<ProviderScheduleCharges>) => {
this.doctorCharges = response;
let abc = [] // provider availability charge types with values
for (var item of response) {
abc.push({ id: item.id, name: item.name, value: item.value, providerAvailabilityChargeTypeId: item.providerAvailabilityChargeTypeId });
}
console.log(abc);
let charge = [] //charge types from masters for OP
for (var chargeType of this.charges) {
charge.push({ id: chargeType.id, name: chargeType.name, value: 0, providerAvailabilityChargeTypeId: 0 })
}
charge.forEach(x => { // values which are not present in abc and present in charge pushed to abc.
if (!abc.find(y => y.id === x.id)) {
abc.push(x);
}
});
if (providerScheduleCharge) {
abc.forEach((item) => {
this.forms.chargeArray.push(this.buildChargeForm(item));
});
this.doctorCharges.forEach((data) => {
this.providerScheduleChargeForm.patchValue({
providerId: data.providerId,
specializationId: data.specializationId,
startDate: data.startDate,
endDate: data.endDate,
partsOfDayId: data.partsOfDayId,
providerAvailabilityChargeTypeId: data.providerAvailabilityChargeTypeId,
locationId: data.locationId,
consultationTypeId: data.consultationTypeId,
followUpDays: data.followUpDays ? data.followUpDays : 0,
followUpDaysLimit: data.followUpDaysLimit ? data.followUpDaysLimit : 0,
})
})
}
},
() => {
this.doctorCharges = new Array<ProviderScheduleCharges>();
}
);
}
onChangeLocation(event?: IResource) {
this.locationId = event.id;
this.fetchDoctorSpecialization(null)
this.fetchLocationSpecialization(event.id);
this.fetchProviders(event.id);
}
onChangeFilterLocation(event?: IResource) {
this.locationId = event.id;
this.fetchLocationSpecialization(event.id);
this.fetchProviders(event.id);
}
fetchProviderScheduleCharges() {
this.loading = true;
const request = Object.assign(UtilHelper.clone(this.filters.options), UtilHelper.clone(this.pagination));
if (this.filters.options.toDate < this.filters.options.fromDate) {
this.notifyService.warningToast("end should not be lessthan start date");
return;
}
if (!request.locationId) {
request.locationId = this.page.userAccount.locationId;
}
//if (!request.providerId) {
// request.specializationId = null;
//}
this.providerSchedulerCharges = new Array<ProviderScheduleCharges>();
this.providerSchedulerChargeType = new Array<ProviderScheduleCharges>();
this.httpService
.post<Array<ProviderScheduleCharges>>(ApiResources.getURI(ApiResources.providerScheduleCharges.base, ApiResources.providerScheduleCharges.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: any) => {
this.providerSchedulerCharges = response.item1;
this.providerSchedulerChargeType = response.item2;
UtilHelper.applyPagination(this.providerSchedulerCharges, this.pagination);
this.fetchProviderResources();
this.fetchspecializationForProviderAvialability();
},
() => {
this.providerSchedulerCharges = [];
}
);
}
onChangeProvider(p: ProviderSpecialization) {
this.filters.options.specializationId = p.specializationId;
// console.log(a);
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetchProviderScheduleCharges();
}
onSubmit() {
this.submitted = true;
if (!this.providerScheduleChargeForm.valid) {
this.notifyService.warningToast("Please fill all the fields.");
return;
}
if (this.providerScheduleChargeForm.value.endDate < this.providerScheduleChargeForm.value.startDate) {
this.notifyService.warningToast("end should not be lessthan start end");
return;
}
const request = Object.assign(UtilHelper.clone(this.providerScheduleChargeForm.getRawValue()));
let abc = request.charges.filter(m => m.value == null);
if (abc.length > 0) {
return this.notifyService.warningToast("Please provide Charge amount");
}
request["modifiedByName"] = this.page.userAccount.fullName;
request["charges"] = this.providerScheduleChargeForm.value.charges;
request.createdBy = this.page.userAccount.accountId;
if (request["providerAvailabilityChargeTypeId"] > 0) {
request["modifiedBy"] = this.page.userAccount.accountId;
}
this.submitting = true;
var url = ApiResources.getURI(ApiResources.providerScheduleCharges.base, ApiResources.providerScheduleCharges.add);
if (request["providerAvailabilityChargeTypeId"] > 0) {
url = ApiResources.getURI(ApiResources.providerScheduleCharges.base, ApiResources.providerScheduleCharges.update);
}
this.httpService.post(url, request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchProviderScheduleCharges();
this.notifyService.success("provider Schedule Charges has been saved successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warningToast(errorMessage);
} else {
this.notifyService.defaultError();
}
});
}
fetchDays() {
const request = {};
this.httpService
.post<Array<partsOfDay>>(ApiResources.getURI(ApiResources.providerScheduleCharges.base, ApiResources.providerScheduleCharges.dayTypes), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<partsOfDay>) => {
this.days = response;
},
() => {
this.days = new Array<partsOfDay>();
}
);
}
get forms() {
return {
form: this.providerScheduleChargeForm ? this.providerScheduleChargeForm.controls : {},
chargeArray: this.providerScheduleChargeForm.controls["charges"] as FormArray,
}
}
private buildChargeForm(charge: any) {
return this.formBuilder.group({
id: charge.id,
name: charge.name,
value: charge.value ? charge.value : 0,
providerAvailabilityChargeTypeId: charge.providerAvailabilityChargeTypeId ? charge.providerAvailabilityChargeTypeId : 0
});
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.loading = false;
this.submitting = undefined;
this.submitted = undefined;
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.buildForm();
this.fetchLocations();
this.fetchProviderScheduleCharges();
this.fetchDoctorSpecialization();
this.fetchProviderSpecializations();
this.fetchDays();
this.fetchProviders(this.page.userAccount.locationId);
this.fetchConsultationType();
this.fetchProviderResources();
this.fetchspecializationForProviderAvialability();
this.fetchAddChargeTypes();
this.fetchLocationSpecialization(this.page.userAccount.locationId);
} else {
this.page.userAccount = undefined;
}
});
}
private fetchLocations() {
this.resourceService.locations()
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.locations = response;
this.filters.options.locationId = this.page.userAccount.locationId;
});
}
fetchAddChargeTypes() {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.providerLocations.base, ApiResources.providerLocations.fetchChargeType), {})
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: GenericResponse) => {
this.charges = response.data as Array<LookUpModel>;
this.charges.forEach((charge) => {
//this.addChargeToForm(charge);
const item = {
id: charge.id,
name: charge.name,
value: charge.value ? charge.value : 0
};
this.forms.chargeArray.push(this.buildChargeForm(item));
});
},
() => {
this.charges = new Array<LookUpModel>();
}
);
}
private fetchDoctorSpecialization(locationId?: number) {
this.loading = true;
var request = {
locationId: locationId
}
this.httpService
.post<Array<ProviderSpecialization>>(ApiResources.getURI(ApiResources.providerScheduleCharges.base, ApiResources.providerScheduleCharges.fetchProviderSpecialization), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<ProviderSpecialization>) => {
this.providerSpecialization = response;
},
() => {
this.providerSpecialization = new Array<ProviderSpecialization>();
}
);
}
private fetchConsultationType() {
this.loadingconsultationTypes = true;
this.resourceService.consultationType()
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.loadingconsultationTypes = false;
this.consultationType = response;
});
}
customSearch(term: string, item) {
term = term.toLocaleLowerCase();
return item['fullName'].toLocaleLowerCase().indexOf(term) > -1 || item['specializationName'].toLocaleLowerCase().indexOf(term) > -1;
}
onApplyFilters() {
this.filters.applied = UtilHelper.isFiltersApplied(this.filters.options);
this.initPagination();
this.loading = true;
this.fetchProviderScheduleCharges();
}
onResetFilters() {
this.filters.init();
this.loading = true;
this.filters.options.locationId = this.page.userAccount.locationId;
//this.setMaxDate = DateHelper.ngbToday;
//this.setMinDate = DateHelper.ngbToday;
this.fetchProviderScheduleCharges();
}
onChangeStatus(record: ProviderScheduleCharges, status: boolean) {
const request = {
schedulerTypeId: record.schedulerTypeId,
active: status,
modifiedBy: this.page.userAccount.accountId,
roleId: this.page.userAccount.roleId
};
this.notifyService.confirm(`Do you really want to ${status ? "Active" : "Inactive"} this selected Charges?`, () => {
this.modifying = true;
this.modifyingContent = `${status ? "activating" : "inactivating"} the selected Component`;
this.httpService
.post(ApiResources.getURI(ApiResources.providerScheduleCharges.base, ApiResources.providerScheduleCharges.modifyStatus), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.modifying = false }))
.subscribe(
(response: number) => {
if (response > 0) {
switch (response) {
case 1:
this.notifyService.successToast("Status is updated successfully.");
this.fetchProviderScheduleCharges();
}
}
this.fetchProviderScheduleCharges();
},
() => {
}
);
}, () => {
});
}
private fetchProviders(locationId?: number) {
this.loadingProviders = true;
this.resourceService.locationProviders(locationId)
.pipe(finalize(() => { this.loadingProviders = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.providers = response;
});
}
private fetchLocationSpecialization(locationId?: number) {
this.loadingSpecialization = true
this.resourceService.locationSpecializations(locationId)
.pipe(finalize(() => { this.loadingSpecialization = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.specializations = response;
});
}
private fetchProviderSpecializations(providerId?: number) {
this.loadingSpecialization = true
this.resourceService.providerSpecializations(providerId)
.pipe(finalize(() => { this.loadingSpecialization = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.specializations = response;
});
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
this.todayDate = null;
this.setDate = null;
this.setDate1 = null;
}
getEndDate() {
//this.greaterThanToday = this.providerScheduleChargeForm.value.startDate;
//this.providerScheduleChargeForm.patchValue({ endDate: this.providerScheduleChargeForm.value.startDate });
const date = this.providerScheduleChargeForm.get("startDate").value.split("-");
const year = Number(date[0]);
const month = Number(date[1]);
const day = Number(date[2]);
this.setDate1 = new NgbDate(year, month, day);
//this.providerScheduleChargeForm.get("endDate").setValue(disableDate);
////this.providerScheduleChargeForm.setValue("endDate") = disableDate;
//this.providerScheduleChargeForm.patchValue({ endDate: disableDate });
}
dateValidation() {
if (this.providerScheduleChargeForm.value.endDate < this.providerScheduleChargeForm.value.startDate) {
this.notifyService.warningToast("end should not be lessthan start end");
return;
}
}
fetchDoctorSpecializationHelper($event: any) {
if ($event && $event.term && $event.term.length > 1) {
// let locationId = this.quickScheduleForm.get("locationId").value
// let consultationTypeId = this.quickScheduleForm.get("consultationTypeId").value
this.fetchDoctorSpecialization(this.page.userAccount.locationId);
} else {
this.providerSpecialization = new Array<ProviderSpecialization>();
}
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(doctorChargeTemplate)"><i class="fe-plus mr-1"></i> Add </button>
</div>
<h4 class="page-title">Doctor Schedule Visits</h4>
</div>
</div>
<div class="col-12 p-0">
<div class="card-box mb-1 p-1">
<table class="table table-borderless table-sm mb-0">
<tr style="font-size:12px;">
<!--<td style="width:14%;">
<div class="form-group mb-0">
<label class="mb-1">Doctor</label>
<select class="form-control custom-select" (keyup.enter)="onApplyFilters()" autocomplete="nope" [(ngModel)]="filters.options.providerId" (click)="providerChange()">
<option [ngValue]="null" *ngIf="!loadingProviders">All</option>
<option selected *ngIf="loadingProviders">Loading...</option>
<option *ngFor="let item of providers;" [textContent]="item.value" [ngValue]="item.id"></option>
</select>
</div>
</td>-->
<td class="col-4 col-sm-4 col-lg-2">
<div class="form-group">
<label class="mb-1">Locations</label>
<ng-select class="ng-select-sm" [items]="locations"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select locations"
[(ngModel)]="filters.options.locationId"
(change)="onChangeFilterLocation($event)">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No locations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</td>
<td class="col-4 col-sm-4 col-lg-2" *ngIf="encryptedProviderId == null">
<div class="form-group">
<label class="mb-0">Doctor</label>
<ng-select [items]="providers"
class="ng-select-sm"
[loading]="loadingProviders"
bindLabel="value"
bindValue="id"
placeholder="Select Doctor"
[(ngModel)]="filters.options.providerId"
(change)="onProviderSelect($event)">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
No providers found<span *ngIf="searchTerm"> for '{{searchTerm}}'</span>.
</ng-template>
<ng-template ng-option-tmp let-item="item" let-i="index">
<h5 class="mb-1 mt-0 font-weight-normal" [textContent]="item.value"></h5>
</ng-template>
<ng-template ng-label-tmp let-item="item">
<div class="media">
<div class="avatar-xs mr-1">
<span class="avatar-title rounded-circle font-11 font-weight-bold bg-soft-primary text-primary"><i class="fe-map-pin"></i></span>
</div>
<div class="media-body">
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="item.value"></h5>
</div>
</div>
</ng-template>
</ng-select>
</div>
</td>
<td style="width:14%;" *ngIf="encryptedProviderId == null">
<div class="form-group mb-0">
<label class="mb-1">Specialization</label>
<select class="form-control custom-select" (keyup.enter)="onApplyFilters()" autocomplete="nope" [(ngModel)]="filters.options.specializationId">
<option [ngValue]="null" *ngIf="!loadingSpecialization">All</option>
<option selected *ngIf="loadingSpecialization">Loading...</option>
<option *ngFor="let item of specializations;" [textContent]="item.value" [ngValue]="item.id"></option>
</select>
</div>
</td>
<td class="col-4 col-sm-4 col-lg-2">
<div class="form-group">
<label class="mb-1">Created By</label>
<ng-select class="ng-select-sm" [items]="accounts"
[loading]="loadingRoles"
[clearable]="true"
bindLabel="value"
bindValue="id"
placeholder="Select User"
[(ngModel)]="filters.options.createdBy">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
No User found<span *ngIf="searchTerm"> for '{{searchTerm}}'</span>.
</ng-template>
<ng-template ng-option-tmp let-item="item" let-i="index">
<h5 class="mb-1 mt-0 font-weight-normal" [textContent]="item.value"></h5>
<small><label class="badge badge-outline-primary" [textContent]="item.optionalText2"></label></small>
</ng-template>
<ng-template ng-label-tmp let-item="item">
<div class="media">
<div class="avatar-xs mr-1">
<span class="avatar-title rounded-circle font-11 font-weight-bold bg-soft-primary text-primary"><i class="fe-map-pin"></i></span>
</div>
<div class="media-body">
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="item.value"></h5>
<small><label class="badge badge-outline-primary" [textContent]="item.optionalText2"></label></small>
</div>
</div>
</ng-template>
</ng-select>
</div>
</td>
<td class="col-4 col-sm-4 col-lg-2">
<div class="form-group">
<label class="mb-1 font-13">Status</label>
<select class="form-control custom-select form-control-sm" autocomplete="nope" [(ngModel)]="filters.options.active">
<option [ngValue]="true">Active</option>
<option [ngValue]="false">InActive</option>
</select>
</div>
</td>
<td style="width: 12%;">
<div style="margin-top: 25px;">
<button type="button" (click)="onApplyFilters()" class="btn btn-sm btn-outline-primary">Search</button>
<button type="button" (click)="onResetFilters()" class="btn btn-sm btn-outline-danger ml-1">Reset</button>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="col-12">
<div class="card-box p-0">
<div class="row p-2" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading ...</span>
</div>
</div>
</div>
<div class="row p-2" *ngIf="!loading && (!providerSchedulerVisits || !providerSchedulerVisits.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(doctorChargeTemplate)"><i class="fe-plus mr-1"></i> Add </button>
</div>
</div>
</div>
<div class="table-responsive" *ngIf="!loading && providerSchedulerVisits.length > 0">
<table class="table table-sm">
<thead class="table-info">
<tr>
<th>Location</th>
<th>Doctor</th>
<th>Specialization Name</th>
<th>Visits</th>
<th>CreatedBy</th>
<th>Modified By</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of providerSchedulerVisits;index as i;">
<td [textContent]="item.locationName"></td>
<td [textContent]="item.providerName"></td>
<td [textContent]="item.specializationName"></td>
<td><span [textContent]="item.visitNames"></span></td>
<td>
<h5 class="font-13 mb-0" [textContent]="item.createdByName"></h5>
<small class="tx-13" [textContent]="item.createdDate | date:'dd-MM-yyyy'"></small>
</td>
<td>
<h5 class="font-13 mb-0" [textContent]="item.modifiedByName"></h5>
<small class="tx-13" [textContent]="item.modifiedDate | date:'dd-MM-yyyy'"></small>
</td>
<td>
<nav class="nav">
<a href="javascript:;" class="action-icon text-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenModel(templateWord, item)"><i class="fe-edit"></i></a>
<button type="button" class="btn btn-sm btn-outline-success" *ngIf="item.active == false" title="Active" (click)="onChangeStatus(item, true)">
<i class="fe-check-square"></i>
</button>
<button type="button" class="btn btn-sm btn-outline-warning" *ngIf="item.active == true" title="Inactive" (click)="onChangeStatus(item, false)">
<i class="fe-x-square"></i>
</button>
</nav>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="7">
<nav class="d-flex align-items-center justify-content-between">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - providerSchedulerVisits.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> Records )</span>
</span>
</p>
<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="true" [ellipses]="true" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>
</nav>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #doctorChargeTemplate>
<form [formGroup]="providerScheduleVisitForm" (ngSubmit)="onSubmit()">
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-human-edit mr-1"></i> Doctor Schedule Visit</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-12">
<label class="mb-1">Locations<code>*</code></label>
<ng-select class="ng-select-sm" [items]="locations"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select locations"
[ngClass]="{ 'is-invalid': submitted && forms.form.locationId.errors }"
formControlName="locationId"
(change)="onChangeLocation($event)">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No locations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
<!--<div class="col-12">
<div class="form-group">
<label class="mb-1">Doctor <code>*</code></label>
<ng-select [items]="providerSpecialization"
[loading]="loading"
[clearable]="true"
bindLabel="fullName"
bindValue="providerId"
[searchFn]="customSearch"
placeholder="Enter Doctor Name/Specialization"
(search)="fetchDoctorSpecializationHelper($event)"
(change)="onChangeProvider($event)"
formControlName="providerId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled" *ngIf="searchTerm && searchTerm.length >= 2">
No Doctor found for '{{searchTerm}}'
</div>
<div class="ng-option disabled" *ngIf="(!searchTerm || searchTerm.length < 2)">
Search Doctor
</div>
</ng-template>
<ng-template ng-option-tmp let-item="item" let-i="index">
<div class="media">
<div class="avatar-xs mr-1">
<span class="avatar-title rounded-circle font-11 font-weight-bold bg-soft-warning text-primary"><i class="fe-map-pin"></i></span>
</div>
<div class="media-body">
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="item.fullName"></h5>
<span class="d-block font-13" [textContent]="item.specializationName || '-----'"></span>
</div>
</div>
</ng-template>
</ng-select>
</div>
</div>-->
<div class="col-12">
<div class="form-group">
<label class="mb-0">Doctor</label>
<ng-select [items]="providers"
class="ng-select-sm"
[loading]="loadingProviders"
bindLabel="value"
bindValue="id"
placeholder="Select Doctor"
[ngClass]="{ 'is-invalid': (submitted && forms.form.providerId.errors) }"
formControlName="providerId"
(change)="onProviderSelect($event)">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
No providers found<span *ngIf="searchTerm"> for '{{searchTerm}}'</span>.
</ng-template>
<ng-template ng-option-tmp let-item="item" let-i="index">
<h5 class="mb-1 mt-0 font-weight-normal" [textContent]="item.value"></h5>
</ng-template>
<ng-template ng-label-tmp let-item="item">
<div class="media">
<div class="avatar-xs mr-1">
<span class="avatar-title rounded-circle font-11 font-weight-bold bg-soft-primary text-primary"><i class="fe-map-pin"></i></span>
</div>
<div class="media-body">
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="item.value"></h5>
</div>
</div>
</ng-template>
</ng-select>
</div>
</div>
<div class="col-12">
<div class="form-group">
<label class="mb-0">Specialization</label>
<ng-select class="ng-select-sm" [items]="specializations"
[loading]="loadingSpecialization"
bindLabel="value"
bindValue="id"
autocomplete="nope"
placeholder="Select specialization"
[ngClass]="{ 'is-invalid': submitted && forms.form.specializationId.errors }"
formControlName="specializationId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
No specialization found<span *ngIf="searchTerm"> for '{{searchTerm}}'</span>.
</ng-template>
</ng-select>
</div>
</div>
<div class="col-lg-12">
<h4 class="mb-1">Visits</h4>
<table class="table table-centered table-nowrap table-sm table-bordered mb-0">
<thead>
<tr>
<th>Name</th>
<th>Duration</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let visit of forms.visitArray.controls;let i = index;" [formGroup]="visit">
<td>
<input type="text" class="form-control-plaintext" readonly formControlName="name" placeholder="Visit Name">
</td>
<td>
<div class="form-group">
<!--<numeric-textbox type="number" formControlName="value" min="0" [max]="2000000" [decimals]="2" [autoCorrect]="true" [format]="currencySymbol + ' 0.00'" [placeholder]="'Enter Value'"></numeric-textbox>-->
<input type="number" class="form-control" numbersOnly formControlName="value" min="0" [placeholder]="'Enter Duration'" />
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
<ng-template #templateWord>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-mother-nurse mr-1"></i>{{providerScheduleVisitForm.value.providerAvailabilityVisitTypeId === 0 ? 'Add' : 'Edit'}} Visit</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<form [formGroup]="providerScheduleVisitForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="col-12">
<div class="form-group">
<label class="mb-1">Locations</label>
<ng-select class="ng-select-sm" [items]="locations"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select locations"
formControlName="locationId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No locations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</div>
<div class="col-12">
<div class="form-group">
<label class="mb-0">Doctor</label>
<ng-select [items]="providers"
class="ng-select-sm"
[loading]="loadingProviders"
bindLabel="value"
bindValue="id"
placeholder="Select Doctor"
formControlName="providerId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
No providers found<span *ngIf="searchTerm"> for '{{searchTerm}}'</span>.
</ng-template>
<ng-template ng-option-tmp let-item="item" let-i="index">
<h5 class="mb-1 mt-0 font-weight-normal" [textContent]="item.value"></h5>
</ng-template>
<ng-template ng-label-tmp let-item="item">
<div class="media">
<div class="avatar-xs mr-1">
<span class="avatar-title rounded-circle font-11 font-weight-bold bg-soft-primary text-primary"><i class="fe-map-pin"></i></span>
</div>
<div class="media-body">
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="item.value"></h5>
</div>
</div>
</ng-template>
</ng-select>
</div>
</div>
<div class="col-12">
<div class="form-group">
<label class="mb-1">Specialization</label>
<ng-select class="ng-select-sm" [items]="specializations"
bindLabel="value"
bindValue="id"
autocomplete="nope"
placeholder="Select specialization"
formControlName="specializationId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No specializations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</div>
<div class="col-lg-12">
<h4 class="mb-1">Visits</h4>
<table class="table table-centered table-nowrap table-sm table-bordered mb-0">
<thead>
<tr>
<th>Name</th>
<th>Duration</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let visit of forms.visitArray.controls;let i = index;" [formGroup]="visit">
<td>
<input type="text" class="form-control-plaintext" readonly formControlName="name" placeholder="Charge Name">
</td>
<td>
<div class="form-group">
<!--<numeric-textbox type="number" formControlName="value" min="0" [max]="2000000" [decimals]="2" [autoCorrect]="true" [format]="currencySymbol + ' 0.00'" [placeholder]="'Enter Value'"></numeric-textbox>-->
<input type="number" class="form-control" numbersOnly formControlName="value" min="0" [placeholder]="'Enter Duration'" />
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService, ResourceService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { HttpErrorResponse } from "@angular/common/http";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { FormGroup, FormBuilder, FormArray, Validators } from "@angular/forms";
import { Page, IUserAccount, Pagination, IResource, GenericResponse } from "@shared/models";
import { LookUpModel } from "../../../services/models/look-up.model";
import { ProviderSpecialization } from "../../../../../shared/entities/provider-specialization.entity";
import { ProviderScheduleVisits } from "../../../../../shared/entities";
import { Role } from "@shared/enums";
import { Router } from "@angular/router";
class TrackBy {
providerSchedulerCharges(item: ProviderScheduleVisits) {
return item.providerId;
}
}
class FilterOptions {
locationId: number = null;
providerId: number = null;
specializationId: number = null;
departmentId: number = null;
createdBy: number = null;
active: boolean = true;
}
class Filters {
options: FilterOptions;
applied: boolean;
constructor() {
this.init();
}
init() {
this.options = new FilterOptions();
this.applied = undefined;
}
}
@Component({
templateUrl: "./provider-schedule-visits.html",
encapsulation: ViewEncapsulation.None
})
export class ProviderScheduleVisitsPage implements OnInit, OnDestroy {
page: Page;
filters: Filters;
trackBy: TrackBy;
pagination: Pagination;
providerScheduleVisitForm: FormGroup;
loading: boolean;
providerSchedulerVisits: Array<ProviderScheduleVisits>;
providerSchedulerVisitType: Array<ProviderScheduleVisits>;
modalRef: NgbModalRef;
submitting: boolean;
submitted: boolean;
modifying: boolean;
modifyingContent: string;
locations: Array<IResource>;
visitors: Array<LookUpModel>;
charges: Array<LookUpModel>;
loadingSpecializationResources: boolean;
loadingproviderResources: boolean;
currencySymbol = "₹";
providerSpecialization: Array<ProviderSpecialization>
isVisitTypeloading: boolean;
chargeDurationForm: FormGroup;
doctorCharges: Array<ProviderScheduleVisits>;
loadingSpecialization: boolean;
specializations: Array<IResource>;
loadingProviders: boolean;
providers: Array<IResource>;
locationId: number;
accounts: Array<IResource>;
loadingRoles: boolean;
encryptedProviderId: string;
currentLocation: number;
providerId: number;
constructor(
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly httpService: HttpService,
private readonly resourceService: ResourceService,
private readonly router: Router,
) {
this.buildForm();
this.page = new Page();
this.filters = new Filters();
this.trackBy = new TrackBy();
this.initPagination();
this.locations = new Array<IResource>();
this.doctorCharges = new Array<ProviderScheduleVisits>();
this.specializations = new Array<IResource>();
this.providers = new Array<IResource>();
this.providerSchedulerVisits = new Array<ProviderScheduleVisits>();
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
private fetchAccounts() {
this.loadingRoles = true;
const roleId = Role.Patient.toString();
this.resourceService.getAllAccountsExpectPassedRoleId(roleId)
.pipe(finalize(() => { this.loadingRoles = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.accounts = response;
});
}
private buildForm() {
this.providerScheduleVisitForm = this.formBuilder.group({
providerAvailabilityVisitTypeId: 0,
locationId: [this.currentLocation ? this.currentLocation : null, [Validators.required]],
specializationId: [null],
providerId: [this.encryptedProviderId != null || this.encryptedProviderId != undefined ? this.providerId : null],
active: [true],
visits: this.formBuilder.array([])
});
this.providerScheduleVisitForm.get("locationId").valueChanges.subscribe((value: number) => {
if (value) {
this.fetchDoctorSpecialization(null)
} else {
return this.providerSpecialization = undefined;
}
})
}
get chargeType() {
return this.chargeDurationForm.controls;
}
get chargeTypeFormArray() { return this.chargeDurationForm.controls["charges"] as FormArray }
get chargeForm() {
return this.chargeTypeFormArray;
}
addChargesToArray(typeId?: number, value?: number) {
return this.formBuilder.group({
chargeTypesId: [typeId ? typeId : null],
chargeTypeCharge: [value ? value : null],
});
}
addChargeTypeToArray(mainItem: LookUpModel, chargeValue?: string) {
return this.formBuilder.group({
typeId: [mainItem.id],
name: [mainItem.name],
value: [chargeValue ? chargeValue : 0]
});
}
onOpenModel(content: TemplateRef<any>, providerScheduleVisit?: ProviderScheduleVisits) {
this.buildForm();
if (providerScheduleVisit != undefined) {
this.fetchDoctorCharge(providerScheduleVisit);
}
if (providerScheduleVisit == undefined || providerScheduleVisit == null) {
this.fetchAddVisitTypes();
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
onChangeProvider(p: ProviderSpecialization) {
this.filters.options.specializationId = p.specializationId;
// console.log(a);
}
fetchDoctorCharge(providerScheduleCharge?: ProviderScheduleVisits) {
const request = {}
if (providerScheduleCharge != undefined) {
request["providerId"] = providerScheduleCharge.providerId;
request["specializationId"] = providerScheduleCharge.specializationId;
}
this.httpService
.post<Array<ProviderScheduleVisits>>(ApiResources.getURI(ApiResources.providerScheduleVisits.base, ApiResources.providerScheduleVisits.doctorVisit), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<ProviderScheduleVisits>) => {
this.doctorCharges = response;
let abc = [] // provider availability visit types with values
for (var item of response) {
abc.push({ id: item.id, name: item.name, value: item.value, providerAvailabilityVisitTypeId: item.providerAvailabilityVisitTypeId });
}
console.log(abc);
let visit = [] //visit types from masters for OP
for (var visittype of this.charges) {
visit.push({ id: visittype.id, name: visittype.name, value: 0, providerAvailabilityVisitTypeId: 0 })
}
visit.forEach(x => { // values which are not present in abc and present in visit pushed to abc.
if (!abc.find(y => y.id === x.id)) {
abc.push(x);
}
});
if (providerScheduleCharge) {
abc.forEach((item) => {
this.forms.visitArray.push(this.buildChargeForm(item));
});
this.doctorCharges.forEach((data) => {
this.providerScheduleVisitForm.patchValue({
providerId: data.providerId,
specializationId: data.specializationId,
startDate: data.startDate,
endDate: data.endDate,
providerAvailabilityVisitTypeId: data.providerAvailabilityVisitTypeId,
locationId: data.locationId,
visitTypeId: data.visitTypeId
})
})
}
},
() => {
this.doctorCharges = new Array<ProviderScheduleVisits>();
}
);
}
//onChangeProvider(event: ProviderSpecialization) {
// this.providerScheduleVisitForm.patchValue({
// specializationId: event.specializationId
// });
// this.filters.options.specializationId = event.specializationId;
// this.filters.options.departmentId = event.departmentId;
//}
//onChangeLocation(event: IResource) {
// this.fetchDoctorSpecialization(null, event.id)
//}
fetchProviderScheduleCharges() {
this.loading = true;
const request = Object.assign(UtilHelper.clone(this.filters.options), UtilHelper.clone(this.pagination));
if (!request.locationId) {
request.locationId = this.page.userAccount.locationId;
}
if (!request.providerId) {
request.specializationId = null;
}
if (this.encryptedProviderId != null || this.encryptedProviderId != undefined) {
request["encryptedProviderId"] = this.encryptedProviderId;
}
this.providerSchedulerVisits = new Array<ProviderScheduleVisits>();
this.httpService
.post<Array<ProviderScheduleVisits>>(ApiResources.getURI(ApiResources.providerScheduleVisits.base, ApiResources.providerScheduleVisits.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: any) => {
this.providerSchedulerVisits = response;
UtilHelper.applyPagination(this.providerSchedulerVisits, this.pagination);
},
() => {
this.providerSchedulerVisits = [];
}
);
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetchProviderScheduleCharges();
}
onSubmit() {
this.submitted = true;
if (!this.providerScheduleVisitForm.valid) {
this.notifyService.warningToast("Please fill all fields.")
return;
}
const request = Object.assign(UtilHelper.clone(this.providerScheduleVisitForm.getRawValue()));
let abc = request.visits.filter(m => m.value == null);
if (abc.length > 0) {
return this.notifyService.warningToast("Please provide Charge amount");
}
request["modifiedByName"] = this.page.userAccount.fullName;
request["visits"] = this.providerScheduleVisitForm.value.visits;
request.createdBy = this.page.userAccount.accountId;
if (request["providerAvailabilityVisitTypeId"] > 0) {
request["modifiedBy"] = this.page.userAccount.accountId;
}
this.submitting = true;
var url = ApiResources.getURI(ApiResources.providerScheduleVisits.base, ApiResources.providerScheduleVisits.add);
if (request["providerAvailabilityVisitTypeId"] > 0) {
url = ApiResources.getURI(ApiResources.providerScheduleVisits.base, ApiResources.providerScheduleVisits.update);
}
this.httpService.post(url, request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchProviderScheduleCharges();
this.notifyService.successToast(`Record ${request["providerAvailabilityVisitTypeId"] > 0 ? 'updated' : 'added'} successfully.`);
//this.notifyService.successToast("provider Schedule Visits has been added successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warningToast(errorMessage);
} else {
this.notifyService.defaultError();
}
});
}
get forms() {
return {
form: this.providerScheduleVisitForm ? this.providerScheduleVisitForm.controls : {},
visitArray: this.providerScheduleVisitForm.controls["visits"] as FormArray,
}
}
private buildChargeForm(charge: any) {
return this.formBuilder.group({
id: charge.id,
name: charge.name,
value: charge.value ? charge.value : 0,
providerAvailabilityVisitTypeId: charge.providerAvailabilityVisitTypeId ? charge.providerAvailabilityVisitTypeId : 0
});
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.loading = false;
this.submitting = undefined;
this.submitted = undefined;
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.currentLocation = this.page.userAccount.locationId;
const url = this.router.url;
this.encryptedProviderId = url.split("/")[url.split("/").length - 2];
if (this.encryptedProviderId == "masters") {
this.encryptedProviderId = null;
}
this.buildForm();
this.fetchLocations();
this.fetchAccounts();
this.fetchProviderScheduleCharges();
this.fetchLocationSpecialization(this.page.userAccount.locationId);
this.fetchProviders(this.page.userAccount.locationId);
this.fetchAddVisitTypes();
} else {
this.page.userAccount = undefined;
}
});
}
private fetchLocations() {
this.resourceService.locations()
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.locations = response;
this.filters.options.locationId = this.page.userAccount.locationId;
this.fetchDoctorSpecialization(this.filters.options.locationId)
});
}
fetchAddVisitTypes() {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.providerLocations.base, ApiResources.providerLocations.fetchVisitTypes), {})
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: GenericResponse) => {
this.charges = response.data as Array<LookUpModel>;
this.charges.forEach((charge) => {
const item = {
id: charge.id,
name: charge.name,
value: charge.value ? charge.value : 0
};
this.forms.visitArray.push(this.buildChargeForm(item));
});
},
() => {
this.charges = new Array<LookUpModel>();
}
);
}
private fetchDoctorSpecialization(locationId?: number) {
this.loading = true;
var request = {
locationId: locationId
}
this.httpService
.post<Array<ProviderSpecialization>>(ApiResources.getURI(ApiResources.providerScheduleVisits.base, ApiResources.providerScheduleVisits.fetchProviderSpecialization), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<ProviderSpecialization>) => {
this.providerSpecialization = response;
},
() => {
this.providerSpecialization = new Array<ProviderSpecialization>();
}
);
}
customSearch(term: string, item) {
term = term.toLocaleLowerCase();
return item['fullName'].toLocaleLowerCase().indexOf(term) > -1 || item['specializationName'].toLocaleLowerCase().indexOf(term) > -1;
}
onApplyFilters() {
this.filters.applied = UtilHelper.isFiltersApplied(this.filters.options);
this.initPagination();
this.loading = true;
this.fetchProviderScheduleCharges();
}
onResetFilters() {
this.filters.init();
this.loading = true;
this.filters.options.locationId = this.page.userAccount.locationId;
this.fetchProviderScheduleCharges();
this.fetchLocationSpecialization(this.page.userAccount.locationId);
}
onProviderSelect(provider?: IResource) {
if (provider != undefined) {
this.fetchProviderSpecializations(provider.id);
} if (provider == undefined) {
this.fetchLocationSpecialization(this.page.userAccount.locationId);
}
//this.fetchProviderSpecializations(provider.id);
if (provider) {
this.providerId = provider.id;
this.providerScheduleVisitForm.patchValue({
providerId: provider.id ? provider.id : null
});
} else {
this.providerScheduleVisitForm.patchValue({
providerId: null
});
}
}
providerChange() {
this.filters.options.specializationId = 1;
}
private fetchProviderSpecializations(providerId?: number) {
this.loadingSpecialization = true;
if (this.encryptedProviderId != null || this.encryptedProviderId != undefined) {
var encryptedProviderId = this.encryptedProviderId;
}
this.resourceService.providerSpecializations(providerId, encryptedProviderId, )
.pipe(finalize(() => { this.loadingSpecialization = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.specializations = response;
});
}
private fetchProviders(locationId?: number) {
this.loadingProviders = true;
if (this.encryptedProviderId != null || this.encryptedProviderId != undefined) {
var encryptedProviderId = this.encryptedProviderId;
}
this.resourceService.locationProviders(locationId, encryptedProviderId)
.pipe(finalize(() => { this.loadingProviders = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.providers = response;
if (this.encryptedProviderId != null || this.encryptedProviderId != undefined) {
this.onProviderSelect(response[0])
}
});
}
private fetchLocationSpecialization(locationId?: number) {
this.loadingSpecialization = true
if (this.encryptedProviderId != null || this.encryptedProviderId != undefined) {
var encryptedProviderId = this.encryptedProviderId;
}
this.resourceService.locationSpecializations(locationId, encryptedProviderId)
.pipe(finalize(() => { this.loadingSpecialization = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.specializations = response;
});
}
onChangeLocation(event: IResource) {
this.locationId = event.id;
this.fetchDoctorSpecialization(null)
this.fetchLocationSpecialization(event.id);
this.fetchProviders(event.id);
}
onChangeFilterLocation(event: IResource) {
this.locationId = event.id;
this.fetchLocationSpecialization(event.id);
this.fetchProviders(event.id);
}
onChangeStatus(record: ProviderScheduleVisits, status: boolean) {
const request = {
schedulerTypeId: record.schedulerTypeId,
active: status,
modifiedBy: this.page.userAccount.accountId,
roleId: this.page.userAccount.roleId
};
this.notifyService.confirm(`Do you really want to ${status ? "Active" : "Inactive"} this selected Charges?`, () => {
this.modifying = true;
this.modifyingContent = `${status ? "activating" : "inactivating"} the selected Component`;
this.httpService
.post(ApiResources.getURI(ApiResources.providerScheduleVisits.base, ApiResources.providerScheduleVisits.modifyStatus), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.modifying = false }))
.subscribe(
(response: number) => {
if (response > 0) {
switch (response) {
case 1:
this.notifyService.successToast("Status is updated successfully.");
this.fetchProviderScheduleCharges();
}
}
this.fetchProviderScheduleCharges();
},
() => {
}
);
}, () => {
});
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
fetchDoctorSpecializationHelper($event: any) {
if ($event && $event.term && $event.term.length > 1) {
// let locationId = this.quickScheduleForm.get("locationId").value
// let consultationTypeId = this.quickScheduleForm.get("consultationTypeId").value
this.fetchDoctorSpecialization(this.page.userAccount.locationId);
} else {
this.providerSpecialization = new Array<ProviderSpecialization>();
}
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<ng-container *menuButton="'HI5VYV'">
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(reasonTemplate)"><i class="fe-plus mr-1"></i> Add </button>
</ng-container>
</div>
<h4 class="page-title">Reasons</h4>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card-box p-0">
<div class="row p-2" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading ...</span>
</div>
</div>
</div>
<div class="row p-2" *ngIf="!loading && (!records || !records.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(reasonTemplate)"><i class="fe-plus mr-1"></i> Add </button>
</div>
</div>
</div>
<div class="table-responsive" *ngIf="!loading && records.length > 0">
<table class="table table-sm">
<thead class="table-info">
<tr>
<th> Reason</th>
<th>CreatedBy</th>
<th>Created Date</th>
<th>Modified By</th>
<th>Modified Date</th>
<th>Status</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of records;index as i;">
<td>
<span [textContent]="item.reason"></span>
</td>
<td>
<h5 class="font-13 mb-0" [textContent]="item.createdByName"></h5>
</td>
<td>
<span [textContent]="item.createdDate | date:'dd-MM-yyyy, hh:mm a'"></span>
</td>
<td>
<div *ngIf="item.modifiedBy">
<h5 class="font-13 mb-0" [textContent]="item.modifiedByName"></h5>
</div>
<span *ngIf="!item.modifiedBy">-----</span>
</td>
<td>
<span *ngIf="item.modifiedDate" [textContent]="item.modifiedDate | date:'dd-MM-yyyy, hh:mm a'"></span>
<span *ngIf="!item.modifiedDate">----</span>
</td>
<td>
<span class="badge badge-soft-success" *ngIf="item.active == true">Active</span>
<span class="badge badge-soft-danger" *ngIf="item.active == false">Inactive</span>
</td>
<td>
<div class="d-flex align-items-center justify-content-end">
<a href="javascript:;" class="action-icon text-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenModel(reasonTemplate, item)"><i class="fe-edit"></i></a>
<a href="javascript:;" class="action-icon text-danger" placement="left" ngbTooltip="Delete" (click)="onDelete(item)"><i class="fe-trash-2"></i></a>
<button type="button" class="btn btn-xs btn-outline-success" *ngIf="item.active == true" title="Active" (click)="onModifyStatus(item,false)">
<i class="fe-delete"></i>
</button>
<button type="button" class="btn btn-xs btn-outline-danger" *ngIf="item.active == false" title="Inactive" (click)="onModifyStatus(item,true)">
<i class="fe-check"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #reasonTemplate>
<form [formGroup]="reasonForm" (ngSubmit)="onSubmit()">
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-human-edit mr-1"></i>{{reasonForm.value.reasonId === 0 ? 'Add' : 'Edit'}} Reason</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-12">
<div class="form-group">
<label class="mb-1">Reason <code>*</code></label>
<input type="text" class="form-control" placeholder="Enter Reason." formControlName="reason" textOnly
[ngClass]="{ 'is-invalid': submitted && form.reason.errors }" />
<div class="text-danger" *ngIf="submitted && form.reason.errors">
<p *ngIf="form.reason.errors.required">Reason is required.</p>
<p *ngIf="form.reason.errors.maxlength">Only 250 characters are allowed.</p>
<p *ngIf="form.reason.errors.whiteSpaces">Please remove white space...</p>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
\ No newline at end of file
import { OnInit, OnDestroy, Component, TemplateRef } from "@angular/core";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { Page, IUserAccount } from "@shared/models";
import { AppData, HttpService, NotifyService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { HttpErrorResponse } from "@angular/common/http";
import { Reasons } from "@shared/entities";
import { WhiteSpaceValidator } from "../../../../../shared/validators";
@Component({
templateUrl: "./reasons.html",
})
export class ReasonPage implements OnInit, OnDestroy {
page: Page;
loading: boolean;
modalRef: NgbModalRef;
submitting: boolean;
submitted: boolean;
reasonForm: FormGroup;
records: Array<Reasons>;
constructor(
private readonly appData: AppData,
private readonly httpService: HttpService,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
) {
this.loading = true;
this.page = new Page();
this.buildForm();
this.records = new Array<Reasons>();
}
private buildForm() {
this.reasonForm = this.formBuilder.group({
reasonsId: 0,
reason: [null, [Validators.required, Validators.maxLength(250), WhiteSpaceValidator.isValid]],
});
}
get form() { return this.reasonForm.controls; }
onOpenModel(content: TemplateRef<any>, record?: Reasons) {
this.buildForm();
if (record) {
this.reasonForm.patchValue({
reasonsId: record.reasonsId,
reason: record.reason
});
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: false,
windowClass: "custom-modal effect-scale"
});
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.loading = false;
this.submitting = undefined;
this.submitted = undefined;
}
onSubmit() {
this.submitted = true;
if (this.reasonForm.invalid) {
return;
}
this.submitting = true;
const request = {
...this.reasonForm.getRawValue(),
createdBy: this.page.userAccount.accountId,
modifiedBy: this.page.userAccount.accountId,
loginRoleId: this.page.userAccount.roleId,
createdByName: this.page.userAccount.fullName,
modifiedByName: this.page.userAccount.fullName,
};
var url = ApiResources.getURI(ApiResources.reason.base, ApiResources.reason.insert);
if (request["reasonsId"] > 0) {
url = ApiResources.getURI(ApiResources.reason.base, ApiResources.reason.update);
}
this.httpService.post(url, request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitted = this.submitting = false))
.subscribe(
(response: number) => {
if (response > 0) {
this.notifyService.successToast(`Record ${request["reasonsId"] > 0 ? 'updated' : 'added'} successfully.`);
}
if (response === -1) {
this.notifyService.warningToast("This Reasons already exists.");
return;
}
this.onCloseModal();
this.fetchAll();
},
(error: HttpErrorResponse) => {
this.notifyService.errorToast(error.error);
}
);
}
onDelete(record: Reasons) {
this.notifyService.delete(() => {
const request = {
reasonsId: record.reasonsId,
reason: record.reason,
createdBy: this.page.userAccount.accountId,
createdByName: this.page.userAccount.fullName,
loginRoleId: this.page.userAccount.roleId,
modifiedByName: this.page.userAccount.fullName
};
this.httpService.post(ApiResources.getURI(ApiResources.reason.base, ApiResources.reason.delete), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
() => {
this.notifyService.successToast("Record deleted successfully.");
this.fetchAll();
},
(error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
}
);
})
}
onModifyStatus(reason: Reasons, status: boolean) {
this.notifyService.confirm(`You want to ${status ? 'Activate' : 'Deactivate'} this Reasons?`, () => {
const request = {
createdBy: this.page.userAccount.accountId,
active: status,
reasonsId: reason.reasonsId,
createdByName: this.page.userAccount.fullName,
createdByRole: this.page.userAccount.roleName,
loginRoleId: this.page.userAccount.roleId,
modifiedBy: this.page.userAccount.accountId,
modifiedByName: this.page.userAccount.fullName,
reason: reason.reason
};
this.httpService.post(ApiResources.getURI(ApiResources.reason.base, ApiResources.reason.modifyStatus), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loading = false }))
.subscribe((response: number) => {
if (response > 0) {
this.notifyService.successToast(`${status ? 'Activated' : 'Deactivated'} successfully.`);
}
this.fetchAll();
}, (error: HttpErrorResponse) => {
this.notifyService.errorToast(error.error);
});
});
}
private fetchAll() {
this.loading = true;
const request = {
};
this.httpService.post(ApiResources.getURI(ApiResources.reason.base, ApiResources.reason.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: Array<Reasons>) => {
this.records = response;
},
(error: HttpErrorResponse) => {
this.notifyService.errorToast(error.error);
}
);
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetchAll();
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModel(templateModule)"><i class="fe-plus mr-1"></i> Add Reference</button>
</div>
<h4 class="page-title">References</h4>
</div>
</div>
</div>
<div>
<div class="col-12">
<div class="card-box p-0">
<div class="table-responsive">
<table class="table table-centered table-sm table-striped table-borderless mb-0">
<thead>
<tr>
<th> Name</th>
<th>CreatedBy</th>
<th>Created Date</th>
<th>Modified By</th>
<th>Modified Date</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let reference of references;let i = index;">
<td [textContent]="reference.name"></td>
<td>
<h5 class="font-13 mb-0" [textContent]="reference.createdByName"></h5>
<!--<span class="badge badge-outline-info font-11" [textContent]="reference.createdByRole"></span>-->
</td>
<td>
<span [textContent]="reference.createdDate | date:'dd-MM-yyyy, hh:mm a'"></span>
</td>
<td>
<div *ngIf="reference.modifiedBy">
<h5 class="font-13 mb-0" [textContent]="reference.modifiedByName"></h5>
<!--<span class="badge badge-outline-secondary font-11" [textContent]="reference.modifiedByRole"></span>-->
</div>
<span *ngIf="!reference.modifiedBy">-----</span>
</td>
<td>
<span *ngIf="reference.modifiedDate" [textContent]="reference.modifiedDate | date:'dd-MM-yyyy, hh:mm a'"></span>
<span *ngIf="!reference.modifiedDate">----</span>
</td>
<td>
<div class="d-flex align-items-center justify-content-end">
<a href="javascript:;" class="action-icon text-primary mr-1" placement="left" ngbTooltip="Edit" (click)="onOpenModel(templateModule, reference)"><i class="fe-edit"></i></a>
<a href="javascript:;" class="action-icon text-danger" placement="left" ngbTooltip="Delete" (click)="onDelete(reference)"><i class="fe-trash-2"></i></a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<!--referenceTypeId Name-->
<ng-template #templateModule>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-mother-nurse mr-1"></i> Reference Types</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<form [formGroup]="moduleForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group mb-3">
<label class="mb-1">Reference Type <code>*</code></label>
<div class="form-group">
<input tabindex="1" type="text" block maxlength="150" autofocus formControlName="name" autocomplete="nope" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.name.errors) }" placeholder="Enter Reference Type" />
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
\ No newline at end of file
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { AppData, HttpService, NotifyService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { Page, IUserAccount } from "@shared/models";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { HttpErrorResponse } from "@angular/common/http";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { NgbModalRef, NgbModal } from "@ng-bootstrap/ng-bootstrap";
import { ReferenceTypes } from "@shared/entities";
@Component({
templateUrl: "./reference-types.html",
encapsulation: ViewEncapsulation.None
})
export class ReferenceTypePage implements OnInit, OnDestroy {
page: Page;
loading: boolean;
modalRef: NgbModalRef;
submitted: boolean;
submitting: boolean;
moduleForm: FormGroup;
references: Array<ReferenceTypes>;
selectedModule: ReferenceTypes;
constructor(
private readonly appData: AppData,
private readonly formBuilder: FormBuilder,
private readonly modalService: NgbModal,
private readonly httpService: HttpService,
private readonly notifyService: NotifyService
) {
this.page = new Page();
this.references = new Array<ReferenceTypes>();
this.selectedModule = new ReferenceTypes();
}
private buildForm() {
this.moduleForm = this.formBuilder.group({
patientReferredById: 0,
name: [null, [Validators.required]],
})
}
onOpenModel(content: TemplateRef<any>, module?: ReferenceTypes) {
this.buildForm();
if (module) {
this.selectedModule = module;
this.updateForm();
}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale"
});
}
private updateForm() {
this.moduleForm.patchValue({
patientReferredById: this.selectedModule.patientReferredById,
name: this.selectedModule.name
});
}
get form() {
return this.moduleForm.controls;
}
private fetchAllReferences() {
this.loading = true;
const request = {};
this.httpService.post<Array<ReferenceTypes>>(ApiResources.getURI(ApiResources.referenceTypes.base, ApiResources.referenceTypes.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe((response: Array<ReferenceTypes>) => {
this.references = response;
});
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.fetchAllReferences();
} else {
this.page.userAccount = undefined;
}
});
this.buildForm();
}
onResetForm() {
this.submitted = this.submitting = false;
this.buildForm();
}
onSubmit() {
this.submitted = true;
if (!this.moduleForm.valid) {
return;
}
this.submitting = true;
const request = {
...this.moduleForm.getRawValue(),
createdBy: this.page.userAccount.accountId,
loginRoleId: this.page.userAccount.roleId,
createdByName: this.page.userAccount.fullName
}
if (this.moduleForm.value.patientReferredById === 0) {
request["createdBy"] = this.page.userAccount.accountId;
this.httpService.post<number>(ApiResources.getURI(ApiResources.referenceTypes.base, ApiResources.referenceTypes.add), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
this.page.loading = false;
}))
.subscribe((response: number) => {
if (response > 0) {
this.notifyService.successToast(`Reference created successfully.`);
}
if (response === -1) {
this.notifyService.warningToast("This reference already exists.");
}
if (response === -2) {
this.notifyService.warningToast("Unable to update roles.");
}
this.onCloseModal();
this.fetchAllReferences();
});
}
else {
request.modifiedBy = this.page.userAccount.accountId;
request["modifiedByName"] = this.page.userAccount.fullName;
//delete request.type;
this.httpService.post(ApiResources.getURI(ApiResources.referenceTypes.base, ApiResources.referenceTypes.update), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.submitting = false;
this.submitted = false;
}))
.subscribe(() => {
this.onCloseModal();
this.fetchAllReferences();
this.notifyService.successToast("Module details has been updated successfully.");
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warningToast(errorMessage);
} else {
this.notifyService.defaultErrorToast();
}
});
}
}
onDelete(record: ReferenceTypes) {
this.notifyService.confirm(
`Are you sure to Delete <span class='font-weight-bold'>${record.name}</span>`,
() => {
const request = {
patientReferredById: record.patientReferredById,
idProofName: record.name,
createdBy: this.page.userAccount.accountId,
loginRoleId: this.page.userAccount.roleId,
createdByName: this.page.userAccount.fullName
};
this.httpService
.post(ApiResources.getURI(ApiResources.referenceTypes.base, ApiResources.referenceTypes.delete), request)
.pipe(takeUntil(this.page.unSubscribe))
.subscribe(
() => {
this.notifyService.successToast("Module deleted successfully.");
this.fetchAllReferences();
},
() => {
this.notifyService.defaultErrorToast();
}
);
}
);
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
}
ngOnDestroy() {
this.onCloseModal();
this.page.unsubscribeAll();
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button type="button" class="btn btn-primary btn-sm" *ngIf="!loading && specialization && specialization.length" (click)="onOpenModal(templateSpecialization)"><i class="fe-plus mr-1"></i> Add Specialization</button>
</div>
<h4 class="page-title">
Specializations
</h4>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading specialization ...</span>
</div>
</div>
</div>
<div class="col-12 p-0">
<div class="card-box mb-1 p-1">
<table class="table table-borderless table-sm mb-0">
<tr style="font-size:12px;" class="myFlex">
<td class="col-6 col-sm-3">
<div class="form-group mb-0">
<label class="mb-1">Locations </label>
<ng-select class="ng-select-sm text-uppercase" [items]="locations"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select locations"
[(ngModel)]="filters.options.locationId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No locations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</td>
<td class="col-6 col-sm-3">
<div class="form-group mb-0">
<label class="mb-1">Specialization </label>
<ng-select class="ng-select-sm text-uppercase" [items]="specializationsAll"
bindLabel="value"
bindValue="id"
autocomplete="nope"
placeholder="Select Specializations"
[(ngModel)]="filters.options.specializationId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No specialization found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</td>
<td class="col-6 col-sm-3">
<div class="form-group mb-0">
<label class="mb-1">Status</label>
<select class="form-control form-control-md" [(ngModel)]="filters.options.active">
<option [ngValue]="null">All</option>
<option [ngValue]="true">Active</option>
<option [ngValue]="false">Inactive</option>
</select>
</div>
</td>
<td class="col-6 col-sm-3 align-middle">
<div style="margin-top: 25px;" class="d-flex justify-content-center justify-content-lg-start">
<button type="button" (click)="onApplyFilters()" class="btn btn-sm btn-outline-primary m-0">Search</button>
<button type="button" (click)="onResetFilters()" class="btn btn-sm btn-outline-danger ml-1 mb-0">Reset</button>
</div>
</td>
</table>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && (!specialization || !specialization.length)">
<div class="col-12 mh-400">
<div class="no-data">
<img src="assets/images/no-data.png" alt="No data" />
<h4 class="title">Oops! No specialization found.</h4>
<p class="sub-title">There is no data to show you right now.</p>
<button type="button" class="btn btn-primary btn-sm" (click)="onOpenModal(templateSpecialization)"><i class="fe-plus mr-1"></i> Add Specialization</button>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && specialization && specialization.length">
<div class="col-12 p-0">
<div class="card mb-0">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-centered table-sm table-striped table-borderless">
<thead>
<tr>
<th>Specialization</th>
<th>Avaliable At</th>
<th>Description</th>
<th>Status</th>
<!--<th>Priority</th>-->
<th class="text-right" style="width: 85px">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of specialization;let i = index;">
<td>
<div class="media">
<!--<div class="avatar-sm mr-2">
<avatar-img *ngIf="item.url" [src]="safe(item.url)" [alt]="item.specializationName" cssClass="img-fluid rounded-circle bg-primary"></avatar-img>
<span *ngIf="!item.url" class="avatar-title rounded-circle font-11 font-weight-bold text-white" avatar-bg [index]="i" [textContent]="item.specializationName | initials"></span>
</div>-->
<div class="media-body">
<h5 class="mb-0 mt-0 font-weight-normal" [textContent]="item.specializationName"></h5>
</div>
</div>
</td>
<td [textContent]="item.locationNames || '---'"></td>
<td>
<span *ngIf="item.specializationDescription" [textContent]="item.specializationDescription"></span>
<span *ngIf="!item.specializationDescription">----</span>
</td>
<td>
<span class="badge badge-soft-success" *ngIf="item.active">Active</span>
<span class="badge badge-soft-danger" *ngIf="!item.active">Inactive</span>
</td>
<!--<td>
<span class="badge badge-soft-success" *ngIf="item.priority === 1 && item.active">High</span>
<span class="badge badge-soft-success" *ngIf="item.priority === 2 && item.active">Medium</span>
<span class="badge badge-soft-success" *ngIf="item.priority === 3 && item.active">Low</span>
<span class="badge badge-soft-success" *ngIf="!item.priority && item.active">Low</span>
</td>-->
<td>
<div class="d-flex align-items-center justify-content-end">
<a class="action-icon text-primary mr-1" href="javascript:;" placement="left" ngbTooltip="Edit" (click)="onOpenModal(templateSpecialization, item)"><i class="fe-edit"></i></a>
<a class="action-icon text-primary mr-1" href="javascript:;" placement="left" ngbTooltip="{{item.active?'Reject':'Approve'}}" (click)="updateStatus(item)"><i *ngIf="item.active" class="fe-x"></i><i *ngIf="!item.active" class="fe-check"></i></a>
<!--<a class="action-icon text-danger" href="javascript:;" placement="left" ngbTooltip="Delete" (click)="onDelete(item)"><i class="fe-trash-2"></i></a>-->
</div>
</td>
</tr>
</tbody>
</table>
</div>
<nav class="d-flex align-items-center justify-content-between p-2" *ngIf="pagination.totalPages > 1">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="pagination.currentPage"></span> of <span [textContent]="pagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="pagination.currentItems - specialization.length + 1"></span> - <span [textContent]="pagination.currentItems"></span> of <span [textContent]="pagination.totalItems"></span> specializations)</span>
</span>
</p>
<!--<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="false" [ellipses]="false" [(page)]="pagination.pageIndex" [pageSize]="pagination.pageSize" (pageChange)="onNextPage()" [collectionSize]="pagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>-->
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateSpecialization>
<form [formGroup]="uploadForm" (ngSubmit)="onSubmit()">
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-file-multiple mr-1"></i>{{uploadForm.value.specializationId === 0 ? 'Add' : 'Edit'}} Specialization</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Specialization Name <code>*</code></label>
<input type="text" class="form-control" formControlName="specializationName" [ngClass]="{ 'is-invalid': (submitted && form.specializationName.errors) }" placeholder="Enter full name" />
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="mb-1">Locations <code>*</code> </label>
<ng-select class="ng-select-sm text-uppercase" [items]="locations"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select locations"
[ngClass]="{ 'is-invalid': submitted && form.locationIds.errors }"
[multiple]="true"
formControlName="locationIds">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No locations found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
<div *ngIf="submitted && form.locationIds.errors" class="invalid-feedback show-must">
<div *ngIf="form.locationIds.errors.required">Location is required.</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label class="mb-1">Encounter For Specialization</label>
<ng-select class="ng-select-sm text-uppercase" [items]="encounterType"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select Encounter Type"
[ngClass]="{ 'is-invalid': submitted && form.encounterTypeId.errors }"
formControlName="encounterTypeId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No encounter type found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
<div *ngIf="submitted && form.encounterTypeId.errors" class="invalid-feedback show-must">
<div *ngIf="form.encounterTypeId.errors.required">Encounter Type is required.</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label>Priority</label>
<select class="form-control custom-select form-control-sm" autocomplete="nope" formControlName="priority">
<option [textContent]="'High'" [ngValue]="1"></option>
<option [textContent]="'Medium'" [ngValue]="2"></option>
<option [textContent]="'Low'" [ngValue]="3"></option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label>Description</label>
<textarea class="form-control" formControlName="specializationDescription" placeholder="Enter description"></textarea>
</div>
</div>
</div>
<div class="row">
<div class="col-12 mt-2" *ngIf="uploadForm.value.specializationIconId != 0">
<label>Icon</label>
<img [src]="safe(uploadForm.value.url)" style="cursor: pointer" class="icon-image" height="150" width="100" alt="SelectedIcon" />
<div class="mt-1">
<button type="button" style="margin-left: 30px;" (click)="onEditIcon()" class="btn btn-sm btn-primary ml-1">Edit</button>
<!--<button type="button" style="margin-left: 30px;" (click)="onRemoveIcon()" class="btn btn-sm btn-danger ml-1">Delete</button>-->
</div>
</div>
</div>
<div class="row">
<div class="col-12 mt-2" *ngIf="uploadForm.value.specializationIconId === 0 && icons.length > 0">
<label class="mb-1">Icons</label>
<div class="row">
<div class="col-3 col-md-2 mb-1" *ngFor="let icon of icons">
<img [src]="safe(icon.url)" (click)="onIconSelect(icon)" style="cursor: pointer" class="icon-image" height="100" width="100" [alt]="icon.iconName" />
</div>
<div class="col-12 mt-1">
<nav class="d-flex align-items-center justify-content-between p-2" *ngIf="iconPagination.totalPages > 1">
<p class="mb-0 font-13">
<span class="text-dark">Page <span [textContent]="iconPagination.currentPage"></span> of <span [textContent]="iconPagination.totalPages"></span></span>
<span class="ml-1">
<span>(Showing <span [textContent]="iconPagination.currentItems - icons.length + 1"></span> - <span [textContent]="iconPagination.currentItems"></span> of <span [textContent]="iconPagination.totalItems"></span> Icons)</span>
</span>
</p>
<!--<ngb-pagination class="pagination justify-content-end" [maxSize]="5" [rotate]="true" [ellipses]="true" [(page)]="iconPagination.pageIndex" [pageSize]="iconPagination.pageSize" (pageChange)="fetchIcons()" [collectionSize]="iconPagination.totalItems">
<ng-template ngbPaginationPrevious><i class="fe-arrow-left"></i></ng-template>
<ng-template ngbPaginationNext><i class="fe-arrow-right"></i></ng-template>
</ngb-pagination>-->
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default btn-sm" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm ml-1">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</div>
</form>
</ng-template>
\ No newline at end of file
import { Component, OnDestroy, OnInit, ViewEncapsulation, TemplateRef } from "@angular/core";
import { Router } from "@angular/router";
import { IUserAccount, Page, Pagination, IResource, IconModel } from "@shared/models";
import { Specialization } from "@shared/entities";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { AppData, HttpService, NotifyService, ResourceService } from "@shared/services";
import { takeUntil, finalize } from "rxjs/operators";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { HttpErrorResponse } from "@angular/common/http";
import { WhiteSpaceValidator } from "../../../../../shared/validators";
import { FormsModule } from '@angular/forms';
class TrackBy {
special(item: Specialization) {
return item.specializationId;
}
resource(item: IResource) {
return item.id;
}
}
class FilterOptions {
specializationId?: number = null;
locationId?: number = null;
active?: boolean = true;
}
class Filters {
options: FilterOptions;
applied: boolean;
constructor() {
this.init();
}
init() {
this.options = new FilterOptions();
this.applied = undefined;
}
}
@Component({
templateUrl: "./specializations.html",
encapsulation: ViewEncapsulation.None
})
export class SpecializationPage implements OnInit, OnDestroy {
page: Page;
pagination: Pagination;
trackBy: TrackBy;
activeRoute: string;
isEdit: boolean = false;
filters: Filters;
specialization: Array<Specialization>;
selectedSpecialization: Specialization;
loading: boolean;
modalRef: NgbModalRef;
uploadForm: FormGroup;
modifying: boolean;
icons: Array<IconModel>;
iconLoading: boolean;
iconPagination: Pagination;
submitting: boolean;
submitted: boolean;
errorMessage: string;
warningMessage: string;
modifyingContent: string;
locations: Array<IResource>;
specializationsAll: Array<IResource>;
loadingSpecialization: boolean;
specializationForm: FormGroup;
encounterType: IResource[];
constructor(
private readonly appData: AppData,
private readonly httpService: HttpService,
private readonly router: Router,
private readonly modalService: NgbModal,
private readonly notifyService: NotifyService,
private readonly formBuilder: FormBuilder,
private readonly resourceService: ResourceService
) {
this.page = new Page();
this.icons = new Array<IconModel>();
this.initIconPagination();
//this.buildSpecializationForm();
this.buildspecializationAllForm();
this.trackBy = new TrackBy();
this.filters = new Filters();
}
safe = (url: any) => {
if (url) {
return `assets/images/SpecializationIcons/${url}`
}
}
private initPagination() {
this.pagination = new Pagination();
this.pagination.pageIndex = 1;
this.pagination.pageSize = 10;
}
private initIconPagination() {
this.iconPagination = new Pagination();
this.iconPagination.pageIndex = 1;
this.iconPagination.pageSize = 12;
}
//private buildSpecializationForm() {
// this.uploadForm = this.formBuilder.group({
// specializationName: ["", [Validators.required]],
// specializationActive: [false, [Validators.required]],
// specializationIconId: [0],
// specializationJson: [null],
// specializationDescription: [""],
// locationId: [0],
// url: [null],
// priority: [null]
// //createdBy: [this.page.userAccount.accountId, [Validators.required]]
// });
//}
private buildspecializationAllForm() {
this.specializationForm = this.formBuilder.group({
specializationIds: [0],
locatlocationIds: [0]
});
}
onApplyFilters() {
this.filters.applied = UtilHelper.isFiltersApplied(this.filters.options);
this.loading = true;
this.fetchSpecializations();
this.onCloseFilters();
}
onCloseFilters() {
$("body").removeClass("right-bar-enabled");
}
onResetFilters() {
this.loading = true;
this.filters.init();
this.fetchSpecializations();
this.onCloseFilters();
}
private fetchSpecializations() {
this.loading = true;
const request = {
...this.pagination,
...this.filters.options
};
this.httpService.post(ApiResources.getURI(ApiResources.specialization.base, ApiResources.specialization.fetch), request)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loading = false }))
.subscribe((response: Array<any>) => {
this.specialization = response;
UtilHelper.applyPagination(this.specialization, this.pagination);
});
}
private fetchSpecializationsAll() {
this.loadingSpecialization = true;
this.resourceService.specializations()
.pipe(finalize(() => { this.loadingSpecialization = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.specializationsAll = response;
});
}
private buildForm() {
this.uploadForm = this.formBuilder.group({
specializationId: 0,
specializationIconId: 0,
specializationName: [null, [Validators.required, WhiteSpaceValidator.isValid]],
specializationDescription: "",
url: "",
priority: 3,
locationIds: [null, [Validators.required]],
encounterTypeId: [null]
});
}
get form() { return this.uploadForm.controls }
onOpenModal(content: TemplateRef<any>, specialization?: Specialization) {
this.fetchLocations();
this.fetchEncounterType();
this.buildForm();
this.fetchIcons();
if (specialization) {
var locationIds = new Array<number>();
if (specialization && specialization.locationIds) {
specialization.locationIds.split(",").forEach((item) => {
locationIds.push(parseInt(item))
});
}
//let locationIds = new Array<number>();
//specialization.locationIds.split(",").forEach((item) => { locationIds.push(parseInt(item)) });
this.uploadForm.patchValue({
specializationId: specialization.specializationId,
specializationIconId: specialization.specializationIconId,
specializationName: specialization.specializationName,
specializationDescription: specialization.specializationDescription,
url: specialization.url,
priority: specialization.priority,
locationIds: locationIds,
encounterTypeId: specialization.encounterTypeId
});
}
this.modalRef = this.modalService.open(content, {
keyboard: false,
centered: true,
windowClass: "custom-modal effect-scale",
backdrop: "static",
size: "lg"
});
}
onSubmit() {
this.submitted = true;
if (!this.uploadForm.valid) {
return;
}
this.errorMessage = undefined;
this.submitting = true;
const model = Object.assign(UtilHelper.clone(this.uploadForm.getRawValue()));
//if (model.locationIds) {
// model.locationIds = model.locationIds.join(",")
//}
if (model["locationIds"]) {
model["locationIds"] = model.locationIds.join(",");
}
if (model["specializationId"] === 0) {
model["createdBy"] = this.page.userAccount.accountId;
model["createdByName"] = this.page.userAccount.fullName;
model["loginRoleId"] = this.page.userAccount.roleId;
this.httpService
.postFile(ApiResources.getURI(ApiResources.specialization.base, ApiResources.specialization.add), model)
.pipe(finalize(() => { this.submitted = false, this.submitting = false; }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe(
() => {
this.notifyService.success("Specialization added successfully.");
this.onCloseModal();
this.fetchSpecializationsAll();
this.fetchSpecializations();
},
(error: HttpErrorResponse) => {
this.errorMessage = UtilHelper.handleError(error);
this.notifyService.warning(this.errorMessage);
}
);
} else {
model["modifiedBy"] = this.page.userAccount.accountId;
model["modifiedByName"] = this.page.userAccount.fullName;
model["loginRoleId"] = this.page.userAccount.roleId;
this.httpService
.put(ApiResources.getURI(ApiResources.specialization.base, ApiResources.specialization.update), model)
.pipe(finalize(() => { this.submitted = false, this.submitting = false; }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe(
() => {
this.notifyService.success("Specialization details updated successfully.");
this.onCloseModal();
this.fetchSpecializationsAll();
this.fetchSpecializations();
},
(error: HttpErrorResponse) => {
this.errorMessage = UtilHelper.handleError(error);
this.notifyService.warning(this.errorMessage);
}
);
}
}
onDelete(specialization: Specialization) {
specialization.modifiedBy = this.page.userAccount.accountId;
this.notifyService.delete(() => {
this.httpService
.post(ApiResources.getURI(ApiResources.specialization.base, ApiResources.specialization.delete), { specializationId: specialization.specializationId })
.pipe(takeUntil(this.page.unSubscribe))
.subscribe(
() => {
this.notifyService.success("specialization deleted successfully.");
this.fetchSpecializationsAll();
this.fetchSpecializations();
}
);
});
}
onCloseModal() {
if (this.modalRef) {
this.modalRef.close();
this.modalRef = undefined;
this.submitted = undefined;
this.submitting = undefined;
this.errorMessage = undefined;
this.warningMessage = undefined;
this.modifyingContent = undefined;
}
}
onNextPage() {
$("body,html").animate({ scrollTop: 0 });
this.fetchSpecializations();
}
onIconSelect(icon: IconModel) {
this.uploadForm.patchValue({
specializationIconId: icon.iconsId,
url: icon.url
});
}
//onRemoveIcon() {
// this.uploadForm.patchValue({
// specializationIconId: null
// });
//}
onEditIcon() {
this.uploadForm.patchValue({
specializationIconId: 0
});
}
fetchIcons() {
const model = {
pageSize: this.iconPagination.pageSize,
pageIndex: this.iconPagination.pageIndex
};
this.iconLoading = true;
this.httpService.post(ApiResources.getURI(ApiResources.icons.base, ApiResources.icons.fetchIcons), model)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => {
this.iconLoading = false;
}))
.subscribe((response: Array<IconModel>) => {
this.icons = response;
UtilHelper.applyPagination(this.icons, this.iconPagination);
}, (error: HttpErrorResponse) => {
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning("Error occurred while fetching icons.");
} else {
this.notifyService.defaultError();
}
});
}
updateStatus(specialization: Specialization) {
specialization.modifiedBy = this.page.userAccount.accountId;
this.httpService
.put(ApiResources.getURI(ApiResources.specialization.base, ApiResources.specialization.modifyStatus), specialization)
.subscribe(() => {
specialization.active = !specialization.active;
this.fetchSpecializations();
});
}
private fetchLocations() {
this.resourceService.locations()
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.locations = response;
});
}
private fetchEncounterType() {
this.resourceService.encounterType()
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.encounterType = response;
});
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((account: IUserAccount) => {
if (account) {
this.page.userAccount = account;
const url = this.router.url;
this.activeRoute = url.split("/")[url.split("/").length - 1];
this.initPagination();
this.fetchSpecializationsAll();
this.fetchSpecializations();
this.fetchLocations();
this.fetchEncounterType();
} else {
this.page.userAccount = undefined;
}
});
}
ngOnDestroy() {
this.page.unsubscribeAll();
}
}
\ No newline at end of file
export * from "./services.page";
export * from "./pages/orders/orders.page";
export * from "./pages/receipts/receipts.page";
export * from "./pages/final-bill/final-bill.page";
export * from "./pages/discharge/discharge.page";
export * from "./pages/discharge-patient/discharge-patient.page";
export * from "./pages/gate-pass/gate-pass.page";
export * from "./pages/provisional-gate-pass/provisional-gate-pass.page";
\ No newline at end of file
export interface IAdmissionPackageModel {
unit: number;
cost: number;
admissionPackageId: number;
packageId: number;
totalGeneral: number;
totalMedicines: number;
totalKits: number;
totalLabs: number;
name: string;
active: boolean;
createdDate: Date;
modifiedDate: Date;
createdByName: string;
modifiedByName: string;
}
export interface IAdmissionPackageModuleModel {
admissionPackageId: number;
packageModuleId: number;
packageName: string;
moduleTypeId: number;
moduleTypeName: string;
quantity: number;
freeQuantity: number;
expiresIn?: number;
total: number;
counselingId?: number;
active: boolean;
createdDate: Date;
modifiedDate: Date;
createdByName: string;
modifiedByName: string;
appointmentId?: number;
admissionId?: number;
}
\ No newline at end of file

export interface IAdmissionModel {
fullName: string;
fatherOrHusband: string;
gender: string;
age: number;
thumbnailUrl: string;
admissionNo: string;
departmentName: string;
admissionDate: Date;
admissionTime: Date;
attendantName: string;
timeString: string;
attendantContactNo: string;
attendantRelationWithPatient: string;
isDischarged: boolean;
providerName: string;
providerGender: string;
umrNo: string;
bedNumber: string;
roomName: string;
wardName: string;
mobile: string;
status: string;
dischargeDate: Date;
dischargeTime: Date;
dischargeTimeString: string;
expectedDischargeDate: Date;
encryptedProviderId: string;
providerId: string;
patientId: number;
chargeCategoryName: string;
admissionPayTypeName: string;
streetAddress: string;
addressLine2: string;
city: string;
state: string;
zipcode: string;
fullAddress: string;
floorName: string;
locationName: string;
chargeCategoryId: number;
}
\ No newline at end of file
export enum AutomaticType
{
BedCharges = 1,
DoctorCharges = 2
}
\ No newline at end of file
import { RepeatType } from "./repeat-type.model";
import { AutomaticType } from "./automatic-type.model";
import { DiscountType } from "./discount-type.model";
export interface IChargeModel {
chargeId: number;
productId: number;
cost: number;
opCost: number;
chargeName: string;
chargeGroupName: string;
departmentName: string;
serviceOrderId: number;
unit: number;
totalCost: number;
discountAmount: number;
discountPercentage: number;
discountType: DiscountType;
discount: number;
status: boolean;
repeatTypeId: RepeatType;
automaticTypeId: AutomaticType;
active: boolean;
createdDate: Date;
modifiedDate: Date;
createdByName: string;
modifiedByName: string;
isMain: boolean;
departmentId: number;
chargeGroupId: number;
repeatTypeName: string;
automaticTypeName: string;
deleting: boolean;
totalItems: number;
chargeTypeMainId: number;
chargeTypeMainName: string;
chargeTypeId: number;
chargeTypeName: string;
// Package Module
showAmount: boolean;
isInPackage: boolean;
admissionPackageId?: number;
packageModuleDetailId?: number;
usedQuantity?: number;
usedCost?: number;
modulesMasterId?: number;
}
\ No newline at end of file
export interface IDashboardConfigModel {
dashboardConfigId: number;
dashboardConfigMasterId: number;
dashboardWidgetId: number;
dashboardWidgetTypeId: number;
dashboardWidgetCountTypeId: number;
widgetName: string;
icon: string;
rowNumber: number;
size: number;
sequenceNumber: number;
createdByName: string;
storedProcedureName: string;
countTypeName: string;
isRoleDashboard: boolean;
defaultValues: any;
}
\ No newline at end of file
export interface IDischargeModel {
dischargeId: number;
dischargeDate: Date;
dischargeTime: Date;
dischargeStatusId: number;
dischargeInstructionId?: string;
dischargeInstructionName: string;
dischargeStatus: string;
dischargeSummary: string;
dischargeSummaryView: string;
conditionOnDischarge: string;
finalDiagnosis: string;
historyOfIllness: string;
diet: string;
dischargeFollowUpDate: Date;
dischargeFollowUpDays: number;
followUpSummary: string;
isDeath: boolean;
causeOfDeath: string;
deathDate: Date;
deathTime: Date;
createdByName: string;
createdDate: Date;
modifiedByName: string;
modifiedDate: Date;
pastHistory: string;
dischargeAdvise: string;
surgery: string;
generalExamination: string;
localExamination: string;
hospitalCourse: string;
operativeProcedure: string;
operativeNotes: string;
consultantSignature: string;
consultantSignatureName: string;
surgeonNamesId: string;
surgeonNames: string;
}
\ No newline at end of file
export enum DiscountType
{
Number = 1,
Percentage = 2
}
\ No newline at end of file
export class DynamicReport {
dynamicReportId: number;
name: string;
query: string;
status: string;
active: boolean;
createdBy: number;
modifiedBy: number;
}
import { DiscountType } from "./discount-type.model";
export class FinalBillBasicModel {
totalAmountPaid: number;
totalAmount: number;
discountTypeId: DiscountType;
discountDetails: number;
finalAmount: number;
pendingAmount: number;
isFinalBillGenerated: boolean;
isDischarged: boolean;
dischargeDate: Date;
totalAmountPaidInWords: string;
totalDueAmountInWords: string;
totalRefundPendingAmountInWords: string;
totalAmountInWords: string;
netAmountInWords: string;
finalBillId: number;
finalBillInWords: string;
isServiceTaken: boolean;
isFinalGatePass: boolean;
isProvisionalGatePass: boolean;
}
\ No newline at end of file

export class GatepassModel {
gatePassId: number;
admissionId: number;
remark: string;
validUpto: Date;
createdDate: Date;
modifiedDate: Date;
createdByName: string;
modifiedByName: string;
zipcode: string;
city: string;
area: string;
caseTypeName: string;
///////
typeId: number;
}
import { RepeatType } from "./repeat-type.model";
import { AutomaticType } from "./automatic-type.model";
export interface ILabServicesModel {
labServicesId: number;
labBookingHeaderId?: number;
labBookingDetailId?: number;
labStatus: string;
isReportGenerated?: boolean;
isSampleCollected?: boolean;
reportDate?: Date;
labHeaderId: number;
labName: string;
labCode: string;
charge: number;
mrp: number;
cost: number;
isSelected: boolean;
labPackageDetailId: number;
labPackageId: number;
testParameter: string;
labData: Array<string>;
unit: number;
totalCost: number;
discountAmount: number;
discountPercentage: number;
status: boolean;
repeatTypeId: RepeatType;
automaticTypeId: AutomaticType;
active: boolean;
createdDate: Date;
modifiedDate: Date;
createdByName: string;
modifiedByName: string;
isMain: boolean;
repeatTypeName: string;
automaticTypeName: string;
deleting: boolean;
totalItems: number;
signature: string;
createdBy: number;
noOfParameter: number;
inPatientCharge: number;
modifiedBy?: number;
netAmount: number;
showAmount: boolean;
labExitsInPackage: boolean;
}
\ No newline at end of file
export class LookUpModel {
id: number;
name: string;
value: any;
followUpDays: any;
followUpDaysLimit: any;
visitTypeId: number;
visitorName: string;
}
\ No newline at end of file
import { RepeatType } from "./repeat-type.model";
import { AutomaticType } from "./automatic-type.model";
import { DiscountType } from "./discount-type.model";
export class NewLabServicesModel {
labServicesId: number;
newLabBookingHeaderId?: number;
newLabBookingDetailId?: number;
labStatus: string;
isReportGenerated?: boolean;
isSampleCollected?: boolean;
reportDate?: Date;
labMainDetailId: number;
testName: string;
testCode: string;
charge: number;
mrp: number;
cost: number;
isSelected: boolean;
labPackageDetailId: number;
labPackageId: number;
testParameter: string;
labData: Array<string>;
unit: number;
totalCost: number;
discountAmount: number;
discountPercentage: number;
discountType: DiscountType;
discount: number;
status: boolean;
repeatTypeId: RepeatType;
automaticTypeId: AutomaticType;
active: boolean;
createdByName: string;
modifiedByName: string;
isMain: boolean;
repeatTypeName: string;
automaticTypeName: string;
deleting: boolean;
totalItems: number;
signature: string;
createdBy: number;
noOfParameter: number;
inPatientCharge: number;
modifiedBy?: number;
netAmount: number;
showAmount: boolean;
labExitsInPackage: boolean;
labDepartmentId: number;
labSampleTypeId: number;
typeName: string;
departmentName: string;
joined: string;
isInternalLab: boolean;
isExternalLab: boolean;
createdDate: Date;
modifiedDate?: Date;
charges: Array<LabMainDetailCharge>;
templates: Array<LabMainDetailTemplate>;
isLoading: boolean;
patientLabDetailId?: number;
chargeExistForCurrentLocation?: number;
chargesSet?: boolean;
selected: boolean;
chargeCategoryId?: number;
modulesMasterId?: number;
// Package Module
isInPackage: boolean;
admissionPackageId?: number;
packageModuleDetailId?: number;
usedQuantity?: number;
usedCost?: number;
constructor() {
this.charges = new Array<LabMainDetailCharge>();
this.templates = new Array<LabMainDetailTemplate>();
}
}
export class LabMainDetailCharge {
labMainDetailChargeId: number;
labMainDetailId: number;
chargeCategoryId: number;
rate?: number;
amount?: number;
locationId: number;
locationName: string;
chargeCategoryName: string;
default: boolean;
modulesMasterId?: number;
}
export class LabMainDetailTemplate {
labMainDetailTemplateId: number;
labMainDetailId: number;
labTemplateHeaderId: number;
priority: number;
templateName: string;
templateId: string;
}
\ No newline at end of file
import { RepeatType } from "./repeat-type.model";
import { AutomaticType } from "./automatic-type.model";
export class NewServicesModel {
charges: Array<LabMainDetailCharge>;
constructor() {
this.charges = new Array<LabMainDetailCharge>();
}
chargeId: number;
productId: number;
cost: number;
opCost: number;
chargeName: string;
chargeGroupName: string;
departmentName: string;
serviceOrderId: number;
unit: number;
totalCost: number;
discountAmount: number;
discountPercentage: number;
status: boolean;
repeatTypeId: RepeatType;
automaticTypeId: AutomaticType;
active: boolean;
createdDate: Date;
modifiedDate: Date;
createdByName: string;
modifiedByName: string;
isMain: boolean;
departmentId: number;
chargeGroupId: number;
repeatTypeName: string;
automaticTypeName: string;
deleting: boolean;
totalItems: number;
chargeTypeMainId: number;
chargeTypeMainName: string;
chargeTypeId: number;
chargeTypeName: string;
// Package Module
showAmount: boolean;
isInPackage: boolean;
admissionPackageId?: number;
packageModuleDetailId?: number;
usedQuantity?: number;
usedCost?: number;
}
export class LabMainDetailCharge {
labMainDetailChargeId: number;
labMainDetailId: number;
chargeCategoryId: number;
rate?: number;
amount?: number;
locationId: number;
locationName: string;
chargeCategoryName: string;
default: boolean;
}
\ No newline at end of file
export enum PayType
{
Cash = 1,
Card = 2,
Cheque = 3
}
\ No newline at end of file
export interface IPharmacyIndentModel {
categoryName: string;
departmentName: string;
productName: string;
unit: number;
cost: number;
returnQty: number;
productId: number;
pharmacyIssueDetailId: number;
discountAmount: number;
discountPercentage: number;
totalCost: number;
status: boolean;
active: boolean;
createdDate: Date;
modifiedDate: Date;
createdByName: string;
modifiedByName: string;
showAmount: boolean;
}
\ No newline at end of file
export interface IReceiptTypeModel {
receiptTypeId: number;
receiptTypeName: string;
}
export enum ReceiptType
{
Cash = 1,
Refund = 2
}
\ No newline at end of file
import { ReceiptType } from "./receipt-type.model";
import { PayType } from "./pay-type.model";
import { ReceiptAreaType } from "../../../../shared/entities";
export interface IReceiptModel {
receiptId: number;
receiptNo: string;
payTypeId: PayType;
payTypeName: string;
receiptTypeId: ReceiptType;
paymentDetails: string;
admissionId: number;
cost: number;
receiptTypeName: string;
createdByName: string;
createdDate: Date;
modifiedDate: Date;
modifiedByName: string;
active: boolean;
isAdvance: boolean;
isRefunded: boolean;
isSpecial: boolean;
fullName: string;
cancelling: boolean;
isAppointmentReceipt: boolean;
receiptAreaTypeId?: ReceiptAreaType;
receiptAreaMainId?: number;
subRecords?: Array<IReceiptSubModel>;
costModel?: IReceiptCostModel;
isSalucroAdmissionReceipt: boolean;
}
export interface IReceiptSubModel {
cost: number;
discountAmount: number;
discountPercentage: number;
gstAmount: number;
gstPercentage: number;
name: string;
netAmount: number;
totalAmount: number;
unit: number;
}
export interface IReceiptCostModel {
total: number;
discount: number;
gst: number;
netAmount: number;
}
\ No newline at end of file
export enum RepeatType
{
Once = 1,
Day = 2,
Hour = 3
}
\ No newline at end of file
import { RepeatType } from "./repeat-type.model";
import { AutomaticType } from "./automatic-type.model";
import { ScanChargeModel } from "../../../../shared/entities/scan-charge.entity";
export interface IScanChargeModel {
chargeId: number;
productId: number;
cost: number;
opCost: number;
chargeName: string;
chargeGroupName: string;
departmentName: string;
scanServiceId: number;
unit: number;
totalCost: number;
discountAmount: number;
discountPercentage: number;
status: boolean;
repeatTypeId: RepeatType;
automaticTypeId: AutomaticType;
active: boolean;
createdDate: Date;
modifiedDate: Date;
createdByName: string;
modifiedByName: string;
isMain: boolean;
departmentId: number;
chargeGroupId: number;
repeatTypeName: string;
automaticTypeName: string;
deleting: boolean;
totalItems: number;
chargeTypeMainId: number;
chargeTypeMainName: string;
chargeTypeId: number;
chargeTypeName: string;
// Package Module
showAmount: boolean;
isInPackage: boolean;
admissionPackageId?: number;
packageModuleDetailId?: number;
usedQuantity?: number;
usedCost?: number;
modulesMasterId?: number;
scanTestMasterId: number;
scanTestName: string;
charges: Array<ScanChargeModel>;
chargeCategoryName: string;
chargeCategoryId: number;
name: string;
selected: boolean;
isSelected: boolean;
admissionId:number;
}
\ No newline at end of file
import { Time } from "@angular/common";
export interface IShiftsModel {
shiftId: number;
name: string;
active: boolean;
slots: Array<IShiftSlotModel>;
loadingMetaData: boolean;
totalItems: number;
}
export interface IShiftSlotModel {
shiftSlotId: number;
startTime: Time;
endTime: Time;
startDate?: Date;
endDate?: Date;
}
\ No newline at end of file
import { RepeatType } from "./repeat-type.model";
import { AutomaticType } from "./automatic-type.model";
import { SurgeryChargeModel } from "../../operation-theater/models";
export interface ISurgeryChargeModel {
chargeId: number;
productId: number;
cost: number;
opCost: number;
chargeName: string;
chargeGroupName: string;
departmentName: string;
surgeryServiceId: number;
unit: number;
totalCost: number;
discountAmount: number;
discountPercentage: number;
status: boolean;
repeatTypeId: RepeatType;
automaticTypeId: AutomaticType;
active: boolean;
createdDate: Date;
modifiedDate: Date;
createdByName: string;
modifiedByName: string;
isMain: boolean;
departmentId: number;
chargeGroupId: number;
repeatTypeName: string;
automaticTypeName: string;
deleting: boolean;
totalItems: number;
chargeTypeMainId: number;
chargeTypeMainName: string;
chargeTypeId: number;
chargeTypeName: string;
// Package Module
showAmount: boolean;
isInPackage: boolean;
admissionPackageId?: number;
packageModuleDetailId?: number;
usedQuantity?: number;
usedCost?: number;
modulesMasterId?: number;
surgeryId: number;
surgeryName: string;
charges: Array<SurgeryChargeModel>;
chargeCategoryName: string;
chargeCategoryId: number;
name: string;
}
\ No newline at end of file
import { WidgetType } from "../../../../shared/enums/widget-type.enum";
export interface IWidgetModel {
dashboardWidgetId: number;
name: string;
countTypeName: string;
type: string;
icon: string;
storedProcedureName: string;
defaultValues: Array<any>;
active: boolean;
dashboardWidgetTypeId: WidgetType;
dashboardWidgetCountTypeId: number;
loadingMetaData: boolean;
deactivating: boolean;
activating: boolean;
executingSp: boolean;
totalItems: number;
result: {headers: string[], data: any} | string | any;
size: number;
isExecuting: boolean;
isCofiguring: boolean;
isFiltering: boolean;
dashboardConfigId: number;
widgetColor: number;
rolesStr: string;
roles: Array<number>;
roleNames: Array<string>;
roleId?: any;
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<!--editMode.Discharged-->
<div *ngIf="mode === editMode.Discharged" class="page-title-right">
<button class="btn btn-primary btn-sm ml-1" (click)="onEdit()"><i class="fe-edit-2 mr-2"></i> Edit</button>
<button *ngIf="finalBillBasics.isFinalBillGenerated && finalBillBasics.pendingAmount == 0" type="button" class="btn btn-primary btn-sm ml-2" (click)="onOpenModel(templateViewDischarge)">
<span><i class="fe-eye mr-1"></i> Discharge Summary Report</span>
</button>
<button class="btn btn-secondary btn-sm ml-1" (click)="onBack()"><i class="fe-arrow-left ml-1"></i> Back</button>
</div>
</div>
<h4 *ngIf="!form.isDeath.value" class="page-title">Discharge Summary</h4>
<h4 *ngIf="form.isDeath.value" class="page-title">Death Summary</h4>
</div>
</div>
<div class="col-lg-12" *ngIf="!finalBillBasics.isFinalBillGenerated">
<div class="d-flex align-items-center justify-content-center">
<div class="alert alert-info"><i class="mdi mdi-lightbulb"></i> Tip: Generate Final Bill to see <span class="font-weight-bold">Discharge Summary</span></div>
</div>
</div>
<!--<div class="col-lg-12" *ngIf="finalBillBasics.isFinalBillGenerated && finalBillBasics.pendingAmount !== 0">
<div class="d-flex align-items-center justify-content-center">
<div class="alert alert-info">
<i class="mdi mdi-lightbulb"></i> Tip:
<span *ngIf="finalBillBasics.pendingAmount < 0" class="font-weight-bold">Clear the Due Amount</span>
<span *ngIf="finalBillBasics.pendingAmount > 0" class="font-weight-bold">Issue the Refund Amount</span>
to view the discharge summary
</div>
</div>
</div>-->
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading discharge summary ...</span>
</div>
</div>
</div>
</div>
<!--&& finalBillBasics.isFinalBillGenerated && finalBillBasics.pendingAmount === 0"-->
<div class="row" *ngIf="!loading">
<div class="col-lg-12 px-2" *ngIf="mode === editMode.New">
<form [formGroup]="dischargeForm" (submit)="onSubmit()">
<div class="card">
<div class="card-body p-0">
<div class="card-box m-0">
<div class="row">
<div class="col-lg-12">
<div class="form-group">
<label class="d-flex align-items-center">
<input type="checkbox" class="form-control-sm mr-2" formControlName="isDeath" /> Is Death
</label>
</div>
</div>
</div>
<ng-container *ngIf="form.isDeath.value">
<h4 class="box-title mt-3"><i class="mdi mdi-human mr-1"></i>Death Information</h4>
<div class="row">
<div class="col-lg-5">
<div class="form-group">
<label>Death Date & Time <code>*</code></label>
<input type="datetime-local" class="form-control" [min]="today | date: 'yyyy-MM-ddTHH:mm'" [ngClass]="{ 'is-invalid': (submitted && form.deathDate.errors) }" formControlName="deathDate" />
<div *ngIf="submitted && form.deathDate.errors" class="invalid-feedback show-must">
<div *ngIf="form.deathDate.errors.required">Death date is required</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="form-group">
<label>Cause Of Death <code>*</code></label>
<input type="text" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.causeOfDeath.errors) }" formControlName="causeOfDeath" placeholder="Enter cause of death" />
<div *ngIf="submitted && form.causeOfDeath.errors" class="invalid-feedback show-must">
<div *ngIf="form.causeOfDeath.errors.required">Cause of death is required</div>
</div>
</div>
</div>
</div>
</ng-container>
<ng-container *ngIf="!form.isDeath.value">
<div class="row">
<div class="col-lg-12">
<h4 class="box-title"><i class="mdi mdi-information-outline mr-1"></i>General Information</h4>
</div>
</div>
<div class="row">
<div class="col-lg-5">
<div class="form-group">
<label>Discharge Date & Time <code>*</code></label>
<div>
<input type="datetime-local" min="{{maxDischargeDate}}"[ngClass]="{ 'is-invalid': (submitted && form.dischargeDate.errors) }" class="form-control" formControlName="dischargeDate" />
<i *ngIf="form.dischargeDate.value" (click)="clearDate('dischargeDate')" ngbTooltip="Clear" placement="right" class="fe-x date-clear-icon"></i>
</div>
<div *ngIf="submitted && form.dischargeDate.errors" class="invalid-feedback show-must">
<div *ngIf="form.dischargeDate.errors.required">Discharge date is required</div>
</div>
</div>
</div>
<!--<div class="col-lg-4">
<div class="form-group">
<label>Discharge Time <code>*</code></label>
<input type="datetime-local" [ngClass]="{ 'is-invalid': (submitted && form.dischargeTime.errors) }" class="form-control" formControlName="dischargeDate" />
<div *ngIf="submitted && form.dischargeTime.errors" class="invalid-feedback show-must">
<div *ngIf="form.dischargeTime.errors.required">Discharge time is required</div>
</div>
</div>
</div>-->
<div class="col-lg-4">
<div class="form-group">
<label>Discharge Status <code>*</code></label>
<select class="form-control" formControlName="dischargeStatusId" [ngClass]="{ 'is-invalid': (submitted && form.dischargeStatusId.errors) }">
<option selecte hidden [value]="null">Select Status</option>
<option *ngFor="let item of dischargeStatus" [ngValue]="item.id" [textContent]="item.name"></option>
</select>
<div *ngIf="submitted && form.dischargeStatusId.errors" class="invalid-feedback show-must">
<div *ngIf="form.dischargeStatusId.errors.required">Discharge date is required</div>
</div>
</div>
</div>
<!--<div class=" row">
<div class="col-lg-12">
<div class="form-group">
<label>Discharge Instruction</label>
<select class="form-control" formControlName="dischargeInstructionId">
<option selecte hidden [value]="null">Select Instruction</option>
<option *ngFor="let item of dischargeInstructions" [ngValue]="item.id" [textContent]="item.name"></option>
</select>
</div>
</div>
</div>-->
</div>
<div class="row">
<div class="col-lg-12">
<div class="form-group">
<label>Discharge Instruction</label>
<ng-select class="ng-select-sm" [items]="dischargeInstructions" [ngClass]="{ 'is-invalid': submitted && form.dischargeInstructionId.errors }"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select Instructions"
[multiple]="true"
formControlName="dischargeInstructionId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No Discharge Instructions found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="form-group">
<label>Diagnosis</label>
<textarea rows="2" class="form-control" formControlName="finalDiagnosis" placeholder="Enter diagnosis"></textarea>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label>Surgery</label>
<textarea rows="3" class="form-control" formControlName="surgery" placeholder="Enter about Surgery"></textarea>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label>Patient's History</label>
<textarea rows="2" class="form-control" formControlName="historyOfIllness" placeholder="Enter patient's history'"></textarea>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label>Past History</label>
<textarea rows="2" class="form-control" formControlName="pastHistory" placeholder="Enter past history"></textarea>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label>General Examination</label>
<textarea rows="2" class="form-control" formControlName="generalExamination" placeholder="Enter general examination"></textarea>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label>Local Examination</label>
<textarea rows="2" class="form-control" formControlName="localExamination" placeholder="Enter local examination"></textarea>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label>Hospital Course</label>
<textarea rows="2" class="form-control" formControlName="hospitalCourse" placeholder="Enter hospital course"></textarea>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label>Operative Procedure</label>
<textarea rows="2" class="form-control" formControlName="operativeProcedure" placeholder="Enter operative procedure"></textarea>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label class="mb-1">Surgeon Name</label>
<ng-select class="ng-select-sm text-uppercase" [items]="providerResources" [ngClass]="{ 'is-invalid': submitted && form.surgeonNamesId.errors }"
bindLabel="value"
bindValue="id"
autocomplete="nope"
placeholder="Select surgeons"
[multiple]="true"
formControlName="surgeonNamesId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No surgeons found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label>Operative Notes</label>
<textarea rows="2" class="form-control" formControlName="operativeNotes" placeholder="Enter Operative notes"></textarea>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label>Condition On Discharge </label>
<textarea rows="2" class="form-control" formControlName="conditionOnDischarge" placeholder="Enter condition on discharge"></textarea>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label>Discharge Advise</label>
<textarea rows="2" class="form-control" formControlName="dischargeAdvise" placeholder="Enter discharge advise"></textarea>
</div>
</div>
</div>
<h4 class="box-title mt-3"><i class="mdi mdi-repeat mr-1"></i>Follow Up Information</h4>
<div class="row">
<div class="col-lg-5">
<div class="form-group">
<label>Follow Up Date </label>
<div>
<input type="date" [min]="form.dischargeDate.value | date: 'yyyy-MM-dd'" class="form-control" formControlName="dischargeFollowUpDate" placeholder="Enter follow up date" />
<i *ngIf="form.dischargeFollowUpDate.value" (click)="clearDate('dischargeFollowUpDate')" ngbTooltip="Clear" placement="right" class="fe-x date-clear-icon"></i>
</div>
<!--<div>
<input [min]="today | date: 'yyyy-MM-ddTHH:mm'" type="datetime-local" [ngClass]="{ 'is-invalid': (submitted && form.dischargeDate.errors) }" class="form-control" formControlName="dischargeDate" />
<i *ngIf="form.dischargeDate.value" (click)="clearDate('dischargeDate')" ngbTooltip="Clear" placement="right" class="fe-x date-clear-icon"></i>
</div>
<div *ngIf="submitted && form.dischargeDate.errors" class="invalid-feedback show-must">
<div *ngIf="form.dischargeDate.errors.required">Discharge date is required</div>
</div>-->
</div>
</div>
<div class="col-lg-3">
<div class="form-group">
<label>Follow Up Days </label>
<input type="number" class="form-control" formControlName="dischargeFollowUpDays" placeholder="Enter follow up days" />
<div *ngIf="submitted && form.dischargeFollowUpDays.errors" class="invalid-feedback show-must">
<div *ngIf="form.dischargeFollowUpDays.errors.min">Follow up days should be minimum 1</div>
</div>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label>Follow Up Summary </label>
<textarea rows="3" class="form-control" formControlName="followUpSummary" placeholder="Enter follow up summary"></textarea>
</div>
</div>
</div>
</ng-container>
<h4 class="box-title mt-3"><i class="mdi-pen"></i>Consultant Signature</h4>
<div class="row">
<div class="col-lg-6">
<div class="form-group">
<label class="d-flex align-items-center">
<select class="form-control custom-select" formControlName="consultantSignature">
<option [ngValue]="null" *ngIf="!loadingproviderResources">All</option>
<option selected *ngIf="loadingproviderResources">Loading...</option>
<option *ngFor="let item of providerResources; " [textContent]="item.value" [ngValue]="item.id"></option>
<!--trackBy:trackBy.resource-->
</select>
</label>
</div>
</div>
</div>
</div>
</div>
<div class="card-footer bg-light">
<div class="text-right">
<button *ngIf="!record.dischargeId" type="reset" class="btn btn-warning btn-sm mr-2">
<i class="fe-refresh-cw"></i>
<span class="ml-1">Reset</span>
</button>
<button *ngIf="record.dischargeId" type="button" (click)="onCancel()" class="btn btn-danger btn-sm mr-2">
<i class="fe-x"></i>
<span class="ml-1">Cancel</span>
</button>
<button type="submit" [disabled]="!finalBillBasics.isFinalBillGenerated || finalBillBasics.pendingAmount < 0" class="btn btn-sm btn-success">
<!--<span>
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>-->
<span>
<i class="fe-check"></i>
<span class="ml-1">
<span *ngIf="record.dischargeId">Update</span>
<span *ngIf="!record.dischargeId">Discharge Patient</span>
</span>
</span>
</button>
</div>
</div>
</div>
</form>
</div>
<div class="col-lg-12 px-2" *ngIf="mode === editMode.Discharged">
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<div class="card mt-2">
<div class="card-body p-0">
<div class="table-responsive" *ngIf="record">
<table class="table table-centered table-bordered table-sm mb-0">
<tbody>
<ng-container *ngIf="record.isDeath">
<tr class="table-primary">
<th colspan="4">
Death Information
</th>
</tr>
<tr>
<th class="table-active">
Death Date & Time
</th>
<td [textContent]="record.deathDate | date:'dd-MM-yyyy, h:mm:ss a'"></td>
<th class="table-active">
Cause Of Death
</th>
<td [textContent]="record.causeOfDeath"></td>
</tr>
</ng-container>
<ng-container *ngIf="!record.isDeath">
<tr class="table-primary">
<th colspan="4">
<div class="row">
<div class="col-lg-6">General Information</div>
<div class="col-lg-6 text-right">
<span><i class="fe-check mr-2"></i>Patient is discharged</span>
</div>
</div>
</th>
</tr>
<tr>
<th class="table-active">Discharge Date & Time</th>
<td [textContent]="record.dischargeDate | date: 'dd-MM-yyyy, hh:mm a'"></td>
<th class="table-active">Discharge Status</th>
<td [textContent]="record.dischargeStatus"></td>
</tr>
<tr>
<th class="table-active">Discharge Instruction</th>
<td colspan="3" [textContent]="record.dischargeInstructionName || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">Discharge Advice</th>
<td colspan="3" [innerHtml]="record.dischargeAdvise || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">Condition On Discharge</th>
<td colspan="3" [innerHtml]="record.conditionOnDischarge || 'N/A'"></td>
</tr>
<tr>
<th class="table-active"> Diagnosis</th>
<td colspan="3" [innerHtml]="record.finalDiagnosis || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">Patient's History</th>
<td colspan="3" [innerHtml]="record.historyOfIllness || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">Past History</th>
<td colspan="3" [innerHtml]="record.pastHistory || 'N/A'"></td>
</tr>
<!--<tr>
<th class="table-active">Diet</th>
<td colspan="3" [innerHtml]="record.diet || 'N/A'"></td>
</tr>-->
<tr>
<th class="table-active">Surgery</th>
<td colspan="3" [innerHtml]="record.surgery || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">General Examination</th>
<td colspan="3" [innerHtml]="record.generalExamination || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">Local Examination</th>
<td colspan="3" [innerHtml]="record.localExamination || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">Hospital Course</th>
<td colspan="3" [innerHtml]="record.hospitalCourse || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">Operative Procedure</th>
<td colspan="3" [innerHtml]="record.operativeProcedure || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">Surgeon Names</th>
<td colspan="3" [textContent]="record.surgeonNames || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">Operative Notes</th>
<td colspan="3" [innerHtml]="record.operativeNotes || 'N/A'"></td>
</tr>
<!--<tr>
<th class="table-active">Consultant Signature</th>
<td colspan="3" [innerHtml]="record.consultantSignature || 'N/A'"></td>
</tr>-->
<tr class="table-primary">
<th colspan="4">
Follow Up Information
</th>
</tr>
<tr>
<th class="table-active">
Follow Up Date
</th>
<td [textContent]="(record.dischargeFollowUpDate | date: 'dd-MM-yyyy') || 'N/A'"></td>
<th class="table-active">
Follow Up Days
</th>
<td [textContent]="record.dischargeFollowUpDays || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">
Follow Up Summary
</th>
<td colspan="3" [innerHtml]="record.followUpSummary || 'N/A'"></td>
</tr>
</ng-container>
</tbody>
<tbody>
<tr>
<td colspan="4">
<div class="d-flex align-items-end mr-1 justify-content-between flex-column">
<span class="d-flex align-items-end mr-1 justify-content-between">
<h5 class="row d-flex align-items-flex-end ml-1">Consultant Signature </h5>
</span>
<span class="d-block align-items-end ml-1">
<a href="javascript:;" class="text-dark">
<span class="row d-flex align-items-flex-end mr-1" [textContent]="record.consultantSignatureName || 'N/A'"></span>
</a>
</span>
</div>
</td>
</tr>
</tbody>
<tbody>
<tr>
<td colspan="4">
<div class="row d-flex align-items-flex-end">
<div class="col-lg-6">
<span class="small"><span>Last Edited: </span><span class="mr-1" [textContent]="record.createdByName"></span> <span [textContent]="record.createdDate | date: 'dd-MM-yyyy, h:mm:ss a'"></span></span>
</div>
<!--<div class="col-lg-6">
<div class="text-right">
<button class="btn btn-sm btn-light" (click)="onEdit()"><i class="fe-edit-2 mr-2"></i> Edit</button>
</div>
</div>-->
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateViewDischarge>
<div class="modal-header">
<h4 *ngIf="!record.isDeath" class="modal-title"><i class="mdi mdi-receipt mr-1"></i>Discharge Summary Report</h4>
<h4 *ngIf="record.isDeath" class="modal-title"><i class="mdi mdi-receipt mr-1"></i>Discharge Summary Report</h4>
<div>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();"><i class="fe-x"></i></button>
<button [useExistingCss]="true"
printSectionId="print-section"
ngxPrint
class="btn btn-light btn-xs mr-1 d-print-none">
<i class="fe-printer mr-1"></i>Print
</button>
</div>
</div>
<div class="modal-body" id="print-section">
<div class="card">
<div class="card-body p-0">
<div class="card-box m-0">
<div class="row">
<div *ngIf="isPrintLogo" class="col-12" width="100%">
<banner-setting></banner-setting>
</div>
<div class="col-lg-12" *ngIf="!record.isDeath">
<h4 class="box-title mt-3">DISCHARGE SUMMARY</h4>
</div>
<div class="col-lg-12" *ngIf="record.isDeath">
<h4 class="box-title mt-3">DEATH SUMMARY</h4>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="table-responsive">
<table class="table table-sm table-borderless table-centered">
<tbody>
<tr>
<th>Admission No</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.admissionNo"></span>
</td>
<th>Discharge Date</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="(record.dischargeDate | date: 'dd-MM-yyyy, h:mm:ss a') || 'Not Discharged Yet'"></span>
</td>
</tr>
<tr>
<th>Patient Name</th>
<td>
<span class="mr-1">:</span>
<span>
<span [textContent]="admission.fullName + ', '"></span>
<span [textContent]="(admission.gender === 'F' ? 'Female' : 'Male') + ', '"></span>
<span [textContent]="admission.age + 'yrs'"></span>
</span>
</td>
<th>Father/Husband Name</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.fatherOrHusband"></span>
</td>
</tr>
<tr>
<th>Date of Admission</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.admissionDate | date: 'dd-MM-yyyy, h:mm:ss a'"></span>
</td>
<th>Consultant</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.providerName"></span>
</td>
</tr>
<tr>
<th>Department</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.departmentName"></span>
</td>
<th>Admitted Ward</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="!admission.bedNumber ? 'N/A' : (admission.wardName + ' / ' + admission.roomName + ' / ' + admission.bedNumber)"></span>
</td>
</tr>
<tr>
<th>Address</th>
<td>
<span class="mr-1">:</span>
<span>Kothrepally, Vikarabad, Telangana</span>
</td>
<th>UMR No</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.umrNo"></span>
</td>
</tr>
<tr>
<th>Discharge Information</th>
<th colspan="3">
<span class="mr-1">:</span>
<span [textContent]="record.dischargeStatus"></span>
</th>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!--<div class="col-lg-12" *ngIf="finalBillBasics.isFinalBillGenerated && finalBillBasics.pendingAmount !== 0">
<div class="d-flex align-items-center justify-content-center">
<div class="alert alert-info">
<i class="mdi mdi-lightbulb"></i> Tip:
<span *ngIf="finalBillBasics.pendingAmount < 0" class="font-weight-bold">Clear the Due Amount</span>
<span *ngIf="finalBillBasics.pendingAmount > 0" class="font-weight-bold">Issue the Refund Amount</span>
to view the discharge summary
</div>
</div>
</div>
<div class="col-lg-12" *ngIf="!finalBillBasics.isFinalBillGenerated">
<div class="d-flex align-items-center justify-content-center">
<div class="alert alert-info"><i class="mdi mdi-lightbulb"></i> Tip: Generate Final Bill to see <span class="font-weight-bold">Discharge Summary</span></div>
</div>
</div>-->
<div class="row mt-2" *ngIf="record && finalBillBasics.isFinalBillGenerated && finalBillBasics.pendingAmount == 0">
<div class="col-12">
<div class="table-responsive">
<table class="table table-centered table-bordered table-sm mb-0">
<tbody>
<tr class="table-primary" *ngIf="isGeneralInformation">
<th colspan="4">
General Information
</th>
</tr>
<tr *ngIf="record.dischargeInstructionName">
<th class="table-active">Discharge Instruction</th>
<td colspan="3" [textContent]="record.dischargeInstructionName || 'N/A'"></td>
</tr>
<tr *ngIf="record.dischargeSummaryView">
<th class="table-active">Discharge Summary</th>
<td colspan="3" [innerHtml]="record.dischargeSummaryView || 'N/A'"></td>
</tr>
<tr *ngIf="record.conditionOnDischarge">
<th class="table-active">Condition On Discharge</th>
<td colspan="3" [innerHtml]="record.conditionOnDischarge || 'N/A'"></td>
</tr>
<tr *ngIf="record.finalDiagnosis">
<th class="table-active">Diagnosis</th>
<td colspan="3" [innerHtml]="record.finalDiagnosis || 'N/A'"></td>
</tr>
<tr *ngIf="record.historyOfIllness">
<th class="table-active">Patient's History</th>
<td colspan="3" [innerHtml]="record.historyOfIllness || 'N/A'"></td>
</tr>
<tr *ngIf="record.pastHistory">
<th class="table-active">Past History</th>
<td colspan="3" [innerHtml]="record.pastHistory || 'N/A'"></td>
</tr>
<tr *ngIf="record.dischargeAdvise">
<th class="table-active">Discharge Advise</th>
<td colspan="3" [innerHtml]="record.dischargeAdvise || 'N/A'"></td>
</tr>
<tr *ngIf="record.surgery">
<th class="table-active">Surgery</th>
<td colspan="3" [innerHtml]="record.surgery || 'N/A'"></td>
</tr>
<tr *ngIf="record.generalExamination">
<th class="table-active">General Examination</th>
<td colspan="3" [innerHtml]="record.generalExamination || 'N/A'"></td>
</tr>
<tr *ngIf="record.localExamination">
<th class="table-active">Local Examination</th>
<td colspan="3" [innerHtml]="record.localExamination || 'N/A'"></td>
</tr>
<tr *ngIf="record.hospitalCourse">
<th class="table-active">Hospital Course</th>
<td colspan="3" [innerHtml]="record.hospitalCourse || 'N/A'"></td>
</tr>
<tr *ngIf="record.operativeProcedure">
<th class="table-active">Operative Procedure</th>
<td colspan="3" [innerHtml]="record.operativeProcedure || 'N/A'"></td>
</tr>
<tr *ngIf="record.surgeonNames">
<th class="table-active">Surgeon Names</th>
<td colspan="3" [textContent]="record.surgeonNames || 'N/A'"></td>
</tr>
<tr *ngIf="record.operativeNotes">
<th class="table-active">Operative Notes</th>
<td colspan="3" [innerHtml]="record.operativeNotes || 'N/A'"></td>
</tr>
<tr *ngIf="record.diet">
<th class="table-active">Diet</th>
<td colspan="3" [innerHtml]="record.diet || 'N/A'"></td>
</tr>
<tr class="table-primary" *ngIf="isFollowUpInformation">
<th colspan="4">
Follow Up Information
</th>
</tr>
<tr *ngIf="record.dischargeFollowUpDate || record.dischargeFollowUpDays">
<ng-container *ngIf="record.dischargeFollowUpDate">
<th [attr.colspan]="(record.dischargeFollowUpDays ? 1 : 2)" class="table-active">
Follow Up Date
</th>
</ng-container>
<td [textContent]="(record.dischargeFollowUpDate | date: 'dd-MM-yyyy') || 'N/A'"></td>
<ng-container *ngIf="record.dischargeFollowUpDays">
<th [attr.colspan]="(record.dischargeFollowUpDate ? 1 : 2)" class="table-active">
Follow Up Days
</th>
</ng-container>
<td [textContent]="record.dischargeFollowUpDays || 'N/A'"></td>
</tr>
<tr *ngIf="record.followUpSummary">
<th class="table-active">
Follow Up Summary
</th>
<td colspan="3" [innerHtml]="record.followUpSummary || 'N/A'"></td>
</tr>
<tr *ngIf="record.isDeath" class="table-primary">
<th colspan="4">
Death Information <span class="small"></span>
</th>
</tr>
<ng-container *ngIf="record.isDeath">
<tr>
<th class="table-active">
Death Date & Time
</th>
<td [textContent]="record.deathDate | date: 'dd-MM-yyyy, h:mm:ss a'"></td>
<th class="table-active">
Cause Of Death
</th>
<td [textContent]="record.causeOfDeath"></td>
</tr>
</ng-container>
</tbody>
<tbody>
<tr *ngIf="record.consultantSignature">
<td colspan="4">
<div class="d-flex align-items-end mr-1 justify-content-between flex-column">
<span class="d-flex align-items-end mr-1 justify-content-between">
<h5 class="row d-flex align-items-flex-end ml-1"> Consultant Signature </h5>
</span>
<span class="d-block align-items-end ml-1">
<a href="javascript:;" class="text-dark">
<span class="row d-flex align-items-flex-end mr-1" [textContent]="record.consultantSignatureName"></span>
</a>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-template>
import { Component, OnDestroy, OnInit, TemplateRef, Input, } from "@angular/core";
import { ActivatedRoute, Params } from "@angular/router";
import { takeUntil, finalize } from "rxjs/operators";
import { Location } from '@angular/common';
import { IUserAccount, Page, GenericResponse, GenericStatus, IResource } from "@shared/models";
import { AppData, HttpService, NotifyService, FinalBillService, ResourceService, PrintOptionService } from "@shared/services";
import { ApiResources } from "@shared/helpers";
import { IDischargeModel } from "../../models/discharge.model";
import { LookUpModel } from "../../models/look-up.model";
import { IReceiptTypeModel, ReceiptType } from "../../models/receipt-type.model";
import { PayType } from "../../models/pay-type.model";
import { FormGroup, FormBuilder, Validators } from "@angular/forms";
import { FinalBillBasicModel } from "../../models/final-bill-basic.model";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { IAdmissionModel } from "../../models/admission.model";
import { ImageReports } from "@shared/entities";
enum EditMode {
New = 1,
Discharged = 2
}
@Component({
templateUrl: "./discharge-patient.html",
styleUrls: ['../../services.css']
})
export class DischargePatientPage implements OnInit, OnDestroy {
receiptType = ReceiptType;
payType = PayType;
editMode = EditMode;
page: Page;
loading: boolean;
isChargesLoading: boolean;
record: IDischargeModel;
admission: IAdmissionModel;
submitting: boolean;
submitted: boolean;
admissionId: string;
isAdmission: boolean;
isInstructionsLoading: boolean;
dischargeInstructions: Array<LookUpModel>;
isStatusLoading: boolean;
dischargeStatus: Array<LookUpModel>;
receiptTypes: Array<IReceiptTypeModel>;
dischargeForm: FormGroup;
finalBillBasics: FinalBillBasicModel;
mode: EditMode;
today = new Date();
modalRef: NgbModalRef;
loadingproviderResources: boolean;
providerResources: Array<IResource>;
@Input() isPrintLogo: boolean;
bannerBasics: ImageReports;
myImgUrl: string = "assets/images/careaxesLogo.png";
maxDischargeDate: string;
constructor(
private readonly httpService: HttpService,
private readonly route: ActivatedRoute,
private readonly finalBillService: FinalBillService,
private readonly appData: AppData,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly modalService: NgbModal,
//private readonly datePipe: DatePipe,
private readonly location: Location,
private readonly resourceService: ResourceService,
private readonly printOptionService: PrintOptionService
) {
this.mode = EditMode.New;
this.record = {} as IDischargeModel;
this.dischargeInstructions = new Array<LookUpModel>();
this.dischargeStatus = new Array<LookUpModel>();
this.finalBillBasics = new FinalBillBasicModel();
this.isChargesLoading = false;
this.loading = true;
this.page = new Page();
this.buildDischargeForm();
this.formChanges();
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.route.parent.paramMap
.subscribe((params: Params) => {
this.admissionId = params["params"]["id"];
this.isAdmission = params["params"]["type"] === "a";
this.getFinalBillBasics(() => {
this.admissionFetch();
this.fetch();
this.getFinalBillBasics();
});
});
this.fetchInstructions();
this.fetchStatus();
this.fetchProviderResources();
} else {
this.page.userAccount = undefined;
}
this.printOptionService.get((is) => { this.isPrintLogo = is; });
});
}
onBack = () => {
this.location.back();
}
get isGeneralInformation() {
return this.record && Object.keys(this.record).filter(x =>
x !== "dischargeFollowUpDate" &&
x !== "dischargeFollowUpDays" &&
x !== "followUpSummary" &&
x !== "isDeath" &&
x !== "deathDate" &&
x !== "causeOfDeath"
).map(x => this.record[x]).filter(x => x).length;
}
get isFollowUpInformation() {
return this.record &&
Object.keys(this.record).filter(x =>
x === "dischargeFollowUpDate" ||
x === "dischargeFollowUpDays" ||
x === "followUpSummary"
).map(x => this.record[x]).filter(x => x).length;
}
get form() {
return this.dischargeForm.controls;
}
private buildDischargeForm(model?: IDischargeModel) {
function adjust(val) {
if (val > 9) {
return val.toString();
} else {
return '0' + val.toString();
}
}
var today = new Date();
var date = today.getFullYear() + '-' + adjust(today.getMonth() + 1) + '-' + adjust(today.getDate());
var time = adjust(today.getHours()) + ":" + adjust(today.getMinutes());
var dateTimeNow = `${date}T${time}`;
this.maxDischargeDate = `${date}T${time}`;
var disInstructionIds = new Array<number>();
if (model && model.dischargeInstructionId) {
model.dischargeInstructionId.split(",").forEach(item => {
disInstructionIds.push(parseInt(item));
});
}
var surgeonNamesIds = new Array<number>();
if (model && model.surgeonNamesId) {
model.surgeonNamesId.split(",").forEach(item => {
surgeonNamesIds.push(parseInt(item));
});
}
this.dischargeForm = this.formBuilder.group({
//dischargeDate: [model ? model.dischargeDate : this.datePipe.transform(new Date(), 'yyyy-MM-ddTHH:mm'), [Validators.required]],
dischargeDate: [dateTimeNow, [Validators.required]],
dischargeInstructionId: [model ? disInstructionIds : null],
dischargeStatusId: [model ? model.dischargeStatusId : null, [Validators.required]],
//dischargeInstructionName: [model ? model.dischargeInstructionName : null],
dischargeSummary: [model ? model.dischargeSummary : null],
conditionOnDischarge: [model ? model.conditionOnDischarge : null],
finalDiagnosis: [model ? model.finalDiagnosis : null],
historyOfIllness: [model ? model.historyOfIllness : null],//patients history
diet: [model ? model.diet : null],
dischargeFollowUpDate: [model ? model.dischargeFollowUpDate : null],
dischargeFollowUpDays: [model ? model.dischargeFollowUpDays : null, [Validators.min(1)]],
followUpSummary: [model ? model.followUpSummary : null],
isDeath: [model ? model.isDeath : null],
deathDate: [model ? model.deathDate : null],
causeOfDeath: [model ? model.causeOfDeath : null],
pastHistory: [model ? model.pastHistory : null],
dischargeAdvise: [model ? model.dischargeAdvise : null],
surgery: [model ? model.surgery : null],
surgeonNamesId: [model ? surgeonNamesIds : null],
generalExamination: [model ? model.generalExamination : null],
localExamination: [model ? model.localExamination : null],
hospitalCourse: [model ? model.hospitalCourse : null],
operativeProcedure: [model ? model.operativeProcedure : null],
operativeNotes: [model ? model.operativeNotes : null],
consultantSignature: [model ? model.consultantSignature : null],
});
}
onOpenModel(content: TemplateRef<any>) {
this.getFinalBillBasics();
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
size: "lg",
windowClass: "custom-modal slots-modal effect-scale"
});
return;
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.submitting = undefined;
this.submitted = undefined;
}
clearDate = (property: string) => {
this.dischargeForm.patchValue({
[property]: null
});
}
formChanges = () => {
this.dischargeForm.get("isDeath").valueChanges.subscribe((value: boolean) => {
const deathDate = this.dischargeForm.get('deathDate');
const causeOfDeath = this.dischargeForm.get('causeOfDeath');
deathDate.clearValidators();
causeOfDeath.clearValidators();
if (value) {
deathDate.setValidators([Validators.required]);
causeOfDeath.setValidators([Validators.required]);
}
deathDate.updateValueAndValidity();
causeOfDeath.updateValueAndValidity();
});
}
fetch = () => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.dischargefetch),
{ id: this.admissionId })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.mode = EditMode.Discharged;
const record = response.data as IDischargeModel;
record.dischargeSummaryView = record.dischargeSummary
? record.dischargeSummary.replace(/\n/g, "<br />")
: record.dischargeSummary;
this.buildDischargeForm(record);
this.record = record;
} else if (response.status === GenericStatus[GenericStatus.Error]) {
this.mode = EditMode.Discharged;
this.notifyService.defaultError();
} else {
this.mode = EditMode.New;
}
},
() => {
this.record = null;
}
);
}
admissionFetch = () => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.serviceOrder.base, ApiResources.serviceOrder.getAdmissionBasic),
{ id: this.admissionId, isAdmission: this.isAdmission })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.admission = response.data as IAdmissionModel;
//if (this.mode === EditMode.New && this.admission.expectedDischargeDate) {
// this.dischargeForm.patchValue({
// dischargeDate: this.datePipe.transform(new Date(this.admission.expectedDischargeDate), 'yyyy-MM-ddTHH:mm')
// })
//}
}
},
() => {
this.admission = null;
}
);
}
getFinalBillBasics = (callback = () => { }) => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.finalBill.base, ApiResources.finalBill.getBasics),
{
id: this.admissionId,
isAdmission: this.isAdmission
})
.pipe(takeUntil(this.page.unSubscribe))
.subscribe(
(response: GenericResponse) => {
this.finalBillBasics = response.data as FinalBillBasicModel;
callback();
},
() => {
this.finalBillBasics = new FinalBillBasicModel();
}
);
}
fetchInstructions = () => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.fetchInstructions), {})
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.isInstructionsLoading = false))
.subscribe(
(response: GenericResponse) => {
this.dischargeInstructions = response.data as Array<LookUpModel>;
},
() => {
this.dischargeInstructions = new Array<LookUpModel>();
}
);
}
fetchStatus = () => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.fetchStatus), {})
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.isStatusLoading = false))
.subscribe(
(response: GenericResponse) => {
this.dischargeStatus = response.data as Array<LookUpModel>;
},
() => {
this.dischargeStatus = new Array<LookUpModel>();
}
);
}
insert = () => {
this.submitted = true;
if (!this.dischargeForm.valid) {
return;
}
this.submitting = true;
const data = {
...this.dischargeForm.value,
createdBy: this.page.userAccount.accountId,
id: this.admissionId,
};
if (data.dischargeInstructionId) {
data.dischargeInstructionId = data.dischargeInstructionId.join(",")
}
if (data.surgeonNamesId) {
data.surgeonNamesId = data.surgeonNamesId.join(",")
}
data["createdBy"] = this.page.userAccount.accountId;
data["roleId"] = this.page.userAccount.roleId;
data["fullName"] = this.page.userAccount.fullName;
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.dischargeinsert), data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitting = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.notifyService.success("Patient has been discharged successfully");
this.mode = EditMode.Discharged;
} if (response.status === GenericStatus[GenericStatus.Info]) {
this.notifyService.warningToast("Patient cannot be discharged.");
}
this.admissionFetch();
this.fetch();
this.finalBillService.set(true);
//else {
// if (response.message) {
// this.notifyService.info(response.message);
// } else {
// this.notifyService.defaultError();
// }
//}
},
() => {
//this.notifyService.defaultError();
}
);
}
onSubmit = () => {
if (this.record.dischargeId) {
this.update();
} else {
this.insert();
}
}
onEdit = () => {
this.mode = EditMode.New;
}
onCancel = () => {
this.mode = EditMode.Discharged;
}
update = () => {
this.submitted = true;
if (!this.dischargeForm.valid) {
return;
}
this.submitting = true;
const data = {
...this.dischargeForm.value,
id: this.record.dischargeId.toString(),
modifiedBy: this.page.userAccount.accountId
};
if (data.dischargeInstructionId) {
data.dischargeInstructionId = data.dischargeInstructionId.join(",")
}
if (data.surgeonNamesId) {
data.surgeonNamesId = data.surgeonNamesId.join(",")
}
data["modifiedBy"] = this.page.userAccount.accountId;
data["roleId"] = this.page.userAccount.roleId;
data["fullName"] = this.page.userAccount.fullName;
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.dischargeupdate), data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitting = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.notifyService.success("Patient Discharged details has been Updated successfully");
this.mode = EditMode.Discharged;
this.fetch();
} else {
if (response.message) {
this.notifyService.info(response.message);
} else {
this.notifyService.defaultError();
}
}
},
() => {
this.receiptTypes = new Array<IReceiptTypeModel>();
}
);
}
private fetchProviderResources() {
this.loadingproviderResources = true;
this.resourceService.providerNames()
.pipe(finalize(() => { this.loadingproviderResources = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.providerResources = response;
});
}
ngOnDestroy() {
this.page.unSubscribe.next();
this.page.unSubscribe.complete();
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<div *ngIf="mode === editMode.Discharged" class="page-title-right">
<button type="button" class="btn btn-primary btn-sm ml-1" (click)="onOpenModel(templateViewDischarge)">
<span><i class="fe-eye mr-1"></i> Discharge Summary Report</span>
</button>
</div>
<a href="javascript:;" class="btn btn-secondary btn-sm ml-1 page-title-right" (click)="onBack()">
<span><i class="fe-arrow-left mr-1"></i> Back</span>
</a>
</div>
<h4 class="page-title">Discharge Summary</h4>
</div>
</div>
<div class="col-lg-12" *ngIf="!finalBillBasics.isFinalBillGenerated">
<div class="d-flex align-items-center justify-content-center">
<div class="alert alert-info"><i class="mdi mdi-lightbulb"></i> Tip: Generate Final Bill to see <span class="font-weight-bold">Discharge Summary</span></div>
</div>
</div>
<div class="col-lg-12" *ngIf="finalBillBasics.isFinalBillGenerated && finalBillBasics.pendingAmount !== 0">
<div class="d-flex align-items-center justify-content-center">
<div class="alert alert-info">
<i class="mdi mdi-lightbulb"></i> Tip:
<span *ngIf="finalBillBasics.pendingAmount < 0" class="font-weight-bold">Clear the Due Amount</span>
<span *ngIf="finalBillBasics.pendingAmount > 0" class="font-weight-bold">Issue the Refund Amount</span>
to view the discharge summary
</div>
</div>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading discharge summary ...</span>
</div>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && finalBillBasics.isFinalBillGenerated && finalBillBasics.pendingAmount === 0">
<div class="col-lg-12 px-2" *ngIf="mode === editMode.New">
<form [formGroup]="dischargeForm" (submit)="onSubmit()">
<div class="card">
<div class="card-body p-0">
<div class="card-box m-0">
<h4 class="box-title"><i class="mdi mdi-information-outline mr-1"></i>General Information</h4>
<div class="row">
<div class="col-lg-6">
<div class="form-group">
<label>Discharge Date & Time <code>*</code></label>
<div>
<input [min]="today | date: 'yyyy-MM-ddTHH:mm'" type="datetime-local" [ngClass]="{ 'is-invalid': (submitted && form.dischargeDate.errors) }" class="form-control" formControlName="dischargeDate" />
<i *ngIf="form.dischargeDate.value" (click)="clearDate('dischargeDate')" ngbTooltip="Clear" placement="right" class="fe-x date-clear-icon"></i>
</div>
<div *ngIf="submitted && form.dischargeDate.errors" class="invalid-feedback show-must">
<div *ngIf="form.dischargeDate.errors.required">Discharge date is required</div>
</div>
</div>
</div>
<!--<div class="col-lg-4">
<div class="form-group">
<label>Discharge Time <code>*</code></label>
<input type="datetime-local" [ngClass]="{ 'is-invalid': (submitted && form.dischargeTime.errors) }" class="form-control" formControlName="dischargeDate" />
<div *ngIf="submitted && form.dischargeTime.errors" class="invalid-feedback show-must">
<div *ngIf="form.dischargeTime.errors.required">Discharge time is required</div>
</div>
</div>
</div>-->
<div class="col-lg-6">
<div class="form-group">
<label>Discharge Status <code>*</code></label>
<select class="form-control" formControlName="dischargeStatusId" [ngClass]="{ 'is-invalid': (submitted && form.dischargeStatusId.errors) }">
<option selecte hidden [value]="null">Select Status</option>
<option *ngFor="let item of dischargeStatus" [ngValue]="item.id" [textContent]="item.name"></option>
</select>
<div *ngIf="submitted && form.dischargeStatusId.errors" class="invalid-feedback show-must">
<div *ngIf="form.dischargeStatusId.errors.required">Discharge date is required</div>
</div>
</div>
</div>
<!--<div class=" row">
<div class="col-lg-12">
<div class="form-group">
<label>Discharge Instruction</label>
<select class="form-control" formControlName="dischargeInstructionId">
<option selecte hidden [value]="null">Select Instruction</option>
<option *ngFor="let item of dischargeInstructions" [ngValue]="item.id" [textContent]="item.name"></option>
</select>
</div>
</div>
</div>-->
</div>
<div class=" row">
<div class="col-lg-12">
<div class="form-group">
<label>Discharge Instruction</label>
<ng-select class="ng-select-sm" [items]="dischargeInstructions" [ngClass]="{ 'is-invalid': submitted && form.dischargeInstructionId.errors }"
bindLabel="name"
bindValue="id"
autocomplete="nope"
placeholder="Select Instructions"
[multiple]="true"
formControlName="dischargeInstructionId">
<ng-template ng-notfound-tmp let-searchTerm="searchTerm">
<div class="ng-option disabled">
No Discharge Instructions found for '{{searchTerm}}'
</div>
</ng-template>
</ng-select>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="form-group">
<label>Discharge Summary </label>
<textarea rows="3" class="form-control" formControlName="dischargeSummary" placeholder="Enter discharge summary"></textarea>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="form-group">
<label>Condition On Discharge </label>
<textarea rows="3" class="form-control" formControlName="conditionOnDischarge" placeholder="Enter condition on discharge"></textarea>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label>Final Diagnosis </label>
<textarea rows="3" class="form-control" formControlName="finalDiagnosis" placeholder="Enter final diagnosis"></textarea>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label>History Of Illness </label>
<textarea rows="3" class="form-control" formControlName="historyOfIllness" placeholder="Enter history of illness"></textarea>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label>Diet </label>
<textarea rows="3" class="form-control" formControlName="diet" placeholder="Enter diet"></textarea>
</div>
</div>
</div>
<h4 class="box-title mt-3"><i class="mdi mdi-repeat mr-1"></i>Follow Up Information</h4>
<div class="row">
<div class="col-lg-5">
<div class="form-group">
<label>Follow Up Date </label>
<div>
<input type="date" [min]="form.dischargeDate.value | date: 'yyyy-MM-dd'" class="form-control" formControlName="dischargeFollowUpDate" placeholder="Enter follow up date" />
<i *ngIf="form.dischargeFollowUpDate.value" (click)="clearDate('dischargeFollowUpDate')" ngbTooltip="Clear" placement="right" class="fe-x date-clear-icon"></i>
</div>
</div>
</div>
<div class="col-lg-3">
<div class="form-group">
<label>Follow Up Days </label>
<input type="number" class="form-control" formControlName="dischargeFollowUpDays" placeholder="Enter follow up days" />
<div *ngIf="submitted && form.dischargeFollowUpDays.errors" class="invalid-feedback show-must">
<div *ngIf="form.dischargeFollowUpDays.errors.min">Follow up days should be minimum 1</div>
</div>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label>Follow Up Summary </label>
<textarea rows="3" class="form-control" formControlName="followUpSummary" placeholder="Enter follow up summary"></textarea>
</div>
</div>
</div>
<h4 class="box-title mt-3"><i class="mdi mdi-human mr-1"></i>Death Information</h4>
<div class="row">
<div class="col-lg-12">
<div class="form-group">
<label class="d-flex align-items-center">
<input type="checkbox" class="form-control-sm mr-2" formControlName="isDeath" /> Is Death
</label>
</div>
</div>
</div>
<ng-container *ngIf="form.isDeath.value">
<div class="row">
<div class="col-lg-5">
<div class="form-group">
<label>Death Date & Time <code>*</code></label>
<input type="datetime-local" class="form-control" [min]="today | date: 'yyyy-MM-ddTHH:mm'" [ngClass]="{ 'is-invalid': (submitted && form.deathDate.errors) }" formControlName="deathDate" />
<div *ngIf="submitted && form.deathDate.errors" class="invalid-feedback show-must">
<div *ngIf="form.deathDate.errors.required">Death date is required</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="form-group">
<label>Cause Of Death <code>*</code></label>
<input type="text" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.causeOfDeath.errors) }" formControlName="causeOfDeath" placeholder="Enter cause of death" />
<div *ngIf="submitted && form.causeOfDeath.errors" class="invalid-feedback show-must">
<div *ngIf="form.causeOfDeath.errors.required">Cause of death is required</div>
</div>
</div>
</div>
</div>
</ng-container>
</div>
</div>
<div class="card-footer bg-light">
<div class="text-right">
<button *ngIf="!record.dischargeId" type="reset" class="btn btn-warning btn-sm mr-2">
<i class="fe-refresh-cw"></i>
<span class="ml-1">Reset</span>
</button>
<button *ngIf="record.dischargeId" type="button" (click)="onCancel()" class="btn btn-danger btn-sm mr-2">
<i class="fe-x"></i>
<span class="ml-1">Cancel</span>
</button>
<button type="submit" [disabled]="submitting" class="btn btn-sm btn-success">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">
<i class="fe-check"></i>
<span class="ml-1">
<span *ngIf="record.dischargeId">Update</span>
<span *ngIf="!record.dischargeId">Discharge Patient</span>
</span>
</span>
</button>
</div>
</div>
</div>
</form>
</div>
<div class="col-lg-12 px-2" *ngIf="mode === editMode.Discharged">
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<div class="card mt-2">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-centered table-bordered table-sm mb-0">
<tbody>
<tr class="table-primary">
<th colspan="4">
<div class="row">
<div class="col-lg-6">General Information</div>
<div class="col-lg-6 text-right">
<span><i class="fe-check mr-2"></i>Patient is discharged</span>
</div>
</div>
</th>
</tr>
<tr>
<th class="table-active">Discharge Date & Time</th>
<td [textContent]="record.dischargeDate | date: 'dd-MM-yyyy, hh:mm a'"></td>
<th class="table-active">Discharge Status</th>
<td [textContent]="record.dischargeStatus"></td>
</tr>
<tr>
<th class="table-active">Discharge Instruction</th>
<td colspan="3" [textContent]="record.dischargeInstructionName || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">Discharge Summary</th>
<td colspan="3" [innerHtml]="record.dischargeSummaryView || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">Condition On Discharge</th>
<td colspan="3" [innerHtml]="record.conditionOnDischarge || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">Final Diagnosis</th>
<td colspan="3" [innerHtml]="record.finalDiagnosis || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">History Of Illness</th>
<td colspan="3" [innerHtml]="record.historyOfIllness || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">Diet</th>
<td colspan="3" [innerHtml]="record.diet || 'N/A'"></td>
</tr>
<tr class="table-primary">
<th colspan="4">
Follow Up Information
</th>
</tr>
<tr>
<th class="table-active">
Follow Up Date
</th>
<td [textContent]="(record.dischargeFollowUpDate | date: 'dd-MM-yyyy') || 'N/A'"></td>
<th class="table-active">
Follow Up Days
</th>
<td [textContent]="record.dischargeFollowUpDays || 'N/A'"></td>
</tr>
<tr>
<th class="table-active">
Follow Up Summary
</th>
<td colspan="3" [innerHtml]="record.followUpSummary || 'N/A'"></td>
</tr>
<ng-container *ngIf="record.isDeath">
<tr class="table-primary">
<th colspan="4">
Death Information
</th>
</tr>
<tr>
<th class="table-active">
Death Date & Time
</th>
<td [textContent]="record.deathDate | date:'dd-MM-yyyy, h:mm:ss a'"></td>
<th class="table-active">
Cause Of Death
</th>
<td [textContent]="record.causeOfDeath"></td>
</tr>
</ng-container>
</tbody>
<tbody>
<tr>
<td colspan="4">
<div class="row d-flex align-items-flex-end">
<div class="col-lg-6">
<span class="small"><span>Last Edited: </span><span class="mr-1" [textContent]="record.createdByName"></span> <span [textContent]="record.createdDate | date: 'dd-MM-yyyy, h:mm:ss a'"></span></span>
</div>
<div class="col-lg-6">
<div class="text-right">
<button class="btn btn-sm btn-light" (click)="onEdit()"><i class="fe-edit-2 mr-2"></i> Edit</button>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateViewDischarge>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-receipt mr-1"></i>Discharge Summary Report</h4>
<div>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();"><i class="fe-x"></i></button>
<button [useExistingCss]="true"
printSectionId="print-section"
ngxPrint
class="btn btn-light btn-xs mr-1 d-print-none">
<i class="fe-printer mr-1"></i>Print
</button>
</div>
</div>
<div class="modal-body" id="print-section">
<div class="card">
<div class="card-body p-0">
<div class="card-box m-0">
<div class="row">
<div class="col-lg-12" *ngIf="isPrintLogo">
<banner-setting></banner-setting>
</div>
<div class="col-lg-12">
<h4 class="box-title mt-3">DISCHARGE SUMMARY</h4>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="table-responsive">
<table class="table table-sm table-borderless table-centered">
<tbody>
<tr>
<th>Admission No</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.admissionNo"></span>
</td>
<th>Discharge Date</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="(record.dischargeDate | date: 'dd-MM-yyyy, h:mm:ss a') || 'Not Discharged Yet'"></span>
</td>
</tr>
<tr>
<th>Patient Name</th>
<td>
<span class="mr-1">:</span>
<span>
<span [textContent]="admission.fullName + ', '"></span>
<span [textContent]="(admission.gender === 'F' ? 'Female' : 'Male') + ', '"></span>
<span [textContent]="admission.age + 'yrs'"></span>
</span>
</td>
<th>UMR No</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.umrNo"></span>
</td>
</tr>
<tr>
<th>Date of Admission</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.admissionDate | date: 'dd-MM-yyyy, h:mm:ss a'"></span>
</td>
<th>Consultant</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.providerName"></span>
</td>
</tr>
<tr>
<th>Department</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.departmentName"></span>
</td>
<th>Admitted Ward</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="!admission.bedNumber ? 'N/A' : (admission.wardName + ' / ' + admission.roomName + ' / ' + admission.bedNumber)"></span>
</td>
</tr>
<tr>
<th>Address</th>
<td colspan="3">
<span class="mr-1">:</span>
<span>Kothrepally, Vikarabad, Telangana</span>
</td>
</tr>
<tr>
<th>Discharge Information</th>
<th colspan="3">
<span class="mr-1">:</span>
<span [textContent]="record.dischargeStatus"></span>
</th>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="row mt-2" *ngIf="record">
<div class="col-12">
<div class="table-responsive">
<table class="table table-centered table-bordered table-sm mb-0">
<tbody>
<tr class="table-primary" *ngIf="isGeneralInformation">
<th colspan="4">
General Information
</th>
</tr>
<tr *ngIf="record.dischargeInstructionName">
<th class="table-active">Discharge Instruction</th>
<td colspan="3" [textContent]="record.dischargeInstructionName || 'N/A'"></td>
</tr>
<tr *ngIf="record.dischargeSummaryView">
<th class="table-active">Discharge Summary</th>
<td colspan="3" [innerHtml]="record.dischargeSummaryView || 'N/A'"></td>
</tr>
<tr *ngIf="record.conditionOnDischarge">
<th class="table-active">Condition On Discharge</th>
<td colspan="3" [innerHtml]="record.conditionOnDischarge || 'N/A'"></td>
</tr>
<tr *ngIf="record.finalDiagnosis">
<th class="table-active">Final Diagnosis</th>
<td colspan="3" [innerHtml]="record.finalDiagnosis || 'N/A'"></td>
</tr>
<tr *ngIf="record.historyOfIllness">
<th class="table-active">History Of Illness</th>
<td colspan="3" [innerHtml]="record.historyOfIllness || 'N/A'"></td>
</tr>
<tr *ngIf="record.diet">
<th class="table-active">Diet</th>
<td colspan="3" [innerHtml]="record.diet || 'N/A'"></td>
</tr>
<tr class="table-primary" *ngIf="isFollowUpInformation">
<th colspan="4">
Follow Up Information
</th>
</tr>
<tr *ngIf="record.dischargeFollowUpDate || record.dischargeFollowUpDays">
<ng-container *ngIf="record.dischargeFollowUpDate">
<th [attr.colspan]="(record.dischargeFollowUpDays ? 1 : 2)" class="table-active">
Follow Up Date
</th>
</ng-container>
<td [textContent]="(record.dischargeFollowUpDate | date: 'dd-MM-yyyy') || 'N/A'"></td>
<ng-container *ngIf="record.dischargeFollowUpDays">
<th [attr.colspan]="(record.dischargeFollowUpDate ? 1 : 2)" class="table-active">
Follow Up Days
</th>
</ng-container>
<td [textContent]="record.dischargeFollowUpDays || 'N/A'"></td>
</tr>
<tr *ngIf="record.followUpSummary">
<th class="table-active">
Follow Up Summary
</th>
<td colspan="3" [innerHtml]="record.followUpSummary || 'N/A'"></td>
</tr>
<tr *ngIf="record.isDeath" class="table-primary">
<th colspan="4">
Death Information <span class="small"></span>
</th>
</tr>
<ng-container *ngIf="record.isDeath">
<tr>
<th class="table-active">
Death Date & Time
</th>
<td [textContent]="record.deathDate | date: 'dd-MM-yyyy, h:mm:ss a'"></td>
<th class="table-active">
Cause Of Death
</th>
<td [textContent]="record.causeOfDeath"></td>
</tr>
</ng-container>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-template>
import { Component, OnDestroy, OnInit, TemplateRef, Input, } from "@angular/core";
import { ActivatedRoute, Params } from "@angular/router";
import { takeUntil, finalize } from "rxjs/operators";
import { DatePipe, Location } from '@angular/common';
import { IUserAccount, Page, GenericResponse, GenericStatus } from "@shared/models";
import { AppData, HttpService, NotifyService, FinalBillService, PrintOptionService } from "@shared/services";
import { ApiResources } from "../../../../../shared/helpers";
import { IDischargeModel } from "../../models/discharge.model";
import { LookUpModel } from "../../models/look-up.model";
import { IReceiptTypeModel, ReceiptType } from "../../models/receipt-type.model";
import { PayType } from "../../models/pay-type.model";
import { FormGroup, FormBuilder, Validators } from "@angular/forms";
import { FinalBillBasicModel } from "../../models/final-bill-basic.model";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { IAdmissionModel } from "../../models/admission.model";
import { AdmissionFetchHelper } from "../../../progress-report/shared/helper";
enum EditMode {
New = 1,
Discharged = 2
}
@Component({
templateUrl: "./discharge.html",
styleUrls: ['../../services.css']
})
export class DischargePage implements OnInit, OnDestroy {
receiptType = ReceiptType;
payType = PayType;
editMode = EditMode;
page: Page;
loading: boolean;
isChargesLoading: boolean;
record: IDischargeModel;
admission: IAdmissionModel;
submitting: boolean;
submitted: boolean;
admissionId: string;
isAdmission: boolean;
isInstructionsLoading: boolean;
dischargeInstructions: Array<LookUpModel>;
isStatusLoading: boolean;
dischargeStatus: Array<LookUpModel>;
receiptTypes: Array<IReceiptTypeModel>;
dischargeForm: FormGroup;
finalBillBasics: FinalBillBasicModel;
mode: EditMode;
today = new Date();
modalRef: NgbModalRef;
@Input() isPrintLogo: boolean;
constructor(
private readonly httpService: HttpService,
private readonly route: ActivatedRoute,
private readonly finalBillService: FinalBillService,
private readonly appData: AppData,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly modalService: NgbModal,
private readonly datePipe: DatePipe,
private readonly location: Location,
private readonly admissionFetchHelper: AdmissionFetchHelper,
private readonly printOptionService: PrintOptionService
) {
this.mode = EditMode.New;
this.record = {} as IDischargeModel;
this.dischargeInstructions = new Array<LookUpModel>();
this.dischargeStatus = new Array<LookUpModel>();
this.finalBillBasics = new FinalBillBasicModel();
this.isChargesLoading = false;
this.loading = true;
this.page = new Page();
this.buildDischargeForm();
this.formChanges();
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.route.parent.paramMap
.subscribe((params: Params) => {
this.admissionId = params["params"]["id"];
this.isAdmission = params["params"]["type"] === "a";
this.getFinalBillBasics(() => {
this.admissionFetch();
this.fetch();
this.getFinalBillBasics();
});
});
this.fetchInstructions();
this.fetchStatus();
} else {
this.page.userAccount = undefined;
}
this.printOptionService.get((is) => { this.isPrintLogo = is; });
});
}
onBack = () => {
this.location.back();
}
get isGeneralInformation() {
return this.record && Object.keys(this.record).filter(x =>
x !== "dischargeFollowUpDate" &&
x !== "dischargeFollowUpDays" &&
x !== "followUpSummary" &&
x !== "isDeath" &&
x !== "deathDate" &&
x !== "causeOfDeath"
).map(x => this.record[x]).filter(x => x).length;
}
get isFollowUpInformation() {
return this.record &&
Object.keys(this.record).filter(x =>
x === "dischargeFollowUpDate" ||
x === "dischargeFollowUpDays" ||
x === "followUpSummary"
).map(x => this.record[x]).filter(x => x).length;
}
get form() {
return this.dischargeForm.controls;
}
private buildDischargeForm(model?: IDischargeModel) {
var disInstructionIds = new Array<number>();
if (model) {
model.dischargeInstructionId.split(",").forEach(item => {
disInstructionIds.push(parseInt(item));
});
}
this.dischargeForm = this.formBuilder.group({
dischargeDate: [model ? model.dischargeDate : this.datePipe.transform(new Date(), 'yyyy-MM-ddTHH:mm'), [Validators.required]],
dischargeInstructionId: [model ? disInstructionIds : null],
dischargeStatusId: [model ? model.dischargeStatusId : null, [Validators.required]],
//dischargeInstructionName: [model ? model.dischargeInstructionName : null],
dischargeSummary: [model ? model.dischargeSummary : null],
conditionOnDischarge: [model ? model.conditionOnDischarge : null],
finalDiagnosis: [model ? model.finalDiagnosis : null],
historyOfIllness: [model ? model.historyOfIllness : null],
diet: [model ? model.diet : null],
dischargeFollowUpDate: [model ? model.dischargeFollowUpDate : null],
dischargeFollowUpDays: [model ? model.dischargeFollowUpDays : null, [Validators.min(1)]],
followUpSummary: [model ? model.followUpSummary : null],
isDeath: [model ? model.isDeath : null],
deathDate: [model ? model.deathDate : null],
causeOfDeath: [model ? model.causeOfDeath : null]
});
}
onOpenModel(content: TemplateRef<any>) {
this.getFinalBillBasics();
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
size: "lg",
windowClass: "custom-modal slots-modal effect-scale"
});
return;
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.submitting = undefined;
this.submitted = undefined;
}
clearDate = (property: string) => {
this.dischargeForm.patchValue({
[property]: null
});
}
formChanges = () => {
this.dischargeForm.get("isDeath").valueChanges.subscribe((value: boolean) => {
const deathDate = this.dischargeForm.get('deathDate');
const causeOfDeath = this.dischargeForm.get('causeOfDeath');
deathDate.clearValidators();
causeOfDeath.clearValidators();
if (value) {
deathDate.setValidators([Validators.required]);
causeOfDeath.setValidators([Validators.required]);
}
deathDate.updateValueAndValidity();
causeOfDeath.updateValueAndValidity();
});
}
fetch = () => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.fetch),
{ id: this.admissionId })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.mode = EditMode.Discharged;
const record = response.data as IDischargeModel;
record.dischargeSummaryView = record.dischargeSummary
? record.dischargeSummary.replace(/\n/g, "<br />")
: record.dischargeSummary;
this.buildDischargeForm(record);
this.record = record;
} else if (response.status === GenericStatus[GenericStatus.Error]) {
this.mode = EditMode.Discharged;
this.notifyService.defaultError();
} else {
this.mode = EditMode.New;
}
},
() => {
this.record = null;
}
);
}
admissionFetch = () => {
this.admissionFetchHelper.admissionFetch(+this.admissionId, this.isAdmission, (data: IAdmissionModel) => {
this.loading = false
this.admission = data;
if (this.mode === EditMode.New && this.admission.expectedDischargeDate) {
this.dischargeForm.patchValue({
dischargeDate: this.datePipe.transform(new Date(this.admission.expectedDischargeDate), 'yyyy-MM-ddTHH:mm')
})
}
});
}
getFinalBillBasics = (callback = () => { }) => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.finalBill.base, ApiResources.finalBill.getBasics), { id: this.admissionId, isAdmission: this.isAdmission })
.pipe(takeUntil(this.page.unSubscribe))
.subscribe(
(response: GenericResponse) => {
this.finalBillBasics = response.data as FinalBillBasicModel;
callback();
},
() => {
this.finalBillBasics = new FinalBillBasicModel();
}
);
}
fetchInstructions = () => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.fetchInstructions), {})
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.isInstructionsLoading = false))
.subscribe(
(response: GenericResponse) => {
this.dischargeInstructions = response.data as Array<LookUpModel>;
},
() => {
this.dischargeInstructions = new Array<LookUpModel>();
}
);
}
fetchStatus = () => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.fetchStatus), {})
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.isStatusLoading = false))
.subscribe(
(response: GenericResponse) => {
this.dischargeStatus = response.data as Array<LookUpModel>;
},
() => {
this.dischargeStatus = new Array<LookUpModel>();
}
);
}
insert = () => {
this.submitted = true;
if (!this.dischargeForm.valid) {
return;
}
this.submitting = true;
const data = {
...this.dischargeForm.value,
createdBy: this.page.userAccount.accountId,
id: this.admissionId,
};
if (data.dischargeInstructionId) {
data.dischargeInstructionId = data.dischargeInstructionId.join(",")
}
data["modifiedBy"] = this.page.userAccount.accountId;
data["roleId"] = this.page.userAccount.roleId;
data["fullName"] = this.page.userAccount.fullName;
console.log(data)
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.insert), data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitting = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.notifyService.success("Patient has been discharged successfully");
this.mode = EditMode.Discharged;
this.admissionFetch();
this.fetch();
this.finalBillService.set(true);
} else {
if (response.message) {
this.notifyService.info(response.message);
} else {
this.notifyService.defaultError();
}
}
},
() => {
this.notifyService.defaultError();
}
);
}
onSubmit = () => {
if (this.record.dischargeId) {
this.update();
} else {
this.insert();
}
}
onEdit = () => {
this.mode = EditMode.New;
}
onCancel = () => {
this.mode = EditMode.Discharged;
}
update = () => {
this.submitted = true;
if (!this.dischargeForm.valid) {
return;
}
this.submitting = true;
const data = {
...this.dischargeForm.value,
id: this.record.dischargeId.toString(),
modifiedBy: this.page.userAccount.accountId
};
if (data.dischargeInstructionId) {
data.dischargeInstructionId = data.dischargeInstructionId.join(",")
}
data["modifiedBy"] = this.page.userAccount.accountId;
data["roleId"] = this.page.userAccount.roleId;
data["fullName"] = this.page.userAccount.fullName;
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.discharge.base, ApiResources.discharge.update), data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitting = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.notifyService.success("Patient has been discharged successfully");
this.mode = EditMode.Discharged;
this.fetch();
} else {
if (response.message) {
this.notifyService.info(response.message);
} else {
this.notifyService.defaultError();
}
}
},
() => {
this.receiptTypes = new Array<IReceiptTypeModel>();
}
);
}
ngOnDestroy() {
this.page.unSubscribe.next();
this.page.unSubscribe.complete();
}
}
\ No newline at end of file
<style>
.blink {
animation: blinker 1.5s cubic-bezier(.5, 0, 1, 1) infinite alternate;
}
@keyframes blinker {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
</style>
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<div *ngIf="mode !== editMode.New" class="page-title-right">
<button type="button" class="btn btn-primary btn-sm ml-1" (click)="onOpenModel(templateViewFinalBill)">
<span><i class="fe-eye mr-1"></i> Final Bill Report</span>
</button>
</div>
<a href="javascript:;" class="btn btn-secondary btn-sm ml-1 page-title-right" (click)="onBack()">
<span><i class="fe-arrow-left mr-1"></i> Back</span>
</a>
</div>
<h4 class="page-title">Final Bill</h4>
</div>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading service orders ...</span>
</div>
</div>
</div>
<div class="row" *ngIf="!loading">
<div class="col-12">
<div class="card mb-0">
<div class="card-body p-0">
<form [formGroup]="finalBillForm" (submit)="onSubmit()">
<div class="overflow-auto">
<table class="table table-centered table-bordered table-sm mb-0">
<thead>
<tr class="table-active">
<th colspan="8">
<i class="mdi mdi-medical-bag mr-1"></i>Packages
</th>
</tr>
</thead>
<ng-container *ngIf="serviceOrder.packageRecords.length > 0">
<thead>
<tr>
<th style="width: 40px;">#</th>
<th colspan="2">Package Name</th>
<th>Module Type</th>
<th>Quantity</th>
<th>Expires In</th>
<th>Amount</th>
<th style="width: 50px;"></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of serviceOrder.packageRecords; let i = index; trackBy: trackByPackage">
<td [textContent]="i + 1"></td>
<td colspan="2" *ngIf="!item.active">
<span class="title font-weight-semibold text-line-through" [textContent]="item.packageName"></span>
</td>
<td colspan="2" *ngIf="item.active">
<span class="title font-weight-semibold" [textContent]="item.packageName"></span>
<a (click)="onViewPackage(templateViewPackage, item)" href="javascript:;" class="small text-primary ml-1">(View)</a>
</td>
<td [textContent]="item.moduleTypeName"></td>
<td>
<span [textContent]="item.quantity"></span>
<small class="ml-1" *ngIf="item.freeQuantity" [textContent]="'(Free : ' + item.freeQuantity + ')'"></small>
</td>
<td *ngIf="item.expiresIn">
<span [textContent]="item.expiresIn"></span>
<small class="ml-1" [textContent]="'days'"></small>
</td>
<td *ngIf="!item.expiresIn">-</td>
<td [textContent]="(item.total || 0) | currency :'₹ ':'symbol':'1.2-2'"></td>
<td></td>
</tr>
</tbody>
</ng-container>
<tbody *ngIf="serviceOrder.packageRecords.length <= 0">
<tr>
<td colspan="6" class="text-right"> No packages has been added</td>
<td colspan="2" [textContent]="0 | currency:'INR'"></td>
</tr>
</tbody>
<thead>
<tr class="table-active">
<th colspan="8">
<i class="mdi mdi-file-document-outline mr-1"></i>General Services
</th>
</tr>
</thead>
<thead *ngIf="serviceOrder.generalRecords.length > 0">
<tr>
<th style="width: 40px;">#</th>
<th>Department</th>
<th>Charge Group</th>
<th>Charge</th>
<th>OP/IP Cost</th>
<th>Qty</th>
<th>Amount</th>
<th style="width: 50px;"></th>
</tr>
</thead>
<tbody>
<ng-container *ngIf="serviceOrder.generalRecords.length > 0">
<tr *ngFor="let record of serviceOrder.generalRecords; let i = index;">
<td [textContent]="i + 1"></td>
<td [textContent]="record.departmentName"></td>
<td [textContent]="record.chargeGroupName"></td>
<td>
<span>
<i *ngIf="record.automaticTypeId === automaticType.BedCharges" class="mdi mdi-bed mr-1"></i>
<i *ngIf="record.automaticTypeId === automaticType.DoctorCharges || record.chargeTypeId === chargeType.Special" class="mdi mdi-doctor mr-1"></i>
<i *ngIf="record.chargeTypeId === chargeType.Covid" class="mdi mdi-virus mr-1"></i>
<span [textContent]="record.chargeName"></span>
</span>
<div *ngIf="record.chargeTypeMainName">
<span class="small">
Dr. <span [textContent]="record.chargeTypeMainName"></span>
</span>
</div>
</td>
<td>
<div class="d-flex align-items-center justify-content-between">
<span [textContent]="record.cost | currency:'INR'" *ngIf="record.showAmount"></span>
<span [textContent]="0 | currency:'INR'" *ngIf="!record.showAmount"></span>
</div>
</td>
<td>
<!--<span [textContent]="record.unit"></span>
<span class="small">
(
<span [textContent]="repeatType[record.repeatTypeId]"></span>
<span *ngIf="record.unit > 1 && record.repeatTypeId != repeatType.Once">s</span>
)
</span>-->
<div class="d-flex justify-content-between align-items-center">
<div>
<span [textContent]="record.unit + (record.usedQuantity || 0)"></span>
<small class="ml-1 font-11 text-mute">
<span [textContent]="repeatType[record.repeatTypeId]"></span>
<span *ngIf="record.unit > 1 && record.repeatTypeId != repeatType.Once">s</span>
</small>
</div>
<!--<div *ngIf="record.usedQuantity > 0" class="text-primary">
<span class="mr-1">(<span [textContent]="record.usedQuantity"></span>)</span>
<span placement="left" [ngbTooltip]="record.usedQuantity + ' from pacakage'"><i class="mdi mdi-information"></i></span>
</div>-->
</div>
</td>
<td>
<div class="d-flex align-items-center justify-content-between">
<span [textContent]="((record.cost * record.unit) - (record.discount || 0 )) | currency:'INR'" *ngIf="record.showAmount"></span>
<span [textContent]="0 | currency:'INR'" *ngIf="!record.showAmount"></span>
<span class="font-weight-bold text-primary" *ngIf="record.discount"><i class="mdi mdi-sale mr-1"></i><span [textContent]="(record.discount || 0 ) | currency:'INR'"></span></span>
</div>
</td>
<td></td>
</tr>
</ng-container>
<ng-container *ngIf="serviceOrder.generalRecords.length <= 0">
<tr>
<td colspan="6" class="text-right"> No general services found</td>
<td [textContent]="0 | currency:'INR'"></td>
<td></td>
</tr>
</ng-container>
</tbody>
<thead *ngIf="isAdmission">
<tr class="table-active">
<th colspan="8">
<i class="mdi mdi-pill mr-1"></i>Pharmacy Services
</th>
</tr>
</thead>
<thead *ngIf="serviceOrder.pharmacyIndentRecords.length > 0">
<tr>
<th style="width: 40px;">#</th>
<th colspan="2">Category</th>
<th>Product</th>
<th>Rate</th>
<th>Qty</th>
<th>Amount</th>
<th style="width: 50px;"></th>
</tr>
</thead>
<tbody>
<ng-container *ngIf="serviceOrder.pharmacyIndentRecords.length > 0">
<tr *ngFor="let record of serviceOrder.pharmacyIndentRecords; let i = index;">
<td [textContent]="i + 1"></td>
<!--<td [textContent]="record.departmentName"></td>-->
<td colspan="2" [textContent]="record.categoryName"></td>
<td [textContent]="record.productName"></td>
<td>
<div class="d-flex align-items-center justify-content-between">
<span [textContent]="record.cost | currency:'INR'" *ngIf="record.showAmount"></span>
<span [textContent]="0 | currency:'INR'" *ngIf="!record.showAmount"></span>
</div>
</td>
<td [textContent]="record.unit"></td>
<td>
<div *ngIf="record.showAmount">
<span [textContent]="((record.cost * record.unit) - record.discountAmount) | currency:'INR'"></span>
<span class="small ml-1" *ngIf="record.discountPercentage">(<span [textContent]="record.discountPercentage + '% '"></span>discount from pharmacy)</span>
</div>
<div class="d-flex align-items-center justify-content-between" *ngIf="!record.showAmount">
<span [ngClass]="{'text-line-through' : !record.active}" [textContent]="0 | currency:'INR'"></span>
</div>
</td>
<td></td>
</tr>
</ng-container>
<ng-container *ngIf="serviceOrder.pharmacyIndentRecords.length <= 0 && isAdmission">
<tr>
<td colspan="6" class="text-right"> No pharmacy services found</td>
<td colspan="2" [textContent]="0 | currency:'INR'"></td>
</tr>
</ng-container>
</tbody>
<thead>
<tr class="table-active">
<th colspan="8">
<i class="mdi mdi-flask-outline mr-1"></i>Laboratory Services
</th>
</tr>
</thead>
<thead *ngIf="serviceOrder.labServicesRecords.length > 0">
<tr>
<th style="width: 40px;">#</th>
<th colspan="2">Lab name</th>
<th>Lab Code</th>
<th>Charge</th>
<th style="width: 75px;">Qty</th>
<th>Amount</th>
<th style="width: 50px;"></th>
</tr>
</thead>
<tbody>
<ng-container *ngIf="serviceOrder.labServicesRecords.length > 0">
<tr *ngFor="let record of serviceOrder.labServicesRecords; let i = index;">
<td [textContent]="i + 1"></td>
<td [textContent]="record.testName" colspan="2"></td>
<td [textContent]="record.testCode"></td>
<td>
<span *ngIf="record.showAmount" [textContent]="record.cost | currency:'INR'"></span>
<div class="d-flex align-items-center justify-content-between" *ngIf="!record.showAmount">
<span [textContent]="0 | currency:'INR'"></span>
</div>
</td>
<td>
<div class="d-flex justify-content-between align-items-center">
<div>
<span [textContent]="record.unit + (record.usedQuantity || 0)"></span>
</div>
<!--<div *ngIf="item.usedQuantity > 0" class="text-primary">
<span class="mr-1">(<span [textContent]="item.usedQuantity"></span>)</span>
<span placement="left" [ngbTooltip]="item.usedQuantity + ' from pacakage'"><i class="mdi mdi-information"></i></span>
</div>-->
</div>
</td>
<td>
<div class="d-flex align-items-center justify-content-between" *ngIf="record.showAmount">
<span [textContent]="((record.cost * record.unit) - (record.discount || 0 )) | currency:'INR'"></span>
<span class="font-weight-bold text-primary" *ngIf="record.discount"><i class="mdi mdi-sale mr-1"></i><span [textContent]="(record.discount || 0 ) | currency:'INR'"></span></span>
</div>
<div class="d-flex align-items-center justify-content-between" *ngIf="!record.showAmount">
<span [textContent]="0 | currency:'INR'"></span>
</div>
</td>
<td></td>
</tr>
</ng-container>
<ng-container *ngIf="serviceOrder.labServicesRecords.length <= 0">
<tr>
<td colspan="6" class="text-right"> No laboratory services has been added</td>
<td [textContent]="0 | currency:'INR'"></td>
<td colspan="2"></td>
</tr>
</ng-container>
</tbody>
<!--<thead>
<tr class="table-active">
<th colspan="10">
<div class="float-left mt-1"><i class="mdi mdi-flask-outline mr-1"></i>Insurance</div>
</th>
</tr>
</thead>-->
<tfoot>
<tr class="table-warning">
<th colspan="6" class="text-right">Gross Amount</th>
<th colspan="2" [textContent]="((serviceOrder.packageTotal || 0) + (serviceOrder.generalTotal || 0) + (serviceOrder.labServicesTotal || 0) + (serviceOrder.pharmacyIndentTotal || 0)) | currency:'INR'"></th>
</tr>
<tr class="table-active">
<th colspan="6" class="text-right">
<div *ngIf="mode === editMode.New" class="row d-flex align-items-center">
<div class="col-lg-3"></div>
<div class="col-lg-3" *ngIf="!form.discountType.value"></div>
<div class="col-lg-3">
<h5>Discount</h5>
</div>
<div class="col-lg-3">
<select class="form-control" formControlName="discountType">
<option selected [ngValue]="null">No Discount</option>
<option [ngValue]="discountTypeEnum.Number" [disabled]="disableActionBtns">Discount In Amount</option>
<option [ngValue]="discountTypeEnum.Percentage" [disabled]="disableActionBtns">Discount In Percentage</option>
</select>
</div>
<div class="col-lg-3" *ngIf="form.discountType.value">
<div class="input-group">
<input [ngClass]="{ 'is-invalid': form.discount.errors }" type="number" class="form-control" formControlName="discount"
[placeholder]="'max ' + (form.discountType.value == discountTypeEnum.Number ? ('₹' + (((serviceOrder.packageTotal || 0) + (serviceOrder.generalTotal || 0)+ (serviceOrder.labServicesTotal || 0) + (serviceOrder.pharmacyIndentTotal || 0)))) : '100%')">
<div class="input-group-append">
<div class="input-group-text">
<span *ngIf="form.discountType.value != discountTypeEnum.Number">%</span>
<span *ngIf="form.discountType.value == discountTypeEnum.Number"></span>
</div>
</div>
</div>
</div>
</div>
<div *ngIf="mode !== editMode.New" class="row d-flex align-items-center">
<div class="col-lg-3"></div>
<div class="col-lg-3"></div>
<div class="col-lg-3"></div>
<div class="col-lg-3">
<h5 *ngIf="!form.discountType.value">No Discount</h5>
<h5 *ngIf="form.discountType.value == discountTypeEnum.Number">Discount In Amount</h5>
<h5 *ngIf="form.discountType.value == discountTypeEnum.Percentage">Discount In Percentage <span class="small">(<span [textContent]="form.discount.value + '%'"></span>)</span></h5>
</div>
</div>
</th>
<th [textContent]="(!form.discountType.value
? 0
: form.discountType.value == discountTypeEnum.Number
? (form.discount.value || 0)
: ((serviceOrder.packageTotal || 0) + (serviceOrder.generalTotal || 0)+ (serviceOrder.labServicesTotal || 0) + (serviceOrder.pharmacyIndentTotal || 0)) * ((form.discount.value || 0)/100)) | currency:'INR'"></th>
<td></td>
</tr>
<tr *ngFor="let item of insuranceAdmission">
<th colspan="6" class="text-right" [textContent]="item.insuranceCompanyName"></th>
<th colspan="2" [textContent]="(item.expectedAmount || 0) | currency:'INR'"></th>
</tr>
<tr class="table-warning">
<th colspan="6" class="text-right">Insurance Covered</th>
<th colspan="2" [textContent]="(insuranceAmount || 0) | currency:'INR'"></th>
</tr>
<tr class="table-warning">
<th colspan="6" class="text-right">Net Amount</th>
<th colspan="2" [textContent]="(finalAmount || 0) | currency:'INR'"></th>
</tr>
<tr class="table-active">
<th colspan="6" class="text-right">Total Amount Paid</th>
<th colspan="2" class="text-primary" [textContent]="finalBillBasics.totalAmountPaid | currency:'INR'"></th>
</tr>
<tr *ngIf="(finalBillBasics.totalAmountPaid - (finalAmount || 0)) < 0" class="table-active">
<th colspan="6" class="text-right">Total Amount Due</th>
<th colspan="2" class="text-danger" [textContent]="((finalBillBasics.totalAmountPaid - (finalAmount || 0)) * -1) | currency:'INR'"></th>
</tr>
<tr *ngIf="(finalBillBasics.totalAmountPaid - (finalAmount || 0)) > 0" class="table-active">
<th colspan="6" class="text-right">Total Refund Due</th>
<th colspan="2" class="text-success" [textContent]="(finalBillBasics.totalAmountPaid - (finalAmount || 0)) | currency:'INR'"></th>
</tr>
<tr>
<th colspan="8">
<div class="row">
<div class="col-lg-7">
<!--<div class="text-left d-flex">
<div class="mr-3">
<h6>Total Amount Paid(Including Advance): </h6>
<h5 class="text-primary" [textContent]="finalBillBasics.totalAmountPaid | currency:'INR'"></h5>
</div>
<div >
<h6>Total Amount Due: </h6>
<h5 class="text-danger" [textContent]="((finalBillBasics.totalAmountPaid - (finalAmount || 0)) * -1) | currency:'INR'"></h5>
</div>
<div >
<h6>Total Refund Due: </h6>
<h5 class="text-success" [textContent]="(finalBillBasics.totalAmountPaid - (finalAmount || 0)) | currency:'INR'"></h5>
</div>
</div>-->
</div>
<div class="col-lg flex-end">
<ng-container *ngIf="mode !== editMode.New">
<div class="mr-2 badge badge-outline-blue">
<div *ngIf="(finalBillBasics.totalAmountPaid - (finalAmount || 0)) < 0">
<div class="small">*Go to receipts to pay the due amount</div>
</div>
<div *ngIf="(finalBillBasics.totalAmountPaid - (finalAmount || 0)) > 0">
<div class="small">*Go to receipts to issue refund</div>
</div>
</div>
</ng-container>
<div class="text-right">
<button *ngIf="mode === editMode.New && (deletedCharges.length > 0 || deletedPharmacy.length > 0|| deletedLabServices.length > 0)" type="button" (click)="resetHelper()" class="btn btn-warning btn-sm mr-2">
<i class="fe-refresh-cw"></i>
<span class="ml-1">Reset</span>
</button>
<button type="submit" [disabled]="submitting || disableActionBtns" [ngClass]="{'btn-success' : mode === editMode.New, 'btn-danger' : mode === editMode.Final}" class="btn btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">
<i class="fe-check"></i>
<span class="ml-1" [textContent]="mode === editMode.New ? 'Generate Final Bill' : 'Cancel Final Bill'"></span>
</span>
</button>
</div>
</div>
</div>
</th>
</tr>
</tfoot>
</table>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #templateViewFinalBill>
<div>
<div class="modal-header">
<h4 class="modal-title"><i class="mdi mdi-receipt mr-1"></i>Final Bill Report</h4>
<div>
<!--<div class="btn-group d-print-none" style="right: 5px">
<button class="btn btn-sm" [class.btn-light]="!isPrintLogo" [class.btn-outline-light]="isPrintLogo" type="button" (click)="onChangePrintType(false)"><i class="mdi mdi-check mr-1" *ngIf="!isPrintLogo"></i>Without Logo</button>
<button class="btn btn-sm" [class.btn-light]="isPrintLogo" [class.btn-outline-light]="!isPrintLogo" type="button" (click)="onChangePrintType(true)"><i class="mdi mdi-check mr-1" *ngIf="isPrintLogo"></i>With Logo</button>
</div>-->
<!--<button [useExistingCss]="true" printSectionId="receipt-section" ngxPrintclass="btn btn-light btn-xs mr-1 d-print-none"><i class="fe-printer mr-1"></i>Print</button>-->
<button [useExistingCss]="true" printSectionId="receipt-section" ngxPrint class="btn btn-light btn-xs mr-1 d-print-none"><i class="fe-printer mr-1"></i>Print</button>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();"><i class="fe-x"></i></button>
</div>
</div>
<div class="modal-body" id="receipt-section">
<div class="card">
<div class="card-body p-0">
<div class="card-box m-0">
<div class="row">
<div class="col-lg-12" *ngIf="isPrintLogo">
<banner-setting></banner-setting>
</div>
<!--<div class="col-lg-12" *ngIf="!isPrintLogo">
</div>-->
<div class="col-lg-12">
<h4 class="box-title text-center mt-3">FINAL BILL</h4>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="overflow-auto">
<table class="table table-sm table-borderless table-centered">
<tbody>
<tr>
<th>Bill No</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="billNumber || 'N/A'"></span>
</td>
<th>
<span *ngIf="isAdmission">Admission No</span>
<span *ngIf="!isAdmission">Appointment No</span>
</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.admissionNo"></span>
</td>
</tr>
<tr>
<th>Bill Date</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="now | date: 'dd-MM-yyyy, h:mm:ss a'"></span>
</td>
<th>
<span *ngIf="isAdmission">Admission Date</span>
<span *ngIf="!isAdmission">Appointment Date</span>
</th>
<td>
<span class="mr-1">:</span>
<span *ngIf="isAdmission" [textContent]="admission.admissionDate | date: 'dd-MM-yyyy, h:mm:ss a'"></span>
<span *ngIf="!isAdmission">
<span [textContent]="admission.admissionDate | date: 'dd-MM-yyyy'"></span>
<span [textContent]="' ' + admission.timeString"></span>
</span>
</td>
</tr>
<tr>
<th>Patient Name</th>
<td>
<span class="mr-1">:</span>
<span>
<span [textContent]="admission.fullName + ', '"></span>
<span [textContent]="(admission.gender === 'F' ? 'Female' : 'Male') + ', '"></span>
<span [textContent]="admission.age + 'yrs'"></span>
</span>
</td>
<th>Father/Husband Name</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.fatherOrHusband"></span>
</td>
</tr>
<tr>
<th>Doctor Name</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.providerName"></span>
</td>
<th>Department</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.departmentName"></span>
</td>
</tr>
<tr *ngIf="isAdmission">
<th>Admitted Ward</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="!admission.bedNumber ? 'N/A' : (admission.wardName + ' / ' + admission.roomName + ' / ' + admission.bedNumber)"></span>
</td>
<th>Discharge Date</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="(finalBillBasics.dischargeDate | date: 'dd-MM-yyyy, h:mm:ss a') || 'Not Discharged Yet'"></span>
</td>
</tr>
<tr>
<th>Address</th>
<td>
<span class="mr-1">:</span>
<span>Kothrepally, Vikarabad, Telangana</span>
</td>
<th>UMR No</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.umrNo"></span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="row mt-2">
<div class="col-12">
<div class="table-responsive table-responsive-lg">
<table class="table table-centered table-bordered table-sm mb-0">
<thead *ngIf="isAdmission">
<tr class="table-primary">
<th colspan="7" class="text-center">
Hospitalization Charges From <span class="mr-1 ml-1" [textContent]="admission.admissionDate | date: 'dd-MM-yyyy, h:mm:ss a'"></span> To <span class="mr-1 ml-1" [textContent]="(finalBillBasics.dischargeDate | date: 'dd-MM-yyyy, h:mm:ss a') || 'Not Discharged Yet'"></span>
</th>
</tr>
</thead>
<ng-container *ngIf="serviceOrder.packageRecords.length > 0">
<thead>
<tr class="table-active">
<th colspan="8">
<i class="mdi mdi-medical-bag mr-1"></i>Packages
</th>
</tr>
</thead>
<thead>
<tr>
<th style="width: 40px;">#</th>
<th colspan="4">Package Name</th>
<!--<th>Services</th>
<th>Medicines</th>
<th>Surgery Kits</th>-->
<th>Qty</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let record of serviceOrder.packageRecords; let i = index;">
<td [textContent]="i + 1"></td>
<td colspan="4" [textContent]="record.packageName"></td>
<!--<td [textContent]="record.totalGeneral || 0"></td>
<td [textContent]="record.totalMedicines || 0"></td>
<td [textContent]="record.totalKits || 0"></td>-->
<td [textContent]="record.unit"></td>
<td [textContent]="(record.total) | currency:'INR'">
</td>
</tr>
</tbody>
</ng-container>
<ng-container *ngIf="serviceOrder.generalRecords.length > 0">
<thead>
<tr class="table-active">
<th colspan="7">
General services
</th>
</tr>
</thead>
<thead>
<tr>
<th style="width: 40px;">#</th>
<th>Department</th>
<th>Charge Group</th>
<th>Charge</th>
<th>Rate</th>
<th>Qty</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let record of serviceOrder.generalRecords; let i = index;">
<td [textContent]="i + 1"></td>
<td [textContent]="record.departmentName"></td>
<td [textContent]="record.chargeGroupName"></td>
<td>
<div [textContent]="record.chargeName"></div>
<div *ngIf="record.chargeTypeMainName">
<span class="small">
Dr. <span [textContent]="record.chargeTypeMainName"></span>
</span>
</div>
</td>
<td [textContent]="record.cost | currency:'INR'"></td>
<td [textContent]="record.unit"></td>
<td [textContent]="(record.cost * record.unit) | currency:'INR'"></td>
</tr>
</tbody>
</ng-container>
<ng-container *ngIf="serviceOrder.pharmacyIndentRecords.length > 0 && isAdmission">
<thead>
<tr class="table-active">
<th colspan="7">
Pharmacy Services
</th>
</tr>
</thead>
<thead>
<tr>
<th style="width: 40px;">#</th>
<th colspan="2">Category</th>
<th>Product</th>
<th>Rate</th>
<th>Qty</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let record of serviceOrder.pharmacyIndentRecords; let i = index;">
<td [textContent]="i + 1"></td>
<td colspan="2" [textContent]="record.categoryName"></td>
<td [textContent]="record.productName"></td>
<td>
<span *ngIf="record.showAmount" [textContent]="record.cost | currency:'INR'"></span>
<div class="d-flex align-items-center justify-content-between" *ngIf="!record.showAmount">
<span [textContent]="0 | currency:'INR'"></span>
</div>
</td>
<td [textContent]="record.unit"></td>
<td>
<div class="d-flex align-items-center justify-content-between" *ngIf="record.showAmount">
<span [textContent]="((record.cost * record.unit) - record.discountAmount) | currency:'INR'"></span>
<span class="small ml-1" *ngIf="record.discountPercentage">(<span [textContent]="record.discountPercentage + '% '"></span>discount from pharmacy)</span>
</div>
<div class="d-flex align-items-center justify-content-between" *ngIf="!record.showAmount">
<span [textContent]="0 | currency:'INR'"></span>
</div>
</td>
</tr>
</tbody>
</ng-container>
<ng-container *ngIf="serviceOrder.labServicesRecords.length > 0">
<thead>
<tr class="table-active">
<th colspan="7">
Laboratory Services
</th>
</tr>
</thead>
<thead>
<tr>
<th style="width: 40px;">#</th>
<th colspan="2">Lab name</th>
<th>Lab Code</th>
<th>Charge</th>
<th style="width: 75px;">Qty</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let record of serviceOrder.labServicesRecords; let i = index;">
<td [textContent]="i + 1"></td>
<td [textContent]="record.testName" colspan="2"></td>
<td [textContent]="record.testCode"></td>
<td>
<span *ngIf="record.showAmount" [textContent]="record.cost | currency:'INR'"></span>
<div class="d-flex align-items-center justify-content-between" *ngIf="!record.showAmount">
<span [textContent]="0 | currency:'INR'"></span>
</div>
</td>
<td>
<span [textContent]="record.unit"></span>
</td>
<td>
<div class="d-flex align-items-center justify-content-between" *ngIf="record.showAmount">
<span [textContent]="(record.cost * record.unit) | currency:'INR'"></span>
</div>
<div class="d-flex align-items-center justify-content-between" *ngIf="!record.showAmount">
<span [textContent]="0 | currency:'INR'"></span>
</div>
</td>
</tr>
</tbody>
</ng-container>
<tfoot>
<tr class="table-warning">
<th colspan="6" class="text-right">Gross Amount</th>
<th [textContent]="((serviceOrder.packageTotal || 0) + (serviceOrder.generalTotal || 0) + (serviceOrder.pharmacyIndentTotal || 0) + (serviceOrder.labServicesTotal || 0)) | currency:'INR'"></th>
</tr>
<tr class="table-active" *ngIf="form.discountType.value">
<th colspan="6" class="text-right">
<div *ngIf="mode !== editMode.New" class="row d-flex align-items-center">
<div class="col-lg-3"></div>
<div class="col-lg-3"></div>
<div class="col-lg-6 text-right">
<h5 *ngIf="!form.discountType.value">No Concession</h5>
<h5 *ngIf="form.discountType.value == discountTypeEnum.Number">Concession Amount</h5>
<h5 *ngIf="form.discountType.value == discountTypeEnum.Percentage">
Concession Amount
<span class="small">(<span [textContent]="form.discount.value + '%'"></span>)</span>
</h5>
</div>
</div>
</th>
<th [textContent]="(!form.discountType.value
? 0
: form.discountType.value == discountTypeEnum.Number
? (form.discount.value || 0)
: ((serviceOrder.packageTotal || 0) + (serviceOrder.generalTotal || 0) + (serviceOrder.pharmacyIndentTotal || 0) + (serviceOrder.labServicesTotal || 0)) * ((form.discount.value || 0)/100)) | currency:'INR'"></th>
</tr>
<tr class="table-warning">
<th colspan="6" class="text-right">Net Amount</th>
<th [textContent]="(finalAmount || 0) | currency:'INR'"></th>
</tr>
<tr class="table-active">
<th colspan="6" class="text-right">Total Amount Paid</th>
<th colspan="2" class="text-primary" [textContent]="finalBillBasics.totalAmountPaid | currency:'INR'"></th>
</tr>
<tr *ngIf="(finalBillBasics.totalAmountPaid - (finalAmount || 0)) < 0" class="table-active">
<th colspan="6" class="text-right">Total Amount Due</th>
<th colspan="2" class="text-danger" [textContent]="((finalBillBasics.totalAmountPaid - (finalAmount || 0)) * -1) | currency:'INR'"></th>
</tr>
<tr *ngIf="(finalBillBasics.totalAmountPaid - (finalAmount || 0)) > 0" class="table-active">
<th colspan="6" class="text-right">Total Refund Due</th>
<th colspan="2" class="text-success" [textContent]="(finalBillBasics.totalAmountPaid - (finalAmount || 0)) | currency:'INR'"></th>
</tr>
<tr>
<th colspan="7">
<div class="row">
<div class="col-lg-12">
<div class="table-responsive table-responsive-lg">
<table class="table table-sm table-borderless table-centered">
<tbody>
<tr>
<th>
<h5>Total Received Amount in Words </h5>
</th>
<td>
<h5 class="ml-3">: <span [textContent]="finalBillBasics.totalAmountPaidInWords"></span></h5>
</td>
</tr>
<tr *ngIf="(finalBillBasics.totalAmountPaid - (finalAmount || 0)) < 0">
<th>
<h5>Total Due Amount in Words </h5>
</th>
<td>
<h5 class="ml-3">: <span class="text-danger" [textContent]="finalBillBasics.totalDueAmountInWords"></span></h5>
</td>
</tr>
<tr *ngIf="(finalBillBasics.totalAmountPaid - (finalAmount || 0)) > 0">
<th>
<h5>Total Refund Amount Pending in Words </h5>
</th>
<td>
<h5 class="ml-3">: <span class="text-success" [textContent]="finalBillBasics.totalRefundPendingAmountInWords"></span></h5>
</td>
</tr>
<tr>
<th>
<h5>Gross Amount in Words: </h5>
</th>
<td>
<h5 class="ml-3">: <span [textContent]="finalBillBasics.totalAmountInWords"></span></h5>
</td>
</tr>
<tr>
<th>
<h5>Net Amount in Words: </h5>
</th>
<td>
<h5 class="ml-3">: <span [textContent]="finalBillBasics.netAmountInWords"></span></h5>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</th>
</tr>
<tr *ngIf="receipts.length">
<td colspan="7" class="p-0">
<div class="table-responsive table-responsive-lg">
<table class="table table-centered table-bordered table-sm mb-0">
<thead>
<tr class="table-primary">
<th colspan="5" class="text-left">
Receipts
</th>
</tr>
</thead>
<thead>
<tr>
<th>Receipt No.</th>
<th>Date & Time</th>
<th>Payment</th>
<th>Payment Mode</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of receipts; let i = index;">
<td [textContent]="'RN-' + item.receiptNo"></td>
<td>
<span *ngIf="item.modifiedByName" class="ml-1" [textContent]="item.modifiedDate | date:'dd-MM-yyyy, h:mm:ss a'"></span>
<span *ngIf="!item.modifiedByName" class="ml-1" [textContent]="item.createdDate | date:'dd-MM-yyyy, h:mm:ss a'"></span>
</td>
<td>
<div *ngIf="item.receiptTypeId == receiptType.Refund">
<div *ngIf="item.isRefunded">Refunded</div>
<div *ngIf="!item.isRefunded">Refund Pending</div>
</div>
<div *ngIf="item.receiptTypeId == receiptType.Cash">
<div *ngIf="item.isAdvance">Advance</div>
<div *ngIf="!item.isAdvance">Paid</div>
</div>
</td>
<td>
<span *ngIf="item.payTypeId !== payType.Cash" [ngbTooltip]="item.paymentDetails" placement="left" [textContent]="payType[item.payTypeId]"></span>
<span *ngIf="item.payTypeId === payType.Cash" [textContent]="payType[item.payTypeId]"></span>
</td>
<td>
<ng-container *ngIf="item.receiptTypeId == receiptType.Refund">
<span [textContent]="(item.cost * -1) | currency:'INR'"></span>
</ng-container>
<ng-container *ngIf="item.receiptTypeId == receiptType.Cash">
<span [textContent]="item.cost | currency:'INR'"></span>
</ng-container>
</td>
</tr>
</tbody>
<thead>
<tr class="table-active">
<th colspan="4" class="text-right">
Total
</th>
<th [textContent]="(finalAmount || 0) | currency:'INR'"></th>
</tr>
</thead>
</table>
</div>
</td>
</tr>
<tr>
<th colspan="7">
<div class="row">
<div class="col-lg-12">
<div class="text-left d-flex align-items-center justify-content-center">
<div class="mt-10">(Authorized Signatory)</div>
</div>
</div>
</div>
</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-template>
<ng-template #templateViewPackage>
<div class="modal-header d-block">
<div class="d-flex align-items-center justify-content-between">
<h4 class="modal-title">
<i class="mdi mdi-medical-bag mr-1"></i>View Package
</h4>
<div>
<button type="button" [useExistingCss]="true" printSectionId="packages-section" ngxPrint class="btn btn-light btn-xs mr-1 d-print-none"><i class="fe-printer mr-1"></i>Print</button>
<button type="button" class="btn btn-light btn-xs" (click)="onCloseViewPackageModal();"><i class="fe-x mr-1"></i> Close</button>
</div>
</div>
</div>
<div class="modal-body p-0" id="packages-section" style="min-height: 400px">
<view-package-module [packageModuleId]="selectedPackage.packageModuleId" [chargeCategory]="chargeCategory"></view-package-module>
</div>
</ng-template>
\ No newline at end of file
import { Component, OnDestroy, OnInit, TemplateRef, Input } from "@angular/core";
import { ActivatedRoute, Params } from "@angular/router";
import { takeUntil, finalize } from "rxjs/operators";
import { IUserAccount, Page, GenericResponse, GenericStatus, IResource } from "@shared/models";
import { AppData, HttpService, NotifyService, FinalBillService, PrintOptionService } from "@shared/services";
import { ApiResources, MoneyHelper } from "../../../../../shared/helpers";
import { IChargeModel } from "../../models/charge.model";
import { IPharmacyIndentModel } from "../../models/pharmacy-indent.model";
import { DiscountType } from "../../models/discount-type.model";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { FinalBillBasicModel } from "../../models/final-bill-basic.model";
import { IAdmissionModel } from "../../models/admission.model";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { RepeatType } from "../../models/repeat-type.model";
import { IAdmissionPackageModuleModel } from "../../models/admission-package.model";
import { IReceiptModel } from "../../models/receipt.model";
import { PayType } from "../../models/pay-type.model";
import { ReceiptType } from "../../models/receipt-type.model";
import { AutomaticType } from "../../models/automatic-type.model";
import { ChargeType } from "../../../../../shared/enums";
import { Appointment, InsuranceAdmission } from "../../../../../shared/entities";
import { ILabServicesModel } from "../../models/lab-services.model";
import { Location } from "@angular/common";
import { AdmissionFetchHelper } from "../../../progress-report/shared/helper";
import { NewLabServicesModel } from "../../models/new-lab-services.model";
import { PackageModuleModel } from "../../../masters/pages/package-modules/models";
class ServiceOrder {
generalRecords: Array<IChargeModel>;
generalTotal: number;
pharmacyIndentRecords: Array<IPharmacyIndentModel>;
pharmacyIndentTotal: number;
packageRecords: Array<IAdmissionPackageModuleModel>;
packageTotal: number;
labServicesRecords: Array<NewLabServicesModel>;
labServicesTotal: number;
insuranceForAdmissionId: number;
}
class FinalBill {
generalRecords: Array<IChargeModel>;
pharmacyRecords: Array<IChargeModel>;
packageRecords: Array<IAdmissionPackageModuleModel>;
labServicesRecords: Array<ILabServicesModel>;
basics: FinalBillBasicModel;
}
enum EditMode {
New = 1,
Final = 2
}
@Component({
templateUrl: "./final-bill.html",
styleUrls: ['../../services.css']
})
export class FinalBillPage implements OnInit, OnDestroy {
page: Page;
editMode = EditMode;
discountTypeEnum = DiscountType;
repeatType = RepeatType;
automaticType = AutomaticType;
chargeType = ChargeType;
receiptType = ReceiptType;
payType = PayType;
loading: boolean;
isChargesLoading: boolean;
serviceOrder: ServiceOrder;
chargeRecords: Array<IChargeModel>;
now: Date;
submitting: boolean;
submitted: boolean;
admissionId: string;
isAdmission: boolean;
disableActionBtns: boolean = false;
finalBillBasics: FinalBillBasicModel;
appointment: Appointment;
receipts: Array<IReceiptModel>;
selectedPackage: PackageModuleModel;
chargeCategory: IResource;
departments: Array<string>;
chargeGroups: Array<string>;
charges: Array<string>;
deletedCharges: Array<number>;
deletedPharmacy: Array<number>;
deletedLabServices: Array<number>;
finalBillForm: FormGroup;
mode: EditMode;
modalRef: NgbModalRef;
admission: IAdmissionModel;
noOfDays: number;
billNumber: string;
@Input() isPrintLogo: boolean;
insuranceAdmission: Array<InsuranceAdmission>;
insuranceAmount: number;
constructor(
private readonly httpService: HttpService,
private readonly finalBillService: FinalBillService,
private readonly route: ActivatedRoute,
private readonly appData: AppData,
private readonly notifyService: NotifyService,
private readonly formBuilder: FormBuilder,
private readonly modalService: NgbModal,
private readonly location: Location,
private readonly printOptionService: PrintOptionService,
private readonly admissionFetchHelper: AdmissionFetchHelper,
) {
this.receipts = new Array<IReceiptModel>();
this.finalBillBasics = new FinalBillBasicModel();
this.deletedCharges = new Array<number>();
this.deletedPharmacy = new Array<number>();
this.deletedLabServices = new Array<number>();
this.mode = EditMode.New;
this.serviceOrder = new ServiceOrder();
this.serviceOrder.generalRecords = new Array<IChargeModel>();
this.serviceOrder.pharmacyIndentRecords = new Array<IPharmacyIndentModel>();
this.serviceOrder.packageRecords = new Array<IAdmissionPackageModuleModel>();
this.serviceOrder.labServicesRecords = new Array<NewLabServicesModel>();
this.isChargesLoading = true;
this.loading = true;
this.insuranceAdmission = new Array<InsuranceAdmission>();
this.page = new Page();
this.buildForm();
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.route.parent.paramMap
.subscribe((params: Params) => {
this.admissionId = params["params"]["id"];
this.isAdmission = params["params"]["type"] === "a";
if (!this.isAdmission)
this.getAppointment(this.admissionId);
this.getFinalBillBasics(() => {
if (this.finalBillBasics.finalAmount !== 0) {
this.admissionFetch();
this.fetchFinal();
} else {
this.automatic(() => {
this.admissionFetch();
this.fetchFinal();
});
}
});
});
} else {
this.page.userAccount = undefined;
}
this.printOptionService.get((is) => { this.isPrintLogo = is; });
});
}
fetchReceipts = () => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.receipt.base, ApiResources.receipt.fetch), { id: this.admissionId, isAdmission: this.isAdmission, activeOnly: true })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: GenericResponse) => {
const records = response.data as Array<IReceiptModel>;
if (records.length > 0) {
records.forEach((item) => {
item.receiptNo = String(item.receiptId).padStart(6, '0');
});
}
this.receipts = records;
},
() => {
this.receipts = new Array<IReceiptModel>();
}
);
}
buildForm = () => {
this.finalBillForm = this.formBuilder.group({
discountType: [null],
discount: [null]
});
this.finalBillForm.get("discountType").valueChanges.subscribe((value: DiscountType) => {
this.finalBillForm.patchValue({ discount: null });
if (!+value) return;
const discount = this.finalBillForm.get('discount');
discount.clearValidators();
if (+value === DiscountType.Number) {
discount.setValidators([
Validators.min(0),
Validators.max(((this.serviceOrder.packageTotal || 0) + (this.serviceOrder.generalTotal || 0) + (this.serviceOrder.labServicesTotal || 0) + (this.serviceOrder.pharmacyIndentTotal || 0)))
]);
} else {
discount.setValidators([
Validators.min(0),
Validators.max(100)
]);
}
discount.updateValueAndValidity();
});
}
get form() {
return this.finalBillForm.controls;
}
get receiptsTotal() {
if (!this.receipts.length) return 0;
return this.receipts.filter(x => x.receiptTypeId !== ReceiptType.Refund).map(x => x.cost).reduce((a, b) => a + b, 0);
}
get finalAmount() {
var amount = !+this.finalBillForm.value.discountType
? +(((this.serviceOrder.packageTotal || 0) + (this.serviceOrder.generalTotal || 0) + (this.serviceOrder.labServicesTotal || 0) + (this.serviceOrder.pharmacyIndentTotal || 0))).toFixed(2)
: +(((this.serviceOrder.packageTotal || 0) + (this.serviceOrder.generalTotal || 0) + (this.serviceOrder.labServicesTotal || 0) + (this.serviceOrder.pharmacyIndentTotal || 0)) -
(
(+this.finalBillForm.value.discountType) === DiscountType.Number
? (this.finalBillForm.value.discount || 0)
: (((this.serviceOrder.packageTotal || 0) + (this.serviceOrder.generalTotal || 0) + (this.serviceOrder.labServicesTotal || 0) + (this.serviceOrder.pharmacyIndentTotal || 0)) * ((this.finalBillForm.value.discount || 0) / 100))
)).toFixed(2);
if (this.insuranceAmount > 0) {
amount = amount > this.insuranceAmount ? amount - this.insuranceAmount : 0;
}
return amount;
}
admissionFetch = () => {
this.admissionFetchHelper.admissionFetch(+this.admissionId, this.isAdmission, (data: IAdmissionModel) => {
this.loading = false
this.admission = data;
});
}
onOpenModel(content: TemplateRef<any>) {
this.now = new Date();
this.moneyHelper();
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
size: "lg",
windowClass: "custom-modal slots-modal effect-scale"
});
return;
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.submitting = undefined;
this.submitted = undefined;
}
automatic = (callback?: Function) => {
var data = {
id: this.admissionId,
isAdmission: this.isAdmission,
createdBy: this.page.userAccount.accountId
};
this.httpService
.post(ApiResources.getURI(ApiResources.serviceOrder.base, ApiResources.serviceOrder.automatic), data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(() => {
callback();
}, () => {
callback();
});
}
onBack = () => {
this.location.back();
}
getFinalBillBasics = (callback?: Function) => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.finalBill.base, ApiResources.finalBill.getBasics), { id: this.admissionId, isAdmission: this.isAdmission })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.isChargesLoading = false))
.subscribe(
(response: GenericResponse) => {
this.finalBillBasics = response.data as FinalBillBasicModel;
this.moneyHelper();
callback();
},
() => {
this.finalBillBasics = new FinalBillBasicModel();
callback();
}
);
}
getAppointment = (admissionId: string) => {
const request = { appointmentId: parseInt(admissionId) };
this.httpService.post(ApiResources.getURI(ApiResources.appointments.base, ApiResources.appointments.find), request)
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Appointment) => {
this.appointment = response;
this.disableActionBtns = this.appointment && this.appointment.status === "C";
});
}
moneyHelper = () => {
this.finalBillBasics.totalAmountPaidInWords = MoneyHelper.numberCurrencyIn(this.finalBillBasics.totalAmountPaid);
this.finalBillBasics.totalDueAmountInWords = MoneyHelper.numberCurrencyIn(((this.finalBillBasics.totalAmountPaid - (this.finalAmount || 0)) * -1));
this.finalBillBasics.totalRefundPendingAmountInWords = MoneyHelper.numberCurrencyIn(((this.finalBillBasics.totalAmountPaid - (this.finalAmount || 0))));
this.finalBillBasics.netAmountInWords = MoneyHelper.numberCurrencyIn((this.finalAmount || 0));
this.finalBillBasics.totalAmountInWords = MoneyHelper.numberCurrencyIn(this.finalBillBasics.totalAmount);
}
fetchFinal = () => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.finalBill.base, ApiResources.finalBill.fetch),
{
id: this.admissionId, isAdmission: this.isAdmission, modifiedBy: this.page.userAccount.accountId, roleId: this.page.userAccount.roleId, fullName: this.page.userAccount.fullName
})
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
const record = response.data as FinalBill;
this.chargeCategory = { id: record["roomChargeCategoryId"] || record["chargeCategoryId"], value: record["chargeCategoryName"] } as IResource;
if (record.basics && record.basics.finalBillId) {
this.billNumber = 'FN' + String(record.basics.finalBillId).padStart(6, '0');
}
// General Records
const generalRecords = record.generalRecords as Array<IChargeModel>;
if (generalRecords.length > 0) {
const generalSubRecords = new Array<IChargeModel>();
generalRecords.forEach(item => {
generalSubRecords.push({
serviceOrderId: item.serviceOrderId,
chargeId: item.chargeId,
cost: item.cost,
discount: item.discount,
chargeName: item.chargeName,
chargeGroupName: item.chargeGroupName,
departmentName: item.departmentName,
unit: item.unit,
totalCost: item.cost * item.unit,
status: true,
repeatTypeId: item.repeatTypeId,
chargeTypeMainId: item.chargeTypeMainId,
chargeTypeMainName: item.chargeTypeMainName,
chargeTypeId: item.chargeTypeId,
showAmount: true,
usedQuantity: item.usedQuantity
} as IChargeModel);
});
this.serviceOrder.generalRecords = generalSubRecords;
this.serviceOrder.generalTotal = generalSubRecords.map(x => (x.cost * x.unit) - (x.discount || 0)).reduce((a, b) => a + b, 0);
} else {
this.serviceOrder.generalRecords = new Array<IChargeModel>();;
this.serviceOrder.generalTotal = 0;
}
// Lab Services Records
const labServices = record.labServicesRecords as unknown as Array<NewLabServicesModel>;
if (labServices.length > 0) {
const labServicesSubRecords = new Array<NewLabServicesModel>();
labServices.forEach(item => {
labServicesSubRecords.push({
labServicesId: item.labServicesId,
labMainDetailId: item.labMainDetailId,
cost: item.cost,
discount: item.discount,
testName: item.testName,
testCode: item.testCode,
unit: item.unit,
totalCost: item.cost * item.unit,
status: true,
repeatTypeId: item.repeatTypeId,
automaticTypeId: item.automaticTypeId,
active: item.active,
createdDate: item.createdDate,
modifiedDate: item.modifiedDate,
createdByName: item.createdByName,
modifiedByName: item.modifiedByName,
isMain: item.isMain,
showAmount: true,
usedQuantity: item.usedQuantity
} as unknown as NewLabServicesModel);
});
this.serviceOrder.labServicesRecords = labServicesSubRecords;
this.serviceOrder.labServicesTotal = labServicesSubRecords.filter(x => x.active).map(x => (x.cost * x.unit) - (x.discount || 0)).reduce((a, b) => a + b, 0);
} else {
this.serviceOrder.labServicesRecords = new Array<NewLabServicesModel>();
this.serviceOrder.labServicesTotal = 0;
}
// Pharmacy Records
const pharmacyRecords = record.pharmacyRecords as Array<IChargeModel>;
if (pharmacyRecords.length > 0) {
const pharmacySubRecords = new Array<IPharmacyIndentModel>();
pharmacyRecords.forEach(item => {
pharmacySubRecords.push({
pharmacyIssueDetailId: item.productId,
productId: item.productId,
cost: item.cost,
unit: item.unit,
categoryName: item.chargeGroupName,
departmentName: item.departmentName,
productName: item.chargeName,
totalCost: item.cost * item.unit,
discountAmount: (item.cost * item.unit) * item.discountPercentage / 100,
discountPercentage: item.discountPercentage,
status: true,
showAmount: true,
} as IPharmacyIndentModel);
});
this.serviceOrder.pharmacyIndentRecords = pharmacySubRecords;
this.serviceOrder.pharmacyIndentTotal = pharmacySubRecords.map(x => (x.cost * x.unit) - x.discountAmount)
.reduce((a, b) => a + b, 0);
} else {
this.serviceOrder.pharmacyIndentRecords = new Array<IPharmacyIndentModel>();;
this.serviceOrder.pharmacyIndentTotal = 0;
}
// Package Records
const packageRecords = record.packageRecords as Array<IAdmissionPackageModuleModel>;
if (packageRecords.length) {
this.serviceOrder.packageRecords = packageRecords;
this.serviceOrder.packageTotal = packageRecords.filter(x => x.active).map(x => (x.total)).reduce((a, b) => a + b, 0);
} else {
this.serviceOrder.packageRecords = new Array<IAdmissionPackageModuleModel>();
this.serviceOrder.packageTotal = 0;
}
this.finalBillForm.patchValue({
discountType: record.basics.discountTypeId,
discount: record.basics.discountDetails
});
this.mode = EditMode.Final;
this.fetchReceipts();
} else {
this.mode = EditMode.New;
this.fetchServiceOrder();
}
this.getInsurance();
},
() => {
this.serviceOrder.generalRecords = new Array<IChargeModel>();;
this.serviceOrder.generalTotal = 0;
this.serviceOrder.pharmacyIndentRecords = new Array<IPharmacyIndentModel>();;
this.serviceOrder.pharmacyIndentTotal = 0;
this.serviceOrder.packageRecords = new Array<IAdmissionPackageModuleModel>();
this.serviceOrder.packageTotal = 0;
this.serviceOrder.labServicesRecords = new Array<NewLabServicesModel>();
this.serviceOrder.labServicesTotal = 0;
}
);
}
calculateTotals = () => {
this.serviceOrder.generalTotal = this.serviceOrder.generalRecords.filter(x => x.showAmount).map(x => x.cost * x.unit).reduce((a, b) => a + b, 0);
this.serviceOrder.labServicesTotal = this.serviceOrder.labServicesRecords.filter(x => x.active && x.showAmount).map(x => x.cost * x.unit).reduce((a, b) => a + b, 0);
this.serviceOrder.pharmacyIndentTotal = this.serviceOrder.pharmacyIndentRecords.filter(x => x.showAmount).map(x => (x.cost * x.unit) - x.discountAmount).reduce((a, b) => a + b, 0);
}
fetchServiceOrder = () => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.serviceOrder.base, ApiResources.serviceOrder.fetch), { id: this.admissionId, isAdmission: this.isAdmission, activeOnly: true })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: GenericResponse) => {
this.chargeCategory = { id: response.data["roomChargeCategoryId"] || response.data["chargeCategoryId"], value: response.data["chargeCategoryName"] } as IResource;
// General Records
const generalRecords = response.data["generalRecords"] as Array<any>;
if (generalRecords.length > 0) {
const generalSubRecords = new Array<IChargeModel>();
generalRecords.forEach(item => {
generalSubRecords.push({
serviceOrderId: item.serviceOrderId,
chargeId: item.chargeId,
cost: item.cost,
chargeName: item.chargeName,
chargeGroupName: item.chargeGroupName,
departmentName: item.departmentName,
unit: item.unit,
totalCost: item.cost * item.unit,
discount: item.discount,
status: true,
repeatTypeId: item.repeatTypeId,
automaticTypeId: item.automaticTypeId,
chargeTypeMainId: item.chargeTypeMainId,
chargeTypeMainName: item.chargeTypeMainName,
chargeTypeId: item.chargeTypeId,
usedQuantity: item.usedQuantity,
showAmount: true
} as IChargeModel);
});
this.serviceOrder.generalRecords = generalSubRecords;
this.serviceOrder.generalTotal = generalSubRecords.map(x => (x.cost * x.unit) - (x.discount || 0)).reduce((a, b) => a + b, 0);
} else {
this.serviceOrder.generalRecords = new Array<IChargeModel>();
this.serviceOrder.generalTotal = 0;
}
// Lab Services Records
const labServices = response.data["labServices"] as Array<any>;
if (labServices.length > 0) {
const labServicesSubRecords = new Array<NewLabServicesModel>();
labServices.forEach(item => {
labServicesSubRecords.push({
labServicesId: item.labServicesId,
labMainDetailId: item.labMainDetailId,
cost: item.cost,
testName: item.testName,
testCode: item.testCode,
unit: item.unit,
totalCost: item.cost * item.unit,
discount: item.discount,
status: true,
repeatTypeId: item.repeatTypeId,
automaticTypeId: item.automaticTypeId,
active: item.active,
createdDate: item.createdDate,
modifiedDate: item.modifiedDate,
createdByName: item.createdByName,
modifiedByName: item.modifiedByName,
isMain: item.isMain,
usedQuantity: item.usedQuantity,
showAmount: true
} as unknown as NewLabServicesModel);
});
this.serviceOrder.labServicesRecords = labServicesSubRecords;
this.serviceOrder.labServicesTotal = labServicesSubRecords.filter(x => x.active).map(x => (x.cost * x.unit) - (x.discount || 0)).reduce((a, b) => a + b, 0);
} else {
this.serviceOrder.labServicesRecords = new Array<NewLabServicesModel>();
this.serviceOrder.labServicesTotal = 0;
}
// Pharmacy Indent Records
const pharmacyIndentRecords = response.data["pharmacyIndentRecords"] as Array<any>;
if (pharmacyIndentRecords.length > 0) {
const pharmacySubRecords = new Array<IPharmacyIndentModel>();
pharmacyIndentRecords.forEach(item => {
pharmacySubRecords.push({
pharmacyIssueDetailId: item.pharmacyIssueDetailId,
productId: item.productId,
cost: item.cost,
unit: item.unit,
categoryName: item.categoryName,
departmentName: item.departmentName,
productName: item.productName,
totalCost: item.cost * item.unit,
discountAmount: (item.cost * item.unit) * item.discountPercentage / 100,
discountPercentage: item.discountPercentage,
status: true,
showAmount: true
} as IPharmacyIndentModel);
});
this.serviceOrder.pharmacyIndentRecords = pharmacySubRecords;
this.serviceOrder.pharmacyIndentTotal = pharmacySubRecords.map(x => (x.cost * x.unit) - x.discountAmount)
.reduce((a, b) => a + b, 0);
} else {
this.serviceOrder.pharmacyIndentRecords = new Array<IPharmacyIndentModel>();
this.serviceOrder.pharmacyIndentTotal = 0;
}
// Package Records
const packageRecords = response.data["packageRecords"] as Array<IAdmissionPackageModuleModel>;
if (packageRecords.length) {
this.serviceOrder.packageRecords = packageRecords;
this.serviceOrder.packageTotal = packageRecords.filter(x => x.active).map(x => (x.total)).reduce((a, b) => a + b, 0);
} else {
this.serviceOrder.packageRecords = new Array<IAdmissionPackageModuleModel>();
this.serviceOrder.packageTotal = 0;
}
this.mode = EditMode.New;
},
() => {
this.serviceOrder.generalRecords = new Array<IChargeModel>();;
this.serviceOrder.generalTotal = 0;
this.serviceOrder.pharmacyIndentRecords = new Array<IPharmacyIndentModel>();;
this.serviceOrder.pharmacyIndentTotal = 0;
this.serviceOrder.packageRecords = new Array<IAdmissionPackageModuleModel>();
this.serviceOrder.packageTotal = 0;
this.serviceOrder.labServicesRecords = new Array<NewLabServicesModel>();
this.serviceOrder.labServicesTotal = 0;
}
);
}
trackByPackage(_: number, item: PackageModuleModel): number {
return item.packageModuleId;
}
insertHelper = () => {
if (!this.finalBillForm.valid) return;
this.submitting = true;
var data = {
id: this.admissionId,
isAdmission: this.isAdmission,
createdBy: this.page.userAccount.accountId,
totalAmount: this.serviceOrder.packageTotal + this.serviceOrder.generalTotal + this.serviceOrder.labServicesTotal + this.serviceOrder.pharmacyIndentTotal,
discountTypeId: this.finalBillForm.value.discountType,
discountDetails: this.finalBillForm.value.discount,
finalAmount: this.finalAmount,
labServices: [],
generalRecords: [],
pharmacyRecords: [],
packageRecords: [],
roleId: this.page.userAccount.roleId,
roleName: this.page.userAccount.roleName,
fullName: this.page.userAccount.fullName
}
this.serviceOrder.generalRecords.forEach(item => {
data.generalRecords.push(
{
chargeId: item.chargeId,
unit: item.unit,
cost: item.cost,
discount: +(item.discount || 0),
chargeTypeMainId: item.chargeTypeId ? item.chargeTypeMainId : null,
chargeTypeId: item.chargeTypeId,
});
});
this.serviceOrder.labServicesRecords.forEach(item => {
data.labServices.push(
{
labMainDetailId: item.labMainDetailId,
unit: item.unit,
cost: item.cost,
notes: null
});
});
this.serviceOrder.packageRecords.forEach(item => {
data.packageRecords.push(
{
packageId: item.packageModuleId,
total: item.total
});
});
this.serviceOrder.pharmacyIndentRecords.forEach(item => {
data.pharmacyRecords.push(
{
productId: item.productId,
unit: item.unit,
cost: item.cost,
discountPercentage: item.discountPercentage,
});
});
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.finalBill.base, ApiResources.finalBill.insert), data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitting = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.notifyService.success("Final Bill has been Saved successfully");
this.mode = EditMode.Final;
this.getFinalBillBasics(() => {
this.fetchFinal();
this.finalBillService.set(true);
});
} else {
if (response.message) {
this.notifyService.info(response.message);
} else {
this.notifyService.defaultError();
}
}
},
() => {
this.chargeRecords = new Array<IChargeModel>();
}
);
}
cancelHelper = () => {
if (this.finalBillBasics.isDischarged) {
this.notifyService.info("Final Bill can not be cancelled once the patient is discharged");
return;
}
this.submitting = true;
var data = {
id: this.admissionId,
isAdmission: this.isAdmission,
createdBy: this.page.userAccount.accountId,
roleId: this.page.userAccount.roleId,
roleName: this.page.userAccount.roleName,
fullName: this.page.userAccount.fullName
}
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.finalBill.base, ApiResources.finalBill.cancel),
data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitting = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.notifyService.success("Final Bill has been cancelled");
this.deletedCharges = new Array<number>();
this.deletedLabServices = new Array<number>();
this.deletedPharmacy = new Array<number>();
this.mode = EditMode.New;
this.getFinalBillBasics(() => {
this.fetchServiceOrder();
this.finalBillService.set(true);
});
} else {
if (response.message) {
this.notifyService.info(response.message);
} else {
this.notifyService.defaultError();
}
}
},
() => {
this.chargeRecords = new Array<IChargeModel>();
}
);
}
resetHelper = () => {
this.deletedCharges = new Array<number>();
this.deletedPharmacy = new Array<number>();
if (this.mode === EditMode.Final) {
this.fetchFinal();
} else {
this.fetchServiceOrder();
}
}
onSubmit = () => {
if (this.mode === EditMode.New) {
this.insertHelper();
} else {
this.cancelHelper();
}
}
getInsurance() {
var admissionId = null;
var appointmentId = null;
if (this.isAdmission) {
admissionId = this.admissionId;
} else {
appointmentId = this.appointment.appointmentId
}
this.httpService.post(ApiResources.getURI(ApiResources.insuranceAdmission.base, ApiResources.insuranceAdmission.getInsuranceApprovals), { admissionId: Number(admissionId), appointmentId: appointmentId })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => { this.loading = false }))
.subscribe((response: Array<InsuranceAdmission>) => {
if (response != undefined && response !== null) {
this.insuranceAdmission = response;
if (this.insuranceAdmission) {
var amount = 0;
this.insuranceAdmission.forEach((m) => {
amount += m.expectedAmount
});
this.insuranceAmount = amount;
}
}
});
}
onViewPackage(content: TemplateRef<any>, model: PackageModuleModel): void {
this.selectedPackage = model;
this.modalRef = this.modalService.open(content, { size: "lg", windowClass: "custom-modal" });
}
onCloseViewPackageModal(): void {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
}
this.selectedPackage = undefined;
}
ngOnDestroy() {
this.page.unSubscribe.next();
this.page.unSubscribe.complete();
}
}
\ No newline at end of file

<style>
.item {
/* background-color: aqua; */
border-bottom: 1px solid;
border-right: 1px solid;
overflow: hidden;
line-height: 30px;
min-height: 30px;
}
.item > input {
outline: none;
height: 100%;
border: none;
}
.boxContainer {
width: 100%;
display: grid;
margin: auto;
border-top: 1px solid;
border-left: 1px solid;
overflow: auto;
}
</style>
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<!--editMode.Discharged-->
<div class="page-title-right">
<button *ngIf="record.gatePassId" class="btn btn-primary btn-sm ml-1" (click)="onEdit()"><i class="fe-edit-2 mr-2"></i> Edit</button>
<button *ngIf="finalBillBasics.isFinalBillGenerated && finalBillBasics.pendingAmount == 0 && record.gatePassId" type="button" class="btn btn-primary btn-sm ml-2" (click)="onOpenModel(view)">
<span><i class="fe-eye mr-1"></i>Gate Pass Report</span>
</button>
<button class="btn btn-secondary btn-sm ml-1" (click)="onBack()"><i class="fe-arrow-left ml-1"></i> Back</button>
</div>
</div>
<h4 class="page-title">Final Gate Pass</h4>
</div>
</div>
<div class="col-lg-12" *ngIf="!finalBillBasics.isFinalBillGenerated">
<div class="d-flex align-items-center justify-content-center">
<div class="alert alert-info"><i class="mdi mdi-lightbulb"></i> Tip: Generate Final Bill to get <span class="font-weight-bold">Gate Pass</span></div>
</div>
</div>
<div class="col-lg-12" *ngIf="finalBillBasics.isFinalBillGenerated && !finalBillBasics.isDischarged">
<div class="d-flex align-items-center justify-content-center">
<div class="alert alert-info"><i class="mdi mdi-lightbulb"></i> Tip: Discharge the Patient to get The <span class="font-weight-bold">Gate Pass</span></div>
</div>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading Gate-pass</span>
</div>
</div>
</div>
</div>
<!--&& finalBillBasics.isFinalBillGenerated && finalBillBasics.pendingAmount === 0"-->
<div class="row" *ngIf="!loading">
<div class="col-lg-12 px-2" *ngIf="mode === editMode.New">
<form [formGroup]="gatePassForm" (submit)="onSubmit()">
<div class="card">
<div class="card-body p-0">
<div class="card-box m-0">
<ng-container >
<h4 class="box-title"><i class="mdi mdi-human mr-1"></i>Gate Pass Information</h4>
<div class="row">
<div class="col-lg-5">
<div class="form-group">
<label>Valid Upto <code>*</code></label>
<input type="datetime-local" class="form-control" [min]="today | date: 'yyyy-MM-ddTHH:mm'" [ngClass]="{ 'is-invalid': (submitted && form.validUpto.errors) }" formControlName="validUpto" />
<div *ngIf="submitted && form.validUpto.errors" class="invalid-feedback show-must">
<div *ngIf="form.validUpto.errors.required">Valid Date is required</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="form-group">
<label>Remark</label>
<input type="text" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.remark.errors) }" formControlName="remark" placeholder="Enter the remark" />
</div>
</div>
</div>
</ng-container>
</div>
</div>
<div class="card-footer bg-light">
<div class="text-right">
<button *ngIf="!record.gatePassId" type="reset" class="btn btn-warning btn-sm mr-2">
<i class="fe-refresh-cw"></i>
<span class="ml-1">Reset</span>
</button>
<button *ngIf="record.gatePassId" type="button" (click)="onCancel()" class="btn btn-danger btn-sm mr-2">
<i class="fe-x"></i>
<span class="ml-1">Cancel</span>
</button>
<button type="submit" [disabled]="!(finalBillBasics.isFinalBillGenerated && finalBillBasics.isDischarged)" class="btn btn-sm btn-success">
<!--<span>
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>-->
<span>
<i class="fe-check"></i>
<span class="ml-1">
<span *ngIf="record.gatePassId">Update</span>
<span *ngIf="!record.gatePassId">Create</span>
</span>
</span>
</button>
</div>
</div>
</div>
</form>
</div>
<div class="col-lg-12 px-2" *ngIf="mode === editMode.Discharged">
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<div class="card mt-2">
<div class="card-body p-0">
<div class="table-responsive" *ngIf="record">
<table class="table table-centered table-bordered table-sm mb-0">
<tbody>
<ng-container>
<tr class="table-primary">
<th colspan="4">
Patient Information
</th>
</tr>
<tr>
<th class="table-active">
Patient Name
</th>
<td>
<span>
<span [textContent]="admission.fullName + ', '"></span>
<span [textContent]="(admission.gender === 'F' ? 'Female' : 'Male') + ', '"></span>
<span [textContent]="admission.age + 'yrs'"></span>
</span>
</td>
<th class="table-active">
Relation
</th>
<td [textContent]="admission.fatherOrHusband"></td>
</tr>
<tr>
<th class="table-active">
Address
</th>
<td [textContent]="admission.fullAddress"> </td>
<th class="table-active">
Bed Number
</th>
<td [textContent]="admission.bedNumber"></td>
</tr>
</ng-container>
<ng-container>
<tr class="table-primary">
<th colspan="4">
Gate-Pass Information
</th>
</tr>
<tr>
<th class="table-active">
Valid Date & Time
</th>
<td [textContent]="record.validUpto | date:'dd-MM-yyyy, h:mm:ss a'">
</td>
<th class="table-active">
Remark
</th>
<td [textContent]="record.remark"></td>
</tr>
<tr>
<th class="table-active">
Issued Date
</th>
<td [textContent]="record.createdDate | date:'dd-MM-yyyy, h:mm:ss a'">
</td>
<th class="table-active">
Issued By
</th>
<td [textContent]="record.createdByName"></td>
</tr>
</ng-container>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #view>
<div class="modal-header">
<h4 class="modal-title text-center">Gate -pass</h4>
<div>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();"><i class="fe-x"></i></button>
<button [useExistingCss]="true"
printSectionId="print-section"
ngxPrint
class="btn btn-light btn-xs mr-1 d-print-none">
<i class="fe-printer mr-1"></i>Print
</button>
</div>
</div>
<div class="modal-body" id="print-section">
<div class="card">
<div class="card-body p-0">
<div class="card-box m-0">
<div class="row">
<div class="col-lg-12 text-center" >
<h4>Gate Pass</h4>
</div>
</div>
<div class="row">
<div class="col-lg-12 font-18">
<div class="table-responsive">
<table class="table table-sm table-borderless table-centered">
<tbody>
<tr>
<th>Admission No</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.admissionNo"></span>
</td>
<th>Date</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="(maxDischargeDate | date: 'dd-MM-yyyy') "></span>
</td>
<th>Time</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="(maxDischargeDate | date: 'h:mm:ss a')"></span>
</td>
</tr>
<tr>
<th>Patient Name</th>
<td colspan="4">
<span class="mr-1">:</span>
<span>
<span [textContent]="admission.fullName + ', '"></span>
<span [textContent]="(admission.gender === 'F' ? 'Female' : 'Male') + ', '"></span>
<span [textContent]="admission.age + 'yrs'"></span>
</span>
</td>
</tr>
<tr>
<th>Father/Husband Name</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.fatherOrHusband"></span>
</td>
</tr>
<tr>
<th>Address</th>
<td colspan="5">
<span class="mr-1">:</span>
<span [textContent]="admission.fullAddress"></span>
<!--<span [textContent]="record.area || ' ' "></span>
<span *ngIf="record.city" [textContent]="', ' + record.city "></span>
<span *ngIf="record.zipcode" [textContent]="', ' + record.zipcode "></span>-->
</td>
</tr>
<tr>
<th>Case Type</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="record.caseTypeName"></span>
</td>
<th>Bed No.</th>
<td colspan="3">
<span class="mr-1">:</span>
<span [textContent]="!admission.bedNumber ? 'N/A' : (admission.wardName + ' / ' + admission.roomName + ' / ' + admission.bedNumber)"></span>
</td>
</tr>
<tr>
<th>Valid Upto</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="(record.validUpto | date: 'dd-MM-yyyy')"></span>
</td>
<th>Time</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="(record.validUpto | date: 'h:mm:ss a')"></span>
</td>
</tr>
<tr>
</tr>
</tbody>
</table>
</div>
<div class="boxContainer" style="border-bottom: 1px solid; margin: 2px 0;">
<div class="item" style="text-align: center; grid-column: 1/2; min-width: 100px;"></div>
<div class="item" style="text-align: center; grid-column: 2/3; min-width: 100px;">Checked By</div>
<div class="item" style="text-align: center; grid-column: 3/4; min-width: 100px;">Authorized By</div>
<div class="item" style="text-align: left; grid-row: 2; min-width: 100px;">Room Linen</div>
<div class="item" style="text-align: left; grid-row: 2; min-width: 100px;"></div>
<div class="item" style="text-align: left; grid-row: 2; min-width: 100px;"></div>
<div class="item" style="text-align: left; grid-row: 3; min-width: 100px;">Room Inventory</div>
<div class="item" style="text-align: left; grid-row: 3; min-width: 100px;"></div>
<div class="item" style="text-align: left; grid-row: 3; min-width: 100px;"></div>
<div class="item" style="text-align: left; grid-row: 4; min-width: 100px;">Ready For Discharge</div>
<div class="item" style="text-align: left; grid-row: 4; min-width: 100px;"></div>
<div class="item" style="text-align: left; grid-row: 4; min-width: 100px;"></div>
<div class="item" style="text-align: left; grid-row: 5; min-width: 100px;">Gate-Pass</div>
<div class="item" style="text-align: left; grid-row: 5; min-width: 100px;"></div>
<div class="item" style="text-align: left; grid-row: 5; min-width: 100px;"></div>
<div class="item" style="text-align: left; grid-row: 6; min-width: 100px;">Payment Mode</div>
<div class="item" style="text-align: left; grid-row: 6; min-width: 100px;"></div>
<div class="item" style="text-align: left; grid-row: 6; min-width: 100px;"></div>
</div>
<div>
<span>Issued</span>&nbsp;
<span><b>{{page.userAccount.fullName}}</b></span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-template>
import { Component, OnDestroy, OnInit, TemplateRef} from "@angular/core";
import { ActivatedRoute, Params } from "@angular/router";
import { takeUntil, finalize } from "rxjs/operators";
import { Location } from '@angular/common';
import { IUserAccount, Page, GenericResponse, GenericStatus } from "@shared/models";
import { AppData, HttpService, NotifyService, FinalBillService } from "@shared/services";
import { ApiResources } from "@shared/helpers";
import { IReceiptTypeModel} from "../../models/receipt-type.model";
import { FormGroup, FormBuilder, Validators } from "@angular/forms";
import { FinalBillBasicModel } from "../../models/final-bill-basic.model";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { IAdmissionModel } from "../../models/admission.model";
import { GatepassModel } from "../../models/gatepass.model";
enum EditMode {
New = 1,
Discharged = 2
}
@Component({
templateUrl: "./gate-pass.html",
styleUrls: ['../../services.css']
})
export class GatePassPage implements OnInit, OnDestroy {
editMode = EditMode;
page: Page;
loading: boolean;
record: GatepassModel;
admission: IAdmissionModel;
submitting: boolean;
submitted: boolean;
admissionId: string;
isAdmission: boolean;
receiptTypes: Array<IReceiptTypeModel>;
gatePassForm: FormGroup;
finalBillBasics: FinalBillBasicModel;
mode: EditMode;
today = new Date();
modalRef: NgbModalRef;
maxDischargeDate: string;
constructor(
private readonly httpService: HttpService,
private readonly route: ActivatedRoute,
private readonly finalBillService: FinalBillService,
private readonly appData: AppData,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly modalService: NgbModal,
private readonly location: Location
) {
this.mode = EditMode.New;
this.record = {} as GatepassModel;
this.finalBillBasics = new FinalBillBasicModel();
this.loading = true;
this.page = new Page();
this.buildForm();
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.route.parent.paramMap
.subscribe((params: Params) => {
this.admissionId = params["params"]["id"];
this.isAdmission = params["params"]["type"] === "a";
this.getFinalBillBasics(() => {
this.admissionFetch();
this.fetch();
this.getFinalBillBasics();
});
});
} else {
this.page.userAccount = undefined;
}
});
}
onBack = () => {
this.location.back();
}
get form() {
return this.gatePassForm.controls;
}
private buildForm(model?: GatepassModel) {
function adjust(val) {
if (val > 9) {
return val.toString();
} else {
return '0' + val.toString();
}
}
var today = new Date();
var date = today.getFullYear() + '-' + adjust(today.getMonth() + 1) + '-' + adjust(today.getDate());
var time = adjust(today.getHours()) + ":" + adjust(today.getMinutes());
this.maxDischargeDate = `${date}T${time}`;
this.gatePassForm = this.formBuilder.group({
remark: [model ? model.remark : null],
validUpto: [model ? model.validUpto : null, [Validators.required]],
});
}
onOpenModel(content: TemplateRef<any>) {
this.getFinalBillBasics();
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
size: "lg",
windowClass: "custom-modal slots-modal effect-scale"
});
return;
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.submitting = undefined;
this.submitted = undefined;
}
fetch = () => {
const data = {
id: this.admissionId,
typeId:2
};
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.gatePass.base, ApiResources.gatePass.gatePassfetch),
data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.mode = EditMode.Discharged;
const record = response.data as GatepassModel;
this.buildForm(record);
this.record = record;
} else if (response.status === GenericStatus[GenericStatus.Error]) {
this.mode = EditMode.Discharged;
this.notifyService.defaultError();
} else {
this.mode = EditMode.New;
}
},
() => {
this.record = null;
}
);
}
admissionFetch = () => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.serviceOrder.base, ApiResources.serviceOrder.getAdmissionBasic),
{ id: this.admissionId, isAdmission: this.isAdmission })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.admission = response.data as IAdmissionModel;
}
},
() => {
this.admission = null;
}
);
}
getFinalBillBasics = (callback = () => { }) => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.finalBill.base, ApiResources.finalBill.getBasics),
{
id: this.admissionId,
isAdmission: this.isAdmission
})
.pipe(takeUntil(this.page.unSubscribe))
.subscribe(
(response: GenericResponse) => {
this.finalBillBasics = response.data as FinalBillBasicModel;
callback();
},
() => {
this.finalBillBasics = new FinalBillBasicModel();
}
);
}
insert = () => {
this.submitted = true;
if (!this.gatePassForm.valid) {
return;
}
this.submitting = true;
const data = {
...this.gatePassForm.value,
admissionId: parseInt(this.admissionId),
roleId: this.page.userAccount.roleId,
typeId: 2
};
data["createdBy"] = this.page.userAccount.accountId;
data["fullName"] = this.page.userAccount.fullName;
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.gatePass.base, ApiResources.gatePass.gatePassinsert), data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitting = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.notifyService.success("Patient Gate pass has been Generated successfully");
this.mode = EditMode.Discharged;
this.fetch();
this.finalBillService.set(true);
} else {
if (response.message) {
this.notifyService.info(response.message);
} else {
this.notifyService.defaultError();
}
}
},
() => {
this.notifyService.defaultError();
}
);
}
onSubmit = () => {
if (this.record.gatePassId) {
this.update();
} else {
this.insert();
}
}
onEdit = () => {
this.mode = EditMode.New;
}
onCancel = () => {
this.mode = EditMode.Discharged;
}
update = () => {
this.submitted = true;
if (!this.gatePassForm.valid) {
return;
}
this.submitting = true;
const data = {
...this.gatePassForm.value,
id: this.record.gatePassId.toString()
};
data["modifiedBy"] = this.page.userAccount.accountId;
data["roleId"] = this.page.userAccount.roleId;
data["fullName"] = this.page.userAccount.fullName;
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.gatePass.base, ApiResources.gatePass.gatePassupdate), data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitting = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.notifyService.success("Patient Gate Pass details has been Updated successfully");
this.mode = EditMode.Discharged;
this.fetch();
} else {
if (response.message) {
this.notifyService.info(response.message);
} else {
this.notifyService.defaultError();
}
}
},
() => {
this.receiptTypes = new Array<IReceiptTypeModel>();
}
);
}
ngOnDestroy() {
this.page.unSubscribe.next();
this.page.unSubscribe.complete();
}
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.

<style>
.item {
/* background-color: aqua; */
border-bottom: 1px solid;
border-right: 1px solid;
overflow: hidden;
line-height: 30px;
min-height: 30px;
}
.item > input {
outline: none;
height: 100%;
border: none;
}
.boxContainer {
width: 100%;
display: grid;
margin: auto;
border-top: 1px solid;
border-left: 1px solid;
overflow: auto;
}
/* .modal-header > */
th, td {
padding: 0px 0px !important;
}
</style>
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<!--editMode.Discharged-->
<div class="page-title-right">
<button *ngIf="record.gatePassId" class="btn btn-primary btn-sm ml-1" (click)="onEdit()"><i class="fe-edit-2 mr-2"></i> Edit</button>
<button type="button" class="btn btn-primary btn-sm ml-2" (click)="onOpenModel(view)">
<span><i class="fe-eye mr-1"></i>Gate Pass Report</span>
</button>
<button class="btn btn-secondary btn-sm ml-1" (click)="onBack()"><i class="fe-arrow-left ml-1"></i> Back</button>
</div>
</div>
<h4 class="page-title">Provisional Gate Pass</h4>
</div>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading Provisional Gate-pass</span>
</div>
</div>
</div>
</div>
<!--&& finalBillBasics.isFinalBillGenerated && finalBillBasics.pendingAmount === 0"-->
<div class="row" *ngIf="!loading">
<div class="col-lg-12 px-2" *ngIf="mode === editMode.New">
<form [formGroup]="gatePassForm" (submit)="onSubmit()">
<div class="card">
<div class="card-body p-0">
<div class="card-box m-0">
<ng-container >
<h4 class="box-title"><i class="mdi mdi-human mr-1"></i>Gate Pass Information</h4>
<div class="row">
<div class="col-lg-5">
<div class="form-group">
<label>Valid Upto <code>*</code></label>
<input type="datetime-local" class="form-control" [min]="today | date: 'yyyy-MM-ddTHH:mm'" [ngClass]="{ 'is-invalid': (submitted && form.validUpto.errors) }" formControlName="validUpto" />
<div *ngIf="submitted && form.validUpto.errors" class="invalid-feedback show-must">
<div *ngIf="form.validUpto.errors.required">Valid Date is required</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="form-group">
<label>Remark</label>
<input type="text" class="form-control" [ngClass]="{ 'is-invalid': (submitted && form.remark.errors) }" formControlName="remark" placeholder="Enter the remark" />
</div>
</div>
</div>
</ng-container>
</div>
</div>
<div class="card-footer bg-light">
<div class="text-right">
<button *ngIf="!record.gatePassId" type="reset" class="btn btn-warning btn-sm mr-2">
<i class="fe-refresh-cw"></i>
<span class="ml-1">Reset</span>
</button>
<button *ngIf="record.gatePassId" type="button" (click)="onCancel()" class="btn btn-danger btn-sm mr-2">
<i class="fe-x"></i>
<span class="ml-1">Cancel</span>
</button>
<button type="submit" class="btn btn-sm btn-success">
<!--<span>
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>-->
<span>
<i class="fe-check"></i>
<span class="ml-1">
<span *ngIf="record.gatePassId">Update</span>
<span *ngIf="!record.gatePassId">Create</span>
</span>
</span>
</button>
</div>
</div>
</div>
</form>
</div>
<div class="col-lg-12 px-2" *ngIf="mode === editMode.Discharged">
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<div class="card mt-2">
<div class="card-body p-0">
<div class="table-responsive" *ngIf="record">
<table class="table table-centered table-bordered table-sm mb-0">
<tbody>
<ng-container>
<tr class="table-primary">
<th colspan="4">
Patient Information
</th>
</tr>
<tr>
<th class="table-active">
Patient Name
</th>
<td>
<span>
<span [textContent]="admission.fullName + ', '"></span>
<span [textContent]="(admission.gender === 'F' ? 'Female' : 'Male') + ', '"></span>
<span [textContent]="admission.age + 'yrs'"></span>
</span>
</td>
<th class="table-active">
Relation
</th>
<td [textContent]="admission.fatherOrHusband"></td>
</tr>
<tr>
<th class="table-active">
Address
</th>
<td [textContent]="admission.fullAddress"> </td>
<th class="table-active">
Bed Number
</th>
<td [textContent]="admission.bedNumber"></td>
</tr>
</ng-container>
<ng-container>
<tr class="table-primary">
<th colspan="4">
Gate-Pass Information
</th>
</tr>
<tr>
<th class="table-active">
Valid Date & Time
</th>
<td [textContent]="record.validUpto | date:'dd-MM-yyyy, h:mm:ss a'">
</td>
<th class="table-active">
Remark
</th>
<td [textContent]="record.remark"></td>
</tr>
<tr>
<th class="table-active">
Issued Date
</th>
<td [textContent]="record.createdDate | date:'dd-MM-yyyy, h:mm:ss a'">
</td>
<th class="table-active">
Issued By
</th>
<td [textContent]="record.createdByName"></td>
</tr>
</ng-container>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #view>
<div class="modal-header">
<h4 class="modal-title text-center">Gate -pass</h4>
<div>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();"><i class="fe-x"></i></button>
<button [useExistingCss]="true"
printSectionId="print-section"
ngxPrint
class="btn btn-light btn-xs mr-1 d-print-none">
<i class="fe-printer mr-1"></i>Print
</button>
</div>
</div>
<div class="modal-body" id="print-section">
<div class="card">
<div class="card-body p-0">
<div class="card-box m-0">
<div class="row mb-2">
<div class="col-lg-12 text-center" >
<h4><u>Checklist For Discharge</u></h4>
</div>
</div>
<div class="row" style="border:outset">
<div class="col-lg-12 font-18 mt-2">
<!--<div class="table-responsive">
<table class="table-borderless table-centered">
<tbody>
<tr>
<th>IP No</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.admissionNo"></span>
</td>
<th>C R No</th>
<td>
<span class="mr-1">:</span>
<span [textContent]=" "></span>
</td>
<th>Bill No</th>
<td>
<span class="mr-1">:</span>
<span [textContent]=" "></span>
</td>
</tr>
<tr>
<th>Patient Name</th>
<td colspan="3">
<span class="mr-1">:</span>
<span>
<span [textContent]="admission.fullName"></span>
</span>
</td>
<th>Bed No.</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.bedNumber"></span>
</td>
</tr>
<tr>
<th>Age</th>
<td [textContent]="admission.age +'Y'"></td>
<th>Sex</th>
<td [textContent]="(admission.gender === 'F' ? 'Female' : 'Male') "></td>
<th>Floor</th>
<td [textContent]="admission.floorName + ' / ' + admission.locationName "></td>
</tr>
<tr>
<th>Father/Husband Name</th>
<td colspan="3">
<span class="mr-1">:</span>
<span [textContent]="admission.fatherOrHusband"></span>
</td>
<th>Category</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.bedNumber"></span>
</td>
</tr>
<tr>
<th rowspan="3" style="vertical-align: top !important;">Address</th>
<td colspan="3" rowspan="3" style="vertical-align: top !important;">
<span class="mr-1">:</span>
<span class="pr-2" [textContent]="admission.fullAddress"></span>
</td>
<th>DOA</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="admission.admissionDate"></span>
</td>
</tr>
<tr>
<th>Issue Date</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="record.createdDate | date: 'dd-MM-yyyy'"></span>
</td>
</tr>
<tr>
<th>Issue Time</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="record.createdDate | date: 'h:mm:ss a'"></span>
</td>
</tr>
<tr>
<th>Phone</th>
<td colspan="3">
<span class="mr-1">:</span>
<span [textContent]="(admission.mobile)"></span>
</td>
<th>Valid Upto</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="(record.validUpto | date: 'dd-MM-yyyy')"></span>
</td>
</tr>
<tr>
<th>Ref By</th>
<td colspan="3">
<span class="mr-1">:</span>
<span [textContent]=" "></span>
</td>
<th>Valid Time</th>
<td>
<span class="mr-1">:</span>
<span [textContent]="(record.validUpto | date: 'h:mm:ss a')"></span>
</td>
</tr>
<tr>
</tr>
</tbody>
</table>
</div>-->
<div class="table-responsive">
<table class="table table-borderless table-centered">
<tbody>
<tr>
<th>IP No</th>
<td>{{ admission.admissionNo }}</td>
<th>C R No</th>
<td></td>
<th>Bill No</th>
<td></td>
</tr>
<tr>
<th>Patient Name</th>
<td colspan="3">{{ admission.fullName }}</td>
<th>Bed No.</th>
<td>{{ admission.bedNumber }}</td>
</tr>
<tr>
<th>Age</th>
<td>{{ admission.age }}Y</td>
<th>Sex</th>
<td>{{ admission.gender === 'F' ? 'Female' : 'Male' }}</td>
<th>Floor</th>
<td>{{ admission.floorName }} / {{ admission.locationName }}</td>
</tr>
<tr>
<th>Father/Husband Name</th>
<td colspan="3">{{ admission.fatherOrHusband }}</td>
<th>Category</th>
<td>{{admission.bedNumber }}</td>
</tr>
<tr>
<th rowspan="3" style="vertical-align: top !important;">Address</th>
<td colspan="3" rowspan="3">{{ admission.fullAddress }}</td>
<th>DOA</th>
<td>{{ admission.admissionDate }}</td>
</tr>
<tr>
<th>Issue Date</th>
<td>{{ record.createdDate | date: 'dd-MM-yyyy' }}</td>
</tr>
<tr>
<th>Issue Time</th>
<td>{{ record.createdDate | date: 'h:mm:ss a' }}</td>
</tr>
<tr>
<th>Phone</th>
<td colspan="3">{{ admission.mobile }}</td>
<th>Valid Upto</th>
<td>{{ record.validUpto | date: 'dd-MM-yyyy' }}</td>
</tr>
<tr>
<th>Ref By</th>
<td colspan="3"></td>
<th>Valid Time</th>
<td>{{ record.validUpto | date: 'h:mm:ss a' }}</td>
</tr>
</tbody>
</table>
</div>
<div class="boxContainer" style="border-bottom: 1px solid; margin: 2px 0;">
<div class="item" style="text-align: center; grid-column: 1/2; min-width: 100px;"></div>
<div class="item" style="text-align: center; grid-column: 2/3; min-width: 100px;">Checked By</div>
<div class="item" style="text-align: center; grid-column: 3/4; min-width: 100px;">Authorized By</div>
<div class="item" style="text-align: left; grid-row: 2; min-width: 100px;">Payment Made</div>
<div class="item" style="text-align: left; grid-row: 2; min-width: 100px;"></div>
<div class="item" style="text-align: left; grid-row: 2; min-width: 100px;"></div>
<div class="item" style="text-align: left; grid-row: 3; min-width: 100px;">Room Linen</div>
<div class="item" style="text-align: left; grid-row: 3; min-width: 100px;"></div>
<div class="item" style="text-align: left; grid-row: 3; min-width: 100px;"></div>
<div class="item" style="text-align: left; grid-row: 4; min-width: 100px;">Room Inventory</div>
<div class="item" style="text-align: left; grid-row: 4; min-width: 100px;"></div>
<div class="item" style="text-align: left; grid-row: 4; min-width: 100px;"></div>
</div>
<div>
NOTE To be retained by staff nurse.
</div>
<div>
<span>Issued</span>&nbsp;
<span><b>{{page.userAccount.fullName}}</b></span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-template>
import { Component, OnDestroy, OnInit, TemplateRef} from "@angular/core";
import { ActivatedRoute, Params } from "@angular/router";
import { takeUntil, finalize } from "rxjs/operators";
import { Location } from '@angular/common';
import { IUserAccount, Page, GenericResponse, GenericStatus } from "@shared/models";
import { AppData, HttpService, NotifyService, FinalBillService } from "@shared/services";
import { ApiResources } from "@shared/helpers";
import { IReceiptTypeModel} from "../../models/receipt-type.model";
import { FormGroup, FormBuilder, Validators } from "@angular/forms";
import { FinalBillBasicModel } from "../../models/final-bill-basic.model";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { IAdmissionModel } from "../../models/admission.model";
import { GatepassModel } from "../../models/gatepass.model";
enum EditMode {
New = 1,
Discharged = 2
}
@Component({
templateUrl: "./provisional-gate-pass.html",
styleUrls: ['../../services.css']
})
export class ProvisionalGatePassPage implements OnInit, OnDestroy {
editMode = EditMode;
page: Page;
loading: boolean;
record: GatepassModel;
admission: IAdmissionModel;
submitting: boolean;
submitted: boolean;
admissionId: string;
isAdmission: boolean;
receiptTypes: Array<IReceiptTypeModel>;
gatePassForm: FormGroup;
finalBillBasics: FinalBillBasicModel;
mode: EditMode;
today = new Date();
modalRef: NgbModalRef;
maxDischargeDate: string;
constructor(
private readonly httpService: HttpService,
private readonly route: ActivatedRoute,
private readonly finalBillService: FinalBillService,
private readonly appData: AppData,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly modalService: NgbModal,
private readonly location: Location
) {
this.mode = EditMode.New;
this.record = {} as GatepassModel;
this.finalBillBasics = new FinalBillBasicModel();
this.loading = true;
this.page = new Page();
this.buildForm();
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.route.parent.paramMap
.subscribe((params: Params) => {
this.admissionId = params["params"]["id"];
this.isAdmission = params["params"]["type"] === "a";
this.getFinalBillBasics(() => {
this.admissionFetch();
this.fetch();
this.getFinalBillBasics();
});
});
} else {
this.page.userAccount = undefined;
}
});
}
onBack = () => {
this.location.back();
}
get form() {
return this.gatePassForm.controls;
}
private buildForm(model?: GatepassModel) {
function adjust(val) {
if (val > 9) {
return val.toString();
} else {
return '0' + val.toString();
}
}
var today = new Date();
var date = today.getFullYear() + '-' + adjust(today.getMonth() + 1) + '-' + adjust(today.getDate());
var time = adjust(today.getHours()) + ":" + adjust(today.getMinutes());
this.maxDischargeDate = `${date}T${time}`;
this.gatePassForm = this.formBuilder.group({
remark: [model ? model.remark : null],
validUpto: [model ? model.validUpto : null, [Validators.required]],
});
}
onOpenModel(content: TemplateRef<any>) {
this.getFinalBillBasics();
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
size: "xl",
windowClass: "custom-modal effect-scale"
});
return;
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.submitting = undefined;
this.submitted = undefined;
}
fetch = () => {
const data = {
id: this.admissionId,
// GatePassTypeName
typeId:1
};
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.gatePass.base, ApiResources.gatePass.gatePassfetch),
data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.mode = EditMode.Discharged;
const record = response.data as GatepassModel;
this.buildForm(record);
this.record = record;
} else if (response.status === GenericStatus[GenericStatus.Error]) {
this.mode = EditMode.Discharged;
this.notifyService.defaultError();
} else {
this.mode = EditMode.New;
}
},
() => {
this.record = null;
}
);
}
admissionFetch = () => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.serviceOrder.base, ApiResources.serviceOrder.getAdmissionBasic),
{ id: this.admissionId, isAdmission: this.isAdmission })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.admission = response.data as IAdmissionModel;
}
},
() => {
this.admission = null;
}
);
}
getFinalBillBasics = (callback = () => { }) => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.finalBill.base, ApiResources.finalBill.getBasics),
{
id: this.admissionId,
isAdmission: this.isAdmission
})
.pipe(takeUntil(this.page.unSubscribe))
.subscribe(
(response: GenericResponse) => {
this.finalBillBasics = response.data as FinalBillBasicModel;
callback();
},
() => {
this.finalBillBasics = new FinalBillBasicModel();
}
);
}
insert = () => {
this.submitted = true;
if (!this.gatePassForm.valid) {
return;
}
this.submitting = true;
const data = {
...this.gatePassForm.value,
admissionId: parseInt(this.admissionId),
roleId: this.page.userAccount.roleId,
typeId: 1
};
data["createdBy"] = this.page.userAccount.accountId;
data["fullName"] = this.page.userAccount.fullName;
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.gatePass.base, ApiResources.gatePass.gatePassinsert), data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitting = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.notifyService.success("Patient Gate pass has been Generated successfully");
this.mode = EditMode.Discharged;
this.fetch();
this.finalBillService.set(true);
} else {
if (response.message) {
this.notifyService.info(response.message);
} else {
this.notifyService.defaultError();
}
}
},
() => {
this.notifyService.defaultError();
}
);
}
onSubmit = () => {
if (this.record.gatePassId) {
this.update();
} else {
this.insert();
}
}
onEdit = () => {
this.mode = EditMode.New;
}
onCancel = () => {
this.mode = EditMode.Discharged;
}
update = () => {
this.submitted = true;
if (!this.gatePassForm.valid) {
return;
}
this.submitting = true;
const data = {
...this.gatePassForm.value,
id: this.record.gatePassId.toString()
};
data["modifiedBy"] = this.page.userAccount.accountId;
data["roleId"] = this.page.userAccount.roleId;
data["fullName"] = this.page.userAccount.fullName;
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.gatePass.base, ApiResources.gatePass.gatePassupdate), data)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitting = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.notifyService.success("Patient Gate Pass details has been Updated successfully");
this.mode = EditMode.Discharged;
this.fetch();
} else {
if (response.message) {
this.notifyService.info(response.message);
} else {
this.notifyService.defaultError();
}
}
},
() => {
this.receiptTypes = new Array<IReceiptTypeModel>();
}
);
}
ngOnDestroy() {
this.page.unSubscribe.next();
this.page.unSubscribe.complete();
}
}
\ No newline at end of file
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<button type="button" class="btn btn-primary btn-sm ml-1" [disabled]="disableActionBtns" (click)="onOpenModel(templateAddReceipt)">
<span *ngIf="isChargesLoading">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!isChargesLoading"><i class="fe-plus mr-1"></i> Add Receipt</span>
</button>
<a href="javascript:;" class="btn btn-secondary btn-sm ml-1" (click)="onBack()">
<span *ngIf="!isChargesLoading"><i class="fe-arrow-left mr-1"></i> Back</span>
</a>
</div>
<h4 class="page-title">Receipts</h4>
</div>
</div>
<div class="col-lg-12" *ngIf="!finalBillBasics.isFinalBillGenerated">
<div class="d-flex align-items-center justify-content-center">
<div class="alert alert-info"><i class="mdi mdi-lightbulb"></i> Tip: Generate Final Bill to see Amount Dues & Refunds</div>
</div>
</div>
</div>
<div class="row" *ngIf="loading">
<div class="col-12">
<div class="d-flex align-items-center">
<span class="spinner-grow text-warning" role="status" aria-hidden="true"></span>
<span class="ml-2">Please wait while loading receipts ...</span>
</div>
</div>
</div>
</div>
<div class="row" *ngIf="!loading && records.length <= 0">
<div class="col-12 mh-400">
<no-data [title]="'Receipts'"></no-data>
</div>
</div>
<div class="row" *ngIf="!loading && records.length > 0">
<div class="col-lg-12">
<div class="card">
<div class="card-body mb-0">
<div class="table-responsive table-responsive-lg">
<table class="table table-centered table-bordered table-sm mb-0">
<thead>
<tr>
<th>Receipt No.</th>
<th>Cashier</th>
<th>Date & Time</th>
<th>Payment</th>
<th>Payment Mode</th>
<th>Amount</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of records; let i = index;">
<ng-container *ngIf="!item.isSpecial">
<td [ngClass]="{'text-line-through' : !item.active}" [textContent]="'RN-' + item.receiptNo"></td>
<td [ngClass]="{'text-line-through' : !item.active}">
<div class="media">
<div class="avatar-sm mr-2">
<span class="avatar-title rounded-circle font-12 font-weight-bold text-white" avatar-bg [index]="i" [textContent]="(item.modifiedByName ? item.modifiedByName : item.createdByName) | initials"></span>
</div>
<div class="media-body">
<h5 *ngIf="item.modifiedByName" class="mb-0 mt-0 font-weight-normal" [textContent]="item.modifiedByName"></h5>
<h5 *ngIf="!item.modifiedByName" class="mb-0 mt-0 font-weight-normal" [textContent]="item.createdByName"></h5>
<span class="d-block font-13">
<span [textContent]="(item.modifiedByName ? item.modifiedByRole : item.createdByRole)"></span>
</span>
</div>
</div>
</td>
<td [ngClass]="{'text-line-through' : !item.active}">
<span *ngIf="item.modifiedByName" class="ml-1" [textContent]="item.modifiedDate | date:'dd-MM-yyyy, h:mm:ss a'"></span>
<span *ngIf="!item.modifiedByName" class="ml-1" [textContent]="item.createdDate | date:'dd-MM-yyyy, h:mm:ss a'"></span>
</td>
<td>
<div *ngIf="item.receiptTypeId == receiptType.Refund">
<div [ngClass]="{'text-line-through' : !item.active}" *ngIf="item.isRefunded" class="badge badge-danger">Refund Success</div>
<div [ngClass]="{'text-line-through' : !item.active}" *ngIf="!item.isRefunded" class="badge badge-warning">Refund Pending</div>
</div>
<div *ngIf="item.receiptTypeId == receiptType.Cash">
<div [ngClass]="{'text-line-through' : !item.active}" *ngIf="item.isAdvance" class="badge badge-blue">Advance Paid</div>
<div [ngClass]="{'text-line-through' : !item.active}" *ngIf="!item.isAdvance" class="badge badge-success">Paid</div>
</div>
</td>
<td>
<span [ngClass]="{'text-line-through' : !item.active}" *ngIf="item.payTypeName !== 'Cash'" [ngbTooltip]="item.paymentDetails" placement="left" class="badge badge-outline-blue" [textContent]="item.payTypeName"></span>
<span [ngClass]="{'text-line-through' : !item.active}" *ngIf="item.payTypeName === 'Cash'" class="badge badge-outline-blue" [textContent]="item.payTypeName"></span>
</td>
<td>
<div class="d-flex align-items-center justify-content-between">
<span [ngClass]="{'text-line-through' : !item.active}" [textContent]="item.cost | currency:'INR'"></span>
<span>
<span *ngIf="item.isAppointmentReceipt" class="badge badge-outline-success" ngbTooltip="Appointment Booking Charges" placement="left">A</span>
</span>
</div>
</td>
<td>
<span *ngIf="item.active" class="badge badge-success fs-16">Active</span>
<span *ngIf="!item.active" class="badge badge-danger fs-16">Cancelled</span>
</td>
<td>
<div class="d-flex align-items-center justify-content-end">
<a (click)="onOpenViewModel(templateViewReceipt, item)" href="javascript:;" class="action-icon text-primary mr-1" ngbTooltip="View" placement="left"><i class="fe-eye"></i></a>
<a *ngIf="item.active && !disableActionBtns && !item.isDischarged" href="javascript:;" class="action-icon text-danger" (click)="onCancel(item)" placement="left" ngbTooltip="Cancel">
<i *ngIf="!item.cancelling" class="mdi mdi-cancel"></i>
<i *ngIf="item.cancelling" class="spinner-border spinner-border-sm"></i>
</a>
</div>
</td>
</ng-container>
<ng-container *ngIf="item.isSpecial">
<td>
<span class="badge badge-outline-warning">Action Required</span>
</td>
<td>---</td>
<td>---</td>
<td>
<div *ngIf="item.receiptTypeId == receiptType.Refund">
<div class="badge badge-warning">Refund Pending</div>
</div>
<div *ngIf="item.receiptTypeId == receiptType.Cash">
<div class="badge badge-danger">Amount Due</div>
</div>
</td>
<td>---</td>
<td>
<span [textContent]="item.cost | currency:'INR'"></span>
</td>
<td>---</td>
<td>
<button *ngIf="item.receiptTypeId == receiptType.Refund" class="btn btn-sm btn-success" [disabled]="disableActionBtns" (click)="onOpenModel(templateAddReceipt, false, item)"><i class="fe-check"></i> Issue Refund</button>
<button *ngIf="item.receiptTypeId == receiptType.Cash" class="btn btn-sm btn-success" [disabled]="disableActionBtns" (click)="onOpenModel(templateAddReceipt, true, item)"><i class="fe-check"></i> Pay Due</button>
</td>
</ng-container>
</tr>
</tbody>
<tfoot>
<tr>
<th colspan="8">
<div class="row">
<div class="col-lg-12">
<div class="text-right">
<div class="mr-3">
<h6>Total Amount Paid(Including Advance): </h6>
<h5 class="text-primary" [textContent]="amountPaid | currency:'INR'"></h5>
</div>
<div *ngIf="amountRefunded" style="margin-right:25px;">
<h6>Total Amount Refunded: </h6>
<h5 class="text-danger" [textContent]="amountRefunded | currency:'INR'"></h5>
</div>
</div>
</div>
</div>
</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
<!--Please.. Don't remove-->
<div id="dvContent"></div>
<!-- This is related to salucro iframe content-->
</div>
<ng-template #templateAddReceipt>
<form [formGroup]="receiptForm" (submit)="onAddReceipt()">
<div class="modal-header">
<h4 class="modal-title"><i class="fe-calendar mr-1"></i>Add Receipt</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="onCloseModal();">×</button>
</div>
<div class="modal-body">
<div class="appointment-form bg-light bg-pattern">
<div class="row" *ngIf="selected">
<div class="col-lg-12 flex-center">
<div *ngIf="selected.receiptTypeId == receiptType.Refund">
<div class="badge badge-warning">Refund Pending</div>
</div>
<div *ngIf="selected.receiptTypeId == receiptType.Cash">
<div class="badge badge-danger">Amount Due</div>
</div>
</div>
<div class="col-lg-12 flex-center">
<h2 [textContent]="selected.cost | currency:'INR'"></h2>
</div>
</div>
<div class="row">
<div class="col-lg-4" *ngIf="!selected">
<div class="form-group">
<label class="mb-1">Amount<code>*</code></label>
<input [ngClass]="{ 'is-invalid': submitted && form.cost.errors }" type="number" min="0" numbersOnly class="form-control" formControlName="cost"
placeholder="Enter Amount" />
<div *ngIf="submitted && form.cost.errors" class="invalid-feedback show-must">
<div *ngIf="form.cost.errors.required">Please enter amount</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="form-group">
<label>Payment Type <code>*</code></label>
<select class="form-control" formControlName="payTypeId" [ngClass]="{ 'is-invalid': (submitted && form.payTypeId.errors) }">
<option select hidden [value]="null">Select Pay Type</option>
<option *ngFor="let item of payTypeData" [ngValue]="item.id" [textContent]="item.name">
</option>
</select>
<div *ngIf="submitted && form.cost.errors" class="invalid-feedback show-must">
<div *ngIf="form.payTypeId.errors.required">Select Payment Type</div>
</div>
</div>
</div>
<div *ngIf="form.payTypeId.value > 1 && form.payTypeId.value < 9" class="col-lg-4">
<div class="form-group position-relative mb-0">
<label class="mb-1">Payment Number <code>*</code></label>
<input type="text" class="form-control" formControlName="paymentDetails" placeholder="Enter payment number" [ngClass]="{ 'is-invalid': (submitted && form.paymentDetails.errors) }" />
<!--<p *ngIf="form.paymentDetails.errors.whiteSpaces">Please remove white space</p>-->
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light btn-sm mr-1" (click)="onCloseModal();">Cancel</button>
<button type="submit" [disabled]="submitting" class="btn btn-primary btn-sm">
<span *ngIf="submitting">
<span class="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true"></span>
Please wait..
</span>
<span *ngIf="!submitting">Submit</span>
</button>
</div>
</form>
</ng-template>
<ng-template #templateViewReceipt>
<receipt-view-widget (emitOnCloseModel)="onCloseModal()" [receiptId]="selectedReceipt.receiptId" [admissionId]="admissionId" [isAdmission]="isAdmission"></receipt-view-widget>
</ng-template>
import { Component, OnDestroy, OnInit, TemplateRef } from "@angular/core";
import { ActivatedRoute, Params } from "@angular/router";
import { takeUntil, finalize } from "rxjs/operators";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
import { IResource, IUserAccount, Page, GenericResponse, GenericStatus } from "@shared/models";
import { ResourceService, AppData, HttpService, NotifyService, FinalBillService } from "@shared/services";
import { ApiResources, UtilHelper } from "../../../../../shared/helpers";
import { IReceiptModel } from "../../models/receipt.model";
import { IReceiptTypeModel, ReceiptType } from "../../models/receipt-type.model";
import { PayType } from "../../models/pay-type.model";
import { FormGroup, FormBuilder, Validators } from "@angular/forms";
import { FinalBillBasicModel } from "../../models/final-bill-basic.model";
import { IAdmissionModel } from "../../models/admission.model";
import { HttpErrorResponse } from "@angular/common/http";
import { Appointment, Setting } from "../../../../../shared/entities";
import { Location } from "@angular/common";
import { AdmissionFetchHelper } from "../../../progress-report/shared/helper";
import { WhiteSpaceValidator } from "../../../../../shared/validators";
import { PaymentModule } from "../../../../../shared/enums";
//import * as moment from "moment";
@Component({
templateUrl: "./receipts.html",
styleUrls: ['../../services.css']
})
export class ReceiptsPage implements OnInit, OnDestroy {
receiptType = ReceiptType;
payType = PayType;
page: Page;
loading: boolean;
isChargesLoading: boolean;
records: Array<IReceiptModel>;
submitting: boolean;
submitted: boolean;
admissionId: string;
isAdmission: boolean;
disableActionBtns: boolean = false;
receiptTypes: Array<IReceiptTypeModel>;
receiptForm: FormGroup;
appointment: Appointment;
modalRef: NgbModalRef;
finalBillBasics: FinalBillBasicModel;
selected: IReceiptModel;
selectedReceipt: IReceiptModel;
now: Date;
admission: IAdmissionModel;
amountPaid: number;
amountRefunded: number;
payTypeData: Array<IResource>;
payTypeId: number;
loadingPayTypes: boolean;
errorMessage: string;
isSalucro: boolean;
loadingSettings: boolean;
constructor(
private readonly httpService: HttpService,
private readonly route: ActivatedRoute,
private readonly resourceService: ResourceService,
private readonly finalBillService: FinalBillService,
private readonly appData: AppData,
private readonly modalService: NgbModal,
private readonly formBuilder: FormBuilder,
private readonly notifyService: NotifyService,
private readonly location: Location,
private readonly admissionFetchHelper: AdmissionFetchHelper,
) {
this.finalBillBasics = new FinalBillBasicModel();
this.records = new Array<IReceiptModel>();
this.isChargesLoading = false;
this.loading = true;
this.page = new Page();
this.buildReceiptForm();
}
ngOnInit() {
this.appData.userAccount
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((userAccount: IUserAccount) => {
if (userAccount) {
this.page.userAccount = userAccount;
this.getSettingsData();
this.route.parent.paramMap
.subscribe((params: Params) => {
this.admissionId = params["params"]["id"];
this.isAdmission = params["params"]["type"] === "a";
if (!this.isAdmission)
this.getAppointment(this.admissionId);
this.getFinalBillBasics(() => {
this.admissionFetch();
this.fetch();
this.fetchPayTypes(this.isSalucro);
});
});
} else {
this.page.userAccount = undefined;
}
});
}
get form() {
return this.receiptForm.controls;
}
private buildReceiptForm() {
this.receiptForm = this.formBuilder.group({
receiptTypeId: [null, [Validators.required]],
cost: [null, [Validators.required]],
payTypeId: [null, [Validators.required]],
paymentDetails: [null, [Validators.maxLength(50)]],
});
this.receiptForm.get("payTypeId").valueChanges.subscribe((value: number) => {
var paymentDetails = this.receiptForm.get("paymentDetails");
if (value > 1 && value < 9) {
paymentDetails.setValidators([Validators.required, WhiteSpaceValidator.isValid]);
paymentDetails.enable();
paymentDetails.setValue("");
} else {
paymentDetails.clearValidators();
paymentDetails.setErrors(null);
paymentDetails.setValidators(null);
paymentDetails.setValue("");
}
});
}
getAppointment = (admissionId: string) => {
const request = { appointmentId: parseInt(admissionId) };
this.httpService.post(ApiResources.getURI(ApiResources.appointments.base, ApiResources.appointments.find), request)
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Appointment) => {
this.appointment = response;
this.disableActionBtns = this.appointment && this.appointment.status === "C";
});
}
admissionFetch = () => {
this.admissionFetchHelper.admissionFetch(+this.admissionId, this.isAdmission, (data: IAdmissionModel) => {
this.loading = false
this.admission = data;
});
}
onOpenModel(content: TemplateRef<any>, isCash: boolean = true, selected: IReceiptModel = null) {
this.fetchPayTypes(this.isSalucro);
if (!selected && this.finalBillBasics.finalAmount !== 0) {
this.notifyService.info("Receipts can not be added once the final bill is generated, please cancel the Final Bill and try again.");
return;
}
this.selected = selected;
this.receiptForm.reset();
//if (isCash === undefined) {
// this.receiptForm.patchValue({
// receiptTypeId: null,
// cost: selected ? selected.cost : null
// });
//}
//if (isCash != undefined) {
this.receiptForm.patchValue({
receiptTypeId: isCash ? ReceiptType.Cash : ReceiptType.Refund,
cost: selected ? selected.cost : null
});
//}
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
size: "lg",
windowClass: "custom-modal slots-modal effect-scale"
});
return;
}
onOpenViewModel(content: TemplateRef<any>, item: IReceiptModel) {
this.selectedReceipt = item;
this.now = new Date();
this.modalRef = this.modalService.open(content, {
backdrop: "static",
keyboard: false,
centered: true,
size: "lg",
windowClass: "custom-modal slots-modal effect-scale"
});
return;
}
onCloseModal() {
try {
this.modalRef.close();
this.modalRef = undefined;
} catch (e) {
// ignored;
}
this.submitting = undefined;
this.submitted = undefined;
}
fetch = () => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.receipt.base, ApiResources.receipt.fetch),
{ id: this.admissionId, isAdmission: this.isAdmission })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loading = false))
.subscribe(
(response: GenericResponse) => {
const records = response.data.records as Array<IReceiptModel>;
records.forEach(item => {
item.receiptNo = String(item.receiptId).padStart(6, '0');
});
this.amountPaid = records.filter(x => x.receiptTypeId === ReceiptType.Cash && x.active)
.map(x => x.cost).reduce((a, b) => a + b, 0);
this.amountRefunded = records.filter(x => x.receiptTypeId === ReceiptType.Refund && x.active)
.map(x => x.cost).reduce((a, b) => a + b, 0);
this.records = records;
this.unshiftPending();
},
() => {
this.records = new Array<IReceiptModel>();
}
);
}
getFinalBillBasics = (callback = () => { }) => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.finalBill.base, ApiResources.finalBill.getBasics), { id: this.admissionId, isAdmission: this.isAdmission })
.pipe(takeUntil(this.page.unSubscribe))
.subscribe(
(response: GenericResponse) => {
this.finalBillBasics = response.data as FinalBillBasicModel;
callback();
},
() => {
this.finalBillBasics = new FinalBillBasicModel();
}
);
}
unshiftPending = () => {
if (this.finalBillBasics.isFinalBillGenerated && this.finalBillBasics.pendingAmount !== 0) {
let record = {} as IReceiptModel;
if (this.finalBillBasics.pendingAmount < 0) {
// Due
record = {
isSpecial: true,
payTypeId: null,
receiptTypeId: ReceiptType.Cash,
paymentDetails: null,
cost: (this.finalBillBasics.pendingAmount * -1),
} as IReceiptModel;
} else {
// Refund
record = {
isSpecial: true,
payTypeId: null,
receiptTypeId: ReceiptType.Refund,
paymentDetails: null,
cost: this.finalBillBasics.pendingAmount,
} as IReceiptModel;
}
this.records.unshift(record);
}
}
onCancel = (item: IReceiptModel) => {
if (item.cancelling) return;
item.cancelling = true;
this.notifyService.confirm("Do you really want to cancel this receipt? This process can not be undone.",
() => {
this.httpService
.post(ApiResources.getURI(ApiResources.receipt.base, ApiResources.receipt.cancel),
{ id: item.receiptId, loginAccountId: this.page.userAccount.accountId, loginRoleId: this.page.userAccount.roleId })
.pipe(finalize(() => { item.cancelling = false; }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
this.fetch();
this.getFinalBillBasics(() => {
this.finalBillService.set(true);
this.fetch();
});
} else {
this.notifyService.defaultError();
}
},
(error: HttpErrorResponse) => {
item.cancelling = false;
const errorMessage = UtilHelper.handleError(error);
if (errorMessage) {
this.notifyService.warning(errorMessage);
} else {
this.notifyService.defaultError();
}
});
},
() => {
item.cancelling = false;
});
}
onBack = () => {
this.location.back();
}
onAddReceipt = () => {
this.submitted = true;
if (!this.receiptForm.valid) {
this.notifyService.infoToast("Please fill all the mandatory fields.");
return;
}
const self = this;
function callback(response: Document): void {
if (response) {
$("#dvContent").html(response.body.innerHTML);
$(".payment-content form #paynow").click();
self.submitting = false;
} else {
self.submitting = false;
self.errorMessage = UtilHelper.defaultErrorMessage();
}
}
this.submitting = true;
const data = {
...this.receiptForm.value,
id: this.admissionId,
isAdmission: this.isAdmission,
createdBy: this.page.userAccount.accountId,
roleId: this.page.userAccount.roleId,
roleName: this.page.userAccount.roleName,
createdByName: this.page.userAccount.fullName
};
if (this.selected && this.selected.receiptTypeId === ReceiptType.Refund) {
data["isRefunded"] = true;
}
data["totalAmount"] = data["cost"];
data["logFrom"] = this.page.userAccount.roleId;
data["locationId"] = this.page.userAccount.locationId;
data["patientId"] = this.admission.patientId;
const paymentModel = {
type: PaymentModule.Admission,
json: JSON.stringify(data),
mode: data["isRefunded"] ? "Refund" : "Payment"
}
const model = (this.isSalucro && (data.totalAmount > 0)) ? paymentModel : data;
const formData = UtilHelper.prepareFormData(UtilHelper.clone(model));
let url = (this.isSalucro && (data.totalAmount > 0)) ? ApiResources.getURI(ApiResources.appointments.base, ApiResources.appointments.initiatePayment) : ApiResources.getURI(ApiResources.receipt.base, ApiResources.receipt.insert);
this.httpService
.postFile<GenericResponse>(url, formData)
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.submitting = false))
.subscribe(
(response: GenericResponse) => {
if (response.status === GenericStatus[GenericStatus.Success]) {
const data = response.data;
if (typeof (data) === "number") {
this.onCloseModal();
this.getFinalBillBasics(() => {
this.finalBillService.set(true);
this.fetch();
});
}
else {
UtilHelper.getHtml(data, callback);
}
} else {
if (response.message) {
this.notifyService.info(response.message);
} else {
this.notifyService.defaultError();
}
}
},
() => {
this.receiptTypes = new Array<IReceiptTypeModel>();
}
);
}
ngOnDestroy() {
this.page.unSubscribe.next();
this.page.unSubscribe.complete();
}
private fetchPayTypes(isSalucro?: boolean) {
let salucro = isSalucro === true ? true : false;
this.loadingPayTypes = true;
this.resourceService.payType(salucro)
.pipe(finalize(() => { this.loadingPayTypes = false }))
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((response: Array<IResource>) => {
this.payTypeData = response;
let findPayType = null;
if (salucro) {
this.receiptForm.patchValue({
payTypeId: 13
});
}
else {
this.receiptForm.patchValue({
payTypeId: findPayType ? findPayType.value : null
});
}
});
}
private getSettingsData() {
this.loadingSettings = true;
this.httpService.get<Array<Setting>>(ApiResources.getURI(ApiResources.setting.base, ApiResources.setting.fetch), { name: "Salucro" })
.pipe(takeUntil(this.page.unSubscribe))
.pipe(finalize(() => this.loadingSettings = false))
.subscribe((response: Array<Setting>) => {
if (response.length > 0) {
this.isSalucro = response[0].active;
}
});
}
}
\ No newline at end of file
.flex-end {
display: flex;
align-items: flex-end;
justify-content: flex-end;
}
.flex-center {
display: flex;
align-items: center;
justify-content: center;
}
.flex-space-between {
display: flex;
align-items: center;
justify-content: space-between;
}
.vertical-align-middle {
vertical-align: middle;
}
.vertical-align-top {
vertical-align: top;
}
.align-items-flex-end {
align-items: flex-end;
}
.date-clear-icon {
position: absolute;
right: 60px;
cursor: pointer;
top: 37px;
padding: 3px;
}
.table {
border-spacing: 0 !important;
}
.table.table-black-border td, table.table-black-border th {
border-color: black;
}
.date-clear-icon:hover {
background: #e8e6e6;
border-radius: 25px;
}
.text-line-through {
text-decoration: line-through !important;
}
.mt-10 {
margin-top: 9rem;
}
.round-box {
padding: 30px;
border-radius: 50%;
width: 250px;
height: 250px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.bg-services {
background-color: #3181f3;
box-shadow: -6px 6px #98a6ad;
}
.bg-package {
background-color: #3181f3;
box-shadow: -6px 6px #98a6ad;
}
.round-box .round-text {
transition: all .1s ease-in-out;
}
.round-box:hover .round-text {
transform: scale(1.1,1.1)
}
.mt-1x {
margin-top: 0.275rem !important;
}
.search-input {
width: 400px;
}
<div class="sidebar-main-menu bg-pattern lgSubMenu left220px addedLeft pt-1" style="background-size: 200%; background-repeat: no-repeat;">
<div id="two-col-menu" class="h-100" data-simplebar>
<div class="twocolumn-menu-item d-block">
<ng-container *ngIf="record">
<div class="d-flex align-items-center justify-content-center flex-column">
<div class="avatar-md">
<avatar-img *ngIf="record.thumbnailUrl" [src]="record.thumbnailUrl" [alt]="record.fullName" cssClass="img-fluid rounded-circle"></avatar-img>
<span *ngIf="!record.thumbnailUrl" class="avatar-title rounded-circle bg-primary font-24 text-white" [textContent]="record.fullName | initials"></span>
</div>
<h5 class="mb-0 text-center">
<a href="javascript:;" class="text-dark">
<span [textContent]="record.fullName"></span>
<span class="d-block font-13 mt-1x" [textContent]="'(' + record.gender+ ') '"></span>
<span class="d-block font-13 mt-1x" [textContent]="record.age + 'yrs'"></span>
<small class="d-block font-13 mt-1x" style="text-align:center" [textContent]="record.umrNo || '--'"></small>
<small class="d-block font-13 mt-1x" style="text-align:center" [textContent]="record.mobile || '--'"></small>
</a>
</h5>
<h6 class="mb-0" (click)="onViewDoctorProfile(record.encryptedProviderId)">
<a href="javascript:;" class="text-dark">
<span [textContent]="'Dr. ' + record.providerName + ', '"></span>
<span [textContent]="'(' + record.providerGender+ ')'"></span>
<small class="d-block font-13 mt-1x" style="text-align:center" [textContent]="record.departmentName"></small>
</a>
</h6>
<div class="mb-2">
<span class="badge badge-success" *ngIf="isAdmission">In Patient</span>
<span class="badge badge-warning" *ngIf="!isAdmission">Out Patient</span>
</div>
</div>
<div>
<div class="table-responsive">
<table class="table table-centered table-bordered table-sm mb-0">
<tbody>
<tr>
<th class="small">
<span *ngIf="isAdmission">Admission No</span>
<span *ngIf="!isAdmission">Appointment No</span>
</th>
<td class="small" [textContent]="record.admissionNo"></td>
</tr>
<tr>
<th class="small">Date</th>
<td class="small" [textContent]="record.admissionDate | date: 'dd-MM-yyyy'"></td>
</tr>
<tr>
<th class="small">Time</th>
<td class="small">
<span *ngIf="isAdmission" [textContent]="record.admissionDate | date: 'h:mm:ss a'"></span>
<span *ngIf="!isAdmission" [textContent]="record.timeString"></span>
</td>
</tr>
<tr *ngIf="isAdmission">
<th class="small">Bed No</th>
<td class="small" [textContent]="record.bedNumber || '---'"></td>
</tr>
<tr>
<th class="small">Charge category</th>
<td class="small" [textContent]="record.chargeCategoryName || '---'"></td>
</tr>
<tr *ngIf="isAdmission">
<th class="small">Pay Type</th>
<td class="small" [textContent]="record.admissionPayTypeName || '---'"></td>
</tr>
<!--<tr class="table-active">
<th colspan="2" class="small">Doctor Details</th>
</tr>
<tr>
<td colspan="2" class="small" [textContent]="record.providerName + ' (' + record.providerGender + ')'"></td>
</tr>-->
<!--<tr class="table-active">
<th colspan="2" class="small">Discharge Details</th>
</tr>-->
<ng-container *ngIf="finalBillBasics.isFinalBillGenerated">
<tr *ngIf="isAdmission">
<td colspan="2" class="small">
<span *ngIf="!finalBillBasics.isDischarged" class="text-dark">Not Discharged</span>
<span *ngIf="finalBillBasics.isDischarged" class="text-primary"><i class="mdi mdi-check-bold mr-1"></i> Discharged</span>
</td>
</tr>
<!--<tr class="table-active">
<th colspan="2" class="small">Payment Details</th>
</tr>-->
<tr>
<th colspan="2">
<span *ngIf="finalBillBasics.pendingAmount > 0"><span class="small">Refund Pending:</span> <span class="text-success vertical-align-middle ml-2" [textContent]="finalBillBasics.pendingAmount | currency:'INR'"></span></span>
<span *ngIf="finalBillBasics.pendingAmount < 0"><span class="small">Amount Due:</span> <span class="text-danger vertical-align-middle ml-2" [textContent]="(finalBillBasics.pendingAmount * -1) | currency:'INR'"></span></span>
<span class="text-primary small" *ngIf="finalBillBasics.pendingAmount === 0"><i class="mdi mdi-check-bold mr-1"></i> Payment Cleared</span>
</th>
</tr>
</ng-container>
<ng-container *ngIf="!finalBillBasics.isFinalBillGenerated">
<tr class="table-active">
<td colspan="2" rowspan="2">
<div class="d-flex align-items-center justify-content-center small">
<div class="alert alert-info mb-0"><i class="mdi mdi-lightbulb"></i> Tip: Generate Final Bill to see Amount Dues & Refunds</div>
</div>
</td>
</tr>
</ng-container>
<!--<tr class="table-active">
<th colspan="2" class="small">Attendant Details</th>
</tr>
<tr>
<th class="small">Name</th>
<td class="small" [textContent]="record.attendantName"></td>
</tr>
<tr>
<th class="small">Contact No</th>
<td class="small" [textContent]="record.attendantContactNo"></td>
</tr>
<tr>
<th class="small">Relation</th>
<td class="small" [textContent]="record.attendantRelationWithPatient"></td>
</tr>-->
</tbody>
</table>
</div>
</div>
</ng-container>
<h5 class="menu-title text-primary mt-3">Navigation</h5>
<ul class="nav flex-column encounter-menu">
<li class="nav-item" *ngFor="let menu of menus">
<a class="dropdown-item" [ngClass]="{'flex-space-between' : menu.subPage === 'receipts'}"
[routerLink]="menu.subPage"
[class.active]="activeRoute === menu.subPage"
href="javascript:;">
<!-- Appointment -->
<ng-container *ngIf="!this.isAdmission && menu.subPage === 'receipts'">
<span [ngClass]="{'text-success':finalBillBasics.isFinalBillGenerated && finalBillBasics.pendingAmount === 0}">
<i *ngIf="menu.iconClasses" [class]="'mr-1 ' + menu.iconClasses"></i>
<span class="text-capitalize" [textContent]="menu.displayName"></span>
</span>
<ng-container *ngIf="finalBillBasics.isFinalBillGenerated && finalBillBasics.pendingAmount !== 0">
<span [ngClass]="{'badge-light' : activeRoute === 'receipts', 'badge-primary': activeRoute !== 'receipts'}" class="badge mr-3">1</span>
</ng-container>
</ng-container>
<ng-container *ngIf="!this.isAdmission && (menu.subPage == 'new-orders' || menu.subPage == 'orders') ">
<span [ngClass]="{'text-success': finalBillBasics.isServiceTaken}">
<i *ngIf="menu.iconClasses" [class]="'mr-1 ' + menu.iconClasses"></i>
<span class="text-capitalize" [textContent]="menu.displayName"></span>
</span>
</ng-container>
<ng-container *ngIf="!this.isAdmission && menu.subPage === 'final-bill'">
<span [ngClass]="{'text-success': finalBillBasics.isFinalBillGenerated}">
<i *ngIf="menu.iconClasses" [class]="'mr-1 ' + menu.iconClasses"></i>
<span class="text-capitalize" [textContent]="menu.displayName"></span>
</span>
</ng-container>
<!-- Admission -->
<ng-container *ngIf="this.isAdmission && menu.subPage === 'receipts'">
<span [ngClass]="{'text-success':finalBillBasics.isFinalBillGenerated && finalBillBasics.pendingAmount === 0}">
<i *ngIf="menu.iconClasses" [class]="'mr-1 ' + menu.iconClasses"></i>
<span class="text-capitalize" [textContent]="menu.displayName"></span>
</span>
<ng-container *ngIf="finalBillBasics.isFinalBillGenerated && finalBillBasics.pendingAmount !== 0">
<span [ngClass]="{'badge-light' : activeRoute === 'receipts', 'badge-primary': activeRoute !== 'receipts'}" class="badge mr-3">1</span>
</ng-container>
</ng-container>
<ng-container *ngIf="this.isAdmission && (menu.subPage == 'new-orders' || menu.subPage == 'orders') ">
<span [ngClass]="{'text-success': finalBillBasics.isServiceTaken}">
<i *ngIf="menu.iconClasses" [class]="'mr-1 ' + menu.iconClasses"></i>
<span class="text-capitalize" [textContent]="menu.displayName"></span>
</span>
</ng-container>
<ng-container *ngIf="this.isAdmission && menu.subPage === 'final-bill'">
<span [ngClass]="{'text-success': finalBillBasics.isFinalBillGenerated}">
<i *ngIf="menu.iconClasses" [class]="'mr-1 ' + menu.iconClasses"></i>
<span class="text-capitalize" [textContent]="menu.displayName"></span>
</span>
</ng-container>
<ng-container *ngIf="this.isAdmission && menu.subPage === 'discharge-patient'">
<span [ngClass]="{'text-success': finalBillBasics.isDischarged}">
<i *ngIf="menu.iconClasses" [class]="'mr-1 ' + menu.iconClasses"></i>
<span class="text-capitalize" [textContent]="menu.displayName"></span>
</span>
</ng-container>
<ng-container *ngIf="this.isAdmission && menu.subPage == 'provisional-gate-pass'">
<span [ngClass]="{'text-success': finalBillBasics.isProvisionalGatePass}">
<i *ngIf="menu.iconClasses" [class]="'mr-1 ' + menu.iconClasses"></i>
<span class="text-capitalize" [textContent]="menu.displayName"></span>
</span>
</ng-container>
<ng-container *ngIf="this.isAdmission && menu.subPage == 'gate-pass'">
<span [ngClass]="{'text-success': finalBillBasics.isFinalGatePass}">
<i *ngIf="menu.iconClasses" [class]="'mr-1 ' + menu.iconClasses"></i>
<span class="text-capitalize" [textContent]="menu.displayName"></span>
</span>
</ng-container>
</a>
</li>
<!--<li class="nav-item">
<a class="dropdown-item" routerLink="orders" [class.active]="activeRoute === 'orders'" href="javascript:;">
<i class="fe-menu mr-1"></i> Service Order
</a>
</li>
<li class="nav-item">
<a class="dropdown-item d-flex align-items-center justify-content-between" routerLink="receipts" [class.active]="activeRoute === 'receipts'" href="javascript:;">
</a>
</li>
<li class="nav-item">
<a class="dropdown-item" routerLink="final-bill" [class.active]="activeRoute === 'final-bill'" href="javascript:;"><i class="fe-credit-card mr-1"></i> Final Bill</a>
</li>
<li class="nav-item">
<a class="dropdown-item" routerLink="discharge" [class.active]="activeRoute === 'discharge'" href="javascript:;"><i class="fe-log-out mr-1"></i> Discharge</a>
</li>-->
</ul>
</div>
</div>
</div>
<router-outlet></router-outlet>
\ No newline at end of file
import { Component, OnDestroy, OnInit, ViewEncapsulation } from "@angular/core";
import { ActivatedRoute, Router, RouterEvent, NavigationEnd, Params } from "@angular/router";
import { Page, IMenuModel } from "@shared/models";
import { takeUntil } from "rxjs/operators";
import { IAdmissionModel } from "./models/admission.model";
import { GenericResponse } from "@shared/models";
import { HttpService, FinalBillService, MenuService } from "@shared/services";
import { ApiResources } from "../../../shared/helpers";
import { FinalBillBasicModel } from "./models/final-bill-basic.model";
import { Subscription } from "rxjs";
import { MenuType } from "../../../shared/enums";
import { AdmissionFetchHelper } from "../progress-report/shared/helper";
@Component({
templateUrl: "./services.html",
styleUrls: ['./services.css'],
encapsulation: ViewEncapsulation.None
})
export class ServicesPage implements OnInit, OnDestroy {
page: Page;
activeRoute: string;
admissionId: string;
loading: boolean;
record: IAdmissionModel;
finalBillBasics: FinalBillBasicModel;
finalBillServiceSubscription: Subscription;
isAdmission: boolean;
menus: Array<IMenuModel>;
constructor(
private readonly router: Router,
private readonly route: ActivatedRoute,
private readonly httpService: HttpService,
private readonly finalBillService: FinalBillService,
private readonly admissionFetchHelper: AdmissionFetchHelper,
private readonly menuService: MenuService
) {
this.menus = this.menuService.menus(MenuType.SubMenu, "Services & Payments");
this.finalBillBasics = new FinalBillBasicModel();
this.page = new Page();
}
ngOnInit() {
this.finalBillServiceSubscription = this.finalBillService.get.subscribe((value: boolean) => {
if (value) {
this.getFinalBillBasics();
}
});
this.route.params
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((params: Params) => {
this.admissionId = params["id"];
this.isAdmission = params["type"] === "a";
if (!this.isAdmission) {
this.menus = this.menus.filter(x => x.subPage !== 'discharge' && x.subPage !== 'gate-pass');
}
if (!this.isAdmission) {
this.menus = this.menus.filter(x => x.subPage !== 'discharge-patient');
}
if (!this.isAdmission) {
this.menus = this.menus.filter(x => x.subPage !== 'provisional-gate-pass');
}
const url = this.router.url;
this.activeRoute = url.split("/")[url.split("/").length - 1];
this.fetch();
this.getFinalBillBasics();
});
this.router.events
.pipe(takeUntil(this.page.unSubscribe))
.subscribe((event: RouterEvent) => {
if (event instanceof NavigationEnd) {
const url = this.router.url;
this.activeRoute = url.split("/")[url.split("/").length - 1];
}
});
}
onViewDoctorProfile(encryptedProviderId: string) {
this.router.navigateByUrl(`app/provider/${encryptedProviderId}`);
}
getFinalBillBasics = () => {
this.httpService
.post<GenericResponse>(ApiResources.getURI(ApiResources.finalBill.base, ApiResources.finalBill.getBasics), { id: this.admissionId, isAdmission: this.isAdmission })
.pipe(takeUntil(this.page.unSubscribe))
.subscribe(
(response: GenericResponse) => {
this.finalBillBasics = response.data as FinalBillBasicModel;
},
() => {
this.finalBillBasics = new FinalBillBasicModel();
}
);
}
fetch = () => {
this.admissionFetchHelper.admissionFetch(+this.admissionId, this.isAdmission, (data: IAdmissionModel) => {
this.loading = false
this.record = data;
if (!this.isAdmission && this.record && this.record.status && this.record.status === "C") {
this.menus = this.menus.filter(x => x.subPage !== 'orders');
var url = this.router.url;
url = url.replace(url.split("/")[url.split("/").length - 1], this.menus[this.menus.length - 1].subPage);
this.activeRoute = url.split("/")[url.split("/").length - 1];
this.router.navigateByUrl(url);
}
});
}
ngOnDestroy() {
this.finalBillServiceSubscription.unsubscribe();
this.page.unSubscribe.next();
this.page.unSubscribe.complete();
}
}
\ No newline at end of file
 export class WhatsAppTicketList {
ticketId:number
ticketNo:string
mobile :string
name :string
regarding: string
solved: boolean
createdDate: Date
totalItems: number
modifiedBy: number
modifiedDate: Date
modifiedByName:string
}
export class ConsultationReport {
providerId?: number;
doctorName: string;
uMRNo: string;
patientName: string;
appointment: string;
patientRegistration: number;
labs: number;
pharmacy: number;
scanAppointment: number;
fromDate: string;
ToDate: string;
locationId: number;
billDate: Date;
billNumber: string;
}
\ No newline at end of file
export class AdmissionCounts {
departmentId: number;
departmentName :string;
admissionCount: number;
serviceDays: number;
avgServiceDays: number;
locationId: number;
name: string;
createdDate: string;
totalOccupants: number;
avarageStay: number;
wardName: string;
}
\ No newline at end of file
export class DoctrorAppointmentMonthlyReport{
providerId: number;
fullName: string;
monthName: string;
locationName: string;
newPatientSlots: number;
givenAppointmentCount: number;
ancPatientCount: number;
seenAppointmentCount: number;
ancClosedPatientCount: number;
}
\ No newline at end of file
export class EncounterOrderTemplatesList {
encounterTemplateId: number
encounterTypeId: number
encounterTypeName:string
templateName: string
active: boolean
createdBy: number
createdDate: Date
modifiedBy: number
modifiedDate: Date
createdByName: string
modifiedByName: string
totalItems: number
description: string
}

export class EncountersLog {
encounterLogId: number;
logDescription: string;
logDate: string;
encounterTypeId: number;
logFrom: number;
encounterTypeName: string;
AccountId: number;
fullName: string;
roleName: string;
totalItems: number;
roleId: number;
locationId: number;
section: string;
}
export class GeneticSpecialityEncounterList {
geneticSpecialityEncounterId: number;
appointmentId: number;
active: boolean;
createdBy: number;
createdDate: Date;
modifiedBy: number;
modifiedDate: Date;
specialFeaturesPage: string;
geneticVisit: string;
outsideTest: string;
encryptedAppointmentId: string;
jsonString: string;
reminder: string;
orders: string;
}
\ No newline at end of file
export class InsuranceTemplate {
insuranceTemplateId: number;
chargeModuleTemplateId: number;
templateName: string;
insuranceCompanyId: number;
tpaId: number;
tpaName: string;
insuranceCompanyName: string;
active: boolean;
createdDate: Date;
totalItems: number;
modifiedDate: Date;
createdByName: string;
modifiedByName: string;
createdByRole: string;
modifiedByRole: string;
locationName: string;
locationId: number;
admissionPayTypeName: string;
admissionPayTypeId: number;
}
\ No newline at end of file
export class RetailIssueIndentReport {
indentDate:Date;
indentNo: number;
remarks: string;
productName: string;
categoryName: string;
status: string;
quantity: number;
indentTo?: string;
locationId?: number;
departmentId?: number;
retailPharmacyId?: number;
productId?: number;
createdDate?: Date;
fromDate?: string;
toDate?: string;
approvedDate?: string;
statusName?: string;
}
export class PhysiotherapyEncounterList {
physiotherapyEncounterId: number
appointmentId
active: boolean
createdBy: number
createdDate: Date
modifiedBy: number
modifiedDate: Date
createdByName: string
modifiedByName: string
type: string
jsonString: string
specialFeature: string
encryptedAppointmentId: string
reminder: string;
physioTherapyTemplate: string;
outsideTest: string
referralForm:string
}
\ No newline at end of file
export class LabRevenue {
labMainDetailId: number;
labTestName: string;
counts: number;
revenues: number;
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment