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} from 'rxjs';
5 import {debounceTime, single, tap, switchMap} from 'rxjs/operators';
6 import {NgbTabset} 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: NgbTabset;
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).pipe(
79 this.router.navigate(['/staff', 'booking', 'manage_reservations', 'by_patron', response[0].id])
82 this.toast.danger('No patron found with this barcode');
87 this.subscriptions.push(
88 this.resourceBarcode.statusChanges.pipe(
89 debounceTime(debouncing),
91 if ('VALID' === status) {
92 if (this.resourceBarcode.value) {
93 this.router.navigate(['/staff', 'booking', 'manage_reservations', 'by_resource', this.resourceBarcode.value]);
101 this.subscriptions.push(
102 this.resourceType.valueChanges.pipe(
105 this.router.navigate(['/staff', 'booking', 'manage_reservations', 'by_resource_type', value.id]);
107 this.removeFilters();
112 this.subscriptions.push(
113 this.pickupLibraries.valueChanges.pipe(
114 tap((value) => this.store.setItem('eg.booking.manage.selected_org_family', value))
117 this.removeFilters = () => {
118 this.router.navigate(['/staff', 'booking', 'manage_reservations']);
122 this.route.paramMap.pipe(
123 switchMap((params: ParamMap) => {
124 this.patronId = params.has('patron_id') ? +params.get('patron_id') : null;
125 this.filters.patchValue({resourceBarcode: params.get('resource_barcode')}, {emitEvent: false});
126 this.filters.patchValue({resourceType: {id: +params.get('resource_type_id')}}, {emitEvent: false});
129 return this.pcrud.search('au', {
134 flesh_fields: {'au': ['card']}
137 this.filters.patchValue({patronBarcode: resp.card().barcode()}); },
138 (err) => { console.debug(err); }
140 } else if (this.resourceBarcode.value) {
141 this.startingTab = 'resource';
142 return this.pcrud.search('brsrc',
143 {'barcode' : this.resourceBarcode.value}, {'limit': 1}).pipe(
145 this.resourceId = res.id();
147 this.resourceId = -1;
148 this.toast.danger('No resource found with this barcode');
150 } else if (this.resourceType.value) {
151 this.startingTab = 'type';
160 get pickupLibraries() {
161 return this.filters.get('pickupLibraries');
163 get patronBarcode() {
164 return this.filters.get('patronBarcode');
166 get resourceBarcode() {
167 return this.filters.get('resourceBarcode');
170 return this.filters.get('resourceType');
172 get pickupLibrariesForGrid() {
173 return this.pickupLibraries.value ?
174 this.pickupLibraries.value.orgIds :
175 [this.auth.user().ws_ou()];
177 get resourceTypeForGrid() {
178 return this.resourceType.value ? this.resourceType.value.id : null;
181 ngOnDestroy(): void {
182 this.subscriptions.forEach((subscription) => {
183 subscription.unsubscribe();