From 31606727b3232bdf49f0fe514298cd85b814187d Mon Sep 17 00:00:00 2001 From: Zeshan Amjad Date: Sun, 14 Oct 2018 23:41:59 +0100 Subject: [PATCH 01/20] Refactor NewEventForm to reduce duplication --- src/components/NewEventPage/NewEventForm.js | 70 +++++++------------ .../UI/DateRangeField/DateRangeField.js | 29 ++++++++ .../DateRangeField/DateRangeField.module.scss | 1 + src/components/UI/Field/Field.js | 26 +++++++ src/components/UI/Field/Field.module.scss | 1 + src/components/UI/NumberField/NumberField.js | 27 +++++++ .../UI/NumberField/NumberField.module.scss | 1 + src/components/UI/TextField/TextField.js | 21 ++++++ .../UI/TextField/TextField.module.scss | 33 +++++++++ 9 files changed, 164 insertions(+), 45 deletions(-) create mode 100644 src/components/UI/DateRangeField/DateRangeField.js create mode 100644 src/components/UI/DateRangeField/DateRangeField.module.scss create mode 100644 src/components/UI/Field/Field.js create mode 100644 src/components/UI/Field/Field.module.scss create mode 100644 src/components/UI/NumberField/NumberField.js create mode 100644 src/components/UI/NumberField/NumberField.module.scss create mode 100644 src/components/UI/TextField/TextField.js create mode 100644 src/components/UI/TextField/TextField.module.scss diff --git a/src/components/NewEventPage/NewEventForm.js b/src/components/NewEventPage/NewEventForm.js index d49d514..5d9aa6f 100644 --- a/src/components/NewEventPage/NewEventForm.js +++ b/src/components/NewEventPage/NewEventForm.js @@ -1,8 +1,9 @@ import React, { Component } from "react"; -import { FormGroup, InputGroup, NumericInput } from "@blueprintjs/core"; -import { DateRangeInput } from "@blueprintjs/datetime"; import styles from "./NewEventForm.module.scss"; import Button from "../UI/Button/Button"; +import TextField from "../UI/TextField/TextField"; +import NumberField from "../UI/NumberField/NumberField"; +import DateRangeField from "../UI/DateRangeField/DateRangeField"; class NewEventForm extends Component { render() { @@ -19,76 +20,55 @@ class NewEventForm extends Component { generateNameField() { return ( - - - + required={true} + placeholder="What is your event's name?" + /> ); } generateLocationField() { return ( - - - + required={true} + placeholder="Where is your event being held?" + /> ); } generateAttendanceField() { return ( - - - + required={true} + icon="people" + placeholder="What is your event's maximum capacity?" + min={1} + max={200000} + /> ); } generateTimingField() { return ( - - date.toLocaleString()} - parseDate={str => new Date(str)} - shortcuts={false} - allowSingleDayRange={true} - closeOnSelection={true} - contiguousCalendarMonths={true} - minDate={new Date()} - maxDate={new Date("2040-12-31")} - /> - + required={true} + minDate={new Date()} + maxDate={new Date("2040-12-31")} + /> ); } diff --git a/src/components/UI/DateRangeField/DateRangeField.js b/src/components/UI/DateRangeField/DateRangeField.js new file mode 100644 index 0000000..40c8bb0 --- /dev/null +++ b/src/components/UI/DateRangeField/DateRangeField.js @@ -0,0 +1,29 @@ +import React from "react"; +import PropTypes from "prop-types"; +import Field from "../Field/Field"; +import { DateRangeInput } from "@blueprintjs/datetime"; + +const DateRangeField = props => { + return ( + + date.toLocaleString()} + parseDate={str => new Date(str)} + shortcuts={false} + allowSingleDayRange={true} + closeOnSelection={true} + contiguousCalendarMonths={true} + minDate={props.minDate} + maxDate={props.maxDate} + /> + + ); +}; + +DateRangeField.propTypes = { + ...Field.propTypes, + minDate: PropTypes.object, + maxDate: PropTypes.object +}; + +export default DateRangeField; diff --git a/src/components/UI/DateRangeField/DateRangeField.module.scss b/src/components/UI/DateRangeField/DateRangeField.module.scss new file mode 100644 index 0000000..24370cd --- /dev/null +++ b/src/components/UI/DateRangeField/DateRangeField.module.scss @@ -0,0 +1 @@ +@import "../../../styles/_vars.scss"; diff --git a/src/components/UI/Field/Field.js b/src/components/UI/Field/Field.js new file mode 100644 index 0000000..3263ff4 --- /dev/null +++ b/src/components/UI/Field/Field.js @@ -0,0 +1,26 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { FormGroup } from "@blueprintjs/core"; + +const Field = props => { + return ( + + {props.children} + + ); +}; + +Field.propTypes = { + className: PropTypes.string, + label: PropTypes.string, + labelFor: PropTypes.string, + required: PropTypes.bool, + children: PropTypes.element +}; + +export default Field; diff --git a/src/components/UI/Field/Field.module.scss b/src/components/UI/Field/Field.module.scss new file mode 100644 index 0000000..24370cd --- /dev/null +++ b/src/components/UI/Field/Field.module.scss @@ -0,0 +1 @@ +@import "../../../styles/_vars.scss"; diff --git a/src/components/UI/NumberField/NumberField.js b/src/components/UI/NumberField/NumberField.js new file mode 100644 index 0000000..a62c0a1 --- /dev/null +++ b/src/components/UI/NumberField/NumberField.js @@ -0,0 +1,27 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { NumericInput } from "@blueprintjs/core"; +import Field from "../Field/Field"; + +const NumberField = props => { + return ( + + + + ); +}; + +NumberField.propTypes = { + ...Field.propTypes, + min: PropTypes.number, + max: PropTypes.number +}; + +export default NumberField; diff --git a/src/components/UI/NumberField/NumberField.module.scss b/src/components/UI/NumberField/NumberField.module.scss new file mode 100644 index 0000000..24370cd --- /dev/null +++ b/src/components/UI/NumberField/NumberField.module.scss @@ -0,0 +1 @@ +@import "../../../styles/_vars.scss"; diff --git a/src/components/UI/TextField/TextField.js b/src/components/UI/TextField/TextField.js new file mode 100644 index 0000000..706d215 --- /dev/null +++ b/src/components/UI/TextField/TextField.js @@ -0,0 +1,21 @@ +import React from "react"; +import { InputGroup } from "@blueprintjs/core"; +import Field from "../Field/Field"; + +const TextField = props => { + return ( + + + + ); +}; + +TextField.propTypes = { + ...Field.propTypes +}; + +export default TextField; diff --git a/src/components/UI/TextField/TextField.module.scss b/src/components/UI/TextField/TextField.module.scss new file mode 100644 index 0000000..16a8ef4 --- /dev/null +++ b/src/components/UI/TextField/TextField.module.scss @@ -0,0 +1,33 @@ +@import "../../../styles/_vars.scss"; + +.photoBG { + display: block; + position: relative; + width: 100%; + + img { + margin-bottom: -5px; + width: 100%; + } + + .imageOverlay { + background-color: rgba(darken($highlight, 20%), 0.6); + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100%; + } + + h2 { + color: #fff; + font-weight: 500; + left: 50%; + margin: 0; + position: absolute; + text-align: center; + top: 50%; + transform: translate(-50%, -50%); + width: 100%; + } +} From eb8d4ba1cbdc49e6b70f5fe65a62741597b35837 Mon Sep 17 00:00:00 2001 From: Zeshan Amjad Date: Mon, 15 Oct 2018 01:14:59 +0100 Subject: [PATCH 02/20] Add map-related fields to Create New Event form --- src/components/NewEventPage/NewEventForm.js | 86 +++++++++++-- .../NewEventPage/NewEventForm.module.scss | 33 ++++- src/components/Page/Page.module.scss | 4 + src/components/UI/Field/Field.js | 6 +- src/components/UI/Field/Field.module.scss | 6 + src/components/UI/FileField/FileField.js | 23 ++++ .../UI/FileField/FileField.module.scss | 7 ++ src/index.scss | 116 +++++++++++++++++- src/styles/_colors.scss | 2 + 9 files changed, 265 insertions(+), 18 deletions(-) create mode 100644 src/components/UI/FileField/FileField.js create mode 100644 src/components/UI/FileField/FileField.module.scss diff --git a/src/components/NewEventPage/NewEventForm.js b/src/components/NewEventPage/NewEventForm.js index 5d9aa6f..08802a4 100644 --- a/src/components/NewEventPage/NewEventForm.js +++ b/src/components/NewEventPage/NewEventForm.js @@ -4,18 +4,30 @@ import Button from "../UI/Button/Button"; import TextField from "../UI/TextField/TextField"; import NumberField from "../UI/NumberField/NumberField"; import DateRangeField from "../UI/DateRangeField/DateRangeField"; +import FileField from "../UI/FileField/FileField"; class NewEventForm extends Component { render() { - return ( -
- {this.generateNameField()} - {this.generateLocationField()} - {this.generateAttendanceField()} - {this.generateTimingField()} + return [ +
+

Basic Info

+
+ {this.generateNameField()} + {this.generateLocationField()} + {this.generateAttendanceField()} + {this.generateTimingField()} + {this.generateCoverPhotoField()} +
+
, +
+

Mapping Details

+
+ {this.generateMapImageField()} + {this.generateMapWidthField()} +
{this.generateSubmitButton()} -
- ); + + ]; } generateNameField() { @@ -38,6 +50,7 @@ class NewEventForm extends Component { icon="geolocation" label="Location" labelFor="location" + helperText="This can be imprecise, e.g. Leeds, UK" required={true} placeholder="Where is your event being held?" /> @@ -72,11 +85,62 @@ class NewEventForm extends Component { ); } + generateCoverPhotoField() { + return ( + + ); + } + + generateMapImageField() { + return ( +
+ +
+ ); + } + + generateMapWidthField() { + return ( + + ); + } + generateSubmitButton() { return ( - +
+ +
); } diff --git a/src/components/NewEventPage/NewEventForm.module.scss b/src/components/NewEventPage/NewEventForm.module.scss index 64a0996..930a356 100644 --- a/src/components/NewEventPage/NewEventForm.module.scss +++ b/src/components/NewEventPage/NewEventForm.module.scss @@ -1,14 +1,29 @@ @import "../../styles/_vars.scss"; .formGroups { - display: flex; - flex-wrap: wrap; margin-top: 30px; - max-width: 900px; + max-width: 840px; + + h2 { + color: $midText; + margin: 0 0 20px 0; + width: 100%; + } + + .fields { + display: flex; + flex-wrap: wrap; + + & > *:nth-child(even) { + margin-right: 0; + } + } } +$formGroupMargin: 40px; + .formGroup { - margin: 0 40px 40px 0; + margin: 0 $formGroupMargin $formGroupMargin 0; max-width: 600px; min-width: 400px; @@ -34,3 +49,13 @@ } } } + +.fileField { + margin: 0 $formGroupMargin $formGroupMargin 0; + width: 400px; +} + +.submitButtonWrapper { + text-align: right; + width: 100%; +} diff --git a/src/components/Page/Page.module.scss b/src/components/Page/Page.module.scss index 57830ce..cf5c4da 100644 --- a/src/components/Page/Page.module.scss +++ b/src/components/Page/Page.module.scss @@ -1 +1,5 @@ @import "../../styles/_vars.scss"; + +.title { + color: $darkText; +} diff --git a/src/components/UI/Field/Field.js b/src/components/UI/Field/Field.js index 3263ff4..359fa93 100644 --- a/src/components/UI/Field/Field.js +++ b/src/components/UI/Field/Field.js @@ -1,5 +1,6 @@ import React from "react"; import PropTypes from "prop-types"; +import styles from "./Field.module.scss"; // eslint-disable-line import { FormGroup } from "@blueprintjs/core"; const Field = props => { @@ -9,6 +10,7 @@ const Field = props => { label={props.label} labelFor={props.labelFor} labelInfo={props.required ? "(required)" : ""} + helperText={props.helperText} > {props.children} @@ -19,8 +21,10 @@ Field.propTypes = { className: PropTypes.string, label: PropTypes.string, labelFor: PropTypes.string, + helperText: PropTypes.string, required: PropTypes.bool, - children: PropTypes.element + children: PropTypes.element, + onInputChange: PropTypes.func }; export default Field; diff --git a/src/components/UI/Field/Field.module.scss b/src/components/UI/Field/Field.module.scss index 24370cd..1fcf9b9 100644 --- a/src/components/UI/Field/Field.module.scss +++ b/src/components/UI/Field/Field.module.scss @@ -1 +1,7 @@ @import "../../../styles/_vars.scss"; + +:global { + .bp3-form-group .bp3-form-content .bp3-form-helper-text { + margin-top: 12px; + } +} diff --git a/src/components/UI/FileField/FileField.js b/src/components/UI/FileField/FileField.js new file mode 100644 index 0000000..9b44553 --- /dev/null +++ b/src/components/UI/FileField/FileField.js @@ -0,0 +1,23 @@ +import React from "react"; +import { FileInput } from "@blueprintjs/core"; +import styles from "./FileField.module.scss"; +import Field from "../Field/Field"; + +const FileField = props => { + return ( + + event} + /> + + ); +}; + +FileField.propTypes = { + ...Field.propTypes +}; + +export default FileField; diff --git a/src/components/UI/FileField/FileField.module.scss b/src/components/UI/FileField/FileField.module.scss new file mode 100644 index 0000000..dc83ffb --- /dev/null +++ b/src/components/UI/FileField/FileField.module.scss @@ -0,0 +1,7 @@ +@import "../../../styles/_vars.scss"; + +:global { + .bp3-large .bp3-file-upload-input { + width: 400px; + } +} diff --git a/src/index.scss b/src/index.scss index 3cc7cc2..60b6f44 100644 --- a/src/index.scss +++ b/src/index.scss @@ -1,5 +1,61 @@ @import "./styles/_vars.scss"; +@font-face { + font-family: "Cerebri Sans"; + font-style: italic; + font-weight: bold; + src: url("/fonts/CerebriSans-BoldItalic.woff2") format("woff2"), + url("/fonts/CerebriSans-BoldItalic.woff") format("woff"); +} + +@font-face { + font-family: "Cerebri Sans"; + font-style: normal; + font-weight: 300; + src: url("/fonts/CerebriSans-Light.woff2") format("woff2"), + url("/fonts/CerebriSans-Light.woff") format("woff"); +} + +@font-face { + font-family: "Cerebri Sans"; + font-style: italic; + font-weight: 800; + src: url("/fonts/CerebriSans-ExtraBoldItalic.woff2") format("woff2"), + url("/fonts/CerebriSans-ExtraBoldItalic.woff") format("woff"); +} + +@font-face { + font-family: "Cerebri Sans"; + font-style: normal; + font-weight: 600; + src: url("/fonts/CerebriSans-SemiBold.woff2") format("woff2"), + url("/fonts/CerebriSans-SemiBold.woff") format("woff"); +} + +@font-face { + font-family: "Cerebri Sans"; + font-style: italic; + font-weight: 500; + src: url("/fonts/CerebriSans-MediumItalic.woff2") format("woff2"), + url("/fonts/CerebriSans-MediumItalic.woff") format("woff"); +} + +@font-face { + font-family: "Cerebri Sans"; + font-style: italic; + font-weight: 900; + src: url("/fonts/CerebriSans-HeavyItalic.woff2") format("woff2"), + url("/fonts/CerebriSans-HeavyItalic.woff") format("woff"); +} + +@font-face { + font-family: "Cerebri Sans Book"; + font-style: normal; + font-weight: normal; + src: url("/fonts/CerebriSans-Book.woff2") format("woff2"), + url("/fonts/CerebriSans-Book.woff") format("woff"); +} + @font-face { font-family: "Cerebri Sans"; font-style: normal; @@ -8,12 +64,68 @@ url("/fonts/CerebriSans-Regular.woff") format("woff"); } +@font-face { + font-family: "Cerebri Sans"; + font-style: italic; + font-weight: normal; + src: url("/fonts/CerebriSans-Italic.woff2") format("woff2"), + url("/fonts/CerebriSans-Italic.woff") format("woff"); +} + @font-face { font-family: "Cerebri Sans"; font-style: normal; font-weight: 500; - src: url("fonts/CerebriSans-Medium.woff2") format("woff2"), - url("fonts/CerebriSans-Medium.woff") format("woff"); + src: url("/fonts/CerebriSans-Medium.woff2") format("woff2"), + url("/fonts/CerebriSans-Medium.woff") format("woff"); +} + +@font-face { + font-family: "Cerebri Sans"; + font-style: italic; + font-weight: 600; + src: url("/fonts/CerebriSans-SemiBoldItalic.woff2") format("woff2"), + url("/fonts/CerebriSans-SemiBoldItalic.woff") format("woff"); +} + +@font-face { + font-family: "Cerebri Sans"; + font-style: normal; + font-weight: bold; + src: url("/fonts/CerebriSans-Bold.woff2") format("woff2"), + url("/fonts/CerebriSans-Bold.woff") format("woff"); +} + +@font-face { + font-family: "Cerebri Sans"; + font-style: normal; + font-weight: 800; + src: url("/fonts/CerebriSans-ExtraBold.woff2") format("woff2"), + url("/fonts/CerebriSans-ExtraBold.woff") format("woff"); +} + +@font-face { + font-family: "Cerebri Sans"; + font-style: normal; + font-weight: 900; + src: url("/fonts/CerebriSans-Heavy.woff2") format("woff2"), + url("/fonts/CerebriSans-Heavy.woff") format("woff"); +} + +@font-face { + font-family: "Cerebri Sans"; + font-style: italic; + font-weight: 300; + src: url("/fonts/CerebriSans-LightItalic.woff2") format("woff2"), + url("/fonts/CerebriSans-LightItalic.woff") format("woff"); +} + +@font-face { + font-family: "Cerebri Sans Book"; + font-style: italic; + font-weight: normal; + src: url("/fonts/CerebriSans-BookItalic.woff2") format("woff2"), + url("/fonts/CerebriSans-BookItalic.woff") format("woff"); } body.body { diff --git a/src/styles/_colors.scss b/src/styles/_colors.scss index 27ca36a..bde981a 100644 --- a/src/styles/_colors.scss +++ b/src/styles/_colors.scss @@ -2,4 +2,6 @@ $highlight: #514abf; $contentBackground: #fff; $secondaryBackground: #fbfcfc; $mainText: #646e82; +$midText: #626088; +$darkText: #322f5f; $lightestText: #8f8dc1; From 81ffb834087c9adb1e44b538691923affd7c3f6b Mon Sep 17 00:00:00 2001 From: Zeshan Amjad Date: Tue, 16 Oct 2018 20:03:51 +0100 Subject: [PATCH 03/20] Remove indoor-mapping fields from Create New Event form --- src/components/NewEventPage/NewEventForm.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/components/NewEventPage/NewEventForm.js b/src/components/NewEventPage/NewEventForm.js index 08802a4..94bb488 100644 --- a/src/components/NewEventPage/NewEventForm.js +++ b/src/components/NewEventPage/NewEventForm.js @@ -8,6 +8,17 @@ import FileField from "../UI/FileField/FileField"; class NewEventForm extends Component { render() { + /* + const indoorMappingDetails = ( +
+

