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

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);