trc-client-core
Version:
The core of the TRC Client
229 lines (215 loc) • 9.47 kB
JSX
import CancellationPolicy from 'trc-client-core/src/copy/_partials/CancellationPolicy.md';
import ClassBuilder from 'bd-stampy/utils/ClassBuilder';
import Col from 'trc-client-core/src/components/Col';
import Grid from 'trc-client-core/src/components/Grid';
import Icon from 'trc-client-core/src/components/Icon';
import InformationModal from 'trc-client-core/src/components/InformationModal';
import Markdown from 'trc-client-core/src/components/Markdown';
import ModalManager from 'trc-client-core/src/Modal/ModalManager';
import moment from 'moment';
import React from 'react';
import RegistrationActions from 'trc-client-core/src/course/RegistrationActions';
import Select from 'trc-client-core/src/components/Select';
import Site from 'trc-client-core/src/constants/Site';
import SubstitutionPolicy from 'trc-client-core/src/copy/_partials/SubstitutionPolicy.md';
import Table from 'bd-stampy/components/Table';
import Time from 'trc-client-core/src/components/Time';
import UserStore from 'trc-client-core/src/user/UserStore';
import {Link} from 'react-router';
function participantFrom(pp) {
return function (reg) {
return pp.get('participantId') === reg.get('participantId');
};
}
var SoRegistrationBox = React.createClass({
displayName: 'SoRegistrationBox',
mixins: [
require('trc-client-core/src/course/RegistrationMixin')
],
propTypes: {
type: React.PropTypes.oneOf(['registration', 'confirm']),
registrations: React.PropTypes.object,
candidates: React.PropTypes.object.isRequired,
soData: React.PropTypes.object.isRequired
},
getDefaultProps() {
return {
type: 'registration'
};
},
getInitialState() {
return {
dirty: false
};
},
getRefuseWaitlist() {
var {course} = this.props;
return (course.get('canWaitlist') === false && this.getRemainingPlaces() <= 0)
},
onShowCancellationPolicy() {
var concatMarkdown = CancellationPolicy.__content + '\n' + SubstitutionPolicy.__content;
ModalManager.showModal(InformationModal, {
title: 'Cancellation Policy',
children: <Markdown context={Site[UserStore.get('site')]} html={concatMarkdown}/>
});
},
onAddRegistration(ee, details) {
// participantId, selectionArray
if(details.valueArray && !details.valueArray.disabled) {
RegistrationActions.addRegistration(details.value, this.props.soData.get('soId'));
}
this.makeDirty();
},
onRemoveRegistration(participantId) {
RegistrationActions.updateRegistration(participantId, this.props.soData.get('soId'));
this.makeDirty();
},
getRemainingPlaces() {
return this.remainingPlaces(this.props.registrations, this.props.soData);
},
onCheckConfirm(ee) {
if (!this.state.dirty) {
ee.preventDefault()
}
},
makeDirty() {
this.setState({dirty: true});
},
render(){
return this[`render_${this.props.type}`]();
},
render_confirm() {
var {soData} = this.props;
return (
<div className="margin-bottom3">
<h3 className="hug-top">
<Time type="short">{soData.get('soStartDate')}</Time>
<span className="right">{soData.get('facility')}</span>
</h3>
<p>{this.renderCloseStartDateWarning()}</p>
<ul>
{this.renderEnrollmentList(this.props.cancellations)}
{this.renderEnrollmentList(this.props.registrations)}
</ul>
</div>
);
},
render_registration() {
var {soData} = this.props;
return (
<div className="SoRegistrationBox Widget padding2 margin-bottom3 clearfix">
<h2 className="hug-top">
<Time type="short">{soData.get('soStartDate')}</Time>
<span className="right">{soData.get('facility')}</span>
</h2>
<Grid>
<Col>
<p>
{this.renderCloseStartDateWarning()}
{this.renderFullWarning()}
</p>
<Table modifier="data">
<tr>
<td>Start Date:</td>
<td><Time type="full" tz={soData.get('soTimeZone')}>{soData.get('soStartDate')}</Time></td>
</tr>
<tr>
<td>Remaining places:</td>
<td>{this.renderRemainingPlaces()}</td>
</tr>
<tr>
<td>Facility:</td>
<td>{soData.get('facilityDesc')}</td>
</tr>
</Table>
</Col>
<Col>
<div>
<ul>
{this.renderEnrollmentList(this.props.cancellations)}
{this.renderEnrollmentList(this.props.registrations)}
</ul>
<Select
name="test"
placeholder="Search for staff."
disabled={this.getRefuseWaitlist()}
onChange={this.onAddRegistration}
options={this.renderStaffOptions()}
/>
</div>
</Col>
</Grid>
<Link to={`/course/${this.props.courseCode}/confirm_registration`} className="Button right" onClick={this.onCheckConfirm} disabled={!this.state.dirty}>Confirm all Registrations</Link>
</div>
);
},
renderCloseStartDateWarning() {
if(moment().add(21, "days").isAfter(this.props.soData.get('soStartDate'))) {
return <em className="block">Course is within 21 days. Please read <a onClick={this.onShowCancellationPolicy} className="link">Cancellation Policy</a></em>;
}
},
renderFullWarning() {
if(this.getRefuseWaitlist()) {
return <em className="block">Course is currently full.</em>
}
if(this.getRemainingPlaces() < 1) {
return <em className="block">Course is currently full. Only waitlisting available</em>;
}
},
renderRemainingPlaces() {
return (this.getRemainingPlaces() > 0) ? this.getRemainingPlaces() : <span className="t-red">FULL</span>;
},
renderEnrollmentList(list) {
if(list) {
return list.sortBy(reg => reg.get('status')).map((reg, key) => {
var registrationStatus = this.currentStatus(reg, key, this.props.soData);
var classes = new ClassBuilder('RegistrationList_item').is(true, registrationStatus);
if(!registrationStatus) {
classes.add('is-ENROLL');
}
if(this.props.type === 'confirm') {
if(registrationStatus === 'ENROLL' || registrationStatus === 'WAITLIST') {
classes.add('is-old');
}
}
var participant = this.props.candidates.get(reg.get('participantId'));
return (
<li className={classes.className} key={participant.get('participantId')}>
{this.renderRegistrationStatus(reg, registrationStatus)}
<span className="RegistrationList_name">{participant.get('firstName')} {participant.get('lastName')}</span>
</li>
);
}).toJS();
}
},
renderRegistrationStatus(reg, registrationStatus) {
var button = <Icon onClick={this.onRemoveRegistration.bind(null, reg.get('participantId'))} className="RegistrationList_remove" hexCode="E014" size="small" />;
if(registrationStatus === 'UNENROLL' || registrationStatus === 'UNWAITLIST') {
button = <span onClick={this.onRemoveRegistration.bind(null, reg.get('participantId'))} className="RegistrationList_remove">undo</span>;
}
var prettyTable = {
ENROLL: 'Currently enrolled',
UNENROLL: 'Cancellation of enrolment',
UNWAITLIST: 'Cancellation of waitlist',
WAITLIST: 'Currently waitlisted',
WAITLISTING: 'Will be waitlisted'
};
return <span className="right">
<span className="RegistrationList_status" >{prettyTable[registrationStatus] || 'New Enrolment'}</span>
{(this.props.type === 'registration') ? button : null}
</span>;
},
renderStaffOptions() {
return this.props.candidates.toList()
.map((pp) => {
return {
value: pp.get('participantId'),
label: `${pp.get('firstName')} ${pp.get('lastName')}`,
disabled: this.props.allRegistrations.find(participantFrom(pp)) ? true : false
};
})
.sortBy(ii => ii.label)
.toJS();
}
});
module.exports = SoRegistrationBox;