You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
274 lines
7.3 KiB
274 lines
7.3 KiB
import { duration, utc } from "moment"; |
|
import React, { Component } from "react"; |
|
import DatePicker from "react-datepicker"; |
|
import { connect } from "react-redux"; |
|
import { Redirect } from "react-router-dom"; |
|
import { |
|
Container, |
|
Dropdown, |
|
Form, |
|
Header, |
|
Label, |
|
TextArea |
|
} from "semantic-ui-react"; |
|
|
|
import { |
|
setFormEmployeeUUID, |
|
setFormPriceUUID, |
|
setFormShiftStartTime, |
|
setFormShiftDuration, |
|
setFormShiftNote, |
|
setClearCshiftState, |
|
setFormShiftDates |
|
} from "../../../actions/cShift/reducer.actions"; |
|
|
|
import "react-datepicker/dist/react-datepicker.css"; |
|
import "./shiftStartTimeOverrides.css"; |
|
|
|
const CShiftDurationOptions = []; |
|
for (let min = 60; min <= 480; min += 30) { |
|
let displayText = duration(min, "minutes").humanize(); |
|
if (min % 60) { |
|
displayText = duration(Math.floor(min / 60), "hours").humanize(); |
|
displayText += ` and ${duration(min % 60, "minutes").humanize()}`; |
|
} |
|
CShiftDurationOptions.push({ |
|
key: min, |
|
value: min, |
|
text: displayText |
|
}); |
|
} |
|
|
|
class ClientAddShiftForm extends Component { |
|
componentWillMount = () => { |
|
this.props.dispatch(setClearCshiftState()); |
|
}; |
|
|
|
changeSelectedEmployee = (e, { value }) => { |
|
if (value !== this.props.employeeUUID) { |
|
this.props.dispatch(setFormPriceUUID("")); |
|
} |
|
this.props.dispatch(setFormEmployeeUUID(value)); |
|
}; |
|
|
|
changeSelectedPrice = (e, { value }) => { |
|
this.props.dispatch(setFormPriceUUID(value)); |
|
}; |
|
|
|
/** |
|
* change handler for shift start time selector. |
|
* @param momentTime - instance of moment (but we only care about the time) |
|
*/ |
|
changeShiftStartTime = momentTime => { |
|
this.props.dispatch(setFormShiftStartTime(momentTime)); |
|
}; |
|
|
|
changeShiftDuration = (e, { value }) => { |
|
this.props.dispatch(setFormShiftDuration(value)); |
|
}; |
|
|
|
changeShiftNote = event => { |
|
this.props.dispatch(setFormShiftNote(event.target.value)); |
|
}; |
|
|
|
/** |
|
* change handler for shift date selector |
|
* @param momentDate - instance of moment (but we only care about the day) |
|
*/ |
|
handleSelectDate = momentDate => { |
|
const shiftDatesCopy = { ...this.props.shiftDates }; |
|
const key = momentDate.format("YYYY-MM-DD"); |
|
if (shiftDatesCopy.hasOwnProperty(key)) { |
|
delete shiftDatesCopy[key]; |
|
} else { |
|
shiftDatesCopy[key] = momentDate; |
|
} |
|
this.props.dispatch(setFormShiftDates(shiftDatesCopy)); |
|
}; |
|
|
|
render() { |
|
const { |
|
selfUser, |
|
employeeUUID, |
|
priceUUID, |
|
startTime, |
|
duration, |
|
note, |
|
shiftDates |
|
} = this.props; |
|
|
|
if (!selfUser.client) { |
|
return <Redirect to="/" />; |
|
} |
|
|
|
const employeeChoices = selfUser.client.employees |
|
.filter(employee => !employee.deleted && !!employee.approved) |
|
.map(({ uuid, provider }) => ({ |
|
key: uuid, |
|
value: uuid, |
|
text: provider.email |
|
})); |
|
|
|
const priceChoices = []; |
|
if (employeeUUID) { |
|
const employee = selfUser.client.employees.find(emp => { |
|
return emp && emp.uuid === employeeUUID; |
|
}); |
|
priceChoices.push( |
|
...employee.prices |
|
.filter(price => !price.deleted) |
|
.map(({ amount, uuid, work_type }) => ({ |
|
key: uuid, |
|
value: uuid, |
|
text: work_type.label, |
|
content: ( |
|
<Header> |
|
<Label |
|
circular |
|
empty |
|
style={{ |
|
backgroundColor: work_type.color, |
|
borderColor: work_type.color |
|
}} |
|
/> |
|
{work_type.label} |
|
<Header.Subheader |
|
style={{ paddingLeft: "2em" }} |
|
content={`Hourly Rate: ${amount}`} |
|
/> |
|
</Header> |
|
) |
|
})) |
|
); |
|
} |
|
|
|
const selectedShiftDates = Object.keys(shiftDates).map( |
|
key => shiftDates[key] |
|
); |
|
return ( |
|
<ClientAddShiftFormView |
|
user={selfUser} |
|
employeeChoices={employeeChoices} |
|
priceChoices={priceChoices} |
|
employeeUUID={employeeUUID} |
|
priceUUID={priceUUID} |
|
startTime={startTime} |
|
duration={duration} |
|
note={note} |
|
selectedShiftDates={selectedShiftDates} |
|
changeSelectedEmployee={this.changeSelectedEmployee} |
|
changeSelectedPrice={this.changeSelectedPrice} |
|
changeShiftStartTime={this.changeShiftStartTime} |
|
changeShiftDuration={this.changeShiftDuration} |
|
changeShiftNote={this.changeShiftNote} |
|
handleSelectDate={this.handleSelectDate} |
|
/> |
|
); |
|
} |
|
} |
|
|
|
function mapStateToProps(state) { |
|
return { ...state.cShift, selfUser: state.user.selfUser }; |
|
} |
|
|
|
const ClientAddShiftFormView = ({ |
|
user, |
|
employeeChoices, |
|
priceChoices, |
|
employeeUUID, |
|
priceUUID, |
|
startTime, |
|
duration, |
|
note, |
|
selectedShiftDates, |
|
changeSelectedEmployee, |
|
changeSelectedPrice, |
|
changeShiftStartTime, |
|
changeShiftDuration, |
|
changeShiftNote, |
|
handleSelectDate |
|
}) => ( |
|
<Container> |
|
<Header>Schedule Shifts</Header> |
|
<Form> |
|
<Form.Group widths="equal"> |
|
<Form.Field> |
|
<label>Employee</label> |
|
<Dropdown |
|
onChange={changeSelectedEmployee} |
|
options={employeeChoices} |
|
placeholder="Select employee" |
|
selection |
|
fluid |
|
search |
|
noResultsMessage="No approved employees found." |
|
value={employeeUUID} |
|
/> |
|
</Form.Field> |
|
<Form.Field> |
|
<label>Price</label> |
|
<Dropdown |
|
onChange={changeSelectedPrice} |
|
options={priceChoices} |
|
placeholder="Select price" |
|
selection |
|
fluid |
|
search |
|
noResultsMessage="No prices for given employee." |
|
value={priceUUID} |
|
/> |
|
</Form.Field> |
|
<Form.Field> |
|
<label>Shift Start Time</label> |
|
<DatePicker |
|
selected={startTime} |
|
onChange={changeShiftStartTime} |
|
showTimeSelect |
|
showTimeSelectOnly |
|
timeIntervals={30} |
|
dateFormat="LT Z" |
|
timeFormat="hh:mm" |
|
placeholderText="Select shift start time" |
|
/> |
|
</Form.Field> |
|
<Form.Field> |
|
<label>Shift Duration</label> |
|
<Dropdown |
|
onChange={changeShiftDuration} |
|
options={CShiftDurationOptions} |
|
placeholder="Select duration" |
|
selection |
|
fluid |
|
value={duration} |
|
/> |
|
</Form.Field> |
|
</Form.Group> |
|
<Form.Field> |
|
<label>Note</label> |
|
<TextArea |
|
placeholder="Employee notes" |
|
value={note} |
|
onChange={changeShiftNote} |
|
/> |
|
</Form.Field> |
|
<Form.Field style={{ textAlign: "center" }}> |
|
<label>Dates</label> |
|
<DatePicker |
|
inline |
|
onSelect={handleSelectDate} |
|
highlightDates={selectedShiftDates} |
|
monthsShown={2} |
|
// https://github.com/Hacker0x01/react-datepicker/pull/1360 |
|
peekNextMonth={false} // this is broken? Fixed in PR 1360 |
|
minDate={utc(new Date()).add(1, "day")} |
|
maxDate={utc(new Date()) |
|
.add(1, "month") |
|
.endOf("month")} |
|
/> |
|
</Form.Field> |
|
<Form.Button>Schedule Shift</Form.Button> |
|
</Form> |
|
</Container> |
|
); |
|
|
|
export default connect(mapStateToProps)(ClientAddShiftForm);
|
|
|