diff options
Diffstat (limited to 'client/components')
| -rw-r--r-- | client/components/App.jsx | 36 | ||||
| -rw-r--r-- | client/components/CalorieView.jsx | 56 | ||||
| -rw-r--r-- | client/components/LoggedOutView.jsx | 26 | ||||
| -rw-r--r-- | client/components/MealView.jsx | 302 |
4 files changed, 328 insertions, 92 deletions
diff --git a/client/components/App.jsx b/client/components/App.jsx index 5a026b4..99c2c11 100644 --- a/client/components/App.jsx +++ b/client/components/App.jsx @@ -1,54 +1,52 @@ import React from 'react' import LoggedOutView from './LoggedOutView.jsx' -import CalorieView from './CalorieView.jsx' +import MealView from './MealView.jsx' -import feathers from 'feathers/client' -import feathersHooks from 'feathers-hooks' -import feathersRest from 'feathers-rest/client' -import feathersAuthentication from 'feathers-authentication/client' -import superagent from 'superagent' - -const rest = feathersRest(window.location.origin) - -const client = feathers() - .configure(feathersHooks()) - .configure(feathersAuthentication({ storage: localStorage })) - .configure(rest.superagent(superagent)) +import client from '../client' export default class App extends React.Component { constructor() { super() this.state = { - ready: true, + ready: false, loggedIn: false, user: {}, } client.authenticate() .then(user => { - console.log(user) - this.setState({ ready: true, loggedIn: true, user: user }) + this.setState({ + ready: true, + loggedIn: true, + user: user.data + }) }) .catch(error => { this.setState({ ready: true }) console.error(error) }) } + logOut() { + this.setState({ + user: null, + loggedIn: false, + }) + } render() { if (this.state.ready) { if (this.state.loggedIn) { return ( - <CalorieView client={client} /> + <MealView user={this.state.user} /> ) } else { return ( - <LoggedOutView client={client} /> + <LoggedOutView /> ) } } else { return ( - <div>LOADING...</div> + <div>Loading...</div> ) } } diff --git a/client/components/CalorieView.jsx b/client/components/CalorieView.jsx deleted file mode 100644 index 3c5fe2d..0000000 --- a/client/components/CalorieView.jsx +++ /dev/null @@ -1,56 +0,0 @@ -import React from 'react' -import ModalDialog from './ModalDialog.jsx' - -export default class LoggedOutView extends React.Component { - constructor() { - super() - this.state = { modal: null } -// this.showLogin = this.showLogin.bind(this) -// this.showSignup = this.showSignup.bind(this) -// this.closeModal = this.closeModal.bind(this) - } -// showLogin() { -// this.setState({ modal: 'login' }) -// } -// showSignup() { -// this.setState({ modal: 'signup' }) -// } -// closeModal() { -// this.setState({ modal: '' }) -// } - render() { -// const loginVisible = this.state.modal == 'login' -// const signupVisible = this.state.modal == 'signup' - return ( - <div> - LOGGED IN - </div> -// <Welcome -// onLoginClick={this.showLogin} -// onSignupClick={this.showSignup} /> -// <LoginForm -// client={this.props.client} -// visible={loginVisible} -// onClose={this.closeModal} /> -// <SignupForm -// client={this.props.client} -// visible={signupVisible} -// onClose={this.closeModal} /> - ) - } -} - - -// export default class UserForm extends React.Component { -// render() { -// return ( -// ) -// } -// } -// -// export default class MealForm extends React.Component { -// render() { -// return ( -// ) -// } -// } diff --git a/client/components/LoggedOutView.jsx b/client/components/LoggedOutView.jsx index e058455..f217143 100644 --- a/client/components/LoggedOutView.jsx +++ b/client/components/LoggedOutView.jsx @@ -1,5 +1,6 @@ import React from 'react' import ModalDialog from './ModalDialog.jsx' +import client from '../client' export default class LoggedOutView extends React.Component { constructor() { @@ -27,11 +28,9 @@ export default class LoggedOutView extends React.Component { onLoginClick={this.showLogin} onSignupClick={this.showSignup} /> <LoginForm - client={this.props.client} visible={loginVisible} onClose={this.closeModal} /> <SignupForm - client={this.props.client} visible={signupVisible} onClose={this.closeModal} /> </div> @@ -76,15 +75,13 @@ class LoginForm extends React.Component { } handleSubmit(event) { event.preventDefault() - this.props.client.authenticate({ + client.authenticate({ type: 'local', email: this.state.email, password: this.state.password, }).then(res => { console.log('Authenticated!', res); - // this.props.client.set('user', res.data) - // something in this library is hardcoded accessToken - // return this.props.client.passport.setJWT(res.token) + window.location.reload() }).catch(error => { console.error('Error authenticating!', error); this.setState({ @@ -138,23 +135,18 @@ class SignupForm extends React.Component { } handleSubmit(event) { event.preventDefault() - const usersService = this.props.client.service('users') + const usersService = client.service('users') usersService.create(this.state).then(result => { - return this.props.client.authenticate({ + return client.authenticate({ strategy: 'local', email: this.state.email, password: this.state.password, }) - }) - .then(res => { - this.props.client.set('user', res.data) - this.props.client.set('token', res.accessToken) - return client.passport.verifyJWT(res.accessToken) - }) - .then(payload => { - console.log(payload) + }).then(res => { + console.log('Authenticated!', res) + window.location.reload() }).catch(error => { - console.error(error) + console.error('Error authenticating!', error) this.setState({ error: error.toString() }) diff --git a/client/components/MealView.jsx b/client/components/MealView.jsx new file mode 100644 index 0000000..920dca9 --- /dev/null +++ b/client/components/MealView.jsx @@ -0,0 +1,302 @@ +import React from 'react' +import ModalDialog from './ModalDialog.jsx' + +import client from '../client' + +export default class MealView extends React.Component { + constructor(props) { + super() + this.state = { + user: Object.assign({}, props.user), + meals: [], + } + this.updateUser = this.updateUser.bind(this) + } + updateUser(user) { + this.setState({ + user: user + }) + } + render() { + const user = this.state.user + const meals = this.state.meals + return ( + <div> + <Menu user={user} currentUser={this.props.user} updateUser={this.updateUser} /> + <MealList user={user} currentUser={this.props.user} /> + <div className='users'> + <UserList /> + </div> + </div> + ) + } +} + +class Menu extends React.Component { + constructor() { + super() + this.setGoal = this.setGoal.bind(this) + this.logout = this.logout.bind(this) + } + setGoal() { + const goal = Math.abs(parseInt(prompt('Please enter your calorie goal', this.props.user.goal))) + if (goal) { + client.service('users').patch(this.props.user.id, { + goal: goal, + token: client.get('token'), + }).then((user) => { + this.props.updateUser(user) + }) + } + } + logout() { + client.logout().then(() => { + window.location.reload() + }) + } + render() { + const user = this.props.user + const items = [] + items.push( <li key='hello'>Hello {user.email}</li> ) + items.push( <li key='goal'><a href='#' onClick={this.setGoal}>Goal</a>: {user.goal}</li> ) + items.push( <li key='logout'><a href='#' onClick={this.logout}>Logout</a></li> ) + + return ( + <div> + <ul className='menu'> + {items} + </ul> + <ProfileModal user={user} visible={false} onClose={() => {}} /> + </div> + ) + } +} + +class ProfileModal extends React.Component { + render() { + return ( + <ModalDialog visible={this.props.visible} onClose={this.props.onClose}> + </ModalDialog> + ) + } +} + +class MealList extends React.Component { + constructor(props) { + super() + + this.state = { + total: 0, + limit: 0, + skip: 0, + data: [] + } + + this.handleCreate = this.handleCreate.bind(this) + this.handleUpdate = this.handleUpdate.bind(this) + this.pickMeal = this.pickMeal.bind(this) + + client.service('meals').find({ + query: { + userid: props.user.id, + '$sort': { 'date': '-1' }, + token: client.get('token'), + }, + }).then((data) => { + console.log(data) + this.setState(data) + }).catch((error) => { + console.error(error) + }) + } + handleCreate(meal) { + const meals = this.state.data.slice() + meals.unshift( meal ) + this.setState({ + data: meals.sort(sortByDate) + }) + } + handleUpdate(meal) { + const meals = this.state.data.map((data, i) => { + return (data.id == meal.id) ? meal : data + }).sort(sortByDate) + this.setState({ + data: meals + }) + } + pickMeal(meal) { + this.mealForm.pick(meal) + } + render() { + console.log(this.state.data) + const items = this.state.data.map((meal, i) => { + return ( + <MealItem key={meal.id} + meal={meal} + onClick={this.pickMeal} /> + ) + }) + return ( + <div> + <MealForm user={this.props.user} + ref={(mealForm) => { this.mealForm = mealForm }} + onCreate={(meal) => { this.handleCreate(meal) }} + onUpdate={(meal) => { this.handleUpdate(meal) }} + /> + <div> + {items} + </div> + </div> + ) + } +} + +class MealItem extends React.Component { + render() { + const meal = this.props.meal + const date = parseDate(meal.date) + const time = parseTime(meal.time) + return ( + <div className='meal' onClick={() => this.props.onClick(meal)}> + <div className='name'>{meal.name}</div> + <div className='calories'>{meal.calories} cal</div> + <div className='date'>{date}</div> + <div className='time'>{time}</div> + </div> + ) + } +} + +class MealForm extends React.Component { + constructor(props) { + super() + this.state = { + id: '', + userid: props.user.id, + name: '', + calories: '', + date: new Date (), + time: new Date (), + } + this.updateState = this.updateState.bind(this) + this.handleSubmit = this.handleSubmit.bind(this) + } + reset() { + this.setState({ + id: '', + name: '', + calories: '', + date: new Date (), + time: new Date (), + }) + } + pick(meal){ + console.log(meal) + this.setState(meal) + } + updateState(event){ + const name = event.target.name + let value = event.target.value + if (name === 'date') { + value = new Date(value).toString() + } else if (name === 'time') { + value = new Date('1970-01-01T' + value).toString() + } else if (name === 'calories') { + value = parseInt(value) + } + this.setState({ + [name]: value, + error: null, + }) + } + handleSubmit(event) { + event.preventDefault() + + const id = this.state.id + + if (! id) { + this.create() + } + else { + this.update() + } + } + create() { + const mealsService = client.service('meals') + const params = { query: { token: client.get('token') } } + + mealsService.create(this.state, params).then(result => { + console.log(result) + this.props.onCreate(result) + this.reset() + }).catch(error => { + console.error(error) + this.setState({ + error: error.toString() + }) + }) + } + update() { + const mealsService = client.service('meals') + const params = { query: { token: client.get('token') } } + + mealsService.update(this.state.id, this.state, params).then(result => { + console.log(result) + this.props.onUpdate(result) + this.reset() + }).catch(error => { + console.error(error) + this.setState({ + error: error.toString() + }) + }) + } + render() { + const id = this.state.id + const action = id ? 'update' : 'create' + + const date = parseDate(this.state.date) + const time = parseTime(this.state.time) + return ( + <form onSubmit={this.handleSubmit} className={action}> + <input type='hidden' name='id' value={this.state.id} readOnly /> + <input type='hidden' name='userid' value={this.state.userid} readOnly /> + <input type='text' name='name' placeholder='Name' value={this.state.name} required onChange={this.updateState} /> + <input type='number' name='calories' placeholder='Calories' value={this.state.calories} required onChange={this.updateState} min='0' max='10000' /> + <input type='date' name='date' placeholder='Date' value={date} required onChange={this.updateState} /> + <input type='time' name='time' placeholder='Time' value={time} required onChange={this.updateState} step='60' /> + <input type='submit' value={capitalize(action)} /> + <span className='clear' onClick={() => this.reset()}>clear</span> + <div className='error'>{this.state.error}</div> + </form> + ) + } +} + +function sortByDate(a,b){ + return new Date(b.date) - new Date(a.date) +} + +function parseDate(d){ + return new Date(d).toISOString().substr(0, 10) +} + +function parseTime(d){ + return new Date(d).toISOString().substr(11, 5) +} + +function capitalize(s){ + s = s || ''; + return (s[0] || '').toUpperCase() + s.substr(1) +} + +class UserList extends React.Component { + render() { + const items = [] + return ( + <div> + {items} + </div> + ) + } +} |
