├── .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 | ![React Coding Challenges](./assets/images/React-Cdoing-Challenges.png) 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 | ![word sentences counter tool](https://ik.imagekit.io/cpnw7c0xpe/Codevertiser/word-sentence-counter.png?updatedAt=1726141603149) 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 | ![reactjs password generator](./assets/images/react-random-password-generator.png) 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 | ![react random quote generator](./assets/images/react-random-quote-generator.png) 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 | ![react typescript todo list](./assets/images/react-typescript-todo-list.png) 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 | ![react memory game](./assets/images/memory-game-react.png) 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 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /memory-marvel/src/assets/icons/cocktail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /memory-marvel/src/assets/icons/emoji.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 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 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /memory-marvel/src/assets/icons/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /memory-marvel/src/assets/icons/polaroid.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /memory-marvel/src/assets/icons/refresh.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 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 | Card Front 10 |
11 |
12 | Number icon 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 | modal title 17 |

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

20 | game status 25 | 26 | refresh game 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 | {`${title} 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 |