├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt └── src ├── App.css ├── App.js ├── App.test.js ├── components ├── accordian │ ├── data.js │ ├── index.jsx │ └── styles.css ├── custom-modal-popup │ ├── modal-test.jsx │ ├── modal.css │ └── modal.jsx ├── custom-tabs │ ├── tab-test.jsx │ ├── tabs.css │ └── tabs.jsx ├── feature-flag │ ├── context │ │ └── index.jsx │ ├── data.js │ └── index.jsx ├── github-profile-finder │ ├── index.jsx │ ├── styles.css │ └── user.jsx ├── image-slider │ ├── index.jsx │ └── styles.css ├── light-dark-mode │ ├── index.jsx │ ├── theme.css │ └── useLocalStroage.jsx ├── load-more-data │ ├── index.jsx │ └── styles.css ├── qr-code-generator │ ├── index.jsx │ └── styles.css ├── random-color │ └── index.jsx ├── scroll-indicator │ ├── index.jsx │ └── scroll.css ├── scroll-to-top-and-bottom │ ├── index.jsx │ └── scroll-to-section.jsx ├── search-autocomplete-with-api │ ├── index.jsx │ └── suggesstions.jsx ├── star-rating │ ├── index.jsx │ └── styles.css ├── tic-tact-toe │ ├── index.jsx │ └── styles.css ├── tree-view │ ├── data.js │ ├── index.jsx │ ├── menu-item.jsx │ ├── menu-list.jsx │ └── styles.css ├── use-fetch │ ├── index.jsx │ └── test.jsx ├── use-outside-click │ ├── index.jsx │ └── test.jsx └── use-window-resize │ ├── index.jsx │ └── test.jsx ├── index.css ├── index.js ├── logo.svg ├── reportWebVitals.js └── setupTests.js /.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 | # 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 your browser. 13 | 14 | The page will reload when you make changes.\ 15 | You may 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 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `npm run build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reactjs-interview-projects", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.17.0", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "react": "^18.2.0", 10 | "react-dom": "^18.2.0", 11 | "react-icons": "^4.12.0", 12 | "react-qr-code": "^2.0.12", 13 | "react-scripts": "5.0.1", 14 | "web-vitals": "^2.1.4" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "eslintConfig": { 23 | "extends": [ 24 | "react-app", 25 | "react-app/jest" 26 | ] 27 | }, 28 | "browserslist": { 29 | "production": [ 30 | ">0.2%", 31 | "not dead", 32 | "not op_mini all" 33 | ], 34 | "development": [ 35 | "last 1 chrome version", 36 | "last 1 firefox version", 37 | "last 1 safari version" 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sangammukherjee/25-reactjs-interview-projects/bf366c78d52d5288653c278f8ad6e869b4a6d8eb/public/favicon.ico -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sangammukherjee/25-reactjs-interview-projects/bf366c78d52d5288653c278f8ad6e869b4a6d8eb/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sangammukherjee/25-reactjs-interview-projects/bf366c78d52d5288653c278f8ad6e869b4a6d8eb/public/logo512.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import "./App.css"; 2 | import Accordian from "./components/accordian"; 3 | import ModalTest from "./components/custom-modal-popup/modal-test"; 4 | import TabTest from "./components/custom-tabs/tab-test"; 5 | import FeatureFlags from "./components/feature-flag"; 6 | import FeatureFlagGlobalState from "./components/feature-flag/context"; 7 | import GithubProfileFinder from "./components/github-profile-finder"; 8 | import ImageSlider from "./components/image-slider"; 9 | import LightDarkMode from "./components/light-dark-mode"; 10 | import LoadMoreData from "./components/load-more-data"; 11 | import QRCodeGenerator from "./components/qr-code-generator"; 12 | import RandomColor from "./components/random-color"; 13 | import ScrollIndicator from "./components/scroll-indicator"; 14 | import ScrollToTopAndBottom from "./components/scroll-to-top-and-bottom"; 15 | import ScrollToSection from "./components/scroll-to-top-and-bottom/scroll-to-section"; 16 | import SearchAutocomplete from "./components/search-autocomplete-with-api"; 17 | import StarRating from "./components/star-rating"; 18 | import TicTacToe from "./components/tic-tact-toe"; 19 | import TreeView from "./components/tree-view"; 20 | import menus from "./components/tree-view/data"; 21 | import UseFetchHookTest from "./components/use-fetch/test"; 22 | import UseOnclickOutsideTest from "./components/use-outside-click/test"; 23 | import UseWindowResizeTest from "./components/use-window-resize/test"; 24 | 25 | function App() { 26 | return ( 27 |
28 | {/* Accordian component */} 29 | {/* */} 30 | {/* Random color component */} 31 | {/* */} 32 | 33 | {/* Star rating component */} 34 | {/* */} 35 | 36 | {/* Image slider component */} 37 | {/* */} 42 | 43 | {/* Load more products component */} 44 | {/* */} 45 | 46 | {/* Tree view component/menu UI component / recursive navigation menu */} 47 | {/* */} 48 | 49 | {/* QR code generator */} 50 | {/* */} 51 | 52 | {/* light and dark theme switch */} 53 | {/* */} 54 | 55 | {/* Scroll indicator component */} 56 | {/* */} 57 | 58 | {/* Custom tabs component */} 59 | {/* */} 60 | 61 | {/* Custom Modal Component */} 62 | {/* */} 63 | 64 | {/* Github profile finder */} 65 | {/* */} 66 | 67 | {/* Search Autocomplete */} 68 | {/* */} 69 | 70 | {/* Tic tac toe */} 71 | {/* */} 72 | 73 | {/* Feature Flag IMplementation */} 74 | {/* 75 | 76 | */} 77 | 78 | {/* useFetch - Custom Hook Test*/} 79 | {/* */} 80 | 81 | {/* Use Onclick Outside Hook Test */} 82 | {/* */} 83 | 84 | {/* Use Window Resize Hook Test */} 85 | {/* */} 86 | 87 | {/* Scroll to Top and Bottom */} 88 | {/* */} 89 | 90 | {/* Scroll to a Particular Section */} 91 | 92 |
93 | ); 94 | } 95 | 96 | export default App; 97 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /src/components/accordian/data.js: -------------------------------------------------------------------------------- 1 | const data = [ 2 | { 3 | id : '1', 4 | question: "What are accordion components?", 5 | answer: 6 | "Accordion components are user interface elements used for organizing and presenting content in a collapsible manner. They typically consist of a header, content, and an expand/collapse action.", 7 | }, 8 | { 9 | id : '2', 10 | question: "What are they used for?", 11 | answer: 12 | "They are commonly employed in various contexts, including FAQs, product descriptions, navigation menus, settings panels, and data tables, to save screen space and provide a structured and user-friendly interface for presenting information or options.", 13 | }, 14 | { 15 | id : '3', 16 | question: "Accordion as a musical instrument", 17 | answer: 18 | "The accordion is a musical instrument with a keyboard and bellows. It produces sound by air passing over reeds when the player expands or compresses the bellows, used in various music genres.", 19 | }, 20 | { 21 | id : '4', 22 | question: "Can I create an accordion component with a different framework?", 23 | answer: 24 | "Yes of course, it is very possible to create an accordion component with another framework.", 25 | }, 26 | ]; 27 | 28 | export default data; -------------------------------------------------------------------------------- /src/components/accordian/index.jsx: -------------------------------------------------------------------------------- 1 | //single selection 2 | //multiple selection 3 | 4 | import { useState } from "react"; 5 | import data from "./data"; 6 | import "./styles.css"; 7 | 8 | export default function Accordian() { 9 | const [selected, setSelected] = useState(null); 10 | const [enableMultiSelection, setEnableMultiSelection] = useState(false); 11 | const [multiple, setMultiple] = useState([]); 12 | 13 | function handleSingleSelection(getCurrentId) { 14 | setSelected(getCurrentId === selected ? null : getCurrentId); 15 | } 16 | 17 | function handleMultiSelection(getCurrentId) { 18 | let cpyMutiple = [...multiple]; 19 | const findIndexOfCurrentId = cpyMutiple.indexOf(getCurrentId); 20 | 21 | console.log(findIndexOfCurrentId); 22 | if (findIndexOfCurrentId === -1) cpyMutiple.push(getCurrentId); 23 | else cpyMutiple.splice(findIndexOfCurrentId, 1); 24 | 25 | setMultiple(cpyMutiple); 26 | } 27 | 28 | console.log(selected, multiple); 29 | return ( 30 |
31 | 34 |
35 | {data && data.length > 0 ? ( 36 | data.map((dataItem) => ( 37 |
38 |
handleMultiSelection(dataItem.id) 42 | : () => handleSingleSelection(dataItem.id) 43 | } 44 | className="title" 45 | > 46 |

{dataItem.question}

47 | + 48 |
49 | {enableMultiSelection 50 | ? multiple.indexOf(dataItem.id) !== -1 && ( 51 |
{dataItem.answer}
52 | ) 53 | : selected === dataItem.id && ( 54 |
{dataItem.answer}
55 | )} 56 | {/* {selected === dataItem.id || 57 | multiple.indexOf(dataItem.id) !== -1 ? ( 58 |
{dataItem.answer}
59 | ) : null} */} 60 |
61 | )) 62 | ) : ( 63 |
No data found !
64 | )} 65 |
66 |
67 | ); 68 | } 69 | -------------------------------------------------------------------------------- /src/components/accordian/styles.css: -------------------------------------------------------------------------------- 1 | .acc-wrapper { 2 | display: flex; 3 | height: 100vh; 4 | width: 100vw; 5 | justify-content: center; 6 | align-items: center; 7 | flex-direction: column; 8 | gap: 20px; 9 | } 10 | 11 | .acc-wrapper button { 12 | padding: 10px 20px; 13 | background: #614101; 14 | color: #fff; 15 | font-weight: bold; 16 | font-size: 20px; 17 | cursor: pointer; 18 | } 19 | 20 | .accordian { 21 | width: 500px; 22 | } 23 | 24 | .item { 25 | background: #614101; 26 | margin-bottom: 10px; 27 | padding: 10px 20px; 28 | } 29 | 30 | .title { 31 | color: #ffffff; 32 | display: flex; 33 | justify-content: space-between; 34 | align-items: center; 35 | cursor: pointer; 36 | } 37 | 38 | .acc-content { 39 | color: #ffffff; 40 | height: auto; 41 | } 42 | -------------------------------------------------------------------------------- /src/components/custom-modal-popup/modal-test.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import Modal from "./modal"; 3 | import "./modal.css"; 4 | 5 | export default function ModalTest() { 6 | const [showModalPopup, setShowModalPopup] = useState(false); 7 | 8 | function handleToggleModalPopup() { 9 | setShowModalPopup(!showModalPopup); 10 | } 11 | 12 | function onClose() { 13 | setShowModalPopup(false); 14 | } 15 | 16 | return ( 17 |
18 | 19 | {showModalPopup && ( 20 | Customized Header} 23 | footer={

Customized Footer

} 24 | onClose={onClose} 25 | body={
Customized body
} 26 | /> 27 | )} 28 |
29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /src/components/custom-modal-popup/modal.css: -------------------------------------------------------------------------------- 1 | .modal { 2 | position: fixed; 3 | z-index: 1; 4 | padding-top: 150px; 5 | left: 0; 6 | top: 0; 7 | width: 100%; 8 | height: 100%; 9 | overflow: auto; 10 | background-color: #baf005; 11 | } 12 | 13 | .modal-content { 14 | position: relative; 15 | background-color: #fefefe; 16 | margin: auto; 17 | padding: 0; 18 | border: 1px solid red; 19 | width: 80%; 20 | animation-name: animateModal; 21 | animation-duration: 0.5s; 22 | } 23 | 24 | .close-modal-icon { 25 | cursor: pointer; 26 | font-size: 40px; 27 | float: right; 28 | font-weight: bold; 29 | } 30 | 31 | .header { 32 | padding: 4px 16px; 33 | background-color: #5cb85c; 34 | color: #fff; 35 | } 36 | 37 | .body { 38 | padding: 2px 16px; 39 | height: 200px; 40 | } 41 | 42 | .footer { 43 | padding: 2px 16px; 44 | background-color: #5cb85c; 45 | color: #fff; 46 | } 47 | 48 | @keyframes animateModal { 49 | from { 50 | top: -200px; 51 | opacity: 0; 52 | } 53 | 54 | to { 55 | top: 0; 56 | opacity: 1; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/components/custom-modal-popup/modal.jsx: -------------------------------------------------------------------------------- 1 | export default function Modal({ id, header, body, footer, onClose }) { 2 | return ( 3 |
4 |
5 |
6 | × 7 |

{header ? header : "Header"}

8 |
9 |
10 | {body ? ( 11 | body 12 | ) : ( 13 |
14 |

This is our Modal Body

15 |
16 | )} 17 |
18 |
{footer ? footer :

Footer

}
19 |
20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /src/components/custom-tabs/tab-test.jsx: -------------------------------------------------------------------------------- 1 | import Tabs from "./tabs"; 2 | import './tabs.css'; 3 | 4 | function RandomComponent() { 5 | return

Some random content

; 6 | } 7 | 8 | export default function TabTest() { 9 | const tabs = [ 10 | { 11 | label: "Tab 1", 12 | content:
This is content for Tab 1
, 13 | }, 14 | { 15 | label: "Tab 2", 16 | content:
This is content for Tab 2
, 17 | }, 18 | { 19 | label: "Tab 3", 20 | content: , 21 | }, 22 | ]; 23 | 24 | function handleChange(currentTabIndex) { 25 | console.log(currentTabIndex); 26 | } 27 | 28 | return ; 29 | } 30 | -------------------------------------------------------------------------------- /src/components/custom-tabs/tabs.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | padding: 8px; 3 | } 4 | 5 | .heading { 6 | display: flex; 7 | justify-content: center; 8 | margin-bottom: 12px; 9 | } 10 | 11 | .tab-item { 12 | display: inline-flex; 13 | font-size: 30px; 14 | font-weight: bold; 15 | text-align: center; 16 | padding: 10px 15px; 17 | cursor: pointer; 18 | border: none; 19 | color: #fff; 20 | background: #4e016a; 21 | } 22 | 23 | .tab-item.active { 24 | border-color: #000; 25 | background: #a1d600; 26 | color: #fff; 27 | } 28 | 29 | .content { 30 | padding: 20px 10px; 31 | height: 300px; 32 | overflow: auto; 33 | background-color: #fff; 34 | } 35 | -------------------------------------------------------------------------------- /src/components/custom-tabs/tabs.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | export default function Tabs({ tabsContent, onChange }) { 4 | const [currentTabIndex, setCurrentTabIndex] = useState(0); 5 | 6 | function handleOnClick(getCurrentIndex) { 7 | setCurrentTabIndex(getCurrentIndex); 8 | onChange(getCurrentIndex); 9 | } 10 | 11 | return ( 12 |
13 |
14 | {tabsContent.map((tabItem, index) => ( 15 |
handleOnClick(index)} 18 | key={tabItem.label} 19 | > 20 | {tabItem.label} 21 |
22 | ))} 23 |
24 |
25 | {tabsContent[currentTabIndex] && tabsContent[currentTabIndex].content} 26 |
27 |
28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /src/components/feature-flag/context/index.jsx: -------------------------------------------------------------------------------- 1 | import { createContext, useEffect, useState } from "react"; 2 | import featureFlagsDataServiceCall from "../data"; 3 | 4 | export const FeatureFlagsContext = createContext(null); 5 | 6 | export default function FeatureFlagGlobalState({ children }) { 7 | const [loading, setLoading] = useState(false); 8 | const [enabledFlags, setEnabledFlags] = useState({}); 9 | 10 | async function fetchFeatureFlags() { 11 | try { 12 | setLoading(true); 13 | //original service call 14 | const response = await featureFlagsDataServiceCall(); 15 | setEnabledFlags(response); 16 | setLoading(false); 17 | } catch (error) { 18 | console.log(error); 19 | setLoading(false); 20 | throw new Error(error); 21 | } 22 | } 23 | 24 | useEffect(() => { 25 | fetchFeatureFlags(); 26 | }, []); 27 | 28 | return ( 29 | 30 | {children} 31 | 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /src/components/feature-flag/data.js: -------------------------------------------------------------------------------- 1 | const dummyApiResponse = { 2 | showLightAndDarkMode: true, 3 | showTicTacToeBoard: true, 4 | showRandomColorGenerator: true, 5 | showAccordian: true, 6 | showTreeView: true, 7 | showTabs : true 8 | }; 9 | 10 | function featureFlagsDataServiceCall() { 11 | return new Promise((resolve, reject) => { 12 | if (dummyApiResponse) setTimeout(resolve(dummyApiResponse), 500); 13 | else reject("Some error occured! Please try again"); 14 | }); 15 | } 16 | 17 | export default featureFlagsDataServiceCall; 18 | -------------------------------------------------------------------------------- /src/components/feature-flag/index.jsx: -------------------------------------------------------------------------------- 1 | import { useContext } from "react"; 2 | import Accordian from "../accordian"; 3 | import LightDarkMode from "../light-dark-mode"; 4 | import RandomColor from "../random-color"; 5 | import TicTacToe from "../tic-tact-toe"; 6 | import TreeView from "../tree-view"; 7 | import { FeatureFlagsContext } from "./context"; 8 | import menus from "../tree-view/data"; 9 | import TabTest from "../custom-tabs/tab-test"; 10 | 11 | export default function FeatureFlags() { 12 | const { loading, enabledFlags } = useContext(FeatureFlagsContext); 13 | 14 | const componentsToRender = [ 15 | { 16 | key: "showLightAndDarkMode", 17 | component: , 18 | }, 19 | { 20 | key: "showTicTacToeBoard", 21 | component: , 22 | }, 23 | { 24 | key: "showRandomColorGenerator", 25 | component: , 26 | }, 27 | { 28 | key: "showAccordian", 29 | component: , 30 | }, 31 | { 32 | key: "showTreeView", 33 | component: , 34 | }, 35 | { 36 | key : 'showTabs', 37 | component : 38 | } 39 | ]; 40 | 41 | function checkEnabledFlags(getCurrentKey) { 42 | return enabledFlags[getCurrentKey]; 43 | } 44 | 45 | if (loading) return

Loading data ! Please wait

; 46 | 47 | return ( 48 |
49 |

Feature Flags

50 | {componentsToRender.map((componentItem) => 51 | checkEnabledFlags(componentItem.key) ? componentItem.component : null 52 | )} 53 |
54 | ); 55 | } 56 | -------------------------------------------------------------------------------- /src/components/github-profile-finder/index.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import User from "./user"; 3 | import './styles.css'; 4 | 5 | export default function GithubProfileFinder() { 6 | const [userName, setUserName] = useState("sangammukherjee"); 7 | const [userData, setUserData] = useState(null); 8 | const [loading, setLoading] = useState(true); 9 | 10 | async function fetchGithubUserData() { 11 | setLoading(true); 12 | const res = await fetch(`https://api.github.com/users/${userName}`); 13 | 14 | const data = await res.json(); 15 | if (data) { 16 | setUserData(data); 17 | setLoading(false); 18 | setUserName('') 19 | } 20 | } 21 | 22 | function handleSubmit() { 23 | fetchGithubUserData() 24 | } 25 | 26 | useEffect(() => { 27 | fetchGithubUserData(); 28 | }, []); 29 | 30 | if (loading) { 31 | return

Loading data ! Please wait

; 32 | } 33 | 34 | return ( 35 |
36 |
37 | setUserName(event.target.value)} 43 | /> 44 | 45 |
46 | {userData !== null ? : null} 47 |
48 | ); 49 | } 50 | -------------------------------------------------------------------------------- /src/components/github-profile-finder/styles.css: -------------------------------------------------------------------------------- 1 | .github-profile-container { 2 | margin: 0 auto; 3 | width: 90%; 4 | max-width: 1000px; 5 | padding: 20px; 6 | border-radius: 8px; 7 | } 8 | 9 | .input-wrapper { 10 | display: flex; 11 | gap: 20px; 12 | justify-content: center; 13 | margin-bottom: 20px; 14 | } 15 | 16 | .input-wrapper input { 17 | padding: 12px; 18 | font-size: 16px; 19 | border: none; 20 | } 21 | 22 | .input-wrapper button { 23 | padding: 5px 12px; 24 | border: none; 25 | border-radius: 8px; 26 | background-color: #00f4ec; 27 | color: #000; 28 | cursor: pointer; 29 | } 30 | 31 | .user{ 32 | padding: 15px; 33 | border-radius: 10px; 34 | border: 1px solid; 35 | } 36 | 37 | .avatar{ 38 | height: 150px; 39 | aspect-ratio: 1/1; 40 | border-radius: 50%; 41 | } 42 | 43 | 44 | .name-container{ 45 | display: flex; 46 | gap: 20px; 47 | justify-content: center; 48 | margin-top: 20px; 49 | } 50 | 51 | .name-container p{ 52 | margin: 0px; 53 | font-size: 20px; 54 | font-weight: bold; 55 | } 56 | 57 | .profile-info div{ 58 | display: flex; 59 | justify-content: center; 60 | gap: 20px; 61 | font-size: 20px; 62 | font-weight: bold; 63 | } -------------------------------------------------------------------------------- /src/components/github-profile-finder/user.jsx: -------------------------------------------------------------------------------- 1 | export default function User({ user }) { 2 | const { 3 | avatar_url, 4 | followers, 5 | following, 6 | public_repos, 7 | name, 8 | login, 9 | created_at, 10 | } = user; 11 | 12 | const createdDate = new Date(created_at); 13 | 14 | return ( 15 |
16 |
17 | User 18 |
19 |
20 | {name || login} 21 |

22 | User joined on{" "} 23 | {`${createdDate.getDate()} ${createdDate.toLocaleString("en-us", { 24 | month: "short", 25 | })} ${createdDate.getFullYear()}`} 26 |

27 |
28 |
29 |
30 |

Public Repos

31 |

{public_repos}

32 |
33 |
34 |

Followers

35 |

{followers}

36 |
37 |
38 |

Following

39 |

{following}

40 |
41 |
42 |
43 | ); 44 | } 45 | -------------------------------------------------------------------------------- /src/components/image-slider/index.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { BsArrowLeftCircleFill, BsArrowRightCircleFill } from "react-icons/bs"; 3 | import "./styles.css"; 4 | 5 | export default function ImageSlider({ url, limit = 5, page = 1 }) { 6 | const [images, setImages] = useState([]); 7 | const [currentSlide, setCurrentSlide] = useState(0); 8 | const [errorMsg, setErrorMsg] = useState(null); 9 | const [loading, setLoading] = useState(false); 10 | 11 | async function fetchImages(getUrl) { 12 | try { 13 | setLoading(true); 14 | 15 | const response = await fetch(`${getUrl}?page=${page}&limit=${limit}`); 16 | const data = await response.json(); 17 | 18 | if (data) { 19 | setImages(data); 20 | setLoading(false); 21 | } 22 | } catch (e) { 23 | setErrorMsg(e.message); 24 | setLoading(false); 25 | } 26 | } 27 | 28 | function handlePrevious() { 29 | setCurrentSlide(currentSlide === 0 ? images.length - 1 : currentSlide - 1); 30 | } 31 | 32 | function handleNext() { 33 | setCurrentSlide(currentSlide === images.length - 1 ? 0 : currentSlide + 1); 34 | } 35 | 36 | useEffect(() => { 37 | if (url !== "") fetchImages(url); 38 | }, [url]); 39 | 40 | console.log(images); 41 | 42 | if (loading) { 43 | return
Loading data ! Please wait
; 44 | } 45 | 46 | if (errorMsg !== null) { 47 | return
Error occured ! {errorMsg}
; 48 | } 49 | 50 | return ( 51 |
52 | 56 | {images && images.length 57 | ? images.map((imageItem, index) => ( 58 | {imageItem.download_url} 68 | )) 69 | : null} 70 | 74 | 75 | {images && images.length 76 | ? images.map((_, index) => ( 77 | 86 | )) 87 | : null} 88 | 89 |
90 | ); 91 | } 92 | -------------------------------------------------------------------------------- /src/components/image-slider/styles.css: -------------------------------------------------------------------------------- 1 | .container { 2 | position: relative; 3 | display: flex; 4 | justify-content: center; 5 | align-items: center; 6 | width: 600px; 7 | height: 450px; 8 | } 9 | 10 | .current-image { 11 | border-radius: 0.5rem; 12 | box-shadow: 0px 0px 7px #666; 13 | width: 100%; 14 | height: 100%; 15 | } 16 | 17 | .arrow { 18 | position: absolute; 19 | width: 2rem; 20 | height: 2rem; 21 | color: #fff; 22 | filter: drop-shadow(0px 0px 5px #555); 23 | } 24 | 25 | .arrow-left { 26 | left: 1rem; 27 | } 28 | 29 | .arrow-right { 30 | right: 1rem; 31 | } 32 | 33 | .circle-indicators { 34 | display: flex; 35 | position: absolute; 36 | bottom: 1rem; 37 | } 38 | 39 | .current-indicator { 40 | background-color: #ffffff; 41 | height: 15px; 42 | width: 15px; 43 | border-radius: 50%; 44 | border: none; 45 | outline: none; 46 | margin: 0 0.2rem; 47 | cursor: pointer; 48 | } 49 | 50 | .hide-current-image{ 51 | display: none; 52 | } 53 | 54 | .inactive-indicator{ 55 | background-color: gray; 56 | } 57 | -------------------------------------------------------------------------------- /src/components/light-dark-mode/index.jsx: -------------------------------------------------------------------------------- 1 | import useLocalStroage from "./useLocalStroage"; 2 | import './theme.css' 3 | 4 | export default function LightDarkMode() { 5 | const [theme, setTheme] = useLocalStroage("theme", "dark"); 6 | 7 | function handleToggleTheme() { 8 | setTheme(theme === "light" ? "dark" : "light"); 9 | } 10 | 11 | console.log(theme); 12 | 13 | return ( 14 |
15 |
16 |

Hello World !

17 | 18 |
19 |
20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /src/components/light-dark-mode/theme.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --background: #ffffff; 3 | --text-primary: #000; 4 | --button-bg: #000; 5 | --button-text: #ffffff; 6 | } 7 | 8 | [data-theme="dark"] { 9 | --background: #000000; 10 | --text-primary: #fff; 11 | --button-bg: #fff; 12 | --button-text: #000; 13 | } 14 | .light-dark-mode { 15 | background-color: var(--background); 16 | height: 100vh; 17 | display: flex; 18 | flex-direction: column; 19 | justify-content: center; 20 | font-size: 20px; 21 | transition: all 0.5s; 22 | } 23 | 24 | .light-dark-mode .container { 25 | display: flex; 26 | justify-content: center; 27 | align-items: center; 28 | flex-direction: column; 29 | gap: 30px; 30 | } 31 | 32 | .light-dark-mode .container p { 33 | color: var(--text-primary); 34 | font-size: 40px; 35 | margin: 0px; 36 | } 37 | 38 | .light-dark-mode .container button { 39 | background-color: var(--button-bg); 40 | border: 1px solid var(--button-bg); 41 | color: var(--button-text); 42 | padding: 12px; 43 | border-radius: 8px; 44 | font-weight: 600; 45 | cursor: pointer; 46 | } 47 | -------------------------------------------------------------------------------- /src/components/light-dark-mode/useLocalStroage.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | import { useState } from "react"; 3 | 4 | export default function useLocalStroage(key, defaultValue) { 5 | const [value, setValue] = useState(() => { 6 | let currentValue; 7 | 8 | try { 9 | currentValue = JSON.parse( 10 | localStorage.getItem(key) || String(defaultValue) 11 | ); 12 | } catch (error) { 13 | console.log(error); 14 | currentValue = defaultValue; 15 | } 16 | 17 | return currentValue; 18 | }); 19 | 20 | useEffect(() => { 21 | localStorage.setItem(key, JSON.stringify(value)); 22 | }, [key, value]); 23 | 24 | return [value, setValue]; 25 | } 26 | -------------------------------------------------------------------------------- /src/components/load-more-data/index.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import "./styles.css"; 3 | 4 | export default function LoadMoreData() { 5 | const [loading, setLoading] = useState(false); 6 | const [products, setProducts] = useState([]); 7 | const [count, setCount] = useState(0); 8 | const [disableButton, setDisableButton] = useState(false); 9 | 10 | async function fetchProducts() { 11 | try { 12 | setLoading(true); 13 | const response = await fetch( 14 | `https://dummyjson.com/products?limit=20&skip=${ 15 | count === 0 ? 0 : count * 20 16 | }` 17 | ); 18 | 19 | const result = await response.json(); 20 | 21 | if (result && result.products && result.products.length) { 22 | setProducts((prevData) => [...prevData, ...result.products]); 23 | setLoading(false); 24 | } 25 | 26 | console.log(result); 27 | } catch (e) { 28 | console.log(e); 29 | setLoading(false); 30 | } 31 | } 32 | 33 | useEffect(() => { 34 | fetchProducts(); 35 | }, [count]); 36 | 37 | useEffect(() => { 38 | if (products && products.length === 100) setDisableButton(true); 39 | }, [products]); 40 | 41 | if (loading) { 42 | return
Loading data ! Please wait.
; 43 | } 44 | 45 | return ( 46 |
47 |
48 | {products && products.length 49 | ? products.map((item) => ( 50 |
51 | {item.title} 52 |

{item.title}

53 |
54 | )) 55 | : null} 56 |
57 |
58 | 61 | {disableButton ?

You have reached to 100 products

: null} 62 |
63 |
64 | ); 65 | } 66 | -------------------------------------------------------------------------------- /src/components/load-more-data/styles.css: -------------------------------------------------------------------------------- 1 | .load-more-container { 2 | display: flex; 3 | flex-direction: column; 4 | gap: 20px; 5 | } 6 | 7 | .product-container{ 8 | display: grid; 9 | grid-template-columns: repeat(4, 1fr); 10 | gap: 10px; 11 | } 12 | 13 | .product{ 14 | padding: 20px; 15 | border: 1px solid; 16 | display: flex; 17 | flex-direction: column; 18 | gap: 10px; 19 | } 20 | 21 | .product img{ 22 | width: 200px; 23 | height: 200px; 24 | } -------------------------------------------------------------------------------- /src/components/qr-code-generator/index.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import QRCode from "react-qr-code"; 3 | 4 | export default function QRCodeGenerator() { 5 | const [qrCode, setQrCode] = useState(""); 6 | const [input, setInput] = useState(""); 7 | 8 | function handleGenerateQrCode() { 9 | setQrCode(input); 10 | setInput('') 11 | } 12 | 13 | return ( 14 |
15 |

QR Code Generator

16 |
17 | setInput(e.target.value)} 19 | type="text" 20 | name="qr-code" 21 | value={input} 22 | placeholder="Enter your value here" 23 | /> 24 | 30 |
31 |
32 | 33 |
34 |
35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /src/components/qr-code-generator/styles.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sangammukherjee/25-reactjs-interview-projects/bf366c78d52d5288653c278f8ad6e869b4a6d8eb/src/components/qr-code-generator/styles.css -------------------------------------------------------------------------------- /src/components/random-color/index.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | export default function RandomColor() { 4 | const [typeOfColor, setTypeOfColor] = useState("hex"); 5 | const [color, setColor] = useState("#000000"); 6 | 7 | function randomColorUtility(length) { 8 | return Math.floor(Math.random() * length); 9 | } 10 | 11 | function handleCreateRandomHexColor() { 12 | // #678765 13 | const hex = [1, 2, 3, 4, 5, 6, 7, 8, 9, "A", "B", "C", "D", "E", "F"]; 14 | let hexColor = "#"; 15 | 16 | for (let i = 0; i < 6; i++) { 17 | hexColor += hex[randomColorUtility(hex.length)]; 18 | } 19 | setColor(hexColor); 20 | } 21 | 22 | function handleCreateRandomRgbColor() { 23 | const r = randomColorUtility(256); 24 | const g = randomColorUtility(256); 25 | const b = randomColorUtility(256); 26 | 27 | setColor(`rgb(${r},${g}, ${b})`); 28 | } 29 | 30 | useEffect(() => { 31 | if (typeOfColor === "rgb") handleCreateRandomRgbColor(); 32 | else handleCreateRandomHexColor(); 33 | }, [typeOfColor]); 34 | 35 | return ( 36 |
43 | 44 | 45 | 54 |
66 |

{typeOfColor === "rgb" ? "RGB Color" : "HEX Color"}

67 |

{color}

68 |
69 |
70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /src/components/scroll-indicator/index.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import "./scroll.css"; 3 | 4 | export default function ScrollIndicator({ url }) { 5 | const [data, setData] = useState([]); 6 | const [loading, setLoading] = useState(false); 7 | const [errorMessage, setErrorMessage] = useState(""); 8 | const [scrollPercentage, setScrollPercentage] = useState(0); 9 | 10 | async function fetchData(getUrl) { 11 | try { 12 | setLoading(true); 13 | const response = await fetch(getUrl); 14 | const data = await response.json(); 15 | if (data && data.products && data.products.length > 0) { 16 | setData(data.products); 17 | setLoading(false); 18 | } 19 | } catch (e) { 20 | console.log(e); 21 | setErrorMessage(e.message); 22 | } 23 | } 24 | 25 | useEffect(() => { 26 | fetchData(url); 27 | }, [url]); 28 | 29 | function handleScrollPercentage() { 30 | console.log( 31 | document.body.scrollTop, 32 | document.documentElement.scrollTop, 33 | document.documentElement.scrollHeight, 34 | document.documentElement.clientHeight 35 | ); 36 | 37 | const howMuchScrolled = 38 | document.body.scrollTop || document.documentElement.scrollTop; 39 | 40 | const height = 41 | document.documentElement.scrollHeight - 42 | document.documentElement.clientHeight; 43 | 44 | setScrollPercentage((howMuchScrolled / height) * 100); 45 | } 46 | 47 | useEffect(() => { 48 | window.addEventListener("scroll", handleScrollPercentage); 49 | 50 | return () => { 51 | window.removeEventListener("scroll", () => {}); 52 | }; 53 | }, []); 54 | 55 | console.log(data, scrollPercentage); 56 | 57 | if (errorMessage) { 58 | return
Error ! {errorMessage}
; 59 | } 60 | 61 | if (loading) { 62 | return
Loading data ! Pleaae wait
; 63 | } 64 | 65 | return ( 66 |
67 |
68 |

Custom Scroll Indicator

69 |
70 |
74 |
75 |
76 |
77 | {data && data.length > 0 78 | ? data.map((dataItem) =>

{dataItem.title}

) 79 | : null} 80 |
81 |
82 | ); 83 | } 84 | -------------------------------------------------------------------------------- /src/components/scroll-indicator/scroll.css: -------------------------------------------------------------------------------- 1 | .top-container{ 2 | position: fixed; 3 | top: 0; 4 | z-index: 1; 5 | width: 100%; 6 | text-align: center; 7 | background-color: #075b0a; 8 | color: #fff; 9 | } 10 | 11 | .scroll-progress-tracking-container{ 12 | width: 100%; 13 | height: 10px; 14 | background: #aaf900; 15 | } 16 | 17 | .current-progress-bar{ 18 | height: 10px; 19 | background: #8b02b5; 20 | width: 0%; 21 | } 22 | 23 | .data-container{ 24 | margin-top: 100px; 25 | } -------------------------------------------------------------------------------- /src/components/scroll-to-top-and-bottom/index.jsx: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import useFetch from "../use-fetch"; 3 | 4 | export default function ScrollToTopAndBottom() { 5 | const { data, error, pending } = useFetch( 6 | "https://dummyjson.com/products?limit=100", 7 | {} 8 | ); 9 | 10 | const bottomRef = useRef(null); 11 | 12 | function handleScrollToTop() { 13 | window.scrollTo({ 14 | top: 0, 15 | left: 0, 16 | behavior: "smooth", 17 | }); 18 | } 19 | 20 | function handleScrollToBottom() { 21 | bottomRef.current.scrollIntoView({ behavior: "smooth" }); 22 | } 23 | 24 | if (error) { 25 | return

Error occured ! Please try again.

; 26 | } 27 | 28 | if (pending) { 29 | return

Loading ! Please wait

; 30 | } 31 | 32 | return ( 33 |
34 |

Scroll To Top And Bottom Feature

35 |

This is the top section

36 | 37 |
    38 | {data && data.products && data.products.length 39 | ? data.products.map((item) =>
  • {item.title}
  • ) 40 | : null} 41 |
42 | 43 |
44 |

This is the bottom of the page

45 |
46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /src/components/scroll-to-top-and-bottom/scroll-to-section.jsx: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | 3 | export default function ScrollToSection() { 4 | const ref = useRef(); 5 | 6 | const data = [ 7 | { 8 | label: "First Card", 9 | style: { 10 | width: "100%", 11 | height: "600px", 12 | background: "red", 13 | }, 14 | }, 15 | { 16 | label: "Second Card", 17 | style: { 18 | width: "100%", 19 | height: "600px", 20 | background: "grey", 21 | }, 22 | }, 23 | { 24 | label: "Third Card", 25 | style: { 26 | width: "100%", 27 | height: "600px", 28 | background: "blue", 29 | }, 30 | }, 31 | { 32 | label: "Fourth Card", 33 | style: { 34 | width: "100%", 35 | height: "600px", 36 | background: "green", 37 | }, 38 | }, 39 | { 40 | label: "Fifth Card", 41 | style: { 42 | width: "100%", 43 | height: "600px", 44 | background: "orange", 45 | }, 46 | }, 47 | ]; 48 | 49 | function handleScrollToSection() { 50 | let pos = ref.current.getBoundingClientRect().top; 51 | 52 | window.scrollTo({ 53 | top: pos, 54 | behavior: "smooth", 55 | }); 56 | } 57 | 58 | return ( 59 |
60 |

Scroll to a particular section

61 | 62 | {data.map((dataItem, index) => ( 63 |
64 |

{dataItem.label}

65 |
66 | ))} 67 |
68 | ); 69 | } 70 | -------------------------------------------------------------------------------- /src/components/search-autocomplete-with-api/index.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import Suggestions from "./suggesstions"; 3 | 4 | export default function SearchAutocomplete() { 5 | const [loading, setLoading] = useState(false); 6 | const [users, setUsers] = useState([]); 7 | const [error, setError] = useState(null); 8 | const [searchParam, setSearchParam] = useState(""); 9 | const [showDropdown, setShowDropdown] = useState(false); 10 | const [filteredUsers, setFilteredUsers] = useState([]); 11 | 12 | function handleChange(event) { 13 | const query = event.target.value.toLowerCase(); 14 | setSearchParam(query); 15 | if (query.length > 1) { 16 | const filteredData = 17 | users && users.length 18 | ? users.filter((item) => item.toLowerCase().indexOf(query) > -1) 19 | : []; 20 | setFilteredUsers(filteredData); 21 | setShowDropdown(true); 22 | } else { 23 | setShowDropdown(false); 24 | } 25 | } 26 | 27 | function handleClick(event){ 28 | setShowDropdown(false) 29 | setSearchParam(event.target.innerText) 30 | setFilteredUsers([]) 31 | } 32 | 33 | async function fetchListOfUsers() { 34 | try { 35 | setLoading(true); 36 | const response = await fetch("https://dummyjson.com/users"); 37 | const data = await response.json(); 38 | 39 | if (data && data.users && data.users.length) { 40 | setUsers(data.users.map((userItem) => userItem.firstName)); 41 | setLoading(false); 42 | setError(null); 43 | } 44 | } catch (error) { 45 | setLoading(false); 46 | console.log(error); 47 | setError(error); 48 | } 49 | } 50 | 51 | useEffect(() => { 52 | fetchListOfUsers(); 53 | }, []); 54 | 55 | console.log(users, filteredUsers); 56 | 57 | return ( 58 |
59 | {loading ? ( 60 |

Loading Data ! Please wait

61 | ) : ( 62 | 68 | )} 69 | 70 | {showDropdown && } 71 |
72 | ); 73 | } 74 | -------------------------------------------------------------------------------- /src/components/search-autocomplete-with-api/suggesstions.jsx: -------------------------------------------------------------------------------- 1 | export default function Suggestions({ data, handleClick }) { 2 | return ( 3 |
    4 | {data && data.length 5 | ? data.map((item, index) => ( 6 |
  • 7 | {item} 8 |
  • 9 | )) 10 | : null} 11 |
12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/components/star-rating/index.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { FaStar } from "react-icons/fa"; 3 | import './styles.css'; 4 | 5 | export default function StarRating({ noOfStars = 5 }) { 6 | const [rating, setRating] = useState(0); 7 | const [hover, setHover] = useState(0); 8 | 9 | function handleClick(getCurrentIndex) { 10 | setRating(getCurrentIndex); 11 | } 12 | 13 | function handleMouseEnter(getCurrentIndex) { 14 | setHover(getCurrentIndex); 15 | } 16 | 17 | function handleMouseLeave() { 18 | setHover(rating); 19 | } 20 | 21 | return ( 22 |
23 | {[...Array(noOfStars)].map((_, index) => { 24 | index += 1; 25 | 26 | return ( 27 | handleClick(index)} 31 | onMouseMove={() => handleMouseEnter(index)} 32 | onMouseLeave={() => handleMouseLeave()} 33 | size={40} 34 | /> 35 | ); 36 | })} 37 |
38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /src/components/star-rating/styles.css: -------------------------------------------------------------------------------- 1 | .active { 2 | color: #fff700; 3 | } 4 | 5 | .inactive { 6 | color: #000000; 7 | } 8 | -------------------------------------------------------------------------------- /src/components/tic-tact-toe/index.jsx: -------------------------------------------------------------------------------- 1 | // 0 1 2 2 | // 3 4 5 3 | // 6 7 8 4 | 5 | import { useEffect, useState } from "react"; 6 | import "./styles.css"; 7 | 8 | function Square({ value, onClick }) { 9 | return ( 10 | 13 | ); 14 | } 15 | 16 | export default function TicTacToe() { 17 | const [squares, setSquares] = useState(Array(9).fill("")); 18 | const [isXTurn, setIsXTurn] = useState(true); 19 | const [status, setStatus] = useState(""); 20 | 21 | function getWinner(squares) { 22 | const winningPatterns = [ 23 | [0, 1, 2], 24 | [3, 4, 5], 25 | [6, 7, 8], 26 | [2, 5, 8], 27 | [0, 4, 8], 28 | [2, 4, 6], 29 | [0, 3, 6], 30 | [1, 4, 7], 31 | ]; 32 | 33 | for (let i = 0; i < winningPatterns.length; i++) { 34 | const [x, y, z] = winningPatterns[i]; 35 | 36 | if ( 37 | squares[x] && 38 | squares[x] === squares[y] && 39 | squares[x] === squares[z] 40 | ) { 41 | return squares[x]; 42 | } 43 | } 44 | 45 | return null; 46 | } 47 | 48 | function handleClick(getCurrentSquare) { 49 | let cpySquares = [...squares]; 50 | if (getWinner(cpySquares) || cpySquares[getCurrentSquare]) return; 51 | cpySquares[getCurrentSquare] = isXTurn ? "X" : "O"; 52 | setIsXTurn(!isXTurn); 53 | setSquares(cpySquares); 54 | } 55 | 56 | function handleRestart() { 57 | setIsXTurn(true); 58 | setSquares(Array(9).fill("")); 59 | } 60 | 61 | useEffect(() => { 62 | if (!getWinner(squares) && squares.every((item) => item !== "")) { 63 | setStatus(`This is a draw ! Please restart the game`); 64 | } else if (getWinner(squares)) { 65 | setStatus(`Winner is ${getWinner(squares)}. Please restart the game`); 66 | } else { 67 | setStatus(`Next player is ${isXTurn ? "X" : "O"}`); 68 | } 69 | }, [squares, isXTurn]); 70 | 71 | console.log(squares); 72 | 73 | return ( 74 |
75 |
76 | handleClick(0)} /> 77 | handleClick(1)} /> 78 | handleClick(2)} /> 79 |
80 |
81 | handleClick(3)} /> 82 | handleClick(4)} /> 83 | handleClick(5)} /> 84 |
85 |
86 | handleClick(6)} /> 87 | handleClick(7)} /> 88 | handleClick(8)} /> 89 |
90 |

