Guest User

Untitled

a guest
Nov 19th, 2017
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.52 KB | None | 0 0
  1. import React, { Component } from 'react';
  2. import { connect } from 'react-redux';
  3. import * as actions from '../../actions';
  4. import Loading from '../Loading';
  5. import Poll from './Poll';
  6.  
  7. class MyPolls extends Component {
  8. constructor(props) {
  9. super(props);
  10. this.state = {
  11. skip: 0,
  12. isLoading: true,
  13. isLoadingMore: false,
  14. };
  15. }
  16.  
  17. componentDidMount() {
  18. this.props.fetchMyPolls(this.state.skip)
  19. .then(() => {
  20. setTimeout(() => {
  21. this.setState({
  22. skip: this.state.skip + 4,
  23. isLoading: false
  24. });
  25. }, 1000);
  26. });
  27. }
  28.  
  29.  
  30.  
  31. loadMore(skip) {
  32. this.setState({ isLoadingMore: true });
  33.  
  34. setTimeout(() => {
  35. this.props.fetchMyPolls(skip)
  36. .then(() => {
  37. const nextSkip = this.state.skip + 4;
  38. this.setState({
  39. skip: nextSkip,
  40. isLoadingMore: false
  41. });
  42. });
  43. }, 1000);
  44. }
  45.  
  46. renderPolls() {
  47. return this.props.polls.map(poll => {
  48. return (
  49. <Poll
  50. key={poll._id}
  51. title={poll.title}
  52. options={poll.options}
  53. />
  54. )
  55. })
  56. }
  57.  
  58. render() {
  59. console.log(this.props.polls);
  60. console.log('skip:', this.state.skip);
  61. return (
  62. <div className='center-align container'>
  63. <h2>My Polls</h2>
  64. {this.state.isLoading ? <Loading size='big' /> :
  65. <div
  66. style={{
  67. display: 'flex',
  68. flexWrap: 'wrap',
  69. justifyContent: 'space-evenly',
  70. alignItems: 'center',
  71. alignContent: 'center'
  72. }}>
  73. {this.renderPolls()}
  74. </div>}
  75. <div className='row'>
  76. {this.state.isLoadingMore ? <Loading size='small' /> :
  77. <button
  78. className='btn red lighten-2 wave-effect waves-light' onClick={() => this.loadMore(this.state.skip)}>
  79. Load More
  80. </button>}
  81. </div>
  82. </div>
  83.  
  84. );
  85. }
  86. }
  87.  
  88. function mapStateToProps({ polls }) {
  89. return { polls }
  90. }
  91.  
  92. export default connect(mapStateToProps, actions)(MyPolls);
  93.  
  94. import React, { Component } from 'react';
  95. import { connect } from 'react-redux';
  96. import { reduxForm, Field, FieldArray, arrayPush } from 'redux-form';
  97. import * as actions from '../../actions';
  98. import { withRouter } from 'react-router-dom';
  99.  
  100. const cardStyle = {
  101. width: '500px',
  102. height: '75px',
  103. margin: '10px auto',
  104. display: 'flex',
  105. alignItems: 'center',
  106. padding: '10px'
  107. };
  108.  
  109. class NewPoll extends Component {
  110. constructor(props) {
  111. super(props);
  112. this.state = {
  113. showOptions: false,
  114. option: '',
  115. title: ''
  116. };
  117. this.onOptionInputChange = this.onOptionInputChange.bind(this);
  118. this.onAddOption = this.onAddOption.bind(this);
  119. this.renderOption = this.renderOption.bind(this);
  120. this.renderOptionCard = this.renderOptionCard.bind(this);
  121. this.renderTitle = this.renderTitle.bind(this);
  122. this.renderTitleCard = this.renderTitleCard.bind(this);
  123. }
  124.  
  125. onOptionInputChange(event) {
  126. this.setState({ option: event.target.value });
  127. }
  128.  
  129. onAddOption() {
  130. const { dispatch } = this.props;
  131.  
  132. dispatch(arrayPush('newPollForm', 'options', this.state.option));
  133. this.setState({ option: '' });
  134. }
  135.  
  136. renderOption(props) {
  137. return (
  138. <ul>
  139. {props.fields.map((option, index) => (
  140. <li key={index}>
  141. <div
  142. className='card'
  143. style={cardStyle}>
  144. <Field
  145. type='text'
  146. name={option}
  147. index={index}
  148. component={this.renderOptionCard}
  149. />
  150. <i
  151. className='material-icons right'
  152. onClick={() => props.fields.remove(index)}
  153. >
  154. delete
  155. </i>
  156. </div>
  157. <div className='red-text'>
  158. {props.meta.error }
  159. </div>
  160. </li>
  161. ))}
  162. </ul>
  163. );
  164. }
  165.  
  166. renderOptionCard({ index, input }) {
  167. return (
  168. <span className='card-title'
  169. style={{ flex: '1' }}>
  170. {`${index + 1})`} {input.value}
  171. </span>
  172. );
  173. }
  174.  
  175. renderTitle({ input, type, placeholder, meta: { touched, error }}) {
  176. return (
  177. <div>
  178. <div className='input-field inline'>
  179. <input {...input}
  180. type={type}
  181. placeholder={placeholder}
  182. style={{ width: '350px' }}
  183. />
  184. <div className='red-text'>
  185. {touched && error}
  186. </div>
  187. </div>
  188. <button
  189. type='text'
  190. className='red lighten-2 btn waves-effect waves-light'
  191. onClick={() => {
  192. this.setState({ title: input.value });
  193. input.value = '';
  194. }}
  195. disabled={!input.value}>
  196. Add Title
  197. <i className='material-icons right'>
  198. add
  199. </i>
  200. </button>
  201. </div>
  202. )
  203. }
  204.  
  205. renderTitleCard({ input }) {
  206. return (
  207. <div
  208. className='card'
  209. style={cardStyle}>
  210. <span className='card-title' style={{ flex: '1' }}>
  211. <strong><u>{input.value}</u></strong>
  212. </span>
  213. <i className='material-icons right' onClick={() => this.setState({ title: '' })}>
  214. delete
  215. </i>
  216. </div>
  217. )
  218. }
  219.  
  220. onPollSubmit(values) {
  221. const { history } = this.props;
  222. this.props.submitPoll(values, history);
  223. }
  224.  
  225. render() {
  226. return (
  227. <div className='center-align'>
  228. <h3>Create a new poll:</h3>
  229. <form onSubmit={this.props.handleSubmit(this.onPollSubmit.bind(this))}>
  230. <Field
  231. type='text'
  232. placeholder='Title'
  233. name='title'
  234. component={this.state.title ? this.renderTitleCard : this.renderTitle}
  235. />
  236. <FieldArray
  237. name='options' component={this.renderOption}
  238. />
  239. <div className='row'>
  240. <div className='inline input-field'>
  241. <input
  242. value={this.state.option} onChange={this.onOptionInputChange}
  243. placeholder='Option'
  244. style={{ width: '300px' }}
  245. />
  246. </div>
  247. <button
  248. type='text'
  249. className='red lighten-2 btn waves-effect waves-light'
  250. onClick={this.onAddOption}
  251. disabled={!this.state.option}
  252. >
  253. Add Option
  254. <i className='material-icons right'>
  255. add
  256. </i>
  257. </button>
  258. </div>
  259.  
  260. <button
  261. type='submit'
  262. className='teal btn-large waves-effect waves-light'
  263. >
  264. Submit
  265. <i className='material-icons right'>
  266. send
  267. </i>
  268. </button>
  269. </form>
  270. </div>
  271. );
  272. }
  273. }
  274.  
  275. function validate(values) {
  276. const errors = {};
  277.  
  278. if (!values.title) {
  279. errors.title = 'You must provide a title';
  280. }
  281.  
  282. if (!values.options || values.options.length < 2) {
  283. errors.options = { _error: 'You must provide at least 2 options' };
  284. }
  285. return errors;
  286. }
  287.  
  288. NewPoll = reduxForm({
  289. form: 'newPollForm',
  290. validate
  291. })(NewPoll);
  292.  
  293.  
  294. export default connect(null, actions)(withRouter(NewPoll));
  295.  
  296. export const submitPoll = (values, history) => async dispatch => {
  297. const res = await axios.post('/api/polls', values);
  298. history.push('/mypolls');
  299. dispatch({ type: FETCH_USER, payload: res.data });
  300. }
  301.  
  302. export const fetchMyPolls = (skip) => async dispatch => {
  303. const res = await axios.get(`/api/mypolls/${skip}`);
  304.  
  305. dispatch({ type: FETCH_MY_POLLS, payload: res.data });
  306. }
  307.  
  308. app.post('/api/polls', requireLogin, (req, res) => {
  309.  
  310. const { title, options } = req.body;
  311.  
  312. const poll = new Poll({
  313. title,
  314. options: options.map(option => ({ option: option.trim() })),
  315. dateCreated: Date.now(),
  316. _user: req.user.id
  317. });
  318.  
  319. poll.save();
  320. res.send(req.user);
  321. });
  322.  
  323. app.get('/api/mypolls/:skip', requireLogin, (req, res) => {
  324.  
  325. Poll.find({ _user: req.user.id })
  326. .sort({ dateCreated: -1 })
  327. .skip(parseInt(req.params.skip))
  328. .limit(4)
  329. .then(polls => {
  330. res.send(polls);
  331. });
  332. });
  333.  
  334. import { FETCH_MY_POLLS, UPDATE_POLL } from '../actions/types';
  335.  
  336. export default function(state = [], action) {
  337. switch(action.type) {
  338. case FETCH_MY_POLLS:
  339. return [ ...state, ...action.payload];
  340. case UPDATE_POLL:
  341. return (
  342. [...state].map(poll => {
  343. if (poll._id === action.payload._id) {
  344. return action.payload;
  345. }
  346. return poll;
  347. })
  348. )
  349. default:
  350. return state;
  351. }
  352. }
Add Comment
Please, Sign In to add comment