added improvements, validation
This commit is contained in:
parent
76667e8a19
commit
4a0d62d419
26
src/App.tsx
26
src/App.tsx
@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import Header from "./components/Header";
|
||||
import styled from "styled-components";
|
||||
import SideDrawer from "./components/SideDrawer";
|
||||
@ -6,13 +6,14 @@ import { Switch, Route } from "react-router-dom";
|
||||
import Login from "./components/Login";
|
||||
import CreateTask from "./components/CreateTask";
|
||||
import TodoList from "./components/TodoList";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
const StyledApp = styled.div`
|
||||
height: 100vh;
|
||||
background-color: #eee;
|
||||
`;
|
||||
|
||||
function App() {
|
||||
const App = (props: any)=> {
|
||||
const [sideDrawer, setSiderDrawer] = useState<boolean>(false);
|
||||
|
||||
const toggleSideDrawerHandler = () => {
|
||||
@ -23,6 +24,10 @@ function App() {
|
||||
setSiderDrawer(false);
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
props.error !== null && alert(props.error);
|
||||
}, [props.error])
|
||||
|
||||
return (
|
||||
<StyledApp>
|
||||
<Header sideDrawer={toggleSideDrawerHandler} isOpen={sideDrawer} />
|
||||
@ -60,4 +65,19 @@ function App() {
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
interface RootState {
|
||||
isAuth: boolean;
|
||||
todos: [];
|
||||
userId: boolean;
|
||||
idToken: string;
|
||||
isLoading: boolean;
|
||||
error:string;
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: RootState) => {
|
||||
return {
|
||||
error: state.error,
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, null)(App);
|
||||
|
@ -4,7 +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';
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const StyledTasks = styled.div`
|
||||
width: 100%;
|
||||
@ -33,13 +33,13 @@ 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 currDate = dayjs(new Date()).format("YYYY-MM-DD");
|
||||
|
||||
const addTaskHandler = () => {
|
||||
const isValid = formValidator();
|
||||
if (isValid) {
|
||||
props.isAuth
|
||||
? props.addToDo(
|
||||
if (props.isAuth) {
|
||||
props.addToDo(
|
||||
taskName,
|
||||
taskDesc,
|
||||
taskType,
|
||||
@ -47,9 +47,20 @@ const CreateTask = (props: any) => {
|
||||
date,
|
||||
props.idToken,
|
||||
props.userId
|
||||
)
|
||||
: props.history.push("/login");
|
||||
);
|
||||
clearFormHandler();
|
||||
} else {
|
||||
props.history.push("/login");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const clearFormHandler = () => {
|
||||
setTaskName("");
|
||||
setTaskDesc("");
|
||||
setTaskType("bussiness");
|
||||
setIsImportant(false);
|
||||
setDate("");
|
||||
};
|
||||
|
||||
const radioButtonsHandler = (type: string) => {
|
||||
@ -61,8 +72,11 @@ const CreateTask = (props: any) => {
|
||||
};
|
||||
|
||||
const formValidator = () => {
|
||||
if (taskName.length > 1 && taskDesc.length > 1 && date.length > 1)
|
||||
if (taskName.length > 1 && taskDesc.length > 1 && date.length > 1) {
|
||||
return true;
|
||||
} else {
|
||||
alert("Fill in inputs!!!");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@ -160,7 +174,7 @@ const CreateTask = (props: any) => {
|
||||
interface RootState {
|
||||
isAuth: boolean;
|
||||
idToken: string;
|
||||
userId: string
|
||||
userId: string;
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: RootState) => {
|
||||
@ -180,8 +194,11 @@ const mapDispatchToProps = (dispatch: any) => {
|
||||
important: boolean,
|
||||
date: string,
|
||||
token: string,
|
||||
userId: string,
|
||||
) => dispatch(actions.addToDo(name, desc, type, important, date, token, userId)),
|
||||
userId: string
|
||||
) =>
|
||||
dispatch(
|
||||
actions.addToDo(name, desc, type, important, date, token, userId)
|
||||
),
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -3,8 +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";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
interface TODOtype {
|
||||
date: string;
|
||||
@ -14,6 +14,7 @@ interface TODOtype {
|
||||
taskType: string;
|
||||
hash: string;
|
||||
isFinished: boolean;
|
||||
isCanceled: boolean;
|
||||
}
|
||||
|
||||
const TodosStyled = styled.div`
|
||||
@ -21,7 +22,7 @@ const TodosStyled = styled.div`
|
||||
height: 92%;
|
||||
overflow: scroll;
|
||||
justify-content: center;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
.description {
|
||||
height: 100px;
|
||||
overflow: scroll;
|
||||
@ -34,23 +35,20 @@ const TodoList = (props: any) => {
|
||||
}, []);
|
||||
|
||||
const taskType = props.match.path.substring(1);
|
||||
console.log(taskType);
|
||||
|
||||
const finishTaskHandler = (hash: string, idToken: string) => {
|
||||
console.log("update");
|
||||
const finishTaskHandler = (hash: string, idToken: string) =>
|
||||
props.finishToDo(hash, idToken, props.todos);
|
||||
};
|
||||
|
||||
const deleteTaskHandler = (hash: string, idToken: string) => {
|
||||
console.log("delete");
|
||||
const deleteTaskHandler = (hash: string, idToken: string) =>
|
||||
props.deleteToDo(hash, idToken, props.todos);
|
||||
};
|
||||
|
||||
const cancelTaskHandler = (hash: string, idToken: string) =>
|
||||
props.cancelToDo(hash, idToken, props.todos);
|
||||
|
||||
let cards = [];
|
||||
if (props.isLoading === false && props.isAuth === true) {
|
||||
cards = props.todos.map((todo: TODOtype) => {
|
||||
console.log(todo);
|
||||
if (todo.isFinished === true && taskType === "finished") {
|
||||
if (taskType === "finished" && todo.isFinished === true) {
|
||||
return (
|
||||
<div
|
||||
className="card bg-light"
|
||||
@ -79,12 +77,12 @@ const TodoList = (props: any) => {
|
||||
className="btn btn-danger"
|
||||
onClick={() => deleteTaskHandler(todo.hash, props.idToken)}
|
||||
>
|
||||
Delete <i className="fas fa-minus-circle"></i>
|
||||
Delete <i className="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else if (taskType === "all" && todo.isFinished === false ) {
|
||||
} else if (taskType === "all" && todo.isFinished === false) {
|
||||
return (
|
||||
<div
|
||||
className="card bg-light"
|
||||
@ -122,8 +120,17 @@ const TodoList = (props: any) => {
|
||||
className="btn btn-danger"
|
||||
onClick={() => deleteTaskHandler(todo.hash, props.idToken)}
|
||||
>
|
||||
Delete <i className="fas fa-minus-circle"></i>
|
||||
Delete <i className="fas fa-trash"></i>
|
||||
</button>
|
||||
{!todo.isCanceled && (
|
||||
<button
|
||||
onClick={() => cancelTaskHandler(todo.hash, props.idToken)}
|
||||
type="button"
|
||||
className="btn btn-warning"
|
||||
>
|
||||
Cancel <i className="fas fa-minus-circle"></i>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -163,8 +170,17 @@ const TodoList = (props: any) => {
|
||||
className="btn btn-danger"
|
||||
onClick={() => deleteTaskHandler(todo.hash, props.idToken)}
|
||||
>
|
||||
Delete <i className="fas fa-minus-circle"></i>
|
||||
Delete <i className="fas fa-trash"></i>
|
||||
</button>
|
||||
{!todo.isCanceled && (
|
||||
<button
|
||||
onClick={() => cancelTaskHandler(todo.hash, props.idToken)}
|
||||
type="button"
|
||||
className="btn btn-warning"
|
||||
>
|
||||
Cancel <i className="fas fa-minus-circle"></i>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -208,7 +224,105 @@ const TodoList = (props: any) => {
|
||||
className="btn btn-danger"
|
||||
onClick={() => deleteTaskHandler(todo.hash, props.idToken)}
|
||||
>
|
||||
Delete <i className="fas fa-minus-circle"></i>
|
||||
Delete <i className="fas fa-trash"></i>
|
||||
</button>
|
||||
{!todo.isCanceled && (
|
||||
<button
|
||||
onClick={() => cancelTaskHandler(todo.hash, props.idToken)}
|
||||
type="button"
|
||||
className="btn btn-warning"
|
||||
>
|
||||
Cancel <i className="fas fa-minus-circle"></i>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else if (
|
||||
todo.isFinished === false &&
|
||||
(dayjs(new Date()).diff(todo.date) < 0 ||
|
||||
dayjs(new Date()).format("YYYY-MM-DD") === todo.date) &&
|
||||
taskType === "current"
|
||||
) {
|
||||
return (
|
||||
<div
|
||||
className="card bg-light"
|
||||
style={{ 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-trash"></i>
|
||||
</button>
|
||||
{!todo.isCanceled && (
|
||||
<button
|
||||
onClick={() => cancelTaskHandler(todo.hash, props.idToken)}
|
||||
type="button"
|
||||
className="btn btn-warning"
|
||||
>
|
||||
Cancel <i className="fas fa-minus-circle"></i>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else if (todo.isCanceled === true && taskType === "Canceled") {
|
||||
return (
|
||||
<div
|
||||
className="card bg-light"
|
||||
style={{ 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-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -252,6 +366,8 @@ const mapDispatchToProps = (dispatch: any) => {
|
||||
dispatch(actions.finishToDo(hash, idToken, todoList)),
|
||||
deleteToDo: (hash: string, idToken: string, todoList: []) =>
|
||||
dispatch(actions.deleteToDo(hash, idToken, todoList)),
|
||||
cancelToDo: (hash: string, idToken: string, todoList: []) =>
|
||||
dispatch(actions.cancelToDo(hash, idToken, todoList)),
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -12,3 +12,5 @@ export const UPDATE_SUCCESS = 'UPDATE_SUCCESS';
|
||||
export const UPDATE_FAIL = 'UPDATE_FAIL';
|
||||
export const DELETE_SUCCESS = 'DELETE_SUCCESS';
|
||||
export const DELETE_FAIL = 'DELETE_FAIL';
|
||||
export const CANCEL_SUCCESS = 'CANCEL_SUCCESS';
|
||||
export const CANCEL_FAIL = 'CANCEL_FAIL';
|
@ -14,6 +14,7 @@ type ToDos = {
|
||||
type: string;
|
||||
userId: string;
|
||||
hash: string;
|
||||
isCanceled: boolean;
|
||||
};
|
||||
|
||||
export const loadToDos = (userId: string, token: string) => {
|
||||
@ -36,6 +37,7 @@ export const loadToDos = (userId: string, token: string) => {
|
||||
date: data[key].date,
|
||||
userId: data[key].userId,
|
||||
isFinished: data[key].isFinished,
|
||||
isCanceled: data[key].isCanceled,
|
||||
});
|
||||
}
|
||||
dispatch({
|
||||
@ -118,6 +120,7 @@ export const addToDo = (
|
||||
date: date,
|
||||
userId: userId,
|
||||
isFinished: false,
|
||||
isCanceled: false
|
||||
};
|
||||
|
||||
let url = `https://to-do-studia.firebaseio.com/todos.json?auth=${token}`;
|
||||
@ -221,3 +224,48 @@ export const deleteToDo = (
|
||||
})
|
||||
};
|
||||
};
|
||||
|
||||
export const cancelToDo = (
|
||||
hash: string,
|
||||
token: string,
|
||||
todoList: Array<ToDos>
|
||||
) => {
|
||||
return (dispatch: any) => {
|
||||
const data = {
|
||||
isCanceled: true,
|
||||
};
|
||||
|
||||
const newArr = todoList.filter(todo => {
|
||||
if(hash === todo.hash){
|
||||
todo.isCanceled = 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.CANCEL_SUCCESS,
|
||||
todos: newArr
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch({
|
||||
type: actionType.CANCEL_FAIL,
|
||||
error: err,
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
@ -1 +1,9 @@
|
||||
export {loadToDos, addToDo, auth, authLogout, finishToDo, deleteToDo} from './actions';
|
||||
export {
|
||||
loadToDos,
|
||||
addToDo,
|
||||
auth,
|
||||
authLogout,
|
||||
finishToDo,
|
||||
deleteToDo,
|
||||
cancelToDo,
|
||||
} from "./actions";
|
||||
|
@ -88,6 +88,16 @@ const reducer = (state = initialState, action: ActionType) => {
|
||||
...state,
|
||||
error: action.error,
|
||||
};
|
||||
case actionType.CANCEL_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
todos: action.todos,
|
||||
};
|
||||
case actionType.CANCEL_FAIL:
|
||||
return {
|
||||
...state,
|
||||
error: action.error,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user