├── src ├── components │ ├── AccountSection │ │ ├── HookState.tsx │ │ ├── DeleteTasks.tsx │ │ ├── DarkMode.tsx │ │ ├── TasksDone.tsx │ │ ├── MobileAccountData.tsx │ │ └── AccountData.tsx │ ├── Routes │ │ ├── Home.tsx │ │ ├── TodaysTasks.tsx │ │ ├── DoneTasks.tsx │ │ ├── ImportantTasks.tsx │ │ ├── SearchResults.tsx │ │ ├── TaskOnly.tsx │ │ └── Directory.tsx │ ├── hooks │ │ ├── useDate.tsx │ │ ├── useDescriptionTitle.tsx │ │ ├── useBackDrop.tsx │ │ ├── useCompletedTasks.tsx │ │ ├── useSearchQuery.tsx │ │ ├── useTodayTasks.tsx │ │ ├── useVisibility.tsx │ │ ├── useScreenMedia.tsx │ │ └── useSortTasks.tsx │ ├── Utilities │ │ ├── BtnAddTask.tsx │ │ ├── ModalConfirm.tsx │ │ ├── LayoutMenus.tsx │ │ ├── Modal.tsx │ │ ├── ModalDirectory.tsx │ │ ├── LayoutRoutes.tsx │ │ └── ModalTask.tsx │ ├── TasksSection │ │ ├── TaskItem │ │ │ ├── BtnMarkAsImportant.tsx │ │ │ ├── ActionsTaskItem.tsx │ │ │ ├── BtnDeleteTask.tsx │ │ │ ├── InfosTask.tsx │ │ │ ├── TaskItem.tsx │ │ │ ├── BtnEditTask.tsx │ │ │ └── BtnToggleCompleted.tsx │ │ ├── TasksSection.tsx │ │ ├── ButtonsSort.tsx │ │ ├── Notification.tsx │ │ ├── SearchField.tsx │ │ └── HeaderTasks.tsx │ ├── Menu │ │ ├── Directories │ │ │ ├── Directories.tsx │ │ │ ├── ContentDirectories.tsx │ │ │ └── ItemDirectory.tsx │ │ ├── NavLinks.tsx │ │ └── Menu.tsx │ ├── Service │ │ └── condition.js │ └── Footer.tsx ├── assets │ ├── 15puzzle.jpg │ ├── Font │ │ ├── Sans_a4fran3.eot │ │ ├── Sans_a4fran3.ttf │ │ └── Sans_a4fran3.woff │ ├── x.svg │ ├── check.svg │ ├── menu.svg │ ├── search.svg │ ├── arrow.svg │ ├── bell.svg │ ├── edit.svg │ ├── view-1.svg │ ├── options.svg │ ├── sort-alfa-down.svg │ ├── star-line.svg │ ├── user.svg │ ├── view-2.svg │ ├── trash.svg │ ├── date.svg │ ├── sort-number-down.svg │ ├── 2048.svg │ ├── gameboy.svg │ ├── Social.svg │ └── tic-tac-toe.svg ├── interfaces.tsx ├── Weather │ ├── button │ │ ├── Button.jsx │ │ └── button.scss │ ├── WeatherBlock.tsx │ ├── Api.tsx │ ├── AlertBlock.tsx │ ├── modal │ │ ├── Modal.jsx │ │ └── modal.scss │ ├── Weather.css │ └── WeatherApp.tsx ├── game │ ├── TicTacToe │ │ ├── Board │ │ │ ├── Board.css │ │ │ └── Board.jsx │ │ ├── Game │ │ │ ├── Game.css │ │ │ └── Game.jsx │ │ ├── Square │ │ │ ├── Square.jsx │ │ │ └── Square.css │ │ └── Scores │ │ │ ├── Scores.css │ │ │ └── Scores.jsx │ └── Puzzle │ │ ├── components │ │ ├── Time.js │ │ ├── Moves.js │ │ ├── NewGameButton.js │ │ ├── Win.js │ │ ├── ChangeSize.js │ │ └── Game.js │ │ ├── App.css │ │ └── App.js ├── custom.d.ts ├── store │ ├── hooks.tsx │ ├── Modal.store.tsx │ ├── index.tsx │ ├── Menu.store.tsx │ └── Tasks.store.tsx ├── index.tsx ├── App.tsx └── index.css ├── public ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json └── index.html ├── postcss.config.js ├── tailwind.config.js ├── tsconfig.json ├── LICENSE ├── README.md └── package.json /src/components/AccountSection/HookState.tsx: -------------------------------------------------------------------------------- 1 | export let GameHooks = {} as any -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ariyan-emi/ToDo/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ariyan-emi/ToDo/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ariyan-emi/ToDo/HEAD/public/logo512.png -------------------------------------------------------------------------------- /src/assets/15puzzle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ariyan-emi/ToDo/HEAD/src/assets/15puzzle.jpg -------------------------------------------------------------------------------- /src/assets/Font/Sans_a4fran3.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ariyan-emi/ToDo/HEAD/src/assets/Font/Sans_a4fran3.eot -------------------------------------------------------------------------------- /src/assets/Font/Sans_a4fran3.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ariyan-emi/ToDo/HEAD/src/assets/Font/Sans_a4fran3.ttf -------------------------------------------------------------------------------- /src/assets/Font/Sans_a4fran3.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ariyan-emi/ToDo/HEAD/src/assets/Font/Sans_a4fran3.woff -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src/interfaces.tsx: -------------------------------------------------------------------------------- 1 | export interface Task { 2 | title: string; 3 | dir: string; 4 | description: string; 5 | date: string; 6 | completed: boolean; 7 | important: boolean; 8 | id: string; 9 | } 10 | -------------------------------------------------------------------------------- /src/Weather/button/Button.jsx: -------------------------------------------------------------------------------- 1 | import './button.scss'; 2 | 3 | const Button = props => { 4 | return ; 7 | }; 8 | 9 | export default Button; 10 | -------------------------------------------------------------------------------- /src/assets/x.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/check.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Weather/button/button.scss: -------------------------------------------------------------------------------- 1 | button { 2 | border: 0; 3 | outline: 0; 4 | padding: 0.5rem 1.5rem; 5 | font-weight: 600; 6 | color: #fff; 7 | background-color: #625eb9; 8 | border-radius: 5px; 9 | cursor: pointer; 10 | } -------------------------------------------------------------------------------- /src/assets/menu.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/game/TicTacToe/Board/Board.css: -------------------------------------------------------------------------------- 1 | .board { 2 | max-width: 452px; 3 | max-height: 452px; 4 | display: flex; 5 | flex-wrap: wrap; 6 | margin-top: 5px; 7 | } 8 | 9 | @media (max-width: 700px) { 10 | .board { 11 | max-width: 302px; 12 | max-height: 302px; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/assets/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/custom.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.svg" { 2 | import React = require("react"); 3 | export const ReactComponent: React.FC>; 4 | const src: string; 5 | export default src; 6 | } 7 | 8 | 9 | declare module "*.jpg" { 10 | const value: any; 11 | export = value; 12 | } 13 | -------------------------------------------------------------------------------- /src/game/Puzzle/components/Time.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | export default class Time extends Component { 4 | render() { 5 | return ( 6 |
7 | Time
{this.props.time} 8 |
9 | ) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/game/Puzzle/components/Moves.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | export default class Moves extends Component { 4 | render() { 5 | return ( 6 |
7 | Moves
{this.props.moves} 8 |
9 | ) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/store/hooks.tsx: -------------------------------------------------------------------------------- 1 | import { useDispatch, useSelector, TypedUseSelectorHook } from "react-redux"; 2 | // @ts-ignore 3 | import type { RootState, AppDispatch } from "./index.tsx"; 4 | 5 | export const useAppDispatch: () => AppDispatch = useDispatch; 6 | export const useAppSelector: TypedUseSelectorHook = useSelector; 7 | -------------------------------------------------------------------------------- /src/game/Puzzle/components/NewGameButton.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | export default class NewGameButton extends Component { 4 | render() { 5 | return ( 6 |
7 | New
Game 8 |
9 | ) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/game/TicTacToe/Game/Game.css: -------------------------------------------------------------------------------- 1 | .GameTic{ 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: center; 5 | align-items: center; 6 | text-align: center; 7 | position: relative; 8 | 9 | } 10 | @media only screen and (max-width: 700px) { 11 | .GameTic{ 12 | transform: translate(0%, 25%); 13 | } 14 | } -------------------------------------------------------------------------------- /src/game/TicTacToe/Square/Square.jsx: -------------------------------------------------------------------------------- 1 | import "./Square.css"; 2 | 3 | function Square({ id, value, handleClick, board }) { 4 | return ( 5 |
handleClick(id)} className="square"> 6 |

9 | {value} 10 |

11 |
12 | ); 13 | } 14 | 15 | export default Square; 16 | -------------------------------------------------------------------------------- /src/assets/arrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./src/**/*.{js,jsx,ts,tsx}"], 4 | theme: { 5 | extend: { 6 | colors: { 7 | slate: { 8 | 800: "#141E33", 9 | }, 10 | }, 11 | screens: { 12 | "2xl": "1736px", 13 | }, 14 | }, 15 | }, 16 | plugins: [require("@tailwindcss/line-clamp")], 17 | darkMode: "class", 18 | }; 19 | -------------------------------------------------------------------------------- /src/assets/bell.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/edit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/view-1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/game/TicTacToe/Scores/Scores.css: -------------------------------------------------------------------------------- 1 | .scores { 2 | display: flex; 3 | flex-direction: row; 4 | color: black; 5 | font-size: 26px; 6 | justify-content: center; 7 | margin-top: 26px; 8 | font-weight: 100; 9 | } 10 | .scores div { 11 | width: 150px; 12 | text-align: center; 13 | line-height: 35px; 14 | } 15 | 16 | @media (max-width: 700px) { 17 | .scores { 18 | font-size: 22px; 19 | } 20 | .scores div { 21 | width: 100px; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/assets/options.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/game/TicTacToe/Game/Game.jsx: -------------------------------------------------------------------------------- 1 | import "./Game.css"; 2 | import { useState } from "react"; 3 | import Board from "../Board/Board"; 4 | import Scores from "../Scores/Scores"; 5 | 6 | function GameTicTac() { 7 | 8 | const [scores, setScores] = useState({ 9 | x: 0, 10 | o: 0, 11 | tie: 0, 12 | }); 13 | 14 | return ( 15 |
16 | 17 | 18 |
19 | ); 20 | } 21 | 22 | export default GameTicTac; 23 | -------------------------------------------------------------------------------- /src/components/Routes/Home.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import LayoutRoutes from "../Utilities/LayoutRoutes"; 3 | import { useAppSelector } from "../../store/hooks"; 4 | import useDescriptionTitle from "../hooks/useDescriptionTitle"; 5 | 6 | const Home: React.FC = () => { 7 | const tasks = useAppSelector((state) => state.tasks.tasks); 8 | 9 | useDescriptionTitle("Organize your tasks", "All tasks"); 10 | return ; 11 | }; 12 | 13 | export default Home; 14 | -------------------------------------------------------------------------------- /src/components/hooks/useDate.tsx: -------------------------------------------------------------------------------- 1 | const useDate = (date: string): string => { 2 | const fullDate: Date = new Date(date.replaceAll("-", "/")); 3 | const year: number = fullDate.getFullYear(); 4 | const month: number = fullDate.getMonth() + 1; 5 | const day: number = fullDate.getDate(); 6 | 7 | const dateFormated: string = 8 | month.toString().padStart(2, "0") + 9 | "/" + 10 | day.toString().padStart(2, "0") + 11 | "/" + 12 | year; 13 | 14 | return dateFormated; 15 | }; 16 | 17 | export default useDate; 18 | -------------------------------------------------------------------------------- /src/components/hooks/useDescriptionTitle.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | 3 | const useDescriptionTitle = (description: string, title: string): void => { 4 | useEffect(() => { 5 | const metaDescription = document.querySelector('meta[name="description"]')!; 6 | metaDescription.setAttribute("content", description); 7 | 8 | const titleElement = document.querySelector("title")!; 9 | titleElement.innerText = "To-Do List | " + title; 10 | }, [description, title]); 11 | }; 12 | 13 | export default useDescriptionTitle; 14 | -------------------------------------------------------------------------------- /src/components/Routes/TodaysTasks.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import useDescriptionTitle from "../hooks/useDescriptionTitle"; 3 | import useTodayTasks from "../hooks/useTodayTasks"; 4 | import LayoutRoutes from "../Utilities/LayoutRoutes"; 5 | 6 | const TodaysTasks: React.FC = () => { 7 | const todaysTasks = useTodayTasks(); 8 | 9 | useDescriptionTitle("Today's tasks", "Today's tasks"); 10 | 11 | return ( 12 | 13 | ); 14 | }; 15 | 16 | export default TodaysTasks; 17 | -------------------------------------------------------------------------------- /src/assets/sort-alfa-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/store/Modal.store.tsx: -------------------------------------------------------------------------------- 1 | import { createSlice } from "@reduxjs/toolkit"; 2 | 3 | const initialState = { 4 | modalCreateTaskOpen: false, 5 | }; 6 | 7 | const modalSlice = createSlice({ 8 | name: "modal", 9 | initialState: initialState, 10 | reducers: { 11 | openModalCreateTask(state) { 12 | state.modalCreateTaskOpen = true; 13 | }, 14 | closeModalCreateTask(state) { 15 | state.modalCreateTaskOpen = false; 16 | }, 17 | }, 18 | }); 19 | 20 | export const modalActions = modalSlice.actions; 21 | export default modalSlice.reducer; 22 | -------------------------------------------------------------------------------- /src/assets/star-line.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/game/TicTacToe/Scores/Scores.jsx: -------------------------------------------------------------------------------- 1 | import "./Scores.css"; 2 | 3 | function Scores({ scores }) { 4 | return ( 5 |
6 |
7 | Player 8 |
9 | {scores.x} 10 |
11 |
12 | Tie 13 |
14 | {scores.tie} 15 |
16 |
17 | Computer 18 |
19 | {scores.o} 20 |
21 |
22 | ); 23 | } 24 | 25 | export default Scores; 26 | -------------------------------------------------------------------------------- /src/game/Puzzle/components/Win.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | export default class Win extends Component { 4 | winStyle = () => { 5 | return { display: this.props.win ? 'block' : 'none'} 6 | } 7 | render() { 8 | return ( 9 |
10 |
11 | You won!
12 | Time: {this.props.time}
13 | Moves: {this.props.moves} 14 |
15 |
16 | ) 17 | } 18 | } -------------------------------------------------------------------------------- /src/store/index.tsx: -------------------------------------------------------------------------------- 1 | import { configureStore } from "@reduxjs/toolkit"; 2 | import tasksReducer, { tasksMiddleware } from "./Tasks.store"; 3 | import modalReducer from "./Modal.store"; 4 | import menuReducer from "./Menu.store"; 5 | 6 | const store = configureStore({ 7 | reducer: { tasks: tasksReducer, modal: modalReducer, menu: menuReducer }, 8 | middleware: (getDefaultMiddleware: any) => 9 | getDefaultMiddleware().concat(tasksMiddleware), 10 | }); 11 | 12 | export type RootState = ReturnType; 13 | export type AddDispatch = typeof store.dispatch; 14 | export default store; 15 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "WebVaVe ToDo", 3 | "name": "WebVaVe ToDo", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "favicon.ico", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "favicon.ico", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/components/Utilities/BtnAddTask.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useAppDispatch } from "../../store/hooks"; 3 | import { modalActions } from "../../store/Modal.store"; 4 | const BtnAddTask: React.FC<{ className?: string }> = ({ className }) => { 5 | const dispatch = useAppDispatch(); 6 | 7 | const onOpenModal = () => { 8 | dispatch(modalActions.openModalCreateTask()); 9 | }; 10 | return ( 11 | <> 12 | 15 | 16 | ); 17 | }; 18 | 19 | export default BtnAddTask; 20 | -------------------------------------------------------------------------------- /src/assets/user.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src", "src/custom.d.ts", "src/components"] 20 | } 21 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import { Provider } from "react-redux"; 4 | import { BrowserRouter } from "react-router-dom"; 5 | import store from "./store/index"; 6 | import App from "./App"; 7 | import "./index.css"; 8 | const root = ReactDOM.createRoot( 9 | document.getElementById("root") as HTMLElement 10 | ); 11 | root.render( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ); 20 | -------------------------------------------------------------------------------- /src/assets/view-2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/game/Puzzle/components/ChangeSize.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | export default class ChangeSize extends Component { 4 | render() { 5 | return ( 6 |
7 |
this.props.onClick(3)}>3x3
8 |
this.props.onClick(4)}>4x4
9 |
this.props.onClick(5)}>5x5
10 |
this.props.onClick(6)}>6x6
11 |
12 | ) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/components/hooks/useBackDrop.tsx: -------------------------------------------------------------------------------- 1 | import MobileAccountData from "../AccountSection/MobileAccountData"; 2 | import {ReactComponent as X} from "../../assets/x.svg"; 3 | export function BackDrop({ BackState, BackSet }:{BackState:boolean,BackSet:any}){ 4 | return ( 5 | <> 6 |
7 | { 8 | BackState = false 9 | BackSet(false) 10 | }}/> 11 | 12 |
13 | 14 | ) 15 | 16 | } -------------------------------------------------------------------------------- /src/components/hooks/useCompletedTasks.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { Task } from "../../interfaces"; 3 | 4 | interface Props { 5 | tasks: Task[]; 6 | done: boolean; 7 | } 8 | 9 | const useCompletedTasks = (props: Props): { tasks: Task[] } => { 10 | const [tasks, setTasks] = useState([]); 11 | 12 | useEffect(() => { 13 | const filteredTasks: Task[] = props.tasks.filter((task: Task) => { 14 | if (props.done) { 15 | return task.completed; 16 | } else { 17 | return !task.completed; 18 | } 19 | }); 20 | setTasks(filteredTasks); 21 | }, [props.tasks, props.done]); 22 | 23 | return { tasks }; 24 | }; 25 | 26 | export default useCompletedTasks; 27 | -------------------------------------------------------------------------------- /src/assets/trash.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Weather/WeatherBlock.tsx: -------------------------------------------------------------------------------- 1 | import {AlertBlock} from "./AlertBlock"; 2 | import DangerousIcon from "@mui/icons-material/Dangerous"; 3 | import React, {useEffect, useState} from "react"; 4 | import { Condition, If } from "../components/Service/condition"; 5 | 6 | export default function WeatherBlock() { 7 | 8 | const AlertShow = localStorage.getItem('Alert') 9 | return ( 10 |
11 | 12 | 13 | 14 |
15 |

Can't Use This

16 |
17 |
18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/assets/date.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/Routes/DoneTasks.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useAppSelector } from "../../store/hooks"; 3 | import useCompletedTasks from "../hooks/useCompletedTasks"; 4 | import useDescriptionTitle from "../hooks/useDescriptionTitle"; 5 | import LayoutRoutes from "../Utilities/LayoutRoutes"; 6 | 7 | const DoneTasks: React.FC<{ done: boolean; title: string }> = ({ 8 | done, 9 | title, 10 | }) => { 11 | const tasks = useAppSelector((state) => state.tasks.tasks); 12 | 13 | const { tasks: tasksFiltered } = useCompletedTasks({ tasks, done }); 14 | 15 | useDescriptionTitle("All tasks done", title); 16 | 17 | return ; 18 | }; 19 | 20 | export default DoneTasks; 21 | -------------------------------------------------------------------------------- /src/store/Menu.store.tsx: -------------------------------------------------------------------------------- 1 | import { createSlice } from "@reduxjs/toolkit"; 2 | 3 | const initialState = { 4 | menuHeaderOpened: false, 5 | menuAccountOpened: false, 6 | }; 7 | 8 | const menusSlice = createSlice({ 9 | name: "modal", 10 | initialState: initialState, 11 | reducers: { 12 | openMenuHeader(state) { 13 | state.menuHeaderOpened = true; 14 | }, 15 | closeMenuHeader(state) { 16 | state.menuHeaderOpened = false; 17 | }, 18 | openMenuAccount(state) { 19 | state.menuAccountOpened = true; 20 | }, 21 | closeMenuAccount(state) { 22 | state.menuAccountOpened = false; 23 | }, 24 | }, 25 | }); 26 | 27 | export const menusActions = menusSlice.actions; 28 | export default menusSlice.reducer; 29 | -------------------------------------------------------------------------------- /src/components/Utilities/ModalConfirm.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Modal from "./Modal"; 3 | 4 | const ModalConfirm: React.FC<{ 5 | onConfirm: () => void; 6 | onClose: () => void; 7 | text: string; 8 | }> = ({ onConfirm, onClose, text }) => { 9 | const confirmAndCloseModal = () => { 10 | onConfirm(); 11 | onClose(); 12 | }; 13 | return ( 14 | 15 |

{text}

16 |
17 | 18 | 21 |
22 |
23 | ); 24 | }; 25 | 26 | export default ModalConfirm; 27 | -------------------------------------------------------------------------------- /src/assets/sort-number-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/hooks/useSearchQuery.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { Task } from "../../interfaces"; 3 | import { useAppSelector } from "../../store/hooks"; 4 | 5 | const useSearchQuery = (searchQuery: string) => { 6 | const tasks = useAppSelector((state) => state.tasks.tasks); 7 | 8 | const [matchedTasks, setMatchedTasks] = useState([]); 9 | 10 | useEffect(() => { 11 | const filteredTasks = tasks.filter((task: Task) => { 12 | return task.title.toLowerCase().includes(searchQuery.toLowerCase()); 13 | }); 14 | if (searchQuery.trim().length) { 15 | setMatchedTasks(filteredTasks); 16 | } else { 17 | setMatchedTasks([]); 18 | } 19 | }, [searchQuery, tasks]); 20 | 21 | return matchedTasks; 22 | }; 23 | 24 | export default useSearchQuery; 25 | -------------------------------------------------------------------------------- /src/Weather/Api.tsx: -------------------------------------------------------------------------------- 1 | 2 | async function ApiWeather() { 3 | try { 4 | const url = 'https://weatherapi-com.p.rapidapi.com/current.json?q=53.1%2C-0.13'; 5 | const options = { 6 | method: 'GET', 7 | headers: { 8 | 'X-RapidAPI-Key': 'e9599cefeamshbc7374c5a4657fap1ee92fjsn276533db2cd3', 9 | 'X-RapidAPI-Host': 'weatherapi-com.p.rapidapi.com' 10 | } 11 | }; 12 | const response = await fetch(url, options); 13 | const result = await response.json(); 14 | try { 15 | if (response.status === 200) { 16 | return result 17 | } else { 18 | return false 19 | } 20 | } catch (e) { 21 | 22 | } 23 | }catch (e){ 24 | return false 25 | } 26 | } 27 | export {ApiWeather} 28 | -------------------------------------------------------------------------------- /src/components/Routes/ImportantTasks.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { Task } from "../../interfaces"; 3 | import { useAppSelector } from "../../store/hooks"; 4 | import useDescriptionTitle from "../hooks/useDescriptionTitle"; 5 | import LayoutRoutes from "../Utilities/LayoutRoutes"; 6 | 7 | const ImportantTasks: React.FC = () => { 8 | const tasks = useAppSelector((state) => state.tasks.tasks); 9 | const [importantTasks, setImportantTasks] = useState([]); 10 | 11 | useEffect(() => { 12 | const filteredTasks: Task[] = tasks.filter((task: Task) => task.important); 13 | setImportantTasks(filteredTasks); 14 | }, [tasks]); 15 | 16 | useDescriptionTitle("Tasks marked as important", "Important tasks"); 17 | 18 | return ( 19 | 20 | ); 21 | }; 22 | 23 | export default ImportantTasks; 24 | -------------------------------------------------------------------------------- /src/components/Utilities/LayoutMenus.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactNode } from "react"; 2 | import useScreenMedia from "../hooks/useScreenMedia"; 3 | 4 | const LayoutMenus: React.FC<{ 5 | menuOpen: boolean; 6 | children: ReactNode; 7 | closeMenuHandler: () => void; 8 | className?: string; 9 | }> = ({ menuOpen, children, closeMenuHandler, className }) => { 10 | const mediaQueries = useScreenMedia(); 11 | 12 | return ( 13 | <> 14 |
19 | {children} 20 |
21 | {menuOpen && !mediaQueries.xl && ( 22 |
26 | )} 27 | 28 | ); 29 | }; 30 | 31 | export default LayoutMenus; 32 | -------------------------------------------------------------------------------- /src/components/hooks/useTodayTasks.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | import { Task } from "../../interfaces"; 3 | import { useAppSelector } from "../../store/hooks"; 4 | 5 | const useTodayTasks = (): Task[] => { 6 | const tasks = useAppSelector((state) => state.tasks.tasks); 7 | const [todaysTasks, setTodaysTasks] = useState([]); 8 | 9 | const date: Date = new Date(); 10 | const year: number = date.getFullYear(); 11 | const month: number = date.getMonth() + 1; 12 | const day: number = date.getDate(); 13 | 14 | const dateTimeFormat = `${year}-${month.toString().padStart(2, "0")}-${day 15 | .toString() 16 | .padStart(2, "0")}`; 17 | 18 | useEffect(() => { 19 | let filteredTasks: Task[] = tasks.filter( 20 | (task: Task) => task.date === dateTimeFormat 21 | ); 22 | setTodaysTasks(filteredTasks); 23 | }, [dateTimeFormat, tasks]); 24 | return todaysTasks; 25 | }; 26 | 27 | export default useTodayTasks; 28 | -------------------------------------------------------------------------------- /src/components/TasksSection/TaskItem/BtnMarkAsImportant.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useAppDispatch } from "../../../store/hooks"; 3 | import { tasksActions } from "../../../store/Tasks.store"; 4 | import { ReactComponent as StarLine } from "../../../assets/star-line.svg"; 5 | 6 | const BtnMarkAsImportant: React.FC<{ 7 | taskId: string; 8 | taskImportant: boolean; 9 | }> = ({ taskId, taskImportant }) => { 10 | const dispatch = useAppDispatch(); 11 | 12 | const markAsImportantHandler = () => { 13 | dispatch(tasksActions.markAsImportant(taskId)); 14 | }; 15 | 16 | return ( 17 | 28 | ); 29 | }; 30 | 31 | export default React.memo(BtnMarkAsImportant); 32 | -------------------------------------------------------------------------------- /src/components/Routes/SearchResults.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import { useNavigate, useSearchParams } from "react-router-dom"; 3 | import useDescriptionTitle from "../hooks/useDescriptionTitle"; 4 | import useSearchQuery from "../hooks/useSearchQuery"; 5 | import LayoutRoutes from "../Utilities/LayoutRoutes"; 6 | 7 | const SearchResults: React.FC = () => { 8 | const [searchParams] = useSearchParams(); 9 | const navigate = useNavigate(); 10 | 11 | const [currQueryParam, setCurrQueryParam] = useState(""); 12 | 13 | useEffect(() => { 14 | const query = searchParams.get("q"); 15 | if (!query) { 16 | // se "q" for igual a '' ou "q" não existir 17 | navigate("/"); 18 | } else { 19 | setCurrQueryParam(query); 20 | } 21 | }, [navigate, searchParams]); 22 | 23 | const matchedTasks = useSearchQuery(currQueryParam); 24 | 25 | const title = `Results for "${currQueryParam}"`; 26 | 27 | useDescriptionTitle(title, title); 28 | 29 | return ; 30 | }; 31 | 32 | export default SearchResults; 33 | -------------------------------------------------------------------------------- /src/components/TasksSection/TaskItem/ActionsTaskItem.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Task } from "../../../interfaces"; 3 | import BtnEditTask from "./BtnEditTask"; 4 | import BtnMarkAsImportant from "./BtnMarkAsImportant"; 5 | import BtnDeleteTask from "./BtnDeleteTask"; 6 | import BtnToggleCompleted from "./BtnToggleCompleted"; 7 | 8 | const ActionsTaskItem: React.FC<{ task: Task; isListInView1: boolean }> = ({ 9 | task, 10 | isListInView1, 11 | }) => { 12 | return ( 13 | <> 14 |
19 | 24 | 25 | 26 | 27 |
28 | 29 | ); 30 | }; 31 | 32 | export default ActionsTaskItem; 33 | -------------------------------------------------------------------------------- /src/components/AccountSection/DeleteTasks.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { useAppDispatch } from "../../store/hooks"; 3 | import { tasksActions } from "../../store/Tasks.store"; 4 | import ModalConfirm from "../Utilities/ModalConfirm"; 5 | import { ReactComponent as Trash } from "../../assets/trash.svg"; 6 | 7 | 8 | const DeleteTasks: React.FC = () => { 9 | const dispatch = useAppDispatch(); 10 | 11 | const [showModal, setIsModalShown] = useState(false); 12 | 13 | const deleteAllDataHandler = () => { 14 | dispatch(tasksActions.deleteAllData()); 15 | }; 16 | 17 | return ( 18 | <> 19 | {showModal && ( 20 | setIsModalShown(false)} 22 | text="All data will be deleted permanently." 23 | onConfirm={deleteAllDataHandler} 24 | /> 25 | )} 26 | 32 | 33 | ); 34 | }; 35 | 36 | export default React.memo(DeleteTasks); 37 | -------------------------------------------------------------------------------- /src/components/Routes/TaskOnly.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { useNavigate, useParams } from "react-router-dom"; 3 | import { Task } from "../../interfaces"; 4 | import { useAppSelector } from "../../store/hooks"; 5 | import useDescriptionTitle from "../hooks/useDescriptionTitle"; 6 | import LayoutRoutes from "../Utilities/LayoutRoutes"; 7 | 8 | const TaskOnly: React.FC = () => { 9 | const params = useParams(); 10 | const navigate = useNavigate(); 11 | 12 | const tasks = useAppSelector((store) => store.tasks.tasks); 13 | 14 | const [matchedTask, setMatchedTask] = useState([]); 15 | 16 | useEffect(() => { 17 | const taskId = params.taskId; 18 | const filteredTask = tasks.filter((task: Task) => taskId === task.id); 19 | if (!filteredTask.length) { 20 | navigate("/"); 21 | } 22 | setMatchedTask(filteredTask); 23 | }, [navigate, params.taskId, tasks]); 24 | 25 | const title = matchedTask.length ? matchedTask[0].title : ""; 26 | 27 | useDescriptionTitle(`Searching for ${title}`, "Task " + title); 28 | 29 | return ; 30 | }; 31 | 32 | export default TaskOnly; 33 | -------------------------------------------------------------------------------- /src/components/Menu/Directories/Directories.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { ReactComponent as Arrow } from "../../../assets/arrow.svg"; 3 | import ContentDirectories from "./ContentDirectories"; 4 | 5 | const Directories: React.FC<{ classActive: string }> = ({ classActive }) => { 6 | const [isDirectoriesOpen, setIsDirectoriesOpen] = useState(true); 7 | 8 | const toggleDirectoriesOpen = () => { 9 | setIsDirectoriesOpen((prevState) => !prevState); 10 | }; 11 | 12 | return ( 13 |
14 | 27 |
28 | 29 |
30 |
31 | ); 32 | }; 33 | 34 | export default Directories; 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright © 2023 WebVaVe . All rights reserved | Developed and supported by the Ariyan Emami | WebVaVe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/assets/2048.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/Weather/AlertBlock.tsx: -------------------------------------------------------------------------------- 1 | 2 | import React, { useState} from "react"; 3 | import Button from './button/Button'; 4 | import Modal, { ModalBody, ModalFooter, ModalHeader } from './modal/Modal'; 5 | export function AlertBlock() { 6 | const [show, setShow] = useState(true) 7 | 8 | return( 9 |
10 | 14 | 15 |

Alert Weather

16 |
17 | 18 |

19 | As a result of the sanctions imposed on your country, certain capabilities are now 20 | inaccessible for use.
or maybe the API has expired 21 |

22 |
23 | 24 | 27 | 28 |
29 |
30 | ) 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/components/TasksSection/TaskItem/BtnDeleteTask.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { useAppDispatch } from "../../../store/hooks"; 3 | import { tasksActions } from "../../../store/Tasks.store"; 4 | import ModalConfirm from "../../Utilities/ModalConfirm"; 5 | import { ReactComponent as Trash } from "../../../assets/trash.svg"; 6 | 7 | const BtnDeleteTask: React.FC<{ taskId: string }> = ({ taskId }) => { 8 | const [showModal, setIsModalShown] = useState(false); 9 | const dispatch = useAppDispatch(); 10 | 11 | const removeTaskHandler = () => { 12 | dispatch(tasksActions.removeTask(taskId)); 13 | }; 14 | return ( 15 | <> 16 | {showModal && ( 17 | setIsModalShown(false)} 19 | text="This task will be deleted permanently." 20 | onConfirm={removeTaskHandler} 21 | /> 22 | )} 23 | 30 | 31 | ); 32 | }; 33 | 34 | export default React.memo(BtnDeleteTask); 35 | -------------------------------------------------------------------------------- /src/game/TicTacToe/Square/Square.css: -------------------------------------------------------------------------------- 1 | .square { 2 | width: 150px; 3 | height: 150px; 4 | display: flex; 5 | justify-content: center; 6 | align-items: center; 7 | text-align: center; 8 | font-size: 58px; 9 | font-weight: 100; 10 | color: #EAB308 ; 11 | border: 1px solid #ffffffc5; 12 | background-color: #6D28D9; 13 | cursor: pointer; 14 | user-select: none; 15 | } 16 | 17 | @media (max-width: 700px) { 18 | .square { 19 | width: 100px; 20 | height: 100px; 21 | font-size: 44px; 22 | } 23 | } 24 | 25 | .square:nth-child(1) { 26 | border-width: 0 1px 1px 0; 27 | } 28 | .square:nth-child(2) { 29 | border-width: 0 0 1px 0; 30 | } 31 | .square:nth-child(3) { 32 | border-width: 0px 0px 1px 1px; 33 | } 34 | 35 | .square:nth-child(4) { 36 | border-width: 0 1px 0 0; 37 | } 38 | .square:nth-child(5) { 39 | border: none; 40 | } 41 | .square:nth-child(6) { 42 | border-width: 0 0 0 1px; 43 | } 44 | 45 | .square:nth-child(7) { 46 | border-width: 1px 1px 0 0; 47 | } 48 | .square:nth-child(8) { 49 | border-width: 1px 0 0 0; 50 | } 51 | .square:nth-child(9) { 52 | border-width: 1px 0 0 1px; 53 | } 54 | 55 | @keyframes blinker { 56 | 30% { 57 | opacity: 0; 58 | } 59 | } 60 | .changed { 61 | animation: blinker 1s linear infinite; 62 | } 63 | -------------------------------------------------------------------------------- /src/components/Menu/NavLinks.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { NavLink, useLocation } from "react-router-dom"; 3 | 4 | const links = [ 5 | { 6 | name: "Today's tasks", 7 | path: "/today", 8 | }, 9 | { 10 | name: "All tasks", 11 | path: "/", 12 | }, 13 | { 14 | name: "Important tasks", 15 | path: "/important", 16 | }, 17 | { 18 | name: "Completed tasks", 19 | path: "/completed", 20 | }, 21 | { 22 | name: "Uncompleted tasks", 23 | path: "/uncompleted", 24 | }, 25 | ]; 26 | 27 | const NavLinks: React.FC<{ classActive: string }> = ({ classActive }) => { 28 | const route = useLocation(); 29 | const currentPath = route.pathname; 30 | return ( 31 | 47 | ); 48 | }; 49 | 50 | export default NavLinks; 51 | -------------------------------------------------------------------------------- /src/components/TasksSection/TaskItem/InfosTask.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Task } from "../../../interfaces"; 3 | import { ReactComponent as Calendar } from "../../../assets/date.svg"; 4 | import useDate from "../../hooks/useDate"; 5 | 6 | const InfosTask: React.FC<{ task: Task; isListInView1: boolean }> = ({ 7 | task, 8 | isListInView1, 9 | }) => { 10 | const dateFormated = useDate(task.date); 11 | 12 | return ( 13 |
14 |
19 | 20 | {task.title} 21 | 22 |
23 |

29 | {task.description} 30 |

31 | 34 |
35 | ); 36 | }; 37 | 38 | export default InfosTask; 39 | -------------------------------------------------------------------------------- /src/components/hooks/useVisibility.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | const useVisibility = (elements: HTMLElement[], fnClose?: () => void) => { 4 | const [elementIsVisible, setElementIsVisible] = useState(false); 5 | 6 | useEffect(() => { 7 | const checkClick = (e: MouseEvent) => { 8 | if (!elements) return; 9 | 10 | const clickedOutsideElement = elements.every((element) => { 11 | if (!element) return false; 12 | if ( 13 | e.target !== element && 14 | !element.contains(e.target as HTMLElement) 15 | ) { 16 | return true; 17 | } 18 | return false; 19 | }); 20 | 21 | if (clickedOutsideElement) { 22 | setElementIsVisible(false); 23 | if (fnClose) fnClose(); 24 | } 25 | }; 26 | 27 | document.addEventListener("click", checkClick); 28 | return () => { 29 | document.removeEventListener("click", checkClick); 30 | }; 31 | }, [elements, fnClose]); 32 | 33 | const closeElement = () => { 34 | setElementIsVisible(false); 35 | }; 36 | 37 | const showElement = () => { 38 | setElementIsVisible(true); 39 | }; 40 | 41 | return { elementIsVisible, closeElement, showElement }; 42 | }; 43 | 44 | export default useVisibility; 45 | -------------------------------------------------------------------------------- /src/components/Routes/Directory.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import { useNavigate, useParams } from "react-router-dom"; 3 | import { Task } from "../../interfaces"; 4 | import { useAppSelector } from "../../store/hooks"; 5 | import useDescriptionTitle from "../hooks/useDescriptionTitle"; 6 | import LayoutRoutes from "../Utilities/LayoutRoutes"; 7 | 8 | const Directory: React.FC = () => { 9 | const tasks = useAppSelector((state) => state.tasks.tasks); 10 | const directories = useAppSelector((state) => state.tasks.directories); 11 | const params = useParams(); 12 | const navigate = useNavigate(); 13 | 14 | useDescriptionTitle( 15 | `Tasks in "${params.dir}"`, 16 | params.dir ? params.dir + " directory" : "" 17 | ); 18 | 19 | const [tasksInCurrentDirectory, setTasksInCurrentDirectory] = useState< 20 | Task[] 21 | >([]); 22 | 23 | useEffect(() => { 24 | const dirExists = directories.includes(params.dir); 25 | if (!dirExists) { 26 | navigate("/"); 27 | } 28 | const tasksFiltered = tasks.filter((task: Task) => task.dir === params.dir); 29 | setTasksInCurrentDirectory(tasksFiltered); 30 | }, [directories, navigate, params.dir, tasks]); 31 | 32 | return ( 33 | 37 | ); 38 | }; 39 | 40 | export default Directory; 41 | -------------------------------------------------------------------------------- /src/components/TasksSection/TaskItem/TaskItem.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Task } from "../../../interfaces"; 3 | import { Link } from "react-router-dom"; 4 | import InfosTask from "./InfosTask"; 5 | import ActionsTaskItem from "./ActionsTaskItem"; 6 | 7 | const TaskItem: React.FC<{ isListInView1: boolean; task: Task }> = ({ 8 | isListInView1, 9 | task, 10 | }) => { 11 | return ( 12 | <> 13 |
  • 14 | 19 | {task.dir} 20 | 21 |
    26 | 27 | 28 |
    29 |
  • 30 | 31 | ); 32 | }; 33 | 34 | export default React.memo(TaskItem); 35 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import AccountData from "./components/AccountSection/AccountData"; 3 | import Menu from "./components/Menu/Menu"; 4 | import TasksSection from "./components/TasksSection/TasksSection"; 5 | import ModalCreateTask from "./components/Utilities/ModalTask"; 6 | import { Task } from "./interfaces"; 7 | import { useAppDispatch, useAppSelector } from "./store/hooks"; 8 | import { modalActions } from "./store/Modal.store"; 9 | import { tasksActions } from "./store/Tasks.store"; 10 | 11 | const App: React.FC = () => { 12 | const modal = useAppSelector((state) => state.modal); 13 | 14 | const dispatch = useAppDispatch(); 15 | 16 | const closeModalCreateTask = () => { 17 | dispatch(modalActions.closeModalCreateTask()); 18 | }; 19 | 20 | const createNewTaskHandler = (task: Task) => { 21 | dispatch(tasksActions.addNewTask(task)); 22 | }; 23 | 24 | 25 | return ( 26 |
    27 | 28 |
    29 | 30 | {modal.modalCreateTaskOpen && ( 31 | 36 | )} 37 | 38 | 39 |
    40 |
    41 | ); 42 | }; 43 | 44 | export default App; 45 | -------------------------------------------------------------------------------- /src/Weather/modal/Modal.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react'; 2 | import './modal.scss'; 3 | 4 | const Modal = props => { 5 | const modalRef = useRef(); 6 | 7 | useEffect(() => { 8 | const clickOutsideContent = (e) => { 9 | if (e.target === modalRef.current) { 10 | props.setShow(false); 11 | } 12 | }; 13 | window.addEventListener('click', clickOutsideContent); 14 | return () => { 15 | window.removeEventListener('click', clickOutsideContent); 16 | }; 17 | }, [props]); 18 | 19 | return
    20 |
    21 | { 22 | !props.hideCloseButton && props.setShow(false)} className="modal__close"> 23 | × 24 | 25 | } 26 | {props.children} 27 |
    28 |
    ; 29 | }; 30 | 31 | export default Modal; 32 | 33 | export const ModalHeader = props => { 34 | return
    35 | {props.children} 36 |
    37 | } 38 | 39 | export const ModalBody = props => { 40 | return
    41 | {props.children} 42 |
    43 | } 44 | 45 | export const ModalFooter = props => { 46 | return
    47 | {props.children} 48 |
    49 | } 50 | -------------------------------------------------------------------------------- /src/components/Menu/Menu.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useAppDispatch, useAppSelector } from "../../store/hooks"; 3 | import { menusActions } from "../../store/Menu.store"; 4 | import BtnAddTask from "../Utilities/BtnAddTask"; 5 | import Directories from "./Directories/Directories"; 6 | import NavLinks from "./NavLinks"; 7 | import LayoutMenus from "../Utilities/LayoutMenus"; 8 | import Footer from "../Footer"; 9 | 10 | 11 | const classLinkActive = 12 | "text-rose-600 bg-violet-100 border-r-4 border-rose-500 dark:bg-slate-700/[.2] dark:text-slate-200 dark:border-slate-200"; 13 | 14 | const Menu: React.FC = () => { 15 | const menuOpen = useAppSelector((state) => state.menu.menuHeaderOpened); 16 | const dispatch = useAppDispatch(); 17 | 18 | const closeMenuHandler = () => { 19 | dispatch(menusActions.closeMenuHeader()); 20 | }; 21 | return ( 22 | 27 |
    28 |

    29 | ToDo 30 |

    31 | 32 | 33 | 34 |
    35 |