REST DELETE UPDATE

This commit is contained in:
Tomasz Kasprowicz 2020-12-25 12:19:28 +01:00
parent e4e218a910
commit ab1ee69dda
11 changed files with 367 additions and 35 deletions

5
package-lock.json generated
View File

@ -4757,6 +4757,11 @@
"whatwg-url": "^8.0.0"
}
},
"dayjs": {
"version": "1.9.7",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.9.7.tgz",
"integrity": "sha512-IC877KBdMhBrCfBfJXHQlo0G8keZ0Opy7YIIq5QKtUbCuHMzim8S4PyiVK4YmihI3iOF9lhfUBW4AQWHTR5WHA=="
},
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",

View File

@ -12,6 +12,7 @@
"@types/react-router-dom": "^5.1.6",
"@types/styled-components": "^5.1.4",
"bootstrap": "^4.5.3",
"dayjs": "^1.9.7",
"immer": "^8.0.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",

View File

@ -19,10 +19,14 @@ function App() {
setSiderDrawer(!sideDrawer);
};
const closeSidebarOnClickHandler = ()=>{
setSiderDrawer(false);
}
return (
<StyledApp>
<Header sideDrawer={toggleSideDrawerHandler} isOpen={sideDrawer} />
{sideDrawer && <SideDrawer />}
{sideDrawer && <SideDrawer close={closeSidebarOnClickHandler}/>}
<Switch>
<Route exact path="/">
<CreateTask />
@ -39,7 +43,7 @@ function App() {
<Route exact path="/current">
<TodoList />
</Route>
<Route exact path="/business">
<Route exact path="/bussiness">
<TodoList />
</Route>
<Route exact path="/personal">

View File

@ -4,6 +4,7 @@ import "../../node_modules/bootstrap/dist/css/bootstrap.min.css";
import { connect } from "react-redux";
import * as actions from "../store/actions/actions";
import { withRouter } from "react-router-dom";
import dayjs from'dayjs';
const StyledTasks = styled.div`
width: 100%;
@ -32,6 +33,8 @@ const CreateTask = (props: any) => {
const [isImportant, setIsImportant] = useState<boolean>(false);
const [date, setDate] = useState<string>("");
const currDate = dayjs(new Date()).format('YYYY-MM-DD');
const addTaskHandler = () => {
const isValid = formValidator();
if (isValid) {
@ -135,6 +138,7 @@ const CreateTask = (props: any) => {
<label>End Date</label>
<input
type="date"
min={currDate}
className="form-control"
placeholder="Date"
onChange={(e) => setDate(e.target.value)}

View File

@ -9,7 +9,7 @@ const StyledHeader = styled.div`
height: 8%;
position: relative;
z-index: 100;
background-color: #4153af;
/* background-color: #4153af; */
padding: 1rem;
display: flex;
align-items: center;
@ -46,7 +46,7 @@ const Header: React.FC<Props> = (props: Props) => {
}
return (
<StyledHeader>
<StyledHeader className="bg-dark">
<Button onClick={props.sideDrawer}>
{props.isOpen ? (
<i className="fas fa-times menu-icon"></i>

View File

@ -44,7 +44,7 @@ const StyledSidedrawer = styled.div`
color: #fff;
}
.active {
color: #4153af;
color: orange;
}
}
}
@ -53,48 +53,70 @@ const StyledSidedrawer = styled.div`
}
`;
const SideDrawer = () => {
interface Props {
close: () => void;
}
const SideDrawer = (props: Props) => {
return (
<StyledSidedrawer>
<ul>
<li>
<NavLink to={process.env.PUBLIC_URL + "/all"}>
<NavLink to={process.env.PUBLIC_URL + "/all"} onClick={props.close}>
<i className="fas fa-box-open"></i>
<span>All</span>
</NavLink>
</li>
<li>
<NavLink to={process.env.PUBLIC_URL + "/finished"}>
<NavLink
to={process.env.PUBLIC_URL + "/finished"}
onClick={props.close}
>
<i className="fas fa-hourglass-end"></i>
<span>Finished</span>
</NavLink>
</li>
<li>
<NavLink to={process.env.PUBLIC_URL + "/current"}>
<NavLink
to={process.env.PUBLIC_URL + "/current"}
onClick={props.close}
>
<i className="fas fa-stopwatch"></i>
<span>On going</span>
</NavLink>
</li>
<li>
<NavLink to={process.env.PUBLIC_URL + "/business"}>
<NavLink
to={process.env.PUBLIC_URL + "/bussiness"}
onClick={props.close}
>
<i className="fas fa-briefcase"></i>
<span>Bussiness</span>
</NavLink>
</li>
<li>
<NavLink to={process.env.PUBLIC_URL + "/personal"}>
<NavLink
to={process.env.PUBLIC_URL + "/personal"}
onClick={props.close}
>
<i className="fas fa-lock"></i>
<span>Personal</span>
</NavLink>
</li>
<li>
<NavLink to={process.env.PUBLIC_URL + "/important"}>
<NavLink
to={process.env.PUBLIC_URL + "/important"}
onClick={props.close}
>
<i className="fas fa-flag"></i>
<span>Important</span>
</NavLink>
</li>
<li>
<NavLink to={process.env.PUBLIC_URL + "/canceled"}>
<NavLink
to={process.env.PUBLIC_URL + "/canceled"}
onClick={props.close}
>
<i className="fas fa-ban"></i>
<span>Canceled</span>
</NavLink>

View File

@ -3,6 +3,8 @@ import * as actions from "../store/actions/actions";
import "../../node_modules/bootstrap/dist/css/bootstrap.min.css";
import { connect } from "react-redux";
import styled from "styled-components";
import sadFace from "../assets/images/sadFace.png";
import { withRouter } from "react-router-dom";
interface TODOtype {
date: string;
@ -11,13 +13,19 @@ interface TODOtype {
isImportant: string;
taskType: string;
hash: string;
isFinished: boolean;
}
const TodosStyled = styled.div`
display: flex;
flex-direction:column;
height:92%;
height: 92%;
overflow: scroll;
justify-content: center;
flex-wrap: wrap;
.description {
height: 100px;
overflow: scroll;
}
`;
const TodoList = (props: any) => {
@ -25,27 +33,195 @@ const TodoList = (props: any) => {
props.isAuth && props.loadToDos(props.userId, props.idToken);
}, []);
const taskType = props.match.path.substring(1);
console.log(taskType);
const finishTaskHandler = (hash: string, idToken: string) => {
console.log("update");
props.finishToDo(hash, idToken, props.todos);
};
const deleteTaskHandler = (hash: string, idToken: string) => {
console.log("delete");
props.deleteToDo(hash, idToken, props.todos);
};
let cards = [];
if (props.isLoading === false) {
if (props.isLoading === false && props.isAuth === true) {
cards = props.todos.map((todo: TODOtype) => {
return (
<div
className="card text-white bg-info mb-3"
style={{ width: "100%" }}
key={todo.hash}
>
<div className="card-header">{todo.date}</div>
<div className="card-body">
<h5 className="card-title">{todo.taskName}</h5>
<p className="card-text">{todo.taskDesc}</p>
<hr />
<p className="card-text">{todo.isImportant && "important"}</p>
<hr />
<p className="card-text">{todo.taskType}</p>
console.log(todo);
if (todo.isFinished === true && taskType === "finished") {
return (
<div
className="card bg-light"
style={{ width: "200px", flexGrow: 1, height: "min-content" }}
key={todo.hash}
>
<div className="card-header">End Date: {todo.date}</div>
<div className="card-body">
<h5 className="card-title">Title: {todo.taskName}</h5>
<p className="card-text description">
Description: {todo.taskDesc}
</p>
<hr />
<p className="card-text">
Important:{" "}
{todo.isImportant ? (
<input type="checkbox" readOnly checked />
) : (
<input type="checkbox" readOnly checked={false} />
)}
</p>
<hr />
<p className="card-text">type: {todo.taskType}</p>
<button
type="button"
className="btn btn-danger"
onClick={() => deleteTaskHandler(todo.hash, props.idToken)}
>
Delete <i className="fas fa-minus-circle"></i>
</button>
</div>
</div>
</div>
);
);
} else if (taskType === "all" && todo.isFinished === false ) {
return (
<div
className="card bg-light"
style={{ width: "200px", flexGrow: 1, height: "min-content" }}
key={todo.hash}
>
<div className="card-header">End Date: {todo.date}</div>
<div className="card-body">
<h5 className="card-title">Title: {todo.taskName}</h5>
<p className="card-text description">
Description: {todo.taskDesc}
</p>
<hr />
<p className="card-text">
Important:{" "}
{todo.isImportant ? (
<input type="checkbox" readOnly checked />
) : (
<input type="checkbox" readOnly checked={false} />
)}
</p>
<hr />
<p className="card-text">type: {todo.taskType}</p>
{!todo.isFinished && (
<button
onClick={() => finishTaskHandler(todo.hash, props.idToken)}
type="button"
className="btn btn-dark"
>
Finish <i className="fas fa-check"></i>
</button>
)}
<button
type="button"
className="btn btn-danger"
onClick={() => deleteTaskHandler(todo.hash, props.idToken)}
>
Delete <i className="fas fa-minus-circle"></i>
</button>
</div>
</div>
);
} else if (todo.taskType === taskType && todo.isFinished === false) {
return (
<div
className="card bg-light"
style={{ width: "200px", flexGrow: 1, height: "min-content" }}
key={todo.hash}
>
<div className="card-header">End Date: {todo.date}</div>
<div className="card-body">
<h5 className="card-title">Title: {todo.taskName}</h5>
<p className="card-text description">
Description: {todo.taskDesc}
</p>
<hr />
<p className="card-text">
Important:{" "}
{todo.isImportant ? (
<input type="checkbox" readOnly checked />
) : (
<input type="checkbox" readOnly checked={false} />
)}
</p>
<hr />
<p className="card-text">type: {todo.taskType}</p>
<button
onClick={() => finishTaskHandler(todo.hash, props.idToken)}
type="button"
className="btn btn-dark"
>
Finish <i className="fas fa-check"></i>
</button>
<button
type="button"
className="btn btn-danger"
onClick={() => deleteTaskHandler(todo.hash, props.idToken)}
>
Delete <i className="fas fa-minus-circle"></i>
</button>
</div>
</div>
);
} else if (
todo.isImportant &&
taskType === "important" &&
todo.isFinished === false
) {
return (
<div
className="card bg-light"
style={{ width: "200px", flexGrow: 1, height: "min-content" }}
key={todo.hash}
>
<div className="card-header">End Date: {todo.date}</div>
<div className="card-body">
<h5 className="card-title">Title: {todo.taskName}</h5>
<p className="card-text description">
Description: {todo.taskDesc}
</p>
<hr />
<p className="card-text">
Important:{" "}
{todo.isImportant ? (
<input type="checkbox" readOnly checked />
) : (
<input type="checkbox" readOnly checked={false} />
)}
</p>
<hr />
<p className="card-text">type: {todo.taskType}</p>
<button
onClick={() => finishTaskHandler(todo.hash, props.idToken)}
type="button"
className="btn btn-dark"
>
Finish <i className="fas fa-check"></i>
</button>
<button
type="button"
className="btn btn-danger"
onClick={() => deleteTaskHandler(todo.hash, props.idToken)}
>
Delete <i className="fas fa-minus-circle"></i>
</button>
</div>
</div>
);
}
});
} else {
return (
<div style={{ textAlign: "center" }}>
<i className="fas fa-frown" style={{ fontSize: "200px" }}></i>
<h2>Login!</h2>
</div>
);
}
return <TodosStyled>{cards}</TodosStyled>;
};
@ -72,7 +248,14 @@ const mapDispatchToProps = (dispatch: any) => {
return {
loadToDos: (userId: string, idToken: string) =>
dispatch(actions.loadToDos(userId, idToken)),
finishToDo: (hash: string, idToken: string, todoList: []) =>
dispatch(actions.finishToDo(hash, idToken, todoList)),
deleteToDo: (hash: string, idToken: string, todoList: []) =>
dispatch(actions.deleteToDo(hash, idToken, todoList)),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(TodoList);
export default connect(
mapStateToProps,
mapDispatchToProps
)(withRouter(TodoList));

View File

@ -7,4 +7,8 @@ export const AUTH_LOGOUT = 'AUTH_LOGOUT';
export const ADD_SUCCESS = 'ADD_SUCCESS';
export const ADD_FAIL = 'ADD_FAIL';
export const LOAD_FAIL = 'LOAD_FAIL';
export const LOAD_SUCCESS = 'LOAD_SUCCESS';
export const LOAD_SUCCESS = 'LOAD_SUCCESS';
export const UPDATE_SUCCESS = 'UPDATE_SUCCESS';
export const UPDATE_FAIL = 'UPDATE_FAIL';
export const DELETE_SUCCESS = 'DELETE_SUCCESS';
export const DELETE_FAIL = 'DELETE_FAIL';

View File

@ -5,6 +5,17 @@ type ILoadToDos = {
todos: Array<object>;
};
type ToDos = {
date: string;
desc: string;
important: boolean;
isFinished: boolean;
name: string;
type: string;
userId: string;
hash: string;
};
export const loadToDos = (userId: string, token: string) => {
return (dispatch: any) => {
let url = `https://to-do-studia.firebaseio.com/todos.json?auth=${token}&orderBy="userId"&equalTo="${userId}"`;
@ -24,6 +35,7 @@ export const loadToDos = (userId: string, token: string) => {
isImportant: data[key].important,
date: data[key].date,
userId: data[key].userId,
isFinished: data[key].isFinished,
});
}
dispatch({
@ -105,6 +117,7 @@ export const addToDo = (
important: important,
date: date,
userId: userId,
isFinished: false,
};
let url = `https://to-do-studia.firebaseio.com/todos.json?auth=${token}`;
@ -133,3 +146,78 @@ export const addToDo = (
});
};
};
export const finishToDo = (
hash: string,
token: string,
todoList: Array<ToDos>
) => {
return (dispatch: any) => {
const data = {
isFinished: true,
};
const newArr = todoList.filter(todo => {
if(hash === todo.hash){
todo.isFinished = true;
}
return todo;
});
let url = `https://to-do-studia.firebaseio.com/todos/${hash}.json?auth=${token}`;
fetch(url, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
.then((res) => res.json())
.then((data) => {
if (data.error) {
throw new Error(data.error.message);
}
dispatch({
type: actionType.UPDATE_SUCCESS,
todos: newArr
});
})
.catch((err) => {
dispatch({
type: actionType.UPDATE_FAIL,
error: err,
});
});
};
};
export const deleteToDo = (
hash: string,
token: string,
todoList: Array<ToDos>
) => {
return (dispatch: any) => {
const data = {
isFinished: true,
};
const newArr = todoList.filter((todo) => todo.hash !== hash);
let url = `https://to-do-studia.firebaseio.com/todos/${hash}.json?auth=${token}`;
fetch(url, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
.then((res) => res.json())
.then((data) => {
dispatch({
type: actionType.DELETE_SUCCESS,
todos: newArr,
});
})
};
};

View File

@ -1 +1 @@
export {loadToDos, addToDo, auth, authLogout} from './actions';
export {loadToDos, addToDo, auth, authLogout, finishToDo, deleteToDo} from './actions';

View File

@ -55,6 +55,7 @@ const reducer = (state = initialState, action: ActionType) => {
userId: null,
idToken: null,
rateData: null,
todos: [],
};
case actionType.LOAD_SUCCESS:
return {
@ -67,6 +68,26 @@ const reducer = (state = initialState, action: ActionType) => {
...state,
error: action.error,
};
case actionType.UPDATE_SUCCESS:
return {
...state,
todos: action.todos,
};
case actionType.UPDATE_FAIL:
return {
...state,
error: action.error,
};
case actionType.DELETE_SUCCESS:
return {
...state,
todos: action.todos,
};
case actionType.DELETE_FAIL:
return {
...state,
error: action.error,
};
default:
return state;
}