├── .gitignore
├── README.md
├── assets
└── images
│ ├── React-Cdoing-Challenges.png
│ ├── memory-game-react.png
│ ├── react-random-password-generator.png
│ ├── react-random-quote-generator.png
│ ├── react-typescript-todo-list.png
│ └── reactjs-text-analyzer-result.png
├── memory-marvel
├── .eslintrc.cjs
├── .gitignore
├── .prettierignore
├── .prettierrc
├── README.md
├── index.html
├── package-lock.json
├── package.json
├── public
│ └── vite.svg
├── src
│ ├── App.css
│ ├── App.tsx
│ ├── assets
│ │ ├── icons
│ │ │ ├── airplane.svg
│ │ │ ├── bath-tub.svg
│ │ │ ├── card-front.svg
│ │ │ ├── card.svg
│ │ │ ├── cocktail.svg
│ │ │ ├── emoji.svg
│ │ │ ├── flip.svg
│ │ │ ├── hotel.svg
│ │ │ ├── medal.svg
│ │ │ ├── modal-icon.png
│ │ │ ├── modal-icon.svg
│ │ │ ├── number.svg
│ │ │ ├── play.svg
│ │ │ ├── polaroid.svg
│ │ │ ├── refresh.svg
│ │ │ ├── stars-empty.svg
│ │ │ ├── stars-filled.svg
│ │ │ ├── stopwatch.svg
│ │ │ ├── surf.svg
│ │ │ └── timer.svg
│ │ ├── images
│ │ │ └── bg-cover.png
│ │ └── react.svg
│ ├── components
│ │ ├── Card
│ │ │ ├── Card.tsx
│ │ │ └── style.css
│ │ ├── GameInfo
│ │ │ ├── GameInfo.tsx
│ │ │ └── style.css
│ │ ├── GameModal
│ │ │ ├── GameModal.tsx
│ │ │ └── style.css
│ │ ├── Header
│ │ │ └── Header.tsx
│ │ └── ScoreCard
│ │ │ └── ScoreCard.tsx
│ ├── config
│ │ └── icons.ts
│ ├── data
│ │ └── index.ts
│ ├── main.tsx
│ └── vite-env.d.ts
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
├── online-word-sentences-counter
├── .gitignore
├── .prettierrc
├── README.md
├── eslint.config.js
├── index.html
├── package-lock.json
├── package.json
├── public
│ └── vite.svg
├── src
│ ├── App.scss
│ ├── App.tsx
│ ├── assets
│ │ ├── fonts
│ │ │ ├── poppins-v20-latin-200.woff
│ │ │ ├── poppins-v20-latin-200.woff2
│ │ │ ├── poppins-v20-latin-300.woff
│ │ │ ├── poppins-v20-latin-300.woff2
│ │ │ ├── poppins-v20-latin-500.woff
│ │ │ ├── poppins-v20-latin-500.woff2
│ │ │ ├── poppins-v20-latin-600.woff
│ │ │ ├── poppins-v20-latin-600.woff2
│ │ │ ├── poppins-v20-latin-700.woff
│ │ │ ├── poppins-v20-latin-700.woff2
│ │ │ ├── poppins-v20-latin-regular.woff
│ │ │ └── poppins-v20-latin-regular.woff2
│ │ ├── icons
│ │ │ ├── linkedin.svg
│ │ │ ├── twitter.svg
│ │ │ └── website.svg
│ │ └── images
│ │ │ └── appCover.png
│ ├── components
│ │ ├── BottomResultBox
│ │ │ ├── index.scss
│ │ │ └── index.tsx
│ │ ├── Footer
│ │ │ ├── index.scss
│ │ │ └── index.tsx
│ │ ├── Navbar
│ │ │ ├── index.scss
│ │ │ └── index.tsx
│ │ ├── ResultBox
│ │ │ ├── index.scss
│ │ │ └── index.tsx
│ │ └── TextArea
│ │ │ ├── index.scss
│ │ │ └── index.tsx
│ ├── data
│ │ └── pronouns.ts
│ ├── main.tsx
│ ├── styles
│ │ ├── breakpoints.scss
│ │ ├── fonts.scss
│ │ ├── index.scss
│ │ ├── reset.scss
│ │ └── theme.scss
│ └── vite-env.d.ts
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
├── password-generator
├── .eslintrc.cjs
├── .gitignore
├── .prettierrc
├── README.md
├── index.html
├── package-lock.json
├── package.json
├── public
│ └── vite.svg
├── src
│ ├── App.tsx
│ ├── assets
│ │ ├── gif
│ │ │ └── password.gif
│ │ ├── icons
│ │ │ ├── copy.svg
│ │ │ └── refresh.svg
│ │ └── react.svg
│ ├── components
│ │ ├── Checkbox
│ │ │ ├── index.css
│ │ │ └── index.tsx
│ │ └── PasswordGenerator
│ │ │ ├── index.css
│ │ │ └── index.tsx
│ ├── main.tsx
│ ├── styles.css
│ ├── variables.css
│ └── vite-env.d.ts
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
├── random-quote-generator
├── .prettierrc
├── README.md
├── db.json
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── App.css
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── assets
│ │ └── icons
│ │ │ ├── button.svg
│ │ │ ├── quotation.svg
│ │ │ ├── twitter.svg
│ │ │ └── whatsapp.svg
│ ├── index.tsx
│ ├── logo.svg
│ ├── react-app-env.d.ts
│ ├── reportWebVitals.ts
│ └── setupTests.ts
└── tsconfig.json
└── task-list
├── .prettierrc
├── README.md
├── package-lock.json
├── package.json
├── public
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
├── src
├── App.scss
├── App.test.tsx
├── App.tsx
├── assets
│ ├── fonts
│ │ ├── poppins-v20-latin-200.woff
│ │ ├── poppins-v20-latin-200.woff2
│ │ ├── poppins-v20-latin-300.woff
│ │ ├── poppins-v20-latin-300.woff2
│ │ ├── poppins-v20-latin-500.woff
│ │ ├── poppins-v20-latin-500.woff2
│ │ ├── poppins-v20-latin-600.woff
│ │ ├── poppins-v20-latin-600.woff2
│ │ ├── poppins-v20-latin-700.woff
│ │ ├── poppins-v20-latin-700.woff2
│ │ ├── poppins-v20-latin-regular.woff
│ │ └── poppins-v20-latin-regular.woff2
│ └── icons
│ │ ├── add.svg
│ │ ├── arrow.svg
│ │ ├── close.svg
│ │ ├── delete.svg
│ │ ├── drop-down.svg
│ │ └── edit.svg
├── components
│ ├── AddEditTaskForm
│ │ ├── index.tsx
│ │ └── style.scss
│ ├── Button
│ │ ├── index.tsx
│ │ └── style.scss
│ ├── CircularProgressBar
│ │ ├── index.tsx
│ │ └── style.scss
│ ├── DeleteModal
│ │ ├── index.tsx
│ │ └── style.scss
│ ├── Input
│ │ ├── index.tsx
│ │ └── style.scss
│ ├── Modal
│ │ ├── index.tsx
│ │ └── style.scss
│ └── TaskCard
│ │ ├── index.tsx
│ │ └── style.scss
├── index.tsx
├── logo.svg
├── react-app-env.d.ts
├── reportWebVitals.ts
├── setupTests.ts
├── siteData
│ └── taskList.ts
└── styles
│ ├── breakpoints.scss
│ ├── fonts.scss
│ ├── index.scss
│ ├── reset.scss
│ └── theme.scss
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Free ReactJS Coding Challenges: Build Functionality for Responsive UI
2 |
3 | 
4 |
5 | This repository contains a collection of free ReactJS coding challenges designed to help developers improve their ReactJS logic-building skills and create functionality for responsive UI. The challenges are built using **ReactJS with TypeScript.**
6 |
7 | | Title | Objective | Description | Demo Link |
8 | | --------------------------------------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
9 | | Challenge #1: Word and Sentences Counter Tool | A text area that calculates parameters of the typed or pasted text | [Challenge Description](https://www.codevertiser.com/react-online-word-sentences-counter/) | [Live Demo](https://reactjs-text-analyzer.netlify.app/) |
10 | | Challenge #2: React Password Generator | Logic for generating and validating passwords with specified strength | [Challenge Description](https://www.codevertiser.com/react-password-generator/) | [Live Demo](https://reactjs-password-generator.vercel.app/) |
11 | | Challenge #3: React Random Quote Generator | Fetching and displaying random quotes using ReactJS | [Challenge Description](https://www.codevertiser.com/reactjs-challenge-3-random-quote-generator/) | [Live Demo](https://react-random-quote-application.netlify.app/) |
12 | | Challenge #4: CRUD Typescript Tasklist App | Perform CRUD operations in a tasklist app using React and TypeScript | [Challenge Description](https://www.codevertiser.com/reactjs-challenge-4-crud-tasklist-app/) | [Live Demo](https://react-tasklist.vercel.app) |
13 | | Challenge #5: Memory Game React | Write a logic for versatile memory game in Reactjs | [Challenge Description](https://www.codevertiser.com/memory-game-react/) | [Live Demo](https://memory-marvel.vercel.app/) |
14 |
15 | ## Who Can Use these ReactJS Coding Challenges?
16 |
17 | 1. Beginner developers looking for a fun little **frontend coding challenges** to test their **ReactJS logic-building** skills
18 |
19 | 2. Developers interested in building small tools that they can convert into **micro SAAS**
20 |
21 | 3. Companies looking for **ReactJS hiring challenges** to assess their candidate's ReactJS coding skills
22 |
23 | ## List of Reactjs Challenges
24 |
25 | All challenges are free. I wanted the challenges to be different and designed them carefully. In each challenge, I have covered different skill sets of JavaScript and Reactjs, from the array to object, the string to regex, and Reactjs hooks.
26 |
27 | ## Challenge #1: Introduction to Word and Sentences Counter Tool
28 |
29 | 
30 |
31 | The text analyzer (word and sentences counter) is the first in the series of ReactJS coding challenges. In this challenge, we have created a text area that calculates some parameters in the typed or pasted Text. The text area should calculate and show the following:
32 |
33 | 1. Words
34 | 2. Characters
35 | 3. Sentences
36 | 4. Paragraphs
37 | 5. Average reading time
38 | 6. The longest word in paragraphs
39 | 7. Number of pronouns in the Text (list is given)
40 |
41 | **Read the Challenge [Description](https://www.codevertiser.com/react-online-word-sentences-counter/)**
42 |
43 | **Objective:** To make each feature of app functional. [This](https://reactjs-text-analyzer.netlify.app/) is a live link of demo app.
44 |
45 | ## Challenge #2: React Password Generator
46 |
47 | 
48 |
49 | This challenge is suitable for beginners as well. In this challenge, you will develop logic for a password generator, including options for creating and validating a password with a specified strength, copying the password, and passwords with desired characters.
50 |
51 | **Read the Challenge [Description](https://www.codevertiser.com/react-password-generator/)**
52 |
53 | **Objective:** To make a functional app. This is a [live](https://reactjs-password-generator.vercel.app/) link.
54 |
55 | ## Challenge #3: React Random Quote Generator
56 |
57 | 
58 |
59 | Challenge yourself to build a random quote generator using ReactJS and showcase your front-end development skills. Flourish your creativity with this fun code challenge!
60 |
61 | This challenge differs slightly from Text Analyzer and Password Generator because you need to fetch data from json-server using Axios.
62 |
63 | **Read the Challenge [Description](https://www.codevertiser.com/reactjs-challenge-3-random-quote-generator/)**
64 |
65 | **Objective:** To make a functional app. This is a [live](https://react-random-quote-application.netlify.app/) link.
66 |
67 | ## ReactJS Challenge #4: CRUD Typescript Tasklist App
68 |
69 | 
70 |
71 | This React Typescript Tasklist/Todo challenge requires you to perform CRUD operations with instructions to write clean, reusable, manageable, and scalable code.
72 |
73 | CRUD refers to create, read, update, and delete. Mastering these operations in Reactjs means you can build any application.
74 |
75 | This challenge is different and more challenging than the last three challenges you have completed. If you can complete this ReactJS Typescript Tasklist challenge independently, you can be easily hired as an intern/junior React developer.
76 |
77 | This is not just a challenge, but my 3 years of working experience. The tasks you will be performing in this challenge are what a React developer performs daily. So, let's dive in and improve your React development skills!
78 |
79 | **Read the Challenge [Description](https://www.codevertiser.com/reactjs-challenge-4-crud-tasklist-app/)**
80 |
81 | **Objective:** To make a functional app. This is a [live](https://react-tasklist.vercel.app) link.
82 |
83 | ## Challenge #5: Memory Marvel [Memory Game]
84 |
85 | 
86 |
87 | Do you wonder how **Memory Game logic** works or want to write your own using ReactJS?
88 |
89 | For the 5th challenge, I decided to add an interesting game: the Memory Game, I named it **Memory Marvel**.
90 |
91 | This challenge is specially designed to test your **JavaScript and React logics**.
92 |
93 | **Read the Challenge [Description](https://www.codevertiser.com/memory-game-react/)**
94 |
95 | **Objective:** To make a functional app. This is a [live](https://memory-marvel.vercel.app/) link.
96 |
97 | ## Can you star the ReactJS Challenges GitHub repo?
98 |
99 | I love creating free content that helps developers start their jobs and excel in their careers. Each challenge requires a lot of time to create.
100 |
101 | First, I brainstorm the challenge idea. Then, I collaborate with a freelance UI/UX designer to design the idea. After that, I convert the design into code and write content for the challenge.
102 |
103 | It's a lengthy process that requires time, energy, and resources.
104 |
105 | By starring this ReactJS Challenges repository, you will motivate me to create more free content like this.
106 |
107 | ## Need Help or Working Code?
108 |
109 | Ideally, you should finish these challenges on your own regardless of how long it takes, as figuring it out on your own would help hone your skills as a front-end and ReactJS developer. However, you can see hints if you are stuck somewhere in the middle. Hints will give you a better idea about how to write logic.
110 |
111 | Get working code like you've seen in the demo apps, for FREE!
112 |
113 | [Download from Gumroad now!](https://basit313.gumroad.com/l/learn-react-with-mini-projects)
114 |
115 | For suggestions and collaboration, you can send me an email at abdul_basit313@outlook.com or can reach out to me on [LinkedIn](https://www.linkedin.com/in/abdulbasitprofile/) or [Twitter](https://twitter.com/Basit_Miyanji).
116 |
117 | [Here](https://www.codevertiser.com/free-reactjs-coding-challenges-for-responsive-UI/) you can read the intro article of ReactJS Challenges.
118 |
--------------------------------------------------------------------------------
/assets/images/React-Cdoing-Challenges.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/assets/images/React-Cdoing-Challenges.png
--------------------------------------------------------------------------------
/assets/images/memory-game-react.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/assets/images/memory-game-react.png
--------------------------------------------------------------------------------
/assets/images/react-random-password-generator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/assets/images/react-random-password-generator.png
--------------------------------------------------------------------------------
/assets/images/react-random-quote-generator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/assets/images/react-random-quote-generator.png
--------------------------------------------------------------------------------
/assets/images/react-typescript-todo-list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/assets/images/react-typescript-todo-list.png
--------------------------------------------------------------------------------
/assets/images/reactjs-text-analyzer-result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/assets/images/reactjs-text-analyzer-result.png
--------------------------------------------------------------------------------
/memory-marvel/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true },
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:@typescript-eslint/recommended',
7 | 'plugin:react-hooks/recommended',
8 | ],
9 | ignorePatterns: ['dist', '.eslintrc.cjs'],
10 | parser: '@typescript-eslint/parser',
11 | plugins: ['react-refresh'],
12 | rules: {
13 | 'react-refresh/only-export-components': [
14 | 'warn',
15 | { allowConstantExport: true },
16 | ],
17 | },
18 | }
19 |
--------------------------------------------------------------------------------
/memory-marvel/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/memory-marvel/.prettierignore:
--------------------------------------------------------------------------------
1 | # directories
2 | .yarn/
3 | **/build
4 | **/dist
5 | **/node_modules
6 |
7 | # files
8 | *.env
9 | *.log
10 | *.tsbuildinfo
11 | .pnp.*
12 | npm-debug.log*
13 | yarn-debug.log*
14 | yarn-error.log*
15 | README.md
--------------------------------------------------------------------------------
/memory-marvel/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "singleQuote": true,
4 | "tabWidth": 2,
5 | "printWidth": 90
6 | }
7 |
--------------------------------------------------------------------------------
/memory-marvel/README.md:
--------------------------------------------------------------------------------
1 | # React + TypeScript + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
10 | ## Expanding the ESLint configuration
11 |
12 | If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13 |
14 | - Configure the top-level `parserOptions` property like this:
15 |
16 | ```js
17 | parserOptions: {
18 | ecmaVersion: 'latest',
19 | sourceType: 'module',
20 | project: ['./tsconfig.json', './tsconfig.node.json'],
21 | tsconfigRootDir: __dirname,
22 | },
23 | ```
24 |
25 | - Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
26 | - Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
27 | - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
28 |
--------------------------------------------------------------------------------
/memory-marvel/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Memory Marvel
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/memory-marvel/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "memory-game",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "react": "^18.2.0",
14 | "react-dom": "^18.2.0"
15 | },
16 | "devDependencies": {
17 | "@types/react": "^18.2.15",
18 | "@types/react-dom": "^18.2.7",
19 | "@typescript-eslint/eslint-plugin": "^6.0.0",
20 | "@typescript-eslint/parser": "^6.0.0",
21 | "@vitejs/plugin-react": "^4.0.3",
22 | "eslint": "^8.45.0",
23 | "eslint-plugin-react-hooks": "^4.6.0",
24 | "eslint-plugin-react-refresh": "^0.4.3",
25 | "typescript": "^5.0.2",
26 | "vite": "^4.4.5"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/memory-marvel/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/memory-marvel/src/App.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@300;400;500;600;700&display=swap');
2 |
3 | * {
4 | margin: 0;
5 | padding: 0;
6 | box-sizing: border-box;
7 | }
8 |
9 | body {
10 | font-family: 'Quicksand', sans-serif;
11 | background-image: url('../src/assets/images/bg-cover.png');
12 | display: flex;
13 | place-items: center;
14 | min-height: 100vh;
15 | }
16 |
17 | #root {
18 | max-width: 900px;
19 | width: 100%;
20 | margin: 0 auto;
21 | padding: 15px;
22 | }
23 |
24 | .title {
25 | color: #fff;
26 | font-size: 40px;
27 | font-weight: 700;
28 | text-align: center;
29 | margin-bottom: 50px;
30 | letter-spacing: 2px;
31 | }
32 |
33 | .cards-container {
34 | display: grid;
35 | grid-template-columns: repeat(5, 1fr);
36 | grid-gap: 25px;
37 | }
38 |
39 | .flex-center {
40 | display: flex;
41 | justify-content: center;
42 | align-items: center;
43 | flex-direction: column;
44 | }
45 |
46 | @media screen and (max-width: 900px) {
47 | .cards-container {
48 | display: grid;
49 | grid-template-columns: repeat(3, 1fr);
50 | grid-gap: 20px;
51 | justify-items: center;
52 | }
53 | .title {
54 | font-size: 32px;
55 | font-weight: 700;
56 | margin-bottom: 50px;
57 | letter-spacing: 2px;
58 | margin-top: 20px;
59 | }
60 | }
61 |
62 | @media screen and (max-width: 600px) {
63 | .cards-container {
64 | display: grid;
65 | grid-template-columns: repeat(2, 1fr);
66 | grid-gap: 20px;
67 | justify-items: center;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/memory-marvel/src/App.tsx:
--------------------------------------------------------------------------------
1 | import './App.css'
2 | import Card from './components/Card/Card'
3 | import GameInfo from './components/GameInfo/GameInfo'
4 | import GameModal from './components/GameModal/GameModal'
5 | import Header from './components/Header/Header'
6 | import shapes from './data'
7 |
8 | function App() {
9 | const showModal = false
10 |
11 | return (
12 |
13 |
14 |
15 |
16 | {shapes.map(({ shapeId, uniqueId, shape }) => (
17 | {}}
23 | />
24 | ))}
25 |
26 | {showModal && (
27 |
{}} />
28 | )}
29 |
30 | )
31 | }
32 |
33 | export default App
34 |
--------------------------------------------------------------------------------
/memory-marvel/src/assets/icons/airplane.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/memory-marvel/src/assets/icons/bath-tub.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/memory-marvel/src/assets/icons/card-front.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/memory-marvel/src/assets/icons/cocktail.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/memory-marvel/src/assets/icons/emoji.svg:
--------------------------------------------------------------------------------
1 |
66 |
--------------------------------------------------------------------------------
/memory-marvel/src/assets/icons/hotel.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/memory-marvel/src/assets/icons/modal-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/memory-marvel/src/assets/icons/modal-icon.png
--------------------------------------------------------------------------------
/memory-marvel/src/assets/icons/number.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/memory-marvel/src/assets/icons/play.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/memory-marvel/src/assets/icons/polaroid.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/memory-marvel/src/assets/icons/refresh.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/memory-marvel/src/assets/icons/surf.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/memory-marvel/src/assets/images/bg-cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/memory-marvel/src/assets/images/bg-cover.png
--------------------------------------------------------------------------------
/memory-marvel/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/memory-marvel/src/components/Card/Card.tsx:
--------------------------------------------------------------------------------
1 | import { cardFront } from '../../config/icons'
2 | import './style.css'
3 |
4 | const Card = ({ uniqueId, shape }: any) => {
5 | return (
6 |
7 |
8 |
9 |

10 |
11 |
12 |

13 |
14 |
15 |
16 | )
17 | }
18 |
19 | export default Card
20 |
--------------------------------------------------------------------------------
/memory-marvel/src/components/Card/style.css:
--------------------------------------------------------------------------------
1 | .memory-card {
2 | width: 150px;
3 | height: 150px;
4 | border-radius: 20px;
5 | background: #fff;
6 | cursor: pointer;
7 | position: relative;
8 | }
9 |
10 | .card-content {
11 | width: 100%;
12 | height: 100%;
13 | transition: transform 0.5s;
14 | transform-style: preserve-3d;
15 | }
16 |
17 | .memory-card.flipped .card-content {
18 | transform: rotateY(180deg);
19 | }
20 |
21 | .card-front,
22 | .card-back {
23 | width: 100%;
24 | border-radius: 14px;
25 | height: 100%;
26 | position: absolute;
27 | backface-visibility: hidden;
28 | display: flex;
29 | justify-content: center;
30 | align-items: center;
31 | }
32 |
33 | .card-back {
34 | transform: rotateY(180deg);
35 | }
36 |
37 | @media screen and (max-width: 800px) {
38 | .memory-card {
39 | width: 140px;
40 | height: 140px;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/memory-marvel/src/components/GameInfo/GameInfo.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { flip, medal, stopwatch } from '../../config/icons'
3 | import ScoreCard from '../ScoreCard/ScoreCard'
4 | import './style.css'
5 |
6 | interface GameInfoProps {
7 | moves: number
8 | score: string | number
9 | timer?: string
10 | }
11 |
12 | const GameInfo: React.FC = ({ moves, score, timer }) => (
13 |
14 |
15 |
16 | {timer && }
17 |
18 | )
19 |
20 | export default GameInfo
21 |
--------------------------------------------------------------------------------
/memory-marvel/src/components/GameInfo/style.css:
--------------------------------------------------------------------------------
1 | .top-header {
2 | margin-bottom: 30px;
3 | display: flex;
4 | gap: 25px;
5 | }
6 |
7 | .info-card {
8 | position: relative;
9 | z-index: 5;
10 | width: 180px;
11 | }
12 |
13 | .info-icon {
14 | width: 60px;
15 | height: 60px;
16 | background-color: #fff;
17 | border: 1px solid rgba(16, 49, 89, 0.15);
18 | border-radius: 50%;
19 | display: flex;
20 | justify-content: center;
21 | align-items: center;
22 | }
23 |
24 | .info-card-title-wrapper {
25 | position: absolute;
26 | top: 10px;
27 | left: 10px;
28 | width: 170px;
29 | height: 40px;
30 | border: 1px solid rgba(16, 49, 89, 0.15);
31 | padding: 10px 10px 10px 50px;
32 | display: flex;
33 | justify-content: center;
34 | align-items: center;
35 | gap: 10px;
36 | border-radius: 0px 120px 120px 0px;
37 | background: #fff;
38 | z-index: -1;
39 | }
40 |
41 | .info-card-title {
42 | color: #000;
43 | font-size: 18px;
44 | font-weight: 500;
45 | }
46 |
47 | @media screen and (max-width: 600px) {
48 | .top-header {
49 | flex-direction: column;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/memory-marvel/src/components/GameModal/GameModal.tsx:
--------------------------------------------------------------------------------
1 | import { modalIcon, refresh, starsEmpty, starsFilled } from '../../config/icons'
2 | import GameInfo from '../GameInfo/GameInfo'
3 | import './style.css'
4 |
5 | interface GameInfoProps {
6 | moves: number
7 | score: string | number
8 | win: boolean
9 | handleResetGame: () => void
10 | }
11 |
12 | const GameModal: React.FC = ({ moves, score, win, handleResetGame }) => {
13 | return (
14 |
15 |
16 |

17 |
{`${
18 | win ? 'You’re a Champ!' : 'Next time, champ! Keep going!'
19 | }`}
20 |

25 |
26 |

32 |
33 |
34 | )
35 | }
36 |
37 | export default GameModal
38 |
--------------------------------------------------------------------------------
/memory-marvel/src/components/GameModal/style.css:
--------------------------------------------------------------------------------
1 | .modal {
2 | position: fixed;
3 | z-index: 9999;
4 | left: 0;
5 | top: 0;
6 | width: 100%;
7 | height: 100%;
8 | overflow: hidden;
9 | background-color: rgba(0, 0, 0, 0.4);
10 | padding: 20px;
11 | }
12 |
13 | .modal-content {
14 | border-radius: 20px;
15 | box-shadow: 0px 1.70667px 10.24px 0px rgba(184, 183, 183, 0.65);
16 | background-color: #ffffff;
17 | margin: 10% auto;
18 | padding: 20px;
19 | max-width: 650px;
20 | min-height: 200px;
21 | position: relative;
22 | }
23 |
24 | .modal-icon {
25 | position: absolute;
26 | top: -14px;
27 | left: 50%;
28 | transform: translate(-50%, -50%);
29 | width: 300px;
30 | }
31 |
32 | .modal-title {
33 | color: #91181d;
34 | text-align: center;
35 | font-size: 32px;
36 | font-weight: 700;
37 | margin-top: 65px;
38 | }
39 |
40 | .star-icon {
41 | display: flex;
42 | margin: 0 auto;
43 | margin-top: 20px;
44 | margin-bottom: 40px;
45 | }
46 |
47 | .refresh-icon {
48 | position: absolute;
49 | bottom: -58px;
50 | left: 50%;
51 | transform: translate(-50%, -50%);
52 | cursor: pointer;
53 | }
54 |
55 | @media screen and (max-width: 600px) {
56 | .modal-content {
57 | margin: 70px auto;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/memory-marvel/src/components/Header/Header.tsx:
--------------------------------------------------------------------------------
1 | const Header = () => (
2 |
3 |
Memory Marvel
4 | {/* Additional header content can be added here */}
5 |
6 | )
7 |
8 | export default Header
9 |
--------------------------------------------------------------------------------
/memory-marvel/src/components/ScoreCard/ScoreCard.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | interface ScoreCardProps {
4 | icon: string
5 | title: string
6 | value: string | number
7 | }
8 |
9 | const ScoreCard: React.FC = ({ icon, title, value }) => (
10 |
11 |
12 |

13 |
14 |
15 | {`${title}: ${value}`}
16 |
17 |
18 | )
19 |
20 | export default ScoreCard
21 |
--------------------------------------------------------------------------------
/memory-marvel/src/config/icons.ts:
--------------------------------------------------------------------------------
1 | import cardFront from '../assets/icons/card-front.svg'
2 | import flip from '../assets/icons/flip.svg'
3 | import medal from '../assets/icons/medal.svg'
4 | import stopwatch from '../assets/icons/stopwatch.svg'
5 | import modalIcon from '../assets/icons/modal-icon.png'
6 | import refresh from '../assets/icons/refresh.svg'
7 | import starsFilled from '../assets/icons/stars-filled.svg'
8 | import starsEmpty from '../assets/icons/stars-empty.svg'
9 |
10 | import shape1 from '../assets/icons/airplane.svg'
11 | import shape2 from '../assets/icons/cocktail.svg'
12 | import shape3 from '../assets/icons/hotel.svg'
13 | import shape4 from '../assets/icons/surf.svg'
14 | import shape5 from '../assets/icons/bath-tub.svg'
15 | import shape6 from '../assets/icons/polaroid.svg'
16 |
17 | export {
18 | cardFront,
19 | flip,
20 | medal,
21 | stopwatch,
22 | modalIcon,
23 | refresh,
24 | starsFilled,
25 | starsEmpty,
26 | shape1,
27 | shape2,
28 | shape3,
29 | shape4,
30 | shape5,
31 | shape6,
32 | }
33 |
--------------------------------------------------------------------------------
/memory-marvel/src/data/index.ts:
--------------------------------------------------------------------------------
1 | import { shape1, shape2, shape3, shape4, shape5 } from '../config/icons'
2 |
3 | export interface Shape {
4 | shapeId: string
5 | uniqueId: string
6 | shape: string
7 | }
8 |
9 | const shapes: Shape[] = [
10 | {
11 | shapeId: '01',
12 | uniqueId: '001',
13 | shape: shape1,
14 | },
15 | {
16 | shapeId: '02',
17 | uniqueId: '002',
18 | shape: shape2,
19 | },
20 | {
21 | shapeId: '03',
22 | uniqueId: '003',
23 | shape: shape3,
24 | },
25 | {
26 | shapeId: '04',
27 | uniqueId: '004',
28 | shape: shape4,
29 | },
30 | {
31 | shapeId: '05',
32 | uniqueId: '005',
33 | shape: shape5,
34 | },
35 | ]
36 |
37 | export default shapes
38 |
--------------------------------------------------------------------------------
/memory-marvel/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App.tsx'
4 |
5 | ReactDOM.createRoot(document.getElementById('root')!).render(
6 |
7 |
8 |
9 | )
10 |
--------------------------------------------------------------------------------
/memory-marvel/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/memory-marvel/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | /* Linting */
18 | "strict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 | "noFallthroughCasesInSwitch": true
22 | },
23 | "include": ["src"],
24 | "references": [{ "path": "./tsconfig.node.json" }]
25 | }
26 |
--------------------------------------------------------------------------------
/memory-marvel/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true
8 | },
9 | "include": ["vite.config.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/memory-marvel/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "singleQuote": true,
4 | "tabWidth": 2,
5 | "printWidth": 100
6 | }
7 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/README.md:
--------------------------------------------------------------------------------
1 | # React + TypeScript + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
10 | ## Expanding the ESLint configuration
11 |
12 | If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13 |
14 | - Configure the top-level `parserOptions` property like this:
15 |
16 | ```js
17 | export default tseslint.config({
18 | languageOptions: {
19 | // other options...
20 | parserOptions: {
21 | project: ['./tsconfig.node.json', './tsconfig.app.json'],
22 | tsconfigRootDir: import.meta.dirname,
23 | },
24 | },
25 | })
26 | ```
27 |
28 | - Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
29 | - Optionally add `...tseslint.configs.stylisticTypeChecked`
30 | - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
31 |
32 | ```js
33 | // eslint.config.js
34 | import react from 'eslint-plugin-react'
35 |
36 | export default tseslint.config({
37 | // Set the react version
38 | settings: { react: { version: '18.3' } },
39 | plugins: {
40 | // Add the react plugin
41 | react,
42 | },
43 | rules: {
44 | // other rules...
45 | // Enable its recommended rules
46 | ...react.configs.recommended.rules,
47 | ...react.configs['jsx-runtime'].rules,
48 | },
49 | })
50 | ```
51 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/eslint.config.js:
--------------------------------------------------------------------------------
1 | import js from '@eslint/js'
2 | import globals from 'globals'
3 | import reactHooks from 'eslint-plugin-react-hooks'
4 | import reactRefresh from 'eslint-plugin-react-refresh'
5 | import tseslint from 'typescript-eslint'
6 |
7 | export default tseslint.config(
8 | { ignores: ['dist'] },
9 | {
10 | extends: [js.configs.recommended, ...tseslint.configs.recommended],
11 | files: ['**/*.{ts,tsx}'],
12 | languageOptions: {
13 | ecmaVersion: 2020,
14 | globals: globals.browser,
15 | },
16 | plugins: {
17 | 'react-hooks': reactHooks,
18 | 'react-refresh': reactRefresh,
19 | },
20 | rules: {
21 | ...reactHooks.configs.recommended.rules,
22 | 'react-refresh/only-export-components': [
23 | 'warn',
24 | { allowConstantExport: true },
25 | ],
26 | },
27 | },
28 | )
29 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "online-word-sentences-counter",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc -b && vite build",
9 | "lint": "eslint .",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "react": "^18.3.1",
14 | "react-dom": "^18.3.1",
15 | "sass": "^1.78.0"
16 | },
17 | "devDependencies": {
18 | "@eslint/js": "^9.9.0",
19 | "@types/react": "^18.3.3",
20 | "@types/react-dom": "^18.3.0",
21 | "@vitejs/plugin-react": "^4.3.1",
22 | "eslint": "^9.9.0",
23 | "eslint-plugin-react-hooks": "^5.1.0-rc.0",
24 | "eslint-plugin-react-refresh": "^0.4.9",
25 | "globals": "^15.9.0",
26 | "typescript": "^5.5.3",
27 | "typescript-eslint": "^8.0.1",
28 | "vite": "^5.4.1"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/App.scss:
--------------------------------------------------------------------------------
1 | @use 'styles' as *;
2 | @use 'styles/reset.scss';
3 | @use 'styles/fonts.scss';
4 | @use 'styles/breakpoints.scss' as breakpoints;
5 |
6 | body {
7 | background: url('./assets/images/appCover.png') no-repeat center center fixed;
8 | background-size: cover;
9 | background-color: $primary-background;
10 | font-family: 'Poppins', sans-serif;
11 | }
12 |
13 | .container {
14 | width: 100%;
15 | max-width: $large-container;
16 | margin: 0 auto;
17 | padding: 0 15px;
18 | }
19 |
20 | .small-container {
21 | width: 100%;
22 | max-width: $medium-container;
23 | margin: 0 auto;
24 | padding: 0 25px;
25 | min-height: calc(100vh - 100px);
26 | @include breakpoints.devices(sm) {
27 | padding: 18px;
28 | }
29 | }
30 |
31 | .main-app {
32 | display: flex;
33 | flex-direction: column;
34 | justify-content: center;
35 | margin-top: 70px;
36 | margin-bottom: 30px;
37 | @include breakpoints.devices(sm) {
38 | margin-bottom: 0;
39 | margin-top: 15px;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/App.tsx:
--------------------------------------------------------------------------------
1 | import './App.scss'
2 | import BottomResultBox from './components/BottomResultBox'
3 | import Footer from './components/Footer'
4 | import Navbar from './components/Navbar'
5 | import ResultBox from './components/ResultBox'
6 | import TextArea from './components/TextArea'
7 |
8 | const App = () => {
9 | return (
10 | <>
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | >
21 | )
22 | }
23 |
24 | export default App
25 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-200.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-200.woff
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-200.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-200.woff2
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-300.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-300.woff
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-300.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-300.woff2
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-500.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-500.woff
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-500.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-500.woff2
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-600.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-600.woff
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-600.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-600.woff2
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-700.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-700.woff
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-700.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-700.woff2
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-regular.woff
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/online-word-sentences-counter/src/assets/fonts/poppins-v20-latin-regular.woff2
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/icons/linkedin.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/icons/twitter.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/icons/website.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
21 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/assets/images/appCover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/online-word-sentences-counter/src/assets/images/appCover.png
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/components/BottomResultBox/index.scss:
--------------------------------------------------------------------------------
1 | @use '../../styles/theme.scss' as *;
2 | @use '../../styles/breakpoints.scss' as breakpoints;
3 |
4 | .bottom-result-bar {
5 | padding: 26px 30px;
6 | background-color: $secondary-background;
7 | border: $box-border;
8 | display: flex;
9 | justify-content: space-around;
10 | @include breakpoints.devices(lg) {
11 | padding: 20px 26px;
12 | }
13 | @include breakpoints.devices(sm) {
14 | align-items: center;
15 | flex-direction: column;
16 | gap: 20px;
17 | }
18 | .result-box {
19 | display: flex;
20 | flex-direction: row;
21 | align-items: center;
22 | .box-title {
23 | color: $secondary-text;
24 | font-weight: 500;
25 | font-size: 16px;
26 | @include breakpoints.devices(lg) {
27 | font-size: 14px;
28 | }
29 | }
30 | .box-value {
31 | color: $primary-text;
32 | font-weight: 600;
33 | font-size: 18px;
34 | margin-left: 12px;
35 | @include breakpoints.devices(lg) {
36 | font-size: 16px;
37 | }
38 | @include breakpoints.devices(md) {
39 | font-weight: 500;
40 | margin-left: 8px;
41 | }
42 | @include breakpoints.devices(sm) {
43 | font-size: 14px;
44 | }
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/components/BottomResultBox/index.tsx:
--------------------------------------------------------------------------------
1 | import './index.scss'
2 |
3 | const BottomResultBox = () => {
4 | const bottomResultBar = [
5 | {
6 | title: 'Average Reading Time:',
7 | value: '-',
8 | },
9 | {
10 | title: 'Longest word:',
11 | value: '-',
12 | },
13 | ]
14 |
15 | return (
16 |
17 | {bottomResultBar.map(({ title, value }) => (
18 |
19 | {title}
20 | {value}
21 |
22 | ))}
23 |
24 | )
25 | }
26 |
27 | export default BottomResultBox
28 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/components/Footer/index.scss:
--------------------------------------------------------------------------------
1 | @use '../../styles/theme.scss' as *;
2 | @use '../../styles/breakpoints.scss' as breakpoints;
3 |
4 | .footer {
5 | padding: 19px 0;
6 | background: $tertiary-background;
7 | // margin-top: 65px;
8 | border-top: $footer-border;
9 | @include breakpoints.devices(sm) {
10 | margin-top: 30px;
11 | }
12 | .footer-elements {
13 | display: flex;
14 | flex-direction: row;
15 | justify-content: space-between;
16 | p {
17 | color: $primary-text;
18 | font-size: 16px;
19 | font-weight: 500;
20 | @include breakpoints.devices(sm) {
21 | font-size: 14px;
22 | }
23 | }
24 | .other-pages {
25 | display: flex;
26 | flex-direction: row;
27 | li {
28 | color: $primary-text;
29 | font-size: 16px;
30 | font-weight: 500;
31 | margin-left: 20px;
32 | position: relative;
33 | cursor: pointer;
34 | @include breakpoints.devices(sm) {
35 | font-size: 13px;
36 | font-weight: 400;
37 | }
38 | &:not(:last-child):after {
39 | content: '|';
40 | position: absolute;
41 | width: 1px;
42 | height: 100%;
43 | right: -10px;
44 | }
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/components/Footer/index.tsx:
--------------------------------------------------------------------------------
1 | import './index.scss'
2 |
3 | const Footer = () => {
4 | return (
5 |
16 | )
17 | }
18 |
19 | export default Footer
20 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/components/Navbar/index.scss:
--------------------------------------------------------------------------------
1 | @use '../../styles/theme.scss' as *;
2 | @use '../../styles/breakpoints.scss' as breakpoints;
3 |
4 | .navbar {
5 | padding: 19px 0;
6 | background: $tertiary-background;
7 | box-shadow: $shadow-1;
8 | .nav-elements {
9 | display: flex;
10 | flex-direction: row;
11 | justify-content: space-between;
12 | align-items: center;
13 | .app-title {
14 | color: $primary-text;
15 | font-weight: 600;
16 | font-size: 18px;
17 | @include breakpoints.devices(sm) {
18 | font-size: 16px;
19 | }
20 | }
21 | .social-links {
22 | display: flex;
23 | flex-direction: row;
24 | li {
25 | color: $primary-text;
26 | margin-left: 20px;
27 | font-size: 14px;
28 | font-weight: 400;
29 | @include breakpoints.devices(sm) {
30 | font-size: 13px;
31 | margin-left: 14px;
32 | }
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/components/Navbar/index.tsx:
--------------------------------------------------------------------------------
1 | import Linkedin from '../../assets/icons/linkedin.svg'
2 | import Twitter from '../../assets/icons/twitter.svg'
3 | import Website from '../../assets/icons/website.svg'
4 | import './index.scss'
5 |
6 | const Navbar = () => {
7 | return (
8 |
36 | )
37 | }
38 |
39 | export default Navbar
40 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/components/ResultBox/index.scss:
--------------------------------------------------------------------------------
1 | @use '../../styles/theme.scss' as *;
2 | @use '../../styles/breakpoints.scss' as breakpoints;
3 |
4 | .result-bar {
5 | padding: 15px 30px;
6 | background-color: $secondary-background;
7 | border: $box-border;
8 | display: flex;
9 | justify-content: space-around;
10 | @include breakpoints.devices(lg) {
11 | padding: 15px 26px;
12 | justify-content: unset;
13 | }
14 | @include breakpoints.devices(md) {
15 | justify-content: space-between;
16 | flex-wrap: wrap;
17 | }
18 | @include breakpoints.devices(sm) {
19 | justify-content: space-around;
20 | gap: 20px;
21 | }
22 |
23 | .result-box {
24 | display: flex;
25 | flex-direction: column;
26 | margin-right: 80px;
27 | @include breakpoints.devices(md) {
28 | margin-right: unset;
29 | }
30 | .box-title {
31 | color: $secondary-text;
32 | font-weight: 500;
33 | font-size: 16px;
34 | @include breakpoints.devices(lg) {
35 | font-size: 14px;
36 | }
37 | }
38 | .box-value {
39 | color: $primary-text;
40 | font-weight: 600;
41 | font-size: 22px;
42 | margin-top: 10px;
43 | text-align: center;
44 | @include breakpoints.devices(lg) {
45 | font-size: 18px;
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/components/ResultBox/index.tsx:
--------------------------------------------------------------------------------
1 | import './index.scss'
2 |
3 | const ResultBox = () => {
4 | const resultBar = [
5 | {
6 | title: 'Words',
7 | value: 0,
8 | },
9 | {
10 | title: 'Characters',
11 | value: 0,
12 | },
13 | {
14 | title: 'Sentences',
15 | value: 0,
16 | },
17 | {
18 | title: 'Paragraphs ',
19 | value: 0,
20 | },
21 | {
22 | title: 'Pronouns',
23 | value: 0,
24 | },
25 | ]
26 |
27 | return (
28 |
29 | {resultBar.map(({ title, value }) => (
30 |
31 | {title}
32 | {value}
33 |
34 | ))}
35 |
36 | )
37 | }
38 |
39 | export default ResultBox
40 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/components/TextArea/index.scss:
--------------------------------------------------------------------------------
1 | @use '../../styles/theme.scss' as *;
2 | @use '../../styles/breakpoints.scss' as breakpoints;
3 |
4 | .text-area {
5 | padding: 30px;
6 | background-color: $secondary-background;
7 | margin-top: 20px;
8 | margin-bottom: 20px;
9 | min-height: 400px;
10 | border: $box-border;
11 | resize: none;
12 | outline: none;
13 | font-weight: 400;
14 | font-size: 20px;
15 | color: $primary-text;
16 | @include breakpoints.devices(lg) {
17 | font-size: 18px;
18 | }
19 | @include breakpoints.devices(md) {
20 | font-size: 16px;
21 | padding: 20px;
22 | }
23 |
24 | &::placeholder {
25 | font-weight: 700;
26 | color: $light-gray;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/components/TextArea/index.tsx:
--------------------------------------------------------------------------------
1 | import './index.scss'
2 |
3 | const TextArea = () => {
4 | return
5 | }
6 |
7 | export default TextArea
8 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/data/pronouns.ts:
--------------------------------------------------------------------------------
1 | // 1. Personal Pronouns / Subject Pronouns
2 | // 2. Object Pronouns
3 | // 3. Possessive Pronouns
4 | // 4. Reflexive Pronouns
5 |
6 | export const pronouns = [
7 | 'i',
8 | 'we',
9 | 'you',
10 | 'he',
11 | 'she',
12 | 'it',
13 | 'they',
14 | 'me',
15 | 'us',
16 | 'her',
17 | 'him',
18 | 'them',
19 | 'mine',
20 | 'ours',
21 | 'yours',
22 | 'hers',
23 | 'his',
24 | 'theirs',
25 | 'myself',
26 | 'yourself',
27 | 'herself',
28 | 'himself',
29 | 'itself',
30 | 'ourselves',
31 | 'yourselves',
32 | 'themselves',
33 | ]
34 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/main.tsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from 'react'
2 | import { createRoot } from 'react-dom/client'
3 | import App from './App.tsx'
4 |
5 | createRoot(document.getElementById('root')!).render(
6 |
7 |
8 |
9 | )
10 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/styles/breakpoints.scss:
--------------------------------------------------------------------------------
1 | $xs: 400px; // for small screen mobile
2 | $sm: 700px; // for mobile screen
3 | $md: 800px; // for tablets
4 | $lg: 1280px; // for laptops
5 | $xl: 1440px; // for desktop / monitors
6 | $xxl: 1920px; // for big screens
7 |
8 | @mixin devices($breakpoint) {
9 | @if $breakpoint == xs {
10 | @media only screen and (max-width: $xs) {
11 | @content;
12 | }
13 | }
14 |
15 | @if $breakpoint == sm {
16 | @media only screen and (max-width: $sm) {
17 | @content;
18 | }
19 | }
20 |
21 | @if $breakpoint == md {
22 | @media only screen and (max-width: $md) {
23 | @content;
24 | }
25 | }
26 |
27 | @if $breakpoint == lg {
28 | @media only screen and (max-width: $lg) {
29 | @content;
30 | }
31 | }
32 |
33 | @if $breakpoint == xl {
34 | @media only screen and (max-width: $xl) {
35 | @content;
36 | }
37 | }
38 |
39 | @if $breakpoint == xxl {
40 | @media only screen and (max-width: $xxl) {
41 | @content;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/styles/fonts.scss:
--------------------------------------------------------------------------------
1 | /* poppins-200 - latin */
2 | @font-face {
3 | font-family: 'Poppins';
4 | font-style: normal;
5 | font-weight: 200;
6 | font-display: swap;
7 | src: url('../assets/fonts/poppins-v20-latin-200.woff2') format('woff2'),
8 | url('../assets/fonts/poppins-v20-latin-200.woff') format('woff');
9 | }
10 | /* poppins-300 - latin */
11 | @font-face {
12 | font-family: 'Poppins';
13 | font-style: normal;
14 | font-weight: 300;
15 | font-display: swap;
16 | src: url('../assets/fonts/poppins-v20-latin-300.woff2') format('woff2'),
17 | url('../assets/fonts/poppins-v20-latin-300.woff') format('woff');
18 | }
19 | /* poppins-regular - latin */
20 | @font-face {
21 | font-family: 'Poppins';
22 | font-style: normal;
23 | font-weight: 400;
24 | font-display: swap;
25 | src: url('../assets/fonts/poppins-v20-latin-regular.woff2') format('woff2'),
26 | url('../assets/fonts/poppins-v20-latin-regular.woff') format('woff');
27 | }
28 | /* poppins-500 - latin */
29 | @font-face {
30 | font-family: 'Poppins';
31 | font-style: normal;
32 | font-weight: 500;
33 | font-display: swap;
34 | src: url('../assets/fonts/poppins-v20-latin-500.woff2') format('woff2'),
35 | url('../assets/fonts/poppins-v20-latin-500.woff') format('woff');
36 | }
37 | /* poppins-600 - latin */
38 | @font-face {
39 | font-family: 'Poppins';
40 | font-style: normal;
41 | font-weight: 600;
42 | font-display: swap;
43 | src: url('../assets/fonts/poppins-v20-latin-600.woff2') format('woff2'),
44 | url('../assets/fonts/poppins-v20-latin-600.woff') format('woff');
45 | }
46 | /* poppins-700 - latin */
47 | @font-face {
48 | font-family: 'Poppins';
49 | font-style: normal;
50 | font-weight: 700;
51 | font-display: swap;
52 | src: url('../assets/fonts/poppins-v20-latin-700.woff2') format('woff2'),
53 | url('../assets/fonts/poppins-v20-latin-700.woff') format('woff');
54 | }
55 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/styles/index.scss:
--------------------------------------------------------------------------------
1 | @forward './theme.scss';
2 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/styles/reset.scss:
--------------------------------------------------------------------------------
1 | *,
2 | *:before,
3 | *:after {
4 | box-sizing: border-box;
5 | }
6 |
7 | html,
8 | body,
9 | div,
10 | span,
11 | object,
12 | iframe,
13 | figure,
14 | h1,
15 | h2,
16 | h3,
17 | h4,
18 | h5,
19 | h6,
20 | p,
21 | blockquote,
22 | pre,
23 | a,
24 | code,
25 | em,
26 | img,
27 | small,
28 | strike,
29 | strong,
30 | sub,
31 | sup,
32 | tt,
33 | b,
34 | u,
35 | i,
36 | ol,
37 | ul,
38 | li,
39 | fieldset,
40 | form,
41 | label,
42 | table,
43 | caption,
44 | tbody,
45 | tfoot,
46 | thead,
47 | tr,
48 | th,
49 | td,
50 | main,
51 | canvas,
52 | embed,
53 | footer,
54 | header,
55 | nav,
56 | section,
57 | video {
58 | margin: 0;
59 | padding: 0;
60 | border: 0;
61 | font-size: 100%;
62 | font: inherit;
63 | vertical-align: baseline;
64 | text-rendering: optimizeLegibility;
65 | -webkit-font-smoothing: antialiased;
66 | text-size-adjust: none;
67 | }
68 |
69 | footer,
70 | header,
71 | nav,
72 | section,
73 | main {
74 | display: block;
75 | }
76 |
77 | body {
78 | line-height: 1;
79 | }
80 |
81 | ol,
82 | ul {
83 | list-style: none;
84 | }
85 |
86 | blockquote,
87 | q {
88 | quotes: none;
89 | }
90 |
91 | blockquote:before,
92 | blockquote:after,
93 | q:before,
94 | q:after {
95 | content: '';
96 | content: none;
97 | }
98 |
99 | table {
100 | border-collapse: collapse;
101 | border-spacing: 0;
102 | }
103 |
104 | textarea {
105 | font-family: inherit;
106 | }
107 |
108 | input {
109 | -webkit-appearance: none;
110 | border-radius: 0;
111 | }
112 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/styles/theme.scss:
--------------------------------------------------------------------------------
1 | // container width
2 | $large-container: 1200px;
3 | $medium-container: 1010px;
4 |
5 | // Dark mode colors
6 | $primary-text: #e0e0e0;
7 | $secondary-text: #bdbdbd;
8 | $light-gray: #333333;
9 |
10 | $primary-background: #121212;
11 | $secondary-background: #1e1e1e;
12 | $tertiary-background: #2c2c2c;
13 |
14 | $box-border: 1px solid #2c2c2c;
15 | $footer-border: 1px solid rgba(255, 255, 255, 0.1);
16 | $shadow-1: 0px 0.3px 0.9px rgba(255, 255, 255, 0.1), 0px 1.6px 3.6px rgba(255, 255, 255, 0.1);
17 |
18 | // // Light mode colors
19 | // // text colors
20 | // $primary-text: #242424;
21 | // $secondary-text: #9e9e9e;
22 | // $light-gray: #e6e6e6;
23 |
24 | // // background colors
25 | // $primary-background: #f0f2f5;
26 | // $secondary-background: #ffffff;
27 | // $tertiary-background: #f1f7ff;
28 |
29 | // // other colors
30 | // $white: #ffffff;
31 | // $black: #000000;
32 | // $box-border: 1px solid #f7f7f7;
33 | // $shadow-1: 0px 0.3px 0.9px rgba(0, 0, 0, 0.1), 0px 1.6px 3.6px rgba(0, 0, 0, 0.1);
34 | // $footer-border: 1px solid rgba(0, 0, 0, 0.06);
35 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "isolatedModules": true,
13 | "moduleDetection": "force",
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | /* Linting */
18 | "strict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 | "noFallthroughCasesInSwitch": true
22 | },
23 | "include": ["src"]
24 | }
25 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": [],
3 | "references": [
4 | { "path": "./tsconfig.app.json" },
5 | { "path": "./tsconfig.node.json" }
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2022",
4 | "lib": ["ES2023"],
5 | "module": "ESNext",
6 | "skipLibCheck": true,
7 |
8 | /* Bundler mode */
9 | "moduleResolution": "bundler",
10 | "allowImportingTsExtensions": true,
11 | "isolatedModules": true,
12 | "moduleDetection": "force",
13 | "noEmit": true,
14 |
15 | /* Linting */
16 | "strict": true,
17 | "noUnusedLocals": true,
18 | "noUnusedParameters": true,
19 | "noFallthroughCasesInSwitch": true
20 | },
21 | "include": ["vite.config.ts"]
22 | }
23 |
--------------------------------------------------------------------------------
/online-word-sentences-counter/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------
/password-generator/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true },
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:@typescript-eslint/recommended',
7 | 'plugin:react-hooks/recommended',
8 | ],
9 | ignorePatterns: ['dist', '.eslintrc.cjs'],
10 | parser: '@typescript-eslint/parser',
11 | plugins: ['react-refresh'],
12 | rules: {
13 | 'react-refresh/only-export-components': [
14 | 'warn',
15 | { allowConstantExport: true },
16 | ],
17 | },
18 | }
19 |
--------------------------------------------------------------------------------
/password-generator/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/password-generator/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "singleQuote": true,
4 | "tabWidth": 2,
5 | "printWidth": 100
6 | }
7 |
--------------------------------------------------------------------------------
/password-generator/README.md:
--------------------------------------------------------------------------------
1 | # React + TypeScript + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
10 | ## Expanding the ESLint configuration
11 |
12 | If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13 |
14 | - Configure the top-level `parserOptions` property like this:
15 |
16 | ```js
17 | export default {
18 | // other rules...
19 | parserOptions: {
20 | ecmaVersion: 'latest',
21 | sourceType: 'module',
22 | project: ['./tsconfig.json', './tsconfig.node.json'],
23 | tsconfigRootDir: __dirname,
24 | },
25 | }
26 | ```
27 |
28 | - Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
29 | - Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
30 | - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
31 |
--------------------------------------------------------------------------------
/password-generator/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | React Password Generator
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/password-generator/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "password-generator",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "rc-slider": "^10.5.0",
14 | "react": "^18.2.0",
15 | "react-copy-to-clipboard": "^5.1.0",
16 | "react-dom": "^18.2.0"
17 | },
18 | "devDependencies": {
19 | "@types/react": "^18.2.37",
20 | "@types/react-copy-to-clipboard": "^5.0.7",
21 | "@types/react-dom": "^18.2.15",
22 | "@typescript-eslint/eslint-plugin": "^6.10.0",
23 | "@typescript-eslint/parser": "^6.10.0",
24 | "@vitejs/plugin-react": "^4.2.0",
25 | "eslint": "^8.53.0",
26 | "eslint-plugin-react-hooks": "^4.6.0",
27 | "eslint-plugin-react-refresh": "^0.4.4",
28 | "typescript": "^5.2.2",
29 | "vite": "^5.0.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/password-generator/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/password-generator/src/App.tsx:
--------------------------------------------------------------------------------
1 | import PasswordGenerator from './components/PasswordGenerator'
2 | import './styles.css'
3 | import './variables.css'
4 |
5 | function App() {
6 | return
7 | }
8 |
9 | export default App
10 |
--------------------------------------------------------------------------------
/password-generator/src/assets/gif/password.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/password-generator/src/assets/gif/password.gif
--------------------------------------------------------------------------------
/password-generator/src/assets/icons/copy.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/password-generator/src/assets/icons/refresh.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/password-generator/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/password-generator/src/components/Checkbox/index.css:
--------------------------------------------------------------------------------
1 | .checkbox-wrapper {
2 | display: flex;
3 | align-items: center;
4 | justify-content: space-between;
5 | flex-direction: row-reverse;
6 | margin-top: 8px;
7 | }
8 |
9 | .checkbox-wrapper input[type='checkbox'] {
10 | -webkit-appearance: none;
11 | appearance: none;
12 | width: 20px;
13 | height: 20px;
14 | border-radius: 4px;
15 | margin-right: 0.5em;
16 | border: 1px solid #292d32;
17 | outline: none;
18 | cursor: pointer;
19 | }
20 |
21 | input:checked {
22 | background-color: #33cccc;
23 | position: relative;
24 | border: 1px solid #33cccc !important;
25 | }
26 |
27 | input:checked::before {
28 | content: '\2714';
29 | font-size: 1.3em;
30 | color: #fff;
31 | position: absolute;
32 | right: 2px;
33 | top: -4px;
34 | }
35 |
36 | .checkbox-wrapper input[type='checkbox']:disabled {
37 | border-color: #c0c0c0;
38 | background-color: #c0c0c0;
39 | }
40 |
41 | .checkbox-wrapper input[type='checkbox']:disabled + span {
42 | color: #c0c0c0;
43 | }
44 |
45 | .checkbox-wrapper input[type='checkbox']:focus {
46 | box-shadow: 0 0 20px #33cccc;
47 | }
48 |
49 | .checkbox-wrapper label {
50 | font-size: 14px;
51 | cursor: pointer;
52 | }
53 |
--------------------------------------------------------------------------------
/password-generator/src/components/Checkbox/index.tsx:
--------------------------------------------------------------------------------
1 | import './index.css'
2 |
3 | const Checkbox = ({ id, label, checked, name, onChange }: any) => {
4 | return (
5 |
6 |
7 |
8 |
9 | )
10 | }
11 |
12 | export default Checkbox
13 |
--------------------------------------------------------------------------------
/password-generator/src/components/PasswordGenerator/index.css:
--------------------------------------------------------------------------------
1 | .password-wrapper {
2 | background-color: #ffffff;
3 | border-radius: 20px;
4 | max-width: 830px;
5 | width: 100%;
6 | margin: 0 auto;
7 | padding: 25px 80px 40px 80px;
8 | border: 1px solid #588b54;
9 | }
10 |
11 | .gif {
12 | text-align: center;
13 | margin-bottom: 10px;
14 | }
15 |
16 | .gif img {
17 | width: 134px;
18 | }
19 |
20 | .password-wrapper .title {
21 | font-size: 26px;
22 | font-weight: bold;
23 | }
24 |
25 | .password-wrapper .subtitle {
26 | font-size: 16px;
27 | max-width: 470px;
28 | margin: 0 auto;
29 | margin-top: 5px;
30 | }
31 |
32 | .password-input-wrapper {
33 | display: flex;
34 | align-items: center;
35 | margin-top: 24px;
36 | }
37 |
38 | .password-field {
39 | display: flex;
40 | flex: 1;
41 | outline: 1px solid #3f563d;
42 | border-radius: 14px;
43 | margin-right: 15px;
44 | }
45 |
46 | .password-field input {
47 | font-size: 14px;
48 | width: 100%;
49 | border: none;
50 | outline: none;
51 | font-weight: 600;
52 | padding: 11px 12px;
53 | }
54 |
55 | .password-field img {
56 | margin-right: 10px;
57 | cursor: pointer;
58 | }
59 |
60 | .copy-btn {
61 | background-color: #33cccc;
62 | border-radius: 14px;
63 | font-size: 14px;
64 | font-weight: bold;
65 | padding: 8px 18px;
66 | display: flex;
67 | justify-content: center;
68 | align-items: center;
69 | outline: none;
70 | border: none;
71 | }
72 |
73 | .copy-btn img {
74 | margin-right: 7px;
75 | }
76 |
77 | .health {
78 | margin-top: 10px;
79 | display: inline-block;
80 | color: #12b40e;
81 | }
82 |
83 | .slider {
84 | margin-top: 30px;
85 | }
86 |
87 | @media screen and (max-width: 700px) {
88 | .password-wrapper {
89 | padding: 12px 50px 25px 50px;
90 | }
91 | .copy-btn {
92 | font-size: 12px;
93 | padding: 8px 12px;
94 | border-radius: 12px;
95 | -webkit-tap-highlight-color: transparent;
96 | }
97 | .password-field {
98 | border-radius: 14px;
99 | margin-right: 11px;
100 | border-radius: 12px;
101 | }
102 | }
103 |
104 | @media screen and (max-width: 600px) {
105 | .password-wrapper {
106 | padding: 12px 25px 25px 25px;
107 | }
108 | .password-wrapper .title {
109 | font-size: 22px;
110 | }
111 | .password-wrapper .subtitle {
112 | font-size: 14px;
113 | }
114 | .password-field input {
115 | font-size: 12px;
116 | font-weight: 500;
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/password-generator/src/components/PasswordGenerator/index.tsx:
--------------------------------------------------------------------------------
1 | import Slider from 'rc-slider'
2 | import 'rc-slider/assets/index.css'
3 | import { useEffect, useState } from 'react'
4 | import { CopyToClipboard } from 'react-copy-to-clipboard'
5 |
6 | import Checkbox from '../Checkbox'
7 |
8 | import passwordGif from '../../assets/gif/password.gif'
9 | import copyIcon from '../../assets/icons/copy.svg'
10 | import refreshIcon from '../../assets/icons/refresh.svg'
11 |
12 | import './index.css'
13 |
14 | const PasswordGenerator = () => {
15 | const [passwordLength, setPasswordLength] = useState(10)
16 |
17 | const onChangePasswordLength = (value: any) => {
18 | setPasswordLength(value)
19 | }
20 |
21 | return (
22 |
23 |
24 |

25 |
26 |
27 |
PASSWORD GENERATOR
28 |
29 | Ensure online account safety by creating strong and secure passwords
30 |
31 |
32 |
33 |
34 |
35 |

36 |
37 |
41 |
42 |
Weak
43 |
44 |
45 |
46 | {passwordLength}
47 |
48 |
55 |
56 |
57 |
58 |
59 |
60 |
66 |
67 |
68 | )
69 | }
70 |
71 | export default PasswordGenerator
72 |
--------------------------------------------------------------------------------
/password-generator/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App.tsx'
4 |
5 | ReactDOM.createRoot(document.getElementById('root')!).render(
6 |
7 |
8 |
9 | )
10 |
--------------------------------------------------------------------------------
/password-generator/src/styles.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;500;700;900&display=swap');
2 |
3 | *,
4 | *::before,
5 | *::after {
6 | box-sizing: border-box;
7 | }
8 |
9 | html {
10 | font-size: 100%;
11 | }
12 |
13 | h1,
14 | h2,
15 | h3,
16 | h4,
17 | h5,
18 | h6,
19 | p,
20 | ul,
21 | figure,
22 | blockquote,
23 | dl,
24 | dd {
25 | padding: 0;
26 | margin: 0;
27 | }
28 |
29 | button {
30 | border: none;
31 | background-color: transparent;
32 | font-family: inherit;
33 | padding: 0;
34 | cursor: pointer;
35 | }
36 |
37 | body {
38 | padding: 15px;
39 | overflow-x: hidden;
40 | min-height: 100vh;
41 | font-family: 'Roboto', sans-serif;
42 | background-color: var(--bg-color);
43 | color: var(--primary-text-color);
44 | display: flex;
45 | justify-content: center;
46 | align-items: center;
47 | }
48 |
49 | .container {
50 | max-width: 800px;
51 | width: 100%;
52 | margin: 0 auto;
53 | padding: 0 20px;
54 | }
55 |
56 | .success {
57 | color: var(--success-color);
58 | }
59 | .warning {
60 | color: var(--warning-color);
61 | }
62 | .danger {
63 | color: var(--danger-color);
64 | }
65 |
66 | .flx {
67 | display: flex;
68 | flex-direction: row;
69 | align-items: center;
70 | }
71 |
72 | .flxCenter {
73 | display: flex;
74 | justify-content: center;
75 | align-items: center;
76 | }
77 |
78 | .tac {
79 | text-align: center;
80 | }
81 |
82 | .fw-500 {
83 | font-weight: 500;
84 | }
85 |
86 | .slider-style {
87 | margin-top: 22px;
88 | margin-bottom: 30px;
89 | }
90 |
91 | .slider-style .rc-slider-rail {
92 | height: 8px;
93 | background-color: transparent;
94 | border: 1px solid #000000;
95 | border-radius: 4px;
96 | }
97 |
98 | .slider-style .rc-slider-track {
99 | background-color: var(--primary-color);
100 | height: 8px;
101 | }
102 |
103 | .slider-style .rc-slider-handle {
104 | width: 23px;
105 | height: 23px;
106 | border: 1px solid #000000;
107 | background-color: var(--primary-color);
108 | top: 2px;
109 | z-index: 1;
110 | opacity: 1;
111 | }
112 |
113 | @media screen and (max-width: 700px) {
114 | body {
115 | padding: 10px;
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/password-generator/src/variables.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --primary-color: #33cccc;
3 | --primary-text-color: #202020;
4 | --bg-color: #319795;
5 |
6 | --success-color: #198754;
7 | --warning-color: #ffc107;
8 | --danger-color: #dc3545;
9 | }
10 |
--------------------------------------------------------------------------------
/password-generator/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/password-generator/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | /* Linting */
18 | "strict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 | "noFallthroughCasesInSwitch": true
22 | },
23 | "include": ["src"],
24 | "references": [{ "path": "./tsconfig.node.json" }]
25 | }
26 |
--------------------------------------------------------------------------------
/password-generator/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true
8 | },
9 | "include": ["vite.config.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/password-generator/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------
/random-quote-generator/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false
3 | }
--------------------------------------------------------------------------------
/random-quote-generator/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Create React App
2 |
3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4 |
5 | ## Available Scripts
6 |
7 | In the project directory, you can run:
8 |
9 | ### `npm start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13 |
14 | The page will reload if you make edits.\
15 | You will also see any lint errors in the console.
16 |
17 | ### `npm test`
18 |
19 | Launches the test runner in the interactive watch mode.\
20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21 |
22 | ### `npm run build`
23 |
24 | Builds the app for production to the `build` folder.\
25 | It correctly bundles React in production mode and optimizes the build for the best performance.
26 |
27 | The build is minified and the filenames include the hashes.\
28 | Your app is ready to be deployed!
29 |
30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31 |
32 | ### `npm run eject`
33 |
34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
35 |
36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37 |
38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
39 |
40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
41 |
42 | ## Learn More
43 |
44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45 |
46 | To learn React, check out the [React documentation](https://reactjs.org/).
47 |
--------------------------------------------------------------------------------
/random-quote-generator/db.json:
--------------------------------------------------------------------------------
1 | {
2 | "quotes": [
3 | {
4 | "quote": "In the end, we will remember not the words of our enemies, but the silence of our friends.",
5 | "author": "Martin Luther King Jr."
6 | },
7 | {
8 | "quote": "We are all in the gutter, but some of us are looking at the stars.",
9 | "author": "Oscar Wilde"
10 | },
11 | {
12 | "quote": "You can't cross the sea merely by standing and staring at the water.",
13 | "author": "Rabindranath Tagore"
14 | },
15 | {
16 | "quote": "I am not afraid of storms, for I am learning how to sail my ship.",
17 | "author": "Louisa May Alcott"
18 | },
19 | {
20 | "quote": "The true sign of intelligence is not knowledge but imagination.",
21 | "author": "Albert Einstein"
22 | },
23 | {
24 | "quote": "If you can't explain it simply, you don't understand it well enough.",
25 | "author": "Albert Einstein"
26 | },
27 | {
28 | "quote": "Life is a journey, and if you fall in love with the journey, you will be in love forever.",
29 | "author": "Peter Hagerty"
30 | },
31 | {
32 | "quote": "The future belongs to those who believe in the beauty of their dreams.",
33 | "author": "Eleanor Roosevelt"
34 | },
35 | {
36 | "quote": "The best way to find yourself is to lose yourself in the service of others.",
37 | "author": "Mahatma Gandhi"
38 | },
39 | {
40 | "quote": "The only true wisdom is in knowing you know nothing.",
41 | "author": "Socrates"
42 | },
43 | {
44 | "quote": "I have not failed. I've just found 10,000 ways that won't work.",
45 | "author": "Thomas Edison"
46 | },
47 | {
48 | "quote": "The greatest glory in living lies not in never falling, but in rising every time we fall.",
49 | "author": "Nelson Mandela"
50 | },
51 | {
52 | "quote": "Success is not the key to happiness. Happiness is the key to success. If you love what you are doing, you will be successful.",
53 | "author": "Albert Schweitzer"
54 | },
55 | {
56 | "quote": "Life is 10% what happens to us and 90% how we react to it.",
57 | "author": "Charles R. Swindoll"
58 | },
59 | {
60 | "quote": "It always seems impossible until it's done.",
61 | "author": "Nelson Mandela"
62 | },
63 | {
64 | "quote": "Happiness is not something ready made. It comes from your own actions.",
65 | "author": "Dalai Lama"
66 | },
67 | {
68 | "quote": "You miss 100% of the shots you don't take.",
69 | "author": "Wayne Gretzky"
70 | },
71 | {
72 | "quote": "Be the change you wish to see in the world.",
73 | "author": "Mahatma Gandhi"
74 | },
75 | {
76 | "quote": "The only way to do great work is to love what you do.",
77 | "author": "Steve Jobs"
78 | }
79 | ]
80 | }
81 |
--------------------------------------------------------------------------------
/random-quote-generator/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "random-quote-generator",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.16.5",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "@types/jest": "^27.5.2",
10 | "@types/node": "^16.18.6",
11 | "@types/react": "^18.0.26",
12 | "@types/react-dom": "^18.0.9",
13 | "axios": "^1.3.4",
14 | "classnames": "^2.3.2",
15 | "react": "^18.2.0",
16 | "react-dom": "^18.2.0",
17 | "react-scripts": "5.0.1",
18 | "typescript": "^4.9.4",
19 | "web-vitals": "^2.1.4"
20 | },
21 | "scripts": {
22 | "start": "react-scripts start",
23 | "build": "react-scripts build",
24 | "test": "react-scripts test",
25 | "eject": "react-scripts eject"
26 | },
27 | "eslintConfig": {
28 | "extends": [
29 | "react-app",
30 | "react-app/jest"
31 | ]
32 | },
33 | "browserslist": {
34 | "production": [
35 | ">0.2%",
36 | "not dead",
37 | "not op_mini all"
38 | ],
39 | "development": [
40 | "last 1 chrome version",
41 | "last 1 firefox version",
42 | "last 1 safari version"
43 | ]
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/random-quote-generator/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/random-quote-generator/public/favicon.ico
--------------------------------------------------------------------------------
/random-quote-generator/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React Random Quote Application
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/random-quote-generator/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/random-quote-generator/public/logo192.png
--------------------------------------------------------------------------------
/random-quote-generator/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/random-quote-generator/public/logo512.png
--------------------------------------------------------------------------------
/random-quote-generator/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
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 |
--------------------------------------------------------------------------------
/random-quote-generator/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/random-quote-generator/src/App.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Quicksand:wght@400;500;600&display=swap");
2 |
3 | :root {
4 | --primary-color: #ff7d1f;
5 | --secondary-color: #f0faf9;
6 |
7 | --primary-text-color: #46474e;
8 | --light-gary: #999999;
9 | }
10 |
11 | body {
12 | margin: 0;
13 | padding: 0;
14 | position: relative;
15 | background-color: var(--secondary-color);
16 | color: var(--primary-text-color);
17 | font-family: "Quicksand", sans-serif;
18 | }
19 |
20 | .container {
21 | max-width: 900px;
22 | padding: 0 20px;
23 | margin: 0 auto;
24 | }
25 |
26 | .top-strip {
27 | position: fixed;
28 | width: 100%;
29 | height: 39px;
30 | background: var(--primary-color);
31 | top: 0;
32 | }
33 |
34 | .bottom-strip {
35 | position: fixed;
36 | width: 100%;
37 | height: 39px;
38 | background: var(--primary-color);
39 | bottom: 0;
40 | }
41 |
42 | .quotation-box {
43 | min-height: calc(100vh - 39px - 39px - 45px);
44 | margin-top: 120px;
45 | }
46 |
47 | .quote {
48 | font-size: 36px;
49 | font-weight: 500;
50 | line-height: 50px;
51 | color: var(--primary-text-color);
52 | }
53 |
54 | .bottom-navigation {
55 | display: flex;
56 | justify-content: space-between;
57 | margin-top: 60px;
58 | }
59 |
60 | .share {
61 | display: flex;
62 | align-items: center;
63 | gap: 10px;
64 | }
65 |
66 | .share span {
67 | font-size: 22px;
68 | font-weight: 500;
69 | margin-right: 7px;
70 | }
71 |
72 | .rotate {
73 | transform: rotate(180deg);
74 | margin-right: 40px;
75 | }
76 |
77 | .cp {
78 | cursor: pointer;
79 | -webkit-tap-highlight-color: transparent;
80 | }
81 |
82 | .disabled-button {
83 | pointer-events: none;
84 | cursor: not-allowed;
85 | }
86 |
87 | .disabled-button path {
88 | stroke: var(--light-gary);
89 | cursor: not-allowed;
90 | }
91 |
92 | .disable-highlight-color {
93 | -webkit-tap-highlight-color: transparent;
94 | }
95 |
96 | @media screen and (max-width: 700px) {
97 | .quotation-box {
98 | margin-top: 70px;
99 | }
100 |
101 | .quote {
102 | font-size: 28px;
103 | line-height: 40px;
104 | font-weight: 400;
105 | }
106 |
107 | .bottom-navigation {
108 | display: flex;
109 | flex-direction: column;
110 | align-items: center;
111 | margin-top: 30px;
112 | }
113 |
114 | .share {
115 | margin-top: 30px;
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/random-quote-generator/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render, screen } from '@testing-library/react';
3 | import App from './App';
4 |
5 | test('renders learn react link', () => {
6 | render();
7 | const linkElement = screen.getByText(/learn react/i);
8 | expect(linkElement).toBeInTheDocument();
9 | });
10 |
--------------------------------------------------------------------------------
/random-quote-generator/src/App.tsx:
--------------------------------------------------------------------------------
1 | import classnames from "classnames"
2 | import { ReactComponent as Button } from "../src/assets/icons/button.svg"
3 | import { ReactComponent as Quotation } from "../src/assets/icons/quotation.svg"
4 | import { ReactComponent as Twitter } from "../src/assets/icons/twitter.svg"
5 | import { ReactComponent as Whatsapp } from "../src/assets/icons/whatsapp.svg"
6 | import "./App.css"
7 |
8 | function App() {
9 | return (
10 | <>
11 |
14 |
15 |
16 |
17 |
18 |
19 | In the end, we will remember not the words of our enemies, but the
20 | silence of our friends.
21 |
22 |
- Martin Luther King Jr.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | Share At:
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | >
39 | )
40 | }
41 |
42 | export default App
43 |
--------------------------------------------------------------------------------
/random-quote-generator/src/assets/icons/button.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/random-quote-generator/src/assets/icons/quotation.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/random-quote-generator/src/assets/icons/twitter.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/random-quote-generator/src/assets/icons/whatsapp.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/random-quote-generator/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./App";
4 | import reportWebVitals from "./reportWebVitals";
5 |
6 | const root = ReactDOM.createRoot(
7 | document.getElementById("root") as HTMLElement
8 | );
9 | root.render(
10 |
11 |
12 |
13 | );
14 |
15 | // If you want to start measuring performance in your app, pass a function
16 | // to log results (for example: reportWebVitals(console.log))
17 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
18 | reportWebVitals();
19 |
--------------------------------------------------------------------------------
/random-quote-generator/src/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/random-quote-generator/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/random-quote-generator/src/reportWebVitals.ts:
--------------------------------------------------------------------------------
1 | import { ReportHandler } from 'web-vitals';
2 |
3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => {
4 | if (onPerfEntry && onPerfEntry instanceof Function) {
5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
6 | getCLS(onPerfEntry);
7 | getFID(onPerfEntry);
8 | getFCP(onPerfEntry);
9 | getLCP(onPerfEntry);
10 | getTTFB(onPerfEntry);
11 | });
12 | }
13 | };
14 |
15 | export default reportWebVitals;
16 |
--------------------------------------------------------------------------------
/random-quote-generator/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/random-quote-generator/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "strict": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "module": "esnext",
17 | "moduleResolution": "node",
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "noEmit": true,
21 | "jsx": "react-jsx"
22 | },
23 | "include": [
24 | "src"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/task-list/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "printWidth": 120
4 | }
5 |
--------------------------------------------------------------------------------
/task-list/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Create React App
2 |
3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4 |
5 | ## Available Scripts
6 |
7 | In the project directory, you can run:
8 |
9 | ### `npm start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13 |
14 | The page will reload if you make edits.\
15 | You will also see any lint errors in the console.
16 |
17 | ### `npm test`
18 |
19 | Launches the test runner in the interactive watch mode.\
20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21 |
22 | ### `npm run build`
23 |
24 | Builds the app for production to the `build` folder.\
25 | It correctly bundles React in production mode and optimizes the build for the best performance.
26 |
27 | The build is minified and the filenames include the hashes.\
28 | Your app is ready to be deployed!
29 |
30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31 |
32 | ### `npm run eject`
33 |
34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
35 |
36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37 |
38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
39 |
40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
41 |
42 | ## Learn More
43 |
44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45 |
46 | To learn React, check out the [React documentation](https://reactjs.org/).
47 |
--------------------------------------------------------------------------------
/task-list/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "task-manager",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.16.5",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "@types/jest": "^27.5.2",
10 | "@types/node": "^16.18.16",
11 | "@types/react": "^18.0.28",
12 | "@types/react-dom": "^18.0.11",
13 | "classnames": "^2.3.2",
14 | "react": "^18.2.0",
15 | "react-dom": "^18.2.0",
16 | "react-scripts": "5.0.1",
17 | "sass": "^1.59.3",
18 | "typescript": "^4.9.5",
19 | "web-vitals": "^2.1.4"
20 | },
21 | "scripts": {
22 | "start": "react-scripts start",
23 | "build": "react-scripts build",
24 | "test": "react-scripts test",
25 | "eject": "react-scripts eject"
26 | },
27 | "eslintConfig": {
28 | "extends": [
29 | "react-app",
30 | "react-app/jest"
31 | ]
32 | },
33 | "browserslist": {
34 | "production": [
35 | ">0.2%",
36 | "not dead",
37 | "not op_mini all"
38 | ],
39 | "development": [
40 | "last 1 chrome version",
41 | "last 1 firefox version",
42 | "last 1 safari version"
43 | ]
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/task-list/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/task-list/public/favicon.ico
--------------------------------------------------------------------------------
/task-list/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/task-list/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/task-list/public/logo192.png
--------------------------------------------------------------------------------
/task-list/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/task-list/public/logo512.png
--------------------------------------------------------------------------------
/task-list/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
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 |
--------------------------------------------------------------------------------
/task-list/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/task-list/src/App.scss:
--------------------------------------------------------------------------------
1 | @use "styles" as *;
2 | @use "styles/reset.scss";
3 | @use "styles/fonts.scss";
4 | @use "styles/breakpoints.scss" as breakpoints;
5 |
6 | body {
7 | background-color: #f0f2f5;
8 | font-family: "Poppins", sans-serif;
9 | }
10 |
11 | .container {
12 | width: 720px;
13 | max-width: 100%;
14 | padding: 0 15px;
15 | margin: 0 auto;
16 | }
17 |
18 | .page-wrapper {
19 | margin: 50px 0;
20 | }
21 |
22 | .top-title {
23 | display: flex;
24 | justify-content: space-between;
25 | align-items: center;
26 | h2 {
27 | font-weight: 700;
28 | font-size: 36px;
29 | color: $primary-color;
30 | }
31 | }
32 |
33 | .mr-20 {
34 | margin-right: 20px;
35 | }
36 |
37 | .task-container {
38 | margin-top: 40px;
39 | }
40 |
41 | .flex {
42 | display: flex;
43 | flex-direction: column;
44 | }
45 |
46 | .flx-between {
47 | display: flex;
48 | justify-content: space-between;
49 | }
50 |
51 | .flx-right {
52 | display: flex;
53 | justify-content: flex-end;
54 | }
55 |
56 | .mt-50 {
57 | margin-top: 50px;
58 | }
59 |
60 | .cp {
61 | cursor: pointer;
62 | }
63 |
64 | .w-100 {
65 | width: 170px;
66 | }
67 |
--------------------------------------------------------------------------------
/task-list/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render, screen } from '@testing-library/react';
3 | import App from './App';
4 |
5 | test('renders learn react link', () => {
6 | render();
7 | const linkElement = screen.getByText(/learn react/i);
8 | expect(linkElement).toBeInTheDocument();
9 | });
10 |
--------------------------------------------------------------------------------
/task-list/src/App.tsx:
--------------------------------------------------------------------------------
1 | import "./App.scss"
2 | import { ReactComponent as Add } from "./assets/icons/add.svg"
3 | import AddEditTaskForm from "./components/AddEditTaskForm"
4 | import Button from "./components/Button"
5 | import DeleteModal from "./components/DeleteModal"
6 | import TaskCard from "./components/TaskCard"
7 | import { taskList } from "./siteData/taskList"
8 |
9 | const App = () => {
10 | const showAddEditModal = false
11 | const showDeleteModal = false
12 | return (
13 |
14 |
15 |
16 |
Task List
17 | } onClick={() => {}} />
18 |
19 |
20 | {taskList.map((task) => (
21 |
22 | ))}
23 |
24 |
25 | {showAddEditModal &&
}
26 | {showDeleteModal &&
}
27 |
28 | )
29 | }
30 |
31 | export default App
32 |
--------------------------------------------------------------------------------
/task-list/src/assets/fonts/poppins-v20-latin-200.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/task-list/src/assets/fonts/poppins-v20-latin-200.woff
--------------------------------------------------------------------------------
/task-list/src/assets/fonts/poppins-v20-latin-200.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/task-list/src/assets/fonts/poppins-v20-latin-200.woff2
--------------------------------------------------------------------------------
/task-list/src/assets/fonts/poppins-v20-latin-300.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/task-list/src/assets/fonts/poppins-v20-latin-300.woff
--------------------------------------------------------------------------------
/task-list/src/assets/fonts/poppins-v20-latin-300.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/task-list/src/assets/fonts/poppins-v20-latin-300.woff2
--------------------------------------------------------------------------------
/task-list/src/assets/fonts/poppins-v20-latin-500.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/task-list/src/assets/fonts/poppins-v20-latin-500.woff
--------------------------------------------------------------------------------
/task-list/src/assets/fonts/poppins-v20-latin-500.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/task-list/src/assets/fonts/poppins-v20-latin-500.woff2
--------------------------------------------------------------------------------
/task-list/src/assets/fonts/poppins-v20-latin-600.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/task-list/src/assets/fonts/poppins-v20-latin-600.woff
--------------------------------------------------------------------------------
/task-list/src/assets/fonts/poppins-v20-latin-600.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/task-list/src/assets/fonts/poppins-v20-latin-600.woff2
--------------------------------------------------------------------------------
/task-list/src/assets/fonts/poppins-v20-latin-700.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/task-list/src/assets/fonts/poppins-v20-latin-700.woff
--------------------------------------------------------------------------------
/task-list/src/assets/fonts/poppins-v20-latin-700.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/task-list/src/assets/fonts/poppins-v20-latin-700.woff2
--------------------------------------------------------------------------------
/task-list/src/assets/fonts/poppins-v20-latin-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/task-list/src/assets/fonts/poppins-v20-latin-regular.woff
--------------------------------------------------------------------------------
/task-list/src/assets/fonts/poppins-v20-latin-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdulBasit313/practical-reactjs-coding-challenges/e9eba722f8fa1738c4ecb8d7d423e7d11f8864de/task-list/src/assets/fonts/poppins-v20-latin-regular.woff2
--------------------------------------------------------------------------------
/task-list/src/assets/icons/add.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/task-list/src/assets/icons/arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/task-list/src/assets/icons/close.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/task-list/src/assets/icons/delete.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/task-list/src/assets/icons/drop-down.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/task-list/src/assets/icons/edit.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/task-list/src/components/AddEditTaskForm/index.tsx:
--------------------------------------------------------------------------------
1 | import classNames from "classnames"
2 | import { ReactComponent as Close } from "../../assets/icons/close.svg"
3 | import Button from "../Button"
4 | import Input from "../Input"
5 | import Modal from "../Modal"
6 | import "./style.scss"
7 |
8 | const AddEditTaskForm = () => {
9 | return (
10 |
11 |
33 |
34 | )
35 | }
36 |
37 | export default AddEditTaskForm
38 |
--------------------------------------------------------------------------------
/task-list/src/components/AddEditTaskForm/style.scss:
--------------------------------------------------------------------------------
1 | @use "../../styles/index.scss" as *;
2 | @use "../../styles/breakpoints.scss" as breakpoints;
3 |
4 | .add-edit-modal {
5 | .modal-title {
6 | font-size: 22px;
7 | font-weight: 700;
8 | color: #121212;
9 | margin-bottom: 30px;
10 | }
11 | }
12 |
13 | .modal-priority {
14 | margin-top: 20px;
15 | span {
16 | font-size: 14px;
17 | font-weight: 700;
18 | color: $gray;
19 | }
20 | }
21 |
22 | .priority-buttons {
23 | display: flex;
24 | gap: 13px;
25 | margin-top: 12px;
26 | @include breakpoints.devices(sm) {
27 | gap: 10px;
28 | }
29 | li {
30 | border: 1px solid $warning-color;
31 | border-radius: 10px;
32 | font-size: 14px;
33 | font-weight: 500;
34 | color: $warning-color;
35 | text-transform: capitalize;
36 | padding: 10px 0;
37 | width: 90px;
38 | text-align: center;
39 | cursor: pointer;
40 | }
41 | .high {
42 | border: 1px solid $error-color;
43 | color: $error-color;
44 | &-selected {
45 | background-color: $error-color;
46 | color: $white;
47 | }
48 | }
49 | .medium {
50 | border: 1px solid $warning-color;
51 | color: $warning-color;
52 | &-selected {
53 | background-color: $warning-color;
54 | color: $white;
55 | }
56 | }
57 | .low {
58 | border: 1px solid $success-color;
59 | color: $success-color;
60 | &-selected {
61 | background-color: $success-color;
62 | color: $white;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/task-list/src/components/Button/index.tsx:
--------------------------------------------------------------------------------
1 | import classnames from "classnames"
2 | import { MouseEventHandler, ReactNode } from "react"
3 | import "./style.scss"
4 |
5 | type ButtonProps = {
6 | title: string
7 | icon?: ReactNode
8 | outline?: boolean
9 | disabled?: boolean
10 | onClick: MouseEventHandler
11 | }
12 |
13 | const Button = ({ title, icon, outline, disabled, onClick }: ButtonProps) => {
14 | return (
15 |
19 | )
20 | }
21 |
22 | export default Button
23 |
--------------------------------------------------------------------------------
/task-list/src/components/Button/style.scss:
--------------------------------------------------------------------------------
1 | @use "../../styles/index.scss" as *;
2 |
3 | .button {
4 | background: $tertiary-color;
5 | box-shadow: 0px 6px 12px rgba(113, 63, 255, 0.25);
6 | border-radius: 14px;
7 | padding: 13px 30px;
8 | outline: none;
9 | border: none;
10 | cursor: pointer;
11 | font-weight: 600;
12 | font-size: 16px;
13 | color: #ffffff;
14 | &:disabled {
15 | background-color: $gray;
16 | cursor: not-allowed;
17 | }
18 | &.outline {
19 | background: #ffffff;
20 | border: 1px solid #d8e0f0;
21 | box-shadow: 0px 1px 2px rgba(184, 200, 224, 0.222055);
22 | font-weight: 400;
23 | color: #7d8592;
24 | }
25 | .icon {
26 | margin-right: 12px;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/task-list/src/components/CircularProgressBar/index.tsx:
--------------------------------------------------------------------------------
1 | import { FC } from "react"
2 | import "./style.scss"
3 |
4 | interface Props {
5 | strokeWidth: number
6 | sqSize: number
7 | percentage?: number
8 | }
9 |
10 | const CircularProgressBar: FC = (props) => {
11 | const { strokeWidth, sqSize, percentage } = props
12 | const radius = (sqSize - strokeWidth) / 2
13 | const viewBox = `0 0 ${sqSize} ${sqSize}`
14 | const dashArray = radius * Math.PI * 2
15 | const dashOffset = dashArray - (dashArray * (percentage || 0)) / 100
16 |
17 | return (
18 |
39 | )
40 | }
41 |
42 | export default CircularProgressBar
43 |
--------------------------------------------------------------------------------
/task-list/src/components/CircularProgressBar/style.scss:
--------------------------------------------------------------------------------
1 | .circular-progressbar {
2 | display: block;
3 | margin: 0 auto;
4 | }
5 |
6 | .circle-background {
7 | fill: none;
8 | stroke: #e5e6e9;
9 | }
10 |
11 | .circle-progress {
12 | fill: none;
13 | stroke: #713fff;
14 | stroke-linecap: round;
15 | transition: stroke-dashoffset 0.5s ease 0s;
16 | }
17 |
--------------------------------------------------------------------------------
/task-list/src/components/DeleteModal/index.tsx:
--------------------------------------------------------------------------------
1 | import Button from "../Button"
2 | import Modal from "../Modal"
3 | import "./style.scss"
4 |
5 | const DeleteModal = () => {
6 | return (
7 |
8 |
9 |
Are you sure you want to delete this task?
10 |
11 |
14 |
15 |
16 | )
17 | }
18 |
19 | export default DeleteModal
20 |
--------------------------------------------------------------------------------
/task-list/src/components/DeleteModal/style.scss:
--------------------------------------------------------------------------------
1 | @use "../../styles/index.scss" as *;
2 | @use "../../styles/breakpoints.scss" as breakpoints;
3 |
4 | .delete-modal {
5 | margin: 0 auto;
6 | max-width: 300px;
7 | p {
8 | font-size: 20px;
9 | font-weight: 600;
10 | color: $black;
11 | line-height: 1.5;
12 | text-align: center;
13 | }
14 | &__actions {
15 | display: flex;
16 | justify-content: center;
17 | gap: 25px;
18 | margin-top: 30px;
19 | }
20 | @include breakpoints.devices(sm) {
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/task-list/src/components/Input/index.tsx:
--------------------------------------------------------------------------------
1 | import "./style.scss"
2 |
3 | interface InputProps {
4 | label: string
5 | placeholder: string
6 | onChange: (event: React.ChangeEvent) => void
7 | name: string
8 | value: string
9 | }
10 |
11 | const Input = ({ label, placeholder, onChange, name, value }: InputProps) => {
12 | return (
13 |
14 |
15 |
16 |
17 | )
18 | }
19 |
20 | export default Input
21 |
--------------------------------------------------------------------------------
/task-list/src/components/Input/style.scss:
--------------------------------------------------------------------------------
1 | @use "../../styles/index.scss" as *;
2 |
3 | .input {
4 | label {
5 | font-size: 14px;
6 | font-weight: 700;
7 | color: $gray;
8 | display: block;
9 | margin-bottom: 10px;
10 | }
11 | input {
12 | width: 95%;
13 | background: $white;
14 | border: 1px solid #d8e0f0;
15 | box-shadow: 0px 1px 2px rgba(184, 200, 224, 0.222055);
16 | border-radius: 14px;
17 | color: $gray;
18 | font-size: 14px;
19 | font-weight: 400;
20 | padding: 16px 18px;
21 | outline: none;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/task-list/src/components/Modal/index.tsx:
--------------------------------------------------------------------------------
1 | import "./style.scss"
2 |
3 | type ModalProps = {
4 | children: React.ReactNode
5 | }
6 |
7 | const Modal = ({ children }: ModalProps) => {
8 | return (
9 |
12 | )
13 | }
14 |
15 | export default Modal
16 |
--------------------------------------------------------------------------------
/task-list/src/components/Modal/style.scss:
--------------------------------------------------------------------------------
1 | @use "../../styles/breakpoints.scss" as breakpoints;
2 |
3 | .modal {
4 | position: fixed;
5 | z-index: 9999;
6 | left: 0;
7 | top: 0;
8 | width: 100%;
9 | height: 100%;
10 | overflow: hidden;
11 | background-color: rgba(0, 0, 0, 0.4);
12 | }
13 |
14 | /* Modal Content */
15 | .modal-content {
16 | background-color: #ffffff;
17 | box-shadow: 0px 6px 58px rgba(121, 145, 173, 0.195504);
18 | border-radius: 24px;
19 | padding: 40px 60px;
20 | margin: 15% auto;
21 | width: 40%;
22 | min-height: 200px;
23 | @include breakpoints.devices(sm) {
24 | width: 90%;
25 | margin: 50% auto;
26 | padding: 30px 30px;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/task-list/src/components/TaskCard/index.tsx:
--------------------------------------------------------------------------------
1 | import classNames from "classnames"
2 | import { ReactComponent as DeleteIcon } from "../../assets/icons/delete.svg"
3 | import { ReactComponent as EditIcon } from "../../assets/icons/edit.svg"
4 | import CircularProgressBar from "../CircularProgressBar"
5 | import "./style.scss"
6 |
7 | const TaskCard = ({ task }: any) => {
8 | const { id, title, priority, status, progress } = task
9 |
10 | return (
11 |
12 |
13 | Task
14 | {title}
15 |
16 |
17 | Priority
18 | {priority}
19 |
20 |
21 | {status}
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | )
32 | }
33 |
34 | export default TaskCard
35 |
--------------------------------------------------------------------------------
/task-list/src/components/TaskCard/style.scss:
--------------------------------------------------------------------------------
1 | @use "../../styles/index.scss" as *;
2 | @use "../../styles/breakpoints.scss" as breakpoints;
3 |
4 | .task-card {
5 | background: $white;
6 | box-shadow: 0px 6px 58px rgba(196, 203, 214, 0.103611);
7 | border-radius: 24px;
8 | padding: 22px 30px;
9 | display: flex;
10 | justify-content: space-between;
11 | align-items: center;
12 | margin-top: 15px;
13 | @include breakpoints.devices(sm) {
14 | flex-direction: column;
15 | align-items: flex-start;
16 | }
17 | }
18 |
19 | .task-title {
20 | font-size: 14px;
21 | font-weight: 400;
22 | color: $secondary-color;
23 | margin-bottom: 7px;
24 | }
25 |
26 | .task {
27 | font-size: 16px;
28 | font-weight: 400;
29 | line-height: 1.2;
30 | color: $primary-color;
31 | }
32 |
33 | .priority-title {
34 | font-size: 14px;
35 | font-weight: 400;
36 | color: $secondary-color;
37 | margin-bottom: 7px;
38 | @include breakpoints.devices(sm) {
39 | margin-top: 15px;
40 | }
41 | }
42 |
43 | .priority {
44 | font-size: 14px;
45 | font-weight: 700;
46 | color: $success-color;
47 | text-transform: capitalize;
48 | }
49 | .high-priority {
50 | color: $error-color;
51 | }
52 | .medium-priority {
53 | color: $warning-color;
54 | }
55 | .low-priority {
56 | color: $success-color;
57 | }
58 |
59 | .task-status-wrapper {
60 | width: 100px;
61 | text-align: center;
62 | @include breakpoints.devices(sm) {
63 | margin-top: 15px;
64 | text-align: left;
65 | }
66 | }
67 |
68 | .status {
69 | background: rgba(125, 133, 146, 0.14);
70 | border-radius: 8px;
71 | padding: 7px 14px;
72 | color: $gray;
73 | font-weight: 700;
74 | font-size: 12px;
75 | outline: none;
76 | border: none;
77 | cursor: pointer;
78 | }
79 |
80 | .progress {
81 | @include breakpoints.devices(sm) {
82 | margin-top: 15px;
83 | }
84 | }
85 |
86 | .actions {
87 | @include breakpoints.devices(sm) {
88 | margin-top: 15px;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/task-list/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import ReactDOM from "react-dom/client"
3 | import App from "./App"
4 | import reportWebVitals from "./reportWebVitals"
5 |
6 | const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement)
7 | root.render(
8 |
9 |
10 |
11 | )
12 |
13 | // If you want to start measuring performance in your app, pass a function
14 | // to log results (for example: reportWebVitals(console.log))
15 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
16 | reportWebVitals()
17 |
--------------------------------------------------------------------------------
/task-list/src/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/task-list/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/task-list/src/reportWebVitals.ts:
--------------------------------------------------------------------------------
1 | import { ReportHandler } from 'web-vitals';
2 |
3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => {
4 | if (onPerfEntry && onPerfEntry instanceof Function) {
5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
6 | getCLS(onPerfEntry);
7 | getFID(onPerfEntry);
8 | getFCP(onPerfEntry);
9 | getLCP(onPerfEntry);
10 | getTTFB(onPerfEntry);
11 | });
12 | }
13 | };
14 |
15 | export default reportWebVitals;
16 |
--------------------------------------------------------------------------------
/task-list/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/task-list/src/siteData/taskList.ts:
--------------------------------------------------------------------------------
1 | export const taskList = [
2 | {
3 | id: "01",
4 | title: "Go to gym",
5 | priority: "high",
6 | status: "To Do",
7 | progress: 0,
8 | },
9 | {
10 | id: "02",
11 | title: "Read a book",
12 | priority: "low",
13 | status: "Done",
14 | progress: 100,
15 | },
16 | {
17 | id: "03",
18 | title: "Go to market",
19 | priority: "medium",
20 | status: "In Progress",
21 | progress: 50,
22 | },
23 | {
24 | id: "04",
25 | title: "Restart Learning Solidworks",
26 | priority: "high",
27 | status: "To Do",
28 | progress: 0,
29 | },
30 | {
31 | id: "05",
32 | title: "change slider to scroll",
33 | priority: "high",
34 | status: "Done",
35 | progress: 100,
36 | },
37 | {
38 | id: "06",
39 | title: "To publish the article",
40 | priority: "medium",
41 | status: "In Progress",
42 | progress: 50,
43 | },
44 | ]
45 |
--------------------------------------------------------------------------------
/task-list/src/styles/breakpoints.scss:
--------------------------------------------------------------------------------
1 | $xs: 400px; // for small screen mobile
2 | $sm: 600px; // for mobile screen
3 | $md: 800px; // for tablets
4 | $lg: 1280px; // for laptops
5 | $xl: 1440px; // for desktop / monitors
6 | $xxl: 1920px; // for big screens
7 |
8 | @mixin devices($breakpoint) {
9 | @if $breakpoint == xs {
10 | @media only screen and (max-width: $xs) {
11 | @content;
12 | }
13 | }
14 |
15 | @if $breakpoint == sm {
16 | @media only screen and (max-width: $sm) {
17 | @content;
18 | }
19 | }
20 |
21 | @if $breakpoint == md {
22 | @media only screen and (max-width: $md) {
23 | @content;
24 | }
25 | }
26 |
27 | @if $breakpoint == lg {
28 | @media only screen and (max-width: $lg) {
29 | @content;
30 | }
31 | }
32 |
33 | @if $breakpoint == xl {
34 | @media only screen and (max-width: $xl) {
35 | @content;
36 | }
37 | }
38 |
39 | @if $breakpoint == xxl {
40 | @media only screen and (max-width: $xxl) {
41 | @content;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/task-list/src/styles/fonts.scss:
--------------------------------------------------------------------------------
1 | /* poppins-200 - latin */
2 | @font-face {
3 | font-family: 'Poppins';
4 | font-style: normal;
5 | font-weight: 200;
6 | font-display: swap;
7 | src: url('../assets/fonts/poppins-v20-latin-200.woff2') format('woff2'),
8 | url('../assets/fonts/poppins-v20-latin-200.woff') format('woff');
9 | }
10 | /* poppins-300 - latin */
11 | @font-face {
12 | font-family: 'Poppins';
13 | font-style: normal;
14 | font-weight: 300;
15 | font-display: swap;
16 | src: url('../assets/fonts/poppins-v20-latin-300.woff2') format('woff2'),
17 | url('../assets/fonts/poppins-v20-latin-300.woff') format('woff');
18 | }
19 | /* poppins-regular - latin */
20 | @font-face {
21 | font-family: 'Poppins';
22 | font-style: normal;
23 | font-weight: 400;
24 | font-display: swap;
25 | src: url('../assets/fonts/poppins-v20-latin-regular.woff2') format('woff2'),
26 | url('../assets/fonts/poppins-v20-latin-regular.woff') format('woff');
27 | }
28 | /* poppins-500 - latin */
29 | @font-face {
30 | font-family: 'Poppins';
31 | font-style: normal;
32 | font-weight: 500;
33 | font-display: swap;
34 | src: url('../assets/fonts/poppins-v20-latin-500.woff2') format('woff2'),
35 | url('../assets/fonts/poppins-v20-latin-500.woff') format('woff');
36 | }
37 | /* poppins-600 - latin */
38 | @font-face {
39 | font-family: 'Poppins';
40 | font-style: normal;
41 | font-weight: 600;
42 | font-display: swap;
43 | src: url('../assets/fonts/poppins-v20-latin-600.woff2') format('woff2'),
44 | url('../assets/fonts/poppins-v20-latin-600.woff') format('woff');
45 | }
46 | /* poppins-700 - latin */
47 | @font-face {
48 | font-family: 'Poppins';
49 | font-style: normal;
50 | font-weight: 700;
51 | font-display: swap;
52 | src: url('../assets/fonts/poppins-v20-latin-700.woff2') format('woff2'),
53 | url('../assets/fonts/poppins-v20-latin-700.woff') format('woff');
54 | }
55 |
--------------------------------------------------------------------------------
/task-list/src/styles/index.scss:
--------------------------------------------------------------------------------
1 | @forward './theme.scss';
2 |
--------------------------------------------------------------------------------
/task-list/src/styles/reset.scss:
--------------------------------------------------------------------------------
1 | *,
2 | *:before,
3 | *:after {
4 | box-sizing: border-box;
5 | }
6 |
7 | html,
8 | body,
9 | div,
10 | span,
11 | object,
12 | iframe,
13 | figure,
14 | h1,
15 | h2,
16 | h3,
17 | h4,
18 | h5,
19 | h6,
20 | p,
21 | blockquote,
22 | pre,
23 | a,
24 | code,
25 | em,
26 | img,
27 | small,
28 | strike,
29 | strong,
30 | sub,
31 | sup,
32 | tt,
33 | b,
34 | u,
35 | i,
36 | ol,
37 | ul,
38 | li,
39 | fieldset,
40 | form,
41 | label,
42 | table,
43 | caption,
44 | tbody,
45 | tfoot,
46 | thead,
47 | tr,
48 | th,
49 | td,
50 | main,
51 | canvas,
52 | embed,
53 | footer,
54 | header,
55 | nav,
56 | section,
57 | video {
58 | margin: 0;
59 | padding: 0;
60 | border: 0;
61 | font-size: 100%;
62 | font: inherit;
63 | vertical-align: baseline;
64 | text-rendering: optimizeLegibility;
65 | -webkit-font-smoothing: antialiased;
66 | text-size-adjust: none;
67 | }
68 |
69 | footer,
70 | header,
71 | nav,
72 | section,
73 | main {
74 | display: block;
75 | }
76 |
77 | body {
78 | line-height: 1;
79 | }
80 |
81 | ol,
82 | ul {
83 | list-style: none;
84 | }
85 |
86 | blockquote,
87 | q {
88 | quotes: none;
89 | }
90 |
91 | blockquote:before,
92 | blockquote:after,
93 | q:before,
94 | q:after {
95 | content: '';
96 | content: none;
97 | }
98 |
99 | table {
100 | border-collapse: collapse;
101 | border-spacing: 0;
102 | }
103 |
104 | textarea {
105 | font-family: inherit;
106 | }
107 |
108 | input {
109 | -webkit-appearance: none;
110 | border-radius: 0;
111 | }
112 |
--------------------------------------------------------------------------------
/task-list/src/styles/theme.scss:
--------------------------------------------------------------------------------
1 | // Define variables
2 | $primary-color: #0a1629;
3 | $secondary-color: #91929e;
4 | $tertiary-color: #713fff;
5 |
6 | $success-color: #0ac947;
7 | $warning-color: #ffbd21;
8 | $error-color: #f73446;
9 |
10 | $white: #ffffff;
11 | $black: #000000;
12 | $gray: #7d8592;
13 |
14 | $container-width: 720px;
15 | $container-padding: 15px;
16 | $modal-priority-gap: 13px;
17 |
18 | // Define reusable mixins
19 | @mixin flex($direction: row, $justify: flex-start, $align: stretch) {
20 | display: flex;
21 | flex-direction: $direction;
22 | justify-content: $justify;
23 | align-items: $align;
24 | }
25 |
26 | @mixin shadow($x: 0, $y: 6px, $blur: 58px, $color: rgba(196, 203, 214, 0.103611)) {
27 | box-shadow: $x $y $blur $color;
28 | }
29 |
--------------------------------------------------------------------------------
/task-list/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "strict": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "module": "esnext",
17 | "moduleResolution": "node",
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "noEmit": true,
21 | "jsx": "react-jsx"
22 | },
23 | "include": [
24 | "src"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------