REST DELETE UPDATE
This commit is contained in:
parent
e4e218a910
commit
ab1ee69dda
5
package-lock.json
generated
5
package-lock.json
generated
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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">
|
||||
|
@ -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)}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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));
|
||||
|
@ -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';
|
@ -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,
|
||||
});
|
||||
})
|
||||
};
|
||||
};
|
||||
|
@ -1 +1 @@
|
||||
export {loadToDos, addToDo, auth, authLogout} from './actions';
|
||||
export {loadToDos, addToDo, auth, authLogout, finishToDo, deleteToDo} from './actions';
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user