Skip to content

Commit

Permalink
- more support for multiple years in the registration app
Browse files Browse the repository at this point in the history
  • Loading branch information
bcholmes committed Jun 15, 2022
1 parent fbfea22 commit e209d5c
Show file tree
Hide file tree
Showing 19 changed files with 552 additions and 93 deletions.
15 changes: 13 additions & 2 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "code-sandbox-examples",
"name": "Wiscon Online Registration",
"version": "0.1.0",
"private": true,
"dependencies": {
Expand All @@ -8,6 +8,7 @@
"axios": "^0.22.0",
"bootstrap": "^4.6.0",
"bootstrap-icons": "1.7.1",
"dayjs": "1.10.7",
"downloadjs": "1.4.7",
"react": "^17.0.2",
"react-bootstrap": "^1.6.3",
Expand Down
112 changes: 112 additions & 0 deletions client/src/component/conSelection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React, { Component } from 'react';
import axios from 'axios';

import Modal from 'react-bootstrap/Modal';
import store from '../state/store';
import SimpleAlert from './simpleAlert';
import { connect } from 'react-redux';
import Button from 'react-bootstrap/esm/Button';
import Spinner from 'react-bootstrap/esm/Spinner';
import { setConList } from '../state/conActions';

import dayjs from "dayjs";
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import advancedFormat from "dayjs/plugin/advancedFormat"
import customParseFormat from "dayjs/plugin/customParseFormat"
dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.extend(customParseFormat);
dayjs.extend(advancedFormat);

class ConSelection extends Component {

constructor(props) {
super(props);

this.state = {
loading: this.props.conList == null,
message: null
}
}

componentDidMount() {
if (this.state.loading) {
this.fetchCons();
}
}

render() {
return <Modal show={this.props.show} onHide={() => this.props.onClose(null)} size="lg">
<Modal.Header closeButton>
<Modal.Title>Con Selection</Modal.Title>
</Modal.Header>
<Modal.Body>
<SimpleAlert message={this.state.message} />
<p>Choose which con you want to work with.</p>
{this.renderConList()}
</Modal.Body>
</Modal>;
}

renderConList() {
if (this.props.loading) {
return (<div className="text-center">
<Spinner animation="border" />
</div>);
} else if (this.props.conList != null) {
let rows = this.props.conList.map((c) => {
let startDate = dayjs(c.startDate).format('ddd, MMM D, YYYY')
let endDate = dayjs(c.endDate).format('ddd, MMM D, YYYY')

return (<tr key={'con-' + c.id}>
<td>{c.name}</td>
<td>{startDate}</td>
<td>{endDate}</td>
<td className="text-right"><Button variant="outline-primary" onClick={() => this.props.onClose(c)}>Select</Button></td>
</tr>);
});
return (<table className="table">
<tbody>
{rows}
</tbody>
</table>);
} else {
return undefined;
}
}

fetchCons() {
axios.get('/api/get_con_list.php', {
headers: {
"Authorization": "Bearer " + store.getState().auth.jwt
}
})
.then(res => {
let state = this.state;
this.setState({
...state,
loading: false,
message: null,
});
store.dispatch(setConList(res.data.list));
})
.catch(error => {
let state = this.state;
let message = "The cons list could not be loaded."
this.setState({
...state,
loading: false,
message: { severity: "danger", text: message }
})
if (error.response && error.response.status === 401) {
this.forceLogout();
}
});
}
}
function mapStateToProps(state) {
return { conList: state.con.list };
}

export default connect(mapStateToProps)(ConSelection);
26 changes: 12 additions & 14 deletions client/src/component/loadingButton.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
import React, { Component } from 'react';
import React from 'react';

import Button from 'react-bootstrap/Button';
import Spinner from 'react-bootstrap/Spinner';

class LoadingButton extends Component {
const LoadingButton = (props) => {

render() {
const spinner = this.props.loading ? (<Spinner
as="span"
animation="border"
size="sm"
role="status"
aria-hidden="true"
/>) : undefined;
return (<Button variant="primary" onClick={() => this.props.onClick()}
className={this.props.className}
disabled={!this.props.enabled || this.props.loading}>{spinner} {this.props.text}</Button>);
}
const spinner = props.loading ? (<Spinner
as="span"
animation="border"
size="sm"
role="status"
aria-hidden="true"
/>) : undefined;
return (<Button variant="primary" onClick={() => props.onClick()}
className={props.className}
disabled={!props.enabled || props.loading}>{spinner} {props.text} {props.children}</Button>);
}

export default LoadingButton;
13 changes: 11 additions & 2 deletions client/src/component/pageHeader.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { Component } from 'react';
import {connect} from 'react-redux';
import axios from 'axios';

import Button from 'react-bootstrap/Button'
Expand All @@ -12,6 +13,7 @@ import store from '../state/store';
import PropTypes from "prop-types";
import { withRouter } from "react-router";
import { sdlc } from '../util/sdlcUtil';
import { fetchCurrentCon } from '../state/conFunctions';

class PageHeader extends Component {
static propTypes = {
Expand Down Expand Up @@ -42,10 +44,13 @@ class PageHeader extends Component {
}
});
});

}

