\r\n {typeof uniqueNameValidator === \"function\"\r\n ? renderEditForm(props.stationKey)\r\n : null}\r\n
\r\n );\r\n};\r\n\r\nexport default reduxForm({\r\n form: \"stationEdit\",\r\n})(injectIntl(StationEditForm));\r\n","import React, { Component, Fragment } from \"react\";\r\nimport StationsEditList from \"./StationsEditList\";\r\nimport StationEditForm from \"./StationEditForm\";\r\nimport { Button } from \"../../../../components/Buttons\";\r\nimport StationNewForm from \"./StationNewForm\";\r\nimport { injectIntl } from \"react-intl\";\r\nimport messages from \"./messages\";\r\nimport moment from \"moment\";\r\n\r\nclass StationEditBase extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n stations: this.props.event.stations ? this.props.event.stations : [],\r\n showEditForm: false,\r\n showNewForm: false,\r\n stationKey: null,\r\n groupPayment: false,\r\n compensationByAgreement: false\r\n };\r\n\r\n this.handleSubmitStation = this.handleSubmitStation.bind(this);\r\n this.onDeleteStation = this.onDeleteStation.bind(this);\r\n this.submitEvent = this.submitEvent.bind(this);\r\n this.onStationClick = this.onStationClick.bind(this);\r\n this.toggleEditForm = this.toggleEditForm.bind(this);\r\n this.showNewStationForm = this.showNewStationForm.bind(this);\r\n this.handlePaymentChange = this.handlePaymentChange.bind(this);\r\n }\r\n\r\n componentDidMount() {\r\n this.props.fetchEventOffers({ eventId: this.props.event.eventId });\r\n }\r\n\r\n handlePaymentChange(PaymentTypeFieldValue) {\r\n switch (PaymentTypeFieldValue) {\r\n case \"COMPENSATIONBYAGREEMENT\":\r\n this.setState({\r\n groupPayment: false,\r\n compensationByAgreement: true\r\n });\r\n return;\r\n case \"HOURLYRATE\":\r\n this.setState({\r\n groupPayment: false,\r\n compensationByAgreement: false\r\n });\r\n return;\r\n case \"GROUPPAYMENT\":\r\n this.setState({\r\n groupPayment: true,\r\n compensationByAgreement: false\r\n });\r\n return;\r\n case \"PERPERSON\":\r\n this.setState({\r\n groupPayment: false,\r\n compensationByAgreement: false\r\n });\r\n return;\r\n case \"NOCOMPENSATION\":\r\n this.setState({\r\n groupPayment: false,\r\n compensationByAgreement: true\r\n });\r\n return;\r\n default:\r\n return;\r\n }\r\n }\r\n\r\n showNewStationForm() {\r\n this.setState({\r\n showNewForm: true,\r\n showEditForm: false\r\n });\r\n }\r\n\r\n toggleEditForm() {\r\n if (!this.state.showEditForm) {\r\n this.setState({\r\n showEditForm: true,\r\n showNewForm: false\r\n });\r\n } else {\r\n this.setState({\r\n showEditForm: false\r\n });\r\n }\r\n }\r\n\r\n scrollToForm() {\r\n let elem = document.getElementById(\"station-edit-form\");\r\n\r\n if (elem && window.scroll) {\r\n let offsetTop = 0;\r\n do {\r\n if (!isNaN(elem.offsetTop)) {\r\n offsetTop += elem.offsetTop;\r\n }\r\n // eslint-disable-next-line no-cond-assign\r\n } while ((elem = elem.offsetParent));\r\n\r\n window.scroll({\r\n top: offsetTop - 20,\r\n left: 0,\r\n behavior: \"smooth\"\r\n });\r\n }\r\n }\r\n\r\n onStationClick(key, row) {\r\n this.handlePaymentChange(row.paymentType);\r\n const currentKey = this.state.stationKey;\r\n this.setState(\r\n {\r\n stationKey: key,\r\n showEditForm: true,\r\n showNewForm: false\r\n },\r\n () => {\r\n // Only scroll if user clicks on a different station\r\n if (currentKey !== key) {\r\n this.scrollToForm();\r\n }\r\n }\r\n );\r\n }\r\n\r\n submitEvent(stationList) {\r\n this.setState({\r\n stations: stationList\r\n });\r\n this.props.submitEvent({\r\n ...this.props.event,\r\n stations: stationList\r\n });\r\n }\r\n\r\n handleSubmitStation(station) {\r\n this.submitEvent([\r\n ...this.state.stations,\r\n {\r\n ...station,\r\n id: Math.floor(Math.random() * 10000)\r\n }\r\n ]);\r\n }\r\n\r\n onDeleteStation(stationsList) {\r\n this.setState({\r\n showEditForm: false\r\n });\r\n this.submitEvent(stationsList);\r\n }\r\n\r\n render() {\r\n const initialValues = {\r\n start: moment(this.props.event.date)\r\n .set({\r\n hour: 8,\r\n minute: 0\r\n })\r\n .format(\"YYYY-MM-DD HH:mm\"),\r\n end: moment(this.props.event.date)\r\n .set({\r\n hour: 18,\r\n minute: 0\r\n })\r\n .format(\"YYYY-MM-DD HH:mm\")\r\n };\r\n\r\n return (\r\n \r\n }\r\n\r\n return null;\r\n }\r\n\r\n const renderSuccess = () => {\r\n if (status === statuses.SUBMIT_SUCCESS) {\r\n if (sendOfferReminderGroups.length > 0) {\r\n const groups = sendOfferReminderGroups.map(s => s.group.name);\r\n\r\n return
\r\n } else {\r\n return \r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n return (\r\n \r\n } \r\n onClick={onClick} \r\n busy={status === statuses.SUBMITTING}\r\n check={status === statuses.SUBMIT_SUCCESS}\r\n />\r\n {renderError()}\r\n {renderSuccess()}\r\n
\r\n );\r\n};\r\n\r\nexport default SendReminderButton;","import SendReminderButton from \"./SendReminderButton\";\r\nimport { connect } from \"react-redux\";\r\nimport { sendOfferReminder } from \"../../../Offer/reducer\";\r\n\r\nconst mapStateToProps = (state) => ({\r\n status: state.offers.sendOfferReminderStatus,\r\n sendOfferReminderGroups: state.offers.sendOfferReminderGroups\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n sendOfferReminder: data => dispatch(sendOfferReminder(data)),\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(SendReminderButton);\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n sendInvitation: {\r\n buttonText: {\r\n id: 'send-invitation.button-text',\r\n },\r\n error: {\r\n id: 'send-invitation.error',\r\n },\r\n success: {\r\n id: 'send-invitation.success',\r\n },\r\n noInvitationSent: {\r\n id: 'send-invitation.noInvitationSent',\r\n },\r\n noGroupsMatched: {\r\n id: 'send-invitation.no-groups-matched',\r\n }\r\n }\r\n});","import React, { Fragment } from \"react\";\r\nimport { FormattedMessage } from \"react-intl\";\r\nimport { SmallPinkButton } from \"../../../../../components/Buttons\";\r\nimport { statuses } from \"../../../Offer/reducer\";\r\nimport { Error } from \"../../../../../components\"\r\nimport styled from \"styled-components\";\r\nimport messages from \"./messages\"\r\n\r\nconst CustomError = styled(Error)`\r\n font-weight: normal;\r\n text-align: center;\r\n margin-top: 5px;\r\n`;\r\n\r\nconst SentMessageLabel = styled.p`\r\n font-size: 14px;\r\n font-weight: 300;\r\n margin-left: -15px;\r\n`\r\n\r\nclass SendInvitationButton extends React.Component {\r\n constructor(props) {\r\n super(props)\r\n this.state = {\r\n sentToNone: false,\r\n numberSent: 0,\r\n }\r\n }\r\n\r\n onClick () {\r\n const { eventOffers, eventId, confirmStationOffers } = this.props;\r\n var numberSent = 0;\r\n this.setState({sentToNone: false, numberSent: 0})\r\n if (eventOffers && eventOffers[eventId]) {\r\n\tconst offers = eventOffers[eventId].reduce((arr, offer) => {\r\n\t\tconst { groupId, stationId } = offer\r\n\t return offer.status === \"DRAFT\" ? arr.concat({groupId, stationId}) : arr\r\n\t}, [])\r\n\tconfirmStationOffers({\r\n\t offers: offers,\r\n\t eventId: eventId\r\n\t})\r\n\tnumberSent = offers.length\r\n }\r\n if (numberSent === 0) {\r\n this.setState({sentToNone: true})\r\n }\r\n else {\r\n this.setState({numberSent: numberSent})\r\n }\r\n }\r\n\r\n renderError () {\r\n const { intl, status } = this.props;\r\n if (status === statuses.SUBMIT_FAILED) {\r\n return \r\n }\r\n return null;\r\n }\r\n\r\n renderSuccess () {\r\n const { numberSent } = this.state;\r\n if (this.state.sentToNone === true) {\r\n return \r\n }\r\n if (numberSent !== 0) {//status === statuses.SUBMIT_SUCCESS) {\r\n return {numberSent} \r\n }\r\n return null;\r\n }\r\n\r\n\r\n render () {\r\n const { intl, status } = this.props;\r\n return (\r\n \r\n this.onClick()}\r\n busy={status === statuses.SUBMITTING}\r\n check={status === statuses.SUBMIT_SUCCESS}\r\n />\r\n {this.renderError()}\r\n {this.renderSuccess()}\r\n \r\n )\r\n }\r\n}\r\n\r\n// const SendInvitationButton = ({ status, eventId, intl, eventOffers, confirmStationOffer }) => {\r\n// const onClick = () => {\r\n// if (eventOffers && eventOffers[eventId]) {\r\n// for (const offer of eventOffers[eventId]) {\r\n// if (offer.status === \"DRAFT\") {\r\n// confirmStationOffer({\r\n// groupId: offer.groupId,\r\n// stationId: offer.stationId,\r\n// eventId: eventId\r\n// })\r\n// }\r\n// }\r\n// }\r\n// };\r\n\r\n// const renderError = () => {\r\n// if (status === statuses.SUBMIT_FAILED) {\r\n// return \r\n// }\r\n// return null;\r\n// }\r\n\r\n// const renderSuccess = () => {\r\n// if (status === statuses.SUBMIT_SUCCESS) {\r\n// return \r\n// }\r\n// return null;\r\n// }\r\n\r\n// return (\r\n// \r\n// \r\n// {renderError()}\r\n// {renderSuccess()}\r\n// \r\n// );\r\n\r\n// };\r\n\r\nexport default SendInvitationButton;\r\n","import SendInvitationButton from \"./SendInvitationButton\";\r\nimport { connect } from \"react-redux\";\r\nimport { confirmStationOffers } from \"../../../Offer/reducer\";\r\n\r\nconst mapStateToProps = (state) => ({\r\n status: state.offers.sendInvitationStatus,\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n confirmStationOffers: data => dispatch(confirmStationOffers(data)),\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(SendInvitationButton);\r\n","import { defineMessages } from \"react-intl\";\r\n\r\nexport default defineMessages({\r\n header: {\r\n noMailSent: {\r\n id: \"station-allocation.table.header.noMailSent\"\r\n },\r\n lastReminder: {\r\n id: \"station-allocation.table.header.lastReminderSent\"\r\n },\r\n stations: {\r\n id: \"station-allocation.table.header.stations\",\r\n },\r\n },\r\n station: {\r\n workStation: {\r\n id: `station-allocation.table.workStation`\r\n },\r\n officialQuantity: {\r\n id: \"station-allocation.table.officialQuantity\",\r\n },\r\n officialsAllocated: {\r\n id: \"station-allocation.table.officialsAllocated\",\r\n },\r\n officialsProposed: {\r\n id: \"station-allocation.table.officialsProposed\",\r\n },\r\n officialPreliminary: {\r\n id: \"station-allocation.table.officialPreliminary\",\r\n },\r\n officialsAwaitingAnswer: {\r\n id: \"station-allocation.table.officialsAwaitingAnswer\",\r\n },\r\n officialsAccepted: {\r\n id: \"station-allocation.table.officialsAccepted\",\r\n },\r\n officialsMissing: {\r\n id: \"station-allocation.table.officialsMissing\",\r\n },\r\n officialsNotAllocated: {\r\n id: \"station-allocation.table.officialsNotAllocated\",\r\n },\r\n officialMinimumAge: {\r\n id: \"station-allocation.table.age-limit\",\r\n },\r\n skills: {\r\n id: \"station-allocation.table.skills\",\r\n },\r\n noSkills: {\r\n id: \"station-allocation.table.noSkills\",\r\n },\r\n },\r\n groupTable: {\r\n header: {\r\n groupName: {\r\n id: \"station-allocation.table.header.groupName\",\r\n },\r\n requestedQuantity: {\r\n id: \"station-allocation.table.header.requestedQuantity\",\r\n },\r\n ages: {\r\n id: \"station-allocation.table.header.ages\",\r\n },\r\n skills: {\r\n id: \"station-allocation.table.header.skills\",\r\n },\r\n },\r\n draft: {\r\n id: \"station-allocation.table.status-draft\",\r\n },\r\n proposal: {\r\n id: \"station-allocation.table.status-proposal\",\r\n },\r\n accepted: {\r\n id: \"station-allocation.table.status-accepted\",\r\n },\r\n rejected: {\r\n id: \"station-allocation.table.status-rejected\",\r\n }\r\n },\r\n addGroup: {\r\n title: {\r\n id: \"station-allocation.addGroup.title\",\r\n },\r\n button: {\r\n id: \"station-allocation.addGroup.button\",\r\n },\r\n selectGroup: {\r\n id: \"station-allocation.addGroup.selectGroup.placeholder\",\r\n },\r\n requestedQuantity: {\r\n id: \"station-allocation.addGroup.requestedQuantity\",\r\n },\r\n groupSummary: {\r\n title: {\r\n id: \"station-allocation.addGroup.groupSummary.title\",\r\n },\r\n name: {\r\n id: \"station-allocation.addGroup.groupSummary.name\",\r\n },\r\n ages: {\r\n id: \"station-allocation.addGroup.groupSummary.ages\",\r\n },\r\n members: {\r\n id: \"station-allocation.addGroup.groupSummary.members\",\r\n },\r\n sports: {\r\n id: \"station-allocation.addGroup.groupSummary.sports\",\r\n },\r\n skills: {\r\n id: \"station-allocation.addGroup.groupSummary.skills\",\r\n },\r\n },\r\n toManyRequestedError: {\r\n id: \"station-allocation.addGroup.to-many-requested-error\",\r\n },\r\n allocatedError: {\r\n id: \"station-allocation.addGroup.allocated-error\",\r\n },\r\n createOfferError: {\r\n id: \"station-allocation.addGroup.create-offer-error\",\r\n }\r\n },\r\n offers: {\r\n groupName: {\r\n id: \"station-allocation.offer.groupName\",\r\n },\r\n requestedQuantity: {\r\n id: \"station-allocation.offer.requestedQuantity\",\r\n },\r\n status: {\r\n id: \"station-allocation.offer.status\",\r\n },\r\n },\r\n saveButton: {\r\n id: \"station-offer.send-button\",\r\n },\r\n confirmModalTitle: {\r\n id: \"station-offers.confirm-delete-group-offer-modal.title\",\r\n },\r\n confirmModalText: {\r\n id: \"station-offers.confirm-delete-group-offer-modal.text\",\r\n },\r\n confirmModalButton: {\r\n id: \"station-offers.confirm-delete-modal.confirm-button\",\r\n },\r\n cancelConfirmModalButton: {\r\n id: \"station-offers.confirm-delete-modal.cancel-button\",\r\n },\r\n notConfirmedWarning: {\r\n id: \"station-offers.not-confirmed-warning\",\r\n },\r\n historicWarning: {\r\n id: \"station-offers.historic-warning\",\r\n },\r\n});\r\n","import React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport styled from \"styled-components\";\r\nimport { Field, reduxForm, formValueSelector } from \"redux-form\";\r\nimport { connect } from \"react-redux\";\r\nimport messages from \"./messages\";\r\nimport { Input, Select, GeneralError } from \"../../../../components\";\r\nimport { SmallGrayButton } from \"../../../../components/Buttons\";\r\nimport { Col } from \"react-bootstrap/lib\";\r\nimport { FormattedMessage } from \"react-intl\";\r\nimport { required } from \"../../../../validators/index\";\r\nimport { statuses } from \"../../Offer/reducer\";\r\n\r\nconst FormWrapper = styled.div`\r\n margin: 20px 0;\r\n`;\r\n\r\nconst StyledTd = styled.td`\r\n padding: 0 15px 10px 0;\r\n font-size: 18px;\r\n`;\r\n\r\nconst maxOfficials = max => value =>\r\n value > max ? `Du kan max lägga in ${max} funktionärer` : undefined;\r\n\r\nconst getNumOfOccupiedVolunteers = (group, allOffers) => {\r\n let occupiedVolunteers = 0;\r\n if (allOffers) {\r\n allOffers.forEach(offer => {\r\n if (\r\n group &&\r\n group.groupId === offer.groupId &&\r\n offer.status !== \"REJECTED\"\r\n ) {\r\n occupiedVolunteers += parseInt(offer.volunteers, 10);\r\n } else if (\r\n (group === undefined || group === null) &&\r\n offer.status !== \"REJECTED\"\r\n ) {\r\n occupiedVolunteers += parseInt(offer.volunteers, 10);\r\n }\r\n });\r\n }\r\n return occupiedVolunteers;\r\n};\r\n\r\n/**\r\n * Filter out doublets, sort, and filter out all groups that already have an offer\r\n *\r\n * @station: Current event station\r\n * @availableGroups: Array of group availabilities\r\n */\r\nconst getGroupOptions = (station, availableGroups, allOffers, intl) => {\r\n const groupsWithoutDoublets = availableGroups\r\n .slice()\r\n .filter((currentGroup, GroupPos, groupArr) => {\r\n return (\r\n groupArr\r\n .map(group => group[\"groupId\"])\r\n .indexOf(currentGroup[\"groupId\"]) === GroupPos\r\n );\r\n });\r\n groupsWithoutDoublets.sort((a, b) => {\r\n let comparision;\r\n if (a.group.numberOfMembers > b.group.numberOfMembers) {\r\n comparision = 1;\r\n } else {\r\n comparision = -1;\r\n }\r\n return comparision * -1;\r\n });\r\n\r\n // Filter out groups that have an offer on this station\r\n const groupWithoutOfferOnThisStation = groupsWithoutDoublets.filter(\r\n gd =>\r\n !allOffers.find(\r\n ao => ao.groupId === gd.groupId && ao.stationId === station.id\r\n )\r\n );\r\n // Filter out groups that don't have any available volunteers\r\n const groupsWithAvailableVolunteers = groupWithoutOfferOnThisStation.filter(\r\n groupAvailability => {\r\n const occupiedVolunteers = getNumOfOccupiedVolunteers(\r\n groupAvailability.group,\r\n allOffers\r\n );\r\n return occupiedVolunteers < groupAvailability.group.numberOfMembers;\r\n }\r\n );\r\n\r\n const groupOptions = groupsWithAvailableVolunteers.map(({ group }) => {\r\n const occupiedVolunteers = getNumOfOccupiedVolunteers(group, allOffers);\r\n\r\n return {\r\n id: group.id,\r\n text: `${group.organizationName} - ${\r\n group.name\r\n } - ${group.numberOfMembers - occupiedVolunteers} ${\r\n group.skills\r\n ? ` - ${group.skills\r\n .map(skill => intl.formatMessage({ id: `lists.skills.${skill}` }))\r\n .join(\", \")}`\r\n : \"\"\r\n }`\r\n };\r\n });\r\n\r\n return groupOptions;\r\n};\r\n\r\nconst GroupSummary = ({ group, formatMessage, occupiedVolunteers }) => {\r\n if (!group) {\r\n return null;\r\n }\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {group.ages.join(\", \")} \r\n \r\n \r\n \r\n \r\n \r\n {group.numberOfMembers - occupiedVolunteers} \r\n \r\n \r\n \r\n \r\n \r\n {(group.sports || []).join(\", \")} \r\n \r\n \r\n \r\n \r\n \r\n \r\n {group.skills\r\n ? group.skills\r\n .map(skill =>\r\n formatMessage({\r\n id: `lists.skills.${skill}`\r\n }).toLowerCase()\r\n )\r\n .join(\", \")\r\n : null}\r\n \r\n \r\n \r\n
\r\n \r\n );\r\n};\r\n\r\nclass AddGroup extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n const { availableGroups = [], intl, allOffers, station } = this.props;\r\n\r\n this.state = {\r\n groupMemberError: false,\r\n allocatedError: false,\r\n groupOptions: getGroupOptions(station, availableGroups, allOffers, intl)\r\n };\r\n\r\n this.handleSubmit = this.handleSubmit.bind(this);\r\n //this.confirmStationOffers = this.confirmStationOffers.bind(this);\r\n\r\n this.maxAllowedOfficials = maxOfficials(\r\n parseInt(this.props.station.officialQuantity, 10)\r\n );\r\n }\r\n\r\n componentDidUpdate(prevProps) {\r\n if (\r\n this.props.volunteers !== prevProps.volunteers &&\r\n this.state.groupMemberError\r\n ) {\r\n this.checkGroupMemberError();\r\n }\r\n if (this.state.allocatedError) {\r\n const {\r\n officialsAllocated,\r\n officialsProposed,\r\n officialsDraft\r\n } = this.props;\r\n\r\n if (\r\n officialsAllocated !== prevProps.officialsAllocated ||\r\n officialsProposed !== prevProps.officialsProposed ||\r\n officialsDraft !== prevProps.officialsDraft\r\n ) {\r\n this.checkIfAllIsAllocated(this.props.volunteers);\r\n }\r\n }\r\n if (\r\n prevProps.offerCreateStatus[this.props.station.id] ===\r\n statuses.SUBMITTING &&\r\n this.props.offerCreateStatus[this.props.station.id] ===\r\n statuses.SUBMIT_SUCCESS\r\n ) {\r\n // Clear the group field and untouch it to hide the validation message\r\n this.props.change(\"group\", \"\");\r\n this.props.untouch(\"group\", \"\");\r\n this.updateGroupOptions();\r\n }\r\n\r\n if (\r\n this.props.availableGroups !== prevProps.availableGroups ||\r\n prevProps.allOffers.length !== this.props.allOffers.length\r\n ) {\r\n this.updateGroupOptions();\r\n }\r\n }\r\n\r\n updateGroupOptions() {\r\n const { availableGroups = [], intl, allOffers, station } = this.props;\r\n this.setState({\r\n groupOptions: getGroupOptions(station, availableGroups, allOffers, intl)\r\n });\r\n }\r\n\r\n /**\r\n * Check if requested volunteers are lower or equal to number of group members\r\n */\r\n checkGroupMemberError() {\r\n const group = this.props.availableGroups\r\n .map(availableGroup => availableGroup.group)\r\n .find(group => group.id === this.props.group);\r\n const occupiedVolunteers = getNumOfOccupiedVolunteers(\r\n group,\r\n this.props.allOffers\r\n );\r\n const toManyRequestedVolunteers =\r\n this.props.volunteers > group.numberOfMembers - occupiedVolunteers;\r\n\r\n if (this.state.groupMemberError !== toManyRequestedVolunteers) {\r\n this.setState({ groupMemberError: toManyRequestedVolunteers });\r\n }\r\n\r\n return toManyRequestedVolunteers;\r\n }\r\n\r\n /**\r\n * Check if more volunteers are requested than what is missing on the station.\r\n *\r\n * Error = Antal > Behov - Accepted - Proposal - Draft\r\n */\r\n checkIfAllIsAllocated(numberOfRequested) {\r\n const {\r\n officialsAllocated,\r\n officialsProposed,\r\n officialsDraft,\r\n station\r\n } = this.props;\r\n const allocatedError =\r\n parseInt(numberOfRequested, 10) >\r\n parseInt(station.officialQuantity, 10) -\r\n officialsAllocated -\r\n officialsProposed -\r\n officialsDraft;\r\n if (allocatedError !== this.state.allocatedError) {\r\n this.setState({ allocatedError });\r\n }\r\n\r\n return allocatedError;\r\n }\r\n\r\n // confirmStationOffers() {\r\n // if (this.props.offers) {\r\n // for (const offer of this.props.offers) {\r\n // if (offer.status === \"DRAFT\") {\r\n // this.props.confirmStationOffer({\r\n // groupId: offer.groupId,\r\n // stationId: offer.stationId,\r\n // eventId: offer.eventId\r\n // });\r\n // }\r\n // }\r\n // }\r\n \r\n // }\r\n\r\n handleSubmit(fieldValues) {\r\n const toManyRequestedFromGroup = this.checkGroupMemberError();\r\n const allocatedError = this.checkIfAllIsAllocated(fieldValues.volunteers);\r\n\r\n if (!toManyRequestedFromGroup && !allocatedError) {\r\n this.props.createOffer({\r\n volunteers: fieldValues.volunteers ? fieldValues.volunteers : 1,\r\n groupId: fieldValues.group,\r\n stationId: this.props.station.id,\r\n eventId: this.props.eventId\r\n });\r\n }\r\n }\r\n\r\n renderGroupMemberError() {\r\n if (!this.state.groupMemberError) {\r\n return null;\r\n }\r\n return (\r\n \r\n {this.props.intl.formatMessage(messages.addGroup.toManyRequestedError)}\r\n \r\n );\r\n }\r\n\r\n renderAllocatedError() {\r\n if (!this.state.allocatedError) {\r\n return null;\r\n }\r\n return (\r\n \r\n {this.props.intl.formatMessage(messages.addGroup.allocatedError)}\r\n \r\n );\r\n }\r\n\r\n renderCreateOfferError() {\r\n const { offerCreateStatus, station } = this.props;\r\n\r\n if (\r\n offerCreateStatus &&\r\n offerCreateStatus[station.id] &&\r\n offerCreateStatus[station.id] === statuses.SUBMIT_FAILED\r\n ) {\r\n return (\r\n \r\n \r\n {this.props.intl.formatMessage(messages.addGroup.createOfferError)}\r\n \r\n \r\n );\r\n }\r\n\r\n return null;\r\n }\r\n\r\n render() {\r\n const {\r\n availableGroups = [],\r\n intl,\r\n allOffers,\r\n offerCreateStatus,\r\n station\r\n } = this.props;\r\n const group = this.props.group\r\n ? availableGroups\r\n .map(availableGroup => availableGroup.group)\r\n .find(group => group.id === this.props.group)\r\n : null;\r\n const occupiedVolunteers = getNumOfOccupiedVolunteers(group, allOffers);\r\n return (\r\n \r\n {this.props.event.status == \"HISTORIC\" ? \"\" : \r\n \r\n }\r\n
\r\n );\r\n }\r\n}\r\n\r\nAddGroup.propTypes = {\r\n createOffer: PropTypes.func.isRequired,\r\n station: PropTypes.object.isRequired,\r\n availableGroups: PropTypes.array\r\n};\r\n\r\nlet AddGroupForm = reduxForm({\r\n form: `addGroup ${Math.random() * 100}`\r\n})(AddGroup);\r\n\r\nAddGroupForm = connect((state, ownProps) => {\r\n const selector = formValueSelector(ownProps.form);\r\n return {\r\n group: selector(state, \"group\"),\r\n volunteers: selector(state, \"volunteers\"),\r\n initialValues: {\r\n volunteers: ownProps.station ? ownProps.station.officialQuantity - ownProps.officialsProposed - \r\n ownProps.officialsAllocated - ownProps.officialsDraft : 1\r\n }\r\n };\r\n})(AddGroupForm);\r\n\r\nexport default AddGroupForm;\r\n","import React, { Component, Fragment } from \"react\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport styled from \"styled-components\";\r\nimport messages from \"./../messages\";\r\nimport AddGroup from \"../AddGroup\";\r\nimport { ViewVolunteers } from \".\";\r\nimport { SmallGrayButton } from \"../../../../../components/Buttons\";\r\nimport { breakPoints } from \"../../../../../constants/styling-constants\";\r\n\r\n\r\nconst SummaryWrapper = styled.div`\r\n font-size: 18px;\r\n justify-content: space-between;\r\n font-weight: 500;\r\n color: #404040;\r\n background: white;\r\n margin-bottom: 20px;\r\n padding-bottom: 15px;\r\n padding-top: 15px;\r\n`;\r\n\r\nconst Header = styled.div`\r\n font-weight: 600;\r\n font-size: 18px;\r\n display: inline-flex;\r\n`;\r\n\r\nconst SummaryHeader = styled(Row)`\r\n font-weight: 500;\r\n font-size: 24px;\r\n margin-left: 5px;\r\n margin-bottom: 5px;\r\n`;\r\n\r\nconst SkillBox = styled.div`\r\n border: 1px solid #dddddd;\r\n margin-left: 2px;\r\n margin-bottom: 2px;\r\n display: inline-block;\r\n background-color: #eeeeee;\r\n &.empty {\r\n border: 0px;\r\n background-color: transparent;\r\n }\r\n p {\r\n margin-top: 2px;\r\n margin-bottom: 2px;\r\n margin-left: 4px;\r\n margin-right: 4px;\r\n }\r\n`;\r\n\r\nconst SkillWrapper = styled.div`\r\n display: flow-root;\r\n margin-left: -5px;\r\n`;\r\n\r\nconst SummaryRow = styled(Row)`\r\n margin-left: 5px;\r\n margin-bottom: 5px;\r\n`;\r\n\r\nconst ButtonWrapper = styled(Row)`\r\n margin-left: 15px;\r\n width: 90%;\r\n justify-content: space-around;\r\n @media (max-width: ${breakPoints.sm}px) {\r\n flex-direction: column;\r\n align-items: center;\r\n }\r\n`;\r\n\r\nclass AddVolunteersForm extends Component {\r\n componentDidMount() {\r\n if (!Array.isArray(this.props.availableGroups)) {\r\n const { municipality, start, end, id } = this.props.station;\r\n this.props.fetchAvailableGroups({\r\n eventId: this.props.eventId,\r\n location: municipality,\r\n startDate: start,\r\n endDate: end,\r\n stationId: id\r\n });\r\n }\r\n }\r\n\r\n StationSummaryRow(){\r\n const { station, \r\n officialsProposed,\r\n officialsAllocated, \r\n officialsDraft } = this.props;\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n {station.name}\r\n \r\n \r\n \r\n \r\n \r\n {\": \"}\r\n \r\n \r\n {station.officialQuantity}\r\n \r\n \r\n \r\n \r\n \r\n {\": \"}\r\n \r\n {station.officialQuantity - officialsProposed - officialsAllocated - officialsDraft}\r\n \r\n {this.renderMinimumAge()}\r\n {this.renderSkills()}\r\n \r\n
\r\n );\r\n }\r\n\r\n\r\n renderMinimumAge() {\r\n const { station } = this.props;\r\n return (\r\n \r\n \r\n :\r\n {\" \"}\r\n \r\n {station.officialMiniumumAge}\r\n \r\n );\r\n }\r\n\r\n renderSkills() {\r\n const { station, intl } = this.props;\r\n return (\r\n \r\n \r\n :\r\n {\" \"}\r\n \r\n \r\n \r\n {station.skills && station.skills.length > 0 ? (\r\n station.skills.map((skill, index) => (\r\n \r\n {intl.formatMessage({ id: `lists.skills.${skill}` })}
\r\n \r\n ))\r\n ) : (\r\n \r\n
\r\n \r\n )}\r\n \r\n \r\n \r\n );\r\n }\r\n\r\n render() {\r\n const { availableGroups, ...restProps } = this.props;\r\n const { station } = this.props;\r\n return (\r\n \r\n {this.StationSummaryRow()}\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n this.props.prevModal()}\r\n label={\"Föregående\"}\r\n />\r\n this.props.nextModal()}\r\n label={\"Nästa\"}\r\n />\r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nlet AddVolunteersFirst = injectIntl(AddVolunteersForm);\r\n\r\nexport default AddVolunteersFirst;\r\n","import React, { Component } from \"react\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport { Row, Col, Grid } from \"react-bootstrap/lib\";\r\nimport styled from \"styled-components\";\r\nimport { DeleteButton, SmallPinkButton } from \"../../../../../components/Buttons\";\r\nimport {\r\n BorderTable,\r\n GeneralError,\r\n ConfirmationModal\r\n} from \"../../../../../components\";\r\nimport messages from \"./../messages\";\r\nimport { reduxForm } from \"redux-form\";\r\n\r\nconst StyledBorderTable = styled(BorderTable)`\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n`;\r\n\r\nconst validate = values => null;\r\n\r\nconst DeleteListItemButton = ({ row, callback }) => {\r\n const onClick = () => {\r\n callback(row);\r\n };\r\n return (\r\n \r\n );\r\n};\r\n\r\nconst StationOfferRow = ({ groupId, volunteers, status, offer, availableGroups, onDeleteRow, formatMessage, eventStatus }) => {\r\n let group = null;\r\n if (Array.isArray(availableGroups)) {\r\n group = availableGroups.find(g => g.groupId === groupId);\r\n }\r\n return (\r\n \r\n {group ? group.group.name : (offer ? offer.group.name : \"\")} \r\n {volunteers} \r\n {formatMessage(messages.groupTable[status.toLowerCase()])} \r\n \r\n {eventStatus == \"HISTORIC\" ? \"\" : \r\n \r\n }\r\n \r\n \r\n )\r\n};\r\n\r\nclass ViewVolunteers1 extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n showDeleteGroupModal: false,\r\n deletingOffer: false,\r\n offerToDelete: false,\r\n };\r\n this.onDeleteGroupOffer = this.onDeleteGroupOffer.bind(this);\r\n this.onConfirmDelete = this.onConfirmDelete.bind(this);\r\n this.confirmStationOffers = this.confirmStationOffers.bind(this);\r\n this.toggleModal = this.toggleModal.bind(this);\r\n }\r\n\r\n\r\n componentDidMount() {\r\n if (!Array.isArray(this.props.availableGroups)) {\r\n const { municipality, start, end, id } = this.props.station;\r\n this.props.fetchAvailableGroups({\r\n eventId: this.props.eventId,\r\n location: municipality,\r\n startDate: start,\r\n endDate: end,\r\n stationId: id\r\n });\r\n }\r\n }\r\n\r\n componentWillReceiveProps(nextProps) {\r\n if ((!this.props.deleteOfferError && nextProps.deleteOfferError) || (this.props.offers && (!nextProps.offers || this.props.offers.length > nextProps.offers.length))) {\r\n this.setState({\r\n showDeleteGroupModal: false,\r\n deletingOffer: false\r\n });\r\n }\r\n }\r\n\r\n onConfirmDelete() {\r\n this.props.deleteOffer({\r\n eventId: this.props.eventId,\r\n groupId: this.state.offerToDelete.groupId,\r\n stationId: this.state.offerToDelete.stationId\r\n });\r\n this.setState({\r\n deletingOffer: true\r\n });\r\n }\r\n\r\n onDeleteGroupOffer(row) {\r\n this.toggleModal();\r\n this.setState({\r\n offerToDelete: row,\r\n });\r\n }\r\n\r\n toggleModal() {\r\n this.setState({\r\n showDeleteGroupModal: !this.state.showDeleteGroupModal,\r\n });\r\n }\r\n\r\n confirmStationOffers() {\r\n if (this.props.offers) {\r\n\tconst offers = this.props.offers.reduce((arr, offer) => {\r\n\t const { groupId, stationId } = offer\r\n\t return offer.status === \"DRAFT\" ? arr.concat({groupId, stationId}) : arr\r\n\t}, [])\r\n\r\n\tthis.props.confirmStationOffers({\r\n\t offers: offers,\r\n\t eventId: this.props.eventId\r\n\t})\r\n }\r\n }\r\n\r\n render() {\r\n const { intl, station, offers = [], deleteOfferError, availableGroups } = this.props;\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {offers.filter(offer => offer.stationId === station.id).map((offer, index) =>\r\n )}\r\n \r\n \r\n {deleteOfferError ? (\r\n {deleteOfferError.message} ) : null}\r\n \r\n {this.props.event.status == \"HISTORIC\" ? \"\" :\r\n { return offer.status === \"DRAFT\" ? 1 : 0 } ) === undefined}\r\n type=\"button\"\r\n className=\"submit rightPos\"\r\n onClick={this.confirmStationOffers}\r\n label={intl.formatMessage(messages.saveButton)}\r\n />\r\n }\r\n
\r\n \r\n\r\n \r\n )\r\n }\r\n}\r\n\r\nlet ViewVolunteers = reduxForm({\r\n form: \"view-volunteers-modal\",\r\n validate,\r\n})(injectIntl(ViewVolunteers1));\r\n\r\nexport default ViewVolunteers;\r\n","import React, { Component, Fragment } from \"react\";\r\nimport { connect } from \"react-redux\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport SendReminderButton from \"./SendReminderButton\";\r\nimport SendInvitationButton from \"./SendInvitationButton\";\r\nimport { AddVolunteersFirst } from \"./ModalsContent\";\r\nimport { P, H2, PopUpModal } from \"../../../../components\";\r\nimport messages from \"./messages\";\r\nimport BootstrapTable from \"react-bootstrap-table-next\";\r\nimport styled from \"styled-components\";\r\nimport { breakPoints } from \"../../../../constants/styling-constants\";\r\n\r\nexport const filterStationOffers = ({ offers = [], eventId, stationId }) =>\r\n (Array.isArray(offers[eventId]) &&\r\n offers[eventId].filter(offer => offer.stationId === stationId)) ||\r\n undefined;\r\n\r\nconst ButtonWrapper = styled(Col)`\r\n //display: flex; - Add this when we add search group support\r\n @media (max-width: ${breakPoints.xs}px) {\r\n flex-direction: column;\r\n align-items: center;\r\n }\r\n`;\r\nclass Stations extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n order: 'desc',\r\n field: 'officialQuantity'\r\n };\r\n this.toggleAddVolunteersModal = this.toggleAddVolunteersModal.bind(this);\r\n this.handleSort = this.handleSort.bind(this);\r\n }\r\n\r\n toggleAddVolunteersModal(id) {\r\n this.setState({\r\n [`showAddVolunteersModal${id}`]: !this.state[\r\n `showAddVolunteersModal${id}`\r\n ]\r\n });\r\n }\r\n\r\n nextAddVolunteersModal = (currId, nextId) => {\r\n this.setState({\r\n [`showAddVolunteersModal${currId}`]: !this.state[\r\n `showAddVolunteersModal${currId}`\r\n ],\r\n [`showAddVolunteersModal${nextId}`]: !this.state[\r\n `showAddVolunteersModal${nextId}`\r\n ]\r\n });\r\n }\r\n\r\n componentDidMount() {\r\n this.props.fetchEventOffers({ eventId: this.props.eventId });\r\n }\r\n\r\n componentWillUnmount() {\r\n this.props.resetAvailableGroups();\r\n }\r\n\r\n formatModals(stations) {\r\n const { availableGroups, ...restProps } = this.props;\r\n const {\r\n eventOffers,\r\n eventId\r\n } = this.props;\r\n\r\n const mod = (n, m) => {\r\n return ((n % m) + m) % m;\r\n }\r\n\r\n return stations.map((station, index) => {\r\n const modal = (\r\n this.toggleAddVolunteersModal(station.id)}\r\n backdrop='static'\r\n >\r\n this.toggleAddVolunteersModal(station.id)}\r\n nextModal={() => this.nextAddVolunteersModal(station.id, stations[mod(index+1, stations.length)].id)}\r\n prevModal={() => this.nextAddVolunteersModal(station.id, stations[mod(index-1, stations.length)].id)}\r\n {...restProps}\r\n />\r\n )\r\n\r\n return {\r\n modal,\r\n ...station\r\n };\r\n });\r\n }\r\n\r\n formatStations() {\r\n const {\r\n initialValues: { stations = [] } = {},\r\n eventOffers,\r\n eventId\r\n } = this.props;\r\n\r\n return stations.map((station, index) => {\r\n const offers = filterStationOffers({\r\n offers: eventOffers,\r\n eventId,\r\n stationId: station.id\r\n });\r\n const officialsAllocated = offers\r\n ? offers\r\n .filter(offer => offer.status === \"ACCEPTED\")\r\n .reduce((allocated, offer) => allocated + +offer.volunteers, 0)\r\n : 0;\r\n const officialsDraft = offers\r\n ? offers\r\n .filter(offer => offer.status === \"DRAFT\")\r\n .reduce((allocated, offer) => allocated + +offer.volunteers, 0)\r\n : 0;\r\n const officialsProposed = offers\r\n ? offers\r\n .filter(offer => offer.status === \"PROPOSAL\")\r\n .reduce((allocated, offer) => allocated + +offer.volunteers, 0)\r\n : 0;\r\n let officialsMissing =\r\n station.officialQuantity - officialsAllocated < 0\r\n ? 0\r\n : station.officialQuantity - officialsAllocated;\r\n\r\n const officialQuantity = parseInt(station.officialQuantity);\r\n\r\n return {\r\n offers,\r\n officialsAllocated,\r\n officialsDraft,\r\n officialsProposed,\r\n officialsMissing,\r\n ...station,\r\n officialQuantity,\r\n };\r\n });\r\n }\r\n\r\n handleSort(field, order) {\r\n this.setState({\r\n field: field,\r\n order: order\r\n });\r\n }\r\n\r\n render() {\r\n let formattedStations = this.formatStations();\r\n formattedStations.sort((a, b) => (a[this.state.field] > b[this.state.field] ? 1 : -1))\r\n if (this.state.order === \"desc\") formattedStations.reverse();\r\n formattedStations = this.formatModals(formattedStations);\r\n\r\n const columns = [\r\n {\r\n dataField: \"id\",\r\n text: \"id\",\r\n hidden: true,\r\n sort: true\r\n },\r\n {\r\n dataField: \"name\",\r\n text: this.props.intl.formatMessage(messages.station.workStation),\r\n headerStyle: {\r\n textAlign: \"center\"\r\n },\r\n sort: true,\r\n onSort: this.handleSort\r\n },\r\n {\r\n dataField: \"officialQuantity\",\r\n text: this.props.intl.formatMessage(messages.station.officialQuantity),\r\n headerStyle: {\r\n textAlign: \"center\"\r\n },\r\n sort: true,\r\n onSort: this.handleSort\r\n },\r\n {\r\n dataField: \"officialsDraft\",\r\n text: this.props.intl.formatMessage(\r\n messages.station.officialPreliminary\r\n ),\r\n headerStyle: {\r\n textAlign: \"center\"\r\n },\r\n headerClasses: \"hidden-xs\",\r\n classes: \"hidden-xs\",\r\n sort: true,\r\n onSort: this.handleSort\r\n },\r\n {\r\n dataField: \"officialsProposed\",\r\n text: this.props.intl.formatMessage(\r\n messages.station.officialsAwaitingAnswer\r\n ),\r\n headerStyle: {\r\n textAlign: \"center\"\r\n },\r\n headerClasses: \"hidden-xs\",\r\n classes: \"hidden-xs\",\r\n sort: true,\r\n onSort: this.handleSort\r\n },\r\n {\r\n dataField: \"officialsAllocated\",\r\n text: this.props.intl.formatMessage(\r\n messages.station.officialsAllocated\r\n ),\r\n headerStyle: {\r\n textAlign: \"center\"\r\n },\r\n sort: true,\r\n onSort: this.handleSort\r\n },\r\n {\r\n dataField: \"officialsMissing\",\r\n text: this.props.intl.formatMessage(messages.station.officialsMissing),\r\n headerStyle: {\r\n textAlign: \"center\",\r\n },\r\n headerClasses: \"hidden-xs\",\r\n classes: \"hidden-xs\",\r\n sort: true,\r\n onSort: this.handleSort\r\n }\r\n ];\r\n\r\n const { initialValues: { stations = [] } = {} } = this.props;\r\n\r\n const rowEvents = {\r\n onClick: (e, row, rowIndex) => {\r\n this.toggleAddVolunteersModal(row.id);\r\n },\r\n };\r\n\r\n if (this.props.event.status == \"DRAFT\") {\r\n \r\n return (\r\n \r\n \r\n
\r\n );\r\n }\r\n\r\n return (\r\n \r\n {formattedStations.map(s => {return s.modal})}\r\n \r\n \r\n \r\n \r\n \r\n {this.props.event.status == \"HISTORIC\" ? \"\" : \r\n \r\n }\r\n \r\n \r\n {this.props.event.status == \"HISTORIC\" ? \"\" : \r\n \r\n }\r\n \r\n \r\n \r\n \r\n {stations.length > 0 && (\r\n \r\n \r\n \r\n )}\r\n \r\n );\r\n }\r\n}\r\n\r\n// This shall change according to how the server serves stationAllocations\r\nlet StationsForm = injectIntl(Stations);\r\n\r\nStationsForm = connect(state => ({\r\n initialValues: {\r\n // Shallow copy of stations and then sort it on officialQuantity\r\n stations: state.event.event.stations\r\n ? state.event.event.stations\r\n .map(s => Object.assign({}, s))\r\n : [],\r\n },\r\n}))(StationsForm);\r\n\r\nexport default StationsForm;\r\n","import StationOffers from \"./StationOffers\";\r\nimport { withRouter } from \"react-router\";\r\nimport { connect } from \"react-redux\";\r\nimport {\r\n fetchEventOffers,\r\n fetchAvailableGroups,\r\n createOffer,\r\n confirmStationOffers,\r\n deleteOffer,\r\n resetAvailableGroups\r\n} from \"../../Offer/reducer\";\r\n\r\nconst mapStateToProps = (state, ownProps) => ({\r\n eventOffers: state.offers.eventOffers,\r\n availableGroups: state.offers.availableGroups,\r\n event: ownProps.event,\r\n deleteOfferError: state.offers.deleteOfferError,\r\n offerCreateStatus: state.offers.offerCreateStatus,\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n fetchEventOffers: data => dispatch(fetchEventOffers(data)),\r\n fetchAvailableGroups: data => dispatch(fetchAvailableGroups(data)),\r\n createOffer: data => dispatch(createOffer(data)),\r\n //confirmStationOffer: data => dispatch(confirmStationOffer(data)),\r\n confirmStationOffers: data => dispatch(confirmStationOffers(data)),\r\n deleteOffer: data => dispatch(deleteOffer(data)),\r\n resetAvailableGroups: () => dispatch(resetAvailableGroups())\r\n});\r\n\r\nexport default withRouter(connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(StationOffers));\r\n","export const SEND_SEND_OUT = 'SEND_SEND_OUT';\r\nexport const SEND_OUT_SUCCESS = 'SEND_OUT_SUCCESS';\r\nexport const SEND_OUT_FAILED = 'SEND_OUT_FAILED';\r\nexport const FETCH_SEND_OUTS = 'FETCH_SEND_OUTS';\r\nexport const FETCH_SEND_OUTS_SUCCESS = 'FETCH_SEND_OUTS_SUCCESS';\r\nexport const FETCH_SEND_OUTS_FAILED = 'FETCH_SEND_OUTS_FAILED';\r\nexport const FETCH_SEND_OUT = 'FETCH_SEND_OUT';\r\nexport const FETCH_SEND_OUT_SUCCESS = 'FETCH_SEND_OUT_SUCCESS';\r\nexport const FETCH_SEND_OUT_FAILED = 'FETCH_SEND_OUT_FAILED';\r\n\r\nexport function sendSendOut (data) {\r\n return {\r\n type: SEND_SEND_OUT,\r\n payload: data,\r\n };\r\n}\r\n\r\nexport function fetchSendOuts (data) {\r\n return {\r\n type: FETCH_SEND_OUTS,\r\n payload: data,\r\n };\r\n}\r\n\r\nexport function fetchSendOut (data) {\r\n return {\r\n type: FETCH_SEND_OUT,\r\n payload: data,\r\n };\r\n}\r\n\r\nexport const status = {\r\n PENDING: 'PENDING',\r\n SENDING: 'SENDING',\r\n SEND_SUCCESS: 'SEND_SUCCESS',\r\n SEND_FAILED: 'SEND_FAILED',\r\n};\r\n\r\nexport const fetchStatus = {\r\n PENDING: 'PENDING',\r\n FETCHING: 'FETCHING',\r\n FETCH_SUCCESS: 'FETCH_SUCCESS',\r\n FETCH_FAILED: 'FETCH_FAILED',\r\n};\r\n\r\nexport const initialState = {\r\n status: status.PENDING,\r\n fetchStatus: fetchStatus.PENDING,\r\n sendOuts: null,\r\n error: null,\r\n sendOut: null,\r\n fetchSingleStatus: fetchStatus.PENDING,\r\n};\r\n\r\n\r\nconst sortOnCreatedAt = (a,b) => {\r\n return new Date(b.createdAt) - new Date(a.createdAt);\r\n};\r\n\r\nexport default function auth(state = initialState, action) {\r\n if (!action) {\r\n return state;\r\n }\r\n\r\n switch (action.type) {\r\n case SEND_SEND_OUT:\r\n return Object.assign({}, state, {status: status.SENDING});\r\n case SEND_OUT_SUCCESS:\r\n return Object.assign({}, state, {status: status.SEND_SUCCESS});\r\n case SEND_OUT_FAILED:\r\n return Object.assign({}, state, {status: status.SEND_FAILED, error: action.payload});\r\n case FETCH_SEND_OUTS:\r\n return Object.assign({}, state, {fetchStatus: fetchStatus.FETCHING});\r\n case FETCH_SEND_OUTS_SUCCESS:\r\n const sendOuts = action.payload.sort(sortOnCreatedAt);\r\n return Object.assign({}, state, {fetchStatus: fetchStatus.FETCH_SUCCESS, sendOuts: sendOuts});\r\n case FETCH_SEND_OUTS_FAILED:\r\n return Object.assign({}, state, {fetchStatus: fetchStatus.FETCH_FAILED});\r\n case FETCH_SEND_OUT:\r\n return Object.assign({}, state, {fetchSingleStatus: fetchStatus.FETCHING});\r\n case FETCH_SEND_OUT_SUCCESS:\r\n return Object.assign({}, state, {fetchSingleStatus: fetchStatus.FETCH_SUCCESS, sendOut: action.payload});\r\n case FETCH_SEND_OUT_FAILED:\r\n return Object.assign({}, state, {fetchSingleStatus: fetchStatus.FETCH_FAILED});\r\n default:\r\n return state;\r\n }\r\n}","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n form: {\r\n title: {\r\n id: 'send-outs.form.title',\r\n },\r\n previousSendOuts: {\r\n id: 'send-outs.form.previous-send-outs',\r\n },\r\n info: {\r\n id: 'send-outs.form.info',\r\n },\r\n infoItalic: {\r\n id: 'send-outs.form.info-italic',\r\n },\r\n receivers: {\r\n title: {\r\n id: 'send-outs.form.receivers-title',\r\n },\r\n info: {\r\n id: 'send-outs.form.receivers-info',\r\n }\r\n },\r\n header: {\r\n name: {\r\n id: 'send-outs.form.header-name',\r\n },\r\n age: {\r\n id: 'send-outs.form.header-age',\r\n },\r\n phone: {\r\n id: 'send-outs.form.header-phone',\r\n },\r\n email: {\r\n id: 'send-outs.form.header-email',\r\n },\r\n },\r\n recipientTypes: {\r\n id: 'send-outs.form.recipient-types',\r\n },\r\n recipientTypeOptions: {\r\n VOLUNTEERS: {\r\n id: 'send-outs.form.recipient-type-options.volunteers',\r\n },\r\n CONTACT_PERSONS: {\r\n id: 'send-outs.form.recipient-type-options.contact-persons',\r\n },\r\n },\r\n volunteerExpected: {\r\n id: 'send-outs.form.stations.volunteerExpected'\r\n },\r\n officialQuantity: {\r\n id: 'send-outs.form.stations.officialQuantity'\r\n },\r\n stations: {\r\n name: {\r\n id: 'send-outs.form.stations.name',\r\n },\r\n groups: {\r\n id: 'send-outs.form.stations.groups',\r\n },\r\n noStations: {\r\n id: 'send-outs.form.stations.no-stations',\r\n }\r\n },\r\n subject: {\r\n id: 'send-outs.form.subject',\r\n },\r\n message: {\r\n id: 'send-outs.form.message',\r\n },\r\n attachments: {\r\n id: 'send-outs.form.attachments',\r\n },\r\n attachmentsButton: {\r\n id: 'send-outs.form.attachments-button',\r\n },\r\n noStationsError: {\r\n id: 'send-outs.form.no-stations-error',\r\n },\r\n noRecipientTypes: {\r\n id: 'send-outs.form.no-recipient-types-error',\r\n },\r\n sendButton: {\r\n id: 'send-outs.form.send-button',\r\n },\r\n sendError: {\r\n id: 'send-outs.form.send-error',\r\n },\r\n sent: {\r\n id: 'send-outs.form.sent',\r\n }\r\n },\r\n list: {\r\n title: {\r\n id: 'send-outs.list.title',\r\n },\r\n created: {\r\n id: 'send-outs.list.created',\r\n },\r\n subject: {\r\n id: 'send-outs.list.subject',\r\n },\r\n noSendOuts: {\r\n id: 'send-outs.list.no-send-outs',\r\n }\r\n },\r\n single: {\r\n title: {\r\n id: 'send-outs.single.title',\r\n },\r\n error: {\r\n id: 'send-outs.single.error',\r\n },\r\n }\r\n});\r\n","import React, { Fragment, useState } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport messages from \"../messages\";\r\nimport { FormattedMessage } from \"react-intl\";\r\nimport {\r\n Checkbox,\r\n BorderTable,\r\n Error,\r\n P,\r\n} from \"../../../../../components\";\r\nimport styled from \"styled-components\";\r\nimport { colors } from \"../../../../../constants/styling-constants\";\r\n\r\nconst TDDisabledText = styled.td`\r\n &.no-groups {\r\n color: ${colors.mediumLightGray};\r\n }\r\n`;\r\n\r\nconst TDGrayBackground = styled.td`\r\n background-color: ${colors.lightGray} !important;\r\n`;\r\n\r\nconst StationsListCheckboxes = ({ stations, values = [], changeValue, offers, groups = [], meta: { touched, error, warning } }) => {\r\n const [expanded, setExpanded] = useState([]);\r\n const haveNoGroups = (station, allOffers) => {\r\n const ofs = allOffers.filter(o => o.stationId === station.id && o.status === \"ACCEPTED\");\r\n return ofs.length === 0;\r\n };\r\n \r\n const stationsWithNoGroups = stations ? stations.filter(s => haveNoGroups(s, offers)) : [];\r\n\r\n const onChangeStation = (e) => {\r\n const name = parseInt(e.target.name, 10);\r\n let vals = [];\r\n\r\n if (e.target.checked) {\r\n vals = values.splice(0);\r\n vals.push(parseInt(name, 10));\r\n } else {\r\n const index = values.indexOf(name);\r\n\r\n if (index > -1) {\r\n vals = values.filter(v => v !== name);\r\n }\r\n }\r\n\r\n changeValue(\"stations\", vals);\r\n };\r\n\r\n const onRowClick = (rowId) => {\r\n const prevExpanded = expanded;\r\n const isRowExpanded = prevExpanded.includes(rowId);\r\n const newExpanded = isRowExpanded ? prevExpanded.filter(id => id !== rowId) : prevExpanded.concat(rowId);\r\n setExpanded(newExpanded);\r\n }\r\n\r\n const renderVolunteerRowHeader = (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n\r\n const renderVolunteerRow = (volunteer) => {\r\n return (\r\n \r\n \r\n \r\n {volunteer.name} \r\n {volunteer.age} \r\n {volunteer.phone} \r\n {volunteer.email} \r\n \r\n );\r\n }\r\n \r\n const renderRow = (station) => {\r\n const noGroups = haveNoGroups(station, offers);\r\n const group = groups.filter(eventStations => eventStations.stationId === station.id);\r\n const rows = [\r\n onRowClick(station.id)}>\r\n \r\n \r\n \r\n \r\n {expanded.includes(station.id) ? : }\r\n \r\n {station.name} \r\n {renderGroupNames(station, offers)} \r\n {renderVolunteerExpected(station, offers)} \r\n {station.officialQuantity} \r\n \r\n ];\r\n\r\n if(group.length === 0)\r\n return rows;\r\n \r\n if(expanded.includes(station.id)) {\r\n rows.push(renderVolunteerRowHeader);\r\n group.map(g => g.attendees ? rows.push(g.group.volunteers.filter(vol => g.attendees.includes(vol.id)).map(vol => renderVolunteerRow(vol))) : null);\r\n }\r\n return rows;\r\n }\r\n\r\n const onChangeAll = () => {\r\n let vals = [];\r\n\r\n if (values.length !== stations.length - stationsWithNoGroups.length) {\r\n vals = stations.reduce((result, s) => {\r\n if (!haveNoGroups(s, offers)) {\r\n result.push(parseInt(s.id, 10));\r\n }\r\n return result;\r\n }, []);\r\n }\r\n\r\n changeValue(\"stations\", vals);\r\n };\r\n\r\n const renderVolunteerExpected = (station, allOffers) => {\r\n var count = 0;\r\n allOffers.filter(o => o.stationId === station.id && o.status === \"ACCEPTED\").map(o => {\r\n if (o.attendees) {\r\n count = count + o.attendees.length;\r\n }\r\n return o;\r\n })\r\n return count;\r\n }\r\n\r\n const renderGroupNames = (station, allOffers) => {\r\n const ofs = allOffers.filter(o => o.stationId === station.id && o.status === \"ACCEPTED\").map(o => o.group.name);\r\n return ofs.join(\", \");\r\n };\r\n\r\n if (!stations) {\r\n return (
);\r\n }\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {stations.map(stations => renderRow(stations))}\r\n \r\n \r\n {touched &&\r\n ((error && ) ||\r\n (warning && {warning} ))}\r\n \r\n );\r\n};\r\n\r\nStationsListCheckboxes.propTypes = {\r\n stations: PropTypes.array,\r\n values: PropTypes.array,\r\n changeValue: PropTypes.func.isRequired,\r\n offers: PropTypes.array,\r\n};\r\n\r\nexport default StationsListCheckboxes;\r\n","import React, { Component } from \"react\";\r\nimport connect from \"react-redux/lib/connect/connect\";\r\nimport { Field, reduxForm, formValueSelector } from \"redux-form\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport {\r\n H2,\r\n H3,\r\n P,\r\n ItalicP,\r\n FormGroup,\r\n ListSelect,\r\n Input,\r\n TextLabel,\r\n TextArea,\r\n FileUpload,\r\n GeneralError,\r\n TextSection,\r\n} from \"../../../../../components\";\r\nimport { SmallGrayLinkButton } from \"../../../../../components/Links/index\";\r\nimport { SmallPinkButton } from \"../../../../../components/Buttons\";\r\nimport messages from \"../messages\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport StationsListCheckboxes from \"./StationsListCheckboxes\";\r\nimport {\r\n required,\r\n maxLength250,\r\n minLength3,\r\n atLeastOneArrayElement,\r\n validateFileArraySize\r\n} from \"../../../../../validators/index\";\r\nimport { status } from \"../reducer\";\r\nimport moment from \"moment\";\r\nimport styled from \"styled-components\";\r\nimport { breakPoints } from \"../../../../../constants/styling-constants\";\r\n\r\n\r\nconst TagWrapper = styled.div`\r\n display: flex;\r\n flex-direction: row;\r\n`;\r\n\r\nconst TextLabelNoMargin = TextLabel.extend`\r\n margin: 0;\r\n`;\r\n\r\nconst Tag = P.extend`\r\n margin: 0;\r\n margin-left: 5px;\r\n `;\r\n\r\nconst H2WithLink = H2.extend`\r\n display: flex;\r\n justify-content: space-between;\r\n margin-top: 0px;\r\n @media (max-width: ${breakPoints.xs}px) {\r\n flex-direction: column;\r\n align-items: center;\r\n .mobile-view{\r\n margin-top: 15px;\r\n }\r\n }\r\n`;\r\n\r\nconst recipientTypes = [\"VOLUNTEERS\", \"CONTACT_PERSONS\"];\r\nconst totalMaxFileSize = 6.3;\r\n\r\nclass SendOutsForm extends Component {\r\n\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n mappedRecipientTypes: recipientTypes.map(rt => ({\r\n id: rt,\r\n value: this.props.intl.formatMessage({ id: `form.recipientTypeOptions.${rt}` })\r\n })),\r\n sendOutSent: false,\r\n };\r\n\r\n this.handleSendOutSubmit = this.handleSendOutSubmit.bind(this);\r\n this.validateStations = atLeastOneArrayElement(this.props.intl.formatMessage(messages.form.noStationsError));\r\n this.validateStations = this.validateStations.bind(this);\r\n this.validateRecipientTypes = atLeastOneArrayElement(this.props.intl.formatMessage(messages.form.noRecipientTypes));\r\n this.validateRecipientTypes = this.validateRecipientTypes.bind(this);\r\n this.validateFileSize = validateFileArraySize(totalMaxFileSize);\r\n this.getExtraValues = this.getExtraValues.bind(this);\r\n }\r\n\r\n async componentDidMount() {\r\n this.props.fetchEventOffers({ eventId: this.props.event.id });\r\n\r\n }\r\n\r\n componentDidUpdate(prevProps) {\r\n if (this.props.status === status.SEND_SUCCESS && prevProps.status !== status.SEND_SUCCESS) {\r\n this.props.reset();\r\n\r\n this.setState({ sendOutSent: true }, () => {\r\n window.setTimeout(() => {\r\n this.setState({ sendOutSent: false });\r\n }, 5000);\r\n });\r\n }\r\n }\r\n\r\n getMapCoordinates(stationId) {\r\n const coordinates = this.props.event.stations.filter(s => s.id === stationId)[0].markerCoordinates;\r\n return \"https://maps.google.com/?q=\" + coordinates.lat.toFixed(6) + \",\" + coordinates.lng.toFixed(6);\r\n }\r\n\r\n getExtraValues(stations) {\r\n const extra = stations.map(id => { return {id: id, coordinates: this.getMapCoordinates(id)}})\r\n return extra; //[{id: 1231, coordinate: 123123, annat: \"hej\"}, {id: 3123, coordinate: 123128371092, annat: \"dasdkhsa\"}];\r\n }\r\n\r\n addExtra = (stations, message, extra) => {\r\n const keys = ['coordinates']; //Add more keys here to be able to include more tags in a message\r\n const messages = stations.map(s => {\r\n let m = message;\r\n const e = extra.filter(ex => ex.id === s)[0];\r\n keys.map(k => m = m.replace('\\\\' + k, e[k]));\r\n return {id: s, message: m};\r\n });\r\n return messages;\r\n }\r\n\r\n handleSendOutSubmit(fieldValues) {\r\n const extraValues = this.getExtraValues(fieldValues.stations);\r\n const messages = this.addExtra(fieldValues.stations, fieldValues.message, extraValues);\r\n fieldValues.stations.map(id => {\r\n const newValues = JSON.parse(JSON.stringify(Object.assign(fieldValues, { // This may look bad but is needed to create a DEEP copy of the object.\r\n eventId: this.props.event.id,\r\n createdAt: moment().format(),\r\n stations: [id],\r\n message: messages.filter(m => m.id === id)[0].message\r\n })));\r\n return this.props.sendSendOut(newValues);\r\n })\r\n }\r\n\r\n renderError() {\r\n if (this.props.status === status.SEND_FAILED) {\r\n return ( )\r\n }\r\n\r\n return null;\r\n }\r\n\r\n renderSuccess() {\r\n if (this.state.sendOutSent) {\r\n return (
);\r\n }\r\n\r\n return null;\r\n }\r\n\r\n render() {\r\n const linkBase = this.props.isTeamleaderView ? \"/my-pages/teamleaders\" : \"/my-pages/events\";\r\n if(this.props.event.status === \"HISTORIC\"){\r\n return (\r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n )\r\n }\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n
\r\n \r\n \r\n );\r\n }\r\n\r\n}\r\n\r\nSendOutsForm = reduxForm({\r\n form: \"sendOutsForm\",\r\n})(SendOutsForm);\r\n\r\nconst selector = formValueSelector(\"sendOutsForm\");\r\n\r\nSendOutsForm = connect(\r\n state => ({\r\n initialValues: {\r\n // Shallow copy of stations and then sort it on officialQuantity\r\n stations: [],\r\n },\r\n stations: selector(state, \"stations\"),\r\n attachments: selector(state, \"attachments\")\r\n })\r\n)(SendOutsForm);\r\n\r\nexport default injectIntl(SendOutsForm);\r\n","import { connect } from \"react-redux\";\r\nimport { sendSendOut } from \"../reducer\";\r\nimport { withRouter } from \"react-router\";\r\nimport { fetchEventOffers } from \"../../../Offer/reducer\";\r\nimport SendOutsForm from \"./SendOutsForm\";\r\n\r\nconst mapStateToProps = (state) => ({\r\n status: state.sendOuts.status,\r\n eventOffers: state.offers.eventOffers,\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n sendSendOut: data => dispatch(sendSendOut(data)),\r\n fetchEventOffers: data => dispatch(fetchEventOffers(data)),\r\n});\r\n\r\nexport default withRouter(connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(SendOutsForm));\r\n","import React, { Component } from \"react\";\r\nimport moment from \"moment\";\r\nimport {\r\n BorderTable,\r\n FormGroup,\r\n H2,\r\n P,\r\n} from \"../../../../../components\";\r\nimport messages from \"../messages\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport { status, fetchStatus } from \"../reducer\";\r\nimport styled from \"styled-components\";\r\nimport { withRouter } from \"react-router-dom\";\r\n\r\nconst TableRowWithClick = styled(\"tr\")`\r\n cursor: pointer;\r\n`;\r\n\r\nclass SendOutsList extends Component {\r\n\r\n constructor(props) {\r\n super(props);\r\n\r\n this.onRowClick = this.onRowClick.bind(this);\r\n }\r\n\r\n componentDidMount() {\r\n this.props.fetchSendOuts(this.props.event.id);\r\n }\r\n\r\n componentDidUpdate(prevProps) {\r\n if (this.props.status === status.SEND_SUCCESS && prevProps.status !== status.SEND_SUCCESS) {\r\n this.props.fetchSendOuts(this.props.event.id);\r\n }\r\n }\r\n\r\n onRowClick(sendOut) {\r\n const linkBase = this.props.isTeamleaderView ? \"/my-pages/teamleaders\" : \"/my-pages/events\";\r\n this.props.history.push(`${linkBase}/${this.props.event.id}/sendouts/${sendOut.sendOutId}`);\r\n }\r\n\r\n renderSpinner() {\r\n if (this.props.fetchStatus === fetchStatus.FETCHING) {\r\n return ( );\r\n }\r\n\r\n return null;\r\n }\r\n\r\n renderTable() {\r\n if (this.props.fetchStatus === fetchStatus.FETCH_SUCCESS && (!this.props.sendOuts || this.props.sendOuts.length === 0)) {\r\n return (
);\r\n }\r\n\r\n if (!this.props.sendOuts) {\r\n return null;\r\n }\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {this.props.sendOuts.map((s, index) => {\r\n return (\r\n this.onRowClick(s)}\r\n >\r\n {moment(s.createdAt).format(\"YYYY-MM-DD HH:mm\")} \r\n {s.subject} \r\n \r\n )\r\n })}\r\n \r\n \r\n )\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n \r\n {this.renderSpinner()}\r\n {this.renderTable()}\r\n \r\n );\r\n }\r\n}\r\n\r\nexport default withRouter(injectIntl(SendOutsList));\r\n","import { connect } from \"react-redux\";\r\nimport { withRouter } from \"react-router\";\r\nimport { fetchSendOuts } from \"../reducer\";\r\nimport SendOutsList from \"./SendOutsList\";\r\n\r\nconst mapStateToProps = (state) => ({\r\n fetchStatus: state.sendOuts.fetchStatus,\r\n status: state.sendOuts.status,\r\n sendOuts: state.sendOuts.sendOuts,\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n fetchSendOuts: data => dispatch(fetchSendOuts(data)),\r\n});\r\n\r\nexport default withRouter(connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(SendOutsList));\r\n","import React, { Component, Fragment } from \"react\";\r\nimport { withRouter } from \"react-router-dom\";\r\nimport { fetchStatus } from \"../reducer\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport messages from \"../messages\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport {\r\n H2,\r\n P,\r\n GeneralError,\r\n TextLabel,\r\n ListSelect,\r\n Input,\r\n TextArea,\r\n FileUpload,\r\n} from \"../../../../../components\";\r\n\r\nconst recipientTypes = [\"VOLUNTEERS\", \"CONTACT_PERSONS\"];\r\n\r\nclass SendOut extends Component {\r\n\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n mappedRecipientTypes: recipientTypes.map(rt => ({\r\n id: rt,\r\n value: this.props.intl.formatMessage({ id: `form.recipientTypeOptions.${rt}` })\r\n })),\r\n }\r\n }\r\n\r\n componentDidMount() {\r\n this.props.fetchSendOut({\r\n sendOutId: this.props.match.params.sendOutId,\r\n eventId: this.props.event.id\r\n });\r\n }\r\n\r\n renderSelectedStations() {\r\n const stations = [];\r\n\r\n this.props.sendOut.stations.forEach(s => {\r\n const station = this.props.event.stations.find(es => es.id === s);\r\n if (stations) {\r\n stations.push(station.name);\r\n }\r\n });\r\n\r\n return stations.join(\", \");\r\n }\r\n\r\n render() {\r\n if (this.props.status === fetchStatus.FETCHING) {\r\n return ( );\r\n }\r\n\r\n if (!this.props.sendOut) {\r\n return null;\r\n }\r\n\r\n if (this.props.status === fetchStatus.FETCH_FAILED) {\r\n return (\r\n \r\n )\r\n }\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {this.renderSelectedStations()}
\r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n );\r\n }\r\n\r\n}\r\n\r\nexport default withRouter(injectIntl(SendOut));\r\n","import { connect } from \"react-redux\";\r\nimport { withRouter } from \"react-router\";\r\nimport { fetchSendOut } from \"../reducer\";\r\nimport SendOut from \"./SendOut\";\r\n\r\nconst mapStateToProps = (state) => ({\r\n status: state.sendOuts.fetchSingleStatus,\r\n sendOut: state.sendOuts.sendOut,\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n fetchSendOut: data => dispatch(fetchSendOut(data)),\r\n});\r\n\r\nexport default withRouter(connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(SendOut));\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n attendanceList: {\r\n title: {\r\n id: 'attendance.list.title',\r\n },\r\n description: {\r\n id: 'attendance.list.description',\r\n },\r\n showButton: {\r\n id: 'attendance.list.show-button',\r\n },\r\n offerError: {\r\n id: 'attendance.list.offer-error'\r\n },\r\n noStations: {\r\n id: 'attendance.list.no-stations'\r\n }\r\n },\r\n\r\n});\r\n","import React, { Component } from \"react\";\r\nimport styled from \"styled-components\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport messages from \"./messages\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport {\r\n H2,\r\n P,\r\n WhiteTableWithLastToRight,\r\n TableRowWithClick,\r\n GeneralError\r\n} from \"../../../../components/index\";\r\nimport { TableButton } from \"../../../../components/Buttons/index\";\r\nimport moment from \"moment\";\r\nimport { withRouter } from \"react-router\";\r\nimport { statuses } from \"../../Offer/reducer\";\r\n\r\nconst Wrapper = styled.div`\r\n margin-bottom: 80px;\r\n`;\r\n\r\nconst sortOnStartTime = (a, b) => {\r\n if (a.start < b.start)\r\n return -1;\r\n if (a.start > b.start)\r\n return 1;\r\n return 0;\r\n};\r\n\r\nconst AttendanceListRow = ({ station, intl, history, match }) => {\r\n const onClick = () => {\r\n history.push(`${match.url}/${station.id}`);\r\n };\r\n\r\n const renderGroupNames = (station) => {\r\n if (!station.offers) {\r\n return \"\";\r\n }\r\n\r\n const names = station.offers\r\n .filter(o => o.status === \"ACCEPTED\")\r\n .map(o => o.group.name);\r\n\r\n return names.join(\", \");\r\n };\r\n\r\n return (\r\n \r\n {station.name} \r\n {moment(station.start).format(\"HH:mm\")} \r\n {renderGroupNames(station)} \r\n \r\n \r\n )\r\n\r\n};\r\n\r\nconst AttendanceListRowWithRouter = withRouter(AttendanceListRow);\r\n\r\nclass AttendanceList extends Component {\r\n\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n stationsWithOffers: this.matchOfferWithStation(this.props.event.stations, this.props.eventOffers)\r\n }\r\n }\r\n\r\n componentDidUpdate(prevProps) {\r\n if (!prevProps.eventOffers.hasOwnProperty(this.props.event.id) && this.props.eventOffers.hasOwnProperty(this.props.event.id)) {\r\n this.setState({\r\n stationsWithOffers: this.matchOfferWithStation(this.props.event.stations, this.props.eventOffers)\r\n });\r\n }\r\n }\r\n\r\n componentDidMount() {\r\n this.props.fetchEventOffers({ eventId: this.props.event.id });\r\n }\r\n\r\n matchOfferWithStation(stations, offers) {\r\n if (!offers.hasOwnProperty(this.props.event.id)) {\r\n return stations || [];\r\n }\r\n\r\n const stationsWithOffers = JSON.parse(JSON.stringify(stations));\r\n const eventOffers = offers[this.props.event.id].filter(o => stationsWithOffers.find(s => s.id === o.stationId));\r\n\r\n eventOffers.forEach(o => {\r\n const station = stationsWithOffers.find(s => s.id === o.stationId);\r\n if (!station.offers) {\r\n station.offers = [];\r\n }\r\n station.offers.push(o);\r\n });\r\n\r\n stationsWithOffers.sort(sortOnStartTime);\r\n\r\n return stationsWithOffers;\r\n }\r\n\r\n renderTable() {\r\n return (\r\n \r\n \r\n {this.state.stationsWithOffers.length === 0\r\n ? \r\n \r\n \r\n : this.state.stationsWithOffers.map(station => )}\r\n \r\n \r\n );\r\n }\r\n\r\n renderContent() {\r\n if (this.props.offerError) {\r\n return (\r\n \r\n \r\n \r\n )\r\n }\r\n\r\n if (this.props.offerStatus !== statuses.FETCHED) {\r\n return ;\r\n }\r\n\r\n return this.renderTable();\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n \r\n \r\n \r\n
\r\n {this.renderContent()}\r\n \r\n
\r\n\r\n \r\n );\r\n }\r\n\r\n}\r\n\r\nexport default injectIntl(AttendanceList);\r\n","import { connect } from \"react-redux\";\r\nimport { fetchEventOffers } from \"../../Offer/reducer\";\r\nimport AttendanceList from \"./AttendanceList\";\r\nimport { withRouter } from \"react-router\";\r\n\r\nconst mapStateToProps = (state, ownProps) => ({\r\n event: ownProps.event,\r\n eventOffers: state.offers.eventOffers,\r\n offerStatus: state.offers.status,\r\n offerError: state.offers.error,\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n fetchEventOffers: data => dispatch(fetchEventOffers(data)),\r\n});\r\n\r\nexport default withRouter(connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(AttendanceList));\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n attendance: {\r\n form: {\r\n name: {\r\n id: 'attendance.form.name',\r\n },\r\n start: {\r\n id: 'attendance.form.start',\r\n },\r\n end: {\r\n id: 'attendance.form.end',\r\n },\r\n officialQuantity: {\r\n id: 'attendance.form.officialQuantity',\r\n },\r\n officialMinimumAge: {\r\n id: 'attendance.form.officialMinimumAge',\r\n }\r\n },\r\n offerError: {\r\n id: 'attendance.offer-error'\r\n },\r\n noOffers: {\r\n id: 'attendance.no-offers'\r\n }\r\n }\r\n});\r\n","export const ATTENDANCE_SUBMIT = 'ATTENDANCE_SUBMIT';\r\nexport const ATTENDANCE_SUBMIT_SUCCESS = 'ATTENDANCE_SUBMIT_SUCCESS';\r\nexport const ATTENDANCE_SUBMIT_FAILED = 'ATTENDANCE_SUBMIT_FAILED';\r\nexport const RESET = 'RESET';\r\n\r\nexport function submitAttendance (data) {\r\n return {\r\n type: ATTENDANCE_SUBMIT,\r\n payload: data,\r\n };\r\n}\r\n\r\nexport function reset (data) {\r\n return {\r\n type: RESET,\r\n };\r\n}\r\n\r\nconst statuses = {\r\n INIT: 'INIT',\r\n SUBMITTING: 'SUBMITTING',\r\n SUBMITTED: 'SUBMITTED',\r\n FAILED: 'FAILED'\r\n};\r\n\r\nconst initialState = {\r\n groups: {}, // Will have groupId as key and contain status\r\n};\r\n\r\nexport default function attendance(state = initialState, action) {\r\n if (!action) {\r\n return state;\r\n }\r\n\r\n switch (action.type) {\r\n case RESET:\r\n return Object.assign({}, initialState);\r\n case ATTENDANCE_SUBMIT:\r\n const newState = Object.assign({}, state);\r\n newState.groups[action.payload.groupId] = statuses.SUBMITTING;\r\n return newState;\r\n case ATTENDANCE_SUBMIT_SUCCESS:\r\n const newSuccessGroups = Object.assign({}, state.groups);\r\n newSuccessGroups[action.payload.groupId] = statuses.SUBMITTED;\r\n\r\n return Object.assign({}, {groups: newSuccessGroups});\r\n case ATTENDANCE_SUBMIT_FAILED:\r\n const newGroups = Object.assign({}, state.groups);\r\n newGroups[action.payload.groupId] = statuses.FAILED;\r\n\r\n return Object.assign({}, {groups: newGroups});\r\n default:\r\n return state;\r\n }\r\n}\r\n\r\nexport {statuses};\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n groupAttendance: {\r\n title: {\r\n id: 'attendance.group.title'\r\n },\r\n volunteers: {\r\n id: 'attendance.group.volunteers'\r\n },\r\n contactPersons: {\r\n id: 'attendance.group.contact-persons'\r\n },\r\n tableHeader: {\r\n name: {\r\n id: 'attendance.group.table-header.name'\r\n },\r\n email: {\r\n id: 'attendance.group.table-header.email'\r\n },\r\n phone: {\r\n id: 'attendance.group.table-header.phone'\r\n }\r\n },\r\n formTitle: {\r\n id: 'attendance.group.form-title'\r\n },\r\n form: {\r\n adultAttendance: {\r\n id: 'attendance.group.form.adult-attendance'\r\n },\r\n childAttendance: {\r\n id: 'attendance.group.form.child-attendance'\r\n },\r\n submit: {\r\n id: 'attendance.group.form.submit'\r\n }\r\n },\r\n attendanceExceedVolunteers: {\r\n id: 'attendance.group.form.attendance-exceed-volunteers' \r\n },\r\n submitError: {\r\n id: 'attendance.group.form.submit-error'\r\n },\r\n attendanceNotAvailable: {\r\n id: 'attendance.group.form.attendance-not-available'\r\n }\r\n }\r\n\r\n});\r\n","import React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport {\r\n H3,\r\n H4,\r\n P,\r\n Input,\r\n TextSection,\r\n BorderTable,\r\n TextLabel,\r\n FormGroup,\r\n GeneralError\r\n} from \"../../../../../components/index\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport messages from \"./messages\";\r\nimport { Field, reduxForm } from \"redux-form\";\r\nimport { required, positiveNumbers, integer } from \"../../../../../validators/index\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport { Button } from \"../../../../../components/Buttons/index\";\r\nimport { statuses } from \"../reducer\";\r\nimport moment from \"moment\";\r\n\r\nclass GroupAttendance extends Component {\r\n\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n isStationOpen: this.isStationOpen(),\r\n hasValidationError: false,\r\n };\r\n\r\n this.onSubmit = this.onSubmit.bind(this);\r\n }\r\n\r\n componentWillUnmount() {\r\n this.props.reset();\r\n }\r\n\r\n /**\r\n * Station is open if it is today or in the past\r\n * @returns {boolean}\r\n */\r\n isStationOpen() {\r\n const today = moment().format(\"YYYY-MM-DD\");\r\n const start = moment(this.props.station.start).format(\"YYYY-MM-DD\");\r\n const diff = moment(today).diff(start);\r\n\r\n return diff >= 0 && this.props.event.status !== \"HISTORIC\";\r\n }\r\n\r\n onSubmit(fieldValues) {\r\n try {\r\n if(parseInt(this.props.offer.volunteers) >= parseInt(fieldValues.adultAttendance) + parseInt(fieldValues.childAttendance)) {\r\n this.setState({ hasValidationError: false })\r\n this.props.submitAttendance({\r\n ...fieldValues,\r\n eventId: this.props.offer.eventId,\r\n stationId: this.props.offer.stationId,\r\n groupId: this.props.offer.groupId,\r\n });\r\n } else {\r\n this.setState({ hasValidationError: true })\r\n }\r\n \r\n } catch (e) {\r\n console.error(`Failed parsing attendance string with err`)\r\n }\r\n }\r\n\r\n renderError() {\r\n if (this.props.attendance.groups.hasOwnProperty(this.props.offer.groupId) && this.props.attendance.groups[this.props.offer.groupId] === statuses.FAILED) {\r\n return (\r\n \r\n \r\n \r\n );\r\n }\r\n }\r\n\r\n renderContactPersons() {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n {this.props.intl.formatMessage(messages.groupAttendance.tableHeader.name)} \r\n {this.props.intl.formatMessage(messages.groupAttendance.tableHeader.email)} \r\n {this.props.intl.formatMessage(messages.groupAttendance.tableHeader.phone)} \r\n \r\n \r\n \r\n {this.props.offer.group.contactPersons.map((c, index) => {\r\n return (\r\n \r\n {c.name} \r\n {c.email.toLowerCase()} \r\n {c.phone} \r\n \r\n )\r\n })}\r\n \r\n \r\n \r\n );\r\n }\r\n\r\n renderForm() {\r\n return (\r\n \r\n \r\n \r\n \r\n
\r\n );\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n {this.props.offer.group.name} \r\n \r\n {this.renderForm()}\r\n {this.renderContactPersons()}\r\n \r\n );\r\n }\r\n\r\n}\r\n\r\nGroupAttendance.propTypes = {\r\n offer: PropTypes.object.isRequired,\r\n station: PropTypes.object.isRequired,\r\n};\r\n\r\nGroupAttendance = reduxForm({\r\n enableReinitialize: true,\r\n})(GroupAttendance);\r\n\r\nexport default injectIntl(GroupAttendance);\r\n","import { connect } from 'react-redux';\r\nimport { withRouter } from 'react-router';\r\nimport { submitAttendance, reset } from '../reducer';\r\nimport GroupAttendance from './GroupAttendance';\r\n\r\nconst mapStateToProps = (state, ownProps) => ({\r\n event: state.event.event,\r\n attendance: state.attendance,\r\n initialValues: {\r\n adultAttendance: ownProps.offer.adultAttendance || '',\r\n childAttendance: ownProps.offer.childAttendance || '',\r\n }\r\n});\r\n\r\nconst mapDispatchToProps = dispatch => ({\r\n submitAttendance: data => dispatch(submitAttendance(data)),\r\n reset: () => dispatch(reset()),\r\n});\r\n\r\nexport default withRouter(connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(GroupAttendance));\r\n","import React, { Component, Fragment } from \"react\";\r\nimport styled from \"styled-components\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport messages from \"./messages\";\r\nimport {\r\n H2,\r\n P,\r\n GeneralError,\r\n Input,\r\n ContentWrapper\r\n} from \"../../../../../components/index\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport moment from \"moment\";\r\nimport GroupAttendance from \"../GroupAttendance\";\r\n\r\nconst Wrapper = styled.div`\r\n margin-bottom: 80px;\r\n`;\r\n\r\nclass StationAttendance extends Component {\r\n\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n station: this.props.event.stations.find(s => s.id === parseInt(this.props.stationId, 10))\r\n };\r\n }\r\n\r\n componentDidMount() {\r\n this.props.fetchStationOffers({\r\n eventId: this.props.eventId,\r\n stationId: this.props.stationId\r\n });\r\n }\r\n\r\n renderOffers() {\r\n if (this.props.offerError) {\r\n return (\r\n \r\n \r\n \r\n )\r\n }\r\n\r\n if (!this.props.stationOffers) {\r\n return ;\r\n }\r\n\r\n if (this.props.stationOffers.length === 0) {\r\n return (\r\n
\r\n );\r\n }\r\n\r\n return (\r\n \r\n {this.props.stationOffers\r\n .filter(o => o.status === 'ACCEPTED')\r\n .map(o => )}\r\n \r\n );\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n \r\n \r\n {this.state.station.name} \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n {this.renderOffers()}\r\n \r\n
\r\n \r\n \r\n );\r\n }\r\n\r\n}\r\n\r\nexport default injectIntl(StationAttendance);\r\n","import { connect } from \"react-redux\";\r\nimport { withRouter } from \"react-router\";\r\nimport { fetchStationOffers } from \"../../../Offer/reducer\";\r\nimport StationAttendance from \"./StationAttendance\";\r\n\r\nconst mapStateToProps = (state, ownProps) => ({\r\n event: ownProps.event,\r\n stationOffers: state.offers.stationOffers,\r\n offerError: state.offers.stationOfferError,\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n fetchStationOffers: data => dispatch(fetchStationOffers(data)),\r\n});\r\n\r\nexport default withRouter(connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(StationAttendance));\r\n","import React, { Component, Fragment } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport styled from \"styled-components\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport { ContentWrapper, Container, H1, GeneralError } from \"../../../../components/index\";\r\nimport { NavLinkButton } from \"../../../../components/Links\";\r\nimport { status } from \"../reducer\";\r\nimport {\r\n Switch,\r\n Route\r\n} from \"react-router-dom\";\r\nimport EventEdit from \"../Edit\";\r\nimport StationsEdit from \"../Station\";\r\nimport { FormattedMessage } from \"react-intl\";\r\nimport messages from \"./messages\";\r\nimport StationOffers from \"../StationOffers\";\r\nimport SendOutsForm from \"../SendOuts/SendOutsForm\";\r\nimport SendOutsList from \"../SendOuts/SendOutsList\";\r\nimport SendOut from \"../SendOuts/SendOut\";\r\nimport AttendanceList from \"../Attendance\";\r\nimport StationAttendance from \"../Attendance/StationAttendance\";\r\n\r\nconst NavigationWrapper = styled.nav`\r\n margin-bottom: 90px;\r\n`;\r\n\r\nclass EventBase extends Component {\r\n componentDidMount() {\r\n this.props.fetchEvent({ id: this.props.match.params.id });\r\n }\r\n\r\n componentWillUnmount() {\r\n this.props.reset();\r\n }\r\n\r\n renderContent() {\r\n const isTeamleaderView = this.props.isTeamleaderView;\r\n\r\n if (this.props.status === status.FETCHING) {\r\n return (\r\n \r\n );\r\n }\r\n\r\n if (this.props.status === status.FAILED) {\r\n return ;\r\n }\r\n\r\n if (this.props.event) {\r\n const linkBase = isTeamleaderView ? \"/my-pages/teamleaders\" : \"/my-pages/events\";\r\n\r\n return (\r\n \r\n \r\n \r\n {this.props.event.name} \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n {this.props.isTeamleaderView\r\n ? null\r\n :\r\n \r\n }\r\n \r\n \r\n \r\n \r\n
\r\n \r\n }\r\n />\r\n }\r\n />\r\n {this.props.isTeamleaderView\r\n ? null\r\n : }\r\n />\r\n }\r\n }\r\n />\r\n }\r\n />\r\n }\r\n />\r\n }\r\n />\r\n }\r\n isTeamleaderView={isTeamleaderView}\r\n />\r\n \r\n \r\n );\r\n }\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n \r\n {this.renderContent()}\r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nEventBase.propTypes = {\r\n isTeamleaderView: PropTypes.bool.isRequired,\r\n}\r\n\r\nexport default EventBase;\r\n","import { connect } from \"react-redux\";\r\nimport { fetchEvent, submitEvent, reset } from \"../reducer\";\r\nimport EventBase from \"./EventBase\";\r\n\r\nconst mapStateToProps = (state) => {\r\n const obj = {\r\n event: state.event.event,\r\n error: state.event.error,\r\n status: state.event.status,\r\n isTeamleaderView: false,\r\n };\r\n\r\n return obj;\r\n};\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n fetchEvent: data => dispatch(fetchEvent(data)),\r\n submitEvent: data => dispatch(submitEvent(data)),\r\n reset: () => dispatch(reset({})),\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(EventBase);\r\n","import React from 'react';\r\nimport {\r\n Switch,\r\n Route\r\n} from 'react-router-dom';\r\nimport EventStart from './EventStart';\r\nimport EventNewBase from './NewBase';\r\nimport EventCopyBase from './CopyBase';\r\nimport EventBase from './Base';\r\nimport styled from 'styled-components';\r\nimport { colors } from '../../../constants/styling-constants';\r\n\r\nconst Wrapper = styled.div`\r\n flex: 1;\r\n background-color: ${colors.lightPink};\r\n`;\r\n\r\nconst EventRouter = ({ match }) => {\r\n localStorage.setItem('homePath', 'events');\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport default EventRouter;\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n progressBar: {\r\n registerGroup: {\r\n id: 'new-group.progressbar.register-group.placeholder',\r\n },\r\n registerVolunteers: {\r\n id: 'new-group.progressbar.register-volunteers.placeholder',\r\n },\r\n registerAvailability: {\r\n id: 'group.progressbar.register-availability.placeholder',\r\n },\r\n },\r\n title: {\r\n id: 'volunteer-start.title',\r\n },\r\n text: {\r\n id: 'volunteer-start.text',\r\n },\r\n newGroupLink: {\r\n id: 'volunteer-start.new-group-link',\r\n },\r\n answerRequestLink: {\r\n id: 'volunteer-start.answer-request-link',\r\n },\r\n updateVolunteersLink: {\r\n id: 'volunteer-start.update-volunteers-link',\r\n },\r\n myGroups: {\r\n title: {\r\n id: 'volunteer-start.my-groups.list.title',\r\n },\r\n button: {\r\n id: 'volunteer-start.my-groups.list.update-button',\r\n },\r\n },\r\n myEvents: {\r\n title: {\r\n id: 'volunteer-start.my-events.list.title',\r\n },\r\n button: {\r\n id: 'volunteer-start.my-events.list.update-button',\r\n },\r\n },\r\n statusApproved: {\r\n id: 'group.status-approved',\r\n },\r\n statusUnconfirmed: {\r\n id: 'group.status-unconfirmed',\r\n },\r\n statusHistoric: {\r\n id: 'group.status-historic'\r\n },\r\n statusUnknown: {\r\n id: 'group.status-unknown',\r\n },\r\n noGroupsMessage: {\r\n id: 'group.no-groups',\r\n }\r\n});\r\n","\r\n// actions\r\nexport const GROUP_SUBMIT = 'GROUP_SUBMIT';\r\nexport const GROUP_FETCHING = 'GROUP_FETCHING';\r\nexport const GROUP_FETCHED = 'GROUP_FETCHED';\r\nexport const GROUP_SUCCESS = 'GROUP_SUCCESS';\r\nexport const GROUP_FAILED = 'GROUP_FAILED';\r\nexport const GROUP_RESET = 'GROUP_RESET';\r\nexport const GROUPS_SUMMARIES = 'GROUPS_SUMMARIES';\r\nexport const GROUPS_SUMMARIES_SUCCESS = 'GROUPS_SUMMARIES_SUCCESS';\r\nexport const GROUPS_SUMMARIES_FAILED = 'GROUPS_SUMMARIES_FAILED';\r\nexport const FETCH_PUBLIC_EVENTS = 'FETCH_PUBLIC_EVENTS';\r\nexport const FETCH_PUBLIC_EVENTS_SUCCESS = 'FETCH_PUBLIC_EVENTS_SUCCESS';\r\nexport const FETCH_PUBLIC_EVENTS_FAILED = 'FETCH_PUBLIC_EVENTS_FAILED';\r\nexport const FETCH_COMPLETE_EVENT = 'FETCH_COMPLETE_EVENT';\r\nexport const FETCH_COMPLETE_EVENT_SUCCESS = 'FETCH_COMPLETE_EVENT_SUCCESS';\r\nexport const FETCH_COMPLETE_EVENT_FAILED = 'FETCH_COMPLETE_EVENT_FAILED';\r\nexport const GROUP_CONFIRM = 'GROUP_CONFIRM';\r\nexport const GROUP_CONFIRM_SUCCESS = 'GROUP_CONFIRM_SUCCESS';\r\nexport const GROUP_CONFIRM_FAILED = 'GROUP_CONFIRM_FAILED';\r\nexport const LINK = 'LINK';\r\nexport const LINK_SUCCESS = 'LINK_SUCCESS';\r\nexport const LINK_FAILED = 'LINK_FAILED';\r\n\r\n\r\nexport const status = {\r\n INIT: 'INIT',\r\n NOT_SUBMITTED: 'NOT_SUBMITTED',\r\n FETCHING: 'FETCHING',\r\n FETCHED: 'FETCHED',\r\n SUBMITTING: 'SUBMITTING',\r\n SUCCESS: 'SUCCESS',\r\n FAILED: 'FAILED',\r\n};\r\n\r\nexport const groupStatus = status;\r\n\r\nexport function submitGroup (data) {\r\n return {\r\n type: GROUP_SUBMIT,\r\n payload: data,\r\n };\r\n}\r\n\r\nexport function fetchGroup (data) {\r\n return {\r\n type: GROUP_FETCHING,\r\n payload: data,\r\n };\r\n}\r\n\r\nexport function confirmGroup (data) {\r\n return {\r\n type: GROUP_CONFIRM,\r\n payload: data,\r\n };\r\n}\r\n\r\nexport function reset () {\r\n return {\r\n type: GROUP_RESET\r\n };\r\n}\r\n\r\nexport function getGroupSummaries () {\r\n return {\r\n type: GROUPS_SUMMARIES,\r\n };\r\n}\r\n\r\nexport function fetchPublicEvents (data) {\r\n return {\r\n type: FETCH_PUBLIC_EVENTS,\r\n payload: data,\r\n };\r\n}\r\n\r\nexport function fetchCompleteEvent (data) {\r\n return {\r\n type: FETCH_COMPLETE_EVENT,\r\n payload: {\r\n id: data\r\n }\r\n }\r\n}\r\n\r\nexport function createLink( data ) {\r\n return {\r\n type: LINK,\r\n payload: {\r\n id: data\r\n }\r\n }\r\n}\r\n\r\n// reducer with initial state\r\nconst initialState = {\r\n status: status.NOT_SUBMITTED,\r\n statusGroupSummaries: status.INIT,\r\n group: null,\r\n error: null,\r\n groupsSummaries: [],\r\n publicEvents: [],\r\n publicEventError: null,\r\n completeEvents: [],\r\n completeEventError: null\r\n};\r\n\r\nexport default function group(state = initialState, action) {\r\n if (!action) {\r\n return state;\r\n }\r\n\r\n switch (action.type) {\r\n case GROUP_SUBMIT:\r\n return Object.assign({}, state, {status: status.SUBMITTING});\r\n case GROUP_CONFIRM:\r\n return Object.assign({}, state, {status: status.SUBMITTING});\r\n case GROUP_FETCHING:\r\n return Object.assign({}, state, {status: status.FETCHING});\r\n case GROUP_FETCHED:\r\n return Object.assign({}, state, {status: status.FETCHED, group: action.payload});\r\n case GROUP_SUCCESS:\r\n return Object.assign({}, state, {status: status.SUCCESS, group: action.payload});\r\n case GROUP_FAILED:\r\n return Object.assign({}, state, action.payload, {status: status.FAILED, error: action.payload});\r\n case GROUP_RESET:\r\n return Object.assign({}, initialState, {publicEvents: state.publicEvents});\r\n case GROUPS_SUMMARIES:\r\n return Object.assign({}, state, {statusGroupSummaries: status.FETCHING});\r\n case GROUPS_SUMMARIES_SUCCESS:\r\n return Object.assign({}, state, {groupsSummaries: action.payload, statusGroupSummaries: status.INIT});\r\n case GROUPS_SUMMARIES_FAILED:\r\n return Object.assign({}, state, {groupsSummaries: [], statusGroupSummaries: status.INIT});\r\n case FETCH_PUBLIC_EVENTS_SUCCESS:\r\n return Object.assign({}, state, {publicEvents: action.payload, publicEventError: null});\r\n case FETCH_PUBLIC_EVENTS_FAILED:\r\n return Object.assign({}, state, {publicEvents: [], publicEventError: action.error});\r\n case FETCH_COMPLETE_EVENT_SUCCESS:\r\n // Only add an event if it isn't stored already\r\n const existingEvent = state.completeEvents.find((e) => e.eventId === action.payload.eventId);\r\n\r\n if (existingEvent) {\r\n return state;\r\n }\r\n // Immutable copy of array of objects\r\n const completeEvents = state.completeEvents.map(e => {\r\n return Object.assign({}, e);\r\n });\r\n completeEvents.push(action.payload);\r\n return Object.assign({}, state, {completeEvents: completeEvents});\r\n case FETCH_COMPLETE_EVENT_FAILED:\r\n return Object.assign({}, state, {completeEvents: [], completeEventError: action.error});\r\n case GROUP_CONFIRM_SUCCESS:\r\n return Object.assign({}, state, {status: status.SUCCESS, group: action.payload});\r\n case LINK_SUCCESS:\r\n return Object.assign({}, state, {status: status.SUCCESS, link: action.payload});\r\n case LINK_FAILED:\r\n return Object.assign({}, state, {status: status.FAILED, link: action.payload});\r\n default:\r\n return state;\r\n }\r\n}\r\n","import React, { Component } from \"react\";\r\nimport { H2, TableRowWithClick, TableRow, TableStatus, WhiteTableWithLastToRight } from \"../../../../components/index\";\r\nimport { TableButton } from \"../../../../components/Buttons/index\";\r\nimport { breakPoints } from \"../../../../constants/styling-constants\";\r\nimport styled from \"styled-components\";\r\nimport { withRouter } from \"react-router\";\r\nimport messages from \"../messages\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport { status } from \"../reducer\";\r\n\r\nconst Wrapper = styled.div`\r\n margin-bottom: 85px;\r\n`;\r\n\r\nconst Table = styled(WhiteTableWithLastToRight)`\r\n @media (max-width: ${breakPoints.sm}px) {\r\n .table-button-col {\r\n display: none;\r\n }\r\n }\r\n`;\r\n\r\nclass MyGroupsList extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.renderRow = this.renderRow.bind(this);\r\n this.handleClick = this.handleClick.bind(this);\r\n }\r\n\r\n componentDidMount() {\r\n this.props.getGroupsSummaries();\r\n }\r\n\r\n handleClick(row) {\r\n this.props.history.push(`/my-pages/volunteers/${row.id}`);\r\n }\r\n\r\n renderStatus(status) {\r\n switch (status) {\r\n case \"CONFIRMED\":\r\n return ( );\r\n case \"DRAFT\":\r\n return ( );\r\n case \"HISTORIC\":\r\n return ( )\r\n default:\r\n return ( );\r\n }\r\n }\r\n\r\n renderRow(row) {\r\n return (\r\n \r\n {row.name} \r\n {row.organizationName} \r\n {this.renderStatus(row.status)} \r\n \r\n \r\n );\r\n }\r\n\r\n renderContent() {\r\n if (this.props.statusGroupSummaries === status.FETCHING) {\r\n return ;\r\n }\r\n\r\n return (\r\n \r\n \r\n {this.props.groupsSummaries.length > 0\r\n ? this.props.groupsSummaries.sort((a, b) => a && b && a.name && b.name ? a.name.localeCompare(b.name) : 0).map(this.renderRow)\r\n : \r\n \r\n \r\n }\r\n \r\n
\r\n )\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n \r\n {this.renderContent()}\r\n \r\n );\r\n }\r\n}\r\n\r\nexport default withRouter(injectIntl(MyGroupsList));\r\n","import { connect } from \"react-redux\";\r\nimport MyGroupsList from \"./MyGroupsList\";\r\nimport { withRouter } from \"react-router\";\r\nimport { getGroupSummaries } from \"../reducer\";\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n getGroupsSummaries: data => dispatch(getGroupSummaries(data)),\r\n});\r\n\r\nconst mapStateToProps = state => ({\r\n groupsSummaries: state.group.groupsSummaries,\r\n statusGroupSummaries: state.group.statusGroupSummaries\r\n});\r\n\r\nexport default withRouter(connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(MyGroupsList));\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n offers: {\r\n title: {\r\n id: 'volunteer-start.my-events.list.title',\r\n },\r\n button: {\r\n id: 'volunteer-start.my-events.handle-event-button',\r\n },\r\n rejectedButton: {\r\n id: 'volunteer-start.my-events.handle-event.rejected-button',\r\n },\r\n acceptedButton: {\r\n id: 'volunteer-start.my-events.handle-event.accepted-button',\r\n },\r\n pendingButton: {\r\n id: 'volunteer-start.my-events.handle-event.pending-proposal-button',\r\n },\r\n noOffersMessage: {\r\n id: 'volunteer-start.my-events.no-offers-message',\r\n },\r\n showPreviousEvents: {\r\n id: 'volunteer-start.my-events.show-previous-events'\r\n }\r\n },\r\n selfRegistration: {\r\n button:{\r\n id: 'volunteer-start.my-events.self-registration-button'\r\n },\r\n notification:{\r\n id: 'volunteer-start.my-events.self-registration-notification'\r\n },\r\n },\r\n});\r\n\r\n\r\n","import React, { Component } from \"react\";\r\nimport {\r\n H2,\r\n H4,\r\n BoldP,\r\n TableRowWithClick,\r\n WhiteTableWithLastToRight,\r\n TableRow,\r\n TextLabel,\r\n} from \"../../../components/index\";\r\nimport styled from \"styled-components\";\r\nimport messages from \"./messages\";\r\nimport { colors } from \"../../../constants/styling-constants\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport { breakPoints } from \"../../../constants/styling-constants\";\r\nimport { withRouter } from \"react-router-dom\";\r\nimport { TableButton, ToggleButton, SmallGreenButton } from \"../../../components/Buttons/index\";\r\nimport { ToastContainer, toast } from \"react-toastify\";\r\nimport \"react-toastify/dist/ReactToastify.css\";\r\nimport moment from \"moment\";\r\n\r\nconst StyledToast = styled(ToastContainer)`\r\n --toastify-color-success: ${colors.green};\r\n`\r\n\r\nconst Wrapper = styled.div`\r\n margin-bottom: 85px;\r\n`;\r\n\r\nconst EventWrapper = styled.div`\r\n margin-bottom: 40px;\r\n`;\r\n\r\nconst GroupWrapper = styled.div`\r\n margin-bottom: 20px;\r\n`;\r\nconst EventNameWrapper = styled.div`\r\n display: flex;\r\n flex-direction: row;\r\n justify-content: space-between;\r\n margin-right: 13px;\r\n`;\r\nconst GroupNameWrapper = styled.div`\r\n display: flex;\r\n flex-direction: row;\r\n justify-content: space-between;\r\n margin-right: 13px;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n`;\r\n\r\nconst Table = styled(WhiteTableWithLastToRight)`\r\n @media (max-width: ${breakPoints.sm}px) {\r\n .table-button-col {\r\n display: none;\r\n }\r\n }\r\n`;\r\n\r\nconst TableColumn = styled.td`\r\n word-wrap: break-word;\r\n width: 520px;\r\n max-width: 520px;\r\n @media (max-width: ${breakPoints.sm}px) {\r\n width: 100%;\r\n }\r\n`;\r\n\r\nconst RedButton = styled(TableButton)`\r\n background: ${colors.lightPink3};\r\n border: ${colors.darkPink};\r\n width: 134px;\r\n &:hover {\r\n background: ${colors.darkPink};\r\n }\r\n`;\r\n\r\nconst GreyButton = styled(TableButton)`\r\n background: ${colors.lightGray4};\r\n border: ${colors.mediumLightGray};\r\n width: 134px;\r\n &:hover {\r\n background: ${colors.mediumLightGray};\r\n }\r\n`;\r\n\r\nconst GreenButton = styled(TableButton)`\r\n background: ${colors.darkGreen};\r\n border: ${colors.darkGreen};\r\n color: ${colors.white};\r\n width: 134px;\r\n\r\n &:hover {\r\n background: ${colors.greenEndGradient};\r\n }\r\n`;\r\n\r\nconst DarkGreyButton = styled(TableButton)`\r\n width: 134px;\r\n`;\r\n\r\nconst CopyButton = styled(SmallGreenButton)`\r\n width: 200px;\r\n height: 35px;\r\n margin: 0px;\r\n padding: 5px 10px;\r\n`;\r\n\r\nclass GroupOffers extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n groupOffers: this.filterOffersOnStatus(this.props.groupOffers),\r\n past: false,\r\n copy: true,\r\n selfRegistrationLink: null,\r\n selfRegistrationGroupName: null,\r\n selfRegistrationEventId: null,\r\n };\r\n\r\n this.renderRow = this.renderRow.bind(this);\r\n this.handleClick = this.handleClick.bind(this);\r\n this.togglePast = this.togglePast.bind(this);\r\n this.handleCopy = this.handleCopy.bind(this);\r\n this.handleCreateLink = this.handleCreateLink.bind(this);\r\n }\r\n\r\n componentDidMount() {\r\n this.props.fetchGroupsOffers();\r\n }\r\n\r\n componentWillReceiveProps(nextProps) {\r\n this.setState({\r\n groupOffers: this.filterOffersOnStatus(nextProps.groupOffers),\r\n selfRegistrationLink: nextProps.selfRegistrationLink,\r\n }, () => this.state.selfRegistrationLink ? this.handleCopy() : \"\");\r\n }\r\n\r\n filterOffersOnStatus(offers) {\r\n return offers ? offers.filter((o) => o.status !== \"DRAFT\") : null;\r\n }\r\n\r\n handleClick(row) {\r\n this.props.history.push(\r\n `/my-pages/volunteers/engagement/${row.eventId}/${row.groupId}/${row.stationId}`\r\n );\r\n }\r\n\r\n handleCopy() {\r\n if(!this.state.copy){\r\n toast.success(this.props.intl.formatMessage(messages.selfRegistration.notification), {theme: \"colored\", toastId: \"id\"})\r\n navigator.clipboard.writeText(window.location.origin +\r\n \"/self-registration/\" +\r\n this.state.selfRegistrationGroupName.replaceAll(' ', '%20') + \r\n \"/\" + this.state.selfRegistrationEventId + \r\n \"/\" + this.state.selfRegistrationLink.link);\r\n this.setState({copy: true});\r\n }\r\n }\r\n\r\n handleCreateLink(groupOffers) {\r\n this.setState({copy: false, selfRegistrationLink: null, selfRegistrationGroupName: groupOffers[0].groupName, selfRegistrationEventId: groupOffers[0].eventId});\r\n this.props.createLink({ groupId: groupOffers[0].groupId, eventId: groupOffers[0].eventId });\r\n }\r\n\r\n togglePast() {\r\n this.setState({past: !this.state.past})\r\n }\r\n\r\n\r\n renderStatus(status) {\r\n return status;\r\n }\r\n\r\n sortingFunction(offerA, offerB) {\r\n const statusOrder = [\"PROPOSAL\", \"ACCEPTED\", \"REJECTED\"];\r\n if (offerA.status !== offerB.status)\r\n return statusOrder.indexOf(offerA.status) >\r\n statusOrder.indexOf(offerB.status)\r\n ? 1\r\n : -1;\r\n if (\r\n offerA.status === \"ACCEPTED\" &&\r\n moment(offerA.station.start).isAfter(new Date())\r\n )\r\n return moment(offerA.station.start).isAfter(moment(offerB.station.start)) ? -1 : 1;\r\n return moment(offerA.station.start).isAfter(moment(offerB.station.start)) ? 1 : -1;\r\n }\r\n\r\n\r\n\r\n renderProposalButton(status, startDate) {\r\n switch (status) {\r\n case \"ACCEPTED\":\r\n if (moment(startDate).isAfter(new Date())) {\r\n return (\r\n \r\n );\r\n } else {\r\n return (\r\n \r\n );\r\n }\r\n case \"REJECTED\":\r\n return (\r\n \r\n );\r\n case \"PROPOSAL\":\r\n return (\r\n \r\n );\r\n default:\r\n return (\r\n \r\n );\r\n }\r\n }\r\n\r\n renderRow(row) {\r\n return (\r\n \r\n {row.station.name} \r\n \r\n {this.renderProposalButton(\r\n row.status,\r\n row.station ? moment(row.station.start).format(\"YYYY-MM-DD\") : null\r\n )}\r\n \r\n \r\n );\r\n }\r\n\r\n renderLoader() {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n );\r\n }\r\n\r\n renderNoOffers() {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n );\r\n }\r\n\r\n renderEventList(offerList, past=false) {\r\n \r\n const sortedEvents = offerList.sort((e0, e1) => e0.eventId.localeCompare(e1.eventId));\r\n const eventList = past ? sortedEvents.filter((offer, index, array) => !index || offer.eventId !== array[index - 1].eventId)\r\n .sort((a,b) => moment(a.station.start).isAfter(moment(b.station.start)) ? -1 : 1) : sortedEvents.filter((offer, index, array) => !index || offer.eventId !== array[index - 1].eventId)\r\n .sort((a,b) => moment(a.station.start).isAfter(moment(b.station.start)) ? 1 : -1);\r\n return (\r\n \r\n {eventList.map(e => this.renderEvent(e, sortedEvents.filter(offer => offer.eventId === e.eventId), past))}\r\n \r\n )\r\n\r\n }\r\n\r\n renderOffers() {\r\n if (!this.state.groupOffers) {\r\n return ;\r\n }\r\n if (this.state.groupOffers.length < 1) {\r\n return (\r\n \r\n \r\n \r\n )\r\n }\r\n else{\r\n const futureList = this.state.groupOffers && this.state.groupOffers[0].station ? this.state.groupOffers.filter(offer => offer.station.start.localeCompare(new Date().toISOString()) >= 0 && offer.status !== \"REJECTED\") : [];\r\n const pastList = this.state.groupOffers && this.state.groupOffers[0].station ? this.state.groupOffers.filter(offer => (offer.station.start.localeCompare(new Date().toISOString()) < 0 || offer.status === \"REJECTED\") && offer.status !== \"PROPOSAL\") : [];\r\n return(\r\n \r\n {this.renderEventList(futureList)}\r\n \r\n {this.state.past ? this.renderEventList(pastList, true) : \"\"}\r\n \r\n )\r\n }\r\n }\r\n\r\n renderEvent(event, offers, past) {\r\n const sortedGroups = offers.sort((g0, g1) => g0.groupId.localeCompare(g1.groupId));\r\n const groupList = sortedGroups.filter((offer, index, array) => !index || offer.groupId !== array[index - 1].groupId).map(g => g.groupName);\r\n return (\r\n \r\n \r\n \r\n {event.eventName}\r\n \r\n \r\n {event.station ? moment(event.station.start).format(\"YYYY-MM-DD\") : null}\r\n \r\n \r\n {groupList.map(groupName => this.renderGroupOffers(groupName, sortedGroups.filter(offer => offer.groupName === groupName), past))}\r\n \r\n )\r\n } \r\n \r\n renderGroupOffers(groupName, groupOffers, past) {\r\n const sortedOffers = groupOffers.sort(this.sortingFunction);\r\n const accepted = sortedOffers.reduce((prev, curr) => prev || curr.status === \"ACCEPTED\" , false);\r\n return (\r\n \r\n \r\n \r\n {groupName}\r\n \r\n {past === false && accepted ? \r\n this.handleCreateLink(groupOffers)}/> : \"\"}\r\n \r\n \r\n \r\n {sortedOffers.map(this.renderRow)}\r\n \r\n
\r\n \r\n );\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n \r\n \r\n \r\n {this.renderOffers()}\r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nexport default withRouter(injectIntl(GroupOffers));\r\n","import { connect } from \"react-redux\";\r\nimport { withRouter } from \"react-router\";\r\nimport { default as GroupOffersComponent } from \"./GroupOffers\";\r\nimport { fetchGroupsOffers, createLink } from \"./reducer\";\r\n\r\nconst mapStateToProps = (state) => ({\r\n groupOffers: state.offers.groupOffers,\r\n selfRegistrationLink: state.offers.link\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n fetchGroupsOffers: data => dispatch(fetchGroupsOffers(data)),\r\n createLink: data => dispatch(createLink(data)),\r\n});\r\n\r\nexport const GroupOffers = withRouter(connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(GroupOffersComponent));\r\n\r\n","import React, { Component } from \"react\";\r\nimport { ContentWrapper, Container, H1, P } from \"../../../components\";\r\nimport { CircleLinkButton } from \"../../../components/Links\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport styled from \"styled-components\";\r\nimport { breakPoints } from \"../../../constants/styling-constants\";\r\nimport MyGroupsList from \"./MyGroupsList\";\r\nimport TopNavigation from \"../TopNavigation\";\r\nimport messages from \"./messages\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport { GroupOffers } from \"../Offer\";\r\n\r\nconst IconWrapper = styled(Col)`\r\n display: flex;\r\n @media (max-width: ${breakPoints.xs}px) {\r\n flex-direction: column;\r\n align-items: center;\r\n a {\r\n margin-bottom: 25px;\r\n }\r\n }\r\n`;\r\n\r\nclass VolunteerContextStart extends Component {\r\n render() {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nexport default injectIntl(VolunteerContextStart);\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n title: {\r\n id: 'register-group.title',\r\n },\r\n form: {\r\n groupInfo: {\r\n title: {\r\n id: 'register-group.group-info.form.title',\r\n },\r\n name: {\r\n id: 'register-group.form.group-info.name.placeholder',\r\n },\r\n orgNumber: {\r\n id: 'register-group.form.group-info.org-number.placeholder',\r\n },\r\n orgName: {\r\n id: 'register-group.form.group-info.org-name.placeholder',\r\n },\r\n municipality: {\r\n id: 'register-group.form.group-info.municipality.placeholder',\r\n },\r\n },\r\n contact: {\r\n title: {\r\n id: 'register-group.contact.form.title',\r\n },\r\n\r\n },\r\n members: {\r\n title: {\r\n id: 'register-group.members.form.title',\r\n },\r\n numberOfMembers: {\r\n id: 'register-group.form.members.number-of-members.placeholder',\r\n },\r\n },\r\n ages: {\r\n title: {\r\n id: 'register-group.ages.form.title',\r\n },\r\n ages: {\r\n id: 'register-group.form.ages.ages.placeholder',\r\n },\r\n },\r\n alignment: {\r\n sport: {\r\n id: 'register-group.form.alignment.sport.placeholder',\r\n },\r\n skills: {\r\n id: 'register-group.form.alignment.skills.placeholder',\r\n },\r\n },\r\n payment: {\r\n title: {\r\n id: 'register-group.payment.form.title',\r\n },\r\n bank: {\r\n id: 'register-group.form.payment.bank.placeholder',\r\n },\r\n accountNumber: {\r\n id: 'register-group.form.payment.account-number.placeholder',\r\n },\r\n },\r\n },\r\n editGroup: {\r\n form: {\r\n contact: {\r\n id: 'edit-group.form.contact.placeholder',\r\n },\r\n contactExistMessage: {\r\n id: 'edit-group.form.contact-exist-message',\r\n },\r\n contactEmptyMessage: {\r\n id: 'edit-group.form.contact-empty-message',\r\n },\r\n userNotFound: {\r\n id: 'edit-group.form.contact-user-not-found',\r\n },\r\n addContactButton: {\r\n id: 'edit-group.form.add-contact-button',\r\n },\r\n },\r\n contactList: {\r\n name: {\r\n id: 'edit-group.contacts.name.placeholder',\r\n },\r\n email: {\r\n id: 'edit-group.contacts.email.placeholder',\r\n },\r\n phone: {\r\n id: 'edit-group.contacts.phone.placeholder',\r\n },\r\n },\r\n },\r\n volunteers: {\r\n title: {\r\n id: 'edit-group.volunteers.form.title',\r\n },\r\n form: {\r\n name: {\r\n id: 'edit-group.volunteers.name.placeholder',\r\n },\r\n email: {\r\n id: 'edit-group.volunteers.email.placeholder',\r\n },\r\n phone: {\r\n id: 'edit-group.volunteers.phone.placeholder',\r\n },\r\n age: {\r\n id: 'edit-group.volunteers.age.placeholder',\r\n },\r\n addButton: {\r\n id: 'edit-group.volunteers.add-button',\r\n },\r\n },\r\n },\r\n saveGroupButton: {\r\n id: 'save-group-button',\r\n },\r\n nextButton: {\r\n id: 'next-step-button',\r\n },\r\n editGroupButton: {\r\n id: 'edit-group-button',\r\n },\r\n deleteContactText: {\r\n id: 'group.delete-contact.text',\r\n },\r\n});\r\n","// TODO fix this file!!!\r\n// this file is bad, we should move form declaration to parent component and make this to a form section https://redux-form.com/6.5.0/docs/api/formsection.md/\r\n\r\n\r\nimport React from 'react';\r\nimport sports from '../../../../sports.json';\r\nimport { Field, reduxForm } from 'redux-form';\r\nimport { Row, Col } from 'react-bootstrap/lib';\r\nimport {\r\n P,\r\n FormSectionTitle,\r\n Input,\r\n Select,\r\n ListSelect,\r\n FormGroup,\r\n GeneralError,\r\n MultiSelect,\r\n ContactForm,\r\n} from '../../../../components/index';\r\nimport { BigGreenButton } from '../../../../components/Buttons/index';\r\nimport { required, minLength3, positiveNumbers, integer } from '../../../../validators/index';\r\nimport { groupStatus } from '../reducer';\r\nimport messages from './messages';\r\nimport { FormattedMessage, injectIntl } from 'react-intl';\r\nimport { municipalities } from '../../../../constants/municipalities';\r\nimport {lists} from '../../../../constants/lists.js'; // TODO: Add updated volex-data repository\r\nconst {skills} = lists;\r\n\r\nconst withLoadedProps = (LoadedComponent, loadedProps) => props => ;\r\n\r\nconst ages = [\r\n {id: '10', value: '10'},\r\n {id: '11', value: '11'},\r\n {id: '12', value: '12'},\r\n {id: '13', value: '13'},\r\n {id: '14', value: '14'},\r\n {id: '15', value: '15'},\r\n {id: '16', value: '16'},\r\n {id: '17', value: '17'},\r\n {id: '18+', value: '18+'},\r\n];\r\n\r\n// Sort on name but keep 'Ingen' (id 0) on top\r\nconst sortSportOnName = (a,b) => {\r\n if (a.id !== '0' && b.id !== '0' && a.name < b.name) {\r\n return -1;\r\n }\r\n if (a.id !== '0' && b.id !== '0' && a.name > b.name) {\r\n return 1;\r\n }\r\n return 0;\r\n};\r\n\r\nconst sortedSports = sports.sort(sortSportOnName);\r\n\r\n\r\nclass GroupForm extends React.Component {\r\n constructor (props) {\r\n super(props);\r\n\r\n this.state = {\r\n readonly: !this.isNew(),\r\n contactList: this.isNew() ? this.getInitialContactList() : this.props.group && Array.isArray(this.props.group.contactPersons) ? this.props.group.contactPersons : [],\r\n showDeleteContactModal: false,\r\n deletingContactPerson: false,\r\n contactToDelete: null,\r\n newContactEmail: null,\r\n contactError: null,\r\n emailInvalid: null,\r\n submitClicked: false,\r\n nextClicked: false,\r\n };\r\n\r\n this.toggleReadonly = this.toggleReadonly.bind(this);\r\n this.renderSkills = this.renderSkills.bind(this);\r\n this.renderMunicipality = this.renderMunicipality.bind(this);\r\n this.handleContactSubmit = this.handleContactSubmit.bind(this);\r\n this.handleSubmit = this.handleSubmit.bind(this);\r\n this.handleClickNext = this.handleClickNext.bind(this);\r\n this.saveGroup = this.saveGroup.bind(this);\r\n this.updateContactListFromForm = this.updateContactListFromForm.bind(this);\r\n }\r\n\r\n componentWillReceiveProps (nextProps) {\r\n if (this.isNew() && nextProps.user && !this.props.user) {\r\n this.setState({\r\n contactList: [{email: nextProps.user.email, name: `${nextProps.user.firstName } ${ nextProps.user.lastName}`, phone: nextProps.user.phone}]\r\n })\r\n }\r\n if (nextProps.status === groupStatus.SUCCESS && this.props.status !== groupStatus.SUCCESS) {\r\n this.setState({\r\n submitClicked: false,\r\n });\r\n }\r\n }\r\n\r\n getInitialContactList () {\r\n if (this.props.user) {\r\n const user = this.props.user;\r\n return [{email: user.email, name: `${user.firstName } ${ user.lastName}`, phone: user.phone}];\r\n }\r\n return [];\r\n }\r\n\r\n updateContactListFromForm (contactList) {\r\n this.setState({contactList});\r\n }\r\n\r\n validateContact (contactList) {\r\n const listContainsSubmittedEmail = contactList.find(contact => contact.email === this.state.newContactEmail && !contact.toBeDeleted);\r\n\r\n if (!this.state.newContactEmail) {\r\n this.setState({\r\n contactError: ,\r\n });\r\n } else if (listContainsSubmittedEmail) {\r\n this.setState({\r\n contactError: ,\r\n });\r\n } else if (!this.state.emailInvalid) {\r\n this.props.getUserByEmail({email: this.state.newContactEmail});\r\n }\r\n }\r\n\r\n handleContactSubmit() {\r\n this.validateContact(this.state.contactList);\r\n }\r\n\r\n renderSkills () {\r\n const skillOptions = skills.map(skill => ({id: skill, name: this.props.intl.formatMessage({id: `lists.skills.${skill}`})}));\r\n return (\r\n \r\n );\r\n }\r\n\r\n renderMunicipality () {\r\n return (\r\n \r\n );\r\n }\r\n\r\n isNew () {\r\n return !this.props.match.params.id;\r\n }\r\n\r\n toggleReadonly (e) {\r\n e && e.preventDefault();\r\n\r\n this.setState({\r\n readonly: !this.state.readonly,\r\n });\r\n }\r\n\r\n renderButtons () {\r\n const buttons = [];\r\n if (!this.isNew() && this.state.readonly) {\r\n buttons.push( );\r\n }\r\n else if (!this.isNew()) {\r\n buttons.push( );\r\n } \r\n if (this.props.onClickNext) {\r\n buttons.push( );\r\n }\r\n\r\n return buttons;\r\n }\r\n\r\n saveGroup (fieldValues) {\r\n const newGroup = Object.assign({}, fieldValues, {contactPersons: this.state.contactList.filter(c => !c.toBeDeleted)});\r\n newGroup.numberOfMembers = parseInt(newGroup.numberOfMembers, 10);\r\n\r\n if (this.props.group) {\r\n newGroup.id = this.props.group.id;\r\n }\r\n\r\n this.props.submitGroup(newGroup);\r\n }\r\n\r\n handleClickNext (fieldValues) {\r\n this.setState({\r\n nextClicked: true,\r\n });\r\n\r\n this.saveGroup(fieldValues);\r\n this.props.onClickNext(1);\r\n }\r\n\r\n handleSubmit(fieldValues) {\r\n if (this.state.submitClicked) {\r\n return;\r\n }\r\n\r\n this.setState({\r\n submitClicked: true,\r\n });\r\n\r\n this.saveGroup(fieldValues);\r\n if (!this.props.onClickNext) {\r\n this.toggleReadonly();\r\n }\r\n }\r\n\r\n render () {\r\n if ((!this.isNew() && (this.props.status === groupStatus.NOT_SUBMITTED || this.props.status === groupStatus.FETCHING)) || !this.props.user) {\r\n return (Show spinner...
);\r\n }\r\n\r\n return ();\r\n }\r\n}\r\n\r\nconst formName = 'groupForm';\r\nconst GroupFormForm = reduxForm({\r\n form: formName,\r\n})(GroupForm);\r\n\r\nexport default injectIntl(GroupFormForm);\r\n","import { connect } from \"react-redux\";\r\nimport { submitGroup, reset } from \"../reducer\";\r\nimport GroupForm from \"./GroupForm\";\r\nimport { resetUser } from \"../../../User/reducer\";\r\n\r\nconst mapStateToProps = state => ({\r\n group: state.group.group,\r\n status: state.group.status,\r\n user: state.auth.user,\r\n initialValues: state.group.group,\r\n userEmail: state.user,\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n submitGroup: data => dispatch(submitGroup(data)),\r\n resetGroup: () => dispatch(reset()),\r\n resetUser: () => dispatch(resetUser()),\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(GroupForm);\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n confirmTitle: {\r\n id: 'confirm-group.title',\r\n },\r\n confirmText2: {\r\n id: 'new-group.confirmation.text-2',\r\n },\r\n group: {\r\n numberOfMembers: {\r\n id: 'confirm-group.number-of-members.placeholder',\r\n },\r\n },\r\n confirmationModalTitle: {\r\n id: 'confirm-group.confirmation-modal.title',\r\n },\r\n confirmationModalText: {\r\n id: 'confirm-group.confirmation-modal.text',\r\n },\r\n cancelConfirmButton: {\r\n id: 'confirm-group.cancel-confirm-button',\r\n },\r\n confirmModalButton: {\r\n id: 'confirm-group.confirm-button',\r\n },\r\n confirmButton: {\r\n id: 'confirm-group-button',\r\n },\r\n nextButton: {\r\n id: 'confirm-next-button',\r\n },\r\n});\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n title: {\r\n id: 'register-volunteers.title',\r\n },\r\n text: {\r\n id: 'register-volunteers.text',\r\n },\r\n volunteers: {\r\n personalInfoTitle: {\r\n id: 'register-group.volunteers.form.personal-info-title',\r\n },\r\n otherInfoTitle: {\r\n id: 'register-group.volunteers.form.other-info-title',\r\n },\r\n form: {\r\n goBack: {\r\n id: 'group.volunteer.form.goBack'\r\n },\r\n name: {\r\n id: 'group.volunteer.form.name.placeholder',\r\n },\r\n email: {\r\n id: 'group.volunteer.form.email.placeholder',\r\n },\r\n phone: {\r\n id: 'group.volunteer.form.phone.placeholder',\r\n },\r\n age: {\r\n id: 'group.volunteer.form.age.placeholder',\r\n },\r\n substitute:{\r\n id: 'group.volunteer.form.substitute.placeholder',\r\n },\r\n substituteTitle: {\r\n id: 'group.volunteer.form.substitute.title',\r\n },\r\n substituteOption: {\r\n id: 'group.volunteer.form.substitute.option',\r\n },\r\n foodOptionsTitle: {\r\n id: 'group.volunteer.form.food-options-title',\r\n },\r\n shirtSizesTitle: {\r\n id: 'group.volunteer.form.shirt-sizes-title',\r\n },\r\n specialDiets: {\r\n lactoseFree: {\r\n id: 'group.volunteer.form.special-diets.lactose-free.placeholder',\r\n },\r\n glutenFree: {\r\n id: 'group.volunteer.form.special-diets.gluten-free.placeholder',\r\n },\r\n vegetarian: {\r\n id: 'group.volunteer.form.special-diets.vegetarian.placeholder',\r\n },\r\n vegan: {\r\n id: 'group.volunteer.form.special-diets.vegan.placeholder',\r\n },\r\n },\r\n shirtSize: {\r\n id: 'group.volunteer.form.shirt-size.placeholder',\r\n },\r\n addButton: {\r\n id: 'group.volunteer.form.add-button',\r\n },\r\n emailAlreadyExistError: {\r\n id: 'group.volunteer.form.email-already-exist.error',\r\n },\r\n },\r\n list: {\r\n name: {\r\n id: 'group.volunteer.list.name.placeholder',\r\n },\r\n email: {\r\n id: 'group.volunteer.list.email.placeholder',\r\n },\r\n phone: {\r\n id: 'group.volunteer.list.phone.placeholder',\r\n },\r\n age: {\r\n id: 'group.volunteer.list.age.placeholder',\r\n },\r\n specialDiets: {\r\n id: 'group.volunteer.list.special-diets.title',\r\n },\r\n shirtSize: {\r\n id: 'group.volunteer.list.shirt-size.placeholder',\r\n },\r\n },\r\n cancelDeleteButton: {\r\n id: 'group.volunteer.list.cancel-delete-volunteer-button',\r\n },\r\n deleteVolunteerTitle: {\r\n id: 'group.volunteer.list.delete-volunteer-title',\r\n },\r\n deleteVolunteerMessage: {\r\n id: 'group.volunteer.list.delete-volunteer-text',\r\n },\r\n noVolunteersMessage: {\r\n id: 'register-group.volunteers.no-volunteers-yet-message',\r\n },\r\n nextButton: {\r\n id: 'edit-group.volunteers.next-button',\r\n },\r\n },\r\n});\r\n","import React, { Component, Fragment } from \"react\";\r\nimport { injectIntl, FormattedMessage } from \"react-intl\";\r\nimport { Field, reset, reduxForm } from \"redux-form\";\r\nimport { required, email, integer } from \"../../../../validators/index\";\r\nimport { groupStatus } from \"../reducer\";\r\nimport messages from \"./messages\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport { positiveNumbers } from \"../../../../validators/index\";\r\nimport {\r\n Input,\r\n FormSectionTitle,\r\n FormGroup,\r\n GeneralError,\r\n ListSelect,\r\n Select,\r\n H4,\r\n Checkbox,\r\n} from \"../../../../components\";\r\nimport {\r\n BigGreenButton,\r\n BigGrayButton,\r\n} from \"../../../../components/Buttons/index\";\r\nimport { v4 as uuidv4 } from \"uuid\";\r\nimport { lists } from \"../../../../constants/lists.js\"; // TODO: Add updated volex-data repository\r\n\r\nconst { foodOptions, shirtSizes } = lists;\r\n\r\nfunction validateEmailComparison(newVolunteer, volunteers, volunteerToEdit) {\r\n const errors = {};\r\n if (\r\n !newVolunteer.email ||\r\n (volunteers.find((v) => v.email === newVolunteer.email) &&\r\n (!volunteerToEdit ||\r\n (volunteerToEdit && volunteerToEdit.email !== newVolunteer.email)))\r\n ) {\r\n errors.email = (\r\n \r\n \r\n \r\n );\r\n }\r\n return Object.keys(errors).length > 0 ? errors : null;\r\n}\r\n\r\nconst withLoadedProps = (LoadedComponent, loadedProps) => (props) =>\r\n ;\r\n\r\nclass VolunteerForm extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n readonly: false, // !this.isNew(),\r\n newVolunteerErrors: null,\r\n submitting: false,\r\n emailInvalid: null,\r\n buttonDisabled: false,\r\n substituteCheckbox: false,\r\n };\r\n\r\n this.handleVolunteerSubmit = this.handleVolunteerSubmit.bind(this);\r\n this.onContactFieldChange = this.onContactFieldChange.bind(this);\r\n this.fillFormWithVolunteer = this.fillFormWithVolunteer.bind(this);\r\n }\r\n\r\n componentDidMount() {\r\n if (\r\n this.props.location &&\r\n this.props.location.pathname === \"/my-pages/volunteers/new\"\r\n ) {\r\n window.scrollTo(0, 0);\r\n }\r\n\r\n if(this.props.volunteerToEdit){\r\n this.fillFormWithVolunteer(this.props.volunteerToEdit);\r\n }\r\n }\r\n\r\n componentWillReceiveProps(nextProps) {\r\n if (\r\n nextProps.volunteerToEdit !== this.props.volunteerToEdit &&\r\n nextProps.volunteerToEdit !== null &&\r\n !this.state.submitting\r\n ) {\r\n this.fillFormWithVolunteer(nextProps.volunteerToEdit);\r\n }\r\n if (nextProps.status === groupStatus.SUCCESS && this.state.submitting) {\r\n this.setState({\r\n submitting: false,\r\n });\r\n this.props.reset();\r\n }\r\n }\r\n\r\n isNew() {\r\n return !this.props.match.params.id;\r\n }\r\n\r\n handleVolunteerSubmit(fieldValues) {\r\n this.setState({ buttonDisabled: true });\r\n setTimeout(() => this.setState({ buttonDisabled: false }), 500);\r\n const specialDiets = fieldValues.specialDiets ? (fieldValues.specialDiets || []).filter((v) => !!v) : null;\r\n const participant = []\r\n const participate = {}\r\n participate.eventId = this.props.offer ? this.props.offer.eventId : null;\r\n\r\n if(fieldValues.shirtSize || fieldValues.specialDiets || fieldValues.substitute){\r\n const shirtSize = (fieldValues.shirtSize || []);\r\n\r\n if(!fieldValues.shirtSize){\r\n participate.specialDiets = specialDiets\r\n }\r\n else if(!fieldValues.specialDiets){\r\n participate.shirtSize = shirtSize\r\n }\r\n else{\r\n participate.specialDiets = specialDiets\r\n participate.shirtSize = shirtSize\r\n }\r\n\r\n if(fieldValues.substitute && this.state.substituteCheckbox){\r\n participate.substitute = fieldValues.substitute\r\n }\r\n\r\n participant.push(participate)\r\n }\r\n\r\n const newVolunteer = Object.assign({}, fieldValues);\r\n const volunteersList = this.props.group.volunteers\r\n ? this.props.group.volunteers.slice()\r\n : [];\r\n const errors = validateEmailComparison(\r\n newVolunteer,\r\n volunteersList,\r\n this.props.volunteerToEdit\r\n );\r\n if (!errors && !this.state.emailInvalid) {\r\n this.setState({\r\n newVolunteerErrors: null,\r\n submitting: false,\r\n });\r\n\r\n if (this.props.volunteerToEdit) {\r\n if(this.props.volunteerToEdit.participation){\r\n newVolunteer.participation = this.props.volunteerToEdit.participation;\r\n }\r\n\r\n if(newVolunteer.participation && this.props.offer){\r\n const index = newVolunteer.participation.findIndex((event) => event.eventId === this.props.offer.eventId)\r\n index === -1 ? newVolunteer.participation.push(participate) : newVolunteer.participation[index] = participate\r\n }\r\n else{newVolunteer.participation = participant}\r\n\r\n const updatedVolunteerList = volunteersList.map((v) =>\r\n v.id === this.props.volunteerToEdit.id\r\n ? (v = Object.assign({}, newVolunteer, {\r\n id: this.props.volunteerToEdit.id,\r\n }))\r\n : v\r\n );\r\n if(updatedVolunteerList)\r\n this.props.saveGroup(updatedVolunteerList);\r\n } else {\r\n newVolunteer.id = uuidv4();\r\n\r\n if(participant.length > 0 && participate.eventId !== null){\r\n newVolunteer.participation = participant\r\n }\r\n volunteersList.push(newVolunteer);\r\n this.props.saveGroup(volunteersList);\r\n if (typeof this.props.goBackToList === \"function\") {\r\n this.props.goBackToList();\r\n }\r\n }\r\n } else {\r\n this.setState({\r\n newVolunteerErrors: errors,\r\n });\r\n }\r\n }\r\n\r\n onContactFieldChange(e) {\r\n const newVolunteer = { email: e.target.value };\r\n const volunteersList = this.props.group.volunteers\r\n ? this.props.group.volunteers.slice()\r\n : [];\r\n const volunteerToEdit = this.props.volunteerToEdit;\r\n const error = validateEmailComparison(\r\n newVolunteer,\r\n volunteersList,\r\n volunteerToEdit\r\n );\r\n\r\n this.setState({\r\n emailInvalid: e.target.validity.typeMismatch,\r\n newVolunteerErrors: error,\r\n });\r\n }\r\n\r\n fillFormWithVolunteer(volunteer) {\r\n this.props.change(\"name\", volunteer.name);\r\n this.props.change(\"email\", volunteer.email);\r\n this.props.change(\"phone\", volunteer.phone);\r\n this.props.change(\"age\", volunteer.age);\r\n\r\n if(this.props.offer){\r\n const found = volunteer.participation ? volunteer.participation.find((participations) => participations.eventId === this.props.offer.eventId) : undefined;\r\n if(found !== undefined && found.specialDiets){\r\n this.props.change(\"specialDiets\", found.specialDiets);\r\n }\r\n if(found !== undefined && found.shirtSize){\r\n this.props.change(\"shirtSize\", found.shirtSize);\r\n }\r\n if(found !== undefined && found.substitute){\r\n this.setState({substituteCheckbox: true})\r\n this.props.change(\"substitute\", found.substitute)\r\n \r\n }\r\n }\r\n }\r\n\r\n renderVolunteerFormGroup() {\r\n if (this.state.readonly) {\r\n return this.renderVolunteers();\r\n }\r\n\r\n const includedSpecialDietsTranslated = this.props.offer && this.props.offer.foodOptions\r\n ? this.props.offer.foodOptions.map((opt) => ({\r\n id: opt,\r\n label: this.props.intl.formatMessage({\r\n id: `food.${opt.toLowerCase()}`,\r\n }),\r\n }))\r\n : null;\r\n const includedShirtSizesTranslated = this.props.offer && this.props.offer.shirtSizes\r\n ? this.props.offer.shirtSizes.map((opt) => ({\r\n id: opt,\r\n label: this.props.intl.formatMessage({\r\n id: `shirt-size.${opt.toLowerCase()}`,\r\n }),\r\n }))\r\n : null;\r\n\r\n const styleRow =\r\n typeof this.props.goBackToList === \"function\"\r\n ? { display: \"flex\", justifyContent: \"center\" }\r\n : {};\r\n\r\n const errors = this.state.newVolunteerErrors || {};\r\n\r\n return (\r\n \r\n );\r\n }\r\n\r\n render() {\r\n return {this.renderVolunteerFormGroup()} ;\r\n }\r\n}\r\n\r\nconst afterSubmit = (result, dispatch) => dispatch(reset(\"volunteer\"));\r\n\r\nexport default reduxForm({\r\n form: \"volunteer\",\r\n onSubmitSuccess: afterSubmit,\r\n})(injectIntl(VolunteerForm));\r\n","import React, { Component, Fragment } from \"react\";\r\nimport { injectIntl, FormattedMessage } from \"react-intl\";\r\nimport messages from \"./messages\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport { DeleteButton } from \"../../../../components/Buttons/index\";\r\nimport { groupStatus } from \"../reducer\";\r\nimport styled from \"styled-components\";\r\nimport { BorderTable, ConfirmationModal } from \"../../../../components/index\";\r\n\r\nconst Wrapper = styled.div`\r\n margin-bottom: 80px;\r\n`;\r\n\r\nconst Table = styled(BorderTable)`\r\n display: inline-block;\r\n float: left;\r\n`;\r\n\r\nconst DeleteRowButton = ({ row, callback }) => {\r\n const onClick = () => {\r\n callback(row);\r\n };\r\n\r\n return ;\r\n};\r\n\r\nclass VolunteerList extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n showModal: false,\r\n deleting: false,\r\n volunteerToDelete: null,\r\n volunteers: this.props.group ? this.props.group.volunteers : null\r\n };\r\n\r\n this.toggleModal = this.toggleModal.bind(this);\r\n this.onDelete = this.onDelete.bind(this);\r\n this.onConfirmDelete = this.onConfirmDelete.bind(this);\r\n this.renderVolunteersTableRow = this.renderVolunteersTableRow.bind(this);\r\n }\r\n\r\n componentWillReceiveProps(nextProps) {\r\n if (nextProps.status === groupStatus.SUCCESS && this.state.deleting) {\r\n this.setState({\r\n deleting: false,\r\n showModal: false,\r\n volunteers: this.props.group.volunteers\r\n });\r\n }\r\n\r\n if (\r\n nextProps.status === groupStatus.SUCCESS &&\r\n this.props.submittingVolunteerForm\r\n ) {\r\n this.setState({\r\n volunteers: this.props.group.volunteers\r\n });\r\n }\r\n }\r\n\r\n toggleModal() {\r\n this.setState({\r\n showModal: !this.state.showModal\r\n });\r\n }\r\n\r\n onDelete(row) {\r\n this.setState({\r\n showModal: true,\r\n volunteerToDelete: row\r\n });\r\n }\r\n\r\n onConfirmDelete() {\r\n this.setState({\r\n deleting: true\r\n });\r\n\r\n const updatedList = this.state.volunteers.slice();\r\n const indexToRemove = updatedList.indexOf(this.state.volunteerToDelete);\r\n updatedList.splice(indexToRemove, 1);\r\n this.props.saveGroup(updatedList);\r\n }\r\n\r\n renderVolunteersTableRow(row, key) {\r\n // TODO - find better solution for row click event - delete column needs to be excluded from row click event\r\n return (\r\n \r\n this.props.onVolunteerRowClick(key, row)}>\r\n {row.name}\r\n \r\n this.props.onVolunteerRowClick(key, row)}>\r\n {row.email.toLowerCase()}\r\n \r\n this.props.onVolunteerRowClick(key, row)}>\r\n {row.phone}\r\n \r\n this.props.onVolunteerRowClick(key, row)}>\r\n {row.age}\r\n \r\n {/*\r\n this.props.onVolunteerRowClick(key, row)}>{row.specialDiets ? row.specialDiets.map(diet => this.props.intl.formatMessage({ id: `food.${diet.toLowerCase()}` })).join(\", \") : null} \r\n this.props.onVolunteerRowClick(key, row)}>{row.shirtSize ? this.props.intl.formatMessage({ id: `shirt-size.${row.shirtSize.toLowerCase()}` }) : null} \r\n */}\r\n \r\n \r\n \r\n \r\n );\r\n }\r\n\r\n renderVolunteers() {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {/*\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n */}\r\n \r\n \r\n \r\n {this.state.volunteers.map(this.renderVolunteersTableRow)}\r\n \r\n
\r\n \r\n
\r\n \r\n \r\n );\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n {this.state.volunteers && this.state.volunteers.length > 0 ? (\r\n this.renderVolunteers()\r\n ) : (\r\n \r\n )}\r\n \r\n );\r\n }\r\n}\r\n\r\nexport default injectIntl(VolunteerList);\r\n","import React, { Component, Fragment } from \"react\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport { BigGreenButton } from \"../../../../components/Buttons\";\r\nimport { injectIntl, FormattedMessage } from \"react-intl\";\r\nimport { groupStatus } from \"../reducer\";\r\nimport messages from \"../GroupConfirm/messages\";\r\nimport styled from \"styled-components\";\r\nimport VolunteerForm from \"./VolunteerForm\";\r\nimport VolunteerList from \"./VolunteerList\";\r\nimport {\r\n ConfirmationModal,\r\n} from \"../../../../components\";\r\n\r\nconst Wrapper = styled.div`\r\n margin-bottom: 80px;\r\n`;\r\n\r\nclass Volunteers extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n submitting: false,\r\n volunteerToEdit: null,\r\n confirming: false,\r\n showModal: false,\r\n groupStatus: this.props.group ? this.props.group.status : {},\r\n };\r\n\r\n this.saveGroup = this.saveGroup.bind(this);\r\n this.isNew = this.isNew.bind(this);\r\n this.onVolunteerRowClick = this.onVolunteerRowClick.bind(this);\r\n this.handleConfirm = this.handleConfirm.bind(this);\r\n this.toggleModal = this.toggleModal.bind(this);\r\n }\r\n\r\n componentDidUpdate(prevProps) {\r\n if (this.props.status === groupStatus.SUCCESS && this.state.submitting) {\r\n this.setState({\r\n submitting: false,\r\n volunteerToEdit: null,\r\n });\r\n }\r\n\r\n if (prevProps.group.status !== \"CONFIRMED\" && this.props.group.status === \"CONFIRMED\") {\r\n this.setState({\r\n confirming: false,\r\n showModal: null,\r\n });\r\n this.props.history.push(`/my-pages/volunteers/${this.props.group.groupId}/volunteers`);\r\n }\r\n }\r\n\r\n isNew() {\r\n return !this.props.match.params.id;\r\n }\r\n\r\n handleConfirm() {\r\n this.setState({\r\n confirming: true,\r\n });\r\n\r\n this.props.confirmGroup(this.props.group);\r\n }\r\n\r\n toggleModal(e) {\r\n e && e.preventDefault();\r\n this.setState({\r\n showModal: !this.state.showModal,\r\n });\r\n }\r\n\r\n saveGroup(volunteersList) {\r\n const groupToSubmit = this.props.group;\r\n groupToSubmit.volunteers = volunteersList;\r\n this.props.submitGroup(groupToSubmit);\r\n this.setState({\r\n submitting: true,\r\n });\r\n }\r\n\r\n onVolunteerRowClick(key, row) {\r\n this.setState({\r\n volunteerToEdit: row,\r\n volunteerEditKey: key,\r\n editingVolunteer: true,\r\n });\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n {this.props.group && this.props.group.status === \"DRAFT\"\r\n ? \r\n : null\r\n }\r\n \r\n
\r\n }\r\n busy={this.state.confirming}\r\n theme=\"green\"\r\n />\r\n );\r\n }\r\n}\r\n\r\nexport default injectIntl(Volunteers);\r\n","import { connect } from 'react-redux';\r\nimport { submitGroup, reset, status, confirmGroup } from '../reducer';\r\nimport Volunteers from './Volunteers';\r\n\r\nconst mapStateToProps = (state) => {\r\n const obj = {\r\n group: state.group.group,\r\n status: state.group.status,\r\n user: state.auth.user,\r\n };\r\n if (state.group.status === status.FETCHED) {\r\n obj.initialValues = state.group.volunteers;\r\n }\r\n\r\n return obj;\r\n};\r\n\r\nconst mapDispatchToProps = dispatch => ({\r\n submitGroup: data => dispatch(submitGroup(data)),\r\n resetGroup: () => dispatch(reset()),\r\n confirmGroup: data => dispatch(confirmGroup(data)),\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(Volunteers);\r\n","import React, { Fragment } from \"react\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport messages from \"./messages\";\r\nimport { Field, reduxForm } from \"redux-form\";\r\nimport { BigGreenButton } from \"../../../../components/Buttons/index\";\r\nimport { groupStatus } from \"../reducer\";\r\nimport {\r\n P,\r\n Input,\r\n ConfirmationModal,\r\n} from \"../../../../components\";\r\n\r\nclass GroupConfirm extends React.Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n showModal: false,\r\n confirming: false,\r\n groupStatus: this.props.group ? this.props.group.status : {},\r\n };\r\n\r\n this.handleConfirm = this.handleConfirm.bind(this);\r\n this.toggleModal = this.toggleModal.bind(this);\r\n this.onClickNext = this.onClickNext.bind(this);\r\n }\r\n\r\n componentDidMount() {\r\n if (this.props.location && this.props.location.pathname === \"/my-pages/volunteers/new\") {\r\n window.scrollTo(0, 0);\r\n }\r\n }\r\n\r\n componentDidUpdate(prevProps) {\r\n if (this.props.status === groupStatus.SUCCESS && prevProps === groupStatus.SUBMITTING && this.state.confirming) {\r\n this.toggleModal();\r\n this.setState({\r\n confirming: false,\r\n groupStatus: this.props.group.status,\r\n });\r\n }\r\n\r\n if (prevProps.group.status !== \"CONFIRMED\" && this.props.group.status === \"CONFIRMED\") {\r\n this.setState({\r\n confirming: false,\r\n showModal: false,\r\n groupStatus: this.props.group ? this.props.group.status : {},\r\n });\r\n\r\n const url = `/my-pages/volunteers/${this.props.group.groupId}/confirm`;\r\n if (url !== this.props.history.location.pathname) {\r\n this.props.history.push(`/my-pages/volunteers/${this.props.group.groupId}/confirm`);\r\n }\r\n }\r\n }\r\n\r\n handleConfirm() {\r\n this.setState({\r\n confirming: true,\r\n });\r\n\r\n this.props.confirmGroup(this.props.group);\r\n }\r\n\r\n toggleModal(e) {\r\n e && e.preventDefault();\r\n this.setState({\r\n showModal: !this.state.showModal,\r\n });\r\n }\r\n\r\n onClickNext() {\r\n this.props.onClickNext(2);\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n \r\n }\r\n busy={this.state.confirming}\r\n theme=\"green\"\r\n />\r\n \r\n );\r\n }\r\n}\r\n\r\nconst GroupConfirmForm = reduxForm({\r\n form: \"group-confirm\",\r\n})(GroupConfirm);\r\n\r\nexport default injectIntl(GroupConfirmForm);\r\n","import { connect } from 'react-redux';\r\nimport { reset, submitGroup, confirmGroup } from '../reducer';\r\nimport GroupConfirm from './GroupConfirm';\r\n\r\nconst mapStateToProps = (state, ownProps) => ({\r\n group: ownProps.group,\r\n status: state.group.status,\r\n initialValues: ownProps.group,\r\n});\r\n\r\nconst mapDispatchToProps = dispatch => ({\r\n submitGroup: data => dispatch(submitGroup(data)),\r\n resetEvent: () => dispatch(reset()),\r\n confirmGroup: data => dispatch(confirmGroup(data)),\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(GroupConfirm);\r\n","export const GROUP_AVAIL_SAVE = 'GROUP_AVAIL_SAVE';\r\nexport const GROUP_AVAIL_SAVE_SUCCESS = 'GROUP_AVAIL_SAVE_SUCCESS';\r\nexport const GROUP_AVAIL_SAVE_FAILED = 'GROUP_AVAIL_SAVE_FAILED';\r\nexport const GROUP_AVAIL_FETCH = 'GROUP_AVAIL_FETCH';\r\nexport const GROUP_AVAIL_FETCH_SUCCESS = 'GROUP_AVAIL_FETCH_SUCCESS';\r\nexport const GROUP_AVAIL_FETCH_FAILED = 'GROUP_AVAIL_FETCH_FAILED';\r\n\r\nexport const status = {\r\n SAVING: 'SAVING',\r\n NOT_SUBMITTED: 'NOT_SUBMITTED',\r\n SAVE_SUCCESS: 'SAVE_SUCCESS',\r\n SAVE_FAILED: 'SAVE_FAILED',\r\n};\r\n\r\nexport const saveAvailabilitiesStatus = status;\r\n\r\nexport function saveAvailabilities (data) {\r\n return {\r\n type: GROUP_AVAIL_SAVE,\r\n payload: data,\r\n };\r\n}\r\n\r\nexport function fetchAvailabilities (data) {\r\n return {\r\n type: GROUP_AVAIL_FETCH,\r\n payload: data,\r\n };\r\n}\r\n\r\nconst initialState = {\r\n status: status.NOT_SUBMITTED,\r\n availabilities: null,\r\n};\r\n\r\nexport default function groupAvailability (state = initialState, action) {\r\n if (!action) {\r\n return state;\r\n }\r\n\r\n switch (action.type) {\r\n case GROUP_AVAIL_SAVE:\r\n return Object.assign({}, state, {status: status.SAVING});\r\n case GROUP_AVAIL_FETCH_SUCCESS:\r\n return Object.assign({}, state, {availabilities: action.payload});\r\n case GROUP_AVAIL_FETCH_FAILED:\r\n return Object.assign({}, state, {availabilities: [], error: action.payload});\r\n case GROUP_AVAIL_SAVE_SUCCESS:\r\n return Object.assign({}, state, {status: status.SAVE_SUCCESS, availabilities: action.payload});\r\n case GROUP_AVAIL_SAVE_FAILED:\r\n return Object.assign({}, state, {status: status.SAVE_FAILED, availabilities: [], error: action.payload});\r\n default:\r\n return state;\r\n }\r\n}\r\n\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n title: {\r\n id: 'group-availability.title'\r\n },\r\n loading: {\r\n id: 'commmon.loading.message'\r\n },\r\n addForm: {\r\n title: {\r\n id: 'group-availability.add-form.title'\r\n },\r\n submit: {\r\n id: 'group-availability.add-form.submit'\r\n }\r\n },\r\n table: {\r\n type: {\r\n id: 'group-availability.table.header.type',\r\n },\r\n location: {\r\n id: 'group-availability.table.header.location',\r\n },\r\n period: {\r\n id: 'group-availability.table.header.period',\r\n },\r\n event: {\r\n id: 'group-availability.table.header.event',\r\n },\r\n input: {\r\n type: {\r\n id: 'group-availability.table.input.type',\r\n },\r\n types: {\r\n period: {\r\n id: 'group-availability.table.input.type.PERIOD',\r\n },\r\n event: {\r\n id: 'group-availability.table.input.type.EVENT',\r\n },\r\n },\r\n location: {\r\n id: 'group-availability.table.input.location',\r\n },\r\n startDate: {\r\n id: 'group-availability.table.input.startDate',\r\n },\r\n endDate: {\r\n id: 'group-availability.table.input.endDate',\r\n },\r\n event: {\r\n id: 'group-availability.table.input.event',\r\n },\r\n },\r\n newRow: {\r\n id: 'group-availability.table.addAvailability',\r\n },\r\n },\r\n saveButton: {\r\n id: 'group-availability.save-button',\r\n },\r\n});\r\n\r\n","import \"./index.css\";\r\nimport React, { Component, Fragment } from \"react\";\r\nimport { injectIntl } from \"react-intl\";\r\nimport { reduxForm, Field } from \"redux-form\";\r\nimport messages from \"./messages\";\r\nimport styled from \"styled-components\";\r\nimport {\r\n SmallDatePicker,\r\n SmallSelect,\r\n FormGroup\r\n} from \"../../../../components/index\";\r\nimport { BigGreenButton } from \"../../../../components/Buttons\";\r\nimport { municipalities } from \"../../../../constants/municipalities\";\r\nimport { required } from \"../../../../validators\";\r\nimport moment from \"moment\";\r\n\r\nconst TableDatePicker = styled(SmallDatePicker)``;\r\nconst StyledButton = styled(BigGreenButton)`\r\n margin: 0 0 0 0;\r\n background-color: #009aa2;\r\n background: linear-gradient(#00adba,#009aa2);\r\n`;\r\n\r\nclass AddAvailabilityFormComponent extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n type: null,\r\n event: null\r\n };\r\n }\r\n\r\n render() {\r\n const {\r\n intl,\r\n events,\r\n fetchEvent,\r\n completeEvents = [],\r\n handleSubmit\r\n } = this.props || {};\r\n const sortedEventList = events.sort((a, b) => a.name.localeCompare(b.name));\r\n let mun = municipalities;\r\n if (this.state.type && this.state.type === \"EVENT\" && this.state.event) {\r\n const event = completeEvents.find(e => e.eventId === this.state.event);\r\n if (!event) {\r\n fetchEvent(this.state.event);\r\n } else {\r\n mun = municipalities.filter(m => {\r\n return event.stations && event.stations.find(s => s.municipality === m.id);\r\n });\r\n }\r\n }\r\n const typeOptions = [\"PERIOD\", \"EVENT\"].map(k => ({\r\n value: k,\r\n text: intl.formatMessage({\r\n id: `group-availability.table.input.type.${k}`\r\n })\r\n }));\r\n return (\r\n \r\n );\r\n }\r\n}\r\n\r\nconst AddAvailabilityForm = reduxForm({\r\n form: \"addInterestForm\",\r\n initialValues: {\r\n startDate: moment(),\r\n endDate: moment().add(1, \"days\")\r\n }\r\n})(\r\n injectIntl(AddAvailabilityFormComponent)\r\n);\r\n\r\nexport default AddAvailabilityForm;\r\n","import \"./index.css\";\r\nimport React, {Component} from 'react';\r\nimport { withRouter } from 'react-router';\r\nimport {FormattedMessage, injectIntl} from 'react-intl';\r\n\r\nimport { connect } from 'react-redux'\r\nimport { reset } from 'redux-form';\r\nimport { status } from './reducer';\r\n\r\nimport BootstrapTable from 'react-bootstrap-table-next';\r\nimport { Modal } from 'react-bootstrap/lib';\r\n\r\nimport moment from 'moment';\r\nimport messages from './messages';\r\n\r\nimport { H2, TextSection } from '../../../../components/index';\r\nimport { DeleteButton, SmallGrayButton, removeMargin } from '../../../../components/Buttons';\r\nimport { ModalWrapper, Content } from '../../../../components/ConfirmationModal';\r\nimport { municipalities } from '../../../../constants/municipalities';\r\nimport AddAvailabilityForm from './AddGroupAvailabilityForm'\r\nimport styled from \"styled-components\";\r\n\r\nconst SmallThinGrayButton = removeMargin(SmallGrayButton);\r\n\r\nclass GroupAvailability extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n showModal: false,\r\n }\r\n\r\n this.toggleModal = this.toggleModal.bind(this);\r\n this.addGroupAvailability = this.addGroupAvailability.bind(this);\r\n this.submitAvailabilities = this.submitAvailabilities.bind(this);\r\n\r\n }\r\n\r\n UNSAFE_componentWillMount () {\r\n const { fetchPublicEvents, groupId, fetchGroupAvailabilities } = this.props || {};\r\n fetchPublicEvents({startDate: moment().format('YYYY-MM-DD'), endDate: moment().add(3, 'years').format('YYYY-MM-DD')});\r\n groupId && fetchGroupAvailabilities({ groupId: groupId })\r\n }\r\n\r\n toggleModal() {\r\n const { resetForm } = this.props || {};\r\n resetForm()\r\n this.setState({\r\n showModal: !this.state.showModal\r\n });\r\n }\r\n\r\n addGroupAvailability(data) {\r\n const { initialValues: { availabilities = [] } = {}, groupId, submitGroupAvailabilities } = this.props || {}\r\n const newAvailabilities = [...availabilities]\r\n newAvailabilities.push({...data})\r\n const toSubmit = {\r\n groupId: groupId,\r\n availabilities: newAvailabilities,\r\n };\r\n submitGroupAvailabilities(toSubmit);\r\n this.toggleModal()\r\n }\r\n\r\n deleteGroupAvailibility(data) {\r\n const { initialValues: { availabilities = [] } = {} } = this.props || {}\r\n const newAvailabities = availabilities.filter(availability => \r\n !(availability.organizerSK === data.organizerSK && \r\n availability.organizerPK === data.organizerPK &&\r\n availability.groupSK === data.groupSK &&\r\n availability.location === data.location &&\r\n availability.type === data.type \r\n ))\r\n this.submitAvailabilities(newAvailabities)\r\n }\r\n\r\n submitAvailabilities(data) {\r\n const { availabilityStatus, groupId, submitGroupAvailabilities } = this.props || {};\r\n // Prevent double click by not saving when request is ongoing\r\n if (availabilityStatus === status.SAVING) {\r\n return;\r\n }\r\n const toSubmit = {\r\n groupId: groupId,\r\n availabilities: data,\r\n };\r\n submitGroupAvailabilities(toSubmit);\r\n }\r\n\r\n render() {\r\n const columns = [\r\n {\r\n dataField: \"id\",\r\n text: \"id\",\r\n hidden: true,\r\n }, \r\n {\r\n dataField: \"type\",\r\n text: this.props.intl.formatMessage(messages.table.event),\r\n sort: true,\r\n }, \r\n {\r\n dataField: \"location\",\r\n text: this.props.intl.formatMessage(messages.table.location),\r\n sort: true,\r\n },\r\n {\r\n dataField: \"button\",\r\n text: \"\",\r\n classes: \"hidden-column\",\r\n headerStyle: {backgroundColor: \"#e2f0f1\", borderWidth: 0}\r\n }\r\n ]\r\n\r\n const { initialValues: { availabilities = [] } = {}, intl, publicEvents, fetchEvent, completeEvents, groupId, group } = this.props || {}\r\n const products = availabilities ? availabilities.map(availability => {\r\n const location = municipalities.find(municipality => municipality.id === availability.location) || {}\r\n switch (availability.type) {\r\n case \"PERIOD\":\r\n return {id: availability.organizerSK, type: `${moment(availability.startDate).format(\"DD MMMM YYYY\")} - ${moment(availability.endDate).format(\"DD MMMM YYYY\")}`, location: location.name, button: this.deleteGroupAvailibility(availability)} />}\r\n default: { //case \"EVENT\"\r\n const eventFound = (this.props && completeEvents) && (completeEvents.find(publicEvent => publicEvent.eventId === availability.eventId)) //|| fetchEvent(availability.eventId))\r\n return {id : availability.organizerSK, type: eventFound.name || , location: location.name, button: this.deleteGroupAvailibility(availability)} />}\r\n }\r\n }\r\n }) : []\r\n if (!groupId && !group.group.groupId) {\r\n return {'[Det ska inte vara tillåtet att gå hit utan att ha sparat gruppen eftersom vi inte har något grupp-id att referera till. Går ju såklart att bygga men det ger ökad komplexitet så det är ett hörn som vi bör kutta tillsvidare.]'} ;\r\n }\r\n\r\n return (\r\n \r\n \r\n {products.length > 0 && (\r\n \r\n )}\r\n {\r\n this.setState({showModal: !this.state.showModal})\r\n }}>\r\n \r\n \r\n }\r\n />\r\n \r\n );\r\n }\r\n}\r\n\r\nconst SmallDeleteButton = styled(DeleteButton)`\r\n display: block;\r\n margin-left: auto;\r\n margin-right: 0;\r\n i {\r\n font-size: 30px;\r\n color: gray;\r\n }\r\n`;\r\n\r\nconst NoPaddingModalBody = styled(Modal.Body)`\r\n padding: 0px;\r\n`;\r\n\r\nconst AddInterestModal = ({ show, close, form, title }) => (\r\n \r\n \r\n \r\n \r\n
{title} \r\n \r\n \r\n {form}\r\n \r\n \r\n \r\n)\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n resetForm: () => dispatch(reset(\"addInterestForm\"))\r\n})\r\n\r\nconst GroupAvailabilityForm = withRouter(connect(null, mapDispatchToProps)((injectIntl(GroupAvailability))))\r\n\r\nexport default GroupAvailabilityForm;\r\n","import { connect } from \"react-redux\";\r\nimport { fetchPublicEvents, fetchCompleteEvent } from \"../reducer\";\r\nimport GroupAvailability from \"./GroupAvailability\";\r\nimport { saveAvailabilities, fetchAvailabilities } from \"./reducer\";\r\n\r\nconst mapStateToProps = (state) => ({\r\n group: state.group,\r\n completeEvents: state.group.completeEvents,\r\n publicEvents: state.group.publicEvents,\r\n event: state.event,\r\n publicEventsError: state.group.publicEventsError,\r\n status: state.group.status,\r\n availabilityStatus: state.groupAvailabilities.status,\r\n initialValues: { availabilities: state.groupAvailabilities.availabilities },\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n submitGroupAvailabilities: data => dispatch(saveAvailabilities(data)),\r\n fetchGroupAvailabilities: data => dispatch(fetchAvailabilities(data)),\r\n fetchPublicEvents: data => dispatch(fetchPublicEvents(data)),\r\n fetchEvent: data => dispatch(fetchCompleteEvent(data))\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(GroupAvailability);\r\n","import React, { Component, Fragment } from \"react\";\r\nimport { ContentWrapper, Container, H1 } from \"../../../../components\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport GroupForm from \"../GroupForm\";\r\nimport Volunteers from \"../Volunteers\";\r\nimport GroupConfirm from \"../GroupConfirm\";\r\nimport messages from \"../messages\";\r\nimport { FormattedMessage } from \"react-intl\";\r\nimport styled from \"styled-components\";\r\nimport { GreenNavLinkButton } from \"../../../../components/Links\";\r\nimport { groupStatus } from \"../reducer\";\r\nimport GroupAvailability from \"../GroupAvailability\";\r\nimport {\r\n Switch,\r\n Route\r\n} from \"react-router-dom\";\r\n\r\nconst states = [\r\n {\r\n step: 0,\r\n name: ,\r\n },\r\n {\r\n step: 1,\r\n name: ,\r\n },\r\n {\r\n step: 2,\r\n name: ,\r\n },\r\n];\r\n\r\nconst NavigationWrapper = styled.nav`\r\n margin-bottom: 90px;\r\n`;\r\n\r\nclass GroupBase extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n currentStep: 0,\r\n clickedNext: false,\r\n nextStep: 1,\r\n };\r\n\r\n this.goToStep = this.goToStep.bind(this);\r\n this.handleGroupSubmit = this.handleGroupSubmit.bind(this);\r\n }\r\n\r\n componentDidMount() {\r\n if (!this.isNew()) {\r\n this.props.fetchGroup({ id: this.props.match.params.id });\r\n }\r\n }\r\n\r\n componentWillReceiveProps(nextProps) {\r\n if (nextProps.status === groupStatus.SUCCESS && this.props.status === groupStatus.SUBMITTING && this.state.clickedNext) {\r\n this.goToStep(this.state.nextStep);\r\n this.setState({\r\n clickedNext: false,\r\n });\r\n }\r\n }\r\n\r\n componentWillUnmount() {\r\n this.props.reset();\r\n }\r\n\r\n goToStep(step) {\r\n if (step >= 0 && step <= states.length) {\r\n this.setState({\r\n currentStep: step,\r\n });\r\n\r\n if (states[step].link) {\r\n this.props.history.push(states[step].link);\r\n }\r\n }\r\n }\r\n\r\n handleGroupSubmit(step) {\r\n this.setState({\r\n clickedNext: true,\r\n nextStep: step,\r\n });\r\n }\r\n\r\n isNew() {\r\n return !this.props.match.params.id;\r\n }\r\n\r\n render() {\r\n if (!this.props.group) {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n );\r\n }\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n {this.props.group.name} \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n }\r\n />\r\n (\r\n )}\r\n />\r\n }\r\n />\r\n \r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nexport default GroupBase;\r\n","import { connect } from \"react-redux\";\r\nimport { submitGroup, fetchGroup, reset } from \"../reducer\";\r\nimport GroupBase from \"./GroupBase\";\r\n\r\nconst mapStateToProps = (state) => {\r\n const obj = {\r\n group: state.group.group,\r\n error: state.group.error,\r\n status: state.group.status,\r\n user: state.auth.user,\r\n };\r\n\r\n return obj;\r\n};\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n submitGroup: data => dispatch(submitGroup(data)),\r\n fetchGroup: data => dispatch(fetchGroup(data)),\r\n reset: () => dispatch(reset({})),\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(GroupBase);\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n progressBar: {\r\n registerGroup: {\r\n id: 'new-group.progressbar.register-group.placeholder',\r\n },\r\n registerVolunteers: {\r\n id: 'new-group.progressbar.register-volunteers.placeholder',\r\n },\r\n registerAvailability: {\r\n id: 'new-group.progressbar.register-availability.placeholder',\r\n },\r\n },\r\n groupForm: {\r\n title: {\r\n id: 'new-group.group-form.title',\r\n },\r\n text: {\r\n id: 'new-group.group-form.text',\r\n },\r\n },\r\n availability: {\r\n title: {\r\n id: 'new-group.availability.title',\r\n },\r\n text: {\r\n id: 'new-group.availability.text',\r\n },\r\n },\r\n volunteers: {\r\n title: {\r\n id: 'new-group.volunteers.title',\r\n },\r\n text: {\r\n id: 'new-group.volunteers.text',\r\n },\r\n },\r\n confirmation: {\r\n title: {\r\n id: 'new-group.confirmation.title',\r\n },\r\n text: {\r\n id: 'new-group.confirmation.text',\r\n },\r\n },\r\n nextButton: {\r\n id: 'next-step-button',\r\n },\r\n});\r\n","import React, { Component, Fragment } from \"react\";\r\nimport { ContentWrapper, Container, ProgressBar } from \"../../../../components/index\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport GroupForm from \"../GroupForm\";\r\nimport GroupConfirm from \"../GroupConfirm\";\r\nimport Volunteers from \"../Volunteers\";\r\nimport { colors } from \"../../../../constants/styling-constants\";\r\nimport messages from \"./messages\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport { groupStatus } from \"../reducer\";\r\nimport {\r\n H1,\r\n P\r\n} from \"../../../../components\";\r\nimport GroupAvailability from \"../GroupAvailability\";\r\n\r\nconst states = [\r\n {\r\n step: 0,\r\n name: ,\r\n },\r\n {\r\n step: 1,\r\n name: ,\r\n },\r\n {\r\n step: 2,\r\n name: ,\r\n },\r\n];\r\n\r\nclass GroupNewBase extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n currentStep: 0,\r\n clickedNext: false,\r\n };\r\n\r\n\r\n this.goToStep = this.goToStep.bind(this);\r\n this.goToNextStep = this.goToNextStep.bind(this);\r\n this.handleGroupSubmit = this.handleGroupSubmit.bind(this);\r\n }\r\n\r\n componentWillUnmount() {\r\n this.props.reset();\r\n }\r\n\r\n componentWillReceiveProps(nextProps) {\r\n if (nextProps.status === groupStatus.SUCCESS && this.props.status === groupStatus.SUBMITTING && this.state.clickedNext) {\r\n this.goToStep(this.state.currentStep + 1);\r\n this.setState({\r\n clickedNext: false,\r\n });\r\n }\r\n }\r\n\r\n goToStep(step) {\r\n if (step >= 0 && step <= states.length) {\r\n this.setState({\r\n currentStep: step,\r\n });\r\n\r\n if (states[step].link) {\r\n this.props.history.push(states[step].link);\r\n }\r\n }\r\n }\r\n\r\n goToNextStep() {\r\n const nextStep = this.state.currentStep + 1;\r\n this.goToStep(nextStep);\r\n }\r\n\r\n handleGroupSubmit() {\r\n this.setState({\r\n clickedNext: true,\r\n });\r\n }\r\n\r\n handleAvailabilitySubmit(data) {\r\n if (this.props.group && this.props.group.id) {\r\n const updatedGroup = Object.assign({}, this.props.group, { availabilities: data });\r\n this.props.submitGroup(updatedGroup);\r\n }\r\n }\r\n\r\n renderGroupForm() {\r\n return (\r\n \r\n \r\n \r\n \r\n
\r\n \r\n
\r\n \r\n \r\n );\r\n }\r\n\r\n renderVolunteers() {\r\n return (\r\n \r\n \r\n \r\n \r\n
\r\n \r\n
\r\n \r\n \r\n );\r\n }\r\n\r\n renderConfirmation() {\r\n return (\r\n \r\n \r\n \r\n \r\n
\r\n \r\n
\r\n \r\n \r\n \r\n );\r\n }\r\n\r\n renderPage() {\r\n return [\r\n this.renderGroupForm,\r\n this.renderConfirmation,\r\n this.renderVolunteers,\r\n ][this.state.currentStep].call(this);\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n {this.renderPage()}\r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nexport default injectIntl(GroupNewBase);\r\n","import { connect } from \"react-redux\";\r\nimport { submitGroup, reset } from \"../reducer\";\r\nimport GroupNewBase from \"./GroupNewBase\";\r\n\r\nconst mapStateToProps = (state) => {\r\n const obj = {\r\n group: state.group.group,\r\n error: state.group.error,\r\n status: state.group.status,\r\n user: state.auth.user,\r\n };\r\n\r\n return obj;\r\n};\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n submitGroup: data => dispatch(submitGroup(data)),\r\n reset: () => dispatch(reset({})),\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(GroupNewBase);\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n modal: {\r\n newVolunteers: {\r\n id: 'group.volunteer.modal.newVolunteers'\r\n },\r\n newVolunteersCreate: {\r\n\tid: 'group.volunteer.modal.newVolunteersCreate'\r\n },\r\n missingSpecialInfo: {\r\n id: 'group.volunteer.modal.missingSpecialInfo'\r\n },\r\n },\r\n attendees: {\r\n title: {\r\n id: 'group.volunteer.form.list.title'\r\n },\r\n name: {\r\n id: 'group.volunteer.form.name.placeholder',\r\n },\r\n email: {\r\n id: 'group.volunteer.form.email.placeholder',\r\n },\r\n phone: {\r\n id: 'group.volunteer.form.phone.placeholder',\r\n },\r\n age: {\r\n id: 'group.volunteer.form.age.placeholder',\r\n },\r\n notEnoughAttendee: {\r\n id: 'group.volunteer.form.notEnoughAttendee'\r\n },\r\n addButton: {\r\n id: 'group.volunteer.form.addButton'\r\n },\r\n createButton: {\r\n id: 'group.volunteer.form.createButton'\r\n },\r\n submitButton: {\r\n id: 'group.volunteer.form.submitButton'\r\n },\r\n closeButton: {\r\n id: 'group.volunteer.popUp.closeButton'\r\n },\r\n specialDiets: {\r\n title: {\r\n id: 'group.volunteer.list.special-diets.title'\r\n },\r\n lactoseFree: {\r\n id: 'group.volunteer.form.special-diets.lactose-free.placeholder',\r\n },\r\n glutenFree: {\r\n id: 'group.volunteer.form.special-diets.gluten-free.placeholder',\r\n },\r\n vegetarian: {\r\n id: 'group.volunteer.form.special-diets.vegetarian.placeholder',\r\n },\r\n vegan: {\r\n id: 'group.volunteer.form.special-diets.vegan.placeholder',\r\n },\r\n },\r\n shirtSize: {\r\n id: 'group.volunteer.form.shirt-size.placeholder',\r\n },\r\n substitute: {\r\n id: 'group.engagement.volunteer.form.substitute'\r\n },\r\n },\r\n form: {\r\n name: {\r\n id: 'engagement-proposal.form.station-name.placeholder'\r\n },\r\n date: {\r\n id: 'engagement-proposal.form.date.placeholder',\r\n },\r\n start: {\r\n id: 'engagement-proposal.form.start-time.placeholder',\r\n },\r\n end: {\r\n id: 'engagement-proposal.form.end-time.placeholder',\r\n },\r\n officialQuantity: {\r\n id: 'engagement-proposal.form.official-quantity.placeholder',\r\n },\r\n description: {\r\n id: 'engagement-proposal.form.description.placeholder',\r\n },\r\n paymentType: {\r\n id: 'engagement-proposal.form.payment-type.placeholder',\r\n },\r\n paymentAdult: {\r\n id: 'engagement-proposal.form.payment-adult.placeholder',\r\n },\r\n paymentChild: {\r\n id: 'engagement-proposal.form.payment-child.placeholder',\r\n },\r\n groupPayment: {\r\n id: 'engagement-proposal.form.group-payment.placeholder',\r\n },\r\n requiredSkills: {\r\n id: 'engagement-proposal.form.skills.placeholder'\r\n }\r\n },\r\n confirmTitle: {\r\n id: 'engagement-proposal.title',\r\n },\r\n confirmText: {\r\n id: 'engagement-proposal.info',\r\n },\r\n confirmText2: {\r\n id: 'engagement-proposal.info.2',\r\n },\r\n confirmText3: {\r\n id: 'engagement-proposal.info.3',\r\n },\r\n confirmButton: {\r\n id: 'engagement-proposal.confirm-button',\r\n },\r\n rejectButton: {\r\n id: 'engagement-proposal.reject-button',\r\n },\r\n confirmModalText: {\r\n id: 'engagement-proposal.modal-confirm-text',\r\n },\r\n confirmModalTitle: {\r\n id: 'engagement-proposal.modal-confirm.-title',\r\n },\r\n confirmModalCancelButton: {\r\n id: 'engagement-proposal.modal-confirm.cancel-button',\r\n },\r\n confirmModalRejectButton: {\r\n id: 'engagement-proposal.modal-confirm.confirm-button',\r\n },\r\n rejectModalText: {\r\n id: 'engagement-proposal.modal-reject-text',\r\n },\r\n rejectModalCancelButton: {\r\n id: 'engagement-proposal.modal-reject.cancel-button',\r\n },\r\n rejectModalRejectButton: {\r\n id: 'engagement-proposal.modal-reject.reject-button',\r\n },\r\n rejectModalTitle: {\r\n id: 'engagement-proposal.modal-reject.-title',\r\n },\r\n offerConfirmedText: {\r\n id: 'engagement-proposal.confirmed-text',\r\n },\r\n offerRejectedText: {\r\n id: 'engagement-proposal.rejected-text',\r\n }\r\n});\r\n","import React, { Component, Fragment } from \"react\";\r\nimport {FormattedMessage, injectIntl } from \"react-intl\";\r\nimport messages from \"./messages\";\r\nimport _ from \"lodash\";\r\nimport BootstrapTable from \"react-bootstrap-table-next\";\r\nimport { BigGreenButton, BigGrayButton } from \"../../../../components/Buttons\";\r\nimport VolunteerForm from \"../Volunteers/VolunteerForm\";\r\nimport { GeneralError, PopUpModal } from \"../../../../components\";\r\n\r\nclass GroupAttendeesForm extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n selected: [],\r\n createNewVoluntee: false,\r\n volunteerToEdit: {},\r\n editVolunteer: false,\r\n specialInfoPopUp: false,\r\n };\r\n this.selectRow = this.selectRow.bind(this);\r\n this.selectAll = this.selectAll.bind(this);\r\n this.goBackToList = this.goBackToList.bind(this);\r\n this.createNewVoluntee = this.createNewVoluntee.bind(this);\r\n this.submitNewAttendees = this.submitNewAttendees.bind(this);\r\n this.specialInfoPopUp = this.specialInfoPopUp.bind(this);\r\n }\r\n\r\n submitNewAttendees() {\r\n this.setState({ error: false });\r\n const { offer, update, updateOffers } = this.props;\r\n const { attendees = [] } = offer;\r\n const newAttendees = this.state[\"selected\"];\r\n\r\n if (!newAttendees.length > 0) {\r\n this.setState({ error: true });\r\n return;\r\n }\r\n\r\n const attendeesMissingSpecialInfo = [];\r\n /*if(this.props.offer.foodOptions && this.props.offer.shirtSizes){\r\n newAttendees.map((attendee) => attendee.participation ? \r\n attendee.participation.some((event) => event.eventId === this.props.offer.eventId && event.specialDiets && event.shirtSize ? \r\n true : false)? attendees.push(attendee.id) : attendeesMissingSpecialInfo.push(attendee.id):attendeesMissingSpecialInfo.push(attendee.id))\r\n }*/\r\n /*else if(this.props.offer.foodOptions){\r\n newAttendees.map((attendee) => attendee.participation ? \r\n attendee.participation.some((event) => event.eventId === this.props.offer.eventId && event.specialDiets ? \r\n true : false)? attendees.push(attendee.id) : attendeesMissingSpecialInfo.push(attendee.id):attendeesMissingSpecialInfo.push(attendee.id))\r\n }*/\r\n if(this.props.offer.shirtSizes){\r\n newAttendees.map((attendee) => attendee.participation ? \r\n attendee.participation.some((event) => event.eventId === this.props.offer.eventId && event.shirtSize ? \r\n true : false)? attendees.push(attendee.id) : attendeesMissingSpecialInfo.push(attendee.id):attendeesMissingSpecialInfo.push(attendee.id))\r\n }\r\n else{\r\n newAttendees.map((att) => attendees.push(att.id))\r\n }\r\n \r\n if(attendees.length > 0){\r\n update({\r\n eventId: offer.eventId,\r\n groupId: offer.groupId,\r\n stationId: offer.stationId,\r\n attendees: attendees,\r\n });\r\n updateOffers({\r\n eventId: offer.eventId,\r\n groupId: offer.groupId,\r\n });\r\n }\r\n this.setState({ selected: [] });\r\n\r\n if(attendeesMissingSpecialInfo.length > 0){\r\n this.setState({ specialInfoPopUp: true });\r\n }\r\n else{\r\n this.props.handleHide();\r\n }\r\n \r\n }\r\n\r\n selectRow(row) {\r\n var selected = this.state[\"selected\"];\r\n if (\r\n !selected.find(function (el) {\r\n return el.id === row.id;\r\n })\r\n ) {\r\n selected.push(row);\r\n } else {\r\n _.remove(selected, function (el) {\r\n return el.id === row.id;\r\n });\r\n }\r\n this.setState(selected);\r\n }\r\n\r\n selectAll(isSelect, rows) {\r\n var selected = [];\r\n if (isSelect) {\r\n rows.forEach((row) => selected.push(row));\r\n }\r\n this.setState({ selected: selected });\r\n }\r\n\r\n getColumns(intl) {\r\n const columns = [\r\n { dataField: \"id\", text: \"id\", hidden: true },\r\n {\r\n dataField: \"name\",\r\n text: intl.formatMessage(messages.attendees.name),\r\n sort: true,\r\n },\r\n {\r\n dataField: \"email\",\r\n text: intl.formatMessage(messages.attendees.email),\r\n sort: true,\r\n },\r\n {\r\n dataField: \"age\",\r\n text: intl.formatMessage(messages.attendees.age),\r\n sort: true,\r\n },\r\n ...(this.props.offer && this.props.offer.foodOptions\r\n ? [\r\n {\r\n dataField: \"specialDiets\",\r\n text: intl.formatMessage(messages.attendees.specialDiets.title),\r\n sort: true,\r\n },\r\n ]\r\n : []),\r\n ...(this.props.offer && this.props.offer.shirtSizes\r\n ? [\r\n {\r\n dataField: \"shirtSize\",\r\n text: intl.formatMessage(messages.attendees.shirtSize),\r\n sort: true,\r\n },\r\n ]\r\n : []),\r\n ...(this.props.offer && this.props.offer.substitute === \"active\"\r\n ? [\r\n {\r\n dataField: \"substitute\",\r\n text: intl.formatMessage(messages.attendees.substitute),\r\n sort: true,\r\n },\r\n ]\r\n : []),\r\n ];\r\n return columns;\r\n }\r\n\r\n goBackToList() {\r\n this.setState({ createNewVoluntee: false });\r\n this.setState({ volunteerToEdit: null });\r\n this.setState({ editVolunteer: false });\r\n }\r\n\r\n handleClose() {\r\n if(this.state.createNewVoluntee || this.state.editVolunteer){\r\n this.goBackToList();\r\n }\r\n else{\r\n this.props.handleHide();\r\n }\r\n }\r\n\r\n getSpecialDiets(group, intl) {\r\n if (group && group.specialDiets && group.specialDiets.length > 0) {\r\n return group.specialDiets.map((specialDiet, index) => {\r\n return index === 0\r\n ? intl.formatMessage({ id: `food.${specialDiet.toLowerCase()}` })\r\n : \", \" +\r\n intl.formatMessage({ id: `food.${specialDiet.toLowerCase()}` });\r\n });\r\n }\r\n }\r\n\r\n createNewVoluntee() {\r\n this.setState({ createNewVoluntee: true });\r\n }\r\n\r\n specialInfoPopUp(){\r\n this.setState({ specialInfoPopUp: false });\r\n this.props.handleHide();\r\n }\r\n\r\n\r\n render() {\r\n const onRowClick = {\r\n onClick: (e, row, rowIndex) => {\r\n this.setState({ volunteerToEdit: row });\r\n this.setState({ editVolunteer: true });\r\n this.setState({ createNewVoluntee: true });\r\n },\r\n };\r\n\r\n const { intl, group, offer, offers } = this.props;\r\n const nonNullOfferAttendees =\r\n offer && offer.attendees && offer.attendees.length > 0\r\n ? offer.attendees\r\n : [];\r\n\r\n const availableAttendee =\r\n group && group.volunteers && group.volunteers.length > 0\r\n ? group.volunteers.filter(\r\n (volunteer) =>\r\n !nonNullOfferAttendees.find(\r\n (attendee) => attendee === volunteer.id\r\n )\r\n )\r\n : [];\r\n \r\n const noOtherStations =\r\n offers && group && group.volunteers && group.volunteers.length > 0\r\n ? availableAttendee.filter(\r\n (vol) => !offers.some(\r\n (offer) => offer.attendees ? offer.attendees.includes(vol.id) : false\r\n ))\r\n : [];\r\n \r\n const formattedAttendee = noOtherStations.map((attendee) => {\r\n const { substitute, specialDiets, shirtSize, ...rest } = attendee;\r\n const diet = attendee.participation\r\n ? attendee.participation.map((event) =>\r\n event.eventId === this.props.offer.eventId && event.specialDiets\r\n ? this.getSpecialDiets(event, intl)\r\n : null\r\n )\r\n : null;\r\n \r\n const shirt = attendee.participation\r\n ? attendee.participation.map((event) =>\r\n event.eventId === this.props.offer.eventId && event.shirtSize\r\n ? event.shirtSize\r\n : null\r\n )\r\n : null;\r\n\r\n const sub = attendee.participation\r\n ? attendee.participation.map((event) =>\r\n event.eventId === this.props.offer.eventId && event.substitute\r\n ? event.substitute\r\n : null\r\n )\r\n : null;\r\n \r\n return { substitute: sub, specialDiets: diet, shirtSize: shirt, ...rest };\r\n });\r\n return (\r\n \r\n \r\n \r\n {this.state.createNewVoluntee && (\r\n {\r\n const groupToSubmit = this.props.group;\r\n groupToSubmit.volunteers = volunteersList;\r\n this.props.saveGroup(groupToSubmit);\r\n this.goBackToList()\r\n }}\r\n />\r\n )}\r\n {!this.state.createNewVoluntee && (\r\n \r\n \r\n {this.state.error && (\r\n \r\n {intl.formatMessage(messages.attendees.notEnoughAttendee)}\r\n \r\n )}\r\n \r\n \r\n \r\n
\r\n \r\n )}\r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nexport default injectIntl(GroupAttendeesForm);\r\n","import React, { Component, Fragment } from \"react\";\r\nimport { injectIntl } from \"react-intl\";\r\nimport { submitGroup } from \"../reducer\";\r\nimport messages from \"./messages\";\r\nimport { connect } from \"react-redux\";\r\nimport { updateOfferAttendees, fetchGroupOffers } from \"../../Offer/reducer\";\r\nimport { DeleteButton, BigGreenButton } from \"../../../../components/Buttons\";\r\nimport BootstrapTable from \"react-bootstrap-table-next\";\r\nimport { H3 } from \"../../../../components\";\r\nimport GroupAttendeesForm from \"./GroupAttendeesForm\";\r\n\r\nclass GroupAttendees extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n addVolunteersPopup: false,\r\n };\r\n this.toggleAddVolunteersModal = this.toggleAddVolunteersModal.bind(this);\r\n this.deleteAttendees = this.deleteAttendees.bind(this);\r\n }\r\n\r\n getColumns(intl) {\r\n const columns = [\r\n { dataField: \"id\", text: \"id\", hidden: true },\r\n {\r\n dataField: \"name\",\r\n text: intl.formatMessage(messages.attendees.name),\r\n sort: true,\r\n },\r\n {\r\n dataField: \"email\",\r\n text: intl.formatMessage(messages.attendees.email),\r\n sort: true,\r\n },\r\n {\r\n dataField: \"phone\",\r\n text: intl.formatMessage(messages.attendees.phone),\r\n sort: true,\r\n },\r\n {\r\n dataField: \"age\",\r\n text: intl.formatMessage(messages.attendees.age),\r\n sort: true,\r\n },\r\n ...this.props.offer && this.props.offer.foodOptions ? \r\n [{\r\n dataField: \"specialDiets\",\r\n text: intl.formatMessage(messages.attendees.specialDiets.title),\r\n sort: true\r\n }]\r\n : [],\r\n ...this.props.offer && this.props.offer.shirtSizes ?\r\n [{\r\n dataField: \"shirtSize\",\r\n text: intl.formatMessage(messages.attendees.shirtSize),\r\n sort: true\r\n }]\r\n : [], \r\n ...this.props.offer && this.props.offer.substitute === \"active\" ?\r\n [{\r\n dataField: \"substitute\",\r\n text: intl.formatMessage(messages.attendees.substitute),\r\n sort: true\r\n }]\r\n : [],\r\n {\r\n dataField: \"button\",\r\n text: \"\",\r\n classes: \"hidden-column\",\r\n headerStyle: { backgroundColor: \"#e2f0f1\", borderWidth: 0 },\r\n },\r\n ];\r\n return columns;\r\n }\r\n\r\n toggleAddVolunteersModal() {\r\n this.setState({ addVolunteersPopup: !this.state.addVolunteersPopup });\r\n }\r\n\r\n getSpecialDiets(group, intl) {\r\n if (group && group.specialDiets && group.specialDiets.length > 0) {\r\n return group.specialDiets.map((specialDiet, index) => {\r\n return index === 0\r\n ? intl.formatMessage({ id: `food.${specialDiet.toLowerCase()}` })\r\n : \", \" +\r\n intl.formatMessage({\r\n id: `food.${specialDiet.toLowerCase()}`,\r\n });\r\n });\r\n }\r\n }\r\n\r\n deleteAttendees({ id }) {\r\n const { updateOfferAttendees, fetchGroupOffers, offer } = this.props;\r\n const newAttendees = offer.attendees.filter((attendee) => attendee !== id);\r\n\r\n updateOfferAttendees({\r\n eventId: offer.eventId,\r\n groupId: offer.groupId,\r\n stationId: offer.stationId,\r\n attendees: newAttendees,\r\n });\r\n\r\n fetchGroupOffers({\r\n eventId: offer.eventId,\r\n groupId: offer.groupId,\r\n });\r\n }\r\n\r\n render() {\r\n const { offer, offers, group, intl } = this.props;\r\n const currentAttendees = (\r\n offer &&\r\n offer.attendees &&\r\n offer.attendees.length > 0 &&\r\n group &&\r\n group.volunteers &&\r\n group.volunteers.length > 0\r\n ? offer.attendees.map((id) => {\r\n const volunteer = group.volunteers.find(\r\n (volunteer) => volunteer.id === id\r\n );\r\n if(volunteer){\r\n const diet = volunteer.participation ? volunteer.participation.map((event) => event.eventId === this.props.offer.eventId && event.specialDiets ? this.getSpecialDiets(event, intl) : null) : null\r\n const shirt = volunteer.participation ? volunteer.participation.map((event) => event.eventId === this.props.offer.eventId && event.shirtSize ? event.shirtSize : null) : null\r\n const substitute = volunteer.participation ? volunteer.participation.map((event) => event.eventId === this.props.offer.eventId && event.substitute ? event.substitute : null) : null\r\n return {\r\n id: volunteer.id,\r\n name: volunteer.name,\r\n email: volunteer.email,\r\n phone: volunteer.phone,\r\n age: volunteer.age,\r\n specialDiets: diet,\r\n shirtSize: shirt,\r\n substitute: substitute,\r\n\r\n button: (\r\n this.deleteAttendees({ id: volunteer.id })}\r\n />\r\n ), // TODO\r\n };\r\n } else {\r\n this.deleteAttendees({ id });\r\n return undefined;\r\n }\r\n })\r\n : []\r\n ).filter((exist) => exist);\r\n\r\n return (\r\n \r\n {intl.formatMessage(messages.attendees.title)} {/* //TODO */}\r\n \r\n \r\n \r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nconst mapStateToProps = (state, ownProps) => ({\r\n ...ownProps,\r\n initialValues: state.offers.groupOffer,\r\n groupOffer: state.offers.groupOffer,\r\n group: state.group.group,\r\n groupOfferError: state.offers.groupOfferError,\r\n groupOfferAcceptError: state.offers.groupOfferAcceptError,\r\n groupOfferRejectError: state.offers.groupOfferRejectError,\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n updateOfferAttendees: (data) => dispatch(updateOfferAttendees(data)),\r\n submitGroup: (data) => dispatch(submitGroup(data)),\r\n fetchGroupOffers: (data) => dispatch(fetchGroupOffers(data)),\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(injectIntl(GroupAttendees));\r\n","import React, { Component, Fragment } from \"react\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport { Field, reduxForm } from \"redux-form\";\r\nimport messages from \"./messages\";\r\nimport { GeneralError } from \"../../../../components/index\";\r\nimport styled from \"styled-components\";\r\nimport { breakPoints } from \"../../../../constants/styling-constants\";\r\n\r\n\r\n\r\nimport {\r\n P,\r\n FormGroup,\r\n Input,\r\n TextSection,\r\n ContentWrapper,\r\n H2,\r\n Container,\r\n DatePicker,\r\n TextArea,\r\n ConfirmationModal,\r\n TextLabel\r\n} from \"../../../../components\";\r\nimport { BigGreenButton, BigGrayButton } from \"../../../../components/Buttons\";\r\nimport GroupAttendees from \"./GroupAttendees\";\r\nimport MapsComponent, { formatCoordinates } from '../../../../components/Map'\r\n\r\nconst MapsWrapper = styled.div`\r\n height: 500px;\r\n width: 600px;\r\n @media (max-width: ${breakPoints.sm}px) {\r\n width: 350px;\r\n height: 275px;\r\n }\r\n`;\r\n\r\nclass GroupEngagement extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n showConfirmModal: false,\r\n showRejectModal: false,\r\n confirming: false,\r\n rejecting: false\r\n };\r\n\r\n this.toggleConfirmModal = this.toggleConfirmModal.bind(this);\r\n this.toggleRejectModal = this.toggleRejectModal.bind(this);\r\n this.onConfirmOffer = this.onConfirmOffer.bind(this);\r\n this.onRejectOffer = this.onRejectOffer.bind(this);\r\n }\r\n\r\n componentDidMount() {\r\n this.props.fetchGroup({ id: this.props.match.params.groupId });\r\n this.props.fetchGroupOffers({\r\n\tgroupId: this.props.match.params.groupId,\r\n eventId: this.props.match.params.eventId,\r\n });\r\n this.props.fetchGroupOffer({\r\n eventId: this.props.match.params.eventId,\r\n\tstationId: this.props.match.params.stationId,\r\n\tgroupId: this.props.match.params.groupId,\r\n });\r\n }\r\n\r\n componentWillUnmount() {\r\n this.props.resetGroupOfferError();\r\n this.props.resetGroup();\r\n }\r\n\r\n componentWillReceiveProps(nextProps) {\r\n // Handle accept error\r\n if (!this.props.groupOfferAcceptError && nextProps.groupOfferAcceptError) {\r\n this.setState({\r\n showConfirmModal: false,\r\n confirming: false\r\n });\r\n }\r\n\r\n // Handle reject error\r\n if (!this.props.groupOfferRejectError && nextProps.groupOfferRejectError) {\r\n this.setState({\r\n showRejectModal: false,\r\n rejecting: false\r\n });\r\n }\r\n if (\r\n this.props.groupOffer &&\r\n this.props.groupOffer.status !== nextProps.groupOffer.status\r\n ) {\r\n this.setState({\r\n showRejectModal: false,\r\n rejecting: false,\r\n showConfirmModal: false,\r\n confirming: false\r\n });\r\n }\r\n }\r\n\r\n toggleConfirmModal() {\r\n this.setState({\r\n showConfirmModal: !this.state.showConfirmModal\r\n });\r\n }\r\n\r\n onConfirmOffer() {\r\n this.setState({\r\n confirming: true\r\n });\r\n\r\n this.props.acceptStationOffer({\r\n eventId: this.props.match.params.eventId,\r\n groupId: this.props.match.params.groupId,\r\n stationId: this.props.match.params.stationId\r\n });\r\n }\r\n\r\n toggleRejectModal() {\r\n this.setState({\r\n showRejectModal: !this.state.showRejectModal\r\n });\r\n }\r\n\r\n onRejectOffer() {\r\n this.setState({\r\n rejecting: true\r\n });\r\n\r\n this.props.rejectStationOffer({\r\n eventId: this.props.match.params.eventId,\r\n groupId: this.props.match.params.groupId,\r\n stationId: this.props.match.params.stationId\r\n });\r\n }\r\n\r\n renderAcceptError() {\r\n if (this.props.groupOfferAcceptError) {\r\n return (\r\n {this.props.groupOfferAcceptError.message} \r\n );\r\n }\r\n\r\n return null;\r\n }\r\n\r\n renderRejectError() {\r\n if (this.props.groupOfferRejectError) {\r\n return (\r\n {this.props.groupOfferRejectError.message} \r\n );\r\n }\r\n\r\n return null;\r\n }\r\n\r\n renderStatusBasedContent(status) {\r\n switch (status) {\r\n case \"REJECTED\":\r\n return (\r\n \r\n \r\n \r\n );\r\n case \"ACCEPTED\":\r\n return (\r\n \r\n \r\n \r\n );\r\n case \"PROPOSAL\":\r\n default:\r\n return (\r\n \r\n \r\n \r\n \r\n );\r\n }\r\n }\r\n\r\n\r\n renderContent() {\r\n const confirmText2 = this.props.intl.formatMessage(messages.confirmText2) === 'engagement-proposal.info.2' ? null : ;\r\n const confirmText3 = this.props.intl.formatMessage(messages.confirmText3) === 'engagement-proposal.info.3' ? null : ;\r\n\r\n if (this.props.groupOfferError) {\r\n return {this.props.groupOfferError.message} ;\r\n }\r\n if (!this.props.groupOffer) {\r\n return ;\r\n }\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {this.props.initialValues.station.markerLocation ? this.props.initialValues.station.markerLocation : \"\" } {/*TODO: messages.js */}\r\n \r\n \r\n {this.props.initialValues.station.markerCoordinates ? formatCoordinates(this.props.initialValues.station.markerCoordinates) : \"\" }\r\n \r\n {this.props.initialValues.station.markerCoordinates &&\r\n \r\n \r\n \r\n }\r\n
\r\n \r\n {this.props.groupOffer.station.skills ? \r\n this.props.intl.formatMessage({ id: `lists.skills.${skill}` })).join(\", \")}\r\n type=\"text\"\r\n placeholder={this.props.intl.formatMessage(\r\n messages.form.requiredSkills\r\n )}\r\n component={Input}\r\n readonly\r\n >\r\n \r\n : null }\r\n \r\n
\r\n {this.props.groupOffer.station.paymentType !== \"NOCOMPENSATION\" && (\r\n \r\n )}\r\n {this.props.groupOffer.station.paymentType === \"GROUPPAYMENT\" && (\r\n \r\n )}\r\n {(this.props.groupOffer.station.paymentType === \"PERPERSON\" ||\r\n this.props.groupOffer.station.paymentType === \"HOURLYRATE\") && (\r\n \r\n \r\n \r\n \r\n )}\r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n {confirmText2}\r\n
\r\n \r\n {confirmText3}\r\n
\r\n \r\n \r\n
\r\n \r\n \r\n {this.renderAcceptError()}\r\n {this.renderRejectError()}\r\n {this.renderStatusBasedContent(this.props.groupOffer.status)}\r\n \r\n
\r\n \r\n );\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n \r\n {this.renderContent()}\r\n {/* this.props.updateOfferAttendees(\r\n {eventId: this.props.groupOffer.eventId, \r\n groupId: this.props.groupOffer.groupId,\r\n stationId: this.props.groupOffer.stationId,\r\n attendees: [5069]})}\r\n label={this.props.intl.formatMessage(messages.rejectButton)}\r\n /> */}\r\n {this.props.groupOffer &&\r\n this.props.groupOffer.status === \"ACCEPTED\" && (\r\n \r\n )}\r\n\r\n \r\n }\r\n busy={this.state.confirming}\r\n />\r\n \r\n }\r\n busy={this.state.rejecting}\r\n />\r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nconst GroupEngagementWithForm = reduxForm({\r\n enableReinitialize: true,\r\n form: \"group-confirm\"\r\n})(GroupEngagement);\r\n\r\nexport default injectIntl(GroupEngagementWithForm);\r\n","import { connect } from \"react-redux\";\r\nimport GroupEngagement from \"./GroupEngagement\";\r\nimport { fetchGroupOffer, fetchGroupOffers, acceptStationOffer, rejectStationOffer, resetGroupOfferError, updateOfferAttendees } from \"../../Offer/reducer\";\r\nimport { fetchGroup, reset } from \"../reducer\";\r\n\r\nconst mapStateToProps = (state, ownProps) => ({\r\n ...ownProps,\r\n initialValues: state.offers.groupOffer,\r\n groupOffer: state.offers.groupOffer,\r\n groupOffers: state.offers.groupOffers,\r\n group: state.group.group,\r\n groupOfferError: state.offers.groupOfferError,\r\n groupOfferAcceptError: state.offers.groupOfferAcceptError,\r\n groupOfferRejectError: state.offers.groupOfferRejectError,\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n fetchGroupOffer: data => dispatch(fetchGroupOffer(data)),\r\n fetchGroupOffers: data => dispatch(fetchGroupOffers(data)),\r\n fetchGroup: data => dispatch(fetchGroup(data)),\r\n acceptStationOffer: data => dispatch(acceptStationOffer(data)),\r\n rejectStationOffer: data => dispatch(rejectStationOffer(data)),\r\n updateOfferAttendees: data => dispatch(updateOfferAttendees(data)),\r\n resetGroupOfferError: data => dispatch(resetGroupOfferError(data)),\r\n resetGroup: () => dispatch(reset())\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(GroupEngagement);\r\n\r\n","import React from 'react';\r\nimport {\r\n Switch,\r\n Route\r\n} from 'react-router-dom';\r\nimport VolunteerContextStart from './VolunteerContextStart';\r\nimport GroupBase from './GroupBase';\r\nimport GroupNewBase from './GroupNewBase';\r\n\r\nimport styled from 'styled-components';\r\nimport { colors } from '../../../constants/styling-constants';\r\nimport GroupEngagement from './GroupEngagement';\r\n\r\nconst Wrapper = styled.div`\r\n background-color: ${colors.lightGreen};\r\n flex: 1;\r\n`;\r\n\r\nconst VolunteerRouter = ({ match }) => {\r\n localStorage.setItem('homePath', 'volunteers');\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport default VolunteerRouter;\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n title: {\r\n id: 'team-leader-start.title',\r\n },\r\n text: {\r\n id: 'team-leader-start.text',\r\n },\r\n\r\n list: {\r\n title: {\r\n id: 'team-leader.list.title',\r\n },\r\n showButton: {\r\n id: 'team-leader.list.show-button',\r\n },\r\n confirmed: {\r\n id: 'team-leader.list.confirmed',\r\n },\r\n draft: {\r\n id: 'team-leader.list.draft',\r\n },\r\n noEvents: {\r\n id: 'team-leader.list.no-events',\r\n },\r\n },\r\n});\r\n","import React, { Component } from \"react\";\r\nimport styled from \"styled-components\";\r\nimport { H2, WhiteTableWithLastToRight, WhiteTable, TableStatus, TableRowWithClick, P, TableRow } from \"../../../../components/index\";\r\nimport { TableButton, ToggleButton } from \"../../../../components/Buttons/index\";\r\nimport { breakPoints } from \"../../../../constants/styling-constants\";\r\nimport messages from \"../messages\";\r\nimport eventMessages from \"../../Event/messages\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\n\r\nconst Wrapper = styled.div`\r\n margin-top: 90px;\r\n margin-bottom: 85px;\r\n`;\r\n\r\nconst Table = styled(WhiteTable)`\r\n @media (max-width: ${breakPoints.sm}px) {\r\n .table-button-col {\r\n display: none;\r\n }\r\n }\r\n`;\r\n\r\nconst TableRowHeader = TableRow.extend`\r\n th {\r\n background: transparent;\r\n font-weight: bold;\r\n }\r\n`;\r\n\r\nclass TeamLeaderList extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.renderRow = this.renderRow.bind(this);\r\n this.handleRowClick = this.handleRowClick.bind(this);\r\n this.togglePreviousEvents = this.togglePreviousEvents.bind(this);\r\n\r\n this.state = {\r\n sortField: \"date\",\r\n sortDirection: -1,\r\n pastEvents: false\r\n }\r\n }\r\n\r\n componentDidMount() {\r\n this.props.fetchTeamleaderEvents();\r\n }\r\n\r\n handleRowClick(row) {\r\n this.props.history.push(`/my-pages/teamleaders/${row.id}`);\r\n }\r\n\r\n getDate(date) {\r\n return date.getFullYear() + \"-\" + (date.getMonth()<9 ? \"0\" : \"\") + (date.getMonth()+1) + \"-\" + (date.getDate() <10 ? \"0\" : \"\") + date.getDate();\r\n }\r\n\r\n togglePreviousEvents() {\r\n this.setState({pastEvents: !this.state.pastEvents})\r\n }\r\n\r\n renderStatus(status) {\r\n switch (status) {\r\n case \"CONFIRMED\":\r\n return ( );\r\n case \"HISTORIC\":\r\n return ( );\r\n case \"DRAFT\":\r\n default:\r\n return ( );\r\n }\r\n }\r\n\r\n renderTableHeader() {\r\n return (\r\n \r\n this.state.sortField === \"name\" ? this.setState({sortDirection:this.state.sortDirection*-1}) : this.setState({sortField:\"name\"})}> \r\n this.state.sortField === \"date\" ? this.setState({sortDirection:this.state.sortDirection*-1}) : this.setState({sortField:\"date\"})}> \r\n this.state.sortField === \"status\" ? this.setState({sortDirection:this.state.sortDirection*-1}) : this.setState({sortField:\"status\"})}> \r\n \r\n \r\n )\r\n }\r\n\r\n renderRow(row) {\r\n return (\r\n \r\n {row.name} \r\n {row.date ? this.getDate(new Date(row.date)) : \"\"} \r\n {this.renderStatus(row.status)} \r\n \r\n \r\n );\r\n }\r\n\r\n renderTable(events, past=false) {\r\n if(events.length === 0) {\r\n // User has no events, show no events message\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n );\r\n }\r\n return (\r\n \r\n \r\n {this.renderTableHeader()}\r\n {events.sort((a,b) => a[this.state.sortField] ? -1 : 1).sort((a, b) => a && b && a[this.state.sortField] && b[this.state.sortField] ? this.state.sortDirection * a[this.state.sortField].localeCompare(b[this.state.sortField]) : 0).map(e => this.renderRow(e, past))}\r\n \r\n
\r\n );\r\n }\r\n\r\n render() {\r\n \r\n const eventList = this.props.eventsSummaries ? this.props.eventsSummaries.filter(event => !event.date ? false : new Date(event.date) > new Date().setDate(new Date().getDate() - 7)) : null;\r\n const pastList = this.props.eventsSummaries ? this.props.eventsSummaries.filter(event => !eventList.some(e => e.id === event.id)) : null;\r\n\r\n return (\r\n \r\n \r\n {(this.props.eventsSummaries) ? this.renderTable(eventList) : }\r\n {(this.props.eventsSummaries) ? : \"\"}\r\n {(pastList && this.state.pastEvents) ? this.renderTable(pastList, true) : \"\"}\r\n \r\n );\r\n }\r\n}\r\n\r\nexport default injectIntl(TeamLeaderList);\r\n","\r\nexport const TEAMLEADER_EVENTS_FETCH = 'TEAMLEADER_EVENTS_FETCH';\r\nexport const TEAMLEADER_EVENTS_SUCCESS = 'TEAMLEADER_EVENTS_SUCCESS';\r\nexport const TEAMLEADER_EVENTS_FAILED = 'TEAMLEADER_EVENTS_FAILED';\r\nexport const TEAMLEADER_EVENT_FETCH = 'TEAMLEADER_EVENT_FETCH';\r\nexport const TEAMLEADER_EVENT_SUCCESS = 'TEAMLEADER_EVENT_SUCCESS';\r\nexport const TEAMLEADER_EVENT_FAILED = 'TEAMLEADER_EVENT_FAILED';\r\nexport const TEAMLEADER_RESET = 'TEAMLEADER_RESET';\r\n\r\nexport const status = {\r\n INIT: 'INIT',\r\n FETCHING: 'FETCHING',\r\n FETCHED: 'FETCHED',\r\n FAILED: 'FAILED',\r\n};\r\n\r\nexport function fetchTeamleaderEvents () {\r\n return {\r\n type: TEAMLEADER_EVENTS_FETCH,\r\n };\r\n}\r\n\r\nexport function fetchTeamleaderEvent (data) {\r\n return {\r\n type: TEAMLEADER_EVENT_FETCH,\r\n payload: data\r\n };\r\n}\r\n\r\nexport function reset () {\r\n return {\r\n type: TEAMLEADER_RESET,\r\n };\r\n}\r\n\r\nconst initialState = {\r\n status: status.INIT,\r\n error: null,\r\n event: null,\r\n eventsSummaries: null,\r\n};\r\n\r\nexport default function teamleader(state = initialState, action) {\r\n if (!action) {\r\n return state;\r\n }\r\n\r\n switch (action.type) {\r\n case TEAMLEADER_EVENT_SUCCESS:\r\n return Object.assign({}, state, {event: action.payload, status: status.FETCHED});\r\n case TEAMLEADER_EVENT_FAILED:\r\n return Object.assign({}, state, {error: action.payload, status: status.FAILED});\r\n case TEAMLEADER_EVENT_FETCH:\r\n case TEAMLEADER_EVENTS_FETCH:\r\n return Object.assign({}, state, {status: status.FETCHING});\r\n case TEAMLEADER_EVENTS_SUCCESS:\r\n return Object.assign({}, state, {eventsSummaries: action.payload});\r\n case TEAMLEADER_EVENTS_FAILED:\r\n return Object.assign({}, state, {eventsSummaries: []});\r\n case TEAMLEADER_RESET:\r\n return initialState;\r\n default:\r\n return state;\r\n }\r\n}","import { connect } from \"react-redux\";\r\nimport TeamLeaderList from \"./TeamLeaderList\";\r\nimport { withRouter } from \"react-router\";\r\nimport { fetchTeamleaderEvents } from \"../reducer\";\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n fetchTeamleaderEvents: () => dispatch(fetchTeamleaderEvents()),\r\n});\r\n\r\nconst mapStateToProps = (state) => ({\r\n eventsSummaries: state.teamleader.eventsSummaries,\r\n});\r\n\r\nexport default withRouter(connect(\r\n mapStateToProps,\r\n mapDispatchToProps)(TeamLeaderList));\r\n","import React, { Component } from \"react\";\r\nimport { ContentWrapper, Container, H1, P } from \"../../../components/index\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport TopNavigation from \"../TopNavigation\";\r\nimport TeamLeaderList from \"./List\";\r\nimport messages from \"./messages\";\r\nimport { FormattedMessage } from \"react-intl\";\r\n\r\nclass TeamLeaderStart extends Component {\r\n render() {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n
\r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nexport default TeamLeaderStart;\r\n","import { connect } from \"react-redux\";\r\nimport EventBase from \"../../Event/Base/EventBase\";\r\nimport { withRouter } from \"react-router\";\r\nimport { fetchTeamleaderEvent, reset } from \"../reducer\";\r\n\r\nconst mapStateToProps = (state) => ({\r\n event: state.teamleader.event,\r\n error: state.teamleader.error,\r\n status: state.teamleader.status,\r\n isTeamleaderView: true,\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n fetchEvent: data => dispatch(fetchTeamleaderEvent(data)),\r\n reset: () => dispatch(reset({})),\r\n});\r\n\r\nexport default withRouter(connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(EventBase));\r\n","import React from 'react';\r\nimport {\r\n Switch,\r\n Route\r\n} from 'react-router-dom';\r\nimport TeamLeaderStart from './TeamLeaderStart';\r\nimport TeamLeaderEvent from './Event';\r\nimport styled from 'styled-components';\r\nimport { colors } from '../../../constants/styling-constants';\r\n\r\nconst Wrapper = styled.div`\r\n flex: 1;\r\n background-color: ${colors.lightPink};\r\n`;\r\n\r\nconst TeamLeaderRouter = ({ match }) => {\r\n localStorage.setItem('homePath', 'teamleaders');\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport default TeamLeaderRouter;\r\n","import React from 'react';\r\nimport {\r\n Switch,\r\n Route,\r\n Redirect\r\n} from 'react-router-dom';\r\nimport styled from 'styled-components';\r\nimport EventRouter from './Event/EventRouter';\r\nimport VolunteerContextRouter from './VolunteerContext/VolunteerContextRouter';\r\nimport TeamLeaderRouter from './TeamLeader/TeamLeaderRouter';\r\n//import Toolbar from '../../components/Toolbar';\r\n\r\nconst Wrapper = styled.div`\r\n position: relative;\r\n display: flex;\r\n flex: 1;\r\n`;\r\n\r\nconst MyPagesRouter = ({ match }) => {\r\n const defaultLocation = localStorage.getItem('homePath') || 'volunteers';\r\n return (\r\n \r\n {/* */}\r\n \r\n } />\r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport default MyPagesRouter;\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n link: {\r\n about: {\r\n id: 'footer.about-link',\r\n },\r\n faq: {\r\n id: 'footer.faq-link',\r\n },\r\n terms: {\r\n id: 'footer.terms-link',\r\n },\r\n personalData: {\r\n id: 'footer.personal-data-link',\r\n },\r\n contact: {\r\n id: 'footer.contact-link',\r\n },\r\n },\r\n copyRight: {\r\n id: 'footer.copy-right-text',\r\n },\r\n});\r\n","import React from 'react';\r\nimport styled from 'styled-components';\r\nimport { colors } from '../../constants/styling-constants';\r\nimport { Row, Col } from 'react-bootstrap/lib';\r\nimport { Container, FlexSpaceBetween, GrayLogo } from '../';\r\nimport { NavLink } from 'react-router-dom';\r\nimport { breakPoints } from '../../constants/styling-constants';\r\nimport messages from './messages';\r\nimport { FormattedMessage, injectIntl } from 'react-intl';\r\n\r\nconst Wrapper = styled.footer`\r\n background-color: ${colors.gray};\r\n padding: 40px 0 30px;\r\n flex-shrink: 0;\r\n`;\r\n\r\nconst MenuList = styled.ul`\r\n list-style: none;\r\n`;\r\n\r\nconst MenuItem = styled.li`\r\n display: inline-block;\r\n margin-right: 45px;\r\n @media (max-width: ${breakPoints.md}px) {\r\n margin-right: 25px;\r\n }\r\n @media (max-width: ${breakPoints.sm}px) {\r\n display: block;\r\n margin-top: 10px;\r\n }\r\n`;\r\n\r\nconst StyledLink = styled(NavLink)`\r\n font-size: 16px;\r\n color: ${colors.lightGray};\r\n text-transform: uppercase;\r\n &.active {\r\n color: ${colors.lightGray}\r\n }\r\n &:hover {\r\n text-decoration: none;\r\n color: ${colors.lightGray};\r\n }\r\n`;\r\n\r\nconst CopyRight = styled.p`\r\n color: ${colors.mediumLightGray};\r\n font-size: 13px;\r\n margin-top: 40px;\r\n`;\r\n\r\nconst SocialIcon = styled.i`\r\n font-size: 1.5em;\r\n color: white;\r\n`;\r\n\r\nconst IconLink = styled.a`\r\n &:not(:last-child) {\r\n margin-right: 35px;\r\n }\r\n &:last-child {\r\n margin-right: 12px;\r\n }\r\n`;\r\n\r\nconst FloatedDiv = styled.div`\r\n @media (min-width: ${breakPoints.sm}px) {\r\n float: right;\r\n }\r\n margin-top: 30px;\r\n`;\r\n\r\nconst FooterMenu = () => (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n);\r\n\r\nconst Footer = () => (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n
\r\n \r\n \r\n);\r\n\r\nexport default injectIntl(Footer);\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n title: {\r\n id: 'cookies.title',\r\n },\r\n text: {\r\n id: 'cookies.text',\r\n },\r\n button: {\r\n id: 'cookies.agree-button',\r\n },\r\n});","import React, { Fragment, Component } from \"react\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport messages from \"./messages\";\r\nimport styled from \"styled-components\";\r\nimport { colors } from \"../../constants/styling-constants\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport { Container, P, H2 } from \"../\";\r\nimport { SmallGreenButton } from \"../Buttons\";\r\n\r\nlet cookiesAgreed = localStorage.getItem(\"cookiesAgreed\");\r\ncookiesAgreed = JSON.parse(cookiesAgreed);\r\n\r\nconst Wrapper = styled.div`\r\n background-color: ${colors.lightGreen};\r\n position: fixed;\r\n width: 100%;\r\n bottom: 0;\r\n z-index: 9999;\r\n`;\r\n\r\nconst StyledTitle = styled(H2)`\r\n padding: 23px 0 0 0;\r\n margin-bottom: 10px;\r\n`;\r\n\r\nconst StyledButton = styled(SmallGreenButton)`\r\n margin: 0 0 20px 0;\r\n \r\n`;\r\n\r\nclass CookiesMessage extends Component {\r\n\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n cookiesAgreed: false,\r\n };\r\n\r\n this.handleSubmit = this.handleSubmit.bind(this);\r\n }\r\n\r\n componentWillMount() {\r\n if (cookiesAgreed) {\r\n this.setState({\r\n cookiesAgreed: true,\r\n });\r\n }\r\n }\r\n\r\n handleSubmit() {\r\n localStorage.setItem(\"cookiesAgreed\", true);\r\n this.setState({\r\n cookiesAgreed: true,\r\n });\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n {!this.state.cookiesAgreed\r\n ? (\r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n
\r\n \r\n )\r\n : null\r\n }\r\n \r\n );\r\n }\r\n\r\n}\r\n\r\nexport default injectIntl(CookiesMessage);\r\n","import { defineMessages } from \"react-intl\";\r\n\r\nexport default defineMessages({\r\n title: {\r\n id: 'self-registration.title'\r\n },\r\n info: {\r\n eventName:{\r\n id: 'self-registration.info.event-name'\r\n },\r\n foodOptionsTitle: {\r\n id: 'self-registration.info.food-options-title'\r\n },\r\n shirtSizesTitle: {\r\n id: 'self-registration.info.shirt-sizes-title'\r\n },\r\n },\r\n form: {\r\n submitButton: {\r\n id: 'self-registration.form.submit-button'\r\n },\r\n age: {\r\n id: 'self-registration.form.age'\r\n },\r\n phone: {\r\n id: 'self-registration.form.phone'\r\n },\r\n email: {\r\n id: 'self-registration.form.email'\r\n },\r\n name: {\r\n id: 'self-registration.form.name'\r\n },\r\n emailAlreadyExistError: {\r\n id: 'self-registration.form.email-already-exists-error'\r\n },\r\n substituteTitle: {\r\n id: 'self-registration.form.substitute-title'\r\n },\r\n substituteOption: {\r\n id: 'self-registration.form.substitute-option'\r\n },\r\n substituteField: {\r\n id: 'self-registration.form.substitute.placeholder'\r\n }\r\n },\r\n confirmationModal: {\r\n confirmButton: {\r\n id: 'self-registration.confirmation-modal.confirm-button'\r\n },\r\n cancelButton: {\r\n id: 'self-registration.confirmation-modal.cancel-button'\r\n },\r\n text: {\r\n id: 'self-registration.confirmation-modal.text'\r\n },\r\n title: {\r\n id: 'self-registration.confirmation-modal.title'\r\n }\r\n }\r\n\r\n\r\n})","import React, { useState, useEffect } from \"react\";\r\nimport { injectIntl, FormattedMessage } from \"react-intl\";\r\nimport { Field, reduxForm } from \"redux-form\";\r\nimport {\r\n required,\r\n email as emailValidator,\r\n integer,\r\n onlyNumbers,\r\n positiveNumbers,\r\n} from \"../../validators/index\";\r\nimport messages from \"./messages\";\r\nimport messagesVol from \"../MyPages/VolunteerContext/Volunteers/messages\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport {\r\n Input,\r\n FormSectionTitle,\r\n FormGroup,\r\n ListSelect,\r\n Select,\r\n GeneralError,\r\n P,\r\n H4,\r\n Checkbox,\r\n} from \"../../components\";\r\nimport { BigGreenButton } from \"../../components/Buttons/index\";\r\nimport { colors } from \"../../constants/styling-constants\";\r\nimport { ContentWrapper, Container, ConfirmationModal } from \"../../components\";\r\nimport styled from \"styled-components\";\r\nimport { v4 as uuidv4 } from \"uuid\";\r\nimport moment from \"moment\";\r\n\r\nconst Wrapper = styled.div`\r\n flex: 1;\r\n background-color: ${colors.lightGreen};\r\n width: 100%;\r\n`;\r\n\r\nconst SelfRegistrationForm = (props) => {\r\n const [showModal, setShowModal] = useState(false);\r\n const [data, setData] = useState({});\r\n const [showSuccess, setShowSuccess] = useState(false);\r\n const [busy, setBusy] = useState(false);\r\n const [substituteCheckbox, setSubstituteCheckbox] = useState(false);\r\n\r\n const handleConfirm = () => {\r\n setShowModal(false);\r\n return props.onSubmit(data);\r\n };\r\n\r\n const toggleModal = (e) => {\r\n e && e.preventDefault();\r\n setShowModal(!showModal);\r\n };\r\n\r\n const handleSubmit = (values) => {\r\n const id = uuidv4();\r\n const participation = []\r\n const participate = {eventId: props.event.eventId}\r\n\r\n\r\n if(values.shirtSize || values.specialDiets || values.substitute){\r\n if(!values.shirtSize){\r\n participate.specialDiets = values.specialDiets\r\n }\r\n else if(!values.specialDiets){\r\n participate.shirtSize = values.shirtSize\r\n }\r\n else{\r\n participate.specialDiets = values.specialDiets\r\n participate.shirtSize = values.shirtSize\r\n }\r\n\r\n if(values.substitute){\r\n participate.substitute = values.substitute\r\n }\r\n\r\n participation.push(participate)\r\n }\r\n \r\n const data = {\r\n volunteer: { ...values, id, participation },\r\n link: props.match.params.hash,\r\n };\r\n setShowModal(true);\r\n setData(data);\r\n };\r\n\r\n useEffect(() => {\r\n if (props.status === \"SUBMITTING\") setBusy(true);\r\n else setBusy(false);\r\n if (props.status === \"SUCCESS\") {\r\n setShowSuccess(true);\r\n setSubstituteCheckbox(false);\r\n props.reset();\r\n } else setShowSuccess(false);\r\n }, [props.status]);\r\n\r\n useEffect(() => {\r\n const eventId = props.match.params.eventId\r\n ? props.match.params.eventId\r\n : null;\r\n if (props.fetchStatus === \"NOT_FETCHING\" && eventId) {\r\n props.fetchEvent(eventId);\r\n }\r\n }, [props.fetchStatus, props.eventId]);\r\n\r\n const styleRow =\r\n typeof props.goBackToList === \"function\"\r\n ? { display: \"flex\", justifyContent: \"center\" }\r\n : {};\r\n\r\n const time = props.event\r\n ? moment(props.event.date).format(\"YYYY-MM-DD \")\r\n : \"\";\r\n\r\n const withLoadedProps = (LoadedComponent, loadedProps) => (props) =>\r\n ;\r\n\r\n const includedSpecialDietsTranslated =\r\n props.event && props.event.foodOptions\r\n ? props.event.foodOptions.map((opt) => ({\r\n id: opt,\r\n label: props.intl.formatMessage({\r\n id: `food.${opt.toLowerCase()}`,\r\n }),\r\n }))\r\n : null;\r\n const includedShirtSizesTranslated =\r\n props.event && props.event.shirtSizes\r\n ? props.event.shirtSizes.map((opt) => ({\r\n id: opt,\r\n label: props.intl.formatMessage({\r\n id: `shirt-size.${opt.toLowerCase()}`,\r\n }),\r\n }))\r\n : null;\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n {showSuccess ? Tack för din anmälan!
: null}\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport default reduxForm({\r\n form: \"SelfRegistration\",\r\n})(injectIntl(SelfRegistrationForm));\r\n","export const VOLUNTEER_SUBMIT = 'VOLUNTEER SUBMIT';\r\nexport const VOLUNTEER_SUCCESS = 'VOLUNTEER SUCCESS';\r\nexport const VOLUNTEER_FAILED = 'VOLUNTEER FAILED';\r\nexport const FETCH_FAILED = 'EVENT FETCH FAILED';\r\nexport const FETCHING = 'FETCHING EVENT'\r\nexport const FETCH_SUCCESS = 'EVENT FETCH SUCCESS'\r\n\r\nexport const status = {\r\n NOT_SUBMITTED: 'NOT_SUBMITTED',\r\n SUBMITTING: 'SUBMITTING',\r\n SUCCESS: 'SUCCESS',\r\n FAILED: 'FAILED',\r\n};\r\n\r\nexport const fetchStatus = {\r\n NOT_FETCHING: 'NOT_FETCHING',\r\n FETCHING: 'FETCHING',\r\n FETCH_SUCCESS: 'FETCH_SUCCESS',\r\n FETCH_FAILED: 'FETCH_FAILED',\r\n};\r\n\r\nexport function submitVolunteer(data) {\r\n return {\r\n type: VOLUNTEER_SUBMIT,\r\n payload: data,\r\n };\r\n};\r\n\r\nexport function fetchPublicEvent(eventId) {\r\n return {\r\n type: FETCHING,\r\n payload: eventId,\r\n };\r\n};\r\n\r\nconst initialState = {\r\n status: status.NOT_SUBMITTED,\r\n fetchStatus: fetchStatus.NOT_FETCHING,\r\n event: null,\r\n error: null,\r\n};\r\n\r\nexport default function selfRegistration(state = initialState, action) {\r\n if (!action) {\r\n return state;\r\n }\r\n \r\n switch (action.type) {\r\n case VOLUNTEER_SUBMIT:\r\n return Object.assign({}, state, {status: status.SUBMITTING, error: null});\r\n case VOLUNTEER_SUCCESS:\r\n return Object.assign({}, state, {status: status.SUCCESS, error: null});\r\n case VOLUNTEER_FAILED:\r\n return Object.assign({}, state, {status: status.FAILED, error: action.payload});\r\n case FETCHING:\r\n return Object.assign({}, state, {fetchStatus: fetchStatus.FETCHING, event:null});\r\n case FETCH_SUCCESS:\r\n return Object.assign({}, state, {fetchStatus: fetchStatus.FETCH_SUCCESS, event: action.payload});\r\n case FETCH_FAILED:\r\n return Object.assign({}, state, {fetchStatus: fetchStatus.FETCH_FAILED, error: action.payload, event:null});\r\n default: \r\n return state;\r\n };\r\n};","import { connect } from 'react-redux';\r\nimport SelfRegistrationForm from './SelfRegistrationForm';\r\nimport { fetchPublicEvent, submitVolunteer } from './reducer';\r\n\r\nconst mapStateToProps = ( state ) => {\r\n const obj = {\r\n status: state.selfRegistration.status,\r\n fetchStatus: state.selfRegistration.fetchStatus,\r\n formError: state.selfRegistration.error,\r\n event: state.selfRegistration.event,\r\n }\r\n return obj;\r\n};\r\n\r\nconst mapDispatchToProps = ( dispatch ) => ({\r\n onSubmit: data => dispatch(submitVolunteer(data)),\r\n fetchEvent: eventId => dispatch(fetchPublicEvent(eventId))\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(SelfRegistrationForm);\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n form: {\r\n firstName: {\r\n id: 'my-profile.form.firstName.placeholder',\r\n },\r\n lastName: {\r\n id: 'my-profile.form.lastName.placeholder',\r\n },\r\n email: {\r\n id: 'my-profile.form.email.placeholder',\r\n },\r\n phone: {\r\n id: 'my-profile.form.phone.placeholder',\r\n },\r\n countryCode: {\r\n id: 'register.form.countryCode.placeholder',\r\n },\r\n },\r\n title: {\r\n id: 'my-profile.title',\r\n },\r\n editButton: {\r\n id: 'my-profile.edit-profile-button',\r\n },\r\n saveButton: {\r\n id: 'my-profile.save-profile-button',\r\n },\r\n});\r\n","import React, { Component } from \"react\";\r\nimport { H2 } from \"../../../components/index\";\r\nimport { Field, reduxForm } from \"redux-form\";\r\nimport { required, minLength3 } from \"../../../validators\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport { FormGroup, Input, Select } from \"../../../components\";\r\nimport { SmallGrayButton, Button } from \"../../../components/Buttons\";\r\nimport messages from \"./messages\";\r\nimport { injectIntl } from \"react-intl\";\r\nimport { countryCodes } from \"../../../constants/country-codes\";\r\n\r\nclass MyProfile extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n readonly: true\r\n };\r\n\r\n this.toggleReadonly = this.toggleReadonly.bind(this);\r\n this.handleProfileSubmit = this.handleProfileSubmit.bind(this);\r\n }\r\n\r\n toggleReadonly(e) {\r\n if (e) {\r\n e.preventDefault();\r\n }\r\n\r\n this.setState({\r\n readonly: !this.state.readonly\r\n });\r\n }\r\n\r\n handleProfileSubmit(user) {\r\n this.props.onSubmit(user);\r\n this.toggleReadonly();\r\n }\r\n\r\n renderButtons() {\r\n if (this.state.readonly) {\r\n return (\r\n \r\n );\r\n }\r\n return (\r\n \r\n );\r\n }\r\n\r\n renderPhone() {\r\n if (this.state.readonly) {\r\n return (\r\n \r\n );\r\n } else {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n );\r\n }\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n );\r\n }\r\n}\r\n\r\nexport default reduxForm({\r\n form: \"myProfile\",\r\n enableReinitialize: true,\r\n destroyOnUnmount: false\r\n})(injectIntl(MyProfile));\r\n","import { connect } from \"react-redux\";\r\nimport { withRouter } from \"react-router\";\r\nimport MyProfile from \"./MyProfile\";\r\nimport { updateUserInfo } from \"../../../auth/reducer\";\r\nimport { countryCodes } from \"../../../constants/country-codes\";\r\n\r\n/**\r\n * Phone and country code are stored in a single field so\r\n * we need to split the phone into two seperate fields\r\n * that the user can update.\r\n *\r\n * @param user\r\n * @returns {*}\r\n */\r\nconst splitPhoneToCountryCodeAndPhone = (user) => {\r\n countryCodes.map(cc => {\r\n const index = user.phone.indexOf(cc);\r\n\r\n if (index !== -1) {\r\n user.countryCode = cc;\r\n user.phoneWithoutCountryCode = user.phone.substring(cc.length);\r\n }\r\n\r\n return cc;\r\n });\r\n return user;\r\n};\r\n\r\nconst mapStateToProps = state => {\r\n const initialValues = Object.assign({}, { countryCode: \"123\" }, state.auth.user);\r\n\r\n if (initialValues && initialValues.hasOwnProperty(\"phone\")) {\r\n initialValues.user = splitPhoneToCountryCodeAndPhone(initialValues);\r\n }\r\n\r\n return {\r\n auth: state.auth,\r\n initialValues: initialValues,\r\n }\r\n};\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n onSubmit: data => dispatch(updateUserInfo(data)),\r\n});\r\n\r\nexport default withRouter(connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(MyProfile));\r\n","import React, { Component } from \"react\";\r\nimport { Container, ContentWrapper } from \"../../../components/index\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport MyProfile from \"./\";\r\n\r\nimport { injectIntl } from \"react-intl\";\r\nimport styled from \"styled-components\";\r\nimport { colors } from \"../../../constants/styling-constants\";\r\n\r\nconst Wrapper = styled.div`\r\n flex: 1;\r\n background-color: ${colors.lightGray};\r\n width: 100%;\r\n`;\r\n\r\nclass MyProfileStart extends Component {\r\n render() {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nexport default injectIntl(MyProfileStart);\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n\twarning: {\r\n\t\tid: 'test-block.warning'\r\n\t},\r\n\tbutton: {\r\n\t\tid: 'test-block.button'\r\n\t},\r\n\tplaceholder: {\r\n\t\tid: 'test-block.placeholder'\r\n\t},\r\n});\r\n","import React from 'react';\r\nimport { P } from '../index';\r\nimport { Button } from '../Buttons';\r\nimport styled from 'styled-components';\r\nimport { injectIntl, FormattedMessage } from 'react-intl';\r\nimport messages from './messages';\r\n\r\nconst Wrapper = styled.div`\r\n\tposition: fixed;\r\n\theight: 100vh;\r\n\twidth: 100vw;\r\n\tbackground: white;\r\n\tz-index: 99999999999999999;\r\n\tdisplay: flex;\r\n\tflex-direction: row;\r\n\tjustify-content: center;\r\n`;\r\n\r\nconst RowWrapper = styled.div`\r\n\tdisplay: flex;\r\n\tflex-direction: column;\r\n\tjustify-content: center;\r\n`;\r\n\r\nconst TestWall = (props) => {\r\n\tconst handleSubmit = (value) => {\r\n\t\tif (value == \"test123\") {\r\n\t\t\tlocalStorage.setItem(\"testAcknowledged\", true);\r\n\t\t\tprops.update(true);\r\n\t\t}\r\n\t}\r\n\r\n\treturn (\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t
\r\n\t\t\t\t \r\n\t\t\t\t handleSubmit(document.getElementById(\"pass\").value)}\r\n\t\t\t\t\tlabel={props.intl.formatMessage(messages.button)\r\n\t\t\t\t}/>\r\n\t\t\t \r\n\t\t \r\n\t)\r\n}\r\n\r\nexport default injectIntl(TestWall);","import React, { useEffect, useState } from \"react\";\r\nimport Header from \"../Header\";\r\nimport { Route, Switch } from \"react-router-dom\";\r\nimport { PrivateRoute } from \"../\";\r\nimport Start from \"../../containers/Start\";\r\nimport HowItWorksVolunteer from \"../../containers/HowItWorksVolunteer\";\r\nimport HowItWorksOrganizer from \"../../containers/HowItWorksOrganizer\";\r\nimport FAQ from \"../../containers/FAQ\";\r\nimport About from \"../../containers/About\";\r\nimport PrivacyPolicy from \"../../containers/PrivacyPolicy\";\r\nimport Contact from \"../../containers/Contact\";\r\nimport Terms from \"../../containers/Terms\";\r\nimport MyPagesRouter from \"../../containers/MyPages/MyPagesRouter\";\r\nimport Footer from \"../../components/Footer\";\r\nimport styled from \"styled-components\";\r\nimport { connect } from \"react-redux\";\r\nimport { withRouter } from \"react-router\";\r\nimport Cookies from \"../../components/Cookies\";\r\nimport SelfRegistration from \"../../containers/SelfRegistration\";\r\nimport { authStoredUser } from \"../../auth/reducer\";\r\nimport MyProfileStart from \"../../containers/MyPages/MyProfile/MyProfileStart\";\r\nimport TestWall from \"../TestWall\";\r\n\r\n\r\nconst Wrapper = styled.div`\r\n display: flex;\r\n flex-direction: column;\r\n height: 100%;\r\n &.mobile-menu-open {\r\n overflow: hidden;\r\n }\r\n`;\r\n\r\n// Inner Wrapper used for Sticky Footer (https://css-tricks.com/couple-takes-sticky-footer/#article-header-id-3)\r\nconst InnerWrapper = styled.div`\r\n display: flex;\r\n flex-direction: column;\r\n flex: 1 0 auto;\r\n`;\r\n\r\nconst Main = (props) => {\r\n\r\n const [testAcknowledged, setTestAcknowledged] = useState(JSON.parse(localStorage.getItem(\"testAcknowledged\")));\r\n\r\n useEffect(() => {\r\n props.authStoredUser();\r\n });\r\n\r\n const renderApp = () => {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n }\r\n\r\n const stage = process.env.REACT_APP_STAGE || 'dev';\r\n if(stage === \"test\") {\r\n if (testAcknowledged)\r\n return renderApp();\r\n else\r\n return (\r\n \r\n );\r\n }\r\n else\r\n return renderApp();\r\n}\r\n\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n authStoredUser: data => dispatch(authStoredUser(data)),\r\n});\r\n\r\nconst mapStateToProps = state => ({\r\n showMobileMenu: state.menu.showMobileMenu,\r\n});\r\n\r\nexport default withRouter(connect(mapStateToProps, mapDispatchToProps)(Main));\r\n","import React from 'react';\r\nimport styled from 'styled-components';\r\nimport Logo from '../../../components/Logo';\r\nimport { Link } from 'react-router-dom';\r\nimport { breakPoints } from '../../../constants/styling-constants';\r\nimport img from '../../../images/Volex_bild_LoggaIn.jpg';\r\n\r\nconst ContentWrapper = styled.div`\r\n padding: 75px 0;\r\n min-height: 100%;\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n background-image: url(${img});\r\n background-size: cover;\r\n @media (max-width: ${breakPoints.sm}px) {\r\n height: 700px;\r\n }\r\n @media (max-width: ${breakPoints.xs}px) {\r\n font-size: 40px;\r\n height: 484px;\r\n }\r\n justify-content: center;\r\n text-align: center;\r\n`;\r\n\r\nconst InnerWrapper = styled.div`\r\n width: 530px;\r\n @media (max-width: ${breakPoints.xs}px) {\r\n width: 100%\r\n padding: 0 20px;\r\n }\r\n`;\r\n\r\nconst Center = styled.div`\r\n text-align: center;\r\n margin-bottom: 60px;\r\n`;\r\n\r\nconst Wrapper = ({children}) => (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {children}\r\n \r\n \r\n);\r\n\r\nexport default Wrapper;\r\n","import styled from 'styled-components';\r\n\r\nconst ButtonWrapper = styled.div`\r\n display: flex;\r\n justify-content: space-between;\r\n margin-bottom: 40px;\r\n @media (min-width: 500px) {\r\n button, a {\r\n width: 240px;\r\n }\r\n }\r\n`;\r\n\r\nexport default ButtonWrapper;\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n form: {\r\n email: {\r\n id: 'login.form.email.placeholder',\r\n },\r\n password: {\r\n id: 'login.form.password.placeholder',\r\n },\r\n },\r\n loginButton: {\r\n id: 'login.login-button',\r\n },\r\n registerButton: {\r\n id: 'login.register-button',\r\n },\r\n forgotPassword: {\r\n id: 'login.forgot-password.link',\r\n },\r\n error: {\r\n UserNotFoundException: {\r\n id: 'login.error.user-not-found',\r\n },\r\n ResourceNotFoundException: {\r\n id: 'login.error.cognito-service-not-found',\r\n },\r\n UserNotConfirmedException: {\r\n id: 'login.error.user-not-confirmed',\r\n },\r\n default: {\r\n id: 'login.error.unknown-error',\r\n },\r\n NotAuthorizedException: {\r\n id: 'login.error.wrong-password',\r\n },\r\n },\r\n resetPasswordInfo: {\r\n id: 'login.password-reset-info',\r\n }\r\n});\r\n","import React, { Component } from \"react\";\r\nimport { Redirect } from \"react-router-dom\";\r\nimport PropTypes from \"prop-types\";\r\nimport { Field, reduxForm } from \"redux-form\";\r\nimport { Input, WhiteP } from \"../../../components/index\";\r\nimport { SmallPinkButton } from \"../../../components/Buttons/index\";\r\nimport { SmallGrayLinkButton, WhiteLink } from \"../../../components/Links\";\r\nimport { status } from \"../../../auth/reducer\";\r\nimport { required } from \"../../../validators/index\";\r\nimport Wrapper from \"../Components/Wrapper\";\r\nimport ButtonWrapper from \"../Components/ButtonWrapper\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport messages from \"./messages\";\r\nimport connect from \"react-redux/lib/connect/connect\";\r\nimport { colors } from \"../../../constants/styling-constants\";\r\nimport styled from \"styled-components\";\r\n\r\nconst StyledError = styled.p`\r\n color: ${colors.pink};\r\n`;\r\n\r\nclass Login extends Component {\r\n renderError() {\r\n if (this.props.auth.status === status.LOGIN_FAILED) {\r\n // If UserNotConfirmedException, redirect to confirmation page\r\n if (this.props.auth.error.code === \"UserNotConfirmedException\") {\r\n return ;\r\n }\r\n\r\n let message = messages.error[this.props.auth.error.code];\r\n if (!message) {\r\n message = messages.error.default;\r\n console.warn(\"label not found for error:\", this.props.auth.error.code);\r\n }\r\n return ;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n renderResetPasswordText() {\r\n if (this.props.location.search && this.props.location.search.indexOf(\"password-reset\") > -1) {\r\n return ( )\r\n }\r\n\r\n return null;\r\n }\r\n\r\n render() {\r\n if (this.props.auth.status === status.LOGGED_IN) {\r\n // return ;\r\n return ;\r\n }\r\n if (this.props.auth.status === status.NEW_PASSWORD_REQUIRED) {\r\n return ;\r\n }\r\n return (\r\n \r\n {this.renderResetPasswordText()}\r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nLogin.propTypes = {\r\n auth: PropTypes.object.isRequired,\r\n handleSubmit: PropTypes.func.isRequired, // Redux form function that will call this.props.onSubmit if form is valid\r\n};\r\n\r\nlet LoginForm = reduxForm({\r\n form: \"login\",\r\n})(injectIntl(Login));\r\n\r\nLoginForm = connect(\r\n state => ({\r\n initialValues: {\r\n email: state.register.email,// || state.forgotPassword.email || '',\r\n password: state.register.password,// || state.forgotPassword.password || '',\r\n },\r\n })\r\n)(LoginForm);\r\n\r\nexport default LoginForm;\r\n","import { connect } from \"react-redux\";\r\nimport { loginSubmit } from \"../../../auth/reducer\";\r\nimport Login from \"./Login\";\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth,\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n onSubmit: data => dispatch(loginSubmit(data)),\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(Login);\r\n","\r\n// actions\r\nexport const REGISTER_SUBMIT = 'REGISTER_SUBMIT';\r\nexport const REGISTER_SUCCESS = 'REGISTER_SUCCESS';\r\nexport const REGISTER_FAILED = 'REGISTER_FAILED';\r\nexport const REGISTER_RESET = 'REGISTER_RESET';\r\n\r\nexport const status = {\r\n NOT_REGISTERED: 'NOT_REGISTERED',\r\n REGISTERING: 'REGISTERING',\r\n REGISTER_FAILED: 'REGISTER_FAILED',\r\n REGISTERED: 'REGISTERED',\r\n};\r\n\r\nexport function registerSubmit (data) {\r\n return {\r\n type: REGISTER_SUBMIT,\r\n payload: data,\r\n };\r\n}\r\n\r\nexport function reset () {\r\n return {\r\n type: REGISTER_RESET,\r\n };\r\n}\r\n\r\n// reducer with initial state\r\nconst initialState = {\r\n status: status.NOT_REGISTERED,\r\n email: '',\r\n password: '',\r\n};\r\n\r\nexport default function auth(state = initialState, action) {\r\n if (!action) {\r\n return state;\r\n }\r\n\r\n switch (action.type) {\r\n case REGISTER_SUBMIT:\r\n return Object.assign({}, state, {email: action.payload.email.toLowerCase(), password: action.payload.password, status: status.REGISTERING});\r\n case REGISTER_SUCCESS:\r\n return Object.assign({}, state, {status: status.REGISTERED});\r\n case REGISTER_FAILED:\r\n return Object.assign({}, state, {error: action.payload}, {status: status.REGISTER_FAILED});\r\n case REGISTER_RESET:\r\n return initialState;\r\n default:\r\n return state;\r\n }\r\n}\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n introText1: {\r\n id: 'register.intro-text-1',\r\n },\r\n introText2: {\r\n id: 'register.intro-text-2',\r\n },\r\n introText3: {\r\n id: 'register.intro-text-3',\r\n },\r\n form: {\r\n email: {\r\n id: 'register.form.email.placeholder',\r\n },\r\n firstName: {\r\n id: 'register.form.firstName.placeholder',\r\n },\r\n lastName: {\r\n id: 'register.form.lastName.placeholder',\r\n },\r\n countryCode: {\r\n id: 'register.form.countryCode.placeholder',\r\n },\r\n phone: {\r\n id: 'register.form.phone.placeholder',\r\n },\r\n password: {\r\n id: 'register.form.password.placeholder',\r\n },\r\n repeatPassword: {\r\n id: 'register.form.repeatPassword.placeholder',\r\n },\r\n },\r\n passwordRules: {\r\n title: {\r\n id: 'register.passwordRules.title',\r\n },\r\n lowerCase: {\r\n id: 'register.passwordRules.lowerCase',\r\n },\r\n upperCase: {\r\n id: 'register.passwordRules.upperCase',\r\n },\r\n number: {\r\n id: 'register.passwordRules.number',\r\n },\r\n length: {\r\n id: 'register.passwordRules.length',\r\n },\r\n },\r\n loginButton: {\r\n id: 'register.login-button',\r\n },\r\n registerButton: {\r\n id: 'register.register-button',\r\n },\r\n error: {\r\n UserNotFoundException: {\r\n id: 'login.error.user-not-found',\r\n },\r\n ResourceNotFoundException: {\r\n id: 'login.error.cognito-service-not-found',\r\n },\r\n UserNotConfirmedException: {\r\n id: 'login.error.user-not-confirmed',\r\n },\r\n InvalidParameterException: {\r\n id: 'login.error.invalid-parameter',\r\n },\r\n InvalidPhoneNumber: {\r\n id: 'login.error.invalid-phone-number',\r\n },\r\n default: {\r\n id: 'login.error.unknown-error',\r\n },\r\n },\r\n});\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n passwordRules: {\r\n title: {\r\n id: 'register.passwordRules.title',\r\n },\r\n lowerCase: {\r\n id: 'register.passwordRules.lowerCase',\r\n },\r\n upperCase: {\r\n id: 'register.passwordRules.upperCase',\r\n },\r\n number: {\r\n id: 'register.passwordRules.number',\r\n },\r\n length: {\r\n id: 'register.passwordRules.length',\r\n },\r\n },\r\n});\r\n","import React, { Fragment } from \"react\";\r\nimport styled from \"styled-components\";\r\nimport messages from \"./messages\";\r\nimport { colors } from \"../../../../constants/styling-constants\";\r\nimport { P } from \"../../../../components\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\n\r\nconst TextElement = styled(P)`\r\n color: ${props => props.color};\r\n font-size: ${props => props.fontSize};\r\n text-align: ${props => props.textAlign};\r\n padding-top: ${props => props.paddingTop};\r\n`;\r\n\r\nfunction containsNumber(string) {\r\n if (!string) return false;\r\n const numberRegEx = /[0-9]/g;\r\n return string.match(numberRegEx);\r\n}\r\n\r\nfunction containsUpperCase(string) {\r\n if (!string) return false;\r\n const upperCase = /^(?=.*[A-Z])/;\r\n return string.match(upperCase);\r\n}\r\n\r\nfunction containsLowerCase(string) {\r\n if (!string) return false;\r\n const lowerCase = /^(?=.*[a-z])/;\r\n return string.match(lowerCase);\r\n}\r\n\r\nfunction checkLength(string) {\r\n if (!string) return false;\r\n return string.length >= 8;\r\n}\r\n\r\nconst PasswordVerification = ({ password, intl }) => {\r\n\r\n return (\r\n \r\n {intl.formatMessage(messages.passwordRules.title)} \r\n \r\n \r\n {intl.formatMessage(messages.passwordRules.lowerCase)} \r\n {intl.formatMessage(messages.passwordRules.upperCase)} \r\n \r\n \r\n {intl.formatMessage(messages.passwordRules.number)} \r\n {intl.formatMessage(messages.passwordRules.length)} \r\n \r\n
\r\n \r\n );\r\n\r\n};\r\n\r\nexport default PasswordVerification;\r\n","import React, { Component } from \"react\";\r\nimport { Redirect } from \"react-router-dom\";\r\nimport PropTypes from \"prop-types\";\r\nimport { Field, reduxForm } from \"redux-form\";\r\nimport { Input, Select } from \"../../../components/index\";\r\nimport { SmallPinkButton } from \"../../../components/Buttons\";\r\nimport { SmallGrayLinkButton } from \"../../../components/Links\";\r\nimport { status } from \"./reducer\";\r\nimport { P } from \"../../../components\";\r\nimport { required, password } from \"../../../validators/index\";\r\nimport Wrapper from \"../Components/Wrapper\";\r\nimport ButtonWrapper from \"../Components/ButtonWrapper\";\r\nimport styled from \"styled-components\";\r\nimport { colors } from \"../../../constants/styling-constants\";\r\nimport { Row, Col } from \"react-bootstrap/lib\";\r\nimport messages from \"./messages\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport { countryCodes } from \"../../../constants/country-codes\";\r\nimport PasswordVerification from \"../Components/PasswordVerification\";\r\n\r\nconst TextElement = styled(P)`\r\n color: ${props => props.color};\r\n font-size: ${props => props.fontSize};\r\n text-align: ${props => props.textAlign};\r\n padding-top: ${props => props.paddingTop};\r\n`;\r\n\r\nconst StyledError = styled.p`\r\n color: ${colors.pink};\r\n`;\r\n\r\n\r\nconst validate = (values) => {\r\n const errors = {};\r\n\r\n if (values.password !== values.repeatPassword) {\r\n errors.repeatPassword = \"Lösenorden är inte likadana\";\r\n }\r\n\r\n return errors;\r\n};\r\n\r\nclass Register extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n password: null,\r\n };\r\n\r\n // this.passWordIsValid = this.passWordIsValid.bind(this);\r\n this.onPasswordChange = this.onPasswordChange.bind(this);\r\n }\r\n\r\n componentWillUnmount() {\r\n this.props.resetRegister();\r\n }\r\n\r\n // Wait and see if we need this logic\r\n /* passWordIsValid(password) {\r\n if (!password) return true;\r\n const testString = /^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$/;\r\n return !password.match(testString);\r\n }*/\r\n\r\n onPasswordChange(e, fieldValue) {\r\n this.setState({ password: fieldValue });\r\n }\r\n\r\n renderError() {\r\n if (this.props.status === status.REGISTER_FAILED) {\r\n let message = null;\r\n\r\n if (this.props.registerError.code === \"InvalidParameterException\" && this.props.registerError.message.indexOf(\"phone\") !== -1) {\r\n message = messages.error.InvalidPhoneNumber;\r\n } else {\r\n message = messages.error[this.props.registerError.code];\r\n }\r\n if (!message) {\r\n message = messages.error.default;\r\n console.warn(\"label not found for error:\", this.props.registerError.code);\r\n }\r\n return ;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n render() {\r\n if (this.props.status === status.REGISTERED) {\r\n return ;\r\n }\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nRegister.propTypes = {\r\n status: PropTypes.string.isRequired,\r\n handleSubmit: PropTypes.func.isRequired, // Redux form function that will call this.props.onSubmit if form is valid\r\n};\r\n\r\nexport default reduxForm({\r\n form: \"register\",\r\n validate,\r\n})(injectIntl(Register));\r\n","import { connect } from \"react-redux\";\r\nimport { registerSubmit, reset } from \"./reducer\";\r\nimport Register from \"./Register\";\r\n\r\nconst mapStateToProps = state => ({\r\n status: state.register.status,\r\n registerError: state.register.error,\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n onSubmit: data => dispatch(registerSubmit(data)),\r\n resetRegister: () => dispatch(reset()),\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(Register);\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n form: {\r\n email: {\r\n id: 'login.form.email.placeholder',\r\n },\r\n verificationCode: {\r\n id: 'login.form.verificationCode.placeholder',\r\n },\r\n },\r\n popupReminder: {\r\n title: {\r\n id: 'register.verificationReminder.title'\r\n },\r\n body: {\r\n id: 'register.verificationReminder.body'\r\n }\r\n },\r\n confirmRegistrationButtom: {\r\n id: 'login.confirm-registration-button',\r\n },\r\n resendConfirmationCodeButton: {\r\n id: 'login.resend-cofirmation-code-button',\r\n },\r\n error: {\r\n UserNotFoundException: {\r\n id: 'login.error.user-not-found',\r\n },\r\n ResourceNotFoundException: {\r\n id: 'login.error.cognito-service-not-found',\r\n },\r\n UserNotConfirmedException: {\r\n id: 'login.error.user-not-confirmed',\r\n },\r\n CodeMismatchException: {\r\n id: 'login.error.code-mismatch',\r\n },\r\n default: {\r\n id: 'login.error.unknown-error',\r\n },\r\n activationCodeError: {\r\n id: 'register.error.activation-code-error',\r\n }\r\n },\r\n});\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n modalConfirmButtonText: {\r\n id: 'message.modal-confirm-button.text',\r\n }\r\n});\r\n","import React from 'react';\r\nimport { Modal } from 'react-bootstrap/lib';\r\nimport { MediumGrayButton, SmallPinkButton, SmallGreenButton } from '../Buttons';\r\nimport { H2, P } from '../index';\r\nimport styled from 'styled-components';\r\nimport { colors } from '../../constants/styling-constants';\r\nimport messages from './messages';\r\nimport { FormattedMessage, injectIntl } from 'react-intl';\r\n\r\nexport const ModalWrapper = styled(Modal)`\r\n .modal-dialog {\r\n max-width: 530px;\r\n }\r\n .modal-content {\r\n border-radius: 0;\r\n padding: 30px;\r\n }\r\n`;\r\n\r\nexport const Content = styled.section`\r\n text-align: center;\r\n padding: 0 15px;\r\n i {\r\n color: ${colors.pink};\r\n font-size: 110px;\r\n margin-bottom: 25px;\r\n }\r\n`;\r\n\r\nexport const Footer = styled.footer`\r\n display: flex;\r\n justify-content: center;\r\n padding: 0 15px;\r\n`;\r\n\r\nconst renderConfirmButton = (theme, label, busy, handleConfirm) => {\r\n switch(theme) {\r\n case 'pink':\r\n return ;\r\n case 'green':\r\n return ;\r\n case 'gray':\r\n return ;\r\n default:\r\n return ;\r\n }\r\n};\r\n\r\nconst ReminderModal = (\r\n {\r\n show,\r\n handleHide,\r\n title = '',\r\n buttonText = ,\r\n text = '',\r\n busy = false,\r\n theme = 'gray',\r\n handleConfirm = handleHide\r\n }) => (\r\n \r\n \r\n \r\n {title} \r\n {text}
\r\n \r\n \r\n {renderConfirmButton(theme, buttonText, busy, handleConfirm)}\r\n \r\n \r\n \r\n);\r\n\r\nexport default injectIntl(ReminderModal);\r\n","import React, { Component } from \"react\";\r\nimport { Redirect } from \"react-router-dom\";\r\nimport PropTypes from \"prop-types\";\r\nimport { Field, reduxForm } from \"redux-form\";\r\nimport { Input } from \"../../../components/index\";\r\nimport { SmallPinkButton, SmallGrayButton } from \"../../../components/Buttons/index\";\r\nimport { status } from \"../../../auth/reducer\";\r\nimport { required } from \"../../../validators/index\";\r\nimport Wrapper from \"../Components/Wrapper\";\r\nimport ButtonWrapper from \"../Components/ButtonWrapper\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport messages from \"./messages\";\r\nimport { connect } from \"react-redux\";\r\nimport styled from \"styled-components\";\r\nimport { colors } from \"../../../constants/styling-constants\";\r\nimport ReminderModal from \"../../../components/ReminderModal\";\r\n\r\nconst formId = \"confirm-registration\";\r\n\r\nconst StyledError = styled.p`\r\n color: ${colors.pink};\r\n`;\r\n\r\nclass ConfirmRegistration extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n showReminderModal: true\r\n };\r\n this.hideReminderModal = this.hideReminderModal.bind(this);\r\n this.resendConfirmationCode = this.resendConfirmationCode.bind(this);\r\n }\r\n\r\n hideReminderModal() {\r\n this.setState({\r\n showReminderModal: false\r\n });\r\n }\r\n\r\n renderError() {\r\n if (this.props.auth.status === status.VERIFYING_FAILED) {\r\n let message = messages.error[this.props.auth.error.code];\r\n if (!message) {\r\n message = messages.error.default;\r\n console.warn(\"label not found for error:\", this.props.auth.error.code);\r\n }\r\n return ;\r\n }\r\n return null;\r\n }\r\n\r\n renderActivationCodeError() {\r\n if (this.props.auth.activationCodeStatus === status.SENT_FAILED) {\r\n return ;\r\n }\r\n return null;\r\n }\r\n\r\n resendConfirmationCode() {\r\n const { email } = this.props.fieldValues;\r\n this.props.resendConfirmationCode({ email });\r\n }\r\n\r\n render() {\r\n if (this.props.auth.status === status.VERIFYING_SUCCESS) {\r\n return ;\r\n }\r\n return (\r\n \r\n this.hideReminderModal()} \r\n />\r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nConfirmRegistration.propTypes = {\r\n auth: PropTypes.object.isRequired,\r\n handleSubmit: PropTypes.func.isRequired, // Redux form function that will call this.props.onSubmit if form is valid\r\n resendConfirmationCode: PropTypes.func.isRequired,\r\n};\r\n\r\nlet ConfirmationRegistrationForm = reduxForm({\r\n form: formId,\r\n})(injectIntl(ConfirmRegistration));\r\n\r\nConfirmationRegistrationForm = connect(\r\n state => ({\r\n initialValues: {\r\n email: state.register.email,// || state.forgotPassword.email || '',\r\n },\r\n })\r\n)(ConfirmationRegistrationForm);\r\n\r\nexport default ConfirmationRegistrationForm;\r\n","import { connect } from \"react-redux\";\r\nimport { confirmRegistration, resendConfirmationCode } from \"../../../auth/reducer\";\r\nimport ConfirmRegistration from \"./ConfirmRegistration\";\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth,\r\n\r\n // figure a better way to expose form values to props\r\n fieldValues: state.form[\"confirm-registration\"] ? state.form[\"confirm-registration\"].values : {},\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n onSubmit: data => dispatch(confirmRegistration(data)),\r\n resendConfirmationCode: data => dispatch(resendConfirmationCode(data)),\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(ConfirmRegistration);\r\n","export const FORGOT_PASSWORD_CODE_SEND = \"FORGOT_PASSWORD_CODE_SEND\";\r\nexport const FORGOT_PASSWORD_CODE_FAILED = \"FORGOT_PASSWORD_CODE_FAILED\";\r\nexport const FORGOT_PASSWORD_CODE_SUCCESS = \"FORGOT_PASSWORD_CODE_SUCCESS\";\r\nexport const RESET_PASSWORD = \"RESET_PASSWORD\";\r\nexport const RESET_PASSWORD_STATE = \"RESET_PASSWORD_STATE\";\r\nexport const RESET_PASSWORD_SUCCESS = \"RESET_PASSWORD_SUCCESS\";\r\nexport const RESET_PASSWORD_FAILED = \"RESET_PASSWORD_FAILED\";\r\nexport const FORGOT_PASSWORD_CODE_RESET_SUCCESS =\r\n \"FORGOT_PASSWORD_CODE_RESET_SUCCESS\";\r\n\r\nexport function sendForgotPasswordCode(data) {\r\n return {\r\n type: FORGOT_PASSWORD_CODE_SEND,\r\n payload: data\r\n };\r\n}\r\n\r\nexport function resetPasswordSubmit(data) {\r\n return {\r\n type: RESET_PASSWORD,\r\n payload: data\r\n };\r\n}\r\n\r\nexport function resetState(data) {\r\n return {\r\n type: RESET_PASSWORD_STATE\r\n };\r\n}\r\n\r\nexport const status = {\r\n CODE_NOT_SENT: \"CODE_NOT_SENT\",\r\n CODE_SENT: \"CODE_SENT\",\r\n NEW_PASSWORD_SET: \"NEW_PASSWORD_SET\"\r\n};\r\n\r\nexport const status2 = status;\r\n\r\nconst initialState = {\r\n error: null,\r\n status: status.CODE_NOT_SENT\r\n};\r\n\r\nconst stateToUse = initialState;\r\n\r\nexport default function forgotPassword(state = stateToUse, action) {\r\n if (!action) {\r\n return state;\r\n }\r\n\r\n switch (action.type) {\r\n case FORGOT_PASSWORD_CODE_RESET_SUCCESS:\r\n return Object.assign({}, state, {\r\n status: status.CODE_NOT_SENT,\r\n error: null\r\n });\r\n case RESET_PASSWORD_SUCCESS:\r\n return Object.assign({}, state, {\r\n status: status.NEW_PASSWORD_SET,\r\n error: null\r\n });\r\n case RESET_PASSWORD_FAILED:\r\n return Object.assign({}, state, { error: action.error });\r\n case FORGOT_PASSWORD_CODE_SUCCESS:\r\n return Object.assign({}, state, {\r\n status: status.CODE_SENT,\r\n error: null\r\n });\r\n case FORGOT_PASSWORD_CODE_FAILED:\r\n return Object.assign({}, state, {\r\n error: { ...action.payload },\r\n status: action.type\r\n });\r\n default:\r\n return state;\r\n }\r\n}\r\n","import { defineMessages } from \"react-intl\";\r\n\r\nexport default defineMessages({\r\n explainingMessage: {\r\n id: \"reset-password.explaining-messsage\"\r\n },\r\n email: {\r\n placeholder: {\r\n id: \"reset-password.email.placeholder\"\r\n }\r\n },\r\n code: {\r\n placeholder: {\r\n id: \"reset-password.code.placeholder\"\r\n }\r\n },\r\n password: {\r\n placeholder: {\r\n id: \"reset-password.new-password.placeholder\"\r\n }\r\n },\r\n verifyModal: {\r\n title: {\r\n id: \"reset-password.verify-modal.title\"\r\n },\r\n body: {\r\n id: \"reset-password.verify-modal.body\"\r\n },\r\n redirectButton: {\r\n id: \"reset-password.verify-modal.button\"\r\n }\r\n },\r\n sendCodeButton: {\r\n id: \"reset-password.sendCode.button\"\r\n },\r\n loginButton: {\r\n id: \"reset-password.backToLogin.button\"\r\n },\r\n codeSent: {\r\n id: \"reset-password.code-sent\"\r\n },\r\n UserNotFoundException: {\r\n id: \"login.error.user-not-found\"\r\n },\r\n InvalidParameterException: {\r\n id: \"login.error.user-not-verified\"\r\n },\r\n LimitExceededException: {\r\n id: \"login.error.limit-exceeded\"\r\n },\r\n genericError: {\r\n id: \"login.error.generic-error\"\r\n }\r\n});\r\n","import React, { Component } from \"react\";\r\nimport { Redirect } from \"react-router-dom\";\r\nimport PropTypes from \"prop-types\";\r\nimport { Field, reduxForm } from \"redux-form\";\r\nimport { Input, WhiteP } from \"../../../components/index\";\r\nimport { SmallPinkButton } from \"../../../components/Buttons\";\r\nimport { SmallGrayLinkButton } from \"../../../components/Links\";\r\nimport { required } from \"../../../validators/index\";\r\nimport Wrapper from \"../Components/Wrapper\";\r\nimport ButtonWrapper from \"../Components/ButtonWrapper\";\r\nimport ReminderModal from \"../../../components/ReminderModal\";\r\nimport messages from \"./messages\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport { status } from \"./reducer\";\r\nimport { colors } from \"../../../constants/styling-constants\";\r\nimport styled from \"styled-components\";\r\n\r\nconst StyledError = styled.p`\r\n color: ${colors.pink};\r\n`;\r\n\r\nclass ForgotPassword extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.handleSubmit = this.handleSubmit.bind(this);\r\n this.handleHideModal = this.handleHideModal.bind(this);\r\n this.props.resetState();\r\n this.state = {\r\n showModal: null,\r\n verifyRedirect: false\r\n };\r\n }\r\n\r\n handleHideModal() {\r\n this.setState({\r\n showModal: false\r\n });\r\n }\r\n\r\n renderError() {\r\n if (!this.props.submitError) return null;\r\n\r\n const errorMessage = messages[this.props.submitError.code];\r\n const message = errorMessage || messages.genericError;\r\n\r\n if (this.props.submitError.code === \"InvalidParameterException\" && this.state.showModal == null) {\r\n this.setState({\r\n showModal: true\r\n });\r\n }\r\n\r\n return (\r\n \r\n \r\n \r\n );\r\n }\r\n\r\n handleSubmit(data) {\r\n if (this.props.status === status.CODE_SENT) {\r\n this.props.resetPasswordSubmit(data);\r\n } else {\r\n this.props.sendForgotPasswordCode(data);\r\n }\r\n }\r\n\r\n render() {\r\n if (this.props.status === status.NEW_PASSWORD_SET) {\r\n return ;\r\n }\r\n if (this.state.verifyRedirect) {\r\n return ;\r\n }\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nForgotPassword.propTypes = {\r\n handleSubmit: PropTypes.func.isRequired, // Redux form function that will call this.props.onSubmit if form is valid\r\n status: PropTypes.string.isRequired\r\n};\r\n\r\nexport default injectIntl(\r\n reduxForm({\r\n form: \"forgotPassword\"\r\n })(ForgotPassword)\r\n);\r\n","import { connect } from \"react-redux\";\r\nimport {\r\n resetPasswordSubmit,\r\n sendForgotPasswordCode,\r\n resetState\r\n} from \"./reducer\";\r\nimport ForgotPassword from \"./ForgotPassword\";\r\n\r\nconst mapStateToProps = state => {\r\n return {\r\n submitError: state.forgotPassword.error,\r\n status: state.forgotPassword.status\r\n };\r\n};\r\n\r\nconst mapDispatchToProps = dispatch => ({\r\n resetPasswordSubmit: data => dispatch(resetPasswordSubmit(data)),\r\n sendForgotPasswordCode: data => dispatch(sendForgotPasswordCode(data)),\r\n resetState: data => dispatch(resetState(data))\r\n});\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(ForgotPassword);\r\n","import { defineMessages } from 'react-intl';\r\n\r\nexport default defineMessages({\r\n form: {\r\n email: {\r\n id: 'change-password.form.email.placeholder',\r\n },\r\n newPassword: {\r\n id: 'change-password.form.new-password.placeholder',\r\n },\r\n },\r\n loginButton: {\r\n id: 'change-password.login-button',\r\n },\r\n changePasswordButton: {\r\n id: 'change-password.change-password-button',\r\n },\r\n forgotPassword: {\r\n id: 'login.forgot-password.link',\r\n },\r\n error: {\r\n UserNotFoundException: {\r\n id: 'login.error.user-not-found',\r\n },\r\n ResourceNotFoundException: {\r\n id: 'login.error.cognito-service-not-found',\r\n },\r\n UserNotConfirmedException: {\r\n id: 'login.error.user-not-confirmed',\r\n },\r\n default: {\r\n id: 'login.error.unknown-error',\r\n },\r\n NotAuthorizedException: {\r\n id: 'login.error.wrong-password',\r\n },\r\n InvalidPasswordException: {\r\n id: 'change-password.error.password-does-not-meet-policy',\r\n }\r\n },\r\n infoText: {\r\n id: 'change-password.info-text',\r\n }\r\n});\r\n","import React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport connect from \"react-redux/lib/connect/connect\";\r\nimport { Field, reduxForm } from \"redux-form\";\r\nimport { FormattedMessage, injectIntl } from \"react-intl\";\r\nimport { Input, WhiteP } from \"../../../components/index\";\r\nimport Wrapper from \"../Components/Wrapper\";\r\nimport messages from \"./messages\";\r\nimport { required } from \"../../../validators/index\";\r\nimport PasswordVerification from \"../Components/PasswordVerification\";\r\nimport ButtonWrapper from \"../Components/ButtonWrapper\";\r\nimport { SmallPinkButton, SmallGrayButton } from \"../../../components/Buttons\";\r\nimport { status } from \"../../../auth/reducer\";\r\nimport { colors } from \"../../../constants/styling-constants\";\r\nimport styled from \"styled-components\";\r\nimport { Redirect } from \"react-router-dom\";\r\n\r\nconst StyledError = styled.p`\r\n color: ${colors.pink};\r\n`;\r\n\r\nclass ChangePassword extends Component {\r\n\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n password: \"\",\r\n };\r\n\r\n this.onPasswordChange = this.onPasswordChange.bind(this);\r\n this.goToLogin = this.goToLogin.bind(this);\r\n }\r\n\r\n onPasswordChange(e, fieldValue) {\r\n this.setState({ password: fieldValue });\r\n }\r\n\r\n goToLogin() {\r\n this.props.resetAuth();\r\n this.props.history.push(\"/login\");\r\n }\r\n\r\n renderError() {\r\n if (this.props.auth.status === status.CHANGE_PASSWORD_FAILED) {\r\n let message = messages.error[this.props.auth.error.code];\r\n if (!message) {\r\n message = messages.error.default;\r\n console.warn(\"label not found for error:\", this.props.auth.error.code);\r\n }\r\n return ;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n render() {\r\n if (!this.props.auth.user) {\r\n return ;\r\n }\r\n if (this.props.auth.status === status.LOGGED_IN) {\r\n return ;\r\n }\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n );\r\n }\r\n\r\n}\r\n\r\nChangePassword.propTypes = {\r\n auth: PropTypes.object.isRequired,\r\n handleSubmit: PropTypes.func.isRequired, // Redux form function that will call this.props.onSubmit if form is valid\r\n};\r\n\r\nlet ChangePasswordForm = reduxForm({\r\n form: \"change-password\",\r\n})(injectIntl(ChangePassword));\r\n\r\nChangePasswordForm = connect(\r\n state => ({\r\n initialValues: {\r\n user: state.auth.user,\r\n },\r\n })\r\n)(ChangePasswordForm);\r\n\r\nexport default ChangePasswordForm;\r\n","import { connect } from \"react-redux\";\r\nimport { changePassword, reset } from \"../../../auth/reducer\";\r\nimport ChangePassword from \"./ChangePassword\";\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth,\r\n});\r\n\r\nconst mapDispatchToProps = (dispatch) => ({\r\n onSubmit: data => dispatch(changePassword(data)),\r\n resetAuth: () => dispatch(reset()),\r\n});\r\n\r\nexport default connect(\r\n mapStateToProps,\r\n mapDispatchToProps\r\n)(ChangePassword);\r\n","import React, { Component } from 'react';\r\nimport { Route, Switch } from 'react-router-dom';\r\nimport Main from './components/Main';\r\nimport Login from './containers/User/Login';\r\nimport Register from './containers/User/Register';\r\nimport ConfirmRegistration from './containers/User/ConfirmRegistration';\r\nimport ForgotPassword from './containers/User/ForgotPassword';\r\nimport ChangePassword from './containers/User/ChangePassword';\r\n\r\nclass App extends Component {\r\n render() {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nexport default App;\r\n","/* eslint-disable */\r\n// In production, we register a service worker to serve assets from local cache.\r\n\r\n// This lets the app load faster on subsequent visits in production, and gives\r\n// it offline capabilities. However, it also means that developers (and users)\r\n// will only see deployed updates on the \"N+1\" visit to a page, since previously\r\n// cached resources are updated in the background.\r\n\r\n// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.\r\n// This link also includes instructions on opting out of this behavior.\r\n\r\nconst isLocalhost = Boolean(\r\n window.location.hostname === 'localhost' ||\r\n // [::1] is the IPv6 localhost address.\r\n window.location.hostname === '[::1]' ||\r\n // 127.0.0.1/8 is considered localhost for IPv4.\r\n window.location.hostname.match(\r\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\r\n )\r\n);\r\n\r\nexport default function register() {\r\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\r\n // The URL constructor is available in all browsers that support SW.\r\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location);\r\n if (publicUrl.origin !== window.location.origin) {\r\n // Our service worker won't work if PUBLIC_URL is on a different origin\r\n // from what our page is served on. This might happen if a CDN is used to\r\n // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374\r\n return;\r\n }\r\n\r\n window.addEventListener('load', () => {\r\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\r\n\r\n if (isLocalhost) {\r\n // This is running on localhost. Lets check if a service worker still exists or not.\r\n checkValidServiceWorker(swUrl);\r\n\r\n // Add some additional logging to localhost, pointing developers to the\r\n // service worker/PWA documentation.\r\n navigator.serviceWorker.ready.then(() => {\r\n console.log(\r\n 'This web app is being served cache-first by a service ' +\r\n 'worker. To learn more, visit https://goo.gl/SC7cgQ'\r\n );\r\n });\r\n } else {\r\n // Is not local host. Just register service worker\r\n registerValidSW(swUrl);\r\n }\r\n });\r\n }\r\n}\r\n\r\nfunction registerValidSW(swUrl) {\r\n navigator.serviceWorker\r\n .register(swUrl)\r\n .then((registration) => {\r\n registration.onupdatefound = () => {\r\n const installingWorker = registration.installing;\r\n installingWorker.onstatechange = () => {\r\n if (installingWorker.state === 'installed') {\r\n if (navigator.serviceWorker.controller) {\r\n // At this point, the old content will have been purged and\r\n // the fresh content will have been added to the cache.\r\n // It's the perfect time to display a \"New content is\r\n // available; please refresh.\" message in your web app.\r\n console.log('New content is available; please refresh.');\r\n } else {\r\n // At this point, everything has been precached.\r\n // It's the perfect time to display a\r\n // \"Content is cached for offline use.\" message.\r\n console.log('Content is cached for offline use.');\r\n }\r\n }\r\n };\r\n };\r\n })\r\n .catch((error) => {\r\n console.error('Error during service worker registration:', error);\r\n });\r\n}\r\n\r\nfunction checkValidServiceWorker(swUrl) {\r\n // Check if the service worker can be found. If it can't reload the page.\r\n fetch(swUrl)\r\n .then((response) => {\r\n // Ensure service worker exists, and that we really are getting a JS file.\r\n if (\r\n response.status === 404 ||\r\n response.headers.get('content-type').indexOf('javascript') === -1\r\n ) {\r\n // No service worker found. Probably a different app. Reload the page.\r\n navigator.serviceWorker.ready.then((registration) => {\r\n registration.unregister().then(() => {\r\n window.location.reload();\r\n });\r\n });\r\n } else {\r\n // Service worker found. Proceed as normal.\r\n registerValidSW(swUrl);\r\n }\r\n })\r\n .catch(() => {\r\n console.log(\r\n 'No internet connection found. App is running in offline mode.'\r\n );\r\n });\r\n}\r\n\r\nexport function unregister() {\r\n if ('serviceWorker' in navigator) {\r\n navigator.serviceWorker.ready.then((registration) => {\r\n registration.unregister();\r\n });\r\n }\r\n}\r\n/* eslint-enable */\r\n","import {Component} from 'react';\r\nimport { withRouter } from 'react-router-dom';\r\n\r\nclass ScrollToTop extends Component {\r\n\r\n componentDidUpdate(prevProps) {\r\n if (this.props.location !== prevProps.location) {\r\n window.scrollTo(0, 0);\r\n }\r\n }\r\n\r\n render() {\r\n return this.props.children;\r\n }\r\n}\r\n\r\nexport default withRouter(ScrollToTop);","import { Auth } from 'aws-amplify';\r\n\r\n// Auth.signIn stores token in Auth singleton, all API calls\r\n// using API from aws-amplify will get right token automatically\r\nexport function login ({email, password}) {\r\n return Auth.signIn(email.toLowerCase(), password)\r\n .then((user) => {\r\n return user;\r\n });\r\n}\r\n\r\nexport function confirmRegistration ({email, verificationCode}) {\r\n return Auth.confirmSignUp(email.toLowerCase(), verificationCode)\r\n .then((resp) => {\r\n return resp;\r\n });\r\n}\r\n\r\nexport function resendConfirmationCode ({email}) {\r\n return Auth.resendSignUp(email.toLowerCase());\r\n}\r\n\r\nexport function logout () {\r\n return Auth.signOut();\r\n}\r\n\r\nexport function loadAuthenticatedUser () {\r\n return Auth.currentAuthenticatedUser();\r\n}\r\n\r\nexport function loadUserInfo () {\r\n return Auth.currentUserInfo()\r\n .then(resp => ({\r\n firstName: resp.attributes.given_name,\r\n lastName: resp.attributes.family_name,\r\n email: resp.attributes.email.toLowerCase(),\r\n phone: resp.attributes.phone_number,\r\n emailVerified: resp.attributes.email_verified,\r\n phoneNumberVerified: resp.attributes.phone_number_verified,\r\n }));\r\n}\r\n\r\nexport function updateUserAttributes ({firstName, lastName, countryCode, phoneWithoutCountryCode, email}) {\r\n const phoneWithCountryCode = countryCode + ((phoneWithoutCountryCode.substr(0,1) === '0') ? phoneWithoutCountryCode.substr(1) : phoneWithoutCountryCode);\r\n\r\n return Auth.currentUserPoolUser()\r\n .then(user => Auth.updateUserAttributes(user, {\r\n given_name: firstName,\r\n family_name: lastName,\r\n phone_number: phoneWithCountryCode,\r\n email: email.toLowerCase()\r\n }));\r\n}\r\n\r\nexport function changePassword ({user, newPassword}) {\r\n return Auth.completeNewPassword(user, newPassword)\r\n .then(user => {\r\n return user;\r\n });\r\n}\r\n","import { call, put } from 'redux-saga/effects';\r\nimport {\r\n LOGIN_SUCCESS,\r\n LOGIN_FAILED,\r\n NEW_PASSWORD_REQUIRED,\r\n LOGOUT_SUCCESS,\r\n LOGOUT_FAILED,\r\n AUTH_STORED_USER_FAILED,\r\n REGISTRATION_CONFIRM_SUCCESS,\r\n REGISTRATION_CONFIRM_FAILED,\r\n GET_USER_INFO_SUCCESS,\r\n GET_USER_INFO_FAILED,\r\n UPDATE_USER_INFO_SUCCESS,\r\n UPDATE_USER_INFO_FAILED,\r\n GET_USER_INFO,\r\n CHANGE_PASSWORD_FAILED,\r\n REGISTRATION_RESEND_CODE_SUCCESS,\r\n REGISTRATION_RESEND_CODE_FAILED,\r\n} from './reducer';\r\nimport { login, logout, loadAuthenticatedUser, confirmRegistration, resendConfirmationCode, loadUserInfo, updateUserAttributes, changePassword } from './service';\r\n\r\n// payload is an object where code is an exception in https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/cognitoidp/model/AWSCognitoIdentityProviderException.html\r\n\r\nexport function* loginSaga (action) {\r\n try {\r\n const response = yield call(() => login(action.payload));\r\n if (response.challengeName === 'NEW_PASSWORD_REQUIRED') {\r\n yield put({type: NEW_PASSWORD_REQUIRED, payload: { user: response, email: action.payload.email.toLowerCase() }});\r\n } else {\r\n yield put({type: LOGIN_SUCCESS, payload: response});\r\n }\r\n } catch (e) {\r\n yield put({type: LOGIN_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* resendConfirmationSaga (action) {\r\n try {\r\n const response = yield call(() => resendConfirmationCode(action.payload));\r\n yield put({type: REGISTRATION_RESEND_CODE_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: REGISTRATION_RESEND_CODE_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* confirmRegistrationSaga (action) {\r\n try {\r\n const response = yield call(() => confirmRegistration(action.payload));\r\n yield put({type: REGISTRATION_CONFIRM_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: REGISTRATION_CONFIRM_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* logoutSaga () {\r\n try {\r\n const response = yield call(() => logout());\r\n yield put({type: LOGOUT_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: LOGOUT_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* loadAuthenticatedUserSaga () {\r\n try {\r\n const response = yield call(() => loadAuthenticatedUser());\r\n yield put({type: LOGIN_SUCCESS, payload: response});\r\n } catch (e) {\r\n // has not signed in\r\n yield put({type: AUTH_STORED_USER_FAILED, payload: null});\r\n }\r\n}\r\n\r\nexport function* getUserInfoSaga () {\r\n try {\r\n const response = yield call(() => loadUserInfo());\r\n yield put({type: GET_USER_INFO_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: GET_USER_INFO_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* updateUserInfo (action) {\r\n try {\r\n const response = yield call(() => updateUserAttributes(action.payload));\r\n yield put({type: UPDATE_USER_INFO_SUCCESS, payload: response});\r\n yield put({type: GET_USER_INFO});\r\n } catch (e) {\r\n yield put({type: UPDATE_USER_INFO_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* changePasswordSaga (action) {\r\n try {\r\n const response = yield call(() => changePassword(action.payload));\r\n yield put({type: LOGIN_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: CHANGE_PASSWORD_FAILED, payload: e});\r\n }\r\n}\r\n","import { Auth } from 'aws-amplify';\r\n\r\nexport const register = data => new Promise(((resolve, reject) => {\r\n setTimeout(() => {\r\n resolve({\r\n user: {\r\n name: 'Staffan',\r\n },\r\n });\r\n }, 1000);\r\n}));\r\n\r\nexport const signUp = (data) => {\r\n const {\r\n email,\r\n firstName,\r\n lastName,\r\n countryCode,\r\n phone,\r\n password,\r\n } = data;\r\n\r\n const phoneWithCountryCode = countryCode + ((phone.substr(0,1) === '0') ? phone.substr(1) : phone);\r\n\r\n return Auth\r\n .signUp({\r\n username: email.toLowerCase(),\r\n password,\r\n attributes: {\r\n email: email.toLowerCase(),\r\n phone_number: phoneWithCountryCode,\r\n given_name: firstName,\r\n family_name: lastName,\r\n },\r\n custom: {\r\n language: 'sv', // this shall be retrieved from store\r\n },\r\n })\r\n .then((data) => {\r\n return data;\r\n });\r\n};\r\n","import { call, put } from 'redux-saga/effects';\r\nimport { REGISTER_SUCCESS, REGISTER_FAILED } from './reducer';\r\nimport { signUp } from './service';\r\n\r\nexport function* registerSaga(action) {\r\n try {\r\n const response = yield call(() => signUp(action.payload));\r\n yield put({type: REGISTER_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: REGISTER_FAILED, payload: e});\r\n }\r\n}\r\n","\r\nimport { Auth, API } from 'aws-amplify';\r\n\r\n/* export const createGroup = data => new Promise(((resolve, reject) => {\r\n setTimeout(() => {\r\n resolve();\r\n }, 2000);\r\n}));*/\r\n\r\nexport const createGroup = data =>\r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n body: data,\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.post('volex-protected', '/groups', request);\r\n });\r\n\r\nexport const updateGroup = data =>\r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n body: data,\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.put('volex-protected', `/groups/${data.id}`, request);\r\n });\r\n\r\nexport const getGroupsSummaries = () => \r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.get('volex-protected', '/groups/summaries', request);\r\n });\r\n\r\nexport const fetchGroup = ({id}) => \r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.get('volex-protected', `/groups/${id}`, request);\r\n });\r\n\r\nexport const confirmGroup = data =>\r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n body: {},\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.post('volex-protected', `/groups/${data.id}/confirm`, request);\r\n });\r\n","import { Auth, API } from 'aws-amplify';\r\n\r\n// TODO get current session from store\r\nexport const createEvent = data =>\r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n body: data,\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.post('volex-protected', '/events', request);\r\n });\r\n\r\nexport const updateEvent = data =>\r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n body: data,\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.put('volex-protected', `/events/${data.id}`, request);\r\n });\r\n\r\nexport const confirmEvent = data =>\r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n body: {},\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.post('volex-protected', `/events/${data.id}/confirm`, request);\r\n });\r\n\r\nexport const getEventsSummaries = () =>\r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.get('volex-protected', '/events/summaries', request);\r\n });\r\n\r\nexport const removeEvent = (id) =>\r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.del('volex-protected', `/events/${id}`, request);\r\n });\r\n\r\nexport const fetchEvent = ({id}) =>\r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.get('volex-protected', `/events/${id}`, request);\r\n });\r\n\r\nexport const fetchPublicEvent = ({id}) =>\r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.get('volex-protected', `/public/events/${id}`, request);\r\n });\r\n\r\nexport const setHistoric = ({id}) =>\r\n Auth.currentSession()\r\n .then((session) =>{\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.put('volex-protected', `/events/${id}/historic`, request);\r\n });\r\n\r\nexport const getEventsByDateRange = ({startDate, endDate}) =>\r\n API.get('volex-protected', `/public/events?startDate=${startDate}&endDate=${endDate}`);\r\n","import { call, put } from 'redux-saga/effects';\r\nimport { GROUP_SUCCESS, GROUP_FAILED, GROUP_FETCHED, GROUPS_SUMMARIES_FAILED, GROUPS_SUMMARIES_SUCCESS, FETCH_PUBLIC_EVENTS_SUCCESS, FETCH_PUBLIC_EVENTS_FAILED, GROUP_CONFIRM_SUCCESS, GROUP_CONFIRM_FAILED, FETCH_COMPLETE_EVENT_SUCCESS, FETCH_COMPLETE_EVENT_FAILED } from './reducer';\r\nimport { createGroup, updateGroup, fetchGroup as getGroup, getGroupsSummaries, confirmGroup } from './service';\r\nimport { getEventsByDateRange, fetchPublicEvent } from '../Event/service';\r\n\r\nexport function* groupSaga(action) {\r\n try {\r\n const response = action.payload.id ? yield call(() => updateGroup(action.payload)) : yield call(() => createGroup(action.payload));\r\n yield put({type: GROUP_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: GROUP_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* fetchGroup(action) {\r\n try {\r\n const response = yield call(() => getGroup(action.payload));\r\n yield put({type: GROUP_FETCHED, payload: response});\r\n } catch (e) {\r\n yield put({type: GROUP_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* fetchGroupsSummaries (action) {\r\n try {\r\n const response = yield call(() => getGroupsSummaries(action.payload));\r\n yield put({type: GROUPS_SUMMARIES_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: GROUPS_SUMMARIES_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* fetchPublicEvents (action) {\r\n try {\r\n const response = yield call(() => getEventsByDateRange(action.payload));\r\n yield put({type: FETCH_PUBLIC_EVENTS_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: FETCH_PUBLIC_EVENTS_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* confirmGroupSaga (action) {\r\n try {\r\n const response = yield call(() => confirmGroup(action.payload));\r\n yield put({type: GROUP_CONFIRM_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: GROUP_CONFIRM_FAILED, payload: e});\r\n }\r\n}\r\n\r\n\r\nexport function* fetchCompleteEvent (action) {\r\n try {\r\n const response = yield call(() => fetchPublicEvent(action.payload));\r\n yield put({type: FETCH_COMPLETE_EVENT_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: FETCH_COMPLETE_EVENT_FAILED, payload: e});\r\n }\r\n}","import { call, put } from 'redux-saga/effects';\r\nimport { EVENT_SUCCESS, EVENT_FAILED, EVENT_FETCHED, EVENTS_SUMMARIES_FAILED, EVENTS_SUMMARIES_SUCCESS, EVENT_CONFIRM_FAILED, EVENT_CONFIRM_SUCCESS, EVENT_REMOVE_FAILED, EVENT_REMOVE_SUCCESS, SET_HISTORIC, SET_HISTORIC_FAILED, SET_HISTORIC_SUCCESS } from './reducer';\r\nimport { updateEvent, fetchEvent as getEvent, createEvent, getEventsSummaries, confirmEvent, removeEvent as deleteEvent, setHistoric as makeHistoric } from './service';\r\n\r\nexport function* saveEvent (action) {\r\n try {\r\n const response = action.payload.id ? yield call(() => updateEvent(action.payload)) : yield call(() => createEvent(action.payload));\r\n response.id = response.eventId\r\n yield put({type: EVENT_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: EVENT_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* confirmEventSaga (action) {\r\n try {\r\n const response = action.payload.id ? yield call(() => confirmEvent(action.payload)) : yield call(() => createEvent(action.payload));\r\n response.id = response.eventId\r\n yield put({type: EVENT_CONFIRM_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: EVENT_CONFIRM_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* fetchEventsSummaries (action) {\r\n try {\r\n const response = yield call(() => getEventsSummaries(action.payload)); \r\n yield put({type: EVENTS_SUMMARIES_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: EVENTS_SUMMARIES_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* fetchEvent (action) {\r\n try {\r\n const response = yield call(() => getEvent(action.payload));\r\n yield put({type: EVENT_FETCHED, payload: response});\r\n } catch (e) {\r\n yield put({type: EVENT_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* removeEvent (action) {\r\n try {\r\n const response = yield call(() => deleteEvent(action.payload));\r\n response.eventId = action.payload;\r\n yield put({type: EVENT_REMOVE_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: EVENT_REMOVE_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* setHistoric (action) {\r\n try {\r\n const response = yield call(() => makeHistoric(action.payload));\r\n yield put({type: SET_HISTORIC_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: SET_HISTORIC_FAILED, payload: e});\r\n }\r\n}","import { Auth } from 'aws-amplify';\r\n\r\nexport function sendForgotPasswordCode ({email}) {\r\n return Auth.forgotPassword(email.toLowerCase());\r\n}\r\n\r\nexport function resetPassword ({email, code, newPassword}) {\r\n return Auth.forgotPasswordSubmit(email.toLowerCase(), code, newPassword);\r\n}\r\n","import { sendForgotPasswordCode, resetPassword } from \"./service\";\r\nimport { call, put } from \"redux-saga/effects\";\r\nimport {\r\n FORGOT_PASSWORD_CODE_FAILED,\r\n FORGOT_PASSWORD_CODE_SUCCESS,\r\n RESET_PASSWORD_SUCCESS,\r\n RESET_PASSWORD_FAILED,\r\n FORGOT_PASSWORD_CODE_RESET_SUCCESS\r\n} from \"./reducer\";\r\n\r\nexport function* forgotPasswordSaga(action) {\r\n try {\r\n const response = yield call(() => sendForgotPasswordCode(action.payload));\r\n yield put({ type: FORGOT_PASSWORD_CODE_SUCCESS, payload: response });\r\n } catch (e) {\r\n yield put({ type: FORGOT_PASSWORD_CODE_FAILED, payload: e });\r\n }\r\n}\r\n\r\nexport function* forgotPasswordResetSaga(action) {\r\n try {\r\n yield put({ type: FORGOT_PASSWORD_CODE_RESET_SUCCESS, payload: null });\r\n } catch (e) {\r\n yield put({ type: FORGOT_PASSWORD_CODE_RESET_SUCCESS, payload: null });\r\n }\r\n}\r\n\r\nexport function* resetPasswordSaga(action) {\r\n try {\r\n const response = yield call(() => resetPassword(action.payload));\r\n yield put({ type: RESET_PASSWORD_SUCCESS, payload: response });\r\n } catch (e) {\r\n yield put({ type: RESET_PASSWORD_FAILED, payload: e });\r\n }\r\n}\r\n","import { call, put } from 'redux-saga/effects';\r\nimport { FETCH_CALENDAR_EVENTS_SUCCESS, FETCH_CALENDAR_EVENTS_FAILED } from './reducer';\r\nimport { getEventsByDateRange } from '../MyPages/Event/service';\r\n\r\nexport function* fetchCalendarEvents (action) {\r\n try {\r\n const response = yield call(() => getEventsByDateRange(action.payload));\r\n yield put({type: FETCH_CALENDAR_EVENTS_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: FETCH_CALENDAR_EVENTS_FAILED, payload: e});\r\n }\r\n}\r\n","import { Auth, API } from 'aws-amplify';\r\n\r\nexport const putGroupAvailabilities = data =>\r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n body: data.availabilities,\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.put('volex-protected', `/groups/${data.groupId}/availabilities`, request);\r\n });\r\n\r\nexport const getGroupAvailability = ({groupId}) =>\r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.get('volex-protected', `/groups/${groupId}/availabilities`, request);\r\n });\r\n\r\nexport const getAvailableGroups = data => \r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n const queryParameters = new URLSearchParams();\r\n Object.keys(data).forEach((key) => {\r\n queryParameters.append(key, data[key]);\r\n });\r\n return API.get('volex-protected', `/groups/available?${queryParameters.toString()}`, request);\r\n });\r\n","import { call, put } from 'redux-saga/effects';\r\nimport { GROUP_AVAIL_SAVE_SUCCESS, GROUP_AVAIL_SAVE_FAILED, GROUP_AVAIL_FETCH_SUCCESS, GROUP_AVAIL_FETCH_FAILED } from './reducer';\r\nimport { putGroupAvailabilities, getGroupAvailability } from './service';\r\n\r\nexport function* saveGroupAvailabilitySaga (action) {\r\n try {\r\n const response = yield call(() => putGroupAvailabilities(action.payload));\r\n yield put({type: GROUP_AVAIL_SAVE_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: GROUP_AVAIL_SAVE_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* getGroupAvailabilitySaga (action) {\r\n try {\r\n const response = yield call(() => getGroupAvailability(action.payload));\r\n yield put({type: GROUP_AVAIL_FETCH_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: GROUP_AVAIL_FETCH_FAILED, payload: e});\r\n }\r\n}\r\n","import { Auth, API } from \"aws-amplify\";\r\n\r\nexport const fetchGroupOffers = ({ groupId, eventId }) =>\r\n Auth.currentSession().then(session => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken\r\n }\r\n };\r\n return API.get(\"volex-protected\", eventId ? `/groups/${groupId}/offers?eventId=${eventId}` : `/groups/${groupId}/offers`, request);\r\n });\r\n\r\nexport const fetchGroupOffer = ({ eventId, stationId, groupId }) =>\r\n Auth.currentSession().then(session => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken\r\n }\r\n };\r\n return API.get(\r\n \"volex-protected\",\r\n `/offers/groups/${groupId}/${eventId}/${stationId}`,\r\n request\r\n );\r\n });\r\n\r\nexport const fetchEventOffers = ({ eventId }) =>\r\n Auth.currentSession().then(session => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken\r\n }\r\n };\r\n return API.get(\"volex-protected\", `/events/${eventId}/offers`, request);\r\n });\r\n\r\nexport const fetchStationOffers = ({ eventId, stationId }) =>\r\n Auth.currentSession().then(session => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken\r\n }\r\n };\r\n return API.get(\r\n \"volex-protected\",\r\n `/offers/station/${eventId}/${stationId}`,\r\n request\r\n );\r\n });\r\n\r\nexport const fetchAllOffers = () =>\r\n Auth.currentSession().then(session => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken\r\n }\r\n };\r\n return API.get(\"volex-protected\", \"/offers\", request);\r\n });\r\n\r\nexport const fetchGroupsOffers = () =>\r\n Auth.currentSession().then(session => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken\r\n }\r\n };\r\n return API.get(\"volex-protected\", \"/offers/groups\", request);\r\n });\r\n\r\nexport const fetchAvailableGroups = params => {\r\n const searchParams = new URLSearchParams();\r\n Object.keys(params).forEach(param =>\r\n searchParams.append(param, params[param])\r\n );\r\n return Auth.currentSession().then(session => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken\r\n }\r\n };\r\n return API.get(\r\n \"volex-protected\",\r\n `/groups/available?${searchParams.toString()}`,\r\n request\r\n );\r\n });\r\n};\r\n\r\nexport const createOffer = data =>\r\n Auth.currentSession().then(session => {\r\n const request = {\r\n body: data,\r\n headers: {\r\n Authorization: session.idToken.jwtToken\r\n }\r\n };\r\n return API.post(\"volex-protected\", \"/offers\", request);\r\n });\r\n\r\nexport const deleteOffer = data =>\r\n Auth.currentSession().then(session => {\r\n const request = {\r\n body: data,\r\n headers: {\r\n Authorization: session.idToken.jwtToken\r\n }\r\n };\r\n return API.del(\r\n \"volex-protected\",\r\n `/offers/${data.eventId}/${data.groupId}/${data.stationId}`,\r\n request\r\n );\r\n });\r\n\r\nexport const confirmStationOffers = data =>\r\n Auth.currentSession().then(session => {\r\n const request = {\r\n body: data,\r\n headers: {\r\n Authorization: session.idToken.jwtToken\r\n }\r\n };\r\n return API.post(\r\n \"volex-protected\",\r\n `/offers/${data.eventId}/confirm`,\r\n request\r\n );\r\n });\r\n\r\nexport const acceptGroupOffer = data =>\r\n Auth.currentSession().then(session => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken\r\n }\r\n };\r\n return API.post(\r\n \"volex-protected\",\r\n `/offers/${data.eventId}/${data.groupId}/${data.stationId}/accept`,\r\n request\r\n );\r\n });\r\n\r\nexport const rejectGroupOffer = data =>\r\n Auth.currentSession().then(session => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken\r\n }\r\n };\r\n return API.post(\r\n \"volex-protected\",\r\n `/offers/${data.eventId}/${data.groupId}/${data.stationId}/reject`,\r\n request\r\n );\r\n });\r\n\r\nexport const sendOfferReminder = data =>\r\n Auth.currentSession().then(session => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken\r\n }\r\n };\r\n return API.post(\r\n \"volex-protected\",\r\n `/offers/${data.eventId}/send-reminder`,\r\n request\r\n );\r\n });\r\n\r\nexport const updateOfferAttendees = data =>\r\n Auth.currentSession().then(session => {\r\n const request = {\r\n body: data,\r\n headers: {\r\n Authorization: session.idToken.jwtToken\r\n }\r\n };\r\n return API.post(\r\n \"volex-protected\",\r\n `/offers/groups/${data.groupId}/${data.eventId}/${data.stationId}`,\r\n request\r\n );\r\n });\r\n\r\nexport const createLink = data => \r\n Auth.currentSession().then(session => {\r\n const request = {\r\n body: data,\r\n headers: {\r\n Authorization: session.idToken.jwtToken\r\n }\r\n };\r\n return API.post(\r\n \"volex-protected\",\r\n `/link`,\r\n request\r\n );\r\n });\r\n\r\n// comment out when Paul prepares the endpoint\r\n\r\n// export const sendOfferInvitation = data =>\r\n// Auth.currentSession()\r\n// .then((session) => {\r\n// const request = {\r\n// headers: {\r\n// Authorization: session.idToken.jwtToken,\r\n// },\r\n// };\r\n// return API.post(\"volex-protected\", `/offers/${data.eventId}/send-invitation`, request);\r\n// });\r\n","import { call, put } from 'redux-saga/effects';\r\nimport { GROUP_OFFER_FETCH, UPDATE_OFFER_ATTENDEES_FAILED, GROUP_OFFERS_FETCH_SUCCESS, GROUP_OFFERS_FETCH_FAILED, GROUP_OFFER_FETCH_SUCCESS, GROUP_OFFER_FETCH_FAILED, ALL_OFFERS_FETCH_FAILED, ALL_OFFERS_FETCH_SUCCESS, EVENT_OFFERS_FETCH_SUCCESS, EVENT_OFFERS_FETCH_FAILED, AVAILABLE_GROUPS_FETCH_SUCCESS, AVAILABLE_GROUPS_FETCH_FAILED, OFFER_CREATE_FAILED, OFFER_CREATE_SUCCESS, GROUPS_OFFERS_FETCH_SUCCESS, GROUPS_OFFERS_FETCH_FAILED, EVENT_OFFERS_FETCH, CONFIRM_STATION_OFFERS_SUCCESS, CONFIRM_STATION_OFFERS_FAILED, ACCEPT_STATION_OFFER_SUCCESS, ACCEPT_STATION_OFFER_FAILED, REJECT_STATION_OFFER_SUCCESS, REJECT_STATION_OFFER_FAILED, DELETE_OFFER_SUCCESS, DELETE_OFFER_FAILED, STATION_OFFERS_FETCH_SUCCESS, STATION_OFFERS_FETCH_FAILED, SEND_OFFER_REMINDER_SUCCESS, SEND_OFFER_REMINDER_FAILED, CREATE_SELF_REGISTRATION_LINK_SUCCESS, CREATE_SELF_REGISTRATION_LINK_FAIL } from './reducer';\r\nimport { fetchGroupOffers, fetchGroupOffer, fetchAllOffers, fetchEventOffers, fetchAvailableGroups, createOffer, fetchGroupsOffers, confirmStationOffers, acceptGroupOffer, rejectGroupOffer, deleteOffer, fetchStationOffers, sendOfferReminder, updateOfferAttendees, createLink as getLink } from './service';\r\n\r\nexport function* fetchGroupOffersSaga (action) {\r\n try {\r\n const response = yield call(() => fetchGroupOffers(action.payload));\r\n yield put({type: GROUP_OFFERS_FETCH_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: GROUP_OFFERS_FETCH_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* fetchGroupOfferSaga (action) {\r\n try {\r\n const response = yield call(() => fetchGroupOffer(action.payload));\r\n yield put({type: GROUP_OFFER_FETCH_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: GROUP_OFFER_FETCH_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* updateOfferAttendeesSaga (action) {\r\n try {\r\n const response = yield call(() => updateOfferAttendees(action.payload));\r\n yield put({type: GROUP_OFFER_FETCH, payload: response});\r\n } catch (e) {\r\n yield put({type: UPDATE_OFFER_ATTENDEES_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* fetchEventOffersSaga (action) {\r\n try {\r\n const response = yield call(() => fetchEventOffers(action.payload));\r\n yield put({type: EVENT_OFFERS_FETCH_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: EVENT_OFFERS_FETCH_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* fetchStationOffersSaga (action) {\r\n try {\r\n const response = yield call(() => fetchStationOffers(action.payload));\r\n yield put({type: STATION_OFFERS_FETCH_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: STATION_OFFERS_FETCH_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* fetchAllOffersSaga (action) {\r\n try {\r\n const response = yield call(() => fetchAllOffers(action.payload));\r\n yield put({type: ALL_OFFERS_FETCH_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: ALL_OFFERS_FETCH_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* fetchGroupsEventsSaga (action) {\r\n try {\r\n const response = yield call(() => fetchGroupsOffers(action.payload));\r\n yield put({type: GROUPS_OFFERS_FETCH_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: GROUPS_OFFERS_FETCH_FAILED, payload: e, data: action.payload});\r\n }\r\n}\r\n\r\nexport function* fetchAvailableGroupsSaga (action) {\r\n try {\r\n const response = yield call(() => fetchAvailableGroups(action.payload));\r\n yield put({type: AVAILABLE_GROUPS_FETCH_SUCCESS, payload: response, eventId: action.payload.eventId, stationId: action.payload.stationId});\r\n } catch (e) {\r\n yield put({type: AVAILABLE_GROUPS_FETCH_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* createOfferSaga (action) {\r\n try {\r\n const response = yield call(() => createOffer(action.payload));\r\n yield put({type: OFFER_CREATE_SUCCESS, payload: response, data: action.payload});\r\n yield put({type: EVENT_OFFERS_FETCH, payload: action.payload});\r\n } catch (e) {\r\n yield put({type: OFFER_CREATE_FAILED, payload: e, data: action.payload});\r\n }\r\n}\r\n\r\nexport function* confirmStationOffersSaga (action) {\r\n try {\r\n const response = yield call(() => confirmStationOffers(action.payload));\r\n yield put({type: CONFIRM_STATION_OFFERS_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: CONFIRM_STATION_OFFERS_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* acceptGroupOfferSaga (action) {\r\n try {\r\n const response = yield call(() => acceptGroupOffer(action.payload));\r\n yield put({type: ACCEPT_STATION_OFFER_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: ACCEPT_STATION_OFFER_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* rejectGroupOfferSaga (action) {\r\n try {\r\n const response = yield call(() => rejectGroupOffer(action.payload));\r\n yield put({type: REJECT_STATION_OFFER_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: REJECT_STATION_OFFER_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* deleteOfferSaga (action) {\r\n try {\r\n const response = yield call(() => deleteOffer(action.payload));\r\n yield put({type: DELETE_OFFER_SUCCESS, payload: response});\r\n yield put({type: EVENT_OFFERS_FETCH, payload: action.payload});\r\n } catch (e) {\r\n yield put({type: DELETE_OFFER_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* sendOfferReminderSaga (action) {\r\n try {\r\n const response = yield call(() => sendOfferReminder(action.payload));\r\n yield put({type: SEND_OFFER_REMINDER_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: SEND_OFFER_REMINDER_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* createLink (action) {\r\n try {\r\n const response = yield call(() => getLink(action.payload));\r\n yield put({type: CREATE_SELF_REGISTRATION_LINK_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: CREATE_SELF_REGISTRATION_LINK_FAIL, payload: e});\r\n }\r\n}\r\n","import { call, put } from 'redux-saga/effects';\r\nimport { getUserByEmail, createUser } from \"./service\";\r\nimport { GET_USER_BY_EMAIL_SUCCESS, GET_USER_BY_EMAIL_FAILED, CREATE_USER_SUCCESS, CREATE_USER_FAILED } from \"./reducer\";\r\n\r\nexport function* getUserByEmailSaga (action) {\r\n try {\r\n const response = yield call(() => getUserByEmail(action.payload));\r\n yield put({type: GET_USER_BY_EMAIL_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: GET_USER_BY_EMAIL_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* createUserSaga (action) {\r\n try {\r\n yield call(() => createUser(action.payload));\r\n yield put({type: CREATE_USER_SUCCESS, payload: action.payload});\r\n } catch (e) {\r\n yield put({type: CREATE_USER_FAILED, payload: e});\r\n }\r\n}","import { Auth, API, Storage } from 'aws-amplify';\r\n\r\nfunction S3Exception (message, statusCode) {\r\n this.message = message;\r\n this.statusCode = statusCode;\r\n this.name = 'S3Exception';\r\n}\r\n\r\nexport const sendSendOut = data =>\r\n Auth.currentSession()\r\n .then(async (session) => {\r\n // Cant get the user id in the backend (can only find user.sub) so we pass it here so that we know the path to the attachments\r\n let info = await Auth.currentUserInfo();\r\n data.userId = info.id;\r\n\r\n if (Array.isArray(data.attachments)) {\r\n const fileKeys = [];\r\n\r\n for (const file of data.attachments) {\r\n const result = await Storage.put(`${data.eventId}/${file.name}`, file, {\r\n contentType: file.type,\r\n level: 'private',\r\n })\r\n .catch(err => {\r\n throw new S3Exception(err.message || 'Cant upload file to S3', err.statusCode);\r\n });\r\n fileKeys.push(Object.assign(result, {name: file.name, userId: info.id}));\r\n }\r\n\r\n data.attachments = fileKeys;\r\n }\r\n\r\n const request = {\r\n body: data,\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n\r\n return API.post('volex-protected', `/events/${data.eventId}/sendout`, request);\r\n });\r\n\r\nexport const fetchEventSendOuts = (eventId) =>\r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.get('volex-protected', `/events/${eventId}/sendout`, request);\r\n });\r\n\r\nexport const fetchEventSendOut = ({eventId, sendOutId}) =>\r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.get('volex-protected', `/events/${eventId}/sendout/${sendOutId}`, request);\r\n });","import { call, put } from 'redux-saga/effects';\r\nimport { SEND_OUT_SUCCESS, SEND_OUT_FAILED, FETCH_SEND_OUTS_FAILED, FETCH_SEND_OUTS_SUCCESS, FETCH_SEND_OUT_SUCCESS, FETCH_SEND_OUT_FAILED } from \"./reducer\";\r\nimport { sendSendOut, fetchEventSendOuts, fetchEventSendOut } from \"./service\";\r\n\r\nexport function* sendSendOutSaga (action) {\r\n try {\r\n const response = yield call(() => sendSendOut(action.payload));\r\n yield put({type: SEND_OUT_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: SEND_OUT_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* fetchSendOutsSaga (action) {\r\n try {\r\n const response = yield call(() => fetchEventSendOuts(action.payload));\r\n yield put({type: FETCH_SEND_OUTS_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: FETCH_SEND_OUTS_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* fetchSendOutSaga (action) {\r\n try {\r\n const response = yield call(() => fetchEventSendOut(action.payload));\r\n yield put({type: FETCH_SEND_OUT_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: FETCH_SEND_OUT_FAILED, payload: e});\r\n }\r\n}","import { Auth, API } from 'aws-amplify';\r\n\r\nexport const submitAttendance = data =>\r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n body: {\r\n adultAttendance: data.adultAttendance,\r\n childAttendance: data.childAttendance,\r\n },\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.post('volex-protected', `/events/${data.eventId}/attendance/${data.stationId}_${data.groupId}`, request);\r\n });","import { call, put } from 'redux-saga/effects';\r\nimport { ATTENDANCE_SUBMIT_FAILED, ATTENDANCE_SUBMIT_SUCCESS } from \"./reducer\";\r\nimport { STATION_OFFER_UPDATE } from \"../../Offer/reducer\";\r\nimport { submitAttendance } from \"./service\";\r\n\r\nexport function* submitAttendanceSaga(action) {\r\n try {\r\n const response = yield call(() => submitAttendance(action.payload));\r\n yield put({type: ATTENDANCE_SUBMIT_SUCCESS, payload: response});\r\n yield put({type: STATION_OFFER_UPDATE, payload: response});\r\n } catch (e) {\r\n yield put({type: ATTENDANCE_SUBMIT_FAILED, payload: {e, groupId: action.payload.groupId}});\r\n }\r\n}","\r\nimport { Auth, API } from 'aws-amplify';\r\n\r\nexport const getEventsSummaries = () => \r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.get('volex-protected', '/teamleader/events/summaries', request);\r\n });\r\n\r\n export const fetchEvent = (data) => \r\n Auth.currentSession()\r\n .then((session) => {\r\n const request = {\r\n headers: {\r\n Authorization: session.idToken.jwtToken,\r\n },\r\n };\r\n return API.get('volex-protected', `/teamleader/events/${data.id}`, request);\r\n });","import { call, put } from 'redux-saga/effects';\r\nimport { TEAMLEADER_EVENTS_SUCCESS, TEAMLEADER_EVENTS_FAILED, TEAMLEADER_EVENT_SUCCESS, TEAMLEADER_EVENT_FAILED } from './reducer';\r\nimport { getEventsSummaries, fetchEvent } from './service';\r\n\r\nexport function* fetchTeamleaderEvents (action) {\r\n try {\r\n const response = yield call(() => getEventsSummaries(action.payload));\r\n yield put({type: TEAMLEADER_EVENTS_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: TEAMLEADER_EVENTS_FAILED, payload: e});\r\n }\r\n}\r\n\r\nexport function* fetchTeamleaderEvent (action) {\r\n try {\r\n const response = yield call(() => fetchEvent(action.payload));\r\n yield put({type: TEAMLEADER_EVENT_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: TEAMLEADER_EVENT_FAILED, payload: e});\r\n }\r\n}","import { API } from 'aws-amplify';\r\n\r\nexport const submitVolunteer = data => {\r\n const request = {\r\n body: data,\r\n }\r\n return API.post('volex-protected', `/groups/addVolunteer`, request);\r\n}\r\n\r\nexport const getPublicEvent = eventId => {\r\n return API.get('volex-protected',`/public/events/${eventId}`);\r\n}","import { call, put } from 'redux-saga/effects';\r\nimport { VOLUNTEER_SUCCESS, VOLUNTEER_FAILED, FETCH_SUCCESS, FETCH_FAILED } from './reducer';\r\nimport { submitVolunteer, getPublicEvent } from './service';\r\n\r\nexport function* addVolunteer (action) {\r\n try {\r\n const response = yield call(() => submitVolunteer(action.payload));\r\n yield put ({type: VOLUNTEER_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: VOLUNTEER_FAILED, payload: e.response.data.message});\r\n }\r\n}\r\n\r\nexport function* fetchPublicEvent (action) {\r\n try {\r\n const response = yield call(() => getPublicEvent(action.payload));\r\n yield put ({type: FETCH_SUCCESS, payload: response});\r\n } catch (e) {\r\n yield put({type: FETCH_FAILED, payload: e.response.data.message});\r\n }\r\n}","import { takeLatest, takeEvery } from 'redux-saga/effects';\r\n\r\nimport { LOGIN_SUBMIT, LOGOUT, AUTH_STORED_USER, REGISTRATION_RESEND_CODE, REGISTRATION_CONFIRM_SUBMIT, LOGIN_SUCCESS, UPDATE_USER_INFO, GET_USER_INFO, CHANGE_PASSWORD_SUBMIT } from './auth/reducer';\r\nimport { loginSaga, loadAuthenticatedUserSaga, logoutSaga, confirmRegistrationSaga, resendConfirmationSaga, getUserInfoSaga, updateUserInfo, changePasswordSaga } from './auth/saga';\r\n\r\nimport { REGISTER_SUBMIT } from './containers/User/Register/reducer';\r\nimport { registerSaga } from './containers/User/Register/saga';\r\n\r\nimport { GROUP_SUBMIT, GROUP_FETCHING, GROUPS_SUMMARIES, FETCH_PUBLIC_EVENTS, GROUP_CONFIRM, FETCH_COMPLETE_EVENT } from './containers/MyPages/VolunteerContext/reducer';\r\nimport { groupSaga, fetchGroup, fetchGroupsSummaries, fetchPublicEvents, confirmGroupSaga, fetchCompleteEvent } from './containers/MyPages/VolunteerContext/saga';\r\n\r\nimport { EVENT_SUBMIT, EVENT_FETCHING, EVENTS_SUMMARIES, EVENT_CONFIRM, EVENT_REMOVE, SET_HISTORIC } from './containers/MyPages/Event/reducer';\r\nimport { saveEvent, fetchEvent, fetchEventsSummaries, confirmEventSaga, removeEvent, setHistoric } from './containers/MyPages/Event/saga';\r\n\r\nimport { resetPasswordSaga, forgotPasswordSaga, forgotPasswordResetSaga } from './containers/User/ForgotPassword/saga';\r\nimport { RESET_PASSWORD, FORGOT_PASSWORD_CODE_SEND, RESET_PASSWORD_STATE } from './containers/User/ForgotPassword/reducer';\r\nimport { FETCH_CALENDAR_EVENTS } from './containers/Start/reducer';\r\nimport { fetchCalendarEvents } from './containers/Start/saga';\r\nimport { GROUP_AVAIL_SAVE, GROUP_AVAIL_FETCH } from './containers/MyPages/VolunteerContext/GroupAvailability/reducer';\r\nimport { saveGroupAvailabilitySaga, getGroupAvailabilitySaga } from './containers/MyPages/VolunteerContext/GroupAvailability/saga';\r\nimport { GROUP_OFFERS_FETCH, GROUP_OFFER_FETCH, ALL_OFFERS_FETCH, EVENT_OFFERS_FETCH, AVAILABLE_GROUPS_FETCH, OFFER_CREATE, CONFIRM_STATION_OFFERS, GROUPS_OFFERS_FETCH, ACCEPT_STATION_OFFER, REJECT_STATION_OFFER, DELETE_OFFER, STATION_OFFERS_FETCH, SEND_OFFER_REMINDER, UPDATE_OFFER_ATTENDEES, CREATE_SELF_REGISTRATION_LINK } from './containers/MyPages/Offer/reducer';\r\nimport { fetchGroupOffersSaga, updateOfferAttendeesSaga, fetchGroupOfferSaga, fetchAllOffersSaga, fetchEventOffersSaga, fetchAvailableGroupsSaga, createOfferSaga, confirmStationOffersSaga, fetchGroupsEventsSaga, acceptGroupOfferSaga, rejectGroupOfferSaga, deleteOfferSaga, fetchStationOffersSaga, sendOfferReminderSaga, createLink } from './containers/MyPages/Offer/saga';\r\n\r\nimport { GET_USER_BY_EMAIL, CREATE_USER } from \"./containers/User/reducer\";\r\nimport { getUserByEmailSaga, createUserSaga } from \"./containers/User/saga\";\r\n\r\nimport { SEND_SEND_OUT, FETCH_SEND_OUTS, FETCH_SEND_OUT } from \"./containers/MyPages/Event/SendOuts/reducer\";\r\nimport { sendSendOutSaga, fetchSendOutsSaga, fetchSendOutSaga } from \"./containers/MyPages/Event/SendOuts/saga\";\r\n\r\nimport { ATTENDANCE_SUBMIT } from \"./containers/MyPages/Event/Attendance/reducer\";\r\nimport { submitAttendanceSaga } from \"./containers/MyPages/Event/Attendance/saga\";\r\n\r\nimport { TEAMLEADER_EVENTS_FETCH, TEAMLEADER_EVENT_FETCH } from './containers/MyPages/TeamLeader/reducer';\r\nimport { fetchTeamleaderEvents, fetchTeamleaderEvent } from './containers/MyPages/TeamLeader/saga';\r\n\r\nimport { VOLUNTEER_SUBMIT, FETCHING } from './containers/SelfRegistration/reducer';\r\nimport { addVolunteer, fetchPublicEvent } from './containers/SelfRegistration/saga';\r\n\r\n// watcher saga: watches for actions dispatched to the store, starts worker saga\r\nexport function* watcherSaga() {\r\n yield takeLatest(UPDATE_OFFER_ATTENDEES, updateOfferAttendeesSaga)\r\n yield takeLatest(REGISTRATION_RESEND_CODE, resendConfirmationSaga);\r\n yield takeLatest(LOGIN_SUBMIT, loginSaga);\r\n yield takeLatest(LOGIN_SUCCESS, getUserInfoSaga);\r\n yield takeLatest(CHANGE_PASSWORD_SUBMIT, changePasswordSaga);\r\n yield takeLatest(GET_USER_INFO, getUserInfoSaga);\r\n yield takeLatest(LOGOUT, logoutSaga);\r\n yield takeLatest(AUTH_STORED_USER, loadAuthenticatedUserSaga);\r\n yield takeLatest(REGISTER_SUBMIT, registerSaga);\r\n yield takeLatest(GROUP_SUBMIT, groupSaga);\r\n yield takeLatest(GROUP_FETCHING, fetchGroup);\r\n yield takeLatest(EVENT_SUBMIT, saveEvent);\r\n yield takeLatest(EVENT_FETCHING, fetchEvent);\r\n yield takeLatest(REGISTRATION_CONFIRM_SUBMIT, confirmRegistrationSaga);\r\n yield takeLatest(EVENTS_SUMMARIES, fetchEventsSummaries);\r\n yield takeLatest(EVENT_REMOVE, removeEvent);\r\n yield takeLatest(RESET_PASSWORD, resetPasswordSaga);\r\n yield takeLatest(RESET_PASSWORD_STATE, forgotPasswordResetSaga);\r\n yield takeLatest(FORGOT_PASSWORD_CODE_SEND, forgotPasswordSaga);\r\n yield takeLatest(FETCH_CALENDAR_EVENTS, fetchCalendarEvents);\r\n yield takeLatest(UPDATE_USER_INFO, updateUserInfo);\r\n yield takeLatest(GROUPS_SUMMARIES, fetchGroupsSummaries);\r\n yield takeLatest(FETCH_PUBLIC_EVENTS, fetchPublicEvents);\r\n yield takeLatest(FETCH_COMPLETE_EVENT, fetchCompleteEvent);\r\n yield takeLatest(EVENT_CONFIRM, confirmEventSaga);\r\n yield takeLatest(GROUP_CONFIRM, confirmGroupSaga);\r\n yield takeLatest(GROUP_AVAIL_SAVE, saveGroupAvailabilitySaga);\r\n yield takeLatest(GROUP_AVAIL_FETCH, getGroupAvailabilitySaga);\r\n yield takeLatest(GROUP_OFFERS_FETCH, fetchGroupOffersSaga);\r\n yield takeLatest(GROUPS_OFFERS_FETCH, fetchGroupsEventsSaga);\r\n yield takeLatest(GROUP_OFFER_FETCH, fetchGroupOfferSaga);\r\n yield takeLatest(ALL_OFFERS_FETCH, fetchAllOffersSaga);\r\n yield takeLatest(EVENT_OFFERS_FETCH, fetchEventOffersSaga);\r\n yield takeLatest(STATION_OFFERS_FETCH, fetchStationOffersSaga);\r\n yield takeLatest(ACCEPT_STATION_OFFER, acceptGroupOfferSaga);\r\n yield takeLatest(REJECT_STATION_OFFER, rejectGroupOfferSaga);\r\n yield takeLatest(DELETE_OFFER, deleteOfferSaga);\r\n yield takeLatest(SEND_OFFER_REMINDER, sendOfferReminderSaga);\r\n yield takeLatest(GET_USER_BY_EMAIL, getUserByEmailSaga);\r\n yield takeLatest(CREATE_USER, createUserSaga);\r\n yield takeEvery(CONFIRM_STATION_OFFERS, confirmStationOffersSaga);\r\n yield takeEvery(AVAILABLE_GROUPS_FETCH, fetchAvailableGroupsSaga);\r\n yield takeEvery(OFFER_CREATE, createOfferSaga);\r\n yield takeLatest(SEND_SEND_OUT, sendSendOutSaga);\r\n yield takeLatest(FETCH_SEND_OUTS, fetchSendOutsSaga);\r\n yield takeLatest(FETCH_SEND_OUT, fetchSendOutSaga);\r\n yield takeEvery(ATTENDANCE_SUBMIT, submitAttendanceSaga);\r\n yield takeLatest(TEAMLEADER_EVENTS_FETCH, fetchTeamleaderEvents);\r\n yield takeLatest(TEAMLEADER_EVENT_FETCH, fetchTeamleaderEvent);\r\n yield takeLatest(SET_HISTORIC, setHistoric);\r\n yield takeLatest(CREATE_SELF_REGISTRATION_LINK, createLink);\r\n yield takeLatest(VOLUNTEER_SUBMIT, addVolunteer);\r\n yield takeLatest(FETCHING, fetchPublicEvent);\r\n}\r\n","import { store } from '../index';\r\nimport axios from 'axios';\r\n// import { refreshToken } from \"../auth/service\";\r\n\r\n/**\r\n * Set the Authorization Bearer on each request\r\n * (if we have an accessToken)\r\n */\r\nconst injectAuthorizationHeader = (config) => {\r\n const oauth = store.getState().auth;\r\n\r\n if (oauth.accessToken !== null) {\r\n config.headers['Authorization'] = `Bearer ${oauth.accessToken}`;\r\n }\r\n\r\n return config;\r\n};\r\n\r\n\r\n/**\r\n * Intercept all errors.\r\n *\r\n * If it is a 401 run the refreshToken request\r\n * and redo the request afterwards.\r\n */\r\nexport function refreshTokenSetup (error) {\r\n /* TODO...\r\n let oauth = store.getState().auth;\r\n\r\n if (oauth !== null && error.response.status === 401) {\r\n return refreshToken()\r\n .then(() => axios(error.request.config));\r\n }\r\n */\r\n\r\n return Promise.reject(error);\r\n}\r\n\r\nexport const initAxios = () => {\r\n axios.interceptors.request.use(injectAuthorizationHeader);\r\n axios.interceptors.response.use(response => response, refreshTokenSetup);\r\n};\r\n","const devSettings = {\r\n Auth: {\r\n // REQUIRED - Amazon Cognito Identity Pool ID\r\n identityPoolId: 'eu-west-1:f9014821-b8d0-43e1-a46b-8f6808cc2374',\r\n // REQUIRED - Amazon Cognito Region\r\n region: 'eu-west-1',\r\n // OPTIONAL - Amazon Cognito User Pool ID\r\n userPoolId: 'eu-west-1_7ahzB90Ud',\r\n // OPTIONAL - Amazon Cognito Web Client ID\r\n userPoolWebClientId: '5i944ue34eadh1edvflo7fb7fn',\r\n },\r\n API: {\r\n endpoints: [\r\n {\r\n name: 'volex-protected',\r\n // endpoint: '/dev',\r\n // For local development use either configs below\r\n // endpoint: 'https://dev.volex.org/api'\r\n endpoint: 'http://localhost:3001/api'\r\n },\r\n ],\r\n },\r\n Storage: {\r\n bucket: 'volex-dev-uploads', //REQUIRED - Amazon S3 bucket\r\n identityPoolId: 'eu-west-1:f9014821-b8d0-43e1-a46b-8f6808cc2374',\r\n region: 'eu-west-1',\r\n }\r\n}\r\n\r\nconst testSettings = {\r\n Auth: {\r\n // REQUIRED - Amazon Cognito Identity Pool ID\r\n identityPoolId: 'eu-west-1:5acb29b2-c1e5-48cf-85fb-39d5568108a0',\r\n // REQUIRED - Amazon Cognito Region\r\n region: 'eu-west-1',\r\n // OPTIONAL - Amazon Cognito User Pool ID\r\n userPoolId: 'eu-west-1_ZxE3d9Bty',\r\n // OPTIONAL - Amazon Cognito Web Client ID\r\n userPoolWebClientId: '1h3dagdnd2l7subb1b64c9258b',\r\n },\r\n API: {\r\n endpoints: [\r\n {\r\n name: 'volex-protected',\r\n endpoint: '/api',\r\n },\r\n ],\r\n },\r\n Storage: {\r\n bucket: 'volex-test-uploads', //REQUIRED - Amazon S3 bucket\r\n identityPoolId: 'eu-west-1:5acb29b2-c1e5-48cf-85fb-39d5568108a0',\r\n region: 'eu-west-1',\r\n }\r\n};\r\n\r\nconst prodSettings = {\r\n Auth: {\r\n // REQUIRED - Amazon Cognito Identity Pool ID\r\n identityPoolId: 'eu-west-1:19594308-470a-464d-8bb7-7dbc8030e908',\r\n // REQUIRED - Amazon Cognito Region\r\n region: 'eu-west-1',\r\n // OPTIONAL - Amazon Cognito User Pool ID\r\n userPoolId: 'eu-west-1_NsvBPjzV9',\r\n // OPTIONAL - Amazon Cognito Web Client ID\r\n userPoolWebClientId: '1ttrklt08d6fc2gul3vqua0l20',\r\n },\r\n API: {\r\n endpoints: [\r\n {\r\n name: 'volex-protected',\r\n endpoint: '/api',\r\n },\r\n ],\r\n },\r\n Storage: {\r\n bucket: 'volex-prod-uploads', //REQUIRED - Amazon S3 bucket\r\n identityPoolId: 'eu-west-1:19594308-470a-464d-8bb7-7dbc8030e908',\r\n region: 'eu-west-1',\r\n }\r\n};\r\n\r\nconst stage = process.env.REACT_APP_STAGE || 'dev';\r\n\r\nexport default stage === \"dev\" ? devSettings : stage === \"test\" ? testSettings : prodSettings;\r\n","import React, { Component } from \"react\";\r\nimport ReactDOM from \"react-dom\";\r\nimport { connect } from \"react-redux\";\r\nimport {\r\n BrowserRouter as Router\r\n} from \"react-router-dom\";\r\nimport \"./index.css\";\r\nimport \"../node_modules/react-widgets/dist/css/react-widgets.css\"; // TODO: Handle this import in build.\r\nimport \"./styles/font-awesome/css/fontawesome-all.min.css\";\r\nimport \"react-bootstrap-table-next/dist/react-bootstrap-table2.min.css\";\r\n// import \"core-js/es7\";\r\nimport App from \"./App\";\r\n\r\nimport registerServiceWorker from \"./registerServiceWorker\";\r\nimport ScrollToTop from \"./ScrollToTop\";\r\n\r\nimport { createStore, applyMiddleware, compose, combineReducers } from \"redux\";\r\nimport createSagaMiddleware from \"redux-saga\";\r\nimport { Provider } from \"react-redux\";\r\n\r\nimport { reducer as formReducer } from \"redux-form\";\r\nimport auth from \"./auth/reducer\";\r\n\r\nimport register from \"./containers/User/Register/reducer\";\r\nimport menu from \"./components/Menu/reducer\";\r\nimport group from \"./containers/MyPages/VolunteerContext/reducer\";\r\nimport event from \"./containers/MyPages/Event/reducer\";\r\nimport forgotPassword from \"./containers/User/ForgotPassword/reducer\";\r\nimport start from \"./containers/Start/reducer\";\r\nimport groupAvailabilities from \"./containers/MyPages/VolunteerContext/GroupAvailability/reducer\";\r\nimport user from \"./containers/User/reducer\";\r\nimport sendOuts from \"./containers/MyPages/Event/SendOuts/reducer\";\r\nimport attendance from \"./containers/MyPages/Event/Attendance/reducer\";\r\nimport teamleader from \"./containers/MyPages/TeamLeader/reducer\";\r\nimport selfRegistration from \"./containers/SelfRegistration/reducer\";\r\n\r\nimport { watcherSaga } from \"./sagas\";\r\nimport labels from \"./labels.json\";\r\nimport { IntlProvider } from \"react-intl\";\r\n\r\nimport { initAxios } from \"./setup/api\";\r\n\r\nimport moment from \"moment\";\r\nimport momentLocalizer from \"react-widgets-moment\";\r\nimport offers from \"./containers/MyPages/Offer/reducer\";\r\n// import mapStateToProps from 'react-redux/lib/connect/mapStateToProps';\r\n\r\nimport Amplify from 'aws-amplify';\r\nimport awsConfig from './aws-config';\r\nAmplify.configure(awsConfig);\r\n\r\n// create the saga middleware\r\nconst sagaMiddleware = createSagaMiddleware();\r\n\r\n// dev tools middleware\r\nconst reduxDevTools = window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__();\r\n\r\n// create a redux store with our reducer above and middleware\r\nexport const store = createStore(\r\n combineReducers({\r\n form: formReducer,\r\n auth,\r\n register,\r\n menu,\r\n group,\r\n event,\r\n forgotPassword,\r\n start,\r\n groupAvailabilities,\r\n offers,\r\n attendance,\r\n user: user,\r\n sendOuts,\r\n teamleader,\r\n selfRegistration,\r\n }),\r\n reduxDevTools ? compose(applyMiddleware(sagaMiddleware), reduxDevTools) : compose(applyMiddleware(sagaMiddleware))\r\n // applyMiddleware(sagaMiddleware)\r\n);\r\n\r\ninitAxios();\r\n\r\n// run the saga\r\nsagaMiddleware.run(watcherSaga);\r\n\r\n// React Widgets localization\r\nmoment.updateLocale('sv', {\r\n week : {\r\n dow : 1,\r\n doy : 4\r\n }\r\n});\r\nmoment.locale(\"sv\");\r\nmomentLocalizer();\r\n\r\nclass ToggleLabels extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = { onlyKeys: false };\r\n this.keyDown = this.keyDown.bind(this);\r\n this.keyUp = this.keyUp.bind(this);\r\n }\r\n\r\n componentDidMount() {\r\n window.addEventListener(\"keydown\", this.keyDown);\r\n window.addEventListener(\"keyup\", this.keyUp);\r\n }\r\n\r\n componentWillUnmount() {\r\n window.removeEventListener(\"keydown\", this.keyDown);\r\n window.removeEventListener(\"keyup\", this.keyUp);\r\n }\r\n\r\n keyDown(val) {\r\n if (val.keyCode === 16 && val.altKey && val.ctrlKey) {\r\n this.setState({ onlyKeys: !this.state.onlyKeys });\r\n }\r\n }\r\n\r\n keyUp(val) {\r\n if (val.keyCode === 16 && this.state.onlyKeys) {\r\n this.setState({ onlyKeys: !this.state.onlyKeys });\r\n }\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n selectedLanguage: state.menu.selectedLanguage,\r\n});\r\n\r\nconst ConnectedToggleLabels = connect(mapStateToProps)(ToggleLabels)\r\n\r\nReactDOM.render(\r\n \r\n \r\n ,\r\n document.getElementById(\"root\")\r\n);\r\n\r\n\r\nregisterServiceWorker();\r\n","module.exports = __webpack_public_path__ + \"static/media/Volex_bild_undersida2.42a12935.jpg\";","module.exports = __webpack_public_path__ + \"static/media/Volex_bild_undersida6.7f3a1360.jpg\";","module.exports = __webpack_public_path__ + \"static/media/hero.3c670471.jpg\";","module.exports = __webpack_public_path__ + \"static/media/VolEx_logo_pos.818f737d.svg\";","module.exports = __webpack_public_path__ + \"static/media/VolEx_logo_footer.f6acd9fe.svg\";","module.exports = __webpack_public_path__ + \"static/media/Volex_bild_undersida7.970f4d8b.jpg\";","module.exports = __webpack_public_path__ + \"static/media/Volex_bild_undersida9.663d1325.jpg\";","module.exports = __webpack_public_path__ + \"static/media/Volex_bild_undersida11.f6d1819c.jpg\";","module.exports = __webpack_public_path__ + \"static/media/Volex_bild_LoggaIn.13e910c4.jpg\";"],"sourceRoot":""}