4
4
5
5
import React from 'react' ;
6
6
import bind from 'bind-decorator' ;
7
+ import clsx from 'clsx' ;
7
8
8
9
import AccessCodeDialogButton from './AccessCodeDialogButton' ;
9
10
import AvatarDialogButton from './AvatarDialogButton' ;
10
11
import ConditionalLink from './ConditionalLink' ;
11
12
import ConditionalListItem from './ConditionalListItem' ;
12
13
import { Volunteer } from '../app/Volunteer' ;
14
+ import { VolunteerActivityInfo } from '../app/Event' ;
13
15
import slug from '../app/util/Slug' ;
14
16
15
17
import IconButton from '@material-ui/core/IconButton' ;
@@ -24,18 +26,38 @@ const styles = (theme: Theme) =>
24
26
link : {
25
27
textDecoration : 'none' ,
26
28
color : 'inherit' ,
27
- }
29
+ } ,
30
+
31
+ active : {
32
+ ...theme . activeSessionStyle ,
33
+ borderBottomWidth : 0 ,
34
+ } ,
35
+ unavailable : {
36
+ ...theme . pastSessionStyle ,
37
+ borderBottomWidth : 0 ,
38
+ filter : 'grayscale(80%)' ,
39
+ } ,
28
40
} ) ;
29
41
30
42
/**
31
43
* Properties accepted by the <Volunteer> element.
32
44
*/
33
45
interface Properties {
46
+ /**
47
+ * Indicates that the volunteer is active.
48
+ */
49
+ active ?: boolean ;
50
+
34
51
/**
35
52
* The volunteer for whom this element is being rendered.
36
53
*/
37
54
volunteer : Volunteer ;
38
55
56
+ /**
57
+ * Optional activity information that will be displayed for status-based list items.
58
+ */
59
+ volunteerActivityInfo ?: VolunteerActivityInfo ;
60
+
39
61
/**
40
62
* Type of list item that should be rendered. The contents of the list item will automatically
41
63
* be compiled based on the |volunteer| property.
@@ -46,6 +68,11 @@ interface Properties {
46
68
*/
47
69
type : "header" | "status" ;
48
70
71
+ /**
72
+ * Indicates that the volunteer is unavailable.
73
+ */
74
+ unavailable ?: boolean ;
75
+
49
76
/**
50
77
* An event that is to be invoked if the photo of the |volunteer| has been updated. The ability
51
78
* to change the photo will be enabled based on whether this property has been set.
@@ -58,6 +85,29 @@ interface Properties {
58
85
* property can be used to influence which subset of information should be presented.
59
86
*/
60
87
class VolunteerListItem extends React . PureComponent < Properties & WithStyles < typeof styles > > {
88
+ /**
89
+ * Compiles the status line for the volunteer based on the available information.
90
+ */
91
+ compileVolunteerStatusLine ( ) : string {
92
+ const { volunteer, volunteerActivityInfo } = this . props ;
93
+
94
+ let status = volunteer . title ;
95
+
96
+ if ( volunteerActivityInfo && volunteerActivityInfo . currentShift ) {
97
+ const { currentShift } = volunteerActivityInfo ;
98
+
99
+ const until = ' until ' + currentShift . endTime . format ( 'HH:mm' ) ;
100
+
101
+ if ( currentShift . isUnavailable ( ) ) {
102
+ status += ' • unavailable' + until ;
103
+ } else if ( currentShift . isEvent ( ) ) {
104
+ status += ' • ' + currentShift . event . sessions [ 0 ] . name + until ;
105
+ }
106
+ }
107
+
108
+ return status ;
109
+ }
110
+
61
111
/**
62
112
* Opens the dialer on the device (if any) to make a phone call to this volunteer. Should only
63
113
* be called when the volunteer has a known telephone number.
@@ -75,7 +125,7 @@ class VolunteerListItem extends React.PureComponent<Properties & WithStyles<type
75
125
}
76
126
77
127
render ( ) {
78
- const { classes, onPictureUpdated, type, volunteer } = this . props ;
128
+ const { active , classes, onPictureUpdated, type, unavailable , volunteer } = this . props ;
79
129
80
130
let location : string | undefined = '/volunteers/' + slug ( volunteer . name ) ;
81
131
@@ -97,20 +147,21 @@ class VolunteerListItem extends React.PureComponent<Properties & WithStyles<type
97
147
) ;
98
148
break ;
99
149
case 'status' :
100
- // TODO: Include the volunteer's current shift.
101
- secondary = volunteer . title ;
150
+ secondary = this . compileVolunteerStatusLine ( ) ;
102
151
break ;
103
152
default :
104
153
throw new Error ( 'Invalid type value: ' + type ) ;
105
154
}
106
155
107
156
return (
108
157
< ConditionalLink className = { classes . link } to = { location } >
109
- < ConditionalListItem button = { ! ! location } >
158
+ < ConditionalListItem button = { ! ! location } className = { clsx ( active && classes . active , unavailable && classes . unavailable ) } >
110
159
< AvatarDialogButton volunteer = { volunteer } onPictureUpdated = { onPictureUpdated } />
111
160
< ListItemText
112
161
primary = { primary }
113
- secondary = { secondary } />
162
+ primaryTypographyProps = { { noWrap : true } }
163
+ secondary = { secondary }
164
+ secondaryTypographyProps = { { noWrap : true } } />
114
165
{ actions }
115
166
</ ConditionalListItem >
116
167
</ ConditionalLink >
0 commit comments