parent
48cc050c47
commit
0e6fb475b7
17 changed files with 689 additions and 25 deletions
@ -0,0 +1,2 @@ |
||||
{ |
||||
} |
@ -0,0 +1,74 @@ |
||||
import { |
||||
IS_SENDING_WORKTYPE_REQUEST, |
||||
SET_WORKTYPE_REQUEST_ERROR, |
||||
CLEAR_WORKTYPE_REQUEST_ERROR, |
||||
SET_WORKTYPE_REQUEST_SUCCESS, |
||||
CLEAR_WORKTYPE_REQUEST_SUCCESS, |
||||
SET_WORKTYPE_UUID, |
||||
SET_FORM_WORKTYPE_COLOR, |
||||
SET_FORM_WORKTYPE_LABEL |
||||
} from "../../constants/worktype.constants"; |
||||
import { parseError } from "../common.actions"; |
||||
|
||||
export function isSendingWorktypeRequest(sendingRequest) { |
||||
return { |
||||
type: IS_SENDING_WORKTYPE_REQUEST, |
||||
data: sendingRequest |
||||
}; |
||||
} |
||||
|
||||
export function setWorktypeRequestError(exception) { |
||||
let error = parseError(exception); |
||||
if (error.label) { |
||||
error["Label"] = error.label; |
||||
delete error["label"]; |
||||
} |
||||
if (error.color) { |
||||
error["Color"] = error.color; |
||||
delete error["color"]; |
||||
} |
||||
return { |
||||
type: SET_WORKTYPE_REQUEST_ERROR, |
||||
data: error |
||||
}; |
||||
} |
||||
|
||||
export function clearWorktypeRequestError() { |
||||
return { |
||||
type: CLEAR_WORKTYPE_REQUEST_ERROR |
||||
}; |
||||
} |
||||
|
||||
export function setWorktypeRequestSuccess(response) { |
||||
return { |
||||
type: SET_WORKTYPE_REQUEST_SUCCESS, |
||||
data: response.detail || response |
||||
}; |
||||
} |
||||
|
||||
export function clearWorktypeRequestSuccess() { |
||||
return { |
||||
type: CLEAR_WORKTYPE_REQUEST_SUCCESS |
||||
}; |
||||
} |
||||
|
||||
export function setWorktypeUUID(uuid) { |
||||
return { |
||||
type: SET_WORKTYPE_UUID, |
||||
data: uuid |
||||
}; |
||||
} |
||||
|
||||
export function setFormWorktypeColor(color) { |
||||
return { |
||||
type: SET_FORM_WORKTYPE_COLOR, |
||||
data: color |
||||
}; |
||||
} |
||||
|
||||
export function setFormWorktypeLabel(label) { |
||||
return { |
||||
type: SET_FORM_WORKTYPE_LABEL, |
||||
data: label |
||||
}; |
||||
} |
@ -0,0 +1,34 @@ |
||||
import { |
||||
CREATE_WORKTYPE_REQUEST, |
||||
READ_WORKTYPE_REQUEST, |
||||
UPDATE_WORKTYPE_REQUEST, |
||||
DELETE_WORKTYPE_REQUEST |
||||
} from "../../constants/worktype.constants"; |
||||
|
||||
export function createWorktypeRequest(postBody) { |
||||
return { |
||||
type: CREATE_WORKTYPE_REQUEST, |
||||
data: postBody |
||||
}; |
||||
} |
||||
|
||||
export function readWorktypeRequest(payload) { |
||||
return { |
||||
type: READ_WORKTYPE_REQUEST, |
||||
data: payload |
||||
}; |
||||
} |
||||
|
||||
export function updateWorktypeRequest(payload) { |
||||
return { |
||||
type: UPDATE_WORKTYPE_REQUEST, |
||||
data: payload |
||||
}; |
||||
} |
||||
|
||||
export function deleteWorktypeRequest(payload) { |
||||
return { |
||||
type: DELETE_WORKTYPE_REQUEST, |
||||
data: payload |
||||
}; |
||||
} |
@ -0,0 +1,39 @@ |
||||
import { post, get, patch, del } from "./baseApi"; |
||||
|
||||
/** |
||||
* Function wrapping POST request for creating worktypes |
||||
* @param {string} color - color value of worktype |
||||
* @param {string} label - label text of worktype |
||||
*/ |
||||
export function createWorktype(color, label) { |
||||
return post("/worktype/", { color, label }).then(resp => |
||||
Promise.resolve(resp) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Function wrapping GET request for retreiving worktype data |
||||
* @param {string} uuid - worktype unique identifier |
||||
*/ |
||||
export function getWorktype(uuid) { |
||||
return get(`/worktype/${uuid}/`).then(resp => Promise.resolve(resp)); |
||||
} |
||||
|
||||
/** |
||||
* Function wrapping PATCH request for updating worktype |
||||
* @param {string} uuid - worktype unique identifier |
||||
* @param {string} color - color value of worktype |
||||
*/ |
||||
export function updateWorktype(uuid, color) { |
||||
return patch(`/worktype/${uuid}/`, { color }).then(resp => |
||||
Promise.resolve(resp) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Function wrapping DELETE request for removing worktypes |
||||
* @param {string} uuid - worktype unique identifier |
||||
*/ |
||||
export function deleteWorktype(uuid) { |
||||
return del(`/worktype/${uuid}`).then(resp => Promise.resolve(resp)); |
||||
} |
@ -0,0 +1,75 @@ |
||||
import React, { Component } from "react"; |
||||
import { connect } from "react-redux"; |
||||
import { Link } from "react-router-dom"; |
||||
import { Card, Button, Label } from "semantic-ui-react"; |
||||
|
||||
class ClientProfile extends Component { |
||||
render() { |
||||
const { selfUser } = this.props; |
||||
return <ClientProfileView user={selfUser} />; |
||||
} |
||||
} |
||||
|
||||
function mapStateToProps(state) { |
||||
return { ...state.user }; |
||||
} |
||||
|
||||
const ClientProfileView = ({ user }) => ( |
||||
<div> |
||||
<Card fluid={true}> |
||||
<Card.Content> |
||||
<Card.Header>Client Information</Card.Header> |
||||
<Card.Meta>Business Number: {user.client.business_number}</Card.Meta> |
||||
<Card.Description> |
||||
<Button |
||||
basic |
||||
color="green" |
||||
size="small" |
||||
as={Link} |
||||
to="/user/profile/client/create-worktype" |
||||
> |
||||
Create Worktype |
||||
</Button> |
||||
</Card.Description> |
||||
</Card.Content> |
||||
</Card> |
||||
{(user.client.work_types || []).length && |
||||
<Card.Group> |
||||
{user.client.work_types.map((worktype, index) => ( |
||||
<Card key={index}> |
||||
<Card.Content> |
||||
<Card.Header as="h4"> |
||||
<Label |
||||
circular |
||||
empty |
||||
style={{ |
||||
backgroundColor: worktype.color, |
||||
borderColor: worktype.color |
||||
}} |
||||
/>{" " + worktype.label} |
||||
</Card.Header> |
||||
<Card.Meta> |
||||
Worktype |
||||
</Card.Meta> |
||||
</Card.Content> |
||||
<Card.Content extra> |
||||
<Button.Group> |
||||
<Button |
||||
basic |
||||
color="yellow" |
||||
size="small" |
||||
as={Link} |
||||
to={`/user/profile/client/update-worktype/${worktype.uuid}`} |
||||
> |
||||
Edit |
||||
</Button> |
||||
<Button basic color="red" size="small">Delete</Button> |
||||
</Button.Group> |
||||
</Card.Content> |
||||
</Card> |
||||
))} |
||||
</Card.Group>} |
||||
</div> |
||||
); |
||||
|
||||
export default connect(mapStateToProps)(ClientProfile); |
@ -0,0 +1,113 @@ |
||||
import React, { Component } from "react"; |
||||
import { GithubPicker } from "react-color"; |
||||
import { connect } from "react-redux"; |
||||
import { Container, Form, Header, Label, Message } from "semantic-ui-react"; |
||||
|
||||
import { |
||||
clearWorktypeRequestError, |
||||
clearWorktypeRequestSuccess, |
||||
setFormWorktypeColor, |
||||
setFormWorktypeLabel |
||||
} from "../../../actions/worktype/reducer.actions"; |
||||
import { createWorktypeRequest } from "../../../actions/worktype/saga.actions"; |
||||
import Error from "../../Shared/Error"; |
||||
|
||||
class CreateWorkTypeForm extends Component { |
||||
componentWillUnmount = () => { |
||||
this.props.dispatch(clearWorktypeRequestError()); |
||||
this.props.dispatch(clearWorktypeRequestSuccess()); |
||||
}; |
||||
|
||||
changeLabel = event => { |
||||
this.props.dispatch(setFormWorktypeLabel(event.target.value)); |
||||
}; |
||||
|
||||
changeColor = color => { |
||||
this.props.dispatch(setFormWorktypeColor(color.hex)); |
||||
}; |
||||
|
||||
onSubmitWorktype = event => { |
||||
event.preventDefault(); |
||||
const { label, color } = this.props; |
||||
this.props.dispatch(createWorktypeRequest({ label, color })); |
||||
}; |
||||
|
||||
render() { |
||||
const { |
||||
isSendingWorktypeRequest, |
||||
worktypeRequestError, |
||||
worktypeRequestSuccess, |
||||
label, |
||||
color |
||||
} = this.props; |
||||
|
||||
return ( |
||||
<CreateWorkTypeFormView |
||||
isSendingWorktypeRequest={isSendingWorktypeRequest} |
||||
worktypeRequestError={worktypeRequestError} |
||||
worktypeRequestSuccess={worktypeRequestSuccess} |
||||
label={label} |
||||
color={color} |
||||
changeLabel={this.changeLabel} |
||||
changeColor={this.changeColor} |
||||
onSubmitWorktype={this.onSubmitWorktype} |
||||
/> |
||||
); |
||||
} |
||||
} |
||||
|
||||
function mapStateToProps(state) { |
||||
return { ...state.worktype }; |
||||
} |
||||
|
||||
const CreateWorkTypeFormView = ({ |
||||
isSendingWorktypeRequest, |
||||
worktypeRequestError, |
||||
worktypeRequestSuccess, |
||||
label, |
||||
color, |
||||
changeLabel, |
||||
changeColor, |
||||
onSubmitWorktype |
||||
}) => ( |
||||
<Container> |
||||
<Header>Create Worktype</Header> |
||||
<Form |
||||
loading={isSendingWorktypeRequest} |
||||
onSubmit={onSubmitWorktype} |
||||
error={!!worktypeRequestError} |
||||
success={!!worktypeRequestSuccess} |
||||
> |
||||
<Form.Field> |
||||
<label>Label</label> |
||||
<input |
||||
placeholder="My worktype" |
||||
type="text" |
||||
value={label} |
||||
onChange={changeLabel} |
||||
/> |
||||
</Form.Field> |
||||
<Form.Field> |
||||
<label>Color</label> |
||||
<Label |
||||
circular |
||||
empty |
||||
size="massive" |
||||
style={{ |
||||
backgroundColor: color, |
||||
borderColor: color |
||||
}} |
||||
/> |
||||
<GithubPicker color={color} onChangeComplete={changeColor} /> |
||||
</Form.Field> |
||||
<Error header="Create Worktype failed!" error={worktypeRequestError} /> |
||||
<Message success> |
||||
<Message.Header>Create Worktype successful!</Message.Header> |
||||
<p>Set worktype successfully.</p> |
||||
</Message> |
||||
<Form.Button>Submit Worktype</Form.Button> |
||||
</Form> |
||||
</Container> |
||||
); |
||||
|
||||
export default connect(mapStateToProps)(CreateWorkTypeForm); |
@ -0,0 +1,108 @@ |
||||
import React, { Component } from "react"; |
||||
import { GithubPicker } from "react-color"; |
||||
import { connect } from "react-redux"; |
||||
import { Container, Form, Header, Label, Message } from "semantic-ui-react"; |
||||
|
||||
import { |
||||
clearWorktypeRequestError, |
||||
clearWorktypeRequestSuccess, |
||||
setFormWorktypeColor |
||||
} from "../../../actions/worktype/reducer.actions"; |
||||
import { updateWorktypeRequest, readWorktypeRequest } from "../../../actions/worktype/saga.actions"; |
||||
import Error from "../../Shared/Error"; |
||||
|
||||
class UpdateWorkTypeForm extends Component { |
||||
componentWillMount = () => { |
||||
const uuid = this.props.match.params.uuid; |
||||
this.props.dispatch(readWorktypeRequest(uuid)); |
||||
} |
||||
|
||||
componentWillUnmount = () => { |
||||
this.props.dispatch(clearWorktypeRequestError()); |
||||
this.props.dispatch(clearWorktypeRequestSuccess()); |
||||
}; |
||||
|
||||
changeColor = color => { |
||||
this.props.dispatch(setFormWorktypeColor(color.hex)); |
||||
}; |
||||
|
||||
onSubmitWorktype = event => { |
||||
event.preventDefault(); |
||||
const { uuid, color } = this.props; |
||||
this.props.dispatch(updateWorktypeRequest({ uuid, color })); |
||||
}; |
||||
|
||||
render() { |
||||
const { |
||||
isSendingWorktypeRequest, |
||||
worktypeRequestError, |
||||
worktypeRequestSuccess, |
||||
uuid, |
||||
label, |
||||
color |
||||
} = this.props; |
||||
|
||||
return ( |
||||
<UpdateWorkTypeFormView |
||||
isSendingWorktypeRequest={isSendingWorktypeRequest} |
||||
worktypeRequestError={worktypeRequestError} |
||||
worktypeRequestSuccess={worktypeRequestSuccess} |
||||
uuid={uuid} |
||||
label={label} |
||||
color={color} |
||||
changeColor={this.changeColor} |
||||
onSubmitWorktype={this.onSubmitWorktype} |
||||
/> |
||||
); |
||||
} |
||||
} |
||||
|
||||
function mapStateToProps(state) { |
||||
return { ...state.worktype }; |
||||
} |
||||
|
||||
const UpdateWorkTypeFormView = ({ |
||||
isSendingWorktypeRequest, |
||||
worktypeRequestError, |
||||
worktypeRequestSuccess, |
||||
label, |
||||
color, |
||||
changeColor, |
||||
onSubmitWorktype |
||||
}) => ( |
||||
<Container> |
||||
<Header>Update Worktype</Header> |
||||
<Form |
||||
loading={isSendingWorktypeRequest} |
||||
onSubmit={onSubmitWorktype} |
||||
error={!!worktypeRequestError} |
||||
success={!!worktypeRequestSuccess} |
||||
> |
||||
<Form.Field> |
||||
<label>Label</label> |
||||
<input type="text" disabled value={label}/> |
||||
</Form.Field> |
||||
<Form.Field> |
||||
<label>Color</label> |
||||
<Label |
||||
circular |
||||
empty |
||||
size="massive" |
||||
style={{ |
||||
backgroundColor: color, |
||||
borderColor: color |
||||
}} |
||||
/> |
||||
<GithubPicker color={color} onChangeComplete={changeColor} /> |
||||
</Form.Field> |
||||
<Error header="Update Worktype failed!" error={worktypeRequestError} /> |
||||
<Message success> |
||||
<Message.Header>Update Worktype successful!</Message.Header> |
||||
<p>Update worktype successfully.</p> |
||||
</Message> |
||||
<Form.Button>Update Worktype</Form.Button> |
||||
</Form> |
||||
</Container> |
||||
); |
||||
|
||||
export default connect(mapStateToProps)(UpdateWorkTypeForm); |
@ -0,0 +1,15 @@ |
||||
// Reducer Worktype Action Constants
|
||||
export const IS_SENDING_WORKTYPE_REQUEST = "IS_SENDING_WORKTYPE_REQUEST"; |
||||
export const SET_WORKTYPE_REQUEST_ERROR = "SET_WORKTYPE_REQUEST_ERROR"; |
||||
export const CLEAR_WORKTYPE_REQUEST_ERROR = "CLEAR_WORKTYPE_REQUEST_ERROR"; |
||||
export const SET_WORKTYPE_REQUEST_SUCCESS = "SET_WORKTYPE_REQUEST_SUCCESS"; |
||||
export const CLEAR_WORKTYPE_REQUEST_SUCCESS = "CLEAR_WORKTYPE_REQUEST_SUCCESS"; |
||||
export const SET_WORKTYPE_UUID = "SET_WORKTYPE_UUID"; |
||||
export const SET_FORM_WORKTYPE_LABEL = "SET_FORM_WORKTYPE_LABEL"; |
||||
export const SET_FORM_WORKTYPE_COLOR = "SET_FORM_WORKTYPE_COLOR"; |
||||
|
||||
// Saga Worktype Action Constants
|
||||
export const CREATE_WORKTYPE_REQUEST = "CREATE_WORKTYPE_REQUEST"; |
||||
export const READ_WORKTYPE_REQUEST = "READ_WORKTYPE_REQUEST"; |
||||
export const UPDATE_WORKTYPE_REQUEST = "UPDATE_WORKTYPE_REQUEST"; |
||||
export const DELETE_WORKTYPE_REQUEST = "DELETE_WORKTYPE_REQUEST"; |
@ -1,10 +1,12 @@ |
||||
import { combineReducers } from "redux"; |
||||
import authReducer from "./authReducer"; |
||||
import userReducer from "./userReducer"; |
||||
import worktypeReducer from "./worktypeReducer"; |
||||
|
||||
const reducer = combineReducers({ |
||||
auth: authReducer, |
||||
user: userReducer |
||||
user: userReducer, |
||||
worktype: worktypeReducer |
||||
}); |
||||
|
||||
export default reducer; |
||||
|
@ -0,0 +1,68 @@ |
||||
import { |
||||
IS_SENDING_WORKTYPE_REQUEST, |
||||
SET_WORKTYPE_REQUEST_ERROR, |
||||
CLEAR_WORKTYPE_REQUEST_ERROR, |
||||
SET_WORKTYPE_REQUEST_SUCCESS, |
||||
CLEAR_WORKTYPE_REQUEST_SUCCESS, |
||||
SET_WORKTYPE_UUID, |
||||
SET_FORM_WORKTYPE_COLOR, |
||||
SET_FORM_WORKTYPE_LABEL |
||||
} from "../constants/worktype.constants"; |
||||
|
||||
const initialState = { |
||||
isSendingWorktypeRequest: false, |
||||
worktypeRequestError: "", |
||||
worktypeRequestSuccess: "", |
||||
uuid: "", |
||||
color: "", |
||||
label: "" |
||||
}; |
||||
|
||||
function worktypeReducer(state = initialState, action) { |
||||
switch (action.type) { |
||||
case IS_SENDING_WORKTYPE_REQUEST: |
||||
return { |
||||
...state, |
||||
isSendingWorktypeRequest: action.data |
||||
}; |
||||
case SET_WORKTYPE_REQUEST_ERROR: |
||||
return { |
||||
...state, |
||||
worktypeRequestError: action.data |
||||
}; |
||||
case CLEAR_WORKTYPE_REQUEST_ERROR: |
||||
return { |
||||
...state, |
||||
worktypeRequestError: "" |
||||
}; |
||||
case SET_WORKTYPE_REQUEST_SUCCESS: |
||||
return { |
||||
...state, |
||||
worktypeRequestSuccess: action.data |
||||
}; |
||||
case CLEAR_WORKTYPE_REQUEST_SUCCESS: |
||||
return { |
||||
...state, |
||||
worktypeRequestSuccess: "" |
||||
}; |
||||
case SET_WORKTYPE_UUID: |
||||
return { |
||||
...state, |
||||
uuid: action.data |
||||
}; |
||||
case SET_FORM_WORKTYPE_COLOR: |
||||
return { |
||||
...state, |
||||
color: action.data |
||||
}; |
||||
case SET_FORM_WORKTYPE_LABEL: |
||||
return { |
||||
...state, |
||||
label: action.data |
||||
}; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
||||
|
||||
export default worktypeReducer; |
@ -0,0 +1,88 @@ |
||||
import { effects } from "redux-saga"; |
||||
import { |
||||
isSendingWorktypeRequest, |
||||
setWorktypeRequestError, |
||||
setWorktypeRequestSuccess, |
||||
clearWorktypeRequestError, |
||||
clearWorktypeRequestSuccess, |
||||
setWorktypeUUID, |
||||
setFormWorktypeColor, |
||||
setFormWorktypeLabel |
||||
} from "../actions/worktype/reducer.actions"; |
||||
import { getSelfUserRequest } from "../actions/user/saga.actions"; |
||||
import { |
||||
createWorktype, |
||||
getWorktype, |
||||
updateWorktype, |
||||
deleteWorktype |
||||
} from "../api/worktype.api"; |
||||
|
||||
function* createWorktypeCall(postBody) { |
||||
yield effects.put(isSendingWorktypeRequest(true)); |
||||
const { color, label } = postBody; |
||||
try { |
||||
return yield effects.call(createWorktype, color, label); |
||||
} catch (exception) { |
||||
yield effects.put(setWorktypeRequestError(exception)); |
||||
return false; |
||||
} finally { |
||||
yield effects.put(isSendingWorktypeRequest(false)); |
||||
} |
||||
} |
||||
|
||||
function* readWorktypeCall(uuid) { |
||||
yield effects.put(isSendingWorktypeRequest(true)); |
||||
try { |
||||
return yield effects.call(getWorktype, uuid); |
||||
} catch (exception) { |
||||
yield effects.put(setWorktypeRequestError(exception)); |
||||
return false; |
||||
} finally { |
||||
yield effects.put(isSendingWorktypeRequest(false)); |
||||
} |
||||
} |
||||
|
||||
function* updateWorktypeCall(payload) { |
||||
yield effects.put(isSendingWorktypeRequest(true)); |
||||
const { uuid, color } = payload; |
||||
try { |
||||
return yield effects.call(updateWorktype, uuid, color); |
||||
} catch (exception) { |
||||
yield effects.put(setWorktypeRequestError(exception)); |
||||
return false; |
||||
} finally { |
||||
yield effects.put(isSendingWorktypeRequest(false)); |
||||
} |
||||
} |
||||
|
||||
export function* createWorktypeFlow(request) { |
||||
yield effects.put(clearWorktypeRequestSuccess()); |
||||
yield effects.put(clearWorktypeRequestError()); |
||||
const wasSuccessful = yield effects.call(createWorktypeCall, request.data); |
||||
if (wasSuccessful) { |
||||
yield effects.put(getSelfUserRequest()); |
||||
yield effects.put(setWorktypeRequestSuccess(wasSuccessful)); |
||||
yield effects.put(setFormWorktypeColor("")); |
||||
yield effects.put(setFormWorktypeLabel("")); |
||||
yield effects.put(clearWorktypeRequestError()); |
||||
} |
||||
} |
||||
|
||||
export function* readWorktypeFlow(request) { |
||||
const wasSuccessful = yield effects.call(readWorktypeCall, request.data); |
||||
if (wasSuccessful) { |
||||
yield effects.put(setWorktypeUUID(wasSuccessful.uuid)); |
||||
yield effects.put(setFormWorktypeColor(wasSuccessful.color)); |
||||
yield effects.put(setFormWorktypeLabel(wasSuccessful.label)); |
||||
} |
||||
} |
||||
|
||||
export function* updateWorktypeFlow(request) { |
||||
yield effects.put(clearWorktypeRequestSuccess()); |
||||
yield effects.put(clearWorktypeRequestError()); |
||||
const wasSuccessful = yield effects.call(updateWorktypeCall, request.data); |
||||
if (wasSuccessful) { |
||||
yield effects.put(getSelfUserRequest()); |
||||
yield effects.put(setWorktypeRequestSuccess(wasSuccessful)); |
||||
} |
||||
} |
Loading…
Reference in new issue