Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21,043 changes: 0 additions & 21,043 deletions package-lock.json

This file was deleted.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
"@mui/icons-material": "^5.1.1",
"@mui/material": "^5.1.1",
"@mui/styles": "^5.2.0",
"axios": "^0.24.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-minimal-pie-chart": "^8.2.0",
"react-redux": "^7.2.6",
"react-router": "^6.0.2",
"react-router-dom": "^6.0.2",
Expand Down
4 changes: 2 additions & 2 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ function App () {
<Route index element={<div>Landing Page</div>} />
{/* /tasks */}
<Route path="tasks" element={<TasksListPage />} />
{/* /tasks/self */}
<Route path="tasks/self" element={<div>My Tasks</div>} />
{/* /tasks/:user */}
<Route path="tasks/:user" element={<TasksListPage />} />
{/* /dashboard */}
<Route path="dashboard" element={<div>Dashboard in construction</div>} />
</Route>
Expand Down
9 changes: 5 additions & 4 deletions src/actions/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ export const API_START = 'API_START';
export const API_SUCCESS = 'API_SUCCESS';
export const API_FAILURE = 'API_FAILURE';

export const apiStart = ({body, method, url}) => ({
export const apiStart = ({ body, method, url, onSuccess }) => ({
type: API_START,
payload: body,
meta: {method, url}
meta: { method, url, onSuccess },
});

export const apiSuccess = ({response}) => ({
export const apiSuccess = ({ response, onSuccess }) => ({
type: API_SUCCESS,
payload: response
payload: response,
meta: onSuccess,
});

export const apiFailure = ({error}) => ({
Expand Down
54 changes: 45 additions & 9 deletions src/actions/tasks.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,60 @@
import { SET_LOADER } from "./ui";

// feature name
export const TASKS = '[TASKS]';

// action types
// command actions
export const FETCH_TASKS = `${TASKS} FETCH`;
export const POST_TASK = `${TASKS} POST`;
export const PUT_TASK = `${TASKS} PUT`;
// document actions
export const SET_TASKS = `${TASKS} SET`;
export const ADD_TASKS = `${TASKS} ADD`;
export const UPDATE_TASKS = `${TASKS} UPDATE`;
export const SET_TASK_LIST = "SET_TASK_LIST";
export const SET_TASK_FILTER = "SET_TASK_FILTER";
export const SET_TASK_HIDE_TIMER = "SET_TASK_HIDE_TIMER";

export const fetchTasks = ({query}) => ({
export const fetchTasks = ({ query }) => ({
type: FETCH_TASKS,
payload: query
payload: query,
});

export const addTasks = ({ response }) => ({
type: ADD_TASKS,
payload: response,
});

export const postTask = ({ task }) => ({
type: POST_TASK,
payload: task,
});

export const putTask = ({ task, paramId }) => ({
type: PUT_TASK,
payload: task,
paramId
});

export const setTasks = ({list}) => ({
type: SET_TASKS,
payload: list
export const updateTasks = ({ response }) => ({
type: UPDATE_TASKS,
payload: response,
});

export const setList = ({ response }) => ({
type: SET_TASK_LIST,
data: response,
});

export const setFilter = (filter) => ({
type: SET_TASK_FILTER,
filterApplied: filter,
});

export const setHideTimer = (timer) => ({
type: SET_TASK_HIDE_TIMER,
hideTimer: timer,
});


/*
FETCH_TASKS -> API_START -> API_SUCCESS -> SET_TASKS
SET_LOADER SET_LOADER
Expand All @@ -30,4 +66,4 @@ FETCH_TASKS -> API_START -> API_SUCCESS -> SET_TASKS
/*
POST_TASK -> API_START -> API_SUCCESS -> ADD_TASK
-> API_FAILURE -> SET_NOTIFICATION
*/
*/
36 changes: 36 additions & 0 deletions src/components/ChartCard/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from "react";
import { Card, CardContent, CardHeader, Typography } from "@mui/material";
import { PieChart } from "react-minimal-pie-chart";

const ChartCard = ({ data }) => {
const dataForChart = [
{
title: "Done",
value: data.filter((task) => task.completed).length,
color: "#c4e6d5",
},
{
title: "In-Progress",
value: data.filter((task) => !task.completed).length,
color: "#ffc7a2",
},
];
return (
<Card>
<CardHeader></CardHeader>
<CardContent>
<Typography variant="h6">
Done: {dataForChart[0].value}
</Typography>
<Typography variant="h6">
In-Progress: {dataForChart[1].value}
</Typography>
<PieChart
data={dataForChart}
/>
</CardContent>
</Card>
);
};

export default ChartCard;
2 changes: 1 addition & 1 deletion src/components/NavigationBar/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function NavigationBar(props) {
<List>
<ListItemLink to="/" label="Landing Page" icon={<HomeIcon />} />
<ListItemLink to="/tasks" label="Tasks" icon={<TaskIcon />}/>
<ListItemLink to="/tasks/self"label="My Tasks" icon={<TaskIcon />} />
<ListItemLink to="/tasks/Doe"label="My Tasks" icon={<TaskIcon />} />
<ListItemLink to="/dashboard" label="Dashboard" icon={<DashboardIcon />}/>
</List>
<Divider />
Expand Down
38 changes: 24 additions & 14 deletions src/middlewares/api.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
import axios from "axios";
import { apiFailure, apiSuccess, API_START } from "../actions/api";

export const apiMiddleware = ({dispatch}) => (next) => (action) => {
next(action);
if (action.type === API_START) {
const { method, body, url } = action.meta;
fetch(url, { method: method, body: body })
.then(response => response.json())
.then(data => {
dispatch(apiSuccess({response: data.list}));
})
.catch(function(error) {
dispatch(apiFailure({error: error}));
});
}
}
export const apiMiddleware =
({ dispatch }) =>
(next) =>
(action) => {
next(action);
if (action.type === API_START) {
const { method, url, onSuccess } = action.meta;
const config = {
method,
url,
data: action.payload,
};
axios
.request(config)
.then((response) => {
console.log("response", response.data);
dispatch(apiSuccess({ response: response.data, onSuccess }));
})
.catch((error) => {
dispatch(apiFailure({ error: error }));
});
}
};
43 changes: 37 additions & 6 deletions src/middlewares/tasks.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,53 @@
import { apiStart, API_FAILURE, API_SUCCESS } from "../actions/api";
import { FETCH_TASKS, setTasks } from "../actions/tasks";
import { FETCH_TASKS, POST_TASK, PUT_TASK, setList, addTasks, updateTasks } from "../actions/tasks";
import { setLoader, setNotification } from "../actions/ui";

const TASKS_API_GET = "http://localhost:3000/data/tasks.json";
const TASKS_API_ENDPOINT =
"https://davidvida-tasks-service.herokuapp.com/api/v1/task";

export const tasksMiddleware = () => (next) => (action) => {
next(action);
switch(action.type) {
switch (action.type) {
case FETCH_TASKS:
next(apiStart({body: null, method: 'GET', url: TASKS_API_GET}));
next(
apiStart({
body: null,
method: "GET",
url: TASKS_API_ENDPOINT,
onSuccess: (response) => setList(response),
})
);
next(setLoader(true));
break;
case POST_TASK:
next(
apiStart({
body: action.payload,
method: "POST",
url: TASKS_API_ENDPOINT,
onSuccess: (response) => addTasks(response),
})
);
next(setLoader(true));
break;
case PUT_TASK:
next(
apiStart({
body: action.payload,
method: "PUT",
url: `${TASKS_API_ENDPOINT}/${action.paramId}`,
onSuccess: (response) => updateTasks(response),
})
);
next(setLoader(true));
break;
case API_SUCCESS:
next(setTasks({list: action.payload}));
next(action.meta({ response: action.payload }));
next(setLoader(false));
break;
case API_FAILURE:
next(setNotification({error: action.payload}));
next(setNotification({ error: action.payload }));
next(setLoader(false));
break;
}
};
93 changes: 68 additions & 25 deletions src/pages/TaskListPage/FormAddTask/index.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,86 @@
import React, { useState, useRef, useEffect } from "react";
import React, { useState } from "react";
import {
TextField,
Button,
Dialog,
DialogContent,
DialogTitle,
DialogActions,
} from "@mui/material";

const FormAddTask = ({ onSubmitCallback }) => {
const [taskName, setTaskName] = useState("");
const inputRef = useRef();

useEffect(() => {
inputRef.current.focus();
}, []);
const [taskDescription, setTaskDescription] = useState("");
const [open, setOpen] = React.useState(false);

const onChangeName = (event) => {
setTaskName(event.target.value);
}
};
const onChangeDescription = (event) => {
setTaskDescription(event.target.value);
};

const onSubmitListener = (event) => {
event.preventDefault();
onSubmitCallback({
name: taskName
name: taskName,
description: taskDescription,
labels: [],
startDate: "",
endDate: "",
completed: false,
user: "David",
});
setTaskName("");
setOpen(false);
};
const handleClickOpen = () => {
setOpen(true);
};

const handleClose = () => {
setOpen(false);
};

return (
<form onSubmit={onSubmitListener}>
<div>
<label htmlFor="taskName">Task Name</label>
<input
type="text"
id="taskName"
name="name"
autoComplete="off"
ref={inputRef}
value={taskName}
onChange={onChangeName} />
</div>
<div>
<button type="submit" id="submitForm">
Add Task
</button>
</div>
<form>
<Button variant="outlined" onClick={handleClickOpen}>
Add New Task
</Button>
<Dialog open={open} onClose={handleClose}>
<DialogTitle>Add New Task</DialogTitle>
<DialogContent>
<TextField
autoFocus
margin="dense"
label="Task Name"
type="text"
fullWidth
variant="standard"
id="taskName"
name="name"
autoComplete="off"
value={taskName}
onChange={onChangeName}
/>
<TextField
margin="dense"
label="Description"
type="text"
fullWidth
variant="standard"
id="taskDescription"
name="description"
autoComplete="off"
value={taskDescription}
onChange={onChangeDescription}
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button onClick={onSubmitListener}>Add Task</Button>
</DialogActions>
</Dialog>
</form>
);
};
Expand Down
Loading