working details view, approve/reject
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
||||
} from "../../../actions/cShift/saga.actions";
|
||||
import { ClientShiftFormView } from "./ClientShiftFormView";
|
||||
import { getEmployeeFromPrice } from "./ClientShiftShared";
|
||||
import Error from "../../Shared/Error";
|
||||
|
||||
class ClientEditShiftForm extends Component {
|
||||
constructor(props) {
|
||||
@@ -224,11 +225,13 @@ class EditClientShiftWrapper extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { cShiftRequestSuccess } = this.props;
|
||||
const { cShiftRequestSuccess, cShiftRequestErrors } = this.props;
|
||||
if (cShiftRequestSuccess.uuid) {
|
||||
return <ClientEditShiftForm {...this.props} />;
|
||||
} else if (!cShiftRequestErrors.length > 0) {
|
||||
return <Loader active />;
|
||||
} else {
|
||||
return <Loader />;
|
||||
return <Error error={cShiftRequestErrors[0]} />;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -105,29 +105,33 @@ const ClientShiftsView = ({
|
||||
Schedule a Shift
|
||||
</Button>
|
||||
</Segment>
|
||||
{!!isSendingCShiftRequest && <Loader content="Loading" />}
|
||||
{!!isSendingCShiftRequest && <Loader content="Loading" active />}
|
||||
{!isSendingCShiftRequest &&
|
||||
results.length > 0 && (
|
||||
<Item.Group divided>
|
||||
{results.map(result => {
|
||||
const employee = getEmployeeFromPrice(result.price, user);
|
||||
const price = getPriceFromPrice(result.price, user);
|
||||
const employee = getEmployeeFromPrice(result.price, user) || {};
|
||||
const provider = employee.provider || {};
|
||||
const price = getPriceFromPrice(result.price, user) || {};
|
||||
const workType = price.work_type;
|
||||
const min = duration(
|
||||
utc(result.set_end, ISO_8601) - utc(result.set_start, ISO_8601),
|
||||
"milliseconds"
|
||||
).as("minutes");
|
||||
let displayText = duration(min, "minutes").humanize();
|
||||
let displayDuration = duration(min, "minutes").humanize();
|
||||
if (min % 60) {
|
||||
displayText = duration(
|
||||
displayDuration = duration(
|
||||
Math.floor(min / 60),
|
||||
"hours"
|
||||
).humanize();
|
||||
displayText += ` and ${duration(
|
||||
displayDuration += ` and ${duration(
|
||||
min % 60,
|
||||
"minutes"
|
||||
).humanize()}`;
|
||||
}
|
||||
const approved = !!result.approved;
|
||||
const rejected = !result.approved && result.approved !== null;
|
||||
const pending = result.approved === null;
|
||||
return (
|
||||
<Item key={result.uuid}>
|
||||
<Item.Content>
|
||||
@@ -142,24 +146,32 @@ const ClientShiftsView = ({
|
||||
/>
|
||||
{workType.label}
|
||||
</Item.Header>
|
||||
<Item.Extra>
|
||||
<Label
|
||||
color={approved ? "green" : rejected ? "red" : "grey"}
|
||||
tag
|
||||
size="small"
|
||||
>
|
||||
{approved && "Approved"}
|
||||
{pending && "Approval Pending"}
|
||||
{rejected && "Rejected"}
|
||||
</Label>
|
||||
</Item.Extra>
|
||||
<Item.Meta>
|
||||
{"At " +
|
||||
utc(result.set_start, ISO_8601)
|
||||
.local(false)
|
||||
.format("dddd, MMMM Do YYYY, h:mm a Z") +
|
||||
"; for " +
|
||||
displayText +
|
||||
"; rate $" +
|
||||
price.amount +
|
||||
"/hour"}
|
||||
.format("dddd, MMMM Do YYYY, h:mm a Z")}
|
||||
</Item.Meta>
|
||||
<Item.Description>{result.description}</Item.Description>
|
||||
<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.Meta>
|
||||
<a href={"mailto:" + employee.provider.email}>
|
||||
{employee.provider.email}
|
||||
</a>
|
||||
</Item.Meta>
|
||||
<Item.Description>
|
||||
{`${provider.first_name} ${provider.last_name}`.trim() ||
|
||||
"No Name!"}{" "}
|
||||
<a href={"mailto:" + provider.email}>{provider.email}</a>
|
||||
</Item.Description>
|
||||
</Item.Content>
|
||||
{result.actual_start === null && (
|
||||
<Item.Extra>
|
||||
|
174
src/components/User/Provider/ProviderShift.jsx
Normal file
174
src/components/User/Provider/ProviderShift.jsx
Normal file
@@ -0,0 +1,174 @@
|
||||
import { utc, duration, ISO_8601 } from "moment";
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Redirect } from "react-router-dom";
|
||||
import {
|
||||
Button,
|
||||
Container,
|
||||
Header,
|
||||
Label,
|
||||
List,
|
||||
Loader,
|
||||
Message
|
||||
} from "semantic-ui-react";
|
||||
import { setClearPShiftState } from "../../../actions/pShift/reducer.actions";
|
||||
import {
|
||||
getPShiftRequest,
|
||||
updatePShiftRequest
|
||||
} from "../../../actions/pShift/saga.actions";
|
||||
import Error from "../../Shared/Error";
|
||||
import {
|
||||
getEmployerFromPrice,
|
||||
getWorkTypeFromPrice,
|
||||
getPriceFromPrice
|
||||
} from "./ProviderShiftsShared";
|
||||
|
||||
class ProviderShift extends Component {
|
||||
handleChangePShiftApproval = (uuid, approved) => {
|
||||
return () => {
|
||||
this.props.dispatch(
|
||||
updatePShiftRequest({
|
||||
uuid,
|
||||
approved,
|
||||
action: "",
|
||||
chart: null,
|
||||
single: true
|
||||
})
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
isSendingPShiftRequest,
|
||||
pShiftRequestError,
|
||||
pShiftRequestSuccess,
|
||||
selfUser
|
||||
} = this.props;
|
||||
|
||||
if (!selfUser.provider) {
|
||||
return <Redirect to="/" />;
|
||||
}
|
||||
return (
|
||||
<ProviderShiftFormView
|
||||
isSendingPShiftRequest={isSendingPShiftRequest}
|
||||
pShiftRequestError={pShiftRequestError}
|
||||
shift={pShiftRequestSuccess}
|
||||
user={selfUser}
|
||||
handleChangePShiftApproval={this.handleChangePShiftApproval}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const ProviderShiftFormView = ({
|
||||
isSendingPShiftRequest,
|
||||
pShiftRequestError,
|
||||
shift,
|
||||
user,
|
||||
handleChangePShiftApproval
|
||||
}) => {
|
||||
const employer = getEmployerFromPrice(shift.price, user) || {};
|
||||
const client = employer.client || {};
|
||||
const workType = getWorkTypeFromPrice(shift.price, user) || {};
|
||||
const price = getPriceFromPrice(shift.price, user) || {};
|
||||
const min = duration(
|
||||
utc(shift.set_end, ISO_8601) - utc(shift.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 = !!shift.approved;
|
||||
const rejected = !shift.approved && shift.approved !== null;
|
||||
const pending = shift.approved === null;
|
||||
return (
|
||||
<Container>
|
||||
<Header>Shift Details</Header>
|
||||
<Loader active={isSendingPShiftRequest} />
|
||||
<Label color={approved ? "green" : rejected ? "red" : "grey"} tag size="small">
|
||||
{approved && "Approved"}
|
||||
{pending && "Approval Pending"}
|
||||
{rejected && "Rejected"}
|
||||
</Label>
|
||||
<Label
|
||||
circular
|
||||
empty
|
||||
style={{
|
||||
backgroundColor: workType.color,
|
||||
borderColor: workType.color
|
||||
}}
|
||||
/>{" "}
|
||||
{workType.label}
|
||||
<List bulleted>
|
||||
<List.Item>
|
||||
{"Scheduled at " +
|
||||
utc(shift.set_start, ISO_8601)
|
||||
.local(false)
|
||||
.format("dddd, MMMM Do YYYY, h:mm a Z")}
|
||||
</List.Item>
|
||||
<List.Item>{displayDuration}</List.Item>
|
||||
<List.Item>{`Rate $${price.amount}/hour`}</List.Item>
|
||||
<List.Item>
|
||||
<strong>Employer/Client:</strong>{" "}
|
||||
{`${client.first_name} ${client.last_name}`.trim() || "No Name!"}{" "}
|
||||
<a href={"mailto:" + client.email}>{client.email}</a>
|
||||
</List.Item>
|
||||
</List>
|
||||
{shift.description && (
|
||||
<Message>
|
||||
<Message.Header>Description</Message.Header>
|
||||
<p>{shift.description}</p>
|
||||
</Message>
|
||||
)}
|
||||
<Button.Group>
|
||||
{!approved && (
|
||||
<Button
|
||||
color="green"
|
||||
onClick={handleChangePShiftApproval(shift.uuid, true)}
|
||||
>
|
||||
Approve
|
||||
</Button>
|
||||
)}
|
||||
{!rejected && (
|
||||
<Button
|
||||
color="red"
|
||||
onClick={handleChangePShiftApproval(shift.uuid, false)}
|
||||
>
|
||||
Reject
|
||||
</Button>
|
||||
)}
|
||||
</Button.Group>
|
||||
<Error error={pShiftRequestError}/>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return { ...state.pShift, selfUser: state.user.selfUser };
|
||||
}
|
||||
|
||||
class ProviderShiftWrapper extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.props.dispatch(setClearPShiftState());
|
||||
this.props.dispatch(
|
||||
getPShiftRequest({ uuid: this.props.match.params.shiftUUID })
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { pShiftRequestSuccess, pShiftRequestError } = this.props;
|
||||
if (pShiftRequestSuccess.uuid) {
|
||||
return <ProviderShift {...this.props} />;
|
||||
} else if (!pShiftRequestError) {
|
||||
return <Loader active />;
|
||||
} else {
|
||||
return <Error error={pShiftRequestError} />;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(ProviderShiftWrapper);
|
@@ -1,8 +1,9 @@
|
||||
import { utc, ISO_8601, duration } from "moment";
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Redirect } from "react-router-dom";
|
||||
import { Redirect, Link } from "react-router-dom";
|
||||
import {
|
||||
Button,
|
||||
Container,
|
||||
Header,
|
||||
Item,
|
||||
@@ -14,7 +15,10 @@ import {
|
||||
getEmployerFromPrice,
|
||||
getPriceFromPrice
|
||||
} from "./ProviderShiftsShared";
|
||||
import { getPShiftsRequest } from "../../../actions/pShift/saga.actions";
|
||||
import {
|
||||
getPShiftsRequest,
|
||||
updatePShiftRequest
|
||||
} from "../../../actions/pShift/saga.actions";
|
||||
|
||||
class ProviderShifts extends Component {
|
||||
constructor(props) {
|
||||
@@ -44,6 +48,14 @@ class ProviderShifts extends Component {
|
||||
this.setState({ page: activePage });
|
||||
};
|
||||
|
||||
handleChangePShiftApproval = (uuid, approved) => {
|
||||
return () => {
|
||||
this.props.dispatch(
|
||||
updatePShiftRequest({ uuid, approved, action: "", chart: null })
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
isSendingPShiftRequest,
|
||||
@@ -60,6 +72,7 @@ class ProviderShifts extends Component {
|
||||
pageSize={pageSize}
|
||||
user={selfUser}
|
||||
handlePaginationChange={this.handlePaginationChange}
|
||||
handleChangePShiftApproval={this.handleChangePShiftApproval}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
@@ -78,35 +91,40 @@ const ProviderShiftsView = ({
|
||||
user,
|
||||
page,
|
||||
pageSize,
|
||||
handlePaginationChange
|
||||
handlePaginationChange,
|
||||
handleChangePShiftApproval
|
||||
}) => {
|
||||
const { count = 0, results = [] } = pShiftRequestSuccess;
|
||||
return (
|
||||
<Container>
|
||||
<Header>Shifts</Header>
|
||||
{!!isSendingPShiftRequest && <Loader content="Loading" />}
|
||||
{!!isSendingPShiftRequest && <Loader content="Loading" active />}
|
||||
{!isSendingPShiftRequest &&
|
||||
results.length > 0 && (
|
||||
<Item.Group divided>
|
||||
{results.map(result => {
|
||||
const employer = getEmployerFromPrice(result.price, user);
|
||||
const price = getPriceFromPrice(result.price, user);
|
||||
const workType = price.work_type;
|
||||
const employer = getEmployerFromPrice(result.price, user) || {};
|
||||
const client = employer.client || {};
|
||||
const price = getPriceFromPrice(result.price, user) || {};
|
||||
const workType = price.work_type || {};
|
||||
const min = duration(
|
||||
utc(result.set_end, ISO_8601) - utc(result.set_start, ISO_8601),
|
||||
"milliseconds"
|
||||
).as("minutes");
|
||||
let displayText = duration(min, "minutes").humanize();
|
||||
let displayDuration = duration(min, "minutes").humanize();
|
||||
if (min % 60) {
|
||||
displayText = duration(
|
||||
displayDuration = duration(
|
||||
Math.floor(min / 60),
|
||||
"hours"
|
||||
).humanize();
|
||||
displayText += ` and ${duration(
|
||||
displayDuration += ` and ${duration(
|
||||
min % 60,
|
||||
"minutes"
|
||||
).humanize()}`;
|
||||
}
|
||||
const approved = !!result.approved;
|
||||
const rejected = !result.approved && result.approved !== null;
|
||||
const pending = result.approved === null;
|
||||
return (
|
||||
<Item key={result.uuid}>
|
||||
<Item.Content>
|
||||
@@ -121,24 +139,65 @@ const ProviderShiftsView = ({
|
||||
/>
|
||||
{workType.label}
|
||||
</Item.Header>
|
||||
<Item.Extra>
|
||||
<Label
|
||||
color={approved ? "green" : rejected ? "red" : "grey"}
|
||||
tag
|
||||
size="small"
|
||||
>
|
||||
{approved && "Approved"}
|
||||
{pending && "Approval Pending"}
|
||||
{rejected && "Rejected"}
|
||||
</Label>
|
||||
</Item.Extra>
|
||||
<Item.Meta>
|
||||
{"At " +
|
||||
utc(result.set_start, ISO_8601)
|
||||
.local(false)
|
||||
.format("dddd, MMMM Do YYYY, h:mm a Z") +
|
||||
"; for " +
|
||||
displayText +
|
||||
"; rate $" +
|
||||
price.amount +
|
||||
"/hour"}
|
||||
.format("dddd, MMMM Do YYYY, h:mm a Z")}
|
||||
</Item.Meta>
|
||||
<Item.Description>{result.description}</Item.Description>
|
||||
<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.Meta>
|
||||
<a href={"mailto:" + employer.client.email}>
|
||||
{employer.client.email}
|
||||
</a>
|
||||
</Item.Meta>
|
||||
<Item.Description>
|
||||
{`${client.first_name} ${client.last_name}`.trim() ||
|
||||
"No Name!"}{" "}
|
||||
<a href={"mailto:" + client.email}>{client.email}</a>
|
||||
</Item.Description>
|
||||
<Item.Extra>
|
||||
<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 & Check In
|
||||
</Button>
|
||||
</Item.Extra>
|
||||
</Item.Content>
|
||||
</Item>
|
||||
);
|
||||
|
Reference in New Issue
Block a user