1 import {Component, OnInit, ViewChild, OnDestroy} from '@angular/core';
2 import {FormGroup, FormControl} from '@angular/forms';
3 import {Router, ActivatedRoute, ParamMap} from '@angular/router';
4 import {Subscription, of} from 'rxjs';
5 import {debounceTime, single, tap, switchMap} from 'rxjs/operators';
6 import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
7 import {AuthService} from '@eg/core/auth.service';
8 import {PcrudService} from '@eg/core/pcrud.service';
9 import {ReservationsGridComponent} from './reservations-grid.component';
10 import {ServerStoreService} from '@eg/core/server-store.service';
11 import {ToastService} from '@eg/share/toast/toast.service';
12 import {NetService} from '@eg/core/net.service';
13 import {PatronBarcodeValidator} from '@eg/share/validators/patron_barcode_validator.directive';
14 import {BookingResourceBarcodeValidator} from './booking_resource_validator.directive';
15 import {OrgFamily} from '@eg/share/org-family-select/org-family-select.component';
18 selector: 'eg-manage-reservations',
19 templateUrl: './manage-reservations.component.html',
21 export class ManageReservationsComponent implements OnInit, OnDestroy {
25 subscriptions: Subscription[] = [];
27 startingTab: 'patron' | 'resource' | 'type' = 'patron';
28 startingPickupOrgs: OrgFamily = {primaryOrgId: this.auth.user().ws_ou(), includeDescendants: true};
30 @ViewChild('filterTabs', { static: true }) filterTabs: NgbNav;
31 @ViewChild('reservationsGrid', { static: true }) reservationsGrid: ReservationsGridComponent;
33 removeFilters: () => void;
36 private route: ActivatedRoute,
37 private router: Router,
38 private auth: AuthService,
39 private net: NetService,
40 private pcrud: PcrudService,
41 private store: ServerStoreService,
42 private toast: ToastService,
43 private patronValidator: PatronBarcodeValidator,
44 private resourceValidator: BookingResourceBarcodeValidator
46 this.store.getItem('eg.booking.manage.selected_org_family').then((pickupLibs) => {
48 this.startingPickupOrgs = pickupLibs;
54 this.filters = new FormGroup({
55 'pickupLibraries': new FormControl(this.startingPickupOrgs),
56 'patronBarcode': new FormControl('', [], [this.patronValidator.validate]),
57 'resourceBarcode': new FormControl('', [], [this.resourceValidator.validate]),
58 'resourceType': new FormControl(null),
61 const debouncing = 300;
63 this.subscriptions.push(
64 this.pickupLibraries.valueChanges.pipe(
65 ).subscribe(() => this.reservationsGrid.reloadGrid()));
67 this.subscriptions.push(
68 this.patronBarcode.statusChanges.pipe(
69 debounceTime(debouncing),
70 switchMap((status) => {
71 if ('VALID' === status) {
72 return this.net.request(
74 'open-ils.actor.get_barcodes',
75 this.auth.token(), this.auth.user().ws_ou(),
76 'actor', this.patronBarcode.value.trim()).pipe(
79 this.router.navigate(['/staff', 'booking', 'manage_reservations', 'by_patron', response[0].id])
82 this.toast.danger('No patron found with this barcode');
88 this.subscriptions.push(
89 this.resourceBarcode.statusChanges.pipe(
90 debounceTime(debouncing),
92 if ('VALID' === status) {
93 if (this.resourceBarcode.value) {
94 this.router.navigate(['/staff', 'booking', 'manage_reservations', 'by_resource', this.resourceBarcode.value]);
102 this.subscriptions.push(
103 this.resourceType.valueChanges.pipe(
106 this.router.navigate(['/staff', 'booking', 'manage_reservations', 'by_resource_type', value.id]);
108 this.removeFilters();
113 this.subscriptions.push(
114 this.pickupLibraries.valueChanges.pipe(
115 tap((value) => this.store.setItem('eg.booking.manage.selected_org_family', value))
118 this.removeFilters = () => {
119 this.router.navigate(['/staff', 'booking', 'manage_reservations']);
123 this.route.paramMap.pipe(
124 switchMap((params: ParamMap) => {
125 this.patronId = params.has('patron_id') ? +params.get('patron_id') : null;
126 this.filters.patchValue({resourceBarcode: params.get('resource_barcode')}, {emitEvent: false});
127 this.filters.patchValue({resourceType: {id: +params.get('resource_type_id')}}, {emitEvent: false});
130 return this.pcrud.search('au', {
135 flesh_fields: {'au': ['card']}
138 this.filters.patchValue({patronBarcode: resp.card().barcode()});
140 (err: unknown) => { console.debug(err); }
142 } else if (this.resourceBarcode.value) {
143 this.startingTab = 'resource';
144 return this.pcrud.search('brsrc',
145 {'barcode' : this.resourceBarcode.value}, {'limit': 1}).pipe(
147 this.resourceId = res.id();
148 }, (err: unknown) => {
149 this.resourceId = -1;
150 this.toast.danger('No resource found with this barcode');
152 } else if (this.resourceType.value) {
153 this.startingTab = 'type';
162 get pickupLibraries() {
163 return this.filters.get('pickupLibraries');
165 get patronBarcode() {
166 return this.filters.get('patronBarcode');
168 get resourceBarcode() {
169 return this.filters.get('resourceBarcode');
172 return this.filters.get('resourceType');
174 get pickupLibrariesForGrid() {
175 return this.pickupLibraries.value ?
176 this.pickupLibraries.value.orgIds :
177 [this.auth.user().ws_ou()];
179 get resourceTypeForGrid() {
180 return this.resourceType.value ? this.resourceType.value.id : null;
183 ngOnDestroy(): void {
184 this.subscriptions.forEach((subscription) => {
185 subscription.unsubscribe();