Merge branch 'master' into scheduling

This commit is contained in:
Alexander Wong 2018-04-18 13:07:50 -06:00
commit f90099da36
No known key found for this signature in database
GPG Key ID: E90E5D6448C2C663
13 changed files with 882 additions and 6 deletions

View File

@ -0,0 +1,78 @@
import {
IS_SENDING_PRICE_REQUEST,
SET_PRICE_REQUEST_ERROR,
CLEAR_PRICE_REQUEST_ERROR,
SET_PRICE_REQUEST_SUCCESS,
CLEAR_PRICE_REQUEST_SUCCESS,
SET_GET_EMPLOYEE_UUID,
SET_GET_WORKTYPE_UUID,
SET_FORM_PRICE_AMOUNT
} from "../../constants/price.constants";
import { parseError } from "../common.actions";
export function isSendingPriceRequest(sendingRequest) {
return {
type: IS_SENDING_PRICE_REQUEST,
data: sendingRequest
};
}
export function setPriceRequestError(exception) {
let error = parseError(exception);
if (error.amount) {
error["Amount"] = error.amount;
delete error["amount"];
}
if (error.get_employee_uuid) {
error["Employee"] = error.get_employee_uuid;
delete error["get_employee_uuid"];
}
if (error.get_work_type_uuid) {
error["WorkType"] = error.get_work_type_uuid;
delete error["get_work_type_uuid"];
}
return {
type: SET_PRICE_REQUEST_ERROR,
data: error
};
}
export function clearPriceRequestError() {
return {
type: CLEAR_PRICE_REQUEST_ERROR
};
}
export function setPriceRequestSuccess(response) {
return {
type: SET_PRICE_REQUEST_SUCCESS,
data: response.detail || response
};
}
export function clearPriceRequestSuccess() {
return {
type: CLEAR_PRICE_REQUEST_SUCCESS
};
}
export function setGetEmployeeUUID(uuid) {
return {
type: SET_GET_EMPLOYEE_UUID,
data: uuid
};
}
export function setGetWorktypeUUID(uuid) {
return {
type: SET_GET_WORKTYPE_UUID,
data: uuid
};
}
export function setFormPriceAmount(amount) {
return {
type: SET_FORM_PRICE_AMOUNT,
data: amount
};
}

View File

@ -0,0 +1,26 @@
import {
CREATE_PRICE_REQUEST,
UPDATE_PRICE_REQUEST,
DELETE_PRICE_REQUEST
} from "../../constants/price.constants";
export function createPriceRequest(postBody) {
return {
type: CREATE_PRICE_REQUEST,
data: postBody
};
}
export function updatePriceRequest(payload) {
return {
type: UPDATE_PRICE_REQUEST,
data: payload
};
}
export function deletePriceRequest(payload) {
return {
type: DELETE_PRICE_REQUEST,
data: payload
};
}

32
src/api/price.api.js Normal file
View File

@ -0,0 +1,32 @@
import { post, patch, del } from "./baseApi";
/**
* Function wrapping POST request for creating prices
* @param {string} get_employee_uuid - UUID of the employee
* @param {string} get_work_type_uuid - UUID of the work type
* @param {double} amount - amount rate per hour
*/
export function createPrice(get_employee_uuid, get_work_type_uuid, amount) {
return post("/price/", {
get_employee_uuid,
get_work_type_uuid,
amount
}).then(resp => Promise.resolve(resp));
}
/**
* Function wrapping PATCH request for updating prices
* @param {string} uuid - UUID of the price
* @param {double} amount - new amount rate per hour
*/
export function updatePrice(uuid, amount) {
return patch(`/price/${uuid}/`, { amount }).then(resp => Promise.resolve(resp));
}
/**
* Function wrapping DELETE request for deleting the price
* @param {string} uuid - UUID of the price
*/
export function deletePrice(uuid) {
return del(`/price/${uuid}/`).then(resp => Promise.resolve(resp));
}

