87888e2e9ab2cb3265938ea270093c7a51481fd7
[evergreen-equinox.git] / Open-ILS / src / eg2 / src / app / staff / share / patron / summary.component.ts
1 import {Component, OnInit, Input} from '@angular/core';
2 import {Router, ActivatedRoute, ParamMap} from '@angular/router';
3 import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
4 import {OrgService} from '@eg/core/org.service';
5 import {IdlObject} from '@eg/core/idl.service';
6 import {NetService} from '@eg/core/net.service';
7 import {PrintService} from '@eg/share/print/print.service';
8 import {PatronService, PatronSummary} from './patron.service';
9 import {ServerStoreService} from '@eg/core/server-store.service';
10
11 @Component({
12   templateUrl: 'summary.component.html',
13   styleUrls: ['summary.component.css'],
14   selector: 'eg-patron-summary'
15 })
16 export class PatronSummaryComponent implements OnInit {
17
18     private _summary: PatronSummary;
19     @Input() set summary(s: PatronSummary) {
20         if (s && this._summary && s.id !== this._summary.id) {
21             this.showDob = this.showDobDefault;
22         }
23         this._summary = s;
24     }
25
26     get summary(): PatronSummary {
27         return this._summary;
28     }
29
30     showDobDefault = false;
31     showDob = false;
32
33     constructor(
34         private org: OrgService,
35         private net: NetService,
36         private printer: PrintService,
37         private serverStore: ServerStoreService,
38         public patronService: PatronService
39     ) {}
40
41     ngOnInit() {
42         this.serverStore.getItem('circ.obscure_dob').then(hide => {
43             this.showDobDefault = this.showDob = !hide;
44         });
45     }
46
47     p(): IdlObject { // patron shorthand
48         return this.summary ? this.summary.patron : null;
49     }
50
51     hasPrefName(): boolean {
52         if (this.p()) {
53             return (
54                 this.p().pref_first_given_name() ||
55                 this.p().pref_second_given_name() ||
56                 this.p().pref_family_name()
57             );
58         }
59     }
60
61     printAddress(addr: IdlObject) {
62         this.printer.print({
63             templateName: 'patron_address',
64             contextData: {
65                 patron: this.p(),
66                 address: addr
67             },
68             printContext: 'default'
69         });
70     }
71
72     copyAddress(addr: IdlObject) {
73         // Note navigator.clipboard requires special permissions.
74         // This is hinky, but gets the job done without the perms.
75
76         const node = document.getElementById(
77             `patron-address-copy-${addr.id()}`) as HTMLTextAreaElement;
78
79         // Un-hide the textarea just long enough to copy its data.
80         // Using node.style instead of *ngIf in hopes it
81         // will be quicker, so the user never sees the textarea.
82         node.style.visibility = 'visible';
83         node.style.display = 'block';
84         node.focus();
85         node.select();
86
87         if (!document.execCommand('copy')) {
88             console.error('Copy command failed');
89         }
90
91         node.style.visibility = 'hidden';
92         node.style.display = 'none';
93     }
94
95     orgSn(orgId: number): string {
96         const org = this.org.get(orgId);
97         return org ? org.shortname() : '';
98     }
99
100     patronStatusColor(): string {
101
102         const patron = this.p();
103
104         if (patron.barred() === 't') {
105             return 'PATRON_BARRED';
106         }
107
108         if (patron.active() === 'f') {
109             return 'PATRON_INACTIVE';
110         }
111
112         if (this.summary.stats.fines.balance_owed > 0) {
113            return 'PATRON_HAS_BILLS';
114         }
115
116         if (this.summary.stats.checkouts.overdue > 0) {
117             return 'PATRON_HAS_OVERDUES';
118         }
119
120         if (patron.notes().length > 0) {
121             return 'PATRON_HAS_NOTES';
122         }
123
124         if (this.summary.stats.checkouts.lost > 0) {
125             return 'PATRON_HAS_LOST';
126         }
127
128         let penalty: string;
129         let penaltyCount = 0;
130
131         patron.standing_penalties().some(p => {
132             penaltyCount++;
133
134             if (p.standing_penalty().staff_alert() === 't' ||
135                 p.standing_penalty().block_list()) {
136                 penalty = 'PATRON_HAS_STAFF_ALERT';
137                 return true;
138             }
139
140             const name = p.standing_penalty();
141
142             switch (name) {
143                 case 'PATRON_EXCEEDS_CHECKOUT_COUNT':
144                 case 'PATRON_EXCEEDS_OVERDUE_COUNT':
145                 case 'PATRON_EXCEEDS_FINES':
146                     penalty = name;
147                     return true;
148             }
149         });
150
151         if (penalty) { return penalty; }
152
153         if (penaltyCount === 1) {
154             return 'ONE_PENALTY';
155         } else if (penaltyCount > 1) {
156             return 'MULTIPLE_PENALTIES';
157         }
158
159         if (patron.juvenile() === 't') {
160             return 'PATRON_JUVENILE';
161         }
162
163         return 'NO_PENALTIES';
164     }
165 }
166