Mapping Details

+
+ {this.generateMapImageField()} + {this.generateMapWidthField()} +
+
+ ); + */ return [

Basic Info

@@ -17,15 +28,8 @@ class NewEventForm extends Component { {this.generateAttendanceField()} {this.generateTimingField()} {this.generateCoverPhotoField()} + {this.generateSubmitButton()} -
, -
-

Mapping Details

-
- {this.generateMapImageField()} - {this.generateMapWidthField()} -
- {this.generateSubmitButton()}
]; } From a2e1d6aec20fc0f3391ce839328d1b11951bfee9 Mon Sep 17 00:00:00 2001 From: Zeshan Amjad Date: Tue, 16 Oct 2018 20:25:38 +0100 Subject: [PATCH 04/20] Update Redux store when a new event is created --- src/components/EventsPage/EventsPage.js | 31 +++------------------ src/components/NewEventPage/NewEventForm.js | 9 +++++- src/eventsMock.js | 11 ++++++++ src/reducers/index.js | 22 ++++++++++++--- 4 files changed, 41 insertions(+), 32 deletions(-) diff --git a/src/components/EventsPage/EventsPage.js b/src/components/EventsPage/EventsPage.js index fb88f0b..c8b8c97 100644 --- a/src/components/EventsPage/EventsPage.js +++ b/src/components/EventsPage/EventsPage.js @@ -4,36 +4,13 @@ import { Card } from "@blueprintjs/core"; import Page from "../Page/Page"; import Button from "../UI/Button/Button"; import styles from "./EventsPage.module.scss"; +import store from "../../store"; +import _ from "lodash"; export class EventsPage extends Component { /* TODO: Replace this to integrate with back-end */ fetchEvents() { - return [ - { - name: "Leeds Festival", - eventID: "312839", - location: "Leeds, United Kingdom", - startDate: "2018-08-25", - endDate: "2018-08-30", - maxAttendance: "150000" - }, - { - name: "Reading Festival", - eventID: "312840", - location: "Reading, United Kingdom", - startDate: "2018-08-25", - endDate: "2018-08-30", - maxAttendance: "150000" - }, - { - name: "Glastonbury", - eventID: "312841", - location: "Somerset, United Kingdom", - startDate: "2018-08-25", - endDate: "2018-08-30", - maxAttendance: "150000" - } - ]; + return store.getState().events; } generateImage(eventName) { @@ -93,7 +70,7 @@ export class EventsPage extends Component { render() { const eventData = this.fetchEvents(); - const events = eventData.map(event => this.generateEventCard(event)); + const events = _.map(eventData, event => this.generateEventCard(event)); return (
{events}
diff --git a/src/components/NewEventPage/NewEventForm.js b/src/components/NewEventPage/NewEventForm.js index 94bb488..d7f59b0 100644 --- a/src/components/NewEventPage/NewEventForm.js +++ b/src/components/NewEventPage/NewEventForm.js @@ -5,6 +5,8 @@ import TextField from "../UI/TextField/TextField"; import NumberField from "../UI/NumberField/NumberField"; import DateRangeField from "../UI/DateRangeField/DateRangeField"; import FileField from "../UI/FileField/FileField"; +import store from "../../store"; +import { newEventMock } from "../../eventsMock"; class NewEventForm extends Component { render() { @@ -150,7 +152,12 @@ class NewEventForm extends Component { /* TODO: Actually submit the form and then redirect to the next page. */ submitForm() { - alert("Submitted!"); + store.dispatch({ + type: "CREATE_NEW_EVENT", + payload: { + event: newEventMock + } + }); } } diff --git a/src/eventsMock.js b/src/eventsMock.js index a897b58..39f1928 100644 --- a/src/eventsMock.js +++ b/src/eventsMock.js @@ -31,4 +31,15 @@ const eventsMock = { } }; +export const newEventMock = { + name: "Latitude Festival", + eventID: "312842", + location: "Suffolk, United Kingdom", + startDate: "2019-07-18", + endDate: "2019-07-21", + maxAttendance: "150000", + coverPhoto: + "https://www.latitudefestival.com/sites/live.inviqa.latitudefestival.com/files/images/news/kennerdeigh_scott_-_latitude_festival_2016_-_01f666ea-4db3-11e6-b71f-3645563dd1ea_-_api.jpg" +}; + export default eventsMock; diff --git a/src/reducers/index.js b/src/reducers/index.js index 8a65002..f766921 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -3,7 +3,7 @@ import _ from "lodash"; export default (state, action) => { switch (action.type) { /* LOAD_EVENTS: Called when the list of events is loaded from the server. */ - case "LOAD_EVENTS": + case "LOAD_EVENTS": { return { ...state, selectedEvent: _.isEmpty(action.payload.events) @@ -11,15 +11,29 @@ export default (state, action) => { : _.values(action.payload.events)[0], events: action.payload.events }; - + } /* SELECT_NEW_EVENT: Called when a different event is selected in the * sidebar. */ - case "SELECT_NEW_EVENT": + case "SELECT_NEW_EVENT": { return { ...state, selectedEvent: action.payload.selectedEvent }; - default: + } + /* CREATE_NEW_EVENT: Called when a new event is successfully created */ + case "CREATE_NEW_EVENT": { + const updatedEvents = { + ...state.events + }; + updatedEvents[action.payload.event.eventID] = action.payload.event; + return { + ...state, + events: updatedEvents, + selectedEvent: action.payload.event + }; + } + default: { return state; + } } }; From d0e86d94ec4272119fe6c34b0418013f570405f7 Mon Sep 17 00:00:00 2001 From: Zeshan Amjad Date: Tue, 16 Oct 2018 21:45:27 +0100 Subject: [PATCH 05/20] Navigate to 'Add Regions' page on new event creation --- src/CrowdApp.js | 4 ++- src/CrowdApp.routing.js | 9 ++++++ .../AddRegionsPage/AddRegionsPage.js | 16 ++++++++++ .../AddRegionsPage/AddRegionsPage.module.scss | 1 + src/components/EventsPage/EventsPage.js | 6 ---- .../EventsPage/EventsPage.module.scss | 5 ---- src/components/NewEventPage/NewEventForm.js | 10 +++---- src/components/Page/Page.js | 2 ++ .../UI/NavigateButton/NavigateButton.js | 30 +++++++++++++++++++ .../NavigateButton/NavigateButton.module.scss | 1 + 10 files changed, 67 insertions(+), 17 deletions(-) create mode 100644 src/components/AddRegionsPage/AddRegionsPage.js create mode 100644 src/components/AddRegionsPage/AddRegionsPage.module.scss create mode 100644 src/components/UI/NavigateButton/NavigateButton.js create mode 100644 src/components/UI/NavigateButton/NavigateButton.module.scss diff --git a/src/CrowdApp.js b/src/CrowdApp.js index bd351a4..a34577e 100644 --- a/src/CrowdApp.js +++ b/src/CrowdApp.js @@ -18,7 +18,9 @@ class CrowdApp extends Component { name={route.name} path={route.path} exact={route.exact} - render={() => } + render={() => ( + + )} /> )); } diff --git a/src/CrowdApp.routing.js b/src/CrowdApp.routing.js index 8f6f226..d0ce6e0 100644 --- a/src/CrowdApp.routing.js +++ b/src/CrowdApp.routing.js @@ -2,6 +2,7 @@ import { EventsPage } from "./components/EventsPage/EventsPage"; import NewEventPage from "./components/NewEventPage/NewEventPage"; import React from "react"; +import { AddRegionsPage } from "./components/AddRegionsPage/AddRegionsPage"; const routes = [ { @@ -18,6 +19,14 @@ const routes = [ content: NewEventPage, inSidebar: false }, + { + path: "/event/addRegions", + name: "Add Regions", + description: + "Regions are either Bluetooth iBeacons or GPS coordinates with a radius, both of which can be used represent a point of interest at your event.", + content: AddRegionsPage, + inSidebar: false + }, { path: "/maps", name: "Maps", diff --git a/src/components/AddRegionsPage/AddRegionsPage.js b/src/components/AddRegionsPage/AddRegionsPage.js new file mode 100644 index 0000000..6452204 --- /dev/null +++ b/src/components/AddRegionsPage/AddRegionsPage.js @@ -0,0 +1,16 @@ +import React from "react"; +import PropTypes from "prop-types"; +import Page from "../Page/Page"; + +export const AddRegionsPage = props => { + return ( + {props.name}} description={props.description} /> + ); +}; + +AddRegionsPage.propTypes = { + name: PropTypes.string, + description: PropTypes.string +}; + +export default AddRegionsPage; diff --git a/src/components/AddRegionsPage/AddRegionsPage.module.scss b/src/components/AddRegionsPage/AddRegionsPage.module.scss new file mode 100644 index 0000000..57830ce --- /dev/null +++ b/src/components/AddRegionsPage/AddRegionsPage.module.scss @@ -0,0 +1 @@ +@import "../../styles/_vars.scss"; diff --git a/src/components/EventsPage/EventsPage.js b/src/components/EventsPage/EventsPage.js index c8b8c97..d60581d 100644 --- a/src/components/EventsPage/EventsPage.js +++ b/src/components/EventsPage/EventsPage.js @@ -2,7 +2,6 @@ import React, { Component } from "react"; import PropTypes from "prop-types"; import { Card } from "@blueprintjs/core"; import Page from "../Page/Page"; -import Button from "../UI/Button/Button"; import styles from "./EventsPage.module.scss"; import store from "../../store"; import _ from "lodash"; @@ -59,11 +58,6 @@ export class EventsPage extends Component { return (
{pageName}
-
- -
); } diff --git a/src/components/EventsPage/EventsPage.module.scss b/src/components/EventsPage/EventsPage.module.scss index 31f74f2..117e9bd 100644 --- a/src/components/EventsPage/EventsPage.module.scss +++ b/src/components/EventsPage/EventsPage.module.scss @@ -5,11 +5,6 @@ vertical-align: middle; } -.newEventLink { - display: inline-block; - margin-left: 15px; -} - .eventsWrapper { display: flex; flex-wrap: wrap; diff --git a/src/components/NewEventPage/NewEventForm.js b/src/components/NewEventPage/NewEventForm.js index d7f59b0..b8465e0 100644 --- a/src/components/NewEventPage/NewEventForm.js +++ b/src/components/NewEventPage/NewEventForm.js @@ -1,12 +1,12 @@ import React, { Component } from "react"; import styles from "./NewEventForm.module.scss"; -import Button from "../UI/Button/Button"; import TextField from "../UI/TextField/TextField"; import NumberField from "../UI/NumberField/NumberField"; import DateRangeField from "../UI/DateRangeField/DateRangeField"; import FileField from "../UI/FileField/FileField"; import store from "../../store"; import { newEventMock } from "../../eventsMock"; +import NavigateButton from "../UI/NavigateButton/NavigateButton"; class NewEventForm extends Component { render() { @@ -139,13 +139,13 @@ class NewEventForm extends Component { generateSubmitButton() { return (
- + navigateToRoute={"/event/addRegions"} + text="Create Event" + />
); } diff --git a/src/components/Page/Page.js b/src/components/Page/Page.js index 42d303f..8b3bbf0 100644 --- a/src/components/Page/Page.js +++ b/src/components/Page/Page.js @@ -6,6 +6,7 @@ export const Page = props => { return (

{props.title}

+ {props.description ?

{props.description}

: ""}
{props.children}
); @@ -13,6 +14,7 @@ export const Page = props => { Page.propTypes = { title: PropTypes.element, + description: PropTypes.string, children: PropTypes.element }; diff --git a/src/components/UI/NavigateButton/NavigateButton.js b/src/components/UI/NavigateButton/NavigateButton.js new file mode 100644 index 0000000..0085663 --- /dev/null +++ b/src/components/UI/NavigateButton/NavigateButton.js @@ -0,0 +1,30 @@ +import React from "react"; +import PropTypes from "prop-types"; +import Button from "../Button/Button"; +import { withRouter } from "react-router-dom"; + +const NavigateButton = withRouter(props => ( + +)); + +NavigateButton.defaultProps = { + rightIcon: "chevron-right" +}; + +NavigateButton.propTypes = { + onClick: PropTypes.func, + navigateToRoute: PropTypes.string, + text: PropTypes.string, + className: PropTypes.string +}; + +export default NavigateButton; diff --git a/src/components/UI/NavigateButton/NavigateButton.module.scss b/src/components/UI/NavigateButton/NavigateButton.module.scss new file mode 100644 index 0000000..24370cd --- /dev/null +++ b/src/components/UI/NavigateButton/NavigateButton.module.scss @@ -0,0 +1 @@ +@import "../../../styles/_vars.scss"; From 0c8a66a4d11b0e5ba74b175a42a4cb27ada9949c Mon Sep 17 00:00:00 2001 From: Zeshan Amjad Date: Tue, 16 Oct 2018 23:29:45 +0100 Subject: [PATCH 06/20] Display Google Map in flex layout on Add Regions page --- package-lock.json | 69 +++++++++++++++++++ package.json | 1 + .../AddRegionsMap/AddRegionsMap.js | 15 ++++ .../AddRegionsMap/AddRegionsMap.module.scss | 1 + .../AddRegionsPage/AddRegionsPage.js | 17 ++++- .../AddRegionsPage/AddRegionsPage.module.scss | 4 ++ src/components/Page/Page.js | 13 ++-- src/components/Page/Page.module.scss | 17 +++++ 8 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 src/components/AddRegionsPage/AddRegionsMap/AddRegionsMap.js create mode 100644 src/components/AddRegionsPage/AddRegionsMap/AddRegionsMap.module.scss diff --git a/package-lock.json b/package-lock.json index c856711..6cd50b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2561,6 +2561,11 @@ } } }, + "can-use-dom": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/can-use-dom/-/can-use-dom-0.1.0.tgz", + "integrity": "sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo=" + }, "caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -2611,6 +2616,11 @@ "supports-color": "^5.3.0" } }, + "change-emitter": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz", + "integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU=" + }, "character-entities": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", @@ -6161,6 +6171,11 @@ } } }, + "google-maps-infobox": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/google-maps-infobox/-/google-maps-infobox-2.0.0.tgz", + "integrity": "sha512-hTuWmWZZSOxf5D/z7l3/hTF1grgRvLG53BEKMdjiKOG+FcK/kH7vqseUeyIU9Zj2ZIqKTOaro0nknxpAuRq4Vw==" + }, "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", @@ -8754,6 +8769,16 @@ "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==", "dev": true }, + "marker-clusterer-plus": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/marker-clusterer-plus/-/marker-clusterer-plus-2.1.4.tgz", + "integrity": "sha1-+O/3TVmdqzt9Dj/tUmTqDnBPXWc=" + }, + "markerwithlabel": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/markerwithlabel/-/markerwithlabel-2.0.2.tgz", + "integrity": "sha512-C/cbm1A0h/u54gwHk5ZJNdUU3V3+1BbCpRPMsMyFA7vF4yL+aB4rWpxACz29TpQ+cTg6/iQroExh0PMSRGtQFg==" + }, "math-random": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", @@ -13100,6 +13125,34 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-5.0.4.tgz", "integrity": "sha512-grVJtoDzIbSMYgy5rKbSOmt2FvzR4iJnpMBjXmZolSYJM5acQvBHoEbBBNW0FzTE/TLZMZ+gSy0bAHydc1hFEw==" }, + "react-google-maps": { + "version": "9.4.5", + "resolved": "https://registry.npmjs.org/react-google-maps/-/react-google-maps-9.4.5.tgz", + "integrity": "sha512-8z5nX9DxIcBCXuEiurmRT1VXVwnzx0C6+3Es6lxB2/OyY2SLax2/LcDu6Aldxnl3HegefTL7NJzGeaKAJ61pOA==", + "requires": { + "babel-runtime": "^6.11.6", + "can-use-dom": "^0.1.0", + "google-maps-infobox": "^2.0.0", + "invariant": "^2.2.1", + "lodash": "^4.16.2", + "marker-clusterer-plus": "^2.1.4", + "markerwithlabel": "^2.0.1", + "prop-types": "^15.5.8", + "recompose": "^0.26.0", + "scriptjs": "^2.5.8", + "warning": "^3.0.0" + }, + "dependencies": { + "warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", + "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", + "requires": { + "loose-envify": "^1.0.0" + } + } + } + }, "react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", @@ -13589,6 +13642,17 @@ "util.promisify": "^1.0.0" } }, + "recompose": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.26.0.tgz", + "integrity": "sha512-KwOu6ztO0mN5vy3+zDcc45lgnaUoaQse/a5yLVqtzTK13czSWnFGmXbQVmnoMgDkI5POd1EwIKSbjU1V7xdZog==", + "requires": { + "change-emitter": "^0.1.2", + "fbjs": "^0.8.1", + "hoist-non-react-statics": "^2.3.1", + "symbol-observable": "^1.0.4" + } + }, "recursive-readdir": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", @@ -14530,6 +14594,11 @@ } } }, + "scriptjs": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/scriptjs/-/scriptjs-2.5.9.tgz", + "integrity": "sha512-qGVDoreyYiP1pkQnbnFAUIS5AjenNwwQBdl7zeos9etl+hYKWahjRTfzAZZYBv5xNHx7vNKCmaLDQZ6Fr2AEXg==" + }, "scss-tokenizer": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", diff --git a/package.json b/package.json index d101a5d..e55eb5a 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "prop-types": "latest", "react": "^16.5.2", "react-dom": "^16.5.2", + "react-google-maps": "^9.4.5", "react-router-dom": "^4.3.1", "react-scripts": "2.0.4", "redux": "^4.0.1" diff --git a/src/components/AddRegionsPage/AddRegionsMap/AddRegionsMap.js b/src/components/AddRegionsPage/AddRegionsMap/AddRegionsMap.js new file mode 100644 index 0000000..1a55266 --- /dev/null +++ b/src/components/AddRegionsPage/AddRegionsMap/AddRegionsMap.js @@ -0,0 +1,15 @@ +import React from "react"; +import { GoogleMap, withGoogleMap, withScriptjs } from "react-google-maps"; + +const AddRegionsMap = withScriptjs( + withGoogleMap(() => { + return ( + + ); + }) +); + +export default AddRegionsMap; diff --git a/src/components/AddRegionsPage/AddRegionsMap/AddRegionsMap.module.scss b/src/components/AddRegionsPage/AddRegionsMap/AddRegionsMap.module.scss new file mode 100644 index 0000000..24370cd --- /dev/null +++ b/src/components/AddRegionsPage/AddRegionsMap/AddRegionsMap.module.scss @@ -0,0 +1 @@ +@import "../../../styles/_vars.scss"; diff --git a/src/components/AddRegionsPage/AddRegionsPage.js b/src/components/AddRegionsPage/AddRegionsPage.js index 6452204..8c84849 100644 --- a/src/components/AddRegionsPage/AddRegionsPage.js +++ b/src/components/AddRegionsPage/AddRegionsPage.js @@ -1,10 +1,25 @@ import React from "react"; import PropTypes from "prop-types"; import Page from "../Page/Page"; +import AddRegionsMap from "./AddRegionsMap/AddRegionsMap"; +import styles from "./AddRegionsPage.module.scss"; export const AddRegionsPage = props => { + const mapContainer =
; + const MAPS_API_KEY = "AIzaSyDaIck1_kxNWiyEQetkb_DH78bV6T7Lz-g"; return ( - {props.name}} description={props.description} /> + {props.name}} + description={props.description} + flex={true} + > + } + containerElement={mapContainer} + mapElement={
} + /> + ); }; diff --git a/src/components/AddRegionsPage/AddRegionsPage.module.scss b/src/components/AddRegionsPage/AddRegionsPage.module.scss index 57830ce..5dc9954 100644 --- a/src/components/AddRegionsPage/AddRegionsPage.module.scss +++ b/src/components/AddRegionsPage/AddRegionsPage.module.scss @@ -1 +1,5 @@ @import "../../styles/_vars.scss"; + +.mapContainer { + height: 100%; +} diff --git a/src/components/Page/Page.js b/src/components/Page/Page.js index 8b3bbf0..dc8112f 100644 --- a/src/components/Page/Page.js +++ b/src/components/Page/Page.js @@ -4,10 +4,14 @@ import styles from "./Page.module.scss"; export const Page = props => { return ( -
+

{props.title}

- {props.description ?

{props.description}

: ""} -
{props.children}
+ {props.description ? ( +

{props.description}

+ ) : ( + "" + )} +
{props.children}
); }; @@ -15,7 +19,8 @@ export const Page = props => { Page.propTypes = { title: PropTypes.element, description: PropTypes.string, - children: PropTypes.element + children: PropTypes.element, + flex: PropTypes.bool }; export default Page; diff --git a/src/components/Page/Page.module.scss b/src/components/Page/Page.module.scss index cf5c4da..4c50649 100644 --- a/src/components/Page/Page.module.scss +++ b/src/components/Page/Page.module.scss @@ -1,5 +1,22 @@ @import "../../styles/_vars.scss"; +.flexContainer { + display: flex; + flex-direction: column; + height: 100%; + + .pageContent { + flex: 1; + padding-bottom: 25px; + } +} + .title { color: $darkText; } + +.description { + color: $midText; + margin-bottom: 20px; + margin-top: -15px; +} From 91154eeda47795c904bed8a45c6e7cb5bbb8b06b Mon Sep 17 00:00:00 2001 From: Zeshan Amjad Date: Tue, 16 Oct 2018 23:56:10 +0100 Subject: [PATCH 07/20] Refactor Redux store to only store ID of selected event --- .../Sidebar/EventSelector/EventSelector.js | 10 ++++++---- src/components/Sidebar/Sidebar.js | 13 +++++++------ src/reducers/index.js | 8 ++++---- src/store/index.js | 2 +- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/components/Sidebar/EventSelector/EventSelector.js b/src/components/Sidebar/EventSelector/EventSelector.js index 879e739..cd3a0dc 100644 --- a/src/components/Sidebar/EventSelector/EventSelector.js +++ b/src/components/Sidebar/EventSelector/EventSelector.js @@ -17,8 +17,10 @@ class EventSelector extends Component { render() { const eventList = _.map(this.props.events, (event, eventID) => { - return { ...event, id: eventID }; - }); + return { ...event, id: eventID }; + }), + selectedEvent = this.props.events[this.props.selectedEventID], + selectedEventName = selectedEvent ? selectedEvent.name : ""; return (