mirror of https://github.com/fspc/workstand.git
Drew Larson
9 years ago
6 changed files with 190 additions and 58 deletions
@ -0,0 +1,20 @@ |
|||||
|
import React from 'react'; |
||||
|
import AutoComplete from 'material-ui/AutoComplete'; |
||||
|
|
||||
|
export default class Member extends React.Component { |
||||
|
render () { |
||||
|
return ( |
||||
|
<AutoComplete |
||||
|
dataSource={this.props.members} |
||||
|
onUpdateInput={this.props.handleUpdate.bind(this)} |
||||
|
openOnFocus={true} |
||||
|
filter={AutoComplete.noFilter} |
||||
|
onNewRequest={this.props.signIn.bind(this)} |
||||
|
errorText={this.props.error} |
||||
|
hintText="Search members" |
||||
|
searchText={this.props.searchText} |
||||
|
|
||||
|
/> |
||||
|
); |
||||
|
} |
||||
|
} |
@ -0,0 +1,18 @@ |
|||||
|
import React from 'react'; |
||||
|
import SelectField from 'material-ui/SelectField'; |
||||
|
import MenuItem from 'material-ui/MenuItem'; |
||||
|
|
||||
|
export default class Purpose extends React.Component { |
||||
|
render () { |
||||
|
return ( |
||||
|
<SelectField value={this.props.default} onChange={this.props.handleChange.bind(this)}> |
||||
|
<MenuItem value={'VOLUNTEER'} primaryText="Volunteer" /> |
||||
|
<MenuItem value={'FIX'} primaryText="Fix" /> |
||||
|
<MenuItem value={'WORKSHOP'} primaryText="Workshop" /> |
||||
|
<MenuItem value={'DONATE'} primaryText="Donate" /> |
||||
|
<MenuItem value={'STAFF'} primaryText="Staff" /> |
||||
|
</SelectField> |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
@ -0,0 +1,116 @@ |
|||||
|
import React from 'react'; |
||||
|
import RaisedButton from 'material-ui/RaisedButton'; |
||||
|
import { polyFill } from 'es6-promise'; |
||||
|
import fetch from 'isomorphic-fetch'; |
||||
|
import Purpose from './Purpose'; |
||||
|
import Member from './Member'; |
||||
|
import SignedInList from './SignedInList'; |
||||
|
import moment from 'moment'; |
||||
|
|
||||
|
export default class SignIn extends React.Component { |
||||
|
constructor (props) { |
||||
|
super(props); |
||||
|
this.state = { |
||||
|
members: [], |
||||
|
signOn: {purpose: 'FIX', member: undefined}, |
||||
|
error: '', |
||||
|
signedIn: [], |
||||
|
searchText: '' |
||||
|
}; |
||||
|
this.handleUpdate = this.handleUpdate.bind(this); |
||||
|
this.signIn = this.signIn.bind(this); |
||||
|
this.chooseMember = this.chooseMember.bind(this); |
||||
|
this.handlePurposeChoice = this.handlePurposeChoice.bind(this); |
||||
|
} |
||||
|
|
||||
|
handlePurposeChoice (event, index, value) { |
||||
|
this.setState({...this.state, signOn: {...this.state.signOn, purpose: value}}); |
||||
|
} |
||||
|
|
||||
|
handleUpdate (text, dataSource) { |
||||
|
const self = this; |
||||
|
self.setState({searchText: text}) |
||||
|
fetch(`//bikeshop.local/member/search/${text}/`) |
||||
|
.then((response) => { |
||||
|
if (response.status === 200) |
||||
|
return response.json(); |
||||
|
}) |
||||
|
.then((data) => { |
||||
|
if (data.results.length > 0) { |
||||
|
self.setState({ |
||||
|
...this.state, |
||||
|
error: '', |
||||
|
members: data.results.map((result) => { |
||||
|
return {text: `${result.name}`, value: `${result.name} <${result.email}>`, id: result.id} |
||||
|
}) |
||||
|
}); |
||||
|
} else { |
||||
|
self.setState({...this.state, error: 'Member not found.'}) |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
signIn () { |
||||
|
const purpose = this.state.signOn.purpose; |
||||
|
const member = this.state.signOn.member; |
||||
|
|
||||
|
if (!this.state.signedIn.find((signedInMember) => {return signedInMember.id === member.id})) { |
||||
|
fetch('//bikeshop.local/member/signin/', { |
||||
|
method: 'post', |
||||
|
body: `id=${member.id}&purpose=${purpose}`, |
||||
|
headers: { |
||||
|
'Content-Type': 'application/x-www-form-urlencoded' |
||||
|
} |
||||
|
}).then((response) => { |
||||
|
if (response.status === 201) |
||||
|
return response.json(); |
||||
|
}).then((data) => { |
||||
|
const now = moment(); |
||||
|
const signedIn = this.state.signedIn; |
||||
|
signedIn.push({...member, purpose, at: now}); |
||||
|
this.setState({ |
||||
|
...this.state, |
||||
|
signedIn: signedIn, |
||||
|
signOn: {purpose: 'FIX', member: undefined}, |
||||
|
searchText: '', |
||||
|
members: [] |
||||
|
}) |
||||
|
}); |
||||
|
} else { |
||||
|
this.setState({...this.state, error: 'Member already signed in.'}) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
chooseMember (chosenRequest, index) { |
||||
|
console.log(index); |
||||
|
const member = this.state.members[index]; |
||||
|
const purpose = this.state.signOn.purpose; |
||||
|
|
||||
|
this.setState({...this.state, signOn: {member, purpose}}); |
||||
|
} |
||||
|
|
||||
|
onUpdateSearchText(searchText, dataSource) { |
||||
|
this.setState({searchText: searchText}) |
||||
|
} |
||||
|
|
||||
|
render () { |
||||
|
return ( |
||||
|
<div> |
||||
|
<Member |
||||
|
handleUpdate={this.handleUpdate} |
||||
|
signIn={this.chooseMember} |
||||
|
error={this.state.error} |
||||
|
members={this.state.members} |
||||
|
searchText={this.state.searchText} |
||||
|
/> |
||||
|
<br /> |
||||
|
<Purpose handleChange={this.handlePurposeChoice} default={this.state.signOn.purpose} /> |
||||
|
<div> |
||||
|
<RaisedButton onClick={this.signIn} label="Sign-in" /> |
||||
|
</div> |
||||
|
<br /> |
||||
|
<SignedInList members={this.state.signedIn} /> |
||||
|
</div> |
||||
|
); |
||||
|
} |
||||
|
} |
@ -0,0 +1,33 @@ |
|||||
|
import React from 'react'; |
||||
|
import {List, ListItem} from 'material-ui/List'; |
||||
|
|
||||
|
export default class SignedInList extends React.Component { |
||||
|
constructor (props) { |
||||
|
super(props); |
||||
|
this.state = {tick: 0}; |
||||
|
this.componentDidMount = this.componentDidMount.bind(this); |
||||
|
this.componentWillUnmount = this.componentWillUnmount.bind(this); |
||||
|
this.tick = this.tick.bind(this); |
||||
|
} |
||||
|
componentDidMount () { |
||||
|
this.timer = setInterval(this.tick, 50); |
||||
|
} |
||||
|
componentWillUnmount () { |
||||
|
clearInterval(this.timer); |
||||
|
} |
||||
|
tick () { |
||||
|
this.setState({tick: this.state.tick++}); |
||||
|
} |
||||
|
render () { |
||||
|
let members = this.props.members.map((member) => { |
||||
|
return <ListItem key={member.id} primaryText={member.text} secondaryText={`${member.purpose} – ${member.at.fromNow()}`} /> |
||||
|
}); |
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
<h3>Members signed in</h3> |
||||
|
{members} |
||||
|
</div> |
||||
|
); |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue