Skip to content

Commit

Permalink
add task solution
Browse files Browse the repository at this point in the history
  • Loading branch information
P-Nazar committed Sep 7, 2024
1 parent 474ae79 commit 14dcb7b
Show file tree
Hide file tree
Showing 11 changed files with 1,543 additions and 2,114 deletions.
3,057 changes: 1,206 additions & 1,851 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
},
"devDependencies": {
"@cypress/react18": "^2.0.1",
"@mate-academy/scripts": "^1.8.5",
"@mate-academy/scripts": "^1.9.12",
"@mate-academy/students-ts-config": "*",
"@mate-academy/stylelint-config": "*",
"@types/node": "^20.14.10",
Expand Down
74 changes: 57 additions & 17 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,66 @@
import 'bulma/css/bulma.css';
import '@fortawesome/fontawesome-free/css/all.css';
import { Loader, TodoFilter, TodoList, TodoModal } from './components';
import { useEffect, useState } from 'react';
import { getTodos, getUser } from './api';
import { useDispatch } from 'react-redux';
import { setTodos } from './features/todos';
import { Todo } from './types/Todo';
import { saveTodo } from './features/currentTodo';

export const App = () => (
<>
<div className="section">
<div className="container">
<div className="box">
<h1 className="title">Todos:</h1>
export const App = () => {
const dispatch = useDispatch();
const [isLoading, setIsLoading] = useState(false);
const [isOpenerMOdal, setIsOpenerMOdal] = useState(false);

<div className="block">
<TodoFilter />
</div>
useEffect(() => {
setIsLoading(true);
getTodos()
.then(todos => {
dispatch(setTodos(todos));
})
.finally(() => {
setIsLoading(false);
});
}, []);

const openerModalWindow = async (userId: number, todo: Todo) => {
setIsOpenerMOdal(true);

const user = await getUser(userId);

dispatch(
saveTodo({
...todo,
user,
}),
);

setTimeout(() => {
setIsOpenerMOdal(false);
}, 300);
};

<div className="block">
<Loader />
<TodoList />
return (
<>
<div className="section">
<div className="container">
<div className="box">
<h1 className="title">Todos:</h1>

<div className="block">
<TodoFilter />
</div>

<div className="block">
{isLoading && <Loader />}

{!isLoading && <TodoList openerModalWindow={openerModalWindow} />}
</div>
</div>
</div>
</div>
</div>

<TodoModal />
</>
);
<TodoModal isOpenerMOdal={isOpenerMOdal} />
</>
);
};
15 changes: 13 additions & 2 deletions src/app/store.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import { combineSlices, configureStore } from '@reduxjs/toolkit';
import filterReducer, { FilterStateSlice } from '../features/filter';
import todosReducer, { TodosState } from '../features/todos';
import currentTodoReducer, { CurrentTodoState } from '../features/currentTodo';

const rootReducer = combineSlices();
const rootReducer = combineSlices({
filterSlice: filterReducer,
todosSlice: todosReducer,
currentTodoSlice: currentTodoReducer,
});

export const store = configureStore({
reducer: rootReducer,
});

export type RootState = ReturnType<typeof rootReducer>;
export type RootState = {
filterSlice: FilterStateSlice;
todosSlice: TodosState;
currentTodoSlice: CurrentTodoState;
};
export type AppDispatch = typeof store.dispatch;
53 changes: 43 additions & 10 deletions src/components/TodoFilter/TodoFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,42 @@
import React from 'react';
import React, { ChangeEvent } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { clearQuery, setQuery, setStatus } from '../../features/filter';
import { RootState } from '../../app/store';
import { Status } from '../../types/Status';

export const TodoFilter: React.FC = () => {
const dispatch = useDispatch();
const status = useSelector<RootState, Status>(
state => state.filterSlice.status,
);
const query = useSelector<RootState, string>(
state => state.filterSlice.query,
);

const handlerSelectChange = (e: ChangeEvent<HTMLSelectElement>) => {
dispatch(setStatus(e.target.value as Status));
};

const handlerInputChange = (e: ChangeEvent<HTMLInputElement>) => {
dispatch(setQuery(e.target.value as Status));
};

const clearInputChange = () => {
dispatch(clearQuery());
};

return (
<form
className="field has-addons"
onSubmit={event => event.preventDefault()}
>
<p className="control">
<span className="select">
<select data-cy="statusSelect">
<select
data-cy="statusSelect"
value={status}
onChange={handlerSelectChange}
>
<option value="all">All</option>
<option value="active">Active</option>
<option value="completed">Completed</option>
Expand All @@ -22,19 +50,24 @@ export const TodoFilter: React.FC = () => {
type="text"
className="input"
placeholder="Search..."
value={query}
onChange={handlerInputChange}
/>
<span className="icon is-left">
<i className="fas fa-magnifying-glass" />
</span>

<span className="icon is-right" style={{ pointerEvents: 'all' }}>
{/* eslint-disable-next-line jsx-a11y/control-has-associated-label */}
<button
data-cy="clearSearchButton"
type="button"
className="delete"
/>
</span>
{query.length > 0 && (
<span className="icon is-right" style={{ pointerEvents: 'all' }}>
{/* eslint-disable-next-line jsx-a11y/control-has-associated-label */}
<button
data-cy="clearSearchButton"
type="button"
className="delete"
onClick={clearInputChange}
/>
</span>
)}
</p>
</form>
);
Expand Down
Loading

0 comments on commit 14dcb7b

Please sign in to comment.