{status}

91 | 92 |
93 | ); 94 | } 95 | -------------------------------------------------------------------------------- /src/components/tic-tact-toe/styles.css: -------------------------------------------------------------------------------- 1 | .tic-tac-toe-container { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | margin-top: 100px; 6 | } 7 | 8 | .square { 9 | border: 1px solid red; 10 | float: left; 11 | font-size: 40px; 12 | height: 100px; 13 | padding: 0px; 14 | text-align: center; 15 | width: 100px; 16 | margin-right: -1px; 17 | margin-top: -1px; 18 | cursor: pointer; 19 | } 20 | -------------------------------------------------------------------------------- /src/components/tree-view/data.js: -------------------------------------------------------------------------------- 1 | export const menus = [ 2 | { 3 | label: "Home", 4 | to: "/", 5 | }, 6 | { 7 | label: "Profile", 8 | to: "/profile", 9 | children: [ 10 | { 11 | label: "Details", 12 | to: "details", 13 | children: [ 14 | { 15 | label: "Location", 16 | to: "location", 17 | children: [ 18 | { 19 | label: "City", 20 | to: "city", 21 | }, 22 | ], 23 | }, 24 | ], 25 | }, 26 | ], 27 | }, 28 | { 29 | label: "Settings", 30 | to: "/settings", 31 | children: [ 32 | { 33 | label: "Account", 34 | to: "account", 35 | }, 36 | { 37 | label: "Security", 38 | to: "security", 39 | children: [ 40 | { 41 | label: "Login", 42 | to: "login", 43 | }, 44 | { 45 | label: "Register", 46 | to: "register", 47 | children : [ 48 | { 49 | label : 'Random data', 50 | to : '' 51 | } 52 | ] 53 | }, 54 | ], 55 | }, 56 | ], 57 | }, 58 | ]; 59 | 60 | export default menus; 61 | -------------------------------------------------------------------------------- /src/components/tree-view/index.jsx: -------------------------------------------------------------------------------- 1 | import MenuList from "./menu-list"; 2 | import './styles.css' 3 | 4 | export default function TreeView({ menus = [] }) { 5 | return ( 6 |
7 | 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /src/components/tree-view/menu-item.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import MenuList from "./menu-list"; 3 | import {FaMinus, FaPlus} from 'react-icons/fa' 4 | 5 | export default function MenuItem({ item }) { 6 | const [displayCurrentChildren, setDisplayCurrentChildren] = useState({}); 7 | 8 | function handleToggleChildren(getCurrentlabel) { 9 | setDisplayCurrentChildren({ 10 | ...displayCurrentChildren, 11 | [getCurrentlabel]: !displayCurrentChildren[getCurrentlabel], 12 | }); 13 | } 14 | 15 | console.log(displayCurrentChildren); 16 | 17 | return ( 18 |
  • 19 |
    20 |

    {item.label}

    21 | {item && item.children && item.children.length ? ( 22 | handleToggleChildren(item.label)}> 23 | { 24 | displayCurrentChildren[item.label] ? : 25 | } 26 | 27 | ) : null} 28 |
    29 | 30 | {item && item.children && item.children.length > 0 && displayCurrentChildren[item.label] ? ( 31 | 32 | ) : null} 33 |
  • 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /src/components/tree-view/menu-list.jsx: -------------------------------------------------------------------------------- 1 | import MenuItem from "./menu-item"; 2 | 3 | export default function MenuList({ list = [] }) { 4 | return ( 5 |
      6 | {list && list.length 7 | ? list.map((listItem) => ) 8 | : null} 9 |
    10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /src/components/tree-view/styles.css: -------------------------------------------------------------------------------- 1 | .tree-view-container { 2 | min-height: 100vh; 3 | width: 350px; 4 | background: rgb(0, 71, 110); 5 | } 6 | 7 | .menu-item{ 8 | display: flex; 9 | align-items: center; 10 | gap: 20px; 11 | cursor: pointer; 12 | color: #fff; 13 | } 14 | 15 | .menu-list-container { 16 | list-style: none; 17 | margin-top: 0px; 18 | margin-bottom: 0px; 19 | } 20 | -------------------------------------------------------------------------------- /src/components/use-fetch/index.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | export default function useFetch(url, options = {}) { 4 | const [data, setData] = useState(null); 5 | const [pending, setPending] = useState(false); 6 | const [error, setError] = useState(null); 7 | 8 | async function fetchData() { 9 | setPending(true); 10 | try { 11 | const response = await fetch(url, { ...options }); 12 | if (!response.ok) throw new Error(response.statusText); 13 | 14 | const result = await response.json(); 15 | setData(result); 16 | setError(null); 17 | setPending(false); 18 | } catch (e) { 19 | setError(`${e}. Some Error Occured`); 20 | setPending(false); 21 | } 22 | } 23 | 24 | useEffect(() => { 25 | fetchData(); 26 | }, [url]); 27 | 28 | return { data, error, pending }; 29 | } 30 | -------------------------------------------------------------------------------- /src/components/use-fetch/test.jsx: -------------------------------------------------------------------------------- 1 | import useFetch from "."; 2 | 3 | export default function UseFetchHookTest() { 4 | const { data, error, pending } = useFetch( 5 | "https://dummyjson.com/products", 6 | {} 7 | ); 8 | 9 | return ( 10 |
    11 |

    Use Fetch Hook

    12 | {pending ?

    Pending ! Please wait

    : null} 13 | {error ?

    {error}

    : null} 14 | {data && data.products && data.products.length 15 | ? data.products.map((productItem) => ( 16 |

    {productItem.title}

    17 | )) 18 | : null} 19 |
    20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /src/components/use-outside-click/index.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | 3 | export default function useOutsideClick(ref, handler) { 4 | useEffect(() => { 5 | function listener(event) { 6 | if (!ref.current || ref.current.contains(event.target)) { 7 | return; 8 | } 9 | 10 | handler(event); 11 | } 12 | 13 | document.addEventListener("mousedown", listener); 14 | document.addEventListener("touchstart", listener); 15 | 16 | return () => { 17 | document.removeEventListener("mousedown", listener); 18 | document.removeEventListener("touchstart", listener); 19 | }; 20 | }, [handler, ref]); 21 | } 22 | -------------------------------------------------------------------------------- /src/components/use-outside-click/test.jsx: -------------------------------------------------------------------------------- 1 | import { useRef, useState } from "react"; 2 | import useOutsideClick from "."; 3 | 4 | export default function UseOnclickOutsideTest() { 5 | const [showContent, setShowContent] = useState(false); 6 | const ref = useRef(); 7 | useOutsideClick(ref, () => setShowContent(false)); 8 | 9 | return ( 10 |
    11 | {showContent ? ( 12 |
    13 |

    This is a random content

    14 |

    15 | Please click outside of this to close this. It won't close if you 16 | click inside of this content 17 |

    18 |
    19 | ) : ( 20 | 21 | )} 22 |
    23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/components/use-window-resize/index.jsx: -------------------------------------------------------------------------------- 1 | import { useLayoutEffect } from "react"; 2 | import { useState } from "react"; 3 | 4 | export default function useWindowResize() { 5 | const [windowSize, setWindowSize] = useState({ 6 | width: 0, 7 | height: 0, 8 | }); 9 | 10 | function handleResize() { 11 | setWindowSize({ 12 | width: window.innerWidth, 13 | height: window.innerHeight, 14 | }); 15 | } 16 | 17 | useLayoutEffect(() => { 18 | handleResize(); 19 | 20 | window.addEventListener("resize", handleResize); 21 | 22 | return () => { 23 | window.removeEventListener("resize", handleResize); 24 | }; 25 | }, []); 26 | 27 | return windowSize; 28 | } 29 | -------------------------------------------------------------------------------- /src/components/use-window-resize/test.jsx: -------------------------------------------------------------------------------- 1 | import useWindowResize from "."; 2 | 3 | export default function UseWindowResizeTest() { 4 | const windowSize = useWindowResize(); 5 | const { width, height } = windowSize; 6 | 7 | return ( 8 |
    9 |

    Use Window resize Hook

    10 |

    Width is {width}

    11 |

    Height is {height}

    12 |
    13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | import reportWebVitals from "./reportWebVitals"; 6 | 7 | const root = ReactDOM.createRoot(document.getElementById("root")); 8 | root.render(); 9 | 10 | // If you want to start measuring performance in your app, pass a function 11 | // to log results (for example: reportWebVitals(console.log)) 12 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 13 | reportWebVitals(); 14 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 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 | --------------------------------------------------------------------------------