diff --git a/src/actions/cShift/reducer.actions.js b/src/actions/cShift/reducer.actions.js index e9f895f..012a246 100644 --- a/src/actions/cShift/reducer.actions.js +++ b/src/actions/cShift/reducer.actions.js @@ -1,7 +1,7 @@ import { IS_SENDING_CSHIFT_REQUEST, - SET_CSHIFT_REQUEST_ERROR, - CLEAR_CSHIFT_REQUEST_ERROR, + SET_CSHIFT_REQUEST_ERRORS, + CLEAR_CSHIFT_REQUEST_ERRORS, SET_CSHIFT_REQUEST_SUCCESS, CLEAR_CSHIFT_REQUEST_SUCCESS, SET_FORM_EMPLOYEE_UUID, @@ -14,6 +14,13 @@ import { } from "../../constants/cShift.constants"; import { parseError } from "../common.actions"; +function transformError(error) { + if (error.get_price_uuid) { + error["Price"] = error.get_price_uuid; + delete error["get_price_uuid"]; + } +} + export function isSendingCShiftRequest(sendingRequest) { return { type: IS_SENDING_CSHIFT_REQUEST, @@ -23,15 +30,25 @@ export function isSendingCShiftRequest(sendingRequest) { export function setCShiftRequestError(exception) { let error = parseError(exception); + transformError(error); return { - type: SET_CSHIFT_REQUEST_ERROR, - data: error + type: SET_CSHIFT_REQUEST_ERRORS, + data: [error] }; } +export function setCShiftRequestErrors(exceptions) { + let errors = exceptions.map(exception => parseError(exception)); + errors.forEach(error => transformError(error)); + return { + type: SET_CSHIFT_REQUEST_ERRORS, + data: errors + } +} + export function clearCShiftRequestError() { return { - type: CLEAR_CSHIFT_REQUEST_ERROR + type: CLEAR_CSHIFT_REQUEST_ERRORS }; } @@ -90,7 +107,7 @@ export function setFormShiftDates(dates) { }; } -export function setClearCshiftState() { +export function setClearCShiftState() { return { type: SET_CLEAR_CSHIFT_STATE }; diff --git a/src/actions/cShift/saga.actions.js b/src/actions/cShift/saga.actions.js new file mode 100644 index 0000000..7205cee --- /dev/null +++ b/src/actions/cShift/saga.actions.js @@ -0,0 +1,12 @@ +import { CREATE_MULTIPLE_CSHIFT_REQUEST } from "../../constants/cShift.constants"; + +/** + * Saga action for creating a list of shifts + * @param postBody[] array of post body for cshift post endpoint + */ +export function createMultipleCShiftRequest(postBodies) { + return { + type: CREATE_MULTIPLE_CSHIFT_REQUEST, + data: postBodies + }; +} diff --git a/src/api/baseApi.js b/src/api/baseApi.js index 4332b11..0cef4eb 100644 --- a/src/api/baseApi.js +++ b/src/api/baseApi.js @@ -8,7 +8,7 @@ const localStorage = global.process && process.env.NODE_ENV === "test" require("localStorage") : global.window.localStorage; -function headers() { +export function headers() { const token = localStorage.getItem("userToken") || ""; let header = { Accept: "application/json", @@ -59,3 +59,5 @@ export function del(url) { .then(response => response.data) .catch(error => Promise.reject(error)); } + +export default apiInstance; diff --git a/src/api/cShift.api.js b/src/api/cShift.api.js new file mode 100644 index 0000000..bf1c4c5 --- /dev/null +++ b/src/api/cShift.api.js @@ -0,0 +1,19 @@ +import { post } from "./baseApi"; + +export function createCShifts(postBodies) { + const cShiftUrl = `/cshift/`; + // return Promise.all( + // postBodies.map(postBody => post(cShiftUrl, postBody).catch(() => false)) + // ).then(postResponses => { + // Promise.resolve(postResponses); + // }); + return Promise.all( + postBodies.map(postBody => + post(cShiftUrl, postBody).catch(err => { + return { error: true, ...err }; + }) + ) + ).then(resp => { + return Promise.resolve(resp); + }); +} diff --git a/src/components/User/Client/ClientAddShiftForm.jsx b/src/components/User/Client/ClientAddShiftForm.jsx index ef409d9..fab0295 100644 --- a/src/components/User/Client/ClientAddShiftForm.jsx +++ b/src/components/User/Client/ClientAddShiftForm.jsx @@ -9,6 +9,7 @@ import { Form, Header, Label, + Message, TextArea } from "semantic-ui-react"; @@ -18,9 +19,11 @@ import { setFormShiftStartTime, setFormShiftDuration, setFormShiftNote, - setClearCshiftState, + setClearCShiftState, setFormShiftDates } from "../../../actions/cShift/reducer.actions"; +import { createMultipleCShiftRequest } from "../../../actions/cShift/saga.actions"; +import Error from "../../Shared/Error"; import "react-datepicker/dist/react-datepicker.css"; import "./shiftStartTimeOverrides.css"; @@ -41,7 +44,7 @@ for (let min = 60; min <= 480; min += 30) { class ClientAddShiftForm extends Component { componentWillMount = () => { - this.props.dispatch(setClearCshiftState()); + this.props.dispatch(setClearCShiftState()); }; changeSelectedEmployee = (e, { value }) => { @@ -86,8 +89,36 @@ class ClientAddShiftForm extends Component { this.props.dispatch(setFormShiftDates(shiftDatesCopy)); }; + onSubmitShifts = event => { + event.preventDefault(); + // change this into interable cshift post request bodies + const { priceUUID, startTime, duration, note, shiftDates } = this.props; + const postRequestBodies = []; + for (let shiftDateString in shiftDates) { + const dynamicStartTime = utc(startTime); + const startDate = shiftDates[shiftDateString]; + dynamicStartTime.set({ + year: startDate.get("year"), + month: startDate.get("month"), + date: startDate.get("date") + }); + const dynamicEndTime = utc(dynamicStartTime); + dynamicEndTime.add(duration, "minutes"); + postRequestBodies.push({ + get_price_uuid: priceUUID, + set_start: dynamicStartTime.format(), + set_end: dynamicEndTime.format(), + description: note ? note : undefined + }); + } + this.props.dispatch(createMultipleCShiftRequest(postRequestBodies)); + }; + render() { const { + isSendingCShiftRequest, + cShiftRequestErrors, + cShiftRequestSuccess, selfUser, employeeUUID, priceUUID, @@ -101,6 +132,10 @@ class ClientAddShiftForm extends Component { return ; } + if (cShiftRequestSuccess) { + console.log(cShiftRequestSuccess); + } + const employeeChoices = selfUser.client.employees .filter(employee => !employee.deleted && !!employee.approved) .map(({ uuid, provider }) => ({ @@ -120,7 +155,7 @@ class ClientAddShiftForm extends Component { .map(({ amount, uuid, work_type }) => ({ key: uuid, value: uuid, - text: work_type.label, + text: `${work_type.label} ($${amount}/hr)`, content: ( ); } @@ -172,6 +211,9 @@ function mapStateToProps(state) { } const ClientAddShiftFormView = ({ + isSendingCShiftRequest, + cShiftRequestErrors, + cShiftRequestSuccess, user, employeeChoices, priceChoices, @@ -186,11 +228,17 @@ const ClientAddShiftFormView = ({ changeShiftStartTime, changeShiftDuration, changeShiftNote, - handleSelectDate + handleSelectDate, + onSubmitShifts }) => ( Schedule Shifts - + Employee @@ -214,6 +262,7 @@ const ClientAddShiftFormView = ({ selection fluid search + disabled={!employeeUUID} noResultsMessage="No prices for given employee." value={priceUUID} /> @@ -266,6 +315,16 @@ const ClientAddShiftFormView = ({ .endOf("month")} /> + {!!cShiftRequestErrors.length && ( + + )} + + Add Shift successful! + Shifts successfully scheduled. + {!!cShiftRequestSuccess && ( + + )} + Schedule Shift diff --git a/src/constants/cShift.constants.js b/src/constants/cShift.constants.js index 547dbfd..ea88f65 100644 --- a/src/constants/cShift.constants.js +++ b/src/constants/cShift.constants.js @@ -1,7 +1,7 @@ // Reducer CShift Action Constants export const IS_SENDING_CSHIFT_REQUEST = "IS_SENDING_CSHIFT_REQUEST"; -export const SET_CSHIFT_REQUEST_ERROR = "SET_CSHIFT_REQUEST_ERROR"; -export const CLEAR_CSHIFT_REQUEST_ERROR = "CLEAR_CSHIFT_REQUEST_ERROR"; +export const SET_CSHIFT_REQUEST_ERRORS = "SET_CSHIFT_REQUEST_ERRORS"; +export const CLEAR_CSHIFT_REQUEST_ERRORS = "CLEAR_CSHIFT_REQUEST_ERRORS"; export const SET_CSHIFT_REQUEST_SUCCESS = "SET_CSHIFT_REQUEST_SUCCESS"; export const CLEAR_CSHIFT_REQUEST_SUCCESS = "CLEAR_CSHIFT_REQUEST_SUCCESS"; export const SET_FORM_EMPLOYEE_UUID = "SET_FORM_EMPLOYEE_UUID"; diff --git a/src/reducers/cShiftReducer.js b/src/reducers/cShiftReducer.js index 497d1a0..3083443 100644 --- a/src/reducers/cShiftReducer.js +++ b/src/reducers/cShiftReducer.js @@ -1,7 +1,7 @@ import { IS_SENDING_CSHIFT_REQUEST, - SET_CSHIFT_REQUEST_ERROR, - CLEAR_CSHIFT_REQUEST_ERROR, + SET_CSHIFT_REQUEST_ERRORS, + CLEAR_CSHIFT_REQUEST_ERRORS, SET_CSHIFT_REQUEST_SUCCESS, CLEAR_CSHIFT_REQUEST_SUCCESS, SET_FORM_EMPLOYEE_UUID, @@ -15,7 +15,7 @@ import { const initialState = { isSendingCShiftRequest: false, - cShiftRequestError: "", + cShiftRequestErrors: [], cShiftRequestSuccess: "", employeeUUID: "", // Which employee priceUUID: "", // Which price @@ -32,15 +32,15 @@ function cShiftReducer(state = initialState, action) { ...state, isSendingCShiftRequest: action.data }; - case SET_CSHIFT_REQUEST_ERROR: + case SET_CSHIFT_REQUEST_ERRORS: return { ...state, - cShiftRequestError: action.data + cShiftRequestErrors: action.data }; - case CLEAR_CSHIFT_REQUEST_ERROR: + case CLEAR_CSHIFT_REQUEST_ERRORS: return { ...state, - cShiftRequestError: "" + cShiftRequestErrors: [] }; case SET_CSHIFT_REQUEST_SUCCESS: return { diff --git a/src/sagas/cShift.sagas.js b/src/sagas/cShift.sagas.js new file mode 100644 index 0000000..35f3a08 --- /dev/null +++ b/src/sagas/cShift.sagas.js @@ -0,0 +1,61 @@ +import { effects } from "redux-saga"; +import { + isSendingCShiftRequest, + setCShiftRequestError, + setCShiftRequestErrors, + setCShiftRequestSuccess, + clearCShiftRequestError, + clearCShiftRequestSuccess, + setFormEmployeeUUID, + setFormPriceUUID, + setFormShiftDates, + setFormShiftDuration, + setFormShiftNote, + setFormShiftStartTime +} from "../actions/cShift/reducer.actions"; +import { createCShifts } from "../api/cShift.api"; + +function* createCShiftsCall(postBodies) { + yield effects.put(isSendingCShiftRequest(true)); + try { + if (postBodies.length > 0) { + return yield effects.call(createCShifts, postBodies); + } else { + yield effects.put( + setCShiftRequestError({ + response: { data: { dates: ["No dates selected."] } } + }) + ); + return false; + } + } catch (exception) { + yield effects.put(setCShiftRequestError(exception)); + return false; + } finally { + yield effects.put(isSendingCShiftRequest(false)); + } +} + +export function* createCShiftsFlow(request) { + yield effects.put(clearCShiftRequestSuccess()); + yield effects.put(clearCShiftRequestError()); + const arrResponses = yield effects.call(createCShiftsCall, request.data); + console.log(arrResponses); + if (arrResponses) { + const errorResps = arrResponses.filter(resp => !!resp.error); + if (errorResps.length > 0) { + console.log(arrResponses); + yield effects.put(setCShiftRequestErrors(errorResps)); + } + const succResps = arrResponses.filter(resp => !resp.error); + if (succResps.length > 0) { + yield effects.put(setCShiftRequestSuccess(succResps)); + yield effects.put(setFormEmployeeUUID("")); + yield effects.put(setFormPriceUUID("")); + yield effects.put(setFormShiftStartTime(null)); + yield effects.put(setFormShiftDuration("")); + yield effects.put(setFormShiftNote("")); + yield effects.put(setFormShiftDates({})); + } + } +} diff --git a/src/sagas/index.js b/src/sagas/index.js index 72c65b4..379b10b 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -69,6 +69,8 @@ import { updatePriceFlow, deletePriceFlow } from "./price.sagas"; +import { CREATE_MULTIPLE_CSHIFT_REQUEST } from "../constants/cShift.constants"; +import { createCShiftsFlow } from "./cShift.sagas"; export default function* rootSaga() { yield takeLatest(SEND_REGISTER_REQUEST, registerUserFlow); @@ -96,4 +98,5 @@ export default function* rootSaga() { yield takeLatest(CREATE_PRICE_REQUEST, createPriceFlow); yield takeLatest(UPDATE_PRICE_REQUEST, updatePriceFlow); yield takeLatest(DELETE_PRICE_REQUEST, deletePriceFlow); + yield takeLatest(CREATE_MULTIPLE_CSHIFT_REQUEST, createCShiftsFlow); }
Shifts successfully scheduled.