caremyway-client/src/components/User/Client/ClientShifts.jsx

439 lines
14 KiB
React
Raw Normal View History

2018-04-23 04:10:46 +00:00
import { utc, ISO_8601, duration } from "moment";
2018-04-18 19:05:56 +00:00
import React, { Component } from "react";
import { connect } from "react-redux";
import { Redirect, Link } from "react-router-dom";
2018-04-23 00:23:43 +00:00
import {
Button,
Container,
2018-04-23 19:01:41 +00:00
Dropdown,
2018-04-23 00:23:43 +00:00
Header,
Item,
Segment,
2018-04-23 03:07:50 +00:00
Pagination,
2018-04-23 04:10:46 +00:00
Popup,
Loader,
2018-04-23 18:19:14 +00:00
Label,
List,
Message
2018-04-23 00:23:43 +00:00
} from "semantic-ui-react";
2018-04-23 19:01:41 +00:00
import {
setCShiftPage,
2018-04-23 21:44:23 +00:00
setCShiftApprovalFilter,
setCShiftCompletedFilter,
setCShiftProviderFilter,
setCShiftWorkTypeFilter
2018-04-23 19:01:41 +00:00
} from "../../../actions/cShift/reducer.actions";
2018-04-23 04:10:46 +00:00
import {
getCShiftsRequest,
deleteCShiftRequest
} from "../../../actions/cShift/saga.actions";
import { getEmployeeFromPrice, getPriceFromPrice } from "./ClientShiftShared";
2018-04-18 19:05:56 +00:00
class ClientShifts extends Component {
2018-04-23 00:23:43 +00:00
constructor(props) {
super(props);
this.state = {
pageSize: 10 // client can't control this, but set here just in case
};
}
componentWillMount = () => {
this.props.dispatch(
getCShiftsRequest({
2018-04-23 19:01:41 +00:00
page: this.props.page,
approved: this.props.approvalFilter,
2018-04-23 21:44:23 +00:00
completed: this.props.completedFilter,
manage: this.props.providerFilter,
work_type: this.props.workTypeFilter,
2018-04-23 00:23:43 +00:00
page_size: this.state.pageSize
})
);
};
handlePaginationChange = (event, { activePage }) => {
this.props.dispatch(
getCShiftsRequest({
page: activePage,
2018-04-23 19:01:41 +00:00
approved: this.props.approvalFilter,
2018-04-23 21:44:23 +00:00
manage: this.props.providerFilter,
work_type: this.props.workTypeFilter,
2018-04-23 00:23:43 +00:00
page_size: this.state.pageSize
})
);
2018-04-23 19:01:41 +00:00
this.props.dispatch(setCShiftPage(activePage));
};
handleChangeApprovalFilter = (event, { value }) => {
this.props.dispatch(
getCShiftsRequest({
page: 1,
approved: value,
2018-04-23 21:44:23 +00:00
completed: this.props.completedFilter,
manage: this.props.providerFilter,
work_type: this.props.workTypeFilter,
2018-04-23 19:01:41 +00:00
page_size: this.state.pageSize
})
);
this.props.dispatch(setCShiftApprovalFilter(value));
this.props.dispatch(setCShiftPage(1));
2018-04-23 00:23:43 +00:00
};
2018-04-23 21:44:23 +00:00
handleChangeCompletedFilter = (event, { value }) => {
this.props.dispatch(
getCShiftsRequest({
page: 1,
approved: this.props.approvalFilter,
completed: value,
manage: this.props.providerFilter,
work_type: this.props.workTypeFilter,
page_size: this.state.pageSize
})
);
this.props.dispatch(setCShiftCompletedFilter(value));
this.props.dispatch(setCShiftPage(1));
};
handleChangeProviderFilter = (event, { value }) => {
this.props.dispatch(
getCShiftsRequest({
page: 1,
approved: this.props.approvalFilter,
completed: this.props.completedFilter,
manage: value,
work_type: this.props.workTypeFilter,
page_size: this.state.pageSize
})
);
this.props.dispatch(setCShiftProviderFilter(value));
this.props.dispatch(setCShiftPage(1));
};
2018-04-23 22:35:24 +00:00
handleChangeWorkTypeFilter = (event, { value }) => {
2018-04-23 21:44:23 +00:00
this.props.dispatch(
getCShiftsRequest({
page: 1,
approved: this.props.approvalFilter,
completed: this.props.completedFilter,
manage: this.props.manageFilter,
work_type: value,
page_size: this.state.pageSize
})
);
this.props.dispatch(setCShiftWorkTypeFilter(value));
this.props.dispatch(setCShiftPage(1));
2018-04-23 22:35:24 +00:00
};
2018-04-23 21:44:23 +00:00
2018-04-23 04:10:46 +00:00
deleteCShift = uuid => {
this.props.dispatch(deleteCShiftRequest(uuid));
};
2018-04-18 19:05:56 +00:00
render() {
2018-04-23 00:23:43 +00:00
const {
isSendingCShiftRequest,
cShiftRequestSuccess,
2018-04-23 19:01:41 +00:00
selfUser,
page,
2018-04-23 21:44:23 +00:00
approvalFilter,
completedFilter,
providerFilter,
workTypeFilter
2018-04-23 00:23:43 +00:00
} = this.props;
2018-04-23 19:01:41 +00:00
const { pageSize } = this.state;
2018-04-18 19:05:56 +00:00
if (selfUser.client) {
2018-04-23 00:23:43 +00:00
return (
<ClientShiftsView
isSendingCShiftRequest={isSendingCShiftRequest}
cShiftRequestSuccess={cShiftRequestSuccess}
page={page}
2018-04-23 19:01:41 +00:00
approvalFilter={approvalFilter}
2018-04-23 21:44:23 +00:00
completedFilter={completedFilter}
providerFilter={providerFilter}
workTypeFilter={workTypeFilter}
2018-04-23 00:23:43 +00:00
pageSize={pageSize}
user={selfUser}
handlePaginationChange={this.handlePaginationChange}
2018-04-23 19:01:41 +00:00
handleChangeApprovalFilter={this.handleChangeApprovalFilter}
2018-04-23 21:44:23 +00:00
handleChangeCompletedFilter={this.handleChangeCompletedFilter}
handleChangeProviderFilter={this.handleChangeProviderFilter}
handleChangeWorkTypeFilter={this.handleChangeWorkTypeFilter}
2018-04-23 04:10:46 +00:00
deleteCShift={this.deleteCShift}
2018-04-23 00:23:43 +00:00
/>
);
2018-04-18 19:05:56 +00:00
} else {
return <Redirect to="/" />;
}
}
}
function mapStateToProps(state) {
2018-04-23 00:23:43 +00:00
return { ...state.cShift, selfUser: state.user.selfUser };
2018-04-18 19:05:56 +00:00
}
2018-04-23 00:23:43 +00:00
const ClientShiftsView = ({
isSendingCShiftRequest,
cShiftRequestSuccess,
user,
page,
2018-04-23 19:01:41 +00:00
approvalFilter,
2018-04-23 21:44:23 +00:00
completedFilter,
providerFilter,
workTypeFilter,
2018-04-23 00:23:43 +00:00
pageSize,
2018-04-23 04:10:46 +00:00
handlePaginationChange,
2018-04-23 19:01:41 +00:00
handleChangeApprovalFilter,
2018-04-23 21:44:23 +00:00
handleChangeCompletedFilter,
handleChangeProviderFilter,
handleChangeWorkTypeFilter,
2018-04-23 04:10:46 +00:00
deleteCShift
2018-04-23 00:23:43 +00:00
}) => {
const { count = 0, results = [] } = cShiftRequestSuccess;
2018-04-23 19:01:41 +00:00
const approvedOptions = [
{ text: "Approved", value: true },
{ text: "Rejected", value: false },
2018-04-23 20:58:14 +00:00
{ text: "Pending", value: "" },
2018-04-23 19:01:41 +00:00
{ text: "All", value: null }
];
2018-04-23 21:44:23 +00:00
const completedOptions = [
{ text: "Completed", value: true },
{ text: "Incomplete", value: false },
{ text: "All", value: null }
];
const manageOptions = (user.client.employees || []).map(employee => {
const name =
`${employee.provider.first_name} ${employee.provider.last_name}`.trim() ||
"No Name";
return {
text: `${name} <${employee.provider.email}>`,
value: employee.uuid
};
});
manageOptions.push({ text: `All`, value: null });
const workTypeOptions = (user.client.work_types || []).map(workType => {
return {
text: `${workType.label}`,
value: workType.uuid,
label: (
<Label
circular
empty
style={{
backgroundColor: workType.color,
borderColor: workType.color
}}
/>
)
};
});
workTypeOptions.push({ text: `All`, value: null });
2018-04-23 20:58:14 +00:00
const OLD_PEOPLE_TIME_FORMAT = "dddd, MMMM Do YYYY, h:mm a ";
2018-04-23 00:23:43 +00:00
return (
<Container>
<Header>Shifts</Header>
2018-04-23 19:01:41 +00:00
<Segment.Group horizontal>
2018-04-23 22:35:24 +00:00
<Button
attached="left"
basic
color="green"
as={Link}
to="/user/profile/client/add-shift"
>
Schedule Shift
</Button>
2018-04-23 19:01:41 +00:00
<Segment>
2018-04-23 21:44:23 +00:00
{"Filter by Approval "}
2018-04-23 19:01:41 +00:00
<Dropdown
inline
2018-04-23 20:58:14 +00:00
placeholder={approvalFilter === null ? `All` : `Pending`}
2018-04-23 19:01:41 +00:00
options={approvedOptions}
onChange={handleChangeApprovalFilter}
value={approvalFilter}
/>
2018-04-23 21:44:23 +00:00
{" and Completed "}
<Dropdown
inline
placeholder="All"
options={completedOptions}
onChange={handleChangeCompletedFilter}
value={completedFilter}
/>
{" and Provider "}
<Dropdown
inline
placeholder="All"
options={manageOptions}
onChange={handleChangeProviderFilter}
value={providerFilter}
/>
{" and Work Type "}
<Dropdown
inline
placeholder="All"
options={workTypeOptions}
onChange={handleChangeWorkTypeFilter}
value={workTypeFilter}
/>
2018-04-23 19:01:41 +00:00
</Segment>
</Segment.Group>
2018-04-23 17:07:33 +00:00
{!!isSendingCShiftRequest && <Loader content="Loading" active />}
2018-04-23 00:23:43 +00:00
{!isSendingCShiftRequest &&
results.length > 0 && (
2018-04-23 03:07:50 +00:00
<Item.Group divided>
2018-04-23 04:10:46 +00:00
{results.map(result => {
2018-04-23 17:07:33 +00:00
const employee = getEmployeeFromPrice(result.price, user) || {};
const provider = employee.provider || {};
const price = getPriceFromPrice(result.price, user) || {};
2018-04-23 04:10:46 +00:00
const workType = price.work_type;
2018-04-23 18:19:14 +00:00
const checkedIn =
!!result.actual_start && utc(result.actual_start, ISO_8601);
const checkedOut =
!!result.actual_end && utc(result.actual_end, ISO_8601);
2018-04-23 04:10:46 +00:00
const min = duration(
utc(result.set_end, ISO_8601) - utc(result.set_start, ISO_8601),
"milliseconds"
).as("minutes");
2018-04-23 17:07:33 +00:00
let displayDuration = duration(min, "minutes").humanize();
2018-04-23 04:10:46 +00:00
if (min % 60) {
2018-04-23 17:07:33 +00:00
displayDuration = duration(
2018-04-23 04:10:46 +00:00
Math.floor(min / 60),
"hours"
).humanize();
2018-04-23 17:07:33 +00:00
displayDuration += ` and ${duration(
2018-04-23 04:10:46 +00:00
min % 60,
"minutes"
).humanize()}`;
}
2018-04-23 17:07:33 +00:00
const approved = !!result.approved;
const rejected = !result.approved && result.approved !== null;
const pending = result.approved === null;
2018-04-23 04:10:46 +00:00
return (
<Item key={result.uuid}>
<Item.Content>
<Item.Header>
<Label
circular
empty
style={{
backgroundColor: workType.color,
borderColor: workType.color
}}
/>
{workType.label}
</Item.Header>
2018-04-23 17:07:33 +00:00
<Item.Extra>
<Label
color={approved ? "green" : rejected ? "red" : "grey"}
tag
size="small"
>
{approved && "Approved"}
{pending && "Approval Pending"}
{rejected && "Rejected"}
</Label>
</Item.Extra>
2018-04-23 04:10:46 +00:00
<Item.Meta>
{"At " +
utc(result.set_start, ISO_8601)
.local(false)
2018-04-23 20:58:14 +00:00
.format(OLD_PEOPLE_TIME_FORMAT)}
2018-04-23 04:10:46 +00:00
</Item.Meta>
2018-04-23 17:07:33 +00:00
<Item.Meta>{displayDuration}</Item.Meta>
<Item.Meta>{`Rate $${price.amount}/hour`}</Item.Meta>
{/* <Item.Description>{result.description}</Item.Description> */}
2018-04-23 05:04:09 +00:00
{/* <code>{JSON.stringify(result, null, 2)}</code> */}
2018-04-23 17:07:33 +00:00
<Item.Description>
{`${provider.first_name} ${provider.last_name}`.trim() ||
"No Name!"}{" "}
<a href={"mailto:" + provider.email}>{provider.email}</a>
</Item.Description>
2018-04-23 04:10:46 +00:00
</Item.Content>
2018-04-23 18:19:14 +00:00
{!checkedIn && (
2018-04-23 04:10:46 +00:00
<Item.Extra>
<Button
primary
floated="right"
as={Link}
to={`/user/profile/client/edit-shift/${result.uuid}`}
>
Edit
</Button>
<Popup
content={
<div>
Are you sure you want to delete this shift?<br />
<Button
basic
color="red"
size="small"
onClick={() => deleteCShift(result.uuid)}
>
Confirm Deletion
</Button>
</div>
}
trigger={
<Button color="red" floated="right">
Delete
</Button>
}
on="click"
position="top right"
/>
</Item.Extra>
)}
2018-04-23 18:19:14 +00:00
{checkedIn && (
<Item.Content>
<Item.Description>
{result.description && (
<Message>{result.description}</Message>
)}
<strong>Provider</strong>
<List bulleted>
<List.Item>
{"Checked in at " +
checkedIn
.local(false)
2018-04-23 20:58:14 +00:00
.format(OLD_PEOPLE_TIME_FORMAT)}
2018-04-23 18:19:14 +00:00
</List.Item>
{checkedOut && (
<List.Item>
{"Checked out at " +
checkedOut
.local(false)
2018-04-23 20:58:14 +00:00
.format(OLD_PEOPLE_TIME_FORMAT)}
2018-04-23 18:19:14 +00:00
</List.Item>
)}
</List>
{result.chart && (
<Message>
<Message.Header>Chart</Message.Header>
{result.chart}
</Message>
)}
</Item.Description>
</Item.Content>
)}
2018-04-23 04:10:46 +00:00
</Item>
);
})}
2018-04-23 00:23:43 +00:00
</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>
);
};
2018-04-18 19:05:56 +00:00
export default connect(mapStateToProps)(ClientShifts);