added pShift scaffolding
This commit is contained in:
parent
2b15495072
commit
0fc6ac31f5
49
src/actions/pShift/reducer.actions.js
Normal file
49
src/actions/pShift/reducer.actions.js
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import {
|
||||||
|
IS_SENDING_PSHIFT_REQUEST,
|
||||||
|
SET_PSHIFT_REQUEST_SUCCESS,
|
||||||
|
SET_PSHIFT_REQUEST_ERROR,
|
||||||
|
CLEAR_PSHIFT_REQUEST_ERROR,
|
||||||
|
CLEAR_PSHIFT_REQUEST_SUCCESS,
|
||||||
|
SET_CLEAR_PSHIFT_STATE
|
||||||
|
} from "../../constants/pShift.constants";
|
||||||
|
import { parseError } from "../common.actions";
|
||||||
|
|
||||||
|
export function isSendingPShiftRequest(sendingRequest) {
|
||||||
|
return {
|
||||||
|
type: IS_SENDING_PSHIFT_REQUEST,
|
||||||
|
data: sendingRequest
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setPShiftRequestSuccess(response) {
|
||||||
|
return {
|
||||||
|
type: SET_PSHIFT_REQUEST_SUCCESS,
|
||||||
|
data: response.detail || response
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setPShiftRequestError(exception) {
|
||||||
|
let error = parseError(exception);
|
||||||
|
return {
|
||||||
|
type: SET_PSHIFT_REQUEST_ERROR,
|
||||||
|
data: error
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearPShiftRequestError() {
|
||||||
|
return {
|
||||||
|
type: CLEAR_PSHIFT_REQUEST_ERROR
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearPShiftRequestSuccess() {
|
||||||
|
return {
|
||||||
|
type: CLEAR_PSHIFT_REQUEST_SUCCESS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setClearPShiftState() {
|
||||||
|
return {
|
||||||
|
type: SET_CLEAR_PSHIFT_STATE
|
||||||
|
};
|
||||||
|
}
|
8
src/actions/pShift/saga.actions.js
Normal file
8
src/actions/pShift/saga.actions.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { GET_PSHIFTS_REQUEST } from "../../constants/pShift.constants";
|
||||||
|
|
||||||
|
export function getPShiftsRequest(params) {
|
||||||
|
return {
|
||||||
|
type: GET_PSHIFTS_REQUEST,
|
||||||
|
data: params
|
||||||
|
};
|
||||||
|
}
|
5
src/api/pShift.api.js
Normal file
5
src/api/pShift.api.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { get } from "./baseApi";
|
||||||
|
|
||||||
|
export function getPShifts(params) {
|
||||||
|
return get("/pshift/", params).then(resp => Promise.resolve(resp));
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ import ClientShifts from "./User/Client/ClientShifts";
|
||||||
import ClientAddShiftForm from "./User/Client/ClientAddShiftForm";
|
import ClientAddShiftForm from "./User/Client/ClientAddShiftForm";
|
||||||
import ClientEditShiftForm from "./User/Client/ClientEditShiftForm";
|
import ClientEditShiftForm from "./User/Client/ClientEditShiftForm";
|
||||||
import ProviderClients from "./User/Provider/ProviderClients";
|
import ProviderClients from "./User/Provider/ProviderClients";
|
||||||
|
import ProviderShifts from "./User/Provider/ProviderShifts";
|
||||||
import CompleteRegistration from "./User/CompleteRegistration";
|
import CompleteRegistration from "./User/CompleteRegistration";
|
||||||
import EditProfile from "./User/EditProfile";
|
import EditProfile from "./User/EditProfile";
|
||||||
import Profile from "./User/Profile";
|
import Profile from "./User/Profile";
|
||||||
|
@ -101,6 +102,10 @@ class App extends Component {
|
||||||
path="/user/profile/provider/clients"
|
path="/user/profile/provider/clients"
|
||||||
component={ProviderClients}
|
component={ProviderClients}
|
||||||
/>
|
/>
|
||||||
|
<PrivateRoute
|
||||||
|
path="/user/profile/provider/shifts"
|
||||||
|
component={ProviderShifts}
|
||||||
|
/>
|
||||||
<PrivateRoute path="/user/profile/edit" component={EditProfile} />
|
<PrivateRoute path="/user/profile/edit" component={EditProfile} />
|
||||||
<PrivateRoute path="/user/profile" component={Profile} />
|
<PrivateRoute path="/user/profile" component={Profile} />
|
||||||
<Route path="/user/complete-registration" component={Profile} />
|
<Route path="/user/complete-registration" component={Profile} />
|
||||||
|
|
|
@ -83,6 +83,11 @@ const NavbarView = ({ isAuthenticated, dispatchLogoutRequest, selfUser }) => (
|
||||||
Clients
|
Clients
|
||||||
</Dropdown.Item>
|
</Dropdown.Item>
|
||||||
)}
|
)}
|
||||||
|
{selfUser.provider && (
|
||||||
|
<Dropdown.Item as={Link} to="/user/profile/provider/shifts">
|
||||||
|
Shifts
|
||||||
|
</Dropdown.Item>
|
||||||
|
)}
|
||||||
<Dropdown.Item as={Link} to="/auth/settings">
|
<Dropdown.Item as={Link} to="/auth/settings">
|
||||||
Settings
|
Settings
|
||||||
</Dropdown.Item>
|
</Dropdown.Item>
|
||||||
|
|
|
@ -154,7 +154,7 @@ const ClientShiftsView = ({
|
||||||
"/hour"}
|
"/hour"}
|
||||||
</Item.Meta>
|
</Item.Meta>
|
||||||
<Item.Description>{result.description}</Item.Description>
|
<Item.Description>{result.description}</Item.Description>
|
||||||
<code>{JSON.stringify(result, null, 2)}</code>
|
{/* <code>{JSON.stringify(result, null, 2)}</code> */}
|
||||||
<Item.Meta>
|
<Item.Meta>
|
||||||
<a href={"mailto:" + employee.provider.email}>
|
<a href={"mailto:" + employee.provider.email}>
|
||||||
{employee.provider.email}
|
{employee.provider.email}
|
||||||
|
|
166
src/components/User/Provider/ProviderShifts.jsx
Normal file
166
src/components/User/Provider/ProviderShifts.jsx
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
import { utc, ISO_8601, duration } from "moment";
|
||||||
|
import React, { Component } from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { Redirect } from "react-router-dom";
|
||||||
|
import {
|
||||||
|
Container,
|
||||||
|
Header,
|
||||||
|
Item,
|
||||||
|
Pagination,
|
||||||
|
Loader,
|
||||||
|
Label
|
||||||
|
} from "semantic-ui-react";
|
||||||
|
import {
|
||||||
|
getEmployerFromPrice,
|
||||||
|
getPriceFromPrice
|
||||||
|
} from "./ProviderShiftsShared";
|
||||||
|
import { getPShiftsRequest } from "../../../actions/pShift/saga.actions";
|
||||||
|
|
||||||
|
class ProviderShifts extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10 // client can't control this, but set here just in case
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount = () => {
|
||||||
|
this.props.dispatch(
|
||||||
|
getPShiftsRequest({
|
||||||
|
page: this.state.page,
|
||||||
|
page_size: this.state.pageSize
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
handlePaginationChange = (event, { activePage }) => {
|
||||||
|
this.props.dispatch(
|
||||||
|
getPShiftsRequest({
|
||||||
|
page: activePage,
|
||||||
|
page_size: this.state.pageSize
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.setState({ page: activePage });
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
isSendingPShiftRequest,
|
||||||
|
pShiftRequestSuccess,
|
||||||
|
selfUser
|
||||||
|
} = this.props;
|
||||||
|
const { page, pageSize } = this.state;
|
||||||
|
if (selfUser.provider) {
|
||||||
|
return (
|
||||||
|
<ProviderShiftsView
|
||||||
|
isSendingPShiftRequest={isSendingPShiftRequest}
|
||||||
|
pShiftRequestSuccess={pShiftRequestSuccess}
|
||||||
|
page={page}
|
||||||
|
pageSize={pageSize}
|
||||||
|
user={selfUser}
|
||||||
|
handlePaginationChange={this.handlePaginationChange}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return <Redirect to="/" />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return { ...state.pShift, selfUser: state.user.selfUser };
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProviderShiftsView = ({
|
||||||
|
isSendingPShiftRequest,
|
||||||
|
pShiftRequestSuccess,
|
||||||
|
user,
|
||||||
|
page,
|
||||||
|
pageSize,
|
||||||
|
handlePaginationChange
|
||||||
|
}) => {
|
||||||
|
const { count = 0, results = [] } = pShiftRequestSuccess;
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Header>Shifts</Header>
|
||||||
|
{!!isSendingPShiftRequest && <Loader content="Loading" />}
|
||||||
|
{!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 min = duration(
|
||||||
|
utc(result.set_end, ISO_8601) - utc(result.set_start, ISO_8601),
|
||||||
|
"milliseconds"
|
||||||
|
).as("minutes");
|
||||||
|
let displayText = duration(min, "minutes").humanize();
|
||||||
|
if (min % 60) {
|
||||||
|
displayText = duration(
|
||||||
|
Math.floor(min / 60),
|
||||||
|
"hours"
|
||||||
|
).humanize();
|
||||||
|
displayText += ` and ${duration(
|
||||||
|
min % 60,
|
||||||
|
"minutes"
|
||||||
|
).humanize()}`;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Item key={result.uuid}>
|
||||||
|
<Item.Content>
|
||||||
|
<Item.Header>
|
||||||
|
<Label
|
||||||
|
circular
|
||||||
|
empty
|
||||||
|
style={{
|
||||||
|
backgroundColor: workType.color,
|
||||||
|
borderColor: workType.color
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{workType.label}
|
||||||
|
</Item.Header>
|
||||||
|
<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"}
|
||||||
|
</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.Content>
|
||||||
|
</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);
|
42
src/components/User/Provider/ProviderShiftsShared.js
Normal file
42
src/components/User/Provider/ProviderShiftsShared.js
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
export const getEmployerFromPrice = (priceUUID, selfUser) => {
|
||||||
|
const employers =
|
||||||
|
selfUser && selfUser.provider && selfUser.provider.employers;
|
||||||
|
let matchEmployer = null;
|
||||||
|
employers.forEach(employer => {
|
||||||
|
const priceMatch = employer.prices.filter(price => {
|
||||||
|
return price.uuid === priceUUID;
|
||||||
|
});
|
||||||
|
if (priceMatch.length > 0) {
|
||||||
|
matchEmployer = employer;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return matchEmployer;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getWorkTypeFromPrice = (priceUUID, selfUser) => {
|
||||||
|
const employers =
|
||||||
|
selfUser && selfUser.provider && selfUser.provider.employers;
|
||||||
|
let matchWorkType = null;
|
||||||
|
employers.forEach(employer => {
|
||||||
|
employer.prices.forEach(price => {
|
||||||
|
if (price.uuid === priceUUID) {
|
||||||
|
matchWorkType = price.work_type;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return matchWorkType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getPriceFromPrice = (priceUUID, selfUser) => {
|
||||||
|
const employers =
|
||||||
|
selfUser && selfUser.provider && selfUser.provider.employers;
|
||||||
|
let matchPrice = null;
|
||||||
|
employers.forEach(employer => {
|
||||||
|
employer.prices.forEach(price => {
|
||||||
|
if (price.uuid === priceUUID) {
|
||||||
|
matchPrice = price;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return matchPrice;
|
||||||
|
};
|
10
src/constants/pShift.constants.js
Normal file
10
src/constants/pShift.constants.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// Reducer PShift Action Constants
|
||||||
|
export const IS_SENDING_PSHIFT_REQUEST = "IS_SENDING_PSHIFT_REQUEST";
|
||||||
|
export const SET_PSHIFT_REQUEST_ERROR = "SET_PSHIFT_REQUEST_ERROR";
|
||||||
|
export const CLEAR_PSHIFT_REQUEST_ERROR = "CLEAR_PSHIFT_REQUEST_ERROR";
|
||||||
|
export const SET_PSHIFT_REQUEST_SUCCESS = "SET_PSHIFT_REQUEST_SUCCESS";
|
||||||
|
export const CLEAR_PSHIFT_REQUEST_SUCCESS = "CLEAR_PSHIFT_REQUEST_SUCCESS";
|
||||||
|
export const SET_CLEAR_PSHIFT_STATE = "SET_CLEAR_PSHIFT_STATE";
|
||||||
|
|
||||||
|
// Saga PShift Action Constants
|
||||||
|
export const GET_PSHIFTS_REQUEST = "GET_PSHIFTS_REQUEST";
|
|
@ -6,6 +6,7 @@ import employeeReducer from "./employeeReducer";
|
||||||
// import employerReducer from "./employerReducer"; // unused
|
// import employerReducer from "./employerReducer"; // unused
|
||||||
import priceReducer from "./priceReducer";
|
import priceReducer from "./priceReducer";
|
||||||
import cShiftReducer from "./cShiftReducer";
|
import cShiftReducer from "./cShiftReducer";
|
||||||
|
import pShiftReducer from "./pShiftReducer";
|
||||||
|
|
||||||
const reducer = combineReducers({
|
const reducer = combineReducers({
|
||||||
auth: authReducer,
|
auth: authReducer,
|
||||||
|
@ -14,7 +15,8 @@ const reducer = combineReducers({
|
||||||
employee: employeeReducer,
|
employee: employeeReducer,
|
||||||
// employer: employerReducer // unused
|
// employer: employerReducer // unused
|
||||||
price: priceReducer,
|
price: priceReducer,
|
||||||
cShift: cShiftReducer
|
cShift: cShiftReducer,
|
||||||
|
pShift: pShiftReducer
|
||||||
});
|
});
|
||||||
|
|
||||||
export default reducer;
|
export default reducer;
|
||||||
|
|
52
src/reducers/pShiftReducer.js
Normal file
52
src/reducers/pShiftReducer.js
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import {
|
||||||
|
IS_SENDING_PSHIFT_REQUEST,
|
||||||
|
SET_PSHIFT_REQUEST_ERROR,
|
||||||
|
SET_PSHIFT_REQUEST_SUCCESS,
|
||||||
|
CLEAR_PSHIFT_REQUEST_ERROR,
|
||||||
|
CLEAR_PSHIFT_REQUEST_SUCCESS,
|
||||||
|
SET_CLEAR_PSHIFT_STATE
|
||||||
|
} from "../constants/pShift.constants";
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
isSendingPShiftRequest: false,
|
||||||
|
pShiftRequestError: "",
|
||||||
|
pShiftRequestSuccess: ""
|
||||||
|
};
|
||||||
|
|
||||||
|
function pShiftReducer(state = initialState, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case IS_SENDING_PSHIFT_REQUEST:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
isSendingPShiftRequest: action.data
|
||||||
|
};
|
||||||
|
case SET_PSHIFT_REQUEST_ERROR:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
pShiftRequestError: action.data
|
||||||
|
};
|
||||||
|
case CLEAR_PSHIFT_REQUEST_ERROR:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
pShiftRequestError: ""
|
||||||
|
};
|
||||||
|
case SET_PSHIFT_REQUEST_SUCCESS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
pShiftRequestSuccess: action.data
|
||||||
|
};
|
||||||
|
case CLEAR_PSHIFT_REQUEST_SUCCESS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
pShiftRequestSuccess: ""
|
||||||
|
};
|
||||||
|
case SET_CLEAR_PSHIFT_STATE:
|
||||||
|
return {
|
||||||
|
...initialState
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return { ...state };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default pShiftReducer;
|
|
@ -83,6 +83,8 @@ import {
|
||||||
editCShiftFlow,
|
editCShiftFlow,
|
||||||
deleteCShiftFlow
|
deleteCShiftFlow
|
||||||
} from "./cShift.sagas";
|
} from "./cShift.sagas";
|
||||||
|
import { GET_PSHIFTS_REQUEST } from "../constants/pShift.constants";
|
||||||
|
import { getPShiftsFlow } from "./pShift.sagas";
|
||||||
|
|
||||||
export default function* rootSaga() {
|
export default function* rootSaga() {
|
||||||
yield takeLatest(SEND_REGISTER_REQUEST, registerUserFlow);
|
yield takeLatest(SEND_REGISTER_REQUEST, registerUserFlow);
|
||||||
|
@ -115,4 +117,5 @@ export default function* rootSaga() {
|
||||||
yield takeLatest(GET_CSHIFT_REQUEST, getCShiftFlow);
|
yield takeLatest(GET_CSHIFT_REQUEST, getCShiftFlow);
|
||||||
yield takeLatest(EDIT_CSHIFT_REQUEST, editCShiftFlow);
|
yield takeLatest(EDIT_CSHIFT_REQUEST, editCShiftFlow);
|
||||||
yield takeLatest(DELETE_CSHIFT_REQUEST, deleteCShiftFlow);
|
yield takeLatest(DELETE_CSHIFT_REQUEST, deleteCShiftFlow);
|
||||||
|
yield takeLatest(GET_PSHIFTS_REQUEST, getPShiftsFlow);
|
||||||
}
|
}
|
||||||
|
|
30
src/sagas/pShift.sagas.js
Normal file
30
src/sagas/pShift.sagas.js
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { effects } from "redux-saga";
|
||||||
|
import {
|
||||||
|
isSendingPShiftRequest,
|
||||||
|
setPShiftRequestError,
|
||||||
|
setPShiftRequestSuccess,
|
||||||
|
clearPShiftRequestError,
|
||||||
|
clearPShiftRequestSuccess
|
||||||
|
} from "../actions/pShift/reducer.actions";
|
||||||
|
import { getPShifts } from "../api/pShift.api";
|
||||||
|
|
||||||
|
function* getPShiftsCall(params) {
|
||||||
|
yield effects.put(isSendingPShiftRequest(true));
|
||||||
|
try {
|
||||||
|
return yield effects.call(getPShifts, params);
|
||||||
|
} catch (exception) {
|
||||||
|
yield effects.put(setPShiftRequestError(exception));
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
yield effects.put(isSendingPShiftRequest(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* getPShiftsFlow(request) {
|
||||||
|
yield effects.put(clearPShiftRequestSuccess());
|
||||||
|
yield effects.put(clearPShiftRequestError());
|
||||||
|
const wasSuccessful = yield effects.call(getPShiftsCall, request.data);
|
||||||
|
if (wasSuccessful) {
|
||||||
|
yield effects.put(setPShiftRequestSuccess(wasSuccessful));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user