diff --git a/README.md b/README.md index e9b474ba2..c26527247 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,107 @@ # Project Todos -Replace this readme with your own information about your project. +![React](https://img.shields.io/badge/react-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB) +![Redux](https://img.shields.io/badge/redux-%23593d88.svg?style=for-the-badge&logo=redux&logoColor=white) +![Styled Components](https://img.shields.io/badge/styled--components-DB7093?style=for-the-badge&logo=styled-components&logoColor=white) -Start by briefly describing the assignment in a sentence or two. Keep it short and to the point. +A classic to do-app built in React using Redux. -## The problem +## Functionality -Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next? +The user can: +- Add new tasks with a due date +- Check if tasks are overdue +- Delete tasks +- Flag important tasks +- Toggle the completion of tasks +- Get the count of finished tasks +- Get the total count of tasks on the list +- Create and name new projects +- Delete projects +- Add, delete, toggle, flag tasks in projects + +## The process + +- Research design and functionality of commonly used in todo-apps +- Sketch and iterate on a layout and user flow +- Set up the store in Redux React +- Started off with the most basic functionality, i.e. creating reducers and actions to add and delete tasks +- Made sure the data moved properly between the components and the Redux store, using the console and Redux DevTool +- When everything worked I went on to add reducers and actions to toggle, flag and count tasks +- Then I moved on to work on more functionality: Reducers and actions to add new lists in an array, i.e. add new projects +- Added reducers and actions to delete lists + a functionality to toggle between opening and closing lists +- Added functionality to the list items in the lists in the array, i.e. toggle completion of tasks, flag tasks and count tasks +- Styling: I worked with Global Style/Styled Components and made the app responsive +- I got inspired by this [SVG wave animation in code pen](https://codepen.io/tedmcdo/pen/PqxKXg "Wave animation") and decided to manipulate it and place in the header section +
+To Do Demo + +## Potential improvements to be made + +- Work on styling, user flow and accessibility +- Work on backend, such as: authentication and to store all tasks and lists on a database +- Break down the react components a bit more +- Work with styled components more extensively +- Add extra functionality, such as being able to add a task to a specific project when creating it + +## Installation Instructions + +Follow these steps to clone and run the project locally: + +1. Clone the repository +``` +https://github.com/Vera-Sjunnesson/project-todos.git +``` +2. Navigate to the project directory and code folder where the package.json file is located +``` +cd project-todos +``` +then: +``` +cd code +``` +3. Install dependencies: +Ensure you have Node.js and npm installed on your machine. Then install the project dependencies using: +``` +npm install +``` +4. Start the Development Server: +Run the following command to start the development server and launch the app in your default web browser: +``` +npm start +``` +The app should automatically open in your browser at http://localhost:3000. If not, navigate to this URL manually.\ + +5. Explore the App: +Explore the app, add tasks, create projects and test out the functionality. + +### Additional notes: + +- Redux DevTools Extension: If you have the Redux DevTools Extension installed in your browser, you can use it to inspect and debug the state of your Redux store. +- Node.js: Make sure you have Node.js installed on your machine. +- npm (Node Package Manager): npm comes bundled with Node.js; however, ensure you have a recent version. + +## Dependencies + +- React +- ReactDOM +- Redux +- React-Redux +- Styled Components +- date-fns +- react-date-picker +- FontAwesome +- Eslint and related packages +- Uniqid +- react-global-style ## View it live -Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about. +https://to-do-project-vera.netlify.app/ + + + + + + + diff --git a/code/README.md b/code/README.md index 6e1ac173a..83047171b 100644 --- a/code/README.md +++ b/code/README.md @@ -1,19 +1,19 @@ -# Technigo React Starter App +# Project Todos -This app has been generated using `create-react-app`, then cleaned up a little so we have a project with just the elements we need to get started. +To create a to do list using redux toolkit. -Add components in the `src` folder and use them in `src/app.js` to get started. +## The problem -## Usage +I started off by making a sketch how the project would look like and how it would be organized / structured (with dropdowns collapsing) -1. On GitHub, click the 'use this template' button to create a new repo on your account -1. Clone the new repo to your computer -1. Install required dependencies with npm: `npm install` -1. Start the project: `npm start` +Then I started building all basic functionality, like adding items to the list and deleting items, later moved on to sorting items, depending on if they were completed or priority. -Alternatively, if you don't want a new git repo on your account; +When all that worked I moved to trying to create projects from scratch: arrays inside an array. In order (I don't know if it is the best way) to set a project name for each array I placed the arrays inside objects inside the 'main' array. -1. Download & extract the [latest release](https://github.com/Technigo/react-starter/releases/latest) from GitHub -1. Open the directory in the terminal: `cd /path/to/react-starter` -1. Install required dependencies with npm: `npm install` -1. Start the project: `npm start` +I used the redux dev tool a lot and stack overflow. + +If I had more time I would work on structuring the project better. + +## View it live + +https://to-do-project-vera.netlify.app/ diff --git a/code/package-lock.json b/code/package-lock.json index bb51e893e..ad48c235c 100644 --- a/code/package-lock.json +++ b/code/package-lock.json @@ -9,6 +9,11 @@ "version": "1.0.0", "dependencies": { "@babel/eslint-parser": "^7.18.9", + "@fortawesome/fontawesome-svg-core": "^6.4.0", + "@fortawesome/free-solid-svg-icons": "^6.4.0", + "@fortawesome/react-fontawesome": "^0.2.0", + "@reduxjs/toolkit": "^1.9.4", + "date-fns": "^2.29.3", "eslint": "^8.21.0", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-import": "^2.26.0", @@ -16,7 +21,13 @@ "eslint-plugin-react": "^7.30.1", "eslint-plugin-react-hooks": "^4.6.0", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-date-picker": "^10.0.3", + "react-datepicker": "^4.11.0", + "react-dom": "^18.2.0", + "react-global-style": "^0.2.1", + "react-redux": "^8.0.5", + "styled-components": "^5.3.9", + "uniqid": "^5.4.0" }, "devDependencies": { "react-scripts": "5.0.1" @@ -129,7 +140,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "dev": true, "dependencies": { "@babel/types": "^7.18.6" }, @@ -2153,6 +2163,29 @@ "postcss-selector-parser": "^6.0.10" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz", + "integrity": "sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==", + "dependencies": { + "@emotion/memoize": "^0.8.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", + "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" + }, + "node_modules/@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, "node_modules/@eslint/eslintrc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", @@ -2197,6 +2230,51 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz", + "integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz", + "integrity": "sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.4.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz", + "integrity": "sha512-kutPeRGWm8V5dltFP1zGjQOEAzaLZj4StdQhWVZnfGFCvAPVvHh8qk5bRrU4KXnRRRNni5tKQI9PBAdI6MP8nQ==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.4.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/react-fontawesome": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.3" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", @@ -3124,6 +3202,38 @@ } } }, + "node_modules/@popperjs/core": { + "version": "2.11.7", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz", + "integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@reduxjs/toolkit": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.4.tgz", + "integrity": "sha512-j2R4I+dzt7cWjf50CNS17A/TBX0rH5SmFhKcOQDZlFtFvmSGWfEQvNPjrCI729Am5o1USFWT1PaxV/JflmP/Dg==", + "dependencies": { + "immer": "^9.0.21", + "redux": "^4.2.1", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.8" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.0.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -3621,6 +3731,15 @@ "@types/node": "*" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -3671,6 +3790,19 @@ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, + "node_modules/@types/lodash": { + "version": "4.14.194", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.194.tgz", + "integrity": "sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==" + }, + "node_modules/@types/lodash.memoize": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/lodash.memoize/-/lodash.memoize-4.1.7.tgz", + "integrity": "sha512-lGN7WeO4vO6sICVpf041Q7BX/9k1Y24Zo3FY0aUezr1QlKznpjzsDk3T3wvH8ofYzoK0QupN9TWcFAFZlyPwQQ==", + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/mime": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.0.tgz", @@ -3695,6 +3827,11 @@ "integrity": "sha512-fOwvpvQYStpb/zHMx0Cauwywu9yLDmzWiiQBC7gJyq5tYLUXFZvDG7VK1B7WBxxjBJNKFOZ0zLoOQn8vmATbhw==", "dev": true }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, "node_modules/@types/q": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", @@ -3713,6 +3850,24 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", "dev": true }, + "node_modules/@types/react": { + "version": "18.0.35", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.35.tgz", + "integrity": "sha512-6Laome31HpetaIUGFWl1VQ3mdSImwxtFZ39rh059a1MNnKGqBpC88J6NJ8n/Is3Qx7CefDGLgf/KhN/sYCf7ag==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", + "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -3728,6 +3883,11 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, + "node_modules/@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + }, "node_modules/@types/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", @@ -3768,6 +3928,11 @@ "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==", "dev": true }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" + }, "node_modules/@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -4180,6 +4345,14 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@wojtekmaj/date-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@wojtekmaj/date-utils/-/date-utils-1.1.3.tgz", + "integrity": "sha512-rHrDuTl1cx5LYo8F4K4HVauVjwzx4LwrKfEk4br4fj4nK8JjJZ8IG6a6pBHkYmPLBQHCOEDwstb0WNXMGsmdOw==", + "funding": { + "url": "https://github.com/wojtekmaj/date-utils?sponsor=1" + } + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -4867,6 +5040,26 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/babel-plugin-styled-components": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.1.tgz", + "integrity": "sha512-c8lJlszObVQPguHkI+akXv8+Jgb9Ccujx0EetL7oIvwU100LxO6XAGe45qry37wUL40a5U9f23SYrivro2XKhA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-module-imports": "^7.16.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.21", + "picomatch": "^2.3.0" + }, + "peerDependencies": { + "styled-components": ">= 2" + } + }, + "node_modules/babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==" + }, "node_modules/babel-plugin-transform-react-remove-prop-types": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", @@ -5204,6 +5397,14 @@ "node": ">= 6" } }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -5328,6 +5529,11 @@ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "node_modules/clean-css": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz", @@ -5360,6 +5566,14 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -5691,6 +5905,14 @@ "postcss": "^8.4" } }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "engines": { + "node": ">=4" + } + }, "node_modules/css-declaration-sorter": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.0.tgz", @@ -5899,6 +6121,16 @@ "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", "dev": true }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "node_modules/css-tree": { "version": "1.0.0-alpha.37", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", @@ -6095,6 +6327,11 @@ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "dev": true }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -6114,6 +6351,18 @@ "node": ">=10" } }, + "node_modules/date-fns": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", + "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -6226,6 +6475,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-element-overflow": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/detect-element-overflow/-/detect-element-overflow-1.3.1.tgz", + "integrity": "sha512-E29Axx3pyotgg3j5HUbusTTarjPUHsC02p7fZ3/cnUufyK0kx5RzRA9waBvrKFWGc/LWiRj3pD9Y3y+mymMYiQ==", + "funding": { + "url": "https://github.com/wojtekmaj/detect-element-overflow?sponsor=1" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -8304,6 +8561,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-user-locale": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/get-user-locale/-/get-user-locale-2.2.1.tgz", + "integrity": "sha512-3814zipTZ2MvczOcppEXB3jXu+0HWwj5WmPI6//SeCnUIUaRXu7W4S54eQZTEPadlMZefE+jAlPOn+zY3tD4Qw==", + "dependencies": { + "@types/lodash.memoize": "^4.1.7", + "lodash.memoize": "^4.1.1" + }, + "funding": { + "url": "https://github.com/wojtekmaj/get-user-locale?sponsor=1" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -8515,6 +8784,14 @@ "he": "bin/he" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -8800,10 +9077,9 @@ } }, "node_modules/immer": { - "version": "9.0.15", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz", - "integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==", - "dev": true, + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -11695,8 +11971,7 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash.debounce": { "version": "4.0.8", @@ -11707,8 +11982,7 @@ "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -11783,6 +12057,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/make-event-props": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/make-event-props/-/make-event-props-1.5.0.tgz", + "integrity": "sha512-ubtzzj95Ga0t/LoINWPjqQWIxbb1SJ6td7YygKzx8kX5ywu/dpN0YnCsjzJOTxFXKsb/1SJBzy+uBAMnKWMVDw==", + "funding": { + "url": "https://github.com/wojtekmaj/make-event-props?sponsor=1" + } + }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -13940,8 +14222,7 @@ "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/prelude-ls": { "version": "1.2.1", @@ -14226,6 +14507,64 @@ "node": ">=14" } }, + "node_modules/react-calendar": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/react-calendar/-/react-calendar-4.2.1.tgz", + "integrity": "sha512-T5oKXD+KLy/g6bmJJkZ7E9wj0iRMesWMZcrC7q2kI6ybOsu9NlPQx8uXJzG4A4C3Sh5Xi0deznyzWIVsUpF8tA==", + "dependencies": { + "@types/react": "*", + "@wojtekmaj/date-utils": "^1.1.3", + "clsx": "^1.2.1", + "get-user-locale": "^2.2.1", + "prop-types": "^15.6.0" + }, + "funding": { + "url": "https://github.com/wojtekmaj/react-calendar?sponsor=1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-date-picker": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/react-date-picker/-/react-date-picker-10.0.3.tgz", + "integrity": "sha512-v+ZNN66hEQak20bxngSTJLzR9Z52luof0UDrlFO7hv2hCx7aaSuHLHm+lbwhvFF4y7Gn7Pjvbm5jHuwzn9Xw5w==", + "dependencies": { + "@wojtekmaj/date-utils": "^1.1.3", + "clsx": "^1.2.1", + "get-user-locale": "^2.2.1", + "make-event-props": "^1.4.2", + "prop-types": "^15.6.0", + "react-calendar": "^4.2.1", + "react-fit": "^1.5.1", + "update-input-width": "^1.3.1" + }, + "funding": { + "url": "https://github.com/wojtekmaj/react-date-picker?sponsor=1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-datepicker": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.11.0.tgz", + "integrity": "sha512-50n93o7mQwBEhg05tbopjFKgs8qgi8VBCAOMC4VqrKut72eAjESc/wXS/k5hRtnP0oe2FCGw7MJuIwh37wuXOw==", + "dependencies": { + "@popperjs/core": "^2.9.2", + "classnames": "^2.2.6", + "date-fns": "^2.24.0", + "prop-types": "^15.7.2", + "react-onclickoutside": "^6.12.2", + "react-popper": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17 || ^18", + "react-dom": "^16.9.0 || ^17 || ^18" + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -14370,11 +14709,110 @@ "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==", "dev": true }, + "node_modules/react-fast-compare": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.1.tgz", + "integrity": "sha512-xTYf9zFim2pEif/Fw16dBiXpe0hoy5PxcD8+OwBnTtNLfIm3g6WxhKNurY+6OmdH1u6Ta/W/Vl6vjbYP1MFnDg==" + }, + "node_modules/react-fit": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/react-fit/-/react-fit-1.5.1.tgz", + "integrity": "sha512-r86m/6GuJa7j6dLYjC7kENBQRBaDMLTU0mBBoqnh42d/Iil9rmWEeOtdB2KEQEUyDQ8rZXojIx8u+gNFJ+9y1w==", + "dependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "detect-element-overflow": "^1.3.1", + "prop-types": "^15.6.0", + "tiny-warning": "^1.0.0" + }, + "funding": { + "url": "https://github.com/wojtekmaj/react-fit?sponsor=1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-global-style": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/react-global-style/-/react-global-style-0.2.1.tgz", + "integrity": "sha512-DAp0CMFidk0nbtIqMxBwCoMxu306ZDrk+FkTcC/s/EB9RvtHsM94rh9Y2dR0tUdwhrYVqXy+aa39S5ZnlO+rzQ==" + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/react-onclickoutside": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz", + "integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==", + "funding": { + "type": "individual", + "url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md" + }, + "peerDependencies": { + "react": "^15.5.x || ^16.x || ^17.x || ^18.x", + "react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x" + } + }, + "node_modules/react-popper": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", + "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", + "dependencies": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + }, + "peerDependencies": { + "@popperjs/core": "^2.0.0", + "react": "^16.8.0 || ^17 || ^18", + "react-dom": "^16.8.0 || ^17 || ^18" + } + }, + "node_modules/react-redux": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz", + "integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==", + "dependencies": { + "@babel/runtime": "^7.12.1", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/use-sync-external-store": "^0.0.3", + "hoist-non-react-statics": "^3.3.2", + "react-is": "^18.0.0", + "use-sync-external-store": "^1.0.0" + }, + "peerDependencies": { + "@types/react": "^16.8 || ^17.0 || ^18.0", + "@types/react-dom": "^16.8 || ^17.0 || ^18.0", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0", + "react-native": ">=0.59", + "redux": "^4" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/react-redux/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -14531,6 +14969,22 @@ "node": "*" } }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/redux-thunk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "peerDependencies": { + "redux": "^4" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -14686,6 +15140,11 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, + "node_modules/reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" + }, "node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -15206,6 +15665,11 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -15615,6 +16079,35 @@ "webpack": "^5.0.0" } }, + "node_modules/styled-components": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.9.tgz", + "integrity": "sha512-Aj3kb13B75DQBo2oRwRa/APdB5rSmwUfN5exyarpX+x/tlM/rwZA2vVk2vQgVSP6WKaZJHWwiFrzgHt+CLtB4A==", + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^1.1.0", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0", + "react-is": ">= 16.8.0" + } + }, "node_modules/stylehacks": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.0.tgz", @@ -16007,6 +16500,11 @@ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -16261,6 +16759,11 @@ "node": ">=4" } }, + "node_modules/uniqid": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-5.4.0.tgz", + "integrity": "sha512-38JRbJ4Fj94VmnC7G/J/5n5SC7Ab46OM5iNtSstB/ko3l1b5g7ALt4qzHFgGciFkyiRNtDXtLNb+VsxtMSE77A==" + }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -16332,6 +16835,14 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/update-input-width": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/update-input-width/-/update-input-width-1.3.1.tgz", + "integrity": "sha512-hV2DGiSn7FKerjIXaI3s0EG/AnmAeoRTV5cvpsFcygzUzKreYj5qSu7rVihzUOEXF/MP2mjJpUzwi14sZdp0nw==", + "funding": { + "url": "https://github.com/wojtekmaj/update-input-width?sponsor=1" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -16340,6 +16851,14 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -16443,6 +16962,14 @@ "makeerror": "1.0.12" } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", @@ -17460,7 +17987,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "dev": true, "requires": { "@babel/types": "^7.18.6" } @@ -18792,6 +19318,29 @@ "dev": true, "requires": {} }, + "@emotion/is-prop-valid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz", + "integrity": "sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==", + "requires": { + "@emotion/memoize": "^0.8.0" + } + }, + "@emotion/memoize": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", + "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" + }, + "@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, "@eslint/eslintrc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", @@ -18823,6 +19372,35 @@ } } }, + "@fortawesome/fontawesome-common-types": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz", + "integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==" + }, + "@fortawesome/fontawesome-svg-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz", + "integrity": "sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.4.0" + } + }, + "@fortawesome/free-solid-svg-icons": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz", + "integrity": "sha512-kutPeRGWm8V5dltFP1zGjQOEAzaLZj4StdQhWVZnfGFCvAPVvHh8qk5bRrU4KXnRRRNni5tKQI9PBAdI6MP8nQ==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.4.0" + } + }, + "@fortawesome/react-fontawesome": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", + "requires": { + "prop-types": "^15.8.1" + } + }, "@humanwhocodes/config-array": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", @@ -19509,6 +20087,22 @@ "source-map": "^0.7.3" } }, + "@popperjs/core": { + "version": "2.11.7", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz", + "integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==" + }, + "@reduxjs/toolkit": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.4.tgz", + "integrity": "sha512-j2R4I+dzt7cWjf50CNS17A/TBX0rH5SmFhKcOQDZlFtFvmSGWfEQvNPjrCI729Am5o1USFWT1PaxV/JflmP/Dg==", + "requires": { + "immer": "^9.0.21", + "redux": "^4.2.1", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.8" + } + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -19876,6 +20470,15 @@ "@types/node": "*" } }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -19926,6 +20529,19 @@ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, + "@types/lodash": { + "version": "4.14.194", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.194.tgz", + "integrity": "sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==" + }, + "@types/lodash.memoize": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/lodash.memoize/-/lodash.memoize-4.1.7.tgz", + "integrity": "sha512-lGN7WeO4vO6sICVpf041Q7BX/9k1Y24Zo3FY0aUezr1QlKznpjzsDk3T3wvH8ofYzoK0QupN9TWcFAFZlyPwQQ==", + "requires": { + "@types/lodash": "*" + } + }, "@types/mime": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.0.tgz", @@ -19950,6 +20566,11 @@ "integrity": "sha512-fOwvpvQYStpb/zHMx0Cauwywu9yLDmzWiiQBC7gJyq5tYLUXFZvDG7VK1B7WBxxjBJNKFOZ0zLoOQn8vmATbhw==", "dev": true }, + "@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, "@types/q": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", @@ -19968,6 +20589,24 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", "dev": true }, + "@types/react": { + "version": "18.0.35", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.35.tgz", + "integrity": "sha512-6Laome31HpetaIUGFWl1VQ3mdSImwxtFZ39rh059a1MNnKGqBpC88J6NJ8n/Is3Qx7CefDGLgf/KhN/sYCf7ag==", + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-dom": { + "version": "18.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", + "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", + "requires": { + "@types/react": "*" + } + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -19983,6 +20622,11 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, + "@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + }, "@types/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", @@ -20023,6 +20667,11 @@ "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==", "dev": true }, + "@types/use-sync-external-store": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" + }, "@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -20327,6 +20976,11 @@ "@xtuc/long": "4.2.2" } }, + "@wojtekmaj/date-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@wojtekmaj/date-utils/-/date-utils-1.1.3.tgz", + "integrity": "sha512-rHrDuTl1cx5LYo8F4K4HVauVjwzx4LwrKfEk4br4fj4nK8JjJZ8IG6a6pBHkYmPLBQHCOEDwstb0WNXMGsmdOw==" + }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -20831,6 +21485,23 @@ "@babel/helper-define-polyfill-provider": "^0.3.2" } }, + "babel-plugin-styled-components": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.1.tgz", + "integrity": "sha512-c8lJlszObVQPguHkI+akXv8+Jgb9Ccujx0EetL7oIvwU100LxO6XAGe45qry37wUL40a5U9f23SYrivro2XKhA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-module-imports": "^7.16.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.21", + "picomatch": "^2.3.0" + } + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==" + }, "babel-plugin-transform-react-remove-prop-types": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", @@ -21099,6 +21770,11 @@ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "dev": true }, + "camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==" + }, "caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -21189,6 +21865,11 @@ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, + "classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "clean-css": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz", @@ -21217,6 +21898,11 @@ "wrap-ansi": "^7.0.0" } }, + "clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -21471,6 +22157,11 @@ "postcss-selector-parser": "^6.0.9" } }, + "css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==" + }, "css-declaration-sorter": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.0.tgz", @@ -21601,6 +22292,16 @@ "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", "dev": true }, + "css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "requires": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "css-tree": { "version": "1.0.0-alpha.37", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", @@ -21748,6 +22449,11 @@ } } }, + "csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, "damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -21764,6 +22470,11 @@ "whatwg-url": "^8.0.0" } }, + "date-fns": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", + "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==" + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -21843,6 +22554,11 @@ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true }, + "detect-element-overflow": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/detect-element-overflow/-/detect-element-overflow-1.3.1.tgz", + "integrity": "sha512-E29Axx3pyotgg3j5HUbusTTarjPUHsC02p7fZ3/cnUufyK0kx5RzRA9waBvrKFWGc/LWiRj3pD9Y3y+mymMYiQ==" + }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -23368,6 +24084,15 @@ "get-intrinsic": "^1.1.1" } }, + "get-user-locale": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/get-user-locale/-/get-user-locale-2.2.1.tgz", + "integrity": "sha512-3814zipTZ2MvczOcppEXB3jXu+0HWwj5WmPI6//SeCnUIUaRXu7W4S54eQZTEPadlMZefE+jAlPOn+zY3tD4Qw==", + "requires": { + "@types/lodash.memoize": "^4.1.7", + "lodash.memoize": "^4.1.1" + } + }, "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -23521,6 +24246,14 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, "hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -23739,10 +24472,9 @@ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" }, "immer": { - "version": "9.0.15", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz", - "integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==", - "dev": true + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==" }, "import-fresh": { "version": "3.3.0", @@ -25874,8 +26606,7 @@ "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash.debounce": { "version": "4.0.8", @@ -25886,8 +26617,7 @@ "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" }, "lodash.merge": { "version": "4.6.2", @@ -25950,6 +26680,11 @@ "semver": "^6.0.0" } }, + "make-event-props": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/make-event-props/-/make-event-props-1.5.0.tgz", + "integrity": "sha512-ubtzzj95Ga0t/LoINWPjqQWIxbb1SJ6td7YygKzx8kX5ywu/dpN0YnCsjzJOTxFXKsb/1SJBzy+uBAMnKWMVDw==" + }, "makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -27349,8 +28084,7 @@ "postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "prelude-ls": { "version": "1.2.1", @@ -27563,6 +28297,46 @@ "whatwg-fetch": "^3.6.2" } }, + "react-calendar": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/react-calendar/-/react-calendar-4.2.1.tgz", + "integrity": "sha512-T5oKXD+KLy/g6bmJJkZ7E9wj0iRMesWMZcrC7q2kI6ybOsu9NlPQx8uXJzG4A4C3Sh5Xi0deznyzWIVsUpF8tA==", + "requires": { + "@types/react": "*", + "@wojtekmaj/date-utils": "^1.1.3", + "clsx": "^1.2.1", + "get-user-locale": "^2.2.1", + "prop-types": "^15.6.0" + } + }, + "react-date-picker": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/react-date-picker/-/react-date-picker-10.0.3.tgz", + "integrity": "sha512-v+ZNN66hEQak20bxngSTJLzR9Z52luof0UDrlFO7hv2hCx7aaSuHLHm+lbwhvFF4y7Gn7Pjvbm5jHuwzn9Xw5w==", + "requires": { + "@wojtekmaj/date-utils": "^1.1.3", + "clsx": "^1.2.1", + "get-user-locale": "^2.2.1", + "make-event-props": "^1.4.2", + "prop-types": "^15.6.0", + "react-calendar": "^4.2.1", + "react-fit": "^1.5.1", + "update-input-width": "^1.3.1" + } + }, + "react-datepicker": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.11.0.tgz", + "integrity": "sha512-50n93o7mQwBEhg05tbopjFKgs8qgi8VBCAOMC4VqrKut72eAjESc/wXS/k5hRtnP0oe2FCGw7MJuIwh37wuXOw==", + "requires": { + "@popperjs/core": "^2.9.2", + "classnames": "^2.2.6", + "date-fns": "^2.24.0", + "prop-types": "^15.7.2", + "react-onclickoutside": "^6.12.2", + "react-popper": "^2.3.0" + } + }, "react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -27673,11 +28447,68 @@ "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==", "dev": true }, + "react-fast-compare": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.1.tgz", + "integrity": "sha512-xTYf9zFim2pEif/Fw16dBiXpe0hoy5PxcD8+OwBnTtNLfIm3g6WxhKNurY+6OmdH1u6Ta/W/Vl6vjbYP1MFnDg==" + }, + "react-fit": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/react-fit/-/react-fit-1.5.1.tgz", + "integrity": "sha512-r86m/6GuJa7j6dLYjC7kENBQRBaDMLTU0mBBoqnh42d/Iil9rmWEeOtdB2KEQEUyDQ8rZXojIx8u+gNFJ+9y1w==", + "requires": { + "@types/react": "*", + "@types/react-dom": "*", + "detect-element-overflow": "^1.3.1", + "prop-types": "^15.6.0", + "tiny-warning": "^1.0.0" + } + }, + "react-global-style": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/react-global-style/-/react-global-style-0.2.1.tgz", + "integrity": "sha512-DAp0CMFidk0nbtIqMxBwCoMxu306ZDrk+FkTcC/s/EB9RvtHsM94rh9Y2dR0tUdwhrYVqXy+aa39S5ZnlO+rzQ==" + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "react-onclickoutside": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz", + "integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==", + "requires": {} + }, + "react-popper": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", + "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", + "requires": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + } + }, + "react-redux": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz", + "integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==", + "requires": { + "@babel/runtime": "^7.12.1", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/use-sync-external-store": "^0.0.3", + "hoist-non-react-statics": "^3.3.2", + "react-is": "^18.0.0", + "use-sync-external-store": "^1.0.0" + }, + "dependencies": { + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + } + } + }, "react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -27800,6 +28631,20 @@ } } }, + "redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "requires": { + "@babel/runtime": "^7.9.2" + } + }, + "redux-thunk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "requires": {} + }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -27924,6 +28769,11 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, + "reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" + }, "resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -28306,6 +29156,11 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -28620,6 +29475,23 @@ "dev": true, "requires": {} }, + "styled-components": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.9.tgz", + "integrity": "sha512-Aj3kb13B75DQBo2oRwRa/APdB5rSmwUfN5exyarpX+x/tlM/rwZA2vVk2vQgVSP6WKaZJHWwiFrzgHt+CLtB4A==", + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^1.1.0", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + } + }, "stylehacks": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.0.tgz", @@ -28920,6 +29792,11 @@ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, "tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -29113,6 +29990,11 @@ "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", "dev": true }, + "uniqid": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-5.4.0.tgz", + "integrity": "sha512-38JRbJ4Fj94VmnC7G/J/5n5SC7Ab46OM5iNtSstB/ko3l1b5g7ALt4qzHFgGciFkyiRNtDXtLNb+VsxtMSE77A==" + }, "unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -29155,6 +30037,11 @@ "picocolors": "^1.0.0" } }, + "update-input-width": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/update-input-width/-/update-input-width-1.3.1.tgz", + "integrity": "sha512-hV2DGiSn7FKerjIXaI3s0EG/AnmAeoRTV5cvpsFcygzUzKreYj5qSu7rVihzUOEXF/MP2mjJpUzwi14sZdp0nw==" + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -29163,6 +30050,12 @@ "punycode": "^2.1.0" } }, + "use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "requires": {} + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -29248,6 +30141,14 @@ "makeerror": "1.0.12" } }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", diff --git a/code/package.json b/code/package.json index 7aad26ebc..52cbb70e5 100644 --- a/code/package.json +++ b/code/package.json @@ -4,6 +4,11 @@ "private": true, "dependencies": { "@babel/eslint-parser": "^7.18.9", + "@fortawesome/fontawesome-svg-core": "^6.4.0", + "@fortawesome/free-solid-svg-icons": "^6.4.0", + "@fortawesome/react-fontawesome": "^0.2.0", + "@reduxjs/toolkit": "^1.9.4", + "date-fns": "^2.29.3", "eslint": "^8.21.0", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-import": "^2.26.0", @@ -11,7 +16,13 @@ "eslint-plugin-react": "^7.30.1", "eslint-plugin-react-hooks": "^4.6.0", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-date-picker": "^10.0.3", + "react-datepicker": "^4.11.0", + "react-dom": "^18.2.0", + "react-global-style": "^0.2.1", + "react-redux": "^8.0.5", + "styled-components": "^5.3.9", + "uniqid": "^5.4.0" }, "scripts": { "start": "react-scripts start", diff --git a/code/public/images/todo-demo.png b/code/public/images/todo-demo.png new file mode 100644 index 000000000..74bb61697 Binary files /dev/null and b/code/public/images/todo-demo.png differ diff --git a/code/public/index.html b/code/public/index.html index e6730aa66..e0bb116a8 100644 --- a/code/public/index.html +++ b/code/public/index.html @@ -4,16 +4,13 @@ - - Technigo React App + To-Do App + + + + + + diff --git a/code/src/App.js b/code/src/App.js index f2007d229..c5da4d951 100644 --- a/code/src/App.js +++ b/code/src/App.js @@ -1,9 +1,30 @@ -import React from 'react'; +import React from 'react' +import { Provider } from 'react-redux' +import { combineReducers, configureStore } from '@reduxjs/toolkit' +import { ToDoList } from 'components/ToDoList' +import { projects } from 'reducers/projects' +import { Header } from 'components/Header' +import { ProjectToDoList } from 'components/ProjectToDoList' +import { Wrapper, Main } from 'components/style/GlobalStyle' +import { tasks } from './reducers/tasks' + +const reducer = combineReducers({ + tasks: tasks.reducer, + projects: projects.reducer +}) + +const store = configureStore({ reducer }) export const App = () => { return ( -
- Find me in src/app.js! -
- ); -} + +
+
+ + + + +
+ + ) +} \ No newline at end of file diff --git a/code/src/components/CompleteAll.js b/code/src/components/CompleteAll.js new file mode 100644 index 000000000..955b6b7ae --- /dev/null +++ b/code/src/components/CompleteAll.js @@ -0,0 +1,18 @@ +import React from 'react' +import { useDispatch } from 'react-redux' +import { tasks } from 'reducers/tasks'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faCalendarCheck } from '@fortawesome/free-solid-svg-icons' +import { CompleteButton } from './style/GlobalStyle'; + +export const CompleteAll = () => { + const dispatch = useDispatch(); + + const completeAllOnClick = () => { + dispatch(tasks.actions.allCompleteItem(true)); + } + + return ( + + ); +} diff --git a/code/src/components/DeleteAll.js b/code/src/components/DeleteAll.js new file mode 100644 index 000000000..b098b8745 --- /dev/null +++ b/code/src/components/DeleteAll.js @@ -0,0 +1,18 @@ +import React from 'react' +import { useDispatch } from 'react-redux' +import { tasks } from 'reducers/tasks'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faTrashCan } from '@fortawesome/free-solid-svg-icons' +import { DeleteAllButton } from './style/GlobalStyle'; + +export const DeleteAll = () => { + const dispatch = useDispatch(); + + const deleteAllOnClick = () => { + dispatch(tasks.actions.clearAllItems()); + } + + return ( + + ); +} \ No newline at end of file diff --git a/code/src/components/Header.js b/code/src/components/Header.js new file mode 100644 index 000000000..0a6294337 --- /dev/null +++ b/code/src/components/Header.js @@ -0,0 +1,14 @@ +import React from 'react' +import { WaveAnimation } from './WaveAnimation'; +import { HeaderWrapper, HeaderText } from './style/GlobalStyle'; + +export const Header = () => { + return ( + <> + + + TODO TODO TODO TODO TODO TODO TODO TODO TODO + + + ); +} \ No newline at end of file diff --git a/code/src/components/NewToDo.js b/code/src/components/NewToDo.js new file mode 100644 index 000000000..498364524 --- /dev/null +++ b/code/src/components/NewToDo.js @@ -0,0 +1,86 @@ +/* eslint-disable jsx-a11y/label-has-associated-control */ +import React, { useState } from 'react' +import { useDispatch } from 'react-redux' +import { tasks } from 'reducers/tasks' +import DatePicker from 'react-datepicker'; +import 'react-datepicker/dist/react-datepicker.css'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faPlus, faMinus } from '@fortawesome/free-solid-svg-icons' +import { TextInput, ToDoForm, FormButton } from './style/GlobalStyle'; + +export const NewToDo = () => { + const [inputValue, setInputValue] = useState(''); + const [showForm, setShowForm] = useState(false); + const [dueDate, setDueDate] = useState(''); + const dispatch = useDispatch(); + + const onFormSubmit = (event) => { + event.preventDefault(); + const newToDo = { + id: Date.now().toString(), + text: inputValue.charAt(0).toUpperCase() + inputValue.slice(1), + due: dueDate ? dueDate.toDateString() : '-', + complete: false, + priority: false + }; + dispatch(tasks.actions.addItem(newToDo)); + dispatch(tasks.actions.sortItems()); + setInputValue(''); + setDueDate(''); + } + + const handleShowForm = () => { + setShowForm(true) + } + + const handleHideForm = () => { + setShowForm(false) + } + + return ( + <> + {showForm && ( + <> + + + + + +
+
+ setDueDate(date)} + placeholderText="due..." + dateFormat="yyyy-MM-dd" /> +
+ +
+
+ + )} + {!showForm && ( + + + )} + + ) +} \ No newline at end of file diff --git a/code/src/components/ProjectToDoList.js b/code/src/components/ProjectToDoList.js new file mode 100644 index 000000000..7958dda5e --- /dev/null +++ b/code/src/components/ProjectToDoList.js @@ -0,0 +1,221 @@ +/* eslint-disable */ + +import React, { useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { addList, addItem, toggleItem, togglePriority, deleteItem, sortItems, sortPriority, deleteList } from 'reducers/projects'; +import uniqid from 'uniqid'; +import DatePicker from 'react-datepicker'; +import 'react-datepicker/dist/react-datepicker.css'; +import { compareAsc } from 'date-fns' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faChevronDown, faChevronUp, faPlus, faMinus, faFlag, faTrashCan } from '@fortawesome/free-solid-svg-icons' +import { TextInput, CounterText, ListHeaderButton, ProjectTitle, AddNewProjectContainer, AddButton, AddButton2, ProjectNameInput, ProjectNameContainer, ToDoForm, ToDoListWrapper, ToDoCard, ToDoInnerCard, ToDotext, ButtonsBox, DeleteButton, ProjectHeader, ProjectWrapper, FormButton, Duetext } from './style/GlobalStyle'; + +export const ProjectToDoList = () => { + const [projectCreated, setProjectCreated] = useState(false); + const [listNameCreated, setListNameCreated] = useState(false); + const [listName, setListName] = useState(''); + const [itemName, setItemName] = useState(''); + const [dueDate, setDueDate] = useState(''); + const [showForm, setShowForm] = useState(false); + const [projectActive, setProjectActive] = useState(true); + + const lists = useSelector((state) => state.projects.lists); + + const dispatch = useDispatch(); + + const handleAddList = () => { + dispatch(addList({ name: listName.charAt(0).toUpperCase() + listName.slice(1) })); + setListName(''); + setListNameCreated(true) + setProjectCreated(false) + }; + + const handleAddItem = (listIndex) => { + const newToDo = { + id: uniqid(), + text: itemName[listIndex].charAt(0).toUpperCase() + itemName[listIndex].slice(1), + due: dueDate ? dueDate.toDateString() : '-', + complete: false, + priority: false + }; + dispatch(addItem({ listIndex, item: newToDo })); + setItemName(''); + }; + + const handleWantNewProject = () => { + !projectCreated ? setProjectCreated(true) : setProjectCreated(!projectCreated) + }; + + const handleItemNameChange = (listIndex, value) => { + setItemName({ ...itemName, [listIndex]: value }); + } + + const handleProjectClick = (listIndex) => { + setProjectActive((prevProjectActive) => ({ + ...prevProjectActive, + [listIndex]: !prevProjectActive[listIndex], + })); + }; + + const onToDoToggle = (id, listIndex) => { + dispatch(toggleItem({ listIndex, itemId: id })); + dispatch(sortItems({ listIndex })); + dispatch(sortPriority({ listIndex })); +} + + const onTogglePriority = (id, listIndex) => { + dispatch(togglePriority({ listIndex, itemId: id })); + dispatch(sortPriority({ listIndex })); + dispatch(sortItems({ listIndex })); + }; + + const onToDoDelete = (id, listIndex) => { + dispatch(deleteItem({ listIndex, itemId: id })); + }; + + const deleteListByName = (list) => { + dispatch(deleteList({ name: list.name })); + } + + const handleShowForm = () => { + setShowForm(true) + } + + const handleHideForm = () => { + setShowForm(false) + } + + const colorsArray = ['#3d5a80', '#b8dee0', '#79c9b0', '#e8e863', '#e4d1f1', '#831e74', '#ffccb8'] + const a = Math.floor(Math.random() * colorsArray.length); + + return ( + <> + {listNameCreated && ( + + {Array.isArray(lists) && lists.map((list, listIndex) => ( + <> + + {list.name} +
+ {list.items.length} tasks + deleteListByName(list)}> + handleProjectClick(listIndex)}> + {projectActive[listIndex] ? ( + ) + : ()} + +
+
+ {projectActive[listIndex] && ( + <> + + {list.items.map((item) => ( + + +
+
+ onToDoToggle(item.id, listIndex)} /> +
+
+
+ {item.text} + {compareAsc(new Date(item.due), Date.now()) === -1 ? 'overdue' : `due: ${item.due}`} +
+
+ + onTogglePriority(item.id, listIndex)}> + + + onToDoDelete(item.id, listIndex)}> + + ✖️ + + + +
+ ))} +
+ {showForm && ( + + + + + +
+
+ setDueDate(date)} + placeholderText="Due" + dateFormat="yyyy-MM-dd" /> +
+ +
+
)} + {!showForm && ( + + + )} + + )} + + ))} +
)} + {projectCreated && ( + + setListName(e.target.value)} /> + + + + )} + + +

