From 11fe5f1c6163d5dbf282c25624ccd1dea45e7dc0 Mon Sep 17 00:00:00 2001 From: Senad Uka Date: Fri, 25 May 2018 09:10:32 +0200 Subject: [PATCH] Upstream sync --- .../Shared/ValidationErrorsInfoDialog.js | 103 +- src/components/Sidenav/SidenavContent.js | 43 +- src/routes/app/components/NEMTLocation.js | 46 +- src/routes/app/routes/forms/index.js | 2 + .../steppers/components/VerticalNonLinear.js | 54 +- .../forms/routes/visit/components/Steppers.js | 14 + .../visit/components/VerticalNonLinear.js | 1194 +++++++++++++++++ .../app/routes/forms/routes/visit/index.js | 8 + .../routes/visitRide/components/Steppers.js | 14 + .../visitRide/components/VerticalNonLinear.js | 910 +++++++++++++ .../routes/forms/routes/visitRide/index.js | 8 + .../routes/visits/components/Datatable.js | 13 +- src/utils/authorization/index.js | 1 + .../authorization/profiles/visitReporter.js | 7 + 14 files changed, 2296 insertions(+), 121 deletions(-) create mode 100644 src/routes/app/routes/forms/routes/visit/components/Steppers.js create mode 100644 src/routes/app/routes/forms/routes/visit/components/VerticalNonLinear.js create mode 100644 src/routes/app/routes/forms/routes/visit/index.js create mode 100644 src/routes/app/routes/forms/routes/visitRide/components/Steppers.js create mode 100644 src/routes/app/routes/forms/routes/visitRide/components/VerticalNonLinear.js create mode 100644 src/routes/app/routes/forms/routes/visitRide/index.js create mode 100644 src/utils/authorization/profiles/visitReporter.js diff --git a/src/components/Shared/ValidationErrorsInfoDialog.js b/src/components/Shared/ValidationErrorsInfoDialog.js index c42fd6f..f0efe0c 100644 --- a/src/components/Shared/ValidationErrorsInfoDialog.js +++ b/src/components/Shared/ValidationErrorsInfoDialog.js @@ -3,57 +3,60 @@ import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; export class ValidationErrorsInfoDialog extends React.Component { - - state = { + constructor(props) { + super(props) + this.props = props; + this.state = { open: this.props.open, } - - componentWillReceiveProps(newProps){ - this.setState({open: newProps.open}); - } - - handleOpen = () => { - this.setState({ open: true }); - }; - - handleClose = () => { - this.setState({ open: false }); - this.props.onDismiss(); - }; - - render() { - - const actions = [ - , - ]; - - return ( -
- - {this.props.errorMessages.map(errorMessage => { - return ( -
- {errorMessage.message} -
-
- ); - })} -
-
- ); - } } - module.exports = ValidationErrorsInfoDialog; \ No newline at end of file + componentWillReceiveProps(newProps) { + this.setState({ open: newProps.open }); + } + + handleOpen = () => { + this.setState({ open: true }); + }; + + handleClose = () => { + this.setState({ open: false }); + this.props.onDismiss(); + }; + + render() { + + const actions = [ + , + ]; + + return ( +
+ + {this.props.errorMessages.map(errorMessage => { + return ( + + ); + })} + +
+ ); + } +} + +module.exports = ValidationErrorsInfoDialog; \ No newline at end of file diff --git a/src/components/Sidenav/SidenavContent.js b/src/components/Sidenav/SidenavContent.js index eec00f4..f017ccb 100644 --- a/src/components/Sidenav/SidenavContent.js +++ b/src/components/Sidenav/SidenavContent.js @@ -7,6 +7,7 @@ import { loggedUser, planScheduler, providerScheduler, + visitReporter, } from 'utils/authorization'; class SidebarContent extends React.Component { @@ -66,7 +67,6 @@ class SidebarContent extends React.Component { $subUl.stop().slideToggle(slideTime); }); - // HighlightActiveItems const $links = $nav.find('a'); const currentLocation = hashHistory.getCurrentLocation(); @@ -101,27 +101,34 @@ class SidebarContent extends React.Component { return (
    { this.nav = c; }}> + {loggedUser.anyOf(planScheduler, visitReporter) && +
  • Create Visit
  • + } + {!loggedUser.anyOf(planScheduler, visitReporter) && +
  • + directions_carRides +
      +
    • Book Rides
    • +
    • Manage Rides
    • +
    +
  • + } + {!loggedUser.anyOf(planScheduler, visitReporter) && +
  • + people_outlineMembers +
      +
    • Verify Eligibility
    • +
    • Manage Members
    • +
    +
  • + }
  • - directions_carRides + scheduleVisits
      -
    • Book Rides
    • -
    • Manage Rides
    • +
    • Create Visit
    • +
    • Manage Visits
  • -
  • - people_outlineMembers -
      -
    • Verify Eligibility
    • -
    • Manage Members
    • -
    -
  • - -
  • - scheduleVisits -
  • - {/*
  • - mail_outlineMessage Center -
  • */}
  • settingsManage diff --git a/src/routes/app/components/NEMTLocation.js b/src/routes/app/components/NEMTLocation.js index 0b6e7dc..0adb952 100644 --- a/src/routes/app/components/NEMTLocation.js +++ b/src/routes/app/components/NEMTLocation.js @@ -202,28 +202,30 @@ export class NEMTLocation extends React.Component { Instance.getRawConn().get(`/v1/nemt/provider/participating?sort=distance&lat=${lat}&long=${long}`).then(res => { let nearByPlaces = []; let providers = res.data.map(p => { - const streetNumber = p.address.street_address_1.split(' ')[0] - let clickResult = { - id: p.muk_id, - address: `${p.address.street_address_1}, ${p.address.city}, ${p.address.state} (${p.address.zipcode})`, - lat: p.address.lat, - lng: p.address.long, - name: p.name, - type: "provider", - raw: p, - street_number: streetNumber, - street: p.address.street_address_1.replace(streetNumber, '').trim(), - city: p.address.city, - state: p.address.state, - zipcode: p.address.zipcode.substring(0, 5), - country: p.address.country, - saved: false, - } - clickResult.address = `${clickResult.street_number} ${clickResult.street}, ${clickResult.city}` + if (p.address.street_address_1) { + const streetNumber = p.address.street_address_1.split(' ')[0] + let clickResult = { + id: p.muk_id, + address: `${p.address.street_address_1}, ${p.address.city}, ${p.address.state} (${p.address.zipcode})`, + lat: p.address.lat, + lng: p.address.long, + name: p.name, + type: "provider", + raw: p, + street_number: streetNumber, + street: p.address.street_address_1.replace(streetNumber, '').trim(), + city: p.address.city, + state: p.address.state, + zipcode: p.address.zipcode.substring(0, 5), + country: p.address.country, + saved: false, + } + clickResult.address = `${clickResult.street_number} ${clickResult.street}, ${clickResult.city}` - var listItem = (} onClick={(event) => this.handlePlaceChanged(clickResult)} />) - nearByPlaces.push(listItem); - p.providerText = `${p.name} - ${p.address.street_address_1}, ${p.address.city}, ${p.address.state} (${p.address.zipcode}) (${p.address.phone_number})` + var listItem = (} onClick={(event) => this.handlePlaceChanged(clickResult)} />) + nearByPlaces.push(listItem); + p.providerText = `${p.name} - ${p.address.street_address_1}, ${p.address.city}, ${p.address.state} (${p.address.zipcode}) (${p.address.phone_number})` + } return p; }); @@ -461,7 +463,7 @@ export class NEMTLocation extends React.Component { this.setState(Object.assign(this.state, { open: true })); if (this.state.user.useruuid === '' || this.state.user.useruuid !== this.props.data.user.useruuid) { - if (this.props.data.user && this.props.data.user !== null && this.props.data.user.useruuid !== '') { + if (this.props.data.user && this.props.data.user.useruuid !== undefined && this.props.data.user !== null && this.props.data.user.useruuid !== '') { let url = `/v1/nemt/users/member/` + this.props.data.user.useruuid Instance.getRawConn().get(url).then(res => { let user = res.data; diff --git a/src/routes/app/routes/forms/index.js b/src/routes/app/routes/forms/index.js index 43ffb14..ad1b424 100644 --- a/src/routes/app/routes/forms/index.js +++ b/src/routes/app/routes/forms/index.js @@ -6,6 +6,8 @@ module.exports = { require('./routes/components'), require('./routes/layouts'), require('./routes/steppers'), + require('./routes/visitRide'), + require('./routes/visit'), ]); }); } diff --git a/src/routes/app/routes/forms/routes/steppers/components/VerticalNonLinear.js b/src/routes/app/routes/forms/routes/steppers/components/VerticalNonLinear.js index 1982d3a..1c07f4d 100644 --- a/src/routes/app/routes/forms/routes/steppers/components/VerticalNonLinear.js +++ b/src/routes/app/routes/forms/routes/steppers/components/VerticalNonLinear.js @@ -405,8 +405,8 @@ class VerticalNonLinear extends React.Component { }, return_time: new Date(), pickupTimeHide: false, - showValidationErrors:false, - validationErrors:[], + showValidationErrors: false, + validationErrors: [], }; } @@ -451,19 +451,19 @@ class VerticalNonLinear extends React.Component { } }); - let date = new Date(); + let date = new Date(); - let visitTime = new Date(Math.round((date.getTime() + (1 * 60 * 60 * 1000)) / roundingTime) * roundingTime); - let visitDate = date; - let pickupTime = new Date(Math.round((visitTime.getTime() - (0.5 * 60 * 60 * 1000)) / roundingTime) * roundingTime); - let pickupTimeReturn = new Date(Math.round((visitTime.getTime() - (0.5 * 60 * 60 * 1000)) / roundingTime) * roundingTime); - - this.setState(Object.assign(this.state, { - visitDate: visitDate, - visitTime: visitTime, - pickupTime: pickupTime, - pickupTimeReturn: pickupTimeReturn, - })); + let visitTime = new Date(Math.round((date.getTime() + (1 * 60 * 60 * 1000)) / roundingTime) * roundingTime); + let visitDate = date; + let pickupTime = new Date(Math.round((visitTime.getTime() - (0.5 * 60 * 60 * 1000)) / roundingTime) * roundingTime); + let pickupTimeReturn = new Date(Math.round((visitTime.getTime() - (0.5 * 60 * 60 * 1000)) / roundingTime) * roundingTime); + + this.setState(Object.assign(this.state, { + visitDate: visitDate, + visitTime: visitTime, + pickupTime: pickupTime, + pickupTimeReturn: pickupTimeReturn, + })); } //for snackbar handleTouchTap() { @@ -521,11 +521,11 @@ class VerticalNonLinear extends React.Component { self.handleRequestClose(self); window.location.href = '/#/app/page/map/' + res.data.ride_uuid; }).catch(error => { - if (error.response.status === 422){ + if (error.response.status === 422) { //Unprocessable Entity (validation failed) self.setState(Object.assign(self.state, { - showValidationErrors:true, - validationErrors:error.response.data.data + showValidationErrors: true, + validationErrors: error.response.data.data })); } }); @@ -815,9 +815,9 @@ class VerticalNonLinear extends React.Component { } - handleValidationErrosDialogDismiss(){ + handleValidationErrosDialogDismiss() { this.setState(Object.assign(this.state, { - showValidationErrors:false + showValidationErrors: false })); } @@ -860,16 +860,18 @@ class VerticalNonLinear extends React.Component { if (this.state.showUserSelection && this.state.users.length > 0) { const handleAutocomplete = (u) => { let userHomeAddress = null; + if (u.addresses && u.addresses.length > 0) { u.addresses.forEach(address => { if (address.address_type === ADDRESS_TYPE_HOME) { userHomeAddress = address; } }); - if (userHomeAddress != null) { - userHomeAddress.name = "Home"; - state.handlePickupChanged(userHomeAddress,state); - } - state.setState(Object.assign(state.state, { user: u, userSelectionText: u.userdata })); + } + if (userHomeAddress != null) { + userHomeAddress.name = "Home"; + state.handlePickupChanged(userHomeAddress, state); + } + state.setState(Object.assign(state.state, { user: u, userSelectionText: u.userdata })); } const datasourceConfig = { text: 'userdata', value: 'useruuid' } userSelection = ( @@ -894,8 +896,8 @@ class VerticalNonLinear extends React.Component {
    - - + + { + return ( +
    + +
    +
    +
    + ); +}; + +module.exports = Stepper; diff --git a/src/routes/app/routes/forms/routes/visit/components/VerticalNonLinear.js b/src/routes/app/routes/forms/routes/visit/components/VerticalNonLinear.js new file mode 100644 index 0000000..81e75f0 --- /dev/null +++ b/src/routes/app/routes/forms/routes/visit/components/VerticalNonLinear.js @@ -0,0 +1,1194 @@ +import React, { Component } from 'react'; +import { + Step, + Stepper, + StepButton, + StepContent, +} from 'material-ui/Stepper'; +import RaisedButton from 'material-ui/RaisedButton'; +import FlatButton from 'material-ui/FlatButton'; +import QueueAnim from 'rc-queue-anim'; +import { RadioButton, RadioButtonGroup } from 'material-ui/RadioButton'; +import ActionFavorite from 'material-ui/svg-icons/action/favorite'; +import ActionFavoriteBorder from 'material-ui/svg-icons/action/favorite-border'; +import AutoComplete from 'material-ui/AutoComplete'; +import SelectField from 'material-ui/SelectField'; +import MenuItem from 'material-ui/MenuItem'; +import { Tabs, Tab } from 'material-ui/Tabs'; +// import Slider from 'material-ui/Slider'; +import TimePicker from 'material-ui/TimePicker'; +import DatePicker from 'material-ui/DatePicker'; +import TextField from 'material-ui/TextField'; +// import Toggle from 'material-ui/Toggle'; +import Snackbar from 'material-ui/Snackbar'; +import { NEMTLocation } from '../../../../../components/NEMTLocation'; +import { request } from 'https'; +import Divider from 'material-ui/Divider'; +import Paper from 'material-ui/Paper'; +import Dialog from 'material-ui/Dialog'; +import Close from 'material-ui/svg-icons/navigation/close' +import CommunicationCall from 'material-ui/svg-icons/communication/call' +import Message from 'material-ui/svg-icons/communication/message' +import Instance from '../../../../../../../components/Connection'; +import Checkbox from 'material-ui/Checkbox'; +import Popover from 'material-ui/Popover'; +import ValidationErrorsInfoDialog from '../../../../../../../components/Shared/ValidationErrorsInfoDialog'; + +let DateTimeFormat; + + +DateTimeFormat = global.Intl.DateTimeFormat; + + +class SignUp extends React.Component { + constructor(props) { + super(props); + this.props = props; + } + + componentWillReceiveProps = (nextProps) => { + this.props = nextProps; + } + + componentDidMount = () => { } + + clickEvent = (event) => { + event.preventDefault(); + const state = this; + state.handleRequestOpen(); + + let user = { + "first": this.state.first, + "last": this.state.last, + "gender": this.state.gender, + "member": this.state.member, + "email": this.state.email, + "phonenumber": this.state.phonenumber, + "birthdate": this.state.birthdate.toISOString() + } + + Instance.getRawConn().post('/v1/nemt/users/member', user).then(function (res) { + state.handleRequestClose(); + + const eligibility = res.data; + // if (eligibility.results.summary.benefits_found) { + window.location.href = `/#/app/form/steppers/${eligibility.useruuid}`; + // } else { + // alert('NO benefits found for this member'); + // } + }).catch(function (err) { + console.log('Error to get eligibility: ', err); + alert('NO benefits found for this member'); + this.handleRequestClose(); + }); + } + + handleRequestClose = () => { + this.setState(Object.assign(this.state, { open: false })); + }; + + handleRequestOpen = () => { + this.setState(Object.assign(this.state, { open: true })); + }; + + handleChecked = (event, checked) => { + const user = this.props.user; + user.agreedTerms = checked; + if (this.props.onUserChanged) { + this.props.onUserChanged(user); + } + }; + + handleDate = (event, date) => { + const user = this.props.user; + user.birthdate = date; + if (this.props.onUserChanged) { + this.props.onUserChanged(user); + } + }; + + handleMember = (event) => { + const user = this.props.user; + user.member = event.target.value; + if (this.props.onUserChanged) { + this.props.onUserChanged(user); + } + }; + + handleChange = (event, index, value) => { + const user = this.props.user; + user.gender = value; + if (this.props.onUserChanged) { + this.props.onUserChanged(user); + } + }; + + handleMemberType = (event, index, value) => { + const user = this.props.user; + user.type = value; + if (this.props.onUserChanged) { + this.props.onUserChanged(user); + } + }; + + handleFirstName = (event) => { + const user = this.props.user; + user.first = event.target.value; + if (this.props.onUserChanged) { + this.props.onUserChanged(user); + } + }; + + handleEmail = (event) => { + const user = this.props.user; + user.email = event.target.value; + if (this.props.onUserChanged) { + this.props.onUserChanged(user); + } + }; + + handleLastName = (event) => { + const user = this.props.user; + user.last = event.target.value; + if (this.props.onUserChanged) { + this.props.onUserChanged(user); + } + }; + + handlePhone = (event) => { + let phone = event.target.value; + if (phone.indexOf("+1") < 0 && phone.length == 10) { + phone = "+1" + phone; + phone = phone.substring(0, 12); + } + + const user = this.props.user; + user.phonenumber = phone; + if (this.props.onUserChanged) { + this.props.onUserChanged(user); + } + }; + + render() { + return ( +
    +
    + {/*
    */} + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + ); + } +} + +export class DialogExampleSimple extends React.Component { + state = { + open: true, + }; + + handleOpen = () => { + this.setState({ open: true }); + }; + + handleClose = () => { + this.setState({ open: false }); + }; + + render() { + const actions = [ + , + , + ]; + + return ( +
    + + The actions in this window were passed in as an array of React objects. + +
    + ); + } +} +/** + * Dialogs can be nested. This example opens a Date Picker from within a Dialog. + */ +export class DialogExampleDialogDatePicker extends React.Component { + state = { + open: false, + additionalPassenger: + { + passengerType: '', + seatType: '', + } + }; + + handleOpen = () => { + this.setState({ open: true }); + }; + + + handlePassengerTypeChange = (e, i, v, state) => { + this.setState({ additionalPassenger: { passengerType: v } }); + }; + + handleSeatTypeChange = (e, i, v, state) => { + this.setState({ additionalPassenger: { seatType: v } }); + }; + + handleClose = () => { + this.setState({ open: false }); + }; + + render() { + const actions = [ + , + , + ]; + + return ( +
    + + + this.handlePassengerTypeChange(e, i, v, this)} + autoWidth={true} + > + + + + + this.handleSeatTypeChange(e, i, v, this)} + autoWidth={true} + > + + + + + + +
    + ); + } +} +const names = [ + 'Service Animal', + 'Cane / Quad Cane', + 'Electric Wheelchair', + 'Oxygen Tank', + 'Sign Language', + 'White Cane', + 'Leg Braces', + 'Crutches', + 'Manual Wheelchair', + 'Prothesis', + 'Walker', +]; + +/** + * `SelectField` can handle multiple selections. It is enabled with the `multiple` property. + */ +export class SelectFieldExampleMultiSelect extends Component { + state = { + values: [], + }; + + handleChange = (event, index, values) => this.setState({ values }); + + menuItems(values) { + return names.map((name) => ( + -1} + value={name} + primaryText={name} + autoWidth={false} + style={{ width: 215 }} + /> + )); + } + + render() { + const { values } = this.state; + return ( + + {this.menuItems(values)} + + ); + } +} + +const axios = require('axios'); + +const selectStyles = { + customWidth: { + width: 35, + }, +}; + + + + +var tripType = 'To Visit'; +var pickupTimeReturnDisplayMode = "none"; +/** + * `SelectField` is implemented as a controlled component, + * with the current selection set through the `value` property. + * The `SelectField` can be disabled with the `disabled` property. + */ +export class SelectFieldExampleSimple extends Component { + constructor(props) { + super(props); + this.props = props; + this.state = { + value: 'to_visit', + pickupTimeReturnDisplayMode: 'none', + pickupTimeHide: false, + }; + } + + componentDidMount() { + this.setState(Object.assign(this.state, { value: this.props.value })); + } + + handleChange(event, index, value, state) { + let self = state + tripType = value; + switch (tripType) { + + case 'from_visit': + pickupTimeReturnDisplayMode = "none" + self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'none', value: 'from_visit', pickupTimeHide: false })); + break; + + case 'from_visit_call': + pickupTimeReturnDisplayMode = "none" + self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'none', value: 'from_visit_call', pickupTimeHide: true })); + break; + + + case 'to_visit': + pickupTimeReturnDisplayMode = "none" + self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'none', value: 'to_visit', pickupTimeHide: false })); + break; + + + case 'roundtrip': + pickupTimeReturnDisplayMode = "block" + self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'block', value: 'roundtrip', pickupTimeHide: false })); + break; + + case 'roundtrip_call': + pickupTimeReturnDisplayMode = "none"; + self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'none', value: 'roundtrip_call', pickupTimeHide: false })); + break; + + default: + self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'block', value: 'roundtrip', pickupTimeHide: false })); + break; + } + + if (this.props.handleChange) { + this.props.handleChange(event, index, { pickupTimeReturnDisplayMode: self.state.pickupTimeReturnDisplayMode, selectField: this.state.value, pickupTimeHide: this.state.pickupTimeHide }); + } + } + + render() { + return ( +
    + this.handleChange(e, i, v, this)} + autoWidth={false} + style={{ width: 230 }} + > + + + + + + +
    + ); + } +} + + +function disableWeekends(date) { + return date.getDay() === 0 || date.getDay() === 6; +} + + +const styles = { + padding: '12px 18px', + marginBottom: 12, + fontWeight: 400, + maxWidth: 250, + radioButton: { + marginTop: 6 + }, + checkbox: { + marginTop: 16, fontWeight: 100, fontSize: 10 + }, +}; + + + +// const styles = { +// block: { +// maxWidth: 250, +// }, +// checkbox: { +// marginBottom: 16,fontWeight:'regular' +// }, +// }; + +function handleActive(tab) { + console.log(`A tab with this route property ${tab.props.route} was activated.`); +} + + +const + dataConfig = { text: 'text', value: 'value' }; + + +/** + * A basic vertical non-linear implementation + */ +class VerticalNonLinear extends React.Component { + constructor(props) { + super(props); + + this.state = { + stepIndex: 0, + rideTypeValue: 0, + providerID: 0, + providerName: '', + visitDate: new Date(), + visitTime: new Date(), + pickupLocation: null, + pickupTime: new Date(), + pickupTimeReturn: new Date(), + pickupTimeReturnDisplayMode: 'none', + open: false, + message: 'Adding Visit', + origin: {}, + destination: {}, + buttonPickupText: 'Member Address', + buttodDropOffText: 'Choose Drop-Off location', + buttonProviderText: 'Choose Provider', + user: { + name: "", + first: "", + last: "", + gender: "", + member: "", + birthdate: new Date(), + email: "", + phonenumber: "", + type: "", + }, + showUserSelection: true, + userSelectionText: '', + users: [], + visit_external_id: "", + notes: "", + pickupTimeReturnDisplayMode: "none", + eta: { + distance_miles: 0, + duration_seconds: 0, + formatted_time: 0, + showed: false, + }, + trip_type: { + key: "to_visit", + value: "" + }, + return_time: new Date(), + pickupTimeHide: false, + validationErrors: [], + showValidationErrors: false, + }; + + this.handleUser = this.handleUser.bind(this); + } + + componentDidMount() { + const loggedUser = JSON.parse(localStorage.getItem("loggedUser")); + let state = this; + + let user = { + useruuid: this.props.params.uuid + } + + if (user.useruuid !== loggedUser.useruuid) { + Instance.getRawConn().get(`/v1/nemt/users/member/${user.useruuid}`) + .then(function (res) { + state.setState(Object.assign(state.state, { user: res.data, showUserSelection: true, userSelectionText: `${res.data.member} - ${res.data.name}` })); + }) + .catch(err => { + if (err.response.status !== 422) { + console.error(err); + } + }); + } + + let visitTime = new Date(new Date().getTime() + (1 * 60 * 60 * 1000)); + let visitDate = visitTime; + let pickupTime = new Date(visitTime.getTime() - (0.5 * 60 * 60 * 1000)); + let pickupTimeReturn = new Date(visitTime.getTime() - (0.5 * 60 * 60 * 1000)); + + this.setState(Object.assign(this.state, { + visitDate: visitDate, + visitTime: visitTime, + pickupTime: pickupTime, + pickupTimeReturn: pickupTimeReturn, + })); + } + //for snackbar + handleTouchTap() { + this.setState(Object.assign(this.state, { + open: true, + })); + }; + + handleRequestClose(state) { + let self = state; + self.setState(Object.assign(self.state, { + open: false, + })); + }; + + handleNext(state) { + let self = state; + const { stepIndex } = self.state; + + console.log('Step Index: ', stepIndex) + switch (stepIndex) { + case 0: + const eligibility = { + "subscriber": { + "patient_type": self.state.user.type, + "subscriber_id": self.state.user.member, + "name": { + "first": self.state.user.first, + "last": self.state.user.last + }, + "demographic_info": { + "date_of_birth": self.state.user.birthdate, + "gender": self.state.user.gender + } + } + }; + + Instance.getRawConn().post('/v1/nemt/eligibility', eligibility).then(function (res) { + self.setState(Object.assign(self.state, { stepIndex: stepIndex + 1, user: res.data })); + }).catch(err => { + if (err.response.status === 403) { + self.setState(Object.assign(self.state, { + showValidationErrors: true, + validationErrors: [err.response.data], + })); + } else { + console.error(err); + } + }); + break; + case 2: + self.handleTouchTap(); + const visit = { + "user": { + "name": `${self.state.user.first} ${self.state.user.last}`, + "first": self.state.user.first, + "last": self.state.user.last, + "gender": self.state.user.gender, + "member": self.state.user.member, + "birthdate": self.state.user.birthdate, + "type": self.state.user.type, + "email": self.state.user.email, + "phonenumber": self.state.user.phonenumber + }, + "visit_datetime": self.state.visitTime, + "pickup_datetime": self.state.pickupTime, + "external_id": self.state.visit_external_id, + "provider": self.state.destination.raw + }; + + Instance.getRawConn().post('/v1/nemt/visits/', visit).then(function (res) { + window.location.href = '/#/app/table/visits'; + }).catch(console.error); + break; + default: + if (stepIndex < 3) { + self.setState(Object.assign(self.state, { stepIndex: stepIndex + 1 })); + } + }; + }; + + diffMinutes(dt2, dt1) { + var diff = (dt2.getTime() - dt1.getTime()) / 1000; + diff /= 60; + return Math.abs(Math.round(diff)); + } + + handlePrev(state) { + let self = state; + const { stepIndex } = self.state; + if (stepIndex > 0) { + self.setState(Object.assign(self.state, { stepIndex: stepIndex - 1 })); + } + }; + + handleChange(value, state) { + let self = state + self.setState(Object.assign(self.state, { + rideTypeValue: parseInt(value.target.defaultValue) + })); + }; + + handleProvider(value, state) { + let self = state; + console.log(value); + self.setState(Object.assign(self.state, { + providerID: value.value, + providerName: value.text + })); + }; + + handleDate(event, date, state) { + let self = state + let visitTime = new Date(date.getTime() + (1 * 60 * 60 * 1000)); + let visitDate = date; + let pickupTime = new Date(visitTime.getTime() - (0.5 * 60 * 60 * 1000)); + let pickupTimeReturn = new Date(visitTime.getTime() - (0.5 * 60 * 60 * 1000)); + + self.setState(Object.assign(self.state, { + visitDate: visitDate, + visitTime: visitTime, + pickupTime: pickupTime, + pickupTimeReturn: pickupTimeReturn, + })); + } + + handleTime(value, date, state) { + let self = state; + self.setState(Object.assign(self.state, { + visitDate: date, + visitTime: date, + pickupTime: new Date(date.getTime() - (0.5 * 60 * 60 * 1000)), + pickupTimeReturn: new Date(date.getTime() - (0.5 * 60 * 60 * 1000)), + })); + } + + handlePickupTime(value, date, state) { + let self = state; + console.log('Pickup Time', date); + self.setState(Object.assign(self.state, { + pickupTime: date, + pickupTimeReturn: date + })); + } + + handlePickupTimeReturn(value, date, state) { + let self = state; + self.setState(Object.assign(self.state, { + return_time: date, + pickupTimeReturn: date, + pickupTimeReturnDisplayMode: 'block' + })); + } + + handlePickup(value) { + console.log(value); + this.setState(Object.assign(this.state, { + pickupLocation: value.text + })); + }; + + handleExternalID(e, value, state) { + let self = state; + self.setState(Object.assign(self.state, { + visit_external_id: value + })); + } + + handleNotes(e, value, state) { + let self = state + self.setState(Object.assign(self.state, { + notes: value + })); + } + + handleChangeVisitType(event, index, value, state) { + let self = state; + + let trip_type = { + key: value.selectField, + } + + // console.log(event, index, value, state); + // console.log(trip_type); + + + self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: value.pickupTimeReturnDisplayMode, trip_type: trip_type, pickupTimeHide: value.pickupTimeHide })); + } + + renderStepActions(step, state) { + let self = state; + return ( +
    + {step !== 2 && ( + self.handleNext(self)} + style={{ marginRight: 12 }} + /> + )} + {step === 2 && ( + self.handleNext(self)} + style={{ marginRight: 12 }} + href="" + /> + )} + {step > 0 && ( + self.handlePrev(self)} + /> + )} +
    + ); + } + + // checkValue = (value) => { + // return value === this.state.rideTypeValue; + // } + updateCheck() { + this.setState((oldState) => { + return { + checked: !oldState.checked, + }; + }); + } + + getLocation() { + var defaultPlace = { + coords: { + latitude: 41.851382, + longitude: -87.675980 + } + } + if (navigator.geolocation) { + // this.setPosition(defaultPlace); + navigator.geolocation.getCurrentPosition(this.setPosition); + } else { + this.setPosition(defaultPlace); + } + } + + setPosition(position) { + localStorage.setItem('position', JSON.stringify({ latitude: position.coords.latitude, longitude: position.coords.longitude })); + } + + handleProviderChanged(res, state) { + let self = state; + + let destination = { + id: res.id, + name: res.name, + lat: res.lat, + lng: res.lng, + address: res.address, + raw: res.raw + } + const name = res.name; + + if (self.state.origin && self.state.origin.lat && self.state.origin.lng) { + let url = self.state.origin.lat + '/' + self.state.origin.lng + '/' + destination.lat + '/' + destination.lng + Instance.getRawConn().get('/v1/nemt/rides/eta/' + url).then(function (res) { + let obj = { + distance_miles: res.data.cost_estimates[0].estimated_distance_miles, + duration_seconds: res.data.cost_estimates[0].estimated_duration_seconds, + formatted_time: self.formatTime(res.data.cost_estimates[0].estimated_duration_seconds), + showed: true, + } + + localStorage.setItem('eta', JSON.stringify(obj)); + console.log('ETA Info', obj); + if (!self.state.eta.showed) { + + self.setState(Object.assign(self.state, { + message: ('BOOKING...Estimated Distance: ' + obj.distance_miles + ' miles\nEstimated Time: ' + obj.formatted_time), + open: true, + })); + + } + + self.setState(Object.assign(self.state, { + eta: obj, + buttonProviderText: name, + providerName: name, + destination: destination + })); + }); + } else { + self.setState(Object.assign(self.state, { + buttonProviderText: name, + providerName: name, + destination: destination + })); + } + } + + formatTime(sec_num) { + var hours = Math.floor(sec_num / 3600); + var minutes = Math.floor((sec_num - (hours * 3600)) / 60); + var seconds = sec_num - (hours * 3600) - (minutes * 60); + + if (hours < 10) { hours = "0" + hours; } + if (minutes < 10) { minutes = "0" + minutes; } + if (seconds < 10) { seconds = "0" + seconds; } + return hours + ':' + minutes + ':' + seconds; + } + + handlePickupChanged = (res, state) => { + let origin = { + id: res.id, + name: res.name, + lat: res.lat, + lng: res.lng, + address: res.address + } + + const name = res.name; + + if (state.state.destination && state.state.destination.lat && state.state.destination.lng) { + let url = origin.lat + '/' + origin.lng + '/' + state.state.destination.lat + '/' + state.state.destination.lng + Instance.getRawConn().get('/v1/nemt/rides/eta/' + url).then(function (res) { + let obj = { + distance_miles: res.data.cost_estimates[0].estimated_distance_miles, + duration_seconds: res.data.cost_estimates[0].estimated_duration_seconds, + formatted_time: state.formatTime(res.data.cost_estimates[0].estimated_duration_seconds), + showed: true, + } + + localStorage.setItem('eta', JSON.stringify(obj)); + if (!state.state.eta.showed) { + + state.setState(Object.assign(state.state, { + message: ('BOOKING...Estimated Distance: ' + obj.distance_miles + ' miles\nEstimated Time: ' + obj.formatted_time), + open: true, + })); + + } + + state.setState(Object.assign(state.state, { + eta: obj, + buttonPickupText: name, + pickupLocation: name, + origin: origin, + })); + }); + } else { + state.setState(Object.assign(state.state, { + buttonPickupText: name, + pickupLocation: name, + origin: origin + })); + } + + } + + handleUser(user) { + this.setState(Object.assign(this.state, { user: user })); + } + + handleValidationErrosDialogDismiss() { + this.setState(Object.assign(this.state, { + showValidationErrors: false + })); + } + + render() { + // const { stepIndex } = this.state; + this.getLocation(); + + const state = this; + let userSelection; + + let pickupTimeSelector; + if (this.state.pickupTimeReturnDisplayMode !== 'none') { + pickupTimeSelector = ( + this.handlePickupTimeReturn(e, d, this)} + minutesStep={5} + />) + } + + let pickupTime = ( this.handlePickupTime(e, d, this)} + minutesStep={5} + />); + if (this.state.pickupTimeHide) pickupTime = null; + + if (this.state.showUserSelection && this.state.users.length > 0) { + const handleAutocomplete = (u) => { + state.setState(Object.assign(state.state, { user: u, userSelectionText: u.userdata })); + } + const datasourceConfig = { text: 'userdata', value: 'useruuid' } + userSelection = ( +
    + (key.toLowerCase().indexOf(searchText.toLowerCase()) !== -1)} maxSearchResults={5} onNewRequest={handleAutocomplete} searchText={this.state.userSelectionText} /> +
    + ); + } else if (this.state.showUserSelection && this.state.users.length === 0) { + userSelection = (
    + Loading... +
    ); + } else { + userSelection = (
    + {this.state.user.member} - {this.state.user.name} +
    ); + } + + return ( +
    +

    Create Visit

    +
    +
    + +
    + + + + this.setState({ stepIndex: 0 })}> + Member + + +
    + + + +
    + + {this.renderStepActions(0, this)} + + + + + this.setState({ stepIndex: 1 })}> + Provider + + +
    + this.handleProviderChanged(provider, this)} fontSize={12} locationType="provider" loadSuggestion={true} address={this.state.destination} /> + {/*
    */} + + {this.renderStepActions(1, this)} + + + + + + this.setState({ stepIndex: 2 })}> + Visit Details + + +
    +
    + this.handleDate(e, d, this)} shouldDisableDate={disableWeekends} value={this.state.visitDate} /> + this.handleTime(e, d, this)} + minutesStep={5} + /> +
    +
    +
    + this.handleExternalID(e, v, this)} value={this.state.visit_external_id} /> +
    + + + + {/* */} + {this.renderStepActions(1, this)} + + + + + +
    + +
    +
    +
    +

    Complete steps 1 - 3 to create a Visit

    +
    +
    +
    +
    +
    + this.handleRequestClose(this)} + /> + +
    +
    + ); + } +} + +export default VerticalNonLinear; diff --git a/src/routes/app/routes/forms/routes/visit/index.js b/src/routes/app/routes/forms/routes/visit/index.js new file mode 100644 index 0000000..616abb0 --- /dev/null +++ b/src/routes/app/routes/forms/routes/visit/index.js @@ -0,0 +1,8 @@ +module.exports = { + path: 'visit/:uuid', + getComponent(nextState, cb) { + require.ensure([], (require) => { + cb(null, require('./components/Steppers')); + }); + } +}; diff --git a/src/routes/app/routes/forms/routes/visitRide/components/Steppers.js b/src/routes/app/routes/forms/routes/visitRide/components/Steppers.js new file mode 100644 index 0000000..802cf71 --- /dev/null +++ b/src/routes/app/routes/forms/routes/visitRide/components/Steppers.js @@ -0,0 +1,14 @@ +import React from 'react'; +import QueueAnim from 'rc-queue-anim'; +import VerticalNonLinear from './VerticalNonLinear'; +const Stepper = (props) => { + return ( +
    + +
    +
    +
    + ); +}; + +module.exports = Stepper; diff --git a/src/routes/app/routes/forms/routes/visitRide/components/VerticalNonLinear.js b/src/routes/app/routes/forms/routes/visitRide/components/VerticalNonLinear.js new file mode 100644 index 0000000..1b8bf20 --- /dev/null +++ b/src/routes/app/routes/forms/routes/visitRide/components/VerticalNonLinear.js @@ -0,0 +1,910 @@ +import React, { Component } from 'react'; +import { + Step, + Stepper, + StepButton, + StepContent, +} from 'material-ui/Stepper'; +import RaisedButton from 'material-ui/RaisedButton'; +import FlatButton from 'material-ui/FlatButton'; +import QueueAnim from 'rc-queue-anim'; +import { RadioButton, RadioButtonGroup } from 'material-ui/RadioButton'; +import ActionFavorite from 'material-ui/svg-icons/action/favorite'; +import ActionFavoriteBorder from 'material-ui/svg-icons/action/favorite-border'; +import AutoComplete from 'material-ui/AutoComplete'; +import SelectField from 'material-ui/SelectField'; +import MenuItem from 'material-ui/MenuItem'; +import { Tabs, Tab } from 'material-ui/Tabs'; +// import Slider from 'material-ui/Slider'; +import TimePicker from 'material-ui/TimePicker'; +import DatePicker from 'material-ui/DatePicker'; +import TextField from 'material-ui/TextField'; +// import Toggle from 'material-ui/Toggle'; +import Snackbar from 'material-ui/Snackbar'; +import { NEMTLocation } from '../../../../../components/NEMTLocation'; +import { request } from 'https'; +import Divider from 'material-ui/Divider'; +import Paper from 'material-ui/Paper'; +import Dialog from 'material-ui/Dialog'; +import Close from 'material-ui/svg-icons/navigation/close' +import CommunicationCall from 'material-ui/svg-icons/communication/call' +import Message from 'material-ui/svg-icons/communication/message' +import Instance from '../../../../../../../components/Connection'; +import ValidationErrorsInfoDialog from '../../../../../../../components/Shared/ValidationErrorsInfoDialog'; +import Checkbox from 'material-ui/Checkbox'; +import Popover from 'material-ui/Popover'; + +let DateTimeFormat; +const roundingTime = 1000 * 60 * 5; //5 minutes + + +DateTimeFormat = global.Intl.DateTimeFormat; + + +class SignUp extends React.Component { + constructor(props) { + super(props); + + this.props = props; + } + + componentWillReceiveProps = (nextProps) => { + this.props = nextProps; + } + + handleEmail = (event) => { + if (this.props.onUserChanged) { + const user = this.props.user; + user.email = event.target.value; + this.props.onUserChanged(user); + } + }; + + handlePhone = (event) => { + let phone = event.target.value; + if (phone.indexOf("+1") < 0 && phone.length == 10) { + phone = "+1" + phone; + phone = phone.substring(0, 12); + } + + if (this.props.onUserChanged) { + const user = this.props.user; + user.phonenumber = event.target.value; + this.props.onUserChanged(user); + } + }; + + render() { + return ( +
    +
    + {/*
    */} + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + ); + } +} + +export class AdditionalPassengerSelect extends React.Component { + state = { + open: false, + additionalPassenger: + { + passengerType: '', + seatType: '', + } + }; + + handleOpen = () => { + this.setState({ open: true }); + }; + + + handlePassengerTypeChange = (e, i, v, state) => { + this.setState({ additionalPassenger: { passengerType: v } }); + }; + + handleSeatTypeChange = (e, i, v, state) => { + this.setState({ additionalPassenger: { seatType: v } }); + }; + + handleClose = () => { + this.setState({ open: false }); + }; + + render() { + const actions = [ + , + , + ]; + + return ( +
    + + + this.handlePassengerTypeChange(e, i, v, this)} + autoWidth={true} + > + + + + + this.handleSeatTypeChange(e, i, v, this)} + autoWidth={true} + > + + + + + + +
    + ); + } +} + +const names = [ + 'Service Animal', + 'Cane / Quad Cane', + 'Electric Wheelchair', + 'Oxygen Tank', + 'Sign Language', + 'White Cane', + 'Leg Braces', + 'Crutches', + 'Manual Wheelchair', + 'Prothesis', + 'Walker', +]; + +export class MobilitySelect extends Component { + state = { + values: [], + }; + + handleChange = (event, index, values) => this.setState({ values }); + + menuItems(values) { + return names.map((name) => ( + -1} + value={name} + primaryText={name} + autoWidth={false} + style={{ width: 215 }} + /> + )); + } + + render() { + const { values } = this.state; + return ( + + {this.menuItems(values)} + + ); + } +} + +const selectStyles = { + customWidth: { + width: 35, + }, +}; + +var tripType = 'To Visit'; +var pickupTimeReturnDisplayMode = "none"; + + +export class RideTypeSelect extends Component { + constructor(props) { + super(props); + this.props = props; + this.state = { + value: 'to_visit', + pickupTimeReturnDisplayMode: 'none', + pickupTimeHide: false, + }; + } + + componentDidMount() { + this.setState(Object.assign(this.state, { value: this.props.value })); + } + + handleChange(event, index, value, state) { + let self = state + tripType = value; + switch (tripType) { + + case 'from_visit': + pickupTimeReturnDisplayMode = "none" + self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'none', value: 'from_visit', pickupTimeHide: false })); + break; + + case 'from_visit_call': + pickupTimeReturnDisplayMode = "none" + self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'none', value: 'from_visit_call', pickupTimeHide: true })); + break; + + + case 'to_visit': + pickupTimeReturnDisplayMode = "none" + self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'none', value: 'to_visit', pickupTimeHide: false })); + break; + + + case 'roundtrip': + pickupTimeReturnDisplayMode = "block" + self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'block', value: 'roundtrip', pickupTimeHide: false })); + break; + + case 'roundtrip_call': + pickupTimeReturnDisplayMode = "none"; + self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'none', value: 'roundtrip_call', pickupTimeHide: false })); + break; + + default: + self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'block', value: 'roundtrip', pickupTimeHide: false })); + break; + } + + if (this.props.handleChange) { + this.props.handleChange(event, index, { pickupTimeReturnDisplayMode: self.state.pickupTimeReturnDisplayMode, selectField: this.state.value, pickupTimeHide: this.state.pickupTimeHide }); + } + } + + render() { + return ( +
    + this.handleChange(e, i, v, this)} + autoWidth={false} + style={{ width: 230 }} + > + + + + + + +
    + ); + } +} + + +function disableWeekends(date) { + return date.getDay() === 0 || date.getDay() === 6; +} + +const styles = { + padding: '12px 18px', + marginBottom: 12, + fontWeight: 400, + maxWidth: 250, + radioButton: { + marginTop: 6 + }, + checkbox: { + marginTop: 16, fontWeight: 100, fontSize: 10 + }, +}; + + +function handleActive(tab) { + console.log(`A tab with this route property ${tab.props.route} was activated.`); +} + + +const + dataConfig = { text: 'text', value: 'value' }; + + +/** + * A basic vertical non-linear implementation + */ +class VerticalNonLinear extends React.Component { + constructor(props) { + super(props); + + let dateNow = new Date(); + + this.state = { + stepIndex: 0, + rideTypeValue: 0, + providerID: 0, + providerName: '', + visitDate: new Date(), + visitTime: new Date(Math.round(dateNow.getTime() / roundingTime) * roundingTime), + pickupLocation: null, + pickupTime: new Date(Math.round(dateNow.getTime() / roundingTime) * roundingTime), + pickupTimeReturn: new Date(Math.round(dateNow.getTime() / roundingTime) * roundingTime), + pickupTimeReturnDisplayMode: 'none', + open: false, + message: 'Booking Ride', + origin: {}, + destination: {}, + buttonPickupText: 'Member Address', + buttodDropOffText: 'Choose Drop-Off location', + buttonProviderText: 'Choose Provider', + user: null, + showUserSelection: true, + userSelectionText: '', + users: [], + visit_external_id: "", + notes: "", + pickupTimeReturnDisplayMode: "none", + eta: { + distance_miles: 0, + duration_seconds: 0, + formatted_time: 0, + showed: false, + }, + trip_type: { + key: "to_visit", + value: "" + }, + return_time: new Date(), + pickupTimeHide: false, + showValidationErrors: false, + validationErrors: [], + visit: { + visit_uuid: "", + visit_status: { + key: "", + value: "" + }, + user: { + useruuid: "", + name: "", + first: "", + last: "", + gender: "", + member: "", + birthdate: new Date(), + email: "", + phonenumber: "" + }, + visit_datetime: new Date(), + pickup_datetime: new Date(), + notes: "", + pickup_address_id: 33, + pickup: { + id: "" + }, + provider: { + provider_uuid: "", + internal_id: "", + muk_id: "", + name: "", + address: { + street_address_1: "", + city: "", + state: "", + zipcode: "", + country: "", + lat: 0, + long: 0, + phone_number: "" + }, + organization: { + id: "", + type: { + name: "", + key: "" + }, + name: "", + main: false, + active: false, + blocked: false, + suspended: false, + contacts: [], + addresses: [] + } + }, + trip_type: { + key: "", + value: "" + }, + visit_external_id: "" + } + }; + + this.handleUser = this.handleUser.bind(this); + } + + componentDidMount() { + let self = this; + let visit = { + uuid: this.props.params.uuid + } + + Instance.getRawConn().get(`/v1/nemt/visits/${visit.uuid}`) + .then(function (res) { + const visit = res.data; + visit.user.birthdate = new Date(visit.user.birthdate); + visit.visit_datetime = new Date(visit.visit_datetime); + self.setState(Object.assign(self.state, { visit: visit })); + }) + .catch(err => { + if (err.response.status !== 422) { + console.error(err); + } + }); + } + + //for snackbar + handleTouchTap() { + this.setState(Object.assign(this.state, { + open: true, + })); + }; + + handleRequestClose(state) { + let self = state; + self.setState(Object.assign(self.state, { + open: false, + })); + }; + + handleNext(state) { + let self = state; + const { stepIndex } = self.state; + if (stepIndex < 4) { + self.setState(Object.assign(self.state, { stepIndex: stepIndex + 1 })); + if (stepIndex === 3) { + self.handleTouchTap(); + + const visitRide = { + visit: self.state.visit, + trip_type: self.state.trip_type, + pickup_time: self.state.pickupTime, + return_time: self.state.return_time, + notes: self.state.notes, + }; + + if (self.diffMinutes(self.state.pickupTime, new Date()) > 10) { + visitRide.scheduled_pickup_range = { + range_ms: null, + timestamp_ms: new Date(self.state.pickupTime).getTime() + } + } + + Instance.getRawConn().post(`/v1/nemt/visits/${self.state.visit.visit_uuid}/ride`, visitRide).then(function (res) { + window.location.href = '/#/app/page/map/' + res.data.ride_uuid; + }).catch(error => { + if (error.response.status === 422) { + self.setState(Object.assign(self.state, { + showValidationErrors: true, + validationErrors: error.response.data.data + })); + } + }); + } + } + }; + + diffMinutes(dt2, dt1) { + var diff = (dt2.getTime() - dt1.getTime()) / 1000; + diff /= 60; + return Math.abs(Math.round(diff)); + } + + handlePrev(state) { + let self = state; + const { stepIndex } = self.state; + if (stepIndex > 0) { + self.setState(Object.assign(self.state, { stepIndex: stepIndex - 1 })); + } + }; + + handleChange(value, state) { + let self = state + self.setState(Object.assign(self.state, { + rideTypeValue: parseInt(value.target.defaultValue) + })); + }; + + handleDate(event, date, state) { + let self = state + let visitTime = new Date(Math.round((date.getTime() + (1 * 60 * 60 * 1000)) / roundingTime) * roundingTime); + let visitDate = date; + let pickupTime = new Date(Math.round((visitTime.getTime() - (0.5 * 60 * 60 * 1000)) / roundingTime) * roundingTime); + let pickupTimeReturn = new Date(Math.round((visitTime.getTime() - (0.5 * 60 * 60 * 1000)) / roundingTime) * roundingTime); + + self.setState(Object.assign(self.state, { + visitDate: visitDate, + visitTime: visitTime, + pickupTime: pickupTime, + pickupTimeReturn: pickupTimeReturn, + })); + } + + handleTime(value, date, state) { + let self = state; + self.setState(Object.assign(self.state, { + visitDate: date, + visitTime: date, + pickupTime: new Date(date.getTime() - (0.5 * 60 * 60 * 1000)), + pickupTimeReturn: new Date(date.getTime() - (0.5 * 60 * 60 * 1000)), + })); + } + + handlePickupTime(value, date, state) { + let self = state; + console.log('Pickup Time', date); + self.setState(Object.assign(self.state, { + pickupTime: date, + pickupTimeReturn: date + })); + } + + handlePickupTimeReturn(value, date, state) { + let self = state; + self.setState(Object.assign(self.state, { + return_time: date, + pickupTimeReturn: date, + pickupTimeReturnDisplayMode: 'block' + })); + } + + handlePickup(value) { + console.log(value); + this.setState(Object.assign(this.state, { + pickupLocation: value.text + })); + }; + + handleNotes(e, value, state) { + let self = state + self.setState(Object.assign(self.state, { + notes: value + })); + } + + handleChangeVisitType(event, index, value, state) { + let self = state; + + let trip_type = { + key: value.selectField, + } + + self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: value.pickupTimeReturnDisplayMode, trip_type: trip_type, pickupTimeHide: value.pickupTimeHide })); + } + + renderStepActions(step, state) { + let self = state; + return ( +
    + {step !== 2 && ( + self.handleNext(self)} + style={{ marginRight: 12 }} + /> + )} + {step === 2 && ( + self.handleNext(self)} + style={{ marginRight: 12 }} + href="" + /> + )} + {step > 0 && ( + self.handlePrev(self)} + /> + )} +
    + ); + } + + handleValidationErrosDialogDismiss() { + this.setState(Object.assign(this.state, { + showValidationErrors: false + })); + } + + handleUser(user) { + const visit = this.state.visit; + visit.user = user; + this.setState(Object.assign(this.state, { visit: visit })); + + console.log(user); + } + + render() { + const state = this; + let userSelection; + + let pickupTimeSelector; + if (this.state.pickupTimeReturnDisplayMode !== 'none') { + pickupTimeSelector = ( + this.handlePickupTimeReturn(e, d, this)} + minutesStep={5} + />) + } + + let pickupTime = ( this.handlePickupTime(e, d, this)} + minutesStep={5} + />); + if (this.state.pickupTimeHide) pickupTime = null; + + if (this.state.showUserSelection && this.state.users.length > 0) { + const handleAutocomplete = (u) => { + let userHomeAddress = null; + u.addresses.forEach(address => { + if (address.address_type === ADDRESS_TYPE_HOME) { + userHomeAddress = address; + } + }); + if (userHomeAddress != null) { + userHomeAddress.name = "Home"; + state.handlePickupChanged(userHomeAddress, state); + } + state.setState(Object.assign(state.state, { user: u, userSelectionText: u.userdata })); + } + const datasourceConfig = { text: 'userdata', value: 'useruuid' } + userSelection = ( +
    + (key.toLowerCase().indexOf(searchText.toLowerCase()) !== -1)} maxSearchResults={5} onNewRequest={handleAutocomplete} searchText={this.state.userSelectionText} /> +
    + ); + } else if (this.state.showUserSelection && this.state.users.length === 0) { + userSelection = (
    + Loading... +
    ); + } else { + userSelection = (
    + {this.state.user.member} - {this.state.user.name} +
    ); + } + + return ( +
    +

    Book Ride from Visit

    +
    +
    + +
    + + + + + this.setState({ stepIndex: 0 })}> + Member + + +
    + + + {this.renderStepActions(0, this)} +
    +
    + + + this.setState({ stepIndex: 1 })}> + Provider + + +
    + {this.state.visit.provider.name}
    + {this.state.visit.provider.address.street_address_1}
    + {this.state.visit.provider.address.city}, {this.state.visit.provider.address.state} ({this.state.visit.provider.address.zipcode.substr(0, 5)}) +
    + {this.renderStepActions(1, this)} +
    +
    + + + + this.setState({ stepIndex: 2 })}> + Visit Details + + +
    +
    + this.handleDate(e, d, this)} shouldDisableDate={disableWeekends} value={this.state.visit.visit_datetime} disabled={true} /> + this.handleTime(e, d, this)} + minutesStep={5} disabled={true} + /> +
    +
    +
    + this.handleExternalID(e, v, this)} value={this.state.visit.visit_external_id} disable={true} /> +
    + + + + {/* */} + {this.renderStepActions(1, this)} + + + + + this.setState({ stepIndex: 3 })}> + Trip Details + + +
    + this.handleChangeVisitType(e, i, v, this)} value={this.state.trip_type.key} /> + {pickupTime} + {pickupTimeSelector} + + + this.handleNotes(e, v, this)} + value={this.state.notes} multiLine={true} + maxlength={250} + rows={1} + /> + + {this.renderStepActions(2, this)} +
    +
    + +
    + +
    +
    +
    +

    Complete steps 1 - 4 to schedule your ride!

    +
    +
    +
    +
    +
    + this.handleRequestClose(this)} + /> + +
    +
    + ); + } +} + +export default VerticalNonLinear; diff --git a/src/routes/app/routes/forms/routes/visitRide/index.js b/src/routes/app/routes/forms/routes/visitRide/index.js new file mode 100644 index 0000000..150aa86 --- /dev/null +++ b/src/routes/app/routes/forms/routes/visitRide/index.js @@ -0,0 +1,8 @@ +module.exports = { + path: 'visitride/:uuid', + getComponent(nextState, cb) { + require.ensure([], (require) => { + cb(null, require('./components/Steppers')); + }); + } +}; diff --git a/src/routes/app/routes/tables/routes/visits/components/Datatable.js b/src/routes/app/routes/tables/routes/visits/components/Datatable.js index f658bdc..edc66b8 100644 --- a/src/routes/app/routes/tables/routes/visits/components/Datatable.js +++ b/src/routes/app/routes/tables/routes/visits/components/Datatable.js @@ -38,18 +38,22 @@ const getDTList = function (member) { let list = []; member.forEach((r, i) => { + let bookRide = ''; + if (r.trip_type.key === 'no_trip') { + bookRide = (Book Ride) + } + list.push( {moment(r.visit_datetime).format('MM/DD/YYYY - h:mm a')} {r.provider.name} {r.user.name} + {bookRide} {r.user.member} - {/* {r.visit_status.value} */} - {r.provider.id} + {r.provider.provider_uuid} {r.visit_uuid} {r.visit_external_id} - {r.created_user.name} {moment(r.created).format('MM/DD/YYYY - h:mm a')} {moment(r.updated).format('MM/DD/YYYY - h:mm a')} @@ -232,11 +236,10 @@ class DatatableComponent extends React.Component { Visit Time Provider Member + Ride Rides Subscriber ID - {/* Status */} Provider ID - Visit ID External ID Scheduler diff --git a/src/utils/authorization/index.js b/src/utils/authorization/index.js index 04ab8f9..e956552 100644 --- a/src/utils/authorization/index.js +++ b/src/utils/authorization/index.js @@ -14,5 +14,6 @@ export { default as providerScheduler } from './profiles/providerScheduler'; export { default as superAdmin } from './profiles/superAdmin'; export { default as support } from './profiles/support'; export { default as techsupportAdmin } from './profiles/techsupportAdmin'; +export { default as visitReporter } from './profiles/visitReporter'; export default authorization; diff --git a/src/utils/authorization/profiles/visitReporter.js b/src/utils/authorization/profiles/visitReporter.js new file mode 100644 index 0000000..4afa311 --- /dev/null +++ b/src/utils/authorization/profiles/visitReporter.js @@ -0,0 +1,7 @@ +import authorization from '../authorization'; + +const visitReporter = authorization({ + VIRPT: ['provider'], +}); + +export default visitReporter;