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.
447 lines
14 KiB
447 lines
14 KiB
import { utc, ISO_8601, duration } from "moment"; |
|
import React, { Component, Fragment } from "react"; |
|
import { connect } from "react-redux"; |
|
import { Redirect, Link } from "react-router-dom"; |
|
import { |
|
Button, |
|
Container, |
|
Dropdown, |
|
Header, |
|
Item, |
|
Segment, |
|
Pagination, |
|
Loader, |
|
Label, |
|
List |
|
} from "semantic-ui-react"; |
|
import { |
|
getEmployerFromPrice, |
|
getPriceFromPrice |
|
} from "./ProviderShiftsShared"; |
|
import { |
|
setPShiftPage, |
|
setPShiftApprovalFilter, |
|
setPShiftCompletedFilter, |
|
setPShiftClientFilter, |
|
setPShiftWorkTypeFilter |
|
} from "../../../actions/pShift/reducer.actions"; |
|
import { |
|
getPShiftsRequest, |
|
updatePShiftRequest |
|
} from "../../../actions/pShift/saga.actions"; |
|
import ShiftLabel from "../../Shared/ShiftLabel"; |
|
|
|
class ProviderShifts extends Component { |
|
constructor(props) { |
|
super(props); |
|
this.state = { |
|
pageSize: 10 // client can't control this, but set here just in case |
|
}; |
|
} |
|
|
|
componentWillMount = () => { |
|
this.props.dispatch( |
|
getPShiftsRequest({ |
|
page: this.props.page, |
|
provider_approved: this.props.approvalFilter, |
|
completed: this.props.completedFilter, |
|
manage: this.props.clientFilter, |
|
work_type: this.props.workTypeFilter, |
|
page_size: this.state.pageSize |
|
}) |
|
); |
|
}; |
|
|
|
handlePaginationChange = (event, { activePage }) => { |
|
this.props.dispatch( |
|
getPShiftsRequest({ |
|
page: activePage, |
|
provider_approved: this.props.approvalFilter, |
|
completed: this.props.completedFilter, |
|
manage: this.props.clientFilter, |
|
work_type: this.props.workTypeFilter, |
|
page_size: this.state.pageSize |
|
}) |
|
); |
|
this.props.dispatch(setPShiftPage(activePage)); |
|
}; |
|
|
|
handleChangeApprovalFilter = (event, { value }) => { |
|
this.props.dispatch( |
|
getPShiftsRequest({ |
|
page: 1, |
|
provider_approved: value, |
|
completed: this.props.completedFilter, |
|
manage: this.props.clientFilter, |
|
work_type: this.props.workTypeFilter, |
|
page_size: this.state.pageSize |
|
}) |
|
); |
|
this.props.dispatch(setPShiftApprovalFilter(value)); |
|
this.props.dispatch(setPShiftPage(1)); |
|
}; |
|
|
|
handleChangeCompletedFilter = (event, { value }) => { |
|
this.props.dispatch( |
|
getPShiftsRequest({ |
|
page: 1, |
|
provider_approved: this.props.approvalFilter, |
|
completed: value, |
|
manage: this.props.clientFilter, |
|
work_type: this.props.workTypeFilter, |
|
page_size: this.state.pageSize |
|
}) |
|
); |
|
this.props.dispatch(setPShiftCompletedFilter(value)); |
|
this.props.dispatch(setPShiftPage(1)); |
|
}; |
|
|
|
handleChangeClientFilter = (event, { value }) => { |
|
this.props.dispatch( |
|
getPShiftsRequest({ |
|
page: 1, |
|
provider_approved: this.props.approvalFilter, |
|
completed: this.props.completedFilter, |
|
manage: value, |
|
work_type: this.props.workTypeFilter, |
|
page_size: this.state.pageSize |
|
}) |
|
); |
|
this.props.dispatch(setPShiftClientFilter(value)); |
|
this.props.dispatch(setPShiftPage(1)); |
|
}; |
|
|
|
handleChangeWorkTypeFilter = (event, { value }) => { |
|
this.props.dispatch( |
|
getPShiftsRequest({ |
|
page: 1, |
|
provider_approved: this.props.approvalFilter, |
|
completed: this.props.completedFilter, |
|
manage: this.props.clientFilter, |
|
work_type: value, |
|
page_size: this.state.pageSize |
|
}) |
|
); |
|
this.props.dispatch(setPShiftWorkTypeFilter(value)); |
|
this.props.dispatch(setPShiftPage(1)); |
|
}; |
|
|
|
handleChangePShiftApproval = (uuid, approved) => { |
|
return () => { |
|
this.props.dispatch( |
|
updatePShiftRequest({ |
|
uuid, |
|
provider_approved: approved, |
|
action: "", |
|
chart: null |
|
}) |
|
); |
|
}; |
|
}; |
|
|
|
render() { |
|
const { |
|
isSendingPShiftRequest, |
|
pShiftRequestSuccess, |
|
selfUser, |
|
page, |
|
approvalFilter, |
|
completedFilter, |
|
clientFilter, |
|
workTypeFilter |
|
} = this.props; |
|
const { pageSize } = this.state; |
|
if (selfUser.provider) { |
|
return ( |
|
<ProviderShiftsView |
|
isSendingPShiftRequest={isSendingPShiftRequest} |
|
pShiftRequestSuccess={pShiftRequestSuccess} |
|
page={page} |
|
approvalFilter={approvalFilter} |
|
completedFilter={completedFilter} |
|
clientFilter={clientFilter} |
|
workTypeFilter={workTypeFilter} |
|
pageSize={pageSize} |
|
user={selfUser} |
|
handlePaginationChange={this.handlePaginationChange} |
|
handleChangeApprovalFilter={this.handleChangeApprovalFilter} |
|
handleChangeCompletedFilter={this.handleChangeCompletedFilter} |
|
handleChangeClientFilter={this.handleChangeClientFilter} |
|
handleChangeWorkTypeFilter={this.handleChangeWorkTypeFilter} |
|
handleChangePShiftApproval={this.handleChangePShiftApproval} |
|
/> |
|
); |
|
} else { |
|
return <Redirect to="/" />; |
|
} |
|
} |
|
} |
|
|
|
function mapStateToProps(state) { |
|
return { ...state.pShift, selfUser: state.user.selfUser }; |
|
} |
|
|
|
const ProviderShiftsView = ({ |
|
isSendingPShiftRequest, |
|
pShiftRequestSuccess, |
|
user, |
|
page, |
|
approvalFilter, |
|
completedFilter, |
|
clientFilter, |
|
workTypeFilter, |
|
pageSize, |
|
handlePaginationChange, |
|
handleChangeApprovalFilter, |
|
handleChangeCompletedFilter, |
|
handleChangeClientFilter, |
|
handleChangeWorkTypeFilter, |
|
handleChangePShiftApproval |
|
}) => { |
|
const OLD_PEOPLE_TIME_FORMAT = "dddd, MMMM Do YYYY, h:mm a"; |
|
const { count = 0, results = [] } = pShiftRequestSuccess; |
|
const approvedOptions = [ |
|
{ text: "Approved", value: true }, |
|
{ text: "Rejected", value: false }, |
|
{ text: "Pending", value: "" }, |
|
{ text: "All", value: null } |
|
]; |
|
const completedOptions = [ |
|
{ text: "Completed", value: true }, |
|
{ text: "Incomplete", value: false }, |
|
{ text: "All", value: null } |
|
]; |
|
const manageOptions = (user.provider.employers || []).map(employer => { |
|
const name = |
|
`${employer.client.first_name} ${employer.client.last_name}`.trim() || |
|
"No Name"; |
|
return { |
|
text: `${name} <${employer.client.email}>`, |
|
value: employer.uuid |
|
}; |
|
}); |
|
manageOptions.push({ text: `All`, value: null }); |
|
const workTypeMultiOptions = []; |
|
(user.provider.employers || []).forEach(employer => { |
|
(employer.prices || []).forEach(price => { |
|
workTypeMultiOptions.push({ |
|
value: price.work_type.uuid, |
|
text: price.work_type.label, |
|
label: ( |
|
<Label |
|
circular |
|
empty |
|
style={{ |
|
backgroundColor: price.work_type.color, |
|
borderColor: price.work_type.color |
|
}} |
|
/> |
|
) |
|
}); |
|
}); |
|
}); |
|
workTypeMultiOptions.push({ text: `All`, value: null }); |
|
// dedup |
|
const seen = new Set(); |
|
const workTypeOptions = workTypeMultiOptions.filter(option => { |
|
return seen.has(option.value) ? false : seen.add(option.value); |
|
}); |
|
return ( |
|
<Container> |
|
<Header>Shifts</Header> |
|
<Segment.Group horizontal> |
|
<Segment> |
|
{"Filter by Provider Approval "} |
|
<Dropdown |
|
inline |
|
placeholder={approvalFilter === null ? `All` : `Pending`} |
|
options={approvedOptions} |
|
onChange={handleChangeApprovalFilter} |
|
value={approvalFilter} |
|
/> |
|
{" and Completed "} |
|
<Dropdown |
|
inline |
|
placeholder="All" |
|
options={completedOptions} |
|
onChange={handleChangeCompletedFilter} |
|
value={completedFilter} |
|
/> |
|
{" and Client "} |
|
<Dropdown |
|
inline |
|
placeholder="All" |
|
options={manageOptions} |
|
onChange={handleChangeClientFilter} |
|
value={clientFilter} |
|
/> |
|
{" and Work Type "} |
|
<Dropdown |
|
inline |
|
placeholder="All" |
|
options={workTypeOptions} |
|
onChange={handleChangeWorkTypeFilter} |
|
value={workTypeFilter} |
|
/> |
|
</Segment> |
|
</Segment.Group> |
|
{!!isSendingPShiftRequest && <Loader content="Loading" active />} |
|
{!isSendingPShiftRequest && |
|
results.length > 0 && ( |
|
<Item.Group divided> |
|
{results.map(result => { |
|
const employer = getEmployerFromPrice(result.price, user) || {}; |
|
const client = employer.client || {}; |
|
const price = getPriceFromPrice(result.price, user) || {}; |
|
const workType = price.work_type || {}; |
|
const checkedIn = |
|
!!result.actual_start && utc(result.actual_start, ISO_8601); |
|
const checkedOut = |
|
!!result.actual_end && utc(result.actual_end, ISO_8601); |
|
const min = duration( |
|
utc(result.set_end, ISO_8601) - utc(result.set_start, ISO_8601), |
|
"milliseconds" |
|
).as("minutes"); |
|
let displayDuration = duration(min, "minutes").humanize(); |
|
if (min % 60) { |
|
displayDuration = duration( |
|
Math.floor(min / 60), |
|
"hours" |
|
).humanize(); |
|
displayDuration += ` and ${duration( |
|
min % 60, |
|
"minutes" |
|
).humanize()}`; |
|
} |
|
const approved = !!result.provider_approved; |
|
const rejected = |
|
!result.provider_approved && result.provider_approved !== null; |
|
// const pending = result.provider_approved === null; |
|
return ( |
|
<Item key={result.uuid}> |
|
<Item.Content> |
|
<Item.Header> |
|
<Label |
|
circular |
|
empty |
|
style={{ |
|
backgroundColor: workType.color, |
|
borderColor: workType.color |
|
}} |
|
/> |
|
{workType.label} |
|
</Item.Header> |
|
<Item.Extra> |
|
<ShiftLabel |
|
provider_approved={result.provider_approved} |
|
client_approved_start={result.approved_start} |
|
client_approved_end={result.approved_end} |
|
/> |
|
</Item.Extra> |
|
<Item.Meta> |
|
{"Scheduled for " + |
|
utc(result.set_start, ISO_8601) |
|
.local(false) |
|
.format(OLD_PEOPLE_TIME_FORMAT)} |
|
</Item.Meta> |
|
<Item.Meta>{displayDuration}</Item.Meta> |
|
<Item.Meta>{`Rate $${price.amount}/hour`}</Item.Meta> |
|
{/* <Item.Description>{result.description}</Item.Description> */} |
|
{/* <code>{JSON.stringify(result, null, 2)}</code> */} |
|
<Item.Description> |
|
{`${client.first_name} ${client.last_name}`.trim() || |
|
"No Name!"}{" "} |
|
<a href={"mailto:" + client.email}>{client.email}</a> |
|
</Item.Description> |
|
{checkedIn && ( |
|
<Item.Meta> |
|
{"Checked in at: " + |
|
checkedIn.local(false).format(OLD_PEOPLE_TIME_FORMAT)} |
|
</Item.Meta> |
|
)} |
|
{checkedOut && ( |
|
<Item.Meta> |
|
{"Checked out at: " + |
|
checkedOut |
|
.local(false) |
|
.format(OLD_PEOPLE_TIME_FORMAT)} |
|
</Item.Meta> |
|
)} |
|
{result.approved_start && ( |
|
<Fragment> |
|
<strong>Client</strong> |
|
<List bulleted> |
|
<List.Item> |
|
{`Approved time start ${utc(result.approved_start) |
|
.local(false) |
|
.format(OLD_PEOPLE_TIME_FORMAT)}`} |
|
</List.Item> |
|
<List.Item>{`Approved time end ${utc( |
|
result.approved_end |
|
) |
|
.local(false) |
|
.format(OLD_PEOPLE_TIME_FORMAT)}`}</List.Item> |
|
</List> |
|
</Fragment> |
|
)} |
|
</Item.Content> |
|
<Item.Extra> |
|
{!checkedIn && ( |
|
<Button.Group floated="right"> |
|
{!approved && ( |
|
<Button |
|
color="green" |
|
onClick={handleChangePShiftApproval( |
|
result.uuid, |
|
true |
|
)} |
|
> |
|
Approve |
|
</Button> |
|
)} |
|
{!rejected && ( |
|
<Button |
|
color="red" |
|
onClick={handleChangePShiftApproval( |
|
result.uuid, |
|
false |
|
)} |
|
> |
|
Reject |
|
</Button> |
|
)} |
|
</Button.Group> |
|
)} |
|
<Button |
|
floated="right" |
|
as={Link} |
|
to={`/user/profile/provider/shifts/${result.uuid}`} |
|
> |
|
Details{approved && !checkedIn && " & Check In"} |
|
{approved && checkedIn && !checkedOut && " & Check Out"} |
|
</Button> |
|
</Item.Extra> |
|
</Item> |
|
); |
|
})} |
|
</Item.Group> |
|
)} |
|
<div style={{ textAlign: "center" }}> |
|
<Pagination |
|
activePage={page} |
|
onPageChange={handlePaginationChange} |
|
totalPages={Math.ceil(count / pageSize)} |
|
boundaryRange={1} |
|
siblingRange={1} |
|
size="mini" |
|
firstItem={undefined} |
|
lastItem={undefined} |
|
prevItem={null} |
|
nextItem={null} |
|
/> |
|
</div> |
|
</Container> |
|
); |
|
}; |
|
|
|
export default connect(mapStateToProps)(ProviderShifts);
|
|
|