Create new project

+ +
+
+ + ); +} + diff --git a/code/src/components/TaskCounter.js b/code/src/components/TaskCounter.js new file mode 100644 index 000000000..5e9e523f2 --- /dev/null +++ b/code/src/components/TaskCounter.js @@ -0,0 +1,24 @@ +import React from 'react'; +import { useSelector } from 'react-redux'; +import { CounterText } from './style/GlobalStyle'; + +export const TaskCounter = () => { + const items = useSelector((store) => store.tasks.items) + const completed = items.filter((task) => task.complete); + + const doneTasks = () => { + if (items.length === 0) { + return '' + } else if (items.length === completed.length) { + return ( +

All done

) + } else { + return `${completed.length} / ${items.length} done` + } + } + return ( + + {doneTasks()} + + ) +} \ No newline at end of file diff --git a/code/src/components/ToDoList.js b/code/src/components/ToDoList.js new file mode 100644 index 000000000..dc78c2b51 --- /dev/null +++ b/code/src/components/ToDoList.js @@ -0,0 +1,102 @@ +/* eslint-disable jsx-a11y/label-has-associated-control */ +import React, { useState, useEffect } from 'react' +import { useSelector, useDispatch } from 'react-redux' +import uniqid from 'uniqid'; +import { tasks } from 'reducers/tasks'; +import { faChevronDown, faChevronUp, faFlag } from '@fortawesome/free-solid-svg-icons' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { compareAsc } from 'date-fns' +import { CompleteAll } from './CompleteAll'; +import { DeleteAll } from './DeleteAll'; +import { NewToDo } from './NewToDo'; +import { TaskCounter } from './TaskCounter' +import { ToDoCard, ToDoInnerCard, ToDoListWrapper, ListHeader, ListHeaderButton, ListFooter, ButtonsBox, ToDotext, ProjectTitle, DeleteButton, ProjectWrapper, Duetext } from './style/GlobalStyle'; + +export const ToDoList = () => { + const [listActive, setlistActive] = useState(false); + const allTasks = useSelector((store) => store.tasks.items) + const dispatch = useDispatch(); + + const onToDoDelete = (index) => { + dispatch(tasks.actions.deleteItem(index)); + }; + + const onToDoToggle = (id) => { + dispatch(tasks.actions.toggleItem(id)); + dispatch(tasks.actions.sortItems()); + dispatch(tasks.actions.sortPriority()); + }; + + const onTogglePriority = (id) => { + dispatch(tasks.actions.togglePriority(id)); + dispatch(tasks.actions.sortPriority()); + dispatch(tasks.actions.sortItems()); + }; + + useEffect(() => { + dispatch(tasks.actions.sortPriority()); + dispatch(tasks.actions.sortItems()); + }, [dispatch]); + + const toggleList = () => { + setlistActive(!listActive) + }; + + return ( + + + My to do list + + + {listActive ? ( + ) + : ()} + + + {listActive && ( + + {allTasks.map((todoItem, todoIndex) => ( + + +
+
+ onToDoToggle(todoItem.id)} /> +
+
+
+ {todoItem.text} + {compareAsc(new Date(todoItem.due), Date.now()) === -1 ? 'overdue' : `due: ${todoItem.due}`} +
+
+ + onTogglePriority(todoItem.id)}> + + + onToDoDelete(todoIndex)}> + + ✖️ + + + +
+ ))} + + + + + +
+ )} +
+ ) +} diff --git a/code/src/components/WaveAnimation.js b/code/src/components/WaveAnimation.js new file mode 100644 index 000000000..b81f1c153 --- /dev/null +++ b/code/src/components/WaveAnimation.js @@ -0,0 +1,16 @@ +import React from 'react'; +import styled from 'styled-components' + +export const Wave = styled.div` + background-image: url('https://i.postimg.cc/J7S1MkjS/wave-bot-copy.png'); +` + +export const WaveAnimation = () => { + return ( +
+
+ +
+
+ ) +} \ No newline at end of file diff --git a/code/src/components/style/GlobalStyle.js b/code/src/components/style/GlobalStyle.js new file mode 100644 index 000000000..29db4888a --- /dev/null +++ b/code/src/components/style/GlobalStyle.js @@ -0,0 +1,318 @@ +import styled, { createGlobalStyle } from 'styled-components'; + +export const GlobalStyles = createGlobalStyle` +*, +body { + margin: 0; + padding: 0; +} +` + +export const Main = styled.main` + margin: 30px 20px 40px 20px; + display: flex; + flex-direction: column; + gap: 15px; + + @media (min-width:744px) and (max-width:1280px){ + max-width: 533px; + margin: 45px auto 40px auto; + } + + @media (min-width:1280px){ + margin: 40px 20px 40px 20px; + flex-direction: row; + justify-content: center; + } +` + +/* WRAPPERS */ + +export const Wrapper = styled.div` + overflow: hidden; + margin: 0; +` + +export const ToDoListWrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +` + +export const ProjectWrapper = styled.div` + display: flex; + flex-direction: column; + gap: 15px; + + @media (min-width:1280px){ + width: 313.984px; + } +` + +export const ToDoCard = styled.div` + display: flex; + justify-content: space-between; + padding: 10px; + position: relative; + background-color: oldlace; +` + +export const ToDoInnerCard = styled.div` + display: flex; + gap: 10px; +` + +export const ListHeader = styled.div` + display: flex; + justify-content: flex-end; + align-items: center; + padding: 10px; + justify-content: space-between; + background: pink; +` + +export const ProjectHeader = styled.div` + display: flex; + justify-content: flex-end; + align-items: center; + padding: 10px; + justify-content: space-between; +` + +export const ListFooter = styled.div` + display: flex; + gap: 10px; + justify-content: flex-end; + align-items: center; + padding: 10px; + background: pink; + height: 29.5px; +` + +export const ButtonsBox = styled.div` + display: flex; + gap: 10px; + justify-content: flex-end; + align-items: center; +` + +export const AddNewProjectContainer = styled.div` + display: flex; + height: 29.5px; + padding: 10px; + gap: 10px; + align-items: center; + background: #E8E8E8; + + @media (min-width:1280px){ + width: 293.977px; + } +` +export const ProjectNameContainer = styled.div` + display: flex; + height: 27.5px; + padding: 10px; + justify-content: space-between; + align-items: center; + background: transparent; + border: 1px solid #f85f36; + + &:hover { + border: 1px solid pink; + } + + @media (min-width:1280px){ + width: 291.977px; + } +` + +export const HeaderWrapper = styled.div` + width: 100%; + height: 70px; +` + +/* HEADLINES AND PARAGRAPH */ + +export const HeaderText = styled.h2` + font-family: "Raleway", sans-serif; + white-space: nowrap; + color: white; + letter-spacing: 3px; + text-align: center; + font-weight: 900; + margin: 0; + padding-top: 10px; + font-size: 50px; + text-align: center; +` + +export const ProjectTitle = styled.h3` + margin: 0; + color: #f85f36; + margin: auto 0; + font-weight: 700; + font-size: 25px; +` + +export const ToDotext = styled.p` + margin: 0; + color: #464646; + margin: auto 0; + font-weight: 700; + word-break: break-word; +` + +export const Duetext = styled.p` + margin: 0; + color: #464646; + font-weight: 300; + opacity: 0.7; + margin: 5px 0 auto 0; + font-weight: 700; + word-break: break-word; + font-size: 14px; +` + +export const CounterText = styled.p` + font-family: "Raleway", sans-serif; + font-size: 1em; + display: flex; + margin: 0; + color: #f85f36; +` + +/* BUTTONS */ + +export const ListHeaderButton = styled.button` + background: transparent; + border: none; + outline: none; + cursor: pointer; + display: flex; + align-items: center; + justify-content: space-between; + color: pink; + font-weight: 900; +` + +export const AddButton = styled.button` + width: 100%; + background: transparent; + border: none; + outline: none; + justify-content: space-between; + cursor: pointer; + display: flex; + align-items: center; + color: #f85f36; + font-weight: 900; +` + +export const AddButton2 = styled.button` + width: 50%; + background: transparent; + border: none; + outline: none; + justify-content: flex-end; + cursor: pointer; + display: flex; + align-items: center; + color: #f85f36; + font-weight: 900; +` + +export const FormButton = styled.button` + width: 100%; + background: transparent; + border: none; + outline: none; + justify-content: center; + cursor: pointer; + display: flex; + align-items: center; + color: #f85f36; + font-weight: 900; +` + +export const CompleteButton = styled.button` + background: transparent; + border: none; + outline: none; + cursor: pointer; + display: flex; + align-items: center; + gap: 10px; + color: #f85f36; + font-weight: 900; + + &:hover:after { + content: 'check all'; + } +` + +export const DeleteButton = styled.button` + cursor: pointer; + background: transparent; + outline: none; + border: none; +` + +export const DeleteAllButton = styled.button` + background: transparent; + border: none; + outline: none; + cursor: pointer; + display: flex; + align-items: center; + gap: 10px; + color: #f85f36; + font-weight: 900; + + &:hover:after { + content: 'delete all'; + } +` + +/* FORMS */ + +export const ToDoForm = styled.form` + display: flex; + flex-direction: column; + gap: 15px; +` + +export const TextInput = styled.input` + background: #FFFFFF; + border: 2px solid #f85f36; + outline: none; + border-radius: 8px; + height: 48px; + width: 100%; + box-sizing: border-box; + padding: 5px 15px; + font-size: 18px; + + &:focus { + outline: none; + caret-color: #f85f36; + } + + &:hover { + border: 2px solid pink; + } +` + +export const ProjectNameInput = styled.input` + background: transparent; + border: none; + outline: none; + height: 100%; + width: fit-content; + box-sizing: border-box; + color:#f85f36; + font-size: 20px; + + &:focus { + caret-color: #f85f36; + } +` diff --git a/code/src/index.css b/code/src/index.css index 4a1df4db7..23f0a8044 100644 --- a/code/src/index.css +++ b/code/src/index.css @@ -1,8 +1,9 @@ +@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@300;400;500;700;900&display=swap'); + body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: 'Raleway', sans-serif; + font-weight: 500; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } @@ -11,3 +12,169 @@ code { font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } + +@keyframes move_wave { + 0% { + transform: translateX(0) translateZ(0) scaleY(1) + } + 50% { + transform: translateX(-25%) translateZ(0) scaleY(0.55) + } + 100% { + transform: translateX(-50%) translateZ(0) scaleY(1) + } +} +.waveWrapper { + z-index: -1; + overflow: hidden; + position: absolute; + left: 0; + right: 0; + bottom: 0; + top: 0; + margin: auto; + transform: scaleY(-1); +} +.waveWrapperInner { + position: absolute; + width: 400%; + overflow: hidden; + height: 400%; + bottom: -1px; +} +.bgMiddle { + z-index: 10; +} +.bgBottom { + z-index: 5; +} +.wave { + position: absolute; + left: 0; + width: 200%; + height: 100%; + background-repeat: repeat no-repeat; + background-position: 0 bottom; + transform-origin: center bottom; +} + +.waveMiddle { + background-size: 50% 120px; +} +.waveAnimation .waveMiddle { + animation: move_wave 20s linear infinite; +} +.waveBottom { + background-size: 50% 100px; +} +.waveAnimation .waveBottom { + animation: move_wave 15s linear infinite; +} + +.round { + position: relative; + height: 28px; + width: 28px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.round label { + background-color: #fff; + border: 2px solid #f85f36; + border-radius: 50%; + cursor: pointer; + height: 28px; + left: 0; + position: absolute; + top: 0; + width: 28px; +} + +.round label:after { + border: 2px solid #fff; + border-top: none; + border-right: none; + content: ""; + height: 6px; + left: 7px; + opacity: 0; + position: absolute; + top: 8px; + transform: rotate(-45deg); + width: 12px; +} + +.round input[type="checkbox"] { + visibility: hidden; +} + +.round input[type="checkbox"]:checked + label { + background-color: #f85f36; + border-color: #f85f36; +} + +.round input[type="checkbox"]:checked + label:after { + opacity: 1; +} + +.submit-button { + font-size: 1rem; + padding: 0.8em 1.5em; + background-color: pink; + border: 3px solid #f85f36; + border-radius: 8px; + font-family: "Raleway", sans-serif; + font-weight: 900; + color: #f85f36; + transition: cubic-bezier(0.68, -0.55, 0.265, 1.55) 0.4s; + box-shadow: -5px 5px 0px 0px #f85f36; + cursor: pointer; + letter-spacing: 1px; + height: 56px; + width: 100%; +} + +.submit-button:hover { + transform: translate(5px, -5px); + background-color: #f85f36; + border: 3px solid pink; + color: pink; + box-shadow: -5px 5px 0px 0px pink; +} + +::placeholder { + color: #f85f36; + opacity: 0.7; +} + +:-ms-input-placeholder { + color: #f85f36; +} + +::-ms-input-placeholder { + color: #f85f36; +} + +#datePicker { + padding: 10px; + border-radius: 8px; + cursor: pointer; + border: 2px solid #f85f36; + font-weight: 500; + outline: none; + font-family: 'Raleway', sans-serif; + box-sizing: border-box; + width: 100%; + } + + #datePicker:hover { + border: 2px solid pink; + } + + .react-datepicker__input-container { + display: flex; + margin:0; + padding:0; + } \ No newline at end of file diff --git a/code/src/reducers/projects.js b/code/src/reducers/projects.js new file mode 100644 index 000000000..aedf76480 --- /dev/null +++ b/code/src/reducers/projects.js @@ -0,0 +1,118 @@ + +/* eslint-disable */ +import { createSlice } from '@reduxjs/toolkit'; + +const initialState = { + lists: [] +}; + +export const projects = createSlice({ + name: 'projects', + initialState, + + reducers: { + addList: (state, action) => { + const { name } = action.payload; + const newList = { name, items: [] }; + return { ...state, lists: [...state.lists, newList] }; + }, + deleteList: (state, action) => { + const { name } = action.payload; + const listIndex = state.lists.findIndex((list) => list.name === name); + if (listIndex === -1) { + return state; + } + const updatedLists = [ + ...state.lists.slice(0, listIndex), + ...state.lists.slice(listIndex + 1) + ]; + return { ...state, lists: updatedLists }; + }, + addItem: (state, action) => { + const { listIndex, item } = action.payload; + const listToUpdate = state.lists[listIndex]; + const updatedList = { ...listToUpdate, items: [...listToUpdate.items, item] }; + const updatedLists = [...state.lists.slice(0, listIndex), updatedList, ...state.lists.slice(listIndex + 1)]; + return { ...state, lists: updatedLists }; + }, + + deleteItem: (state, action) => { + const { listIndex, itemId } = action.payload; + const listToUpdate = state.lists[listIndex]; + const updatedItems = listToUpdate.items.filter((item) => item.id !== itemId); + const updatedList = { ...listToUpdate, items: updatedItems }; + const updatedLists = [...state.lists.slice(0, listIndex), updatedList, ...state.lists.slice(listIndex + 1)]; + return { ...state, lists: updatedLists }; + }, + + toggleItem: (state, action) => { + const { listIndex, itemId } = action.payload; + const listToUpdate = state.lists[listIndex]; + const itemToUpdate = listToUpdate.items.find((item) => item.id === itemId); + if (itemToUpdate) { + itemToUpdate.complete = !itemToUpdate.complete; + } + }, + togglePriority: (state, action) => { + const { listIndex, itemId } = action.payload; + const listToUpdate = state.lists[listIndex]; + const itemToUpdate = listToUpdate.items.find((item) => item.id === itemId); + if (itemToUpdate) { + itemToUpdate.priority = !itemToUpdate.priority; + } + }, + sortItems: (state, action) => { + const { listIndex } = action.payload; + const listToUpdate = state.lists[listIndex]; + if (!listToUpdate) { + return state; + } + const sortedItems = [...listToUpdate.items]; + sortedItems.sort((a, b) => { + if (a.complete && !b.complete) { + return 1; + } else if (!a.complete && b.complete) { + return -1; + } else { + return 0; + } + }); + const updatedList = { ...listToUpdate, items: sortedItems }; + const updatedLists = [ + ...state.lists.slice(0, listIndex), + updatedList, + ...state.lists.slice(listIndex + 1) + ]; + return { ...state, lists: updatedLists }; + }, + + sortPriority: (state, action) => { + const { listIndex } = action.payload; + const listToUpdate = state.lists[listIndex]; + if (!listToUpdate) { + return state; + } + const sortedItems = [...listToUpdate.items]; + sortedItems.sort((a, b) => { + if (!a.priority && b.priority) { + return 1; + } else if (a.priority && !b.priority) { + return -1; + } else { + return 0; + } + }); + const updatedList = { ...listToUpdate, items: sortedItems }; + const updatedLists = [ + ...state.lists.slice(0, listIndex), + updatedList, + ...state.lists.slice(listIndex + 1) + ]; + return { ...state, lists: updatedLists }; + } + } +}); + +export const { addList, addItem, toggleItem, togglePriority, deleteItem, sortItems, sortPriority, deleteList } = projects.actions; + +export default projects.reducer; diff --git a/code/src/reducers/tasks.js b/code/src/reducers/tasks.js new file mode 100644 index 000000000..eb91f0270 --- /dev/null +++ b/code/src/reducers/tasks.js @@ -0,0 +1,78 @@ + +/* eslint-disable */ + +import { createSlice } from '@reduxjs/toolkit'; + +const initialState = { + items: [ + { id: 1, text: 'Sleep', due: 'Thu Apr 27 2023', complete: false, priority: false }, + { id: 2, text: 'Call my boyfriend', due: 'Thu Apr 27 2023', complete: false, priority: true }, + { id: 3, text: 'Take a bath', due: 'Thu Apr 27 2023', complete: true, priority: false }, + { id: 4, text: 'Go to Friskis&Svettis', due: 'Thu Apr 27 2023', complete: false, priority: false } + ] +} + +export const tasks = createSlice({ + name: 'tasks', + initialState, + reducers: { + + addItem: (store, action) => { + store.items = [...store.items, action.payload]; + }, + + deleteItem: (store, action) => { + store.items.splice(action.payload, 1); + }, + + toggleItem: (state, action) => { + const item = state.items.find((item) => item.id === action.payload); + if (item) { + item.complete = !item.complete; + } + }, + + togglePriority: (state, action) => { + const item = state.items.find((item) => item.id === action.payload); + if (item) { + item.priority = !item.priority; + } + }, + + sortItems: (state, action) => { + const item = state.items.find((item) => item.id === action.payload); + state.items.sort((a, b) => { + if (a.complete && !b.complete) { + return 1; + } else if (!a.complete && b.complete) { + return -1; + } else { + return 0; + } + }); + }, + + sortPriority: (state, action) => { + const item = state.items.find((item) => item.id === action.payload); + state.items.sort((a, b) => { + if (!a.priority && b.priority) { + return 1; + } else if (a.priority && !b.priority) { + return -1; + } else { + return 0; + } + }); + }, + + allCompleteItem: (store, action) => { + store.items = store.items.map((item) => { + return { ...item, complete: action.payload}; + }); + }, + + clearAllItems: (store, action) => { + store.items.splice(action.payload); + } + } +}); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..e69de29bb