11import React , { Component } from 'react'
2- import { IfElse , Markdown , DetailGrid , Detail } from '../shared/Tools'
2+ import { IfElse , Markdown , DetailGrid , Detail , Tick } from '../shared/Tools'
33import Modal from '../shared/Modal'
44
5+ const LS_KEY = '_tcs_user_data_'
6+
57class AptModal extends Component {
68 constructor ( props ) {
79 super ( props )
810 this . apt_id = parseInt ( this . props . id , 10 )
911 this . login = this . login . bind ( this )
1012 this . process_message = this . process_message . bind ( this )
1113 this . update_session = this . update_session . bind ( this )
14+ this . check_client = this . check_client . bind ( this )
1215 this . signout = this . signout . bind ( this )
1316 this . book = this . book . bind ( this )
17+ this . get_srs = this . get_srs . bind ( this )
1418 this . state = {
19+ apt : props . appointments && props . appointments . find ( a => a . id === this . apt_id ) ,
1520 signature : null ,
1621 sso_data : null ,
1722 display_data : null ,
1823 appointment_attendees : null ,
1924 new_student : null ,
25+ booking_allowed : false ,
26+ extra_attendees : 0 ,
2027 }
2128 }
2229
2330 componentDidMount ( ) {
2431 window . addEventListener ( 'message' , this . process_message , false )
25- this . update_session ( window . sessionStorage . __tcs_user_data )
32+ this . update_session ( window . sessionStorage [ LS_KEY ] )
33+ }
34+
35+ componentWillReceiveProps ( nextProps ) {
36+ const new_apt = nextProps . appointments && nextProps . appointments . find ( a => a . id === this . apt_id )
37+ if ( this . state . apt && new_apt && this . state . apt . attendees_count !== new_apt . attendees_count ) {
38+ // clear temporary extra_attendees
39+ this . setState ( { extra_attendees : 0 } )
40+ }
41+ this . setState ( { apt : new_apt } )
2642 }
2743
2844 login ( ) {
@@ -34,11 +50,11 @@ class AptModal extends Component {
3450 const success = this . update_session ( event . data )
3551 if ( success ) {
3652 event . source . close ( )
37- window . sessionStorage . __tcs_user_data = event . data
53+ window . sessionStorage [ LS_KEY ] = event . data
3854 }
3955 }
4056
41- async update_session ( raw_data ) {
57+ update_session ( raw_data ) {
4258 let data
4359 try {
4460 data = JSON . parse ( raw_data )
@@ -47,33 +63,51 @@ class AptModal extends Component {
4763 }
4864 data . display_data = JSON . parse ( data . sso_data )
4965 this . setState ( data )
66+ this . check_client ( data )
67+ return true
68+ }
5069
70+ async check_client ( data ) {
71+ data = data || this . state
5172 const args = { signature : data . signature , sso_data : data . sso_data }
52- this . props . root . requests . get ( 'check-client' , args , { set_app_state : false } ) . then ( data => {
53- this . setState ( { appointment_attendees : data . appointment_attendees } )
54- } ) . catch ( e => {
73+ try {
74+ const r = await this . props . root . requests . get ( 'check-client' , args , { set_app_state : false } )
75+ this . setState ( { appointment_attendees : r . appointment_attendees [ this . apt_id ] || [ ] , booking_allowed : true } )
76+ } catch ( e ) {
5577 if ( e . xhr . status === 403 ) {
56- console . log ( 'got error in update_sesion:' , e )
5778 this . signout ( )
5879 } else {
5980 this . props . root . setState ( { error : e . msg } )
6081 }
61- } )
62- return true
82+ }
6383 }
6484
6585 async book ( student_id ) {
66- console . log ( 'book:' , student_id )
86+ this . setState ( { booking_allowed : false } )
6787 const data = { appointment : this . apt_id }
6888 if ( student_id ) {
6989 data . student_id = student_id
7090 } else {
7191 data . student_name = this . state . new_student
72- this . setState ( { new_student : null } )
7392 }
7493 const url = `book-appointment?signature=${ this . state . signature } &sso_data=${ encodeURIComponent ( this . state . sso_data ) } `
75- const r = await this . props . root . requests . post ( url , data )
76- console . log ( r )
94+ await this . props . root . requests . post ( url , data )
95+ this . props . update_apts ( )
96+ if ( ! student_id ) {
97+ const display_data = Object . assign ( { } , this . state . display_data )
98+ student_id = 999999999
99+ display_data . srs [ student_id ] = data . student_name
100+ this . setState ( { new_student : null , display_data} )
101+ window . sessionStorage . removeItem ( LS_KEY ) // force new login when opening appointment to update students
102+ }
103+ const appointment_attendees = this . state . appointment_attendees . slice ( )
104+ appointment_attendees . push ( student_id )
105+ this . setState ( {
106+ booking_allowed : true ,
107+ extra_attendees : this . state . extra_attendees + 1 ,
108+ appointment_attendees
109+ } )
110+ setTimeout ( ( ) => this . props . update_apts ( ) , 5000 )
77111 }
78112
79113 signout ( ) {
@@ -82,20 +116,32 @@ class AptModal extends Component {
82116 sso_data : null ,
83117 display_data : null ,
84118 appointment_attendees : null ,
119+ new_student : null ,
120+ booking_allowed : false ,
121+ } )
122+ window . sessionStorage . removeItem ( LS_KEY )
123+ }
124+
125+ get_srs ( ) {
126+ return this . state . display_data && Object . entries ( this . state . display_data . srs ) . map ( ( [ k , name ] ) => {
127+ const sr_id = parseInt ( k , 10 )
128+ return {
129+ id : sr_id ,
130+ name : name ,
131+ already_on_apt : this . state . appointment_attendees && this . state . appointment_attendees . includes ( sr_id )
132+ }
85133 } )
86- window . sessionStorage . removeItem ( '__tcs_user_data' )
87134 }
88135
89136 render ( ) {
90- console . log ( this . state )
91137 if ( ! this . props . got_data ) {
92138 return (
93139 < Modal history = { this . props . history } title = '' >
94140 < p > Loading...</ p >
95141 </ Modal >
96142 )
97143 }
98- const apt = this . props . appointments . find ( a => a . id === this . apt_id )
144+ const apt = this . state . apt
99145 if ( ! apt ) {
100146 return (
101147 < Modal history = { this . props . history } title = "Appointment not Found" >
@@ -109,6 +155,9 @@ class AptModal extends Component {
109155 { apt . topic }
110156 </ span >
111157 )
158+ const srs = this . get_srs ( )
159+ const spaces_available = apt . attendees_max - apt . attendees_count - this . state . extra_attendees
160+ const booking_allowed = this . state . booking_allowed && spaces_available > 0
112161 return (
113162 < Modal history = { this . props . history } title = { title } last_url = { this . props . last_url } flex = { false } >
114163 < div className = "tcs-modal-flex" >
@@ -123,7 +172,7 @@ class AptModal extends Component {
123172 < Detail label = "Job" >
124173 { apt . service_name }
125174 </ Detail >
126- { apt . attendees_max && < Detail label = "Spaces Available" > { apt . attendees_max - apt . attendees_count } </ Detail > }
175+ { apt . attendees_max && < Detail label = "Spaces Available" > { spaces_available } </ Detail > }
127176 < Detail label = "Start" className = "tcs-new-line" > { this . props . config . format_datetime ( apt . start ) } </ Detail >
128177 < Detail label = "Finish" > { this . props . config . format_datetime ( apt . finish ) } </ Detail >
129178 { apt . location && < Detail label = "Location" > { apt . location } </ Detail > }
@@ -145,24 +194,42 @@ class AptModal extends Component {
145194 < div className = "tcs-book" >
146195 < IfElse v = { this . state . display_data } >
147196 < div >
148- { Object . entries ( this . state . display_data . srs ) . map ( ( [ k , v ] ) => (
149- < div key = { k } >
150- { v }
197+ { srs && (
198+ < div className = "tcs-book-existing" >
199+ < div > Add your existing Students to the lesson</ div >
200+ { srs . map ( ( { id, name, already_on_apt} ) => (
201+ < div key = { id } className = "tcs-book-item" >
202+ < div className = "tcs-existing-name" >
203+ { name }
204+ </ div >
205+ { already_on_apt ? (
206+ < div className = "tcs-already-added" >
207+ Added < Tick />
208+ </ div >
209+ ) : (
210+ < button className = "tcs-button tcs-add-button"
211+ onClick = { ( ) => this . book ( id ) }
212+ disabled = { ! booking_allowed || already_on_apt } >
213+ { this . props . root . get_text ( 'add_to_lesson' ) }
214+ </ button >
215+ ) }
216+ </ div >
217+ ) ) }
151218 </ div >
152- ) ) }
219+ ) }
153220 < div className = "tcs-book-new" >
154- < div > Add a new Student to the lesson: </ div >
155- < div >
221+ < div > Add a new Student to the lesson</ div >
222+ < div className = "tcs-book-item" >
156223 < input type = "text"
157224 className = "tcs-default-input"
158225 placeholder = "Student Name"
159226 required = { true }
160227 maxLength = { 255 }
161228 value = { this . state . new_student || '' }
162229 onChange = { e => this . setState ( { new_student : e . target . value } ) } />
163- < button className = "tcs-button"
230+ < button className = "tcs-button tcs-add-button "
164231 onClick = { ( ) => this . book ( null ) }
165- disabled = { ! this . state . new_student } >
232+ disabled = { ! booking_allowed || ! this . state . new_student } >
166233 { this . props . root . get_text ( 'add_to_lesson' ) }
167234 </ button >
168235 </ div >
0 commit comments