View File

@ -11,6 +11,8 @@ import CreateWorkTypeForm from "./Worktype/CreateWorkTypeForm";
import UpdateWorkTypeForm from "./Worktype/UpdateWorkTypeForm"; import UpdateWorkTypeForm from "./Worktype/UpdateWorkTypeForm";
import Worktypes from "./Worktype/Worktypes"; import Worktypes from "./Worktype/Worktypes";
import ClientProviders from "./User/Client/ClientProviders"; import ClientProviders from "./User/Client/ClientProviders";
import CreatePriceForm from "./User/Client/CreatePriceForm";
import UpdatePriceForm from "./User/Client/UpdatePriceForm";
import ClientAddProviderForm from "./User/Client/ClientAddProviderForm"; import ClientAddProviderForm from "./User/Client/ClientAddProviderForm";
import ClientShifts from "./User/Client/ClientShifts"; import ClientShifts from "./User/Client/ClientShifts";
import ClientAddShiftForm from "./User/Client/ClientAddShiftForm"; import ClientAddShiftForm from "./User/Client/ClientAddShiftForm";
@ -66,6 +68,14 @@ class App extends Component {
path="/user/profile/client/create-worktype" path="/user/profile/client/create-worktype"
component={CreateWorkTypeForm} component={CreateWorkTypeForm}
/> />
<PrivateRoute
path="/user/profile/client/providers/:providerUUID/update-price/:priceUUID"
component={UpdatePriceForm}
/>
<PrivateRoute
path="/user/profile/client/providers/:providerUUID/create-price"
component={CreatePriceForm}
/>
<PrivateRoute <PrivateRoute
path="/user/profile/client/providers" path="/user/profile/client/providers"
component={ClientProviders} component={ClientProviders}

View File

@ -6,18 +6,24 @@ import {
Card, Card,
Container, Container,
Header, Header,
Icon,
Label, Label,
List, List,
Popup, Popup,
Segment Segment
} from "semantic-ui-react"; } from "semantic-ui-react";
import { deleteEmployeeRequest } from "../../../actions/employee/saga.actions"; import { deleteEmployeeRequest } from "../../../actions/employee/saga.actions";
import { deletePriceRequest } from "../../../actions/price/saga.actions";
class ClientProviders extends Component { class ClientProviders extends Component {
deleteEmployee = uuid => { deleteEmployee = uuid => {
this.props.dispatch(deleteEmployeeRequest(uuid)); this.props.dispatch(deleteEmployeeRequest(uuid));
}; };
deletePrice = uuid => {
this.props.dispatch(deletePriceRequest(uuid));
};
render() { render() {
const { selfUser } = this.props; const { selfUser } = this.props;
if (selfUser.client) { if (selfUser.client) {
@ -25,6 +31,7 @@ class ClientProviders extends Component {
<ClientProvidersView <ClientProvidersView
user={selfUser} user={selfUser}
deleteEmployee={this.deleteEmployee} deleteEmployee={this.deleteEmployee}
deletePrice={this.deletePrice}
/> />
); );
} else { } else {
@ -37,7 +44,7 @@ function mapStateToProps(state) {
return { selfUser: state.user.selfUser }; return { selfUser: state.user.selfUser };
} }
const ClientProvidersView = ({ user, deleteEmployee }) => ( const ClientProvidersView = ({ user, deleteEmployee, deletePrice }) => (
<Container> <Container>
<Header>Providers</Header> <Header>Providers</Header>
<Segment> <Segment>
@ -62,13 +69,13 @@ const ClientProvidersView = ({ user, deleteEmployee }) => (
{(employee.approved === null || {(employee.approved === null ||
employee.approved === false) && ( employee.approved === false) && (
<div> <div>
<Card.Header as="h4">{employee.provider}</Card.Header> <Card.Header as="h3">{employee.provider}</Card.Header>
<Card.Description>{employee.note}</Card.Description> <Card.Description>{employee.note}</Card.Description>
</div> </div>
)} )}
{employee.approved && ( {employee.approved && (
<div> <div>
<Card.Header as="h4"> <Card.Header as="h3">
{`${employee.provider.first_name} ${ {`${employee.provider.first_name} ${
employee.provider.last_name employee.provider.last_name
}`.trim() || "No Name!"} }`.trim() || "No Name!"}
@ -100,6 +107,93 @@ const ClientProvidersView = ({ user, deleteEmployee }) => (
: !!employee.approved ? "Approved" : "Ended"} : !!employee.approved ? "Approved" : "Ended"}
</Label> </Label>
</Card.Content> </Card.Content>
{employee.approved && (
<Card.Content extra>
<Card.Description>
<Card.Header as="h3">
Assigned Work{" "}
<Button
size="mini"
floated="right"
as={Link}
to={`/user/profile/client/providers/${
employee.uuid
}/create-price`}
>
Assign Work
</Button>
</Card.Header>
<List>
{employee.prices
.filter(price => !price.deleted)
.map((price, index) => (
<List.Item key={index}>
<List.Content floated="right">
<Button.Group>
<Button
as={Link}
to={`/user/profile/client/providers/${
employee.uuid
}/update-price/${price.uuid}`}
color="yellow"
size="mini"
icon
>
<Icon name="pencil" />
</Button>
<Popup
content={
<div>
Are you sure you want to delete this work?<br />
<Button
basic
color="red"
size="small"
onClick={() => deletePrice(price.uuid)}
>
Confirm Deletion
</Button>
</div>
}
trigger={
<Button color="red" size="mini" icon>
<Icon name="trash" />
</Button>
}
on="click"
position="top right"
/>
</Button.Group>
</List.Content>
<List.Header>
<Label
circular
empty
style={{
backgroundColor: price.work_type.color,
borderColor: price.work_type.color
}}
/>
<span>
{" "}
{price.work_type.label || "No Label"}
</span>
</List.Header>
<List.Description>
Hourly Rate: ${price.amount}
</List.Description>
</List.Item>
))}
{employee.prices.filter(price => !price.deleted)
.length === 0 && (
<List.Item>
<List.Header>No Prices for this Provider</List.Header>
</List.Item>
)}
</List>
</Card.Description>
</Card.Content>
)}
<Card.Content extra> <Card.Content extra>
<Popup <Popup
content={ content={

View File

@ -0,0 +1,227 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import { Link, Redirect } from "react-router-dom";
import {
Container,
Dropdown,
Form,
Header,
Input,
Label,
Message
} from "semantic-ui-react";
import {
clearPriceRequestError,
clearPriceRequestSuccess,
setGetEmployeeUUID,
setFormPriceAmount,
setGetWorktypeUUID
} from "../../../actions/price/reducer.actions";
import { createPriceRequest } from "../../../actions/price/saga.actions";
import Error from "../../Shared/Error";
class CreatePriceForm extends Component {
constructor(props) {
super(props);
// Get valid worktype options
const { selfUser } = props;
const workTypes = ((selfUser || {}).client || {}).work_types || [];
const workTypeOptions = workTypes
.filter(worktype => !worktype.deleted)
.map(worktype => ({
key: worktype.uuid,
text: worktype.label,
color: worktype.color,
value: worktype.uuid,
content: (
<span>
<Label
circular
empty
style={{
backgroundColor: worktype.color,
borderColor: worktype.color
}}
/>{" "}
{worktype.label}
</span>
)
}));
// Get referenced employee
const employeeUUID = this.props.match.params.providerUUID;
const employees = ((selfUser || {}).client || {}).employees || [];
const employee =
employees.filter(employee => employee.uuid === employeeUUID)[0] || null;
this.props.dispatch(setGetEmployeeUUID((employee || {}).uuid || ""));
this.state = {
workTypeOptions,
employee
};
}
componentWillMount = () => {
this.props.dispatch(clearPriceRequestError());
this.props.dispatch(clearPriceRequestSuccess());
};
changeWorkType = (e, data) => {
this.props.dispatch(setGetWorktypeUUID(data.value));
};
changeAmount = event => {
this.props.dispatch(setFormPriceAmount(event.target.value));
};
onSubmitPrice = event => {
event.preventDefault();
const { getEmployeeUUID, getWorktypeUUID, amount } = this.props;
this.props.dispatch(
createPriceRequest({
get_employee_uuid: getEmployeeUUID,
get_work_type_uuid: getWorktypeUUID,
amount
})
);
};
render() {
const {
isSendingPriceRequest,
priceRequestError,
priceRequestSuccess,
getEmployeeUUID,
getWorktypeUUID,
amount,
selfUser
} = this.props;
const { employee, workTypeOptions } = this.state;
if (!selfUser.client) {
return <Redirect to="/" />;
}
return (
<CreatePriceFormView
isSendingPriceRequest={isSendingPriceRequest}
priceRequestError={priceRequestError}
priceRequestSuccess={priceRequestSuccess}
employee={employee}
workTypeOptions={workTypeOptions}
getEmployeeUUID={getEmployeeUUID}
getWorktypeUUID={getWorktypeUUID}
amout={amount}
changeWorkType={this.changeWorkType}
changeAmount={this.changeAmount}
onSubmitPrice={this.onSubmitPrice}
/>
);
}
}
const CreatePriceFormView = ({
isSendingPriceRequest,
priceRequestError,
priceRequestSuccess,
employee,
workTypeOptions,
getEmployeeUUID,
getWorktypeUUID,
amount,
changeWorkType,
changeAmount,
onSubmitPrice
}) => (
<Container>
<Header>Assign Work</Header>
{employee && (
<Message info>
<Message.Header>Employee Information</Message.Header>
<Message.List>
<Message.Item>UUID: {employee.uuid}</Message.Item>
<Message.Item>
Provider Email: {(employee.provider || {}).email || "No Email!"}
</Message.Item>
<Message.Item>
Provider Name:{" "}
{`${(employee.provider || {}).first_name} ${
(employee.provider || {}).last_name
}`.trim() || "No Name!"}
</Message.Item>
<Message.Item>
Provider Phone Number:{" "}
{`${((employee.provider || {}).userinfo || {}).phone_number ||
"No Number!"}`}
</Message.Item>
<Message.Item>Approved: {"" + employee.approved}</Message.Item>
<Message.Item>Deleted: {"" + employee.deleted}</Message.Item>
</Message.List>
</Message>
)}
{!employee && (
<Message warning>
<Message.Header>Invalid Employee</Message.Header>
<p>No accessable employee exists for given UUID.</p>
</Message>
)}
{!workTypeOptions.length && (
<Message warning>
<Message.Header>No Work Types</Message.Header>
<p>
No worktypes exists. Please{" "}
<Link to="/user/profile/client/worktypes">
create some work types
</Link>.
</p>
</Message>
)}
<Form
loading={isSendingPriceRequest}
onSubmit={onSubmitPrice}
error={!!priceRequestError}
success={!!priceRequestSuccess}
>
<Form.Field>
<label>Work Type</label>
<Dropdown
placeholder="Select Work Type"
fluid
selection
search
options={workTypeOptions}
onChange={changeWorkType}
value={getWorktypeUUID}
/>
</Form.Field>
<Form.Field>
<label>Hourly Rate</label>
<Input
labelPosition="left"
type=""
placeholder="Amount"
onChange={changeAmount}
value={amount}
>
<Label basic>$</Label>
<input />
</Input>
</Form.Field>
<Error header="Create Price failed!" error={priceRequestError} />
<Message success>
<Message.Header>Create Price successful!</Message.Header>
<p>Price successfully created.</p>
{!!priceRequestSuccess && (
<Redirect to="/user/profile/client/providers" />
)}
</Message>
<Form.Button>Submit Price</Form.Button>
</Form>
</Container>
);
function mapStateToProps(state) {
return { ...state.price, selfUser: state.user.selfUser };
}
export default connect(mapStateToProps)(CreatePriceForm);

View File

@ -0,0 +1,189 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import { Redirect } from "react-router-dom";
import {
Container,
Form,
Header,
Input,
Label,
Message
} from "semantic-ui-react";
import {
clearPriceRequestError,
clearPriceRequestSuccess,
setFormPriceAmount
} from "../../../actions/price/reducer.actions";
import { updatePriceRequest } from "../../../actions/price/saga.actions";
import Error from "../../Shared/Error";
class UpdatePriceForm extends Component {
constructor(props) {
super(props);
// Get referenced employee
const { selfUser } = props;
const employeeUUID = this.props.match.params.providerUUID;
const employees = ((selfUser || {}).client || {}).employees || [];
const employee =
employees.filter(employee => employee.uuid === employeeUUID)[0] || null;
// Get referenced price
const priceUUID = this.props.match.params.priceUUID;
const price =
((employee || {}).prices || []).filter(
price => price.uuid === priceUUID && !price.deleted
)[0] || null;
this.props.dispatch(setFormPriceAmount((price || {}).amount || ""));
this.state = {
price,
employee
};
}
componentWillMount = () => {
this.props.dispatch(clearPriceRequestError());
this.props.dispatch(clearPriceRequestSuccess());
};
changeAmount = event => {
this.props.dispatch(setFormPriceAmount(event.target.value));
};
onSubmitPrice = event => {
event.preventDefault();
const { amount } = this.props;
const { price } = this.state;
this.props.dispatch(
updatePriceRequest({ uuid: (price || {}).uuid, amount })
);
};
render() {
const {
isSendingPriceRequest,
priceRequestError,
priceRequestSuccess,
amount,
selfUser
} = this.props;
const { employee, price } = this.state;
if (!selfUser.client) {
return <Redirect to="/" />;
}
return (
<UpdatePriceFormView
isSendingPriceRequest={isSendingPriceRequest}
priceRequestError={priceRequestError}
priceRequestSuccess={priceRequestSuccess}
employee={employee}
price={price}
amount={amount}
changeAmount={this.changeAmount}
onSubmitPrice={this.onSubmitPrice}
/>
);
}
}
const UpdatePriceFormView = ({
isSendingPriceRequest,
priceRequestError,
priceRequestSuccess,
employee,
price,
amount,
changeAmount,
onSubmitPrice
}) => (
<Container>
<Header>Update Assigned Work</Header>
{employee && (
<Message info>
<Message.Header>Employee Information</Message.Header>
<Message.List>
<Message.Item>UUID: {employee.uuid}</Message.Item>
<Message.Item>
Provider Email: {(employee.provider || {}).email || "No Email!"}
</Message.Item>
<Message.Item>
Provider Name:{" "}
{`${(employee.provider || {}).first_name} ${
(employee.provider || {}).last_name
}`.trim() || "No Name!"}
</Message.Item>
<Message.Item>
Provider Phone Number:{" "}
{`${((employee.provider || {}).userinfo || {}).phone_number ||
"No Number!"}`}
</Message.Item>
<Message.Item>Approved: {"" + employee.approved}</Message.Item>
<Message.Item>Deleted: {"" + employee.deleted}</Message.Item>
</Message.List>
</Message>
)}
{!employee && (
<Message warning>
<Message.Header>Invalid Employee</Message.Header>
<p>No accessable employee exists for given UUID.</p>
</Message>
)}
<Form
loading={isSendingPriceRequest}
onSubmit={onSubmitPrice}
error={!!priceRequestError}
success={!!priceRequestSuccess}
>
<Form.Field>
<label>Work Type</label>
<span>
<Label
circular
empty
style={{
backgroundColor: ((price || {}).work_type || {}).color || "#fff",
borderColor: ((price || {}).work_type || {}).color || "#fff"
}}
/>{" "}
{((price || {}).work_type || {}).label || "Unlabeled"}
{((price || {}).work_type || {}).deleted && (
<span>
{" "}
<i>(Deleted!)</i>
</span>
)}
</span>
</Form.Field>
<Form.Field>
<label>Hourly Rate</label>
<Input
labelPosition="left"
type=""
placeholder="Amount"
onChange={changeAmount}
value={amount}
>
<Label basic>$</Label>
<input />
</Input>
</Form.Field>
<Error header="Update Price failed!" error={priceRequestError} />
<Message success>
<Message.Header>Update Price successful!</Message.Header>
<p>Price successfully created.</p>
{!!priceRequestSuccess && (
<Redirect to="/user/profile/client/providers" />
)}
</Message>
<Form.Button>Update Price</Form.Button>
</Form>
</Container>
);
function mapStateToProps(state) {
return { ...state.price, selfUser: state.user.selfUser };
}
export default connect(mapStateToProps)(UpdatePriceForm);

View File

@ -49,7 +49,7 @@ const ProviderClientsView = ({ user, updateEmployer }) => (
{(employer.approved === null || {(employer.approved === null ||
employer.approved === false) && ( employer.approved === false) && (
<div> <div>
<Card.Header as="h4"> <Card.Header as="h3">
{employer.client.trim() || "No Name!"} {employer.client.trim() || "No Name!"}
</Card.Header> </Card.Header>
<Card.Description>{employer.note}</Card.Description> <Card.Description>{employer.note}</Card.Description>
@ -57,7 +57,7 @@ const ProviderClientsView = ({ user, updateEmployer }) => (
)} )}
{employer.approved && ( {employer.approved && (
<div> <div>
<Card.Header as="h4"> <Card.Header as="h3">
{`${employer.client.first_name} ${ {`${employer.client.first_name} ${
employer.client.last_name employer.client.last_name
}`.trim() || "No Name!"} }`.trim() || "No Name!"}
@ -89,6 +89,44 @@ const ProviderClientsView = ({ user, updateEmployer }) => (
: !!employer.approved ? "Approved" : "Ended"} : !!employer.approved ? "Approved" : "Ended"}
</Label> </Label>
</Card.Content> </Card.Content>
{employer.approved && (
<Card.Content extra>
<Card.Description>
<Card.Header as="h3">Assigned Work</Card.Header>
<List>
{employer.prices
.filter(price => !price.deleted)
.map((price, index) => (
<List.Item key={index}>
<List.Header>
<Label
circular
empty
style={{
backgroundColor: price.work_type.color,
borderColor: price.work_type.color
}}
/>
<span>
{" "}
{price.work_type.label || "No Label"}
</span>
</List.Header>
<List.Description>
Hourly Rate: ${price.amount}
</List.Description>
</List.Item>
))}
{employer.prices.filter(price => !price.deleted)
.length === 0 && (
<List.Item>
<List.Header>No Prices for this Client</List.Header>
</List.Item>
)}
</List>
</Card.Description>
</Card.Content>
)}
<Card.Content extra> <Card.Content extra>
<Button.Group> <Button.Group>
{!employer.approved && ( {!employer.approved && (

View File

@ -0,0 +1,14 @@
// Reducer Price Action Constants
export const IS_SENDING_PRICE_REQUEST = "IS_SENDING_PRICE_REQUEST";
export const SET_PRICE_REQUEST_ERROR = "SET_PRICE_REQUEST_ERROR";
export const CLEAR_PRICE_REQUEST_ERROR = "CLEAR_PRICE_REQUEST_ERROR";
export const SET_PRICE_REQUEST_SUCCESS = "SET_PRICE_REQUEST_SUCCESS";
export const CLEAR_PRICE_REQUEST_SUCCESS = "CLEAR_PRICE_REQUEST_SUCCESS";
export const SET_GET_EMPLOYEE_UUID = "SET_GET_EMPLOYEE_UUID";
export const SET_GET_WORKTYPE_UUID = "SET_GET_WORKTYPE_UUID";
export const SET_FORM_PRICE_AMOUNT = "SET_FORM_PRICE_AMOUNT";
// Saga Price Action Constants
export const CREATE_PRICE_REQUEST = "CREATE_PRICE_REQUEST";
export const UPDATE_PRICE_REQUEST = "UPDATE_PRICE_REQUEST";
export const DELETE_PRICE_REQUEST = "DELETE_PRICE_REQUEST";

View File

@ -4,13 +4,15 @@ import userReducer from "./userReducer";
import worktypeReducer from "./worktypeReducer"; import worktypeReducer from "./worktypeReducer";
import employeeReducer from "./employeeReducer"; import employeeReducer from "./employeeReducer";
// import employerReducer from "./employerReducer"; // unused // import employerReducer from "./employerReducer"; // unused
import priceReducer from "./priceReducer";
const reducer = combineReducers({ const reducer = combineReducers({
auth: authReducer, auth: authReducer,
user: userReducer, user: userReducer,
worktype: worktypeReducer, worktype: worktypeReducer,
employee: employeeReducer employee: employeeReducer,
// employer: employerReducer // unused // employer: employerReducer // unused
price: priceReducer
}); });
export default reducer; export default reducer;

View File

@ -0,0 +1,68 @@
import {
IS_SENDING_PRICE_REQUEST,
SET_PRICE_REQUEST_ERROR,
CLEAR_PRICE_REQUEST_ERROR,
SET_PRICE_REQUEST_SUCCESS,
CLEAR_PRICE_REQUEST_SUCCESS,
SET_GET_EMPLOYEE_UUID,
SET_GET_WORKTYPE_UUID,
SET_FORM_PRICE_AMOUNT
} from "../constants/price.constants";
const initialState = {
isSendingPriceRequest: false,
priceRequestError: "",
priceRequestSuccess: "",
getEmployeeUUID: "",
getWorktypeUUID: "",
amount: ""
};
function priceReducer(state = initialState, action) {
switch (action.type) {
case IS_SENDING_PRICE_REQUEST:
return {
...state,
isSendingPriceRequest: action.data
};
case SET_PRICE_REQUEST_ERROR:
return {
...state,
priceRequestError: action.data
};
case CLEAR_PRICE_REQUEST_ERROR:
return {
...state,
priceRequestError: ""
};
case SET_PRICE_REQUEST_SUCCESS:
return {
...state,
priceRequestSuccess: action.data
};
case CLEAR_PRICE_REQUEST_SUCCESS:
return {
...state,
priceRequestSuccess: ""
};
case SET_GET_EMPLOYEE_UUID:
return {
...state,
getEmployeeUUID: action.data
};
case SET_GET_WORKTYPE_UUID:
return {
...state,
getWorktypeUUID: action.data
};
case SET_FORM_PRICE_AMOUNT:
return {
...state,
amount: action.data
};
default:
return state;
}
}
export default priceReducer;

View File

@ -59,6 +59,16 @@ import {
} from "./employee.sagas"; } from "./employee.sagas";
import { UPDATE_EMPLOYER_REQUEST } from "../constants/employer.constants"; import { UPDATE_EMPLOYER_REQUEST } from "../constants/employer.constants";
import { updateEmployerFlow } from "./employer.sagas"; import { updateEmployerFlow } from "./employer.sagas";
import {
CREATE_PRICE_REQUEST,
UPDATE_PRICE_REQUEST,
DELETE_PRICE_REQUEST
} from "../constants/price.constants";
import {
createPriceFlow,
updatePriceFlow,
deletePriceFlow
} from "./price.sagas";
export default function* rootSaga() { export default function* rootSaga() {
yield takeLatest(SEND_REGISTER_REQUEST, registerUserFlow); yield takeLatest(SEND_REGISTER_REQUEST, registerUserFlow);
@ -83,4 +93,7 @@ export default function* rootSaga() {
yield takeLatest(READ_EMPLOYEE_REQUEST, readEmployeeFlow); yield takeLatest(READ_EMPLOYEE_REQUEST, readEmployeeFlow);
yield takeLatest(DELETE_EMPLOYEE_REQUEST, deleteEmployeeFlow); yield takeLatest(DELETE_EMPLOYEE_REQUEST, deleteEmployeeFlow);
yield takeLatest(UPDATE_EMPLOYER_REQUEST, updateEmployerFlow); yield takeLatest(UPDATE_EMPLOYER_REQUEST, updateEmployerFlow);
yield takeLatest(CREATE_PRICE_REQUEST, createPriceFlow);
yield takeLatest(UPDATE_PRICE_REQUEST, updatePriceFlow);
yield takeLatest(DELETE_PRICE_REQUEST, deletePriceFlow);
} }

85
src/sagas/price.sagas.js Normal file
View File

@ -0,0 +1,85 @@
import { effects } from "redux-saga";
import {
isSendingPriceRequest,
setPriceRequestError,
clearPriceRequestError,
setPriceRequestSuccess,
clearPriceRequestSuccess,
setGetEmployeeUUID,
setGetWorktypeUUID,
setFormPriceAmount
} from "../actions/price/reducer.actions";
import { getSelfUserRequest } from "../actions/user/saga.actions";
import { createPrice, updatePrice, deletePrice } from "../api/price.api";
function* createPriceCall(postBody) {
yield effects.put(isSendingPriceRequest(true));
const { get_employee_uuid, get_work_type_uuid, amount } = postBody;
try {
return yield effects.call(
createPrice,
get_employee_uuid,
get_work_type_uuid,
amount
);
} catch (exception) {
yield effects.put(setPriceRequestError(exception));
return false;
} finally {
yield effects.put(isSendingPriceRequest(false));
}
}
function* updatePriceCall(payload) {
yield effects.put(isSendingPriceRequest(true));
const { uuid, amount } = payload;
try {
return yield effects.call(updatePrice, uuid, amount);
} catch (exception) {
yield effects.put(setPriceRequestError(exception));
return false;
} finally {
yield effects.put(isSendingPriceRequest(false));
}
}
function* deletePriceCall(uuid) {
yield effects.put(isSendingPriceRequest(true));
try {
return yield effects.call(deletePrice, uuid);
} catch (exception) {
yield effects.put(setPriceRequestError(exception));
return false;
} finally {
yield effects.put(isSendingPriceRequest(false));
}
}
export function* createPriceFlow(request) {
yield effects.put(clearPriceRequestSuccess());
yield effects.put(clearPriceRequestError());
const wasSuccessful = yield effects.call(createPriceCall, request.data);
if (wasSuccessful) {
yield effects.put(getSelfUserRequest());
yield effects.put(setPriceRequestSuccess(wasSuccessful));
yield effects.put(setGetEmployeeUUID(""));
yield effects.put(setGetWorktypeUUID(""));
yield effects.put(setFormPriceAmount(""));
yield effects.put(clearPriceRequestError());
}
}
export function* updatePriceFlow(request) {
yield effects.put(clearPriceRequestSuccess());
yield effects.put(clearPriceRequestError());
const wasSuccessful = yield effects.call(updatePriceCall, request.data);
if (wasSuccessful) {
yield effects.put(getSelfUserRequest());
yield effects.put(setPriceRequestSuccess(wasSuccessful));
}
}
export function* deletePriceFlow(request) {
yield effects.call(deletePriceCall, request.data);
yield effects.put(getSelfUserRequest());
}