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 Header from "./components/Header";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import SideDrawer from "./components/SideDrawer";
|
import SideDrawer from "./components/SideDrawer";
|
||||||
@ -6,13 +6,14 @@ import { Switch, Route } from "react-router-dom";
|
|||||||
import Login from "./components/Login";
|
import Login from "./components/Login";
|
||||||
import CreateTask from "./components/CreateTask";
|
import CreateTask from "./components/CreateTask";
|
||||||
import TodoList from "./components/TodoList";
|
import TodoList from "./components/TodoList";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
|
||||||
const StyledApp = styled.div`
|
const StyledApp = styled.div`
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
function App() {
|
const App = (props: any)=> {
|
||||||
const [sideDrawer, setSiderDrawer] = useState<boolean>(false);
|
const [sideDrawer, setSiderDrawer] = useState<boolean>(false);
|
||||||
|
|
||||||
const toggleSideDrawerHandler = () => {
|
const toggleSideDrawerHandler = () => {
|
||||||
@ -23,6 +24,10 @@ function App() {
|
|||||||
setSiderDrawer(false);
|
setSiderDrawer(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
props.error !== null && alert(props.error);
|
||||||
|
}, [props.error])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledApp>
|
<StyledApp>
|
||||||
<Header sideDrawer={toggleSideDrawerHandler} isOpen={sideDrawer} />
|
<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 { connect } from "react-redux";
|
||||||
import * as actions from "../store/actions/actions";
|
import * as actions from "../store/actions/actions";
|
||||||
import { withRouter } from "react-router-dom";
|
import { withRouter } from "react-router-dom";
|
||||||
import dayjs from'dayjs';
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
const StyledTasks = styled.div`
|
const StyledTasks = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -33,25 +33,36 @@ const CreateTask = (props: any) => {
|
|||||||
const [isImportant, setIsImportant] = useState<boolean>(false);
|
const [isImportant, setIsImportant] = useState<boolean>(false);
|
||||||
const [date, setDate] = useState<string>("");
|
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 addTaskHandler = () => {
|
||||||
const isValid = formValidator();
|
const isValid = formValidator();
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
props.isAuth
|
if (props.isAuth) {
|
||||||
? props.addToDo(
|
props.addToDo(
|
||||||
taskName,
|
taskName,
|
||||||
taskDesc,
|
taskDesc,
|
||||||
taskType,
|
taskType,
|
||||||
isImportant,
|
isImportant,
|
||||||
date,
|
date,
|
||||||
props.idToken,
|
props.idToken,
|
||||||
props.userId
|
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) => {
|
const radioButtonsHandler = (type: string) => {
|
||||||
setTaskType(type);
|
setTaskType(type);
|
||||||
};
|
};
|
||||||
@ -61,8 +72,11 @@ const CreateTask = (props: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const formValidator = () => {
|
const formValidator = () => {
|
||||||
if (taskName.length > 1 && taskDesc.length > 1 && date.length > 1)
|
if (taskName.length > 1 && taskDesc.length > 1 && date.length > 1) {
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
alert("Fill in inputs!!!");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -160,7 +174,7 @@ const CreateTask = (props: any) => {
|
|||||||
interface RootState {
|
interface RootState {
|
||||||
isAuth: boolean;
|
isAuth: boolean;
|
||||||
idToken: string;
|
idToken: string;
|
||||||
userId: string
|
userId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: RootState) => {
|
const mapStateToProps = (state: RootState) => {
|
||||||
@ -180,8 +194,11 @@ const mapDispatchToProps = (dispatch: any) => {
|
|||||||
important: boolean,
|
important: boolean,
|
||||||
date: string,
|
date: string,
|
||||||
token: string,
|
token: string,
|
||||||
userId: string,
|
userId: string
|
||||||
) => dispatch(actions.addToDo(name, desc, type, important, date, token, userId)),
|
) =>
|
||||||
|
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 "../../node_modules/bootstrap/dist/css/bootstrap.min.css";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import sadFace from "../assets/images/sadFace.png";
|
|
||||||
import { withRouter } from "react-router-dom";
|
import { withRouter } from "react-router-dom";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
interface TODOtype {
|
interface TODOtype {
|
||||||
date: string;
|
date: string;
|
||||||
@ -14,6 +14,7 @@ interface TODOtype {
|
|||||||
taskType: string;
|
taskType: string;
|
||||||
hash: string;
|
hash: string;
|
||||||
isFinished: boolean;
|
isFinished: boolean;
|
||||||
|
isCanceled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TodosStyled = styled.div`
|
const TodosStyled = styled.div`
|
||||||
@ -21,7 +22,7 @@ const TodosStyled = styled.div`
|
|||||||
height: 92%;
|
height: 92%;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||||
.description {
|
.description {
|
||||||
height: 100px;
|
height: 100px;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
@ -34,23 +35,20 @@ const TodoList = (props: any) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const taskType = props.match.path.substring(1);
|
const taskType = props.match.path.substring(1);
|
||||||
console.log(taskType);
|
|
||||||
|
|
||||||
const finishTaskHandler = (hash: string, idToken: string) => {
|
const finishTaskHandler = (hash: string, idToken: string) =>
|
||||||
console.log("update");
|
|
||||||
props.finishToDo(hash, idToken, props.todos);
|
props.finishToDo(hash, idToken, props.todos);
|
||||||
};
|
|
||||||
|
|
||||||
const deleteTaskHandler = (hash: string, idToken: string) => {
|
const deleteTaskHandler = (hash: string, idToken: string) =>
|
||||||
console.log("delete");
|
|
||||||
props.deleteToDo(hash, idToken, props.todos);
|
props.deleteToDo(hash, idToken, props.todos);
|
||||||
};
|
|
||||||
|
const cancelTaskHandler = (hash: string, idToken: string) =>
|
||||||
|
props.cancelToDo(hash, idToken, props.todos);
|
||||||
|
|
||||||
let cards = [];
|
let cards = [];
|
||||||
if (props.isLoading === false && props.isAuth === true) {
|
if (props.isLoading === false && props.isAuth === true) {
|
||||||
cards = props.todos.map((todo: TODOtype) => {
|
cards = props.todos.map((todo: TODOtype) => {
|
||||||
console.log(todo);
|
if (taskType === "finished" && todo.isFinished === true) {
|
||||||
if (todo.isFinished === true && taskType === "finished") {
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="card bg-light"
|
className="card bg-light"
|
||||||
@ -79,12 +77,12 @@ const TodoList = (props: any) => {
|
|||||||
className="btn btn-danger"
|
className="btn btn-danger"
|
||||||
onClick={() => deleteTaskHandler(todo.hash, props.idToken)}
|
onClick={() => deleteTaskHandler(todo.hash, props.idToken)}
|
||||||
>
|
>
|
||||||
Delete <i className="fas fa-minus-circle"></i>
|
Delete <i className="fas fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (taskType === "all" && todo.isFinished === false ) {
|
} else if (taskType === "all" && todo.isFinished === false) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="card bg-light"
|
className="card bg-light"
|
||||||
@ -122,8 +120,17 @@ const TodoList = (props: any) => {
|
|||||||
className="btn btn-danger"
|
className="btn btn-danger"
|
||||||
onClick={() => deleteTaskHandler(todo.hash, props.idToken)}
|
onClick={() => deleteTaskHandler(todo.hash, props.idToken)}
|
||||||
>
|
>
|
||||||
Delete <i className="fas fa-minus-circle"></i>
|
Delete <i className="fas fa-trash"></i>
|
||||||
</button>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -163,8 +170,17 @@ const TodoList = (props: any) => {
|
|||||||
className="btn btn-danger"
|
className="btn btn-danger"
|
||||||
onClick={() => deleteTaskHandler(todo.hash, props.idToken)}
|
onClick={() => deleteTaskHandler(todo.hash, props.idToken)}
|
||||||
>
|
>
|
||||||
Delete <i className="fas fa-minus-circle"></i>
|
Delete <i className="fas fa-trash"></i>
|
||||||
</button>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -208,7 +224,105 @@ const TodoList = (props: any) => {
|
|||||||
className="btn btn-danger"
|
className="btn btn-danger"
|
||||||
onClick={() => deleteTaskHandler(todo.hash, props.idToken)}
|
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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -252,6 +366,8 @@ const mapDispatchToProps = (dispatch: any) => {
|
|||||||
dispatch(actions.finishToDo(hash, idToken, todoList)),
|
dispatch(actions.finishToDo(hash, idToken, todoList)),
|
||||||
deleteToDo: (hash: string, idToken: string, todoList: []) =>
|
deleteToDo: (hash: string, idToken: string, todoList: []) =>
|
||||||
dispatch(actions.deleteToDo(hash, idToken, todoList)),
|
dispatch(actions.deleteToDo(hash, idToken, todoList)),
|
||||||
|
cancelToDo: (hash: string, idToken: string, todoList: []) =>
|
||||||
|
dispatch(actions.cancelToDo(hash, idToken, todoList)),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,4 +11,6 @@ export const LOAD_SUCCESS = 'LOAD_SUCCESS';
|
|||||||
export const UPDATE_SUCCESS = 'UPDATE_SUCCESS';
|
export const UPDATE_SUCCESS = 'UPDATE_SUCCESS';
|
||||||
export const UPDATE_FAIL = 'UPDATE_FAIL';
|
export const UPDATE_FAIL = 'UPDATE_FAIL';
|
||||||
export const DELETE_SUCCESS = 'DELETE_SUCCESS';
|
export const DELETE_SUCCESS = 'DELETE_SUCCESS';
|
||||||
export const DELETE_FAIL = 'DELETE_FAIL';
|
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;
|
type: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
hash: string;
|
hash: string;
|
||||||
|
isCanceled: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const loadToDos = (userId: string, token: string) => {
|
export const loadToDos = (userId: string, token: string) => {
|
||||||
@ -36,6 +37,7 @@ export const loadToDos = (userId: string, token: string) => {
|
|||||||
date: data[key].date,
|
date: data[key].date,
|
||||||
userId: data[key].userId,
|
userId: data[key].userId,
|
||||||
isFinished: data[key].isFinished,
|
isFinished: data[key].isFinished,
|
||||||
|
isCanceled: data[key].isCanceled,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
@ -118,6 +120,7 @@ export const addToDo = (
|
|||||||
date: date,
|
date: date,
|
||||||
userId: userId,
|
userId: userId,
|
||||||
isFinished: false,
|
isFinished: false,
|
||||||
|
isCanceled: false
|
||||||
};
|
};
|
||||||
|
|
||||||
let url = `https://to-do-studia.firebaseio.com/todos.json?auth=${token}`;
|
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,
|
...state,
|
||||||
error: action.error,
|
error: action.error,
|
||||||
};
|
};
|
||||||
|
case actionType.CANCEL_SUCCESS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
todos: action.todos,
|
||||||
|
};
|
||||||
|
case actionType.CANCEL_FAIL:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
error: action.error,
|
||||||
|
};
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user