render() {
if (this.props.currentCon == null) {
fetchCurrentCon();
}

let message = (this.state.login.message) ? (<div className="alert alert-danger">{this.state.login.message}</div>) : undefined;
let adminMenu = this.isAuthenticated()
? (<NavDropdown title={this.getAdminName()} id="admin-nav-dropdown">
Expand Down Expand Up @@ -239,4 +244,8 @@ class PageHeader extends Component {
}
}

export default withRouter(PageHeader);
function mapStateToProps(state) {
return { currentCon: state.con.currentCon };
}

export default withRouter(connect(mapStateToProps)(PageHeader));
41 changes: 12 additions & 29 deletions client/src/component/pageMessage.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,24 @@
import React, { Component } from 'react';
import React from 'react';

import Alert from 'react-bootstrap/Alert';
import { connect } from 'react-redux';

import { removeMessage } from '../state/pageMessageActions';
import store from '../state/store';

class PageMessage extends Component {
const PageMessage = (props) => {

constructor(props) {
super(props);
this.state = { messages: store.getState().pageMessage.messages };
}

componentWillMount() {
this.unsubscribe = store.subscribe(() => {
this.setState({
messages: store.getState().pageMessage.messages
});
});
}

componentWillUnmount() {
if (this.unsubscribe) {
this.unsubscribe();
}
function removeTheMessage(m) {
store.dispatch(removeMessage(m));
}

return props.messages.map((m) => {
return (<Alert variant={m.severity} dismissible onClose={() => removeTheMessage(m)}>{m.text}</Alert>)
});
}

render() {
return this.state.messages.map((m) => {
return (<Alert variant={m.severity} dismissible onClose={() => this.removeMessage(m)}>{m.text}</Alert>)
})
}

removeMessage(m) {
store.dispatch(removeMessage(m));
}
function mapStateToProps(state) {
return { messages: state.pageMessage.messages || [] };
}

export default PageMessage;
export default connect(mapStateToProps)(PageMessage);
57 changes: 40 additions & 17 deletions client/src/component/welcome.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,45 @@
import Alert from 'react-bootstrap/Alert';
import {connect} from 'react-redux';

const Welcome = () => {
import dayjs from "dayjs";
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import advancedFormat from "dayjs/plugin/advancedFormat"
import customParseFormat from "dayjs/plugin/customParseFormat"
dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.extend(customParseFormat);
dayjs.extend(advancedFormat);

return (<div>
<h1>Wiscon Registration</h1>
<p className="lead">WisCon 2022 will be held from May 27, 2022 to May 30, 2022. Register now!</p>
<p>For more information about membership types, including our online memberships, visit {' '}
<a href="https://wiscon.net/register/" target="_blank" rel="noreferrer">https://wiscon.net/register/</a>.</p>
<Alert variant="info">
<h5 className="alert-heading">Masks and Proof of Vaccination Required</h5>
<p>
All attendees, including children, must show documentation of COVID vaccination to attend, and must wear masks in
convention spaces. Unvaccinated individuals, including children too young to be vaccinated, will not be able to
attend WisCon 2022 in person. For more information, visit {' '}
<a href="http://wiscon.net/covid-19-and-wiscon-2022/" className="alert-link" target="_blank" rel="noreferrer">COVID-19 and WisCon 2022</a>.
</p>
</Alert>
</div>);
const Welcome = (props) => {

if (props.currentCon != null) {
let startDate = dayjs(props.currentCon.startDate).format('MMM D, YYYY')
let endDate = dayjs(props.currentCon.endDate).format('MMM D, YYYY')

return (<div>
<h1>Wiscon Registration</h1>
<p className="lead">{props.currentCon.name + ' '} will be held from
{' ' + startDate + ' '} to {' ' + endDate}. Register now!</p>
<p>For more information about membership types, including our online memberships, visit {' '}
<a href="https://wiscon.net/register/" target="_blank" rel="noreferrer">https://wiscon.net/register/</a>.</p>
<Alert variant="info">
<h5 className="alert-heading">Masks and Proof of Vaccination Required</h5>
<p>
All attendees, including children, must show documentation of COVID vaccination to attend, and must wear masks in
convention spaces. Unvaccinated individuals, including children too young to be vaccinated, will not be able to
attend WisCon 2022 in person. For more information, visit {' '}
<a href="http://wiscon.net/covid-19-and-wiscon-2022/" className="alert-link" target="_blank" rel="noreferrer">COVID-19 and WisCon 2022</a>.
</p>
</Alert>
</div>);
} else {
return null;
}
}

function mapStateToProps(state) {
return { currentCon: state.con.currentCon };
}

export default Welcome;
export default connect(mapStateToProps)(Welcome);
Loading

0 comments on commit e209d5c

Please sign in to comment.