Advertisement
Guest User

Untitled

a guest
Nov 13th, 2019
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.04 KB | None | 0 0
  1. import React, { useState } from 'react';
  2. import PropTypes from 'prop-types';
  3.  
  4. import { Icon, Tooltip, Button, Typography } from 'antd';
  5. import { Form, Field } from 'react-final-form';
  6. import arrayMutators from 'final-form-arrays';
  7. import createDecorator from 'final-form-focus';
  8. import cx from 'classnames';
  9.  
  10. import {
  11. Input,
  12. DatePicker,
  13. TimePicker,
  14. Textarea,
  15. Select
  16. } from '../../../components';
  17. import EventPreview from '../../EventPreview/EventPreview';
  18. import ImageBrowser from './ImageBrowser/ImageBrowser';
  19. import Mentors from './Mentors/Mentors';
  20.  
  21. import {
  22. Validators,
  23. eventsStatuses,
  24. eventPositions,
  25. pipe
  26. } from '../../../utils';
  27. import styles from './EventForm.scss';
  28.  
  29. const focusOnError = createDecorator();
  30.  
  31. const EventForm = ({ event, onSave, onDelete, onDuplicate, isNew }) => {
  32. const [eventForPreview, setEventForPreview] = useState(event);
  33. const [isVisible, setIsVisible] = useState(false);
  34.  
  35. return (
  36. <div className={styles.wrapper}>
  37. <Form
  38. onSubmit={onSave}
  39. decorators={[focusOnError]}
  40. mutators={{
  41. ...arrayMutators
  42. }}
  43. initialValues={{
  44. status: 'notPublished',
  45. ...event
  46. }}
  47. validate={values => {
  48. const newImageSRC = (values.newImage || {}).src;
  49.  
  50. /* eslint consistent-return: 0 */
  51. if (!newImageSRC && !values.imageUrl) {
  52. return { imageField: 'Zdjęcie jest wymagane' };
  53. }
  54. }}
  55. render={({ handleSubmit, values, invalid, form }) => (
  56. <form onSubmit={handleSubmit}>
  57. <div className={styles.wrapperOneLine}>
  58. <Typography.Title level={2} className={styles.title}>
  59. {isNew ? 'Dodaj Wydarzenie' : 'Edytuj Wydarzenie'}
  60. </Typography.Title>
  61. <Button
  62. type='primary'
  63. htmlType='submit'
  64. className={styles.saveButton}
  65. >
  66. Zapisz
  67. </Button>
  68. </div>
  69. <div className={cx(styles.wrapperOneLine, styles.eventFormula)}>
  70. <Select
  71. name='status'
  72. options={eventsStatuses}
  73. className={styles.select}
  74. placeholder='Status'
  75. />
  76. <span>
  77. <Tooltip title='Wyświetl event'>
  78. <Icon
  79. type='eye'
  80. className={styles.icon}
  81. onClick={() => {
  82. setEventForPreview(values);
  83. setIsVisible(true);
  84. }}
  85. />
  86. </Tooltip>
  87. <If condition={!isNew}>
  88. <Tooltip title='Duplikuj wydarzenie'>
  89. <Icon
  90. type='copy'
  91. className={cx(
  92. styles.icon,
  93. invalid && styles.iconDisabled
  94. )}
  95. onClick={() => onDuplicate(event.eventId)}
  96. />
  97. </Tooltip>
  98. <Tooltip title='Usuń wydarzenie'>
  99. <Icon
  100. type='delete'
  101. className={cx(styles.icon, styles.iconDelete)}
  102. theme='filled'
  103. onClick={() => onDelete([event.eventId])}
  104. />
  105. </Tooltip>
  106. </If>
  107. </span>
  108. </div>
  109. <div className={styles.wrapperForm}>
  110. <Typography.Title level={4} className={styles.subTitle}>
  111. Nazwa
  112. </Typography.Title>
  113. <hr />
  114. <Input
  115. name='name'
  116. label='Nazwa wydarzenia &#42;'
  117. validate={pipe(
  118. Validators.isRequired,
  119. Validators.min(2),
  120. Validators.max(255)
  121. )}
  122. />
  123. <Typography.Title level={4} className={styles.subTitle}>
  124. Pozycja na stronie
  125. </Typography.Title>
  126. <hr />
  127. <div className={styles.flexBasis45}>
  128. <Select
  129. name='promoted'
  130. label='Pozycja wydarzenia na stronie'
  131. options={eventPositions}
  132. />
  133. </div>
  134. <Typography.Title level={4} className={styles.subTitle}>
  135. Adres
  136. </Typography.Title>
  137. <hr />
  138. <Input
  139. name='locationName'
  140. label='Nazwa miejsca &#42;'
  141. validate={pipe(
  142. Validators.isRequired,
  143. Validators.min(2),
  144. Validators.max(255)
  145. )}
  146. />
  147. <div className={styles.flexBasis60}>
  148. <Input
  149. name='street'
  150. label='Ulica &#42;'
  151. validate={pipe(
  152. Validators.isRequired,
  153. Validators.min(2),
  154. Validators.max(255)
  155. )}
  156. />
  157. </div>
  158. <div className={styles.flexBasis35}>
  159. <Input
  160. name='houseNumber'
  161. label='Numer &#42;'
  162. validate={pipe(
  163. Validators.isRequired,
  164. Validators.max(255)
  165. )}
  166. />
  167. </div>
  168. <div className={styles.flexBasis35}>
  169. <Input
  170. name='zipCode'
  171. label='Kod pocztowy &#42;'
  172. validate={pipe(
  173. Validators.isRequired,
  174. Validators.min(2),
  175. Validators.max(255)
  176. )}
  177. />
  178. </div>
  179. <div className={styles.flexBasis60}>
  180. <Input
  181. name='city'
  182. label='Miasto &#42;'
  183. validate={pipe(
  184. Validators.isRequired,
  185. Validators.min(2),
  186. Validators.max(255)
  187. )}
  188. />
  189. </div>
  190. <Input name='mapLink' label='Google Maps link' />
  191. <Typography.Title level={4} className={styles.subTitle}>
  192. Czas Trwania
  193. </Typography.Title>
  194. <hr />
  195. <div className={styles.flexBasis45}>
  196. <DatePicker
  197. name='startDate'
  198. label='Data od &#42;'
  199. validate={Validators.isRequired}
  200. />
  201. </div>
  202. <div className={styles.flexBasis45}>
  203. <DatePicker
  204. name='endDate'
  205. label='Data do &#42;'
  206. validate={Validators.isRequired}
  207. />
  208. </div>
  209. <div className={styles.flexBasis45}>
  210. <TimePicker
  211. name='startHour'
  212. label='Godzina od &#42;'
  213. validate={Validators.isRequired}
  214. />
  215. </div>
  216. <div className={styles.flexBasis45}>
  217. <TimePicker
  218. name='endHour'
  219. label='Godzina do &#42;'
  220. validate={Validators.isRequired}
  221. />
  222. </div>
  223. <Input
  224. name='timePeriod'
  225. // eslint-disable-next-line max-len
  226. label='Dni tygodnia, w których będzie się odbywać wydarzenie &#42;'
  227. validate={pipe(
  228. Validators.isRequired,
  229. Validators.min(2),
  230. Validators.max(255)
  231. )}
  232. placeholder='Podaj dni tygodnia'
  233. />
  234. <Typography.Title level={4} className={styles.subTitle}>
  235. Opis
  236. </Typography.Title>
  237. <hr />
  238. <Textarea
  239. name='shortDescription'
  240. label='Skrócony opis &#42;'
  241. rows='5'
  242. validate={pipe(
  243. Validators.isRequired,
  244. Validators.min(3),
  245. Validators.max(255)
  246. )}
  247. />
  248. <Textarea
  249. name='longDescription'
  250. label='Pełny opis &#42;'
  251. rows='5'
  252. validate={pipe(
  253. Validators.isRequired,
  254. Validators.min(3),
  255. Validators.max(5000)
  256. )}
  257. />
  258. </div>
  259. <Typography.Title level={4} className={styles.subTitle}>
  260. Zdjęcie &#42;
  261. </Typography.Title>
  262. <hr />
  263. <Field
  264. name='imageField'
  265. render={({ meta }) => (
  266. <React.Fragment>
  267. <ImageBrowser
  268. formValues={values}
  269. updateImage={imageData =>
  270. form.change('newImage', imageData)
  271. }
  272. error={!!(meta.touched && meta.error)}
  273. />
  274. {meta.touched && meta.error && (
  275. <span className={styles.errorField}>{meta.error}</span>
  276. )}
  277. </React.Fragment>
  278. )}
  279. />
  280. <Typography.Title level={4} className={styles.subTitle}>
  281. Mentorzy
  282. </Typography.Title>
  283. <hr />
  284. <Mentors selectedMentors={values.mentors} />
  285. </form>
  286. )}
  287. />
  288. <EventPreview
  289. isVisible={isVisible}
  290. event={eventForPreview}
  291. onOk={() => setIsVisible(false)}
  292. />
  293. </div>
  294. );
  295. };
  296.  
  297. EventForm.propTypes = {
  298. event: PropTypes.object,
  299. onSave: PropTypes.func,
  300. onDelete: PropTypes.func,
  301. onDuplicate: PropTypes.func,
  302. isNew: PropTypes.bool
  303. };
  304.  
  305. export default EventForm;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement