1 import {Component, Input, Output, OnInit, ViewChild, EventEmitter} from '@angular/core';
2 import {FormGroup, FormControl, Validators} from '@angular/forms';
3 import {Router} from '@angular/router';
4 import {Observable, of} from 'rxjs';
5 import {switchMap, single, startWith, tap} from 'rxjs/operators';
6 import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
7 import {AuthService} from '@eg/core/auth.service';
8 import {FormatService} from '@eg/core/format.service';
9 import {IdlObject} from '@eg/core/idl.service';
10 import {NetService} from '@eg/core/net.service';
11 import {OrgService} from '@eg/core/org.service';
12 import {PcrudService} from '@eg/core/pcrud.service';
13 import {DialogComponent} from '@eg/share/dialog/dialog.component';
14 import {notBeforeMomentValidator} from '@eg/share/validators/not_before_moment_validator.directive';
15 import {PatronBarcodeValidator} from '@eg/share/validators/patron_barcode_validator.directive';
16 import {PatronSearchDialogComponent} from '@eg/staff/share/patron/search-dialog.component';
17 import {ToastService} from '@eg/share/toast/toast.service';
18 import {AlertDialogComponent} from '@eg/share/dialog/alert.component';
19 import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
20 import * as moment from 'moment-timezone';
21 import { datesInOrderValidator } from '@eg/share/validators/dates_in_order_validator.directive';
24 selector: 'eg-create-reservation-dialog',
25 templateUrl: './create-reservation-dialog.component.html'
28 export class CreateReservationDialogComponent
29 extends DialogComponent implements OnInit {
31 @Input() targetResource: number;
32 @Input() targetResourceBarcode: string;
33 @Input() targetResourceType: ComboboxEntry;
34 @Input() patronId: number;
35 @Input() attributes: number[] = [];
36 @Input() resources: IdlObject[] = [];
37 @Output() reservationRequestCompleted: EventEmitter<boolean>;
40 patron$: Observable<{first_given_name: string, second_given_name: string, family_name: string}>;
42 timezone: string = this.format.wsOrgTimezone;
43 pickupLibraryUsesDifferentTz: boolean;
45 public disableOrgs: () => number[];
46 addBresv$: () => Observable<any>;
47 @ViewChild('fail', { static: true }) fail: AlertDialogComponent;
48 @ViewChild('patronSearch') patronSearch: PatronSearchDialogComponent;
50 handlePickupLibChange: ($event: IdlObject) => void;
53 private auth: AuthService,
54 private format: FormatService,
55 private net: NetService,
56 private org: OrgService,
57 private pcrud: PcrudService,
58 private router: Router,
59 private modal: NgbModal,
60 private pbv: PatronBarcodeValidator,
61 private toast: ToastService
64 this.reservationRequestCompleted = new EventEmitter<boolean>();
69 this.create = new FormGroup({
70 'patronBarcode': new FormControl('',
71 [Validators.required],
74 'emailNotify': new FormControl(true),
75 'startTime': new FormControl(null, notBeforeMomentValidator(moment().add('15', 'minutes'))),
76 'endTime': new FormControl(),
77 'resourceList': new FormControl(),
78 'note': new FormControl(),
79 }, [datesInOrderValidator(['startTime', 'endTime'])]
82 this.pcrud.search('au', {id: this.patronId}, {
84 flesh_fields: {'au': ['card']}
86 this.create.patchValue({patronBarcode: usr.card().barcode()})
90 this.addBresv$ = () => {
91 let selectedResourceId = this.targetResource ? [this.targetResource] : null;
92 if (!selectedResourceId &&
93 this.resourceListSelection !== null &&
94 'any' !== this.resourceListSelection.id) {
95 selectedResourceId = [this.resourceListSelection.id];
97 return this.net.request(
99 'open-ils.booking.reservations.create',
101 this.patronBarcode.value.trim(),
104 this.targetResourceType.id,
106 this.attributes.filter(Boolean),
110 next: (response) => {
111 if ('ilsevent' in response) {
112 console.warn(response);
115 this.toast.success('Reservation successfully created');
116 console.debug(response);
119 }, error: (response: unknown) => {
120 console.warn(response);
122 }, complete: () => this.reservationRequestCompleted.emit(true)
126 this.handlePickupLibChange = ($event) => {
127 this.pickupLibId = $event.id();
128 this.org.settings('lib.timezone', this.pickupLibId).then((tz) => {
129 this.timezone = tz['lib.timezone'] || this.format.wsOrgTimezone;
130 this.pickupLibraryUsesDifferentTz = (tz['lib.timezone'] && (this.format.wsOrgTimezone !== tz['lib.timezone']));
134 this.disableOrgs = () => this.org.filterList( { canHaveVolumes : false }, true);
136 this.patron$ = this.patronBarcode.statusChanges.pipe(
137 startWith({first_given_name: '', second_given_name: '', family_name: ''}),
139 if ('VALID' === this.patronBarcode.status) {
140 return this.net.request(
142 'open-ils.actor.get_barcodes',
144 this.auth.user().ws_ou(),
145 'actor', this.patronBarcode.value.trim()).pipe(
147 switchMap((result) => {
148 return this.pcrud.retrieve('au', result[0]['id']).pipe(
151 first_given_name: au.first_given_name(),
152 second_given_name: au.second_given_name(),
153 family_name: au.family_name()});
160 first_given_name: '',
161 second_given_name: '',
169 setDefaultTimes(times: moment.Moment[], granularity: number) {
170 this.create.patchValue({startTime: moment.min(times),
171 endTime: moment.max(times).clone().add(granularity, 'minutes')
175 openPatronReservations = (): void => {
178 'open-ils.actor.get_barcodes',
180 this.auth.user().ws_ou(),
181 'actor', this.patronBarcode.value
182 ).subscribe((patron) => this.router.navigate(['/staff', 'booking', 'manage_reservations', 'by_patron', patron[0]['id']]));
185 addBresvAndOpenPatronReservations = (): void => {
187 .subscribe(() => this.openPatronReservations());
191 this.patronSearch.open({size: 'xl'}).toPromise().then(
193 if (!patrons || patrons.length === 0) { return; }
194 const user = patrons[0];
195 this.create.patchValue({patronBarcode: user.card().barcode()});
201 return this.create.get('emailNotify').value;
205 return this.create.get('note').value;
208 get patronBarcode() {
209 return this.create.get('patronBarcode');
212 get resourceListSelection() {
213 return this.create.get('resourceList').value;
216 get selectedTimes() {
217 return [this.create.get('startTime').value.toISOString(),
218 this.create.get('endTime').value.toISOString()];