diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7532bd3..da43eea 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,6 +1,15 @@
### Contribution Guide
-- Feel free to contribute to this repo by raising the __pull request__
-- Use the proper names for variable and functions
+#### PR rules
+
+- Please raise the **pull request** if want to contribute by fixing bugs,
+ improving the code or adding the test cases
+- If you want to enhance the project, please create an issue and can be
+ discussed before proceeding
+
+#### Codebase rules
+
- Do not import libraries unless needed
- Test well before submitting the PR
+- Code quality is the primary requirement
+- Format the files before submission
diff --git a/README.md b/README.md
index 4968944..88bfb5b 100644
--- a/README.md
+++ b/README.md
@@ -40,6 +40,9 @@ Features
- [React](https://react.dev/)
- [Redux Toolkit](https://redux-toolkit.js.org/)
+- [React Router](https://reactrouter.com/en/main/)
+- [React Switch](https://react-switch.netlify.app/)
+- [Sonner](https://sonner.emilkowal.ski/)
- [Sass](https://sass-lang.com/)
- [Vite](https://vitejs.dev/) (Bundler)
diff --git a/package-lock.json b/package-lock.json
index fe23c45..4c1c7bd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7,6 +7,7 @@
"": {
"name": "algo-visualizer",
"version": "0.0.0",
+ "license": "MIT",
"dependencies": {
"@reduxjs/toolkit": "^1.9.5",
"react": "^18.2.0",
@@ -14,7 +15,8 @@
"react-redux": "^8.1.2",
"react-router-dom": "^6.16.0",
"react-switch": "^7.0.0",
- "redux-persist": "^6.0.0"
+ "redux-persist": "^6.0.0",
+ "sonner": "^1.0.3"
},
"devDependencies": {
"@testing-library/jest-dom": "^6.1.3",
@@ -32,7 +34,7 @@
"eslint-plugin-react-refresh": "^0.3.5",
"eslint-plugin-unused-imports": "^3.0.0",
"jsdom": "^22.1.0",
- "postcss": "^8.4.30",
+ "postcss": "^8.4.31",
"sass": "^1.68.0",
"stylelint": "^15.10.3",
"stylelint-config-recess-order": "^4.3.0",
@@ -42,6 +44,9 @@
"typescript": "^5.2.2",
"vite": "^4.3.9",
"vitest": "^0.34.5"
+ },
+ "engines": {
+ "node": ">=18.18.0"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -4604,9 +4609,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.30",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.30.tgz",
- "integrity": "sha512-7ZEao1g4kd68l97aWG/etQKPKq07us0ieSZ2TnFDk11i0ZfDW2AwKHYU8qv4MZKqN2fdBfg+7q0ES06UA73C1g==",
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"dev": true,
"funding": [
{
@@ -5414,6 +5419,15 @@
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
}
},
+ "node_modules/sonner": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sonner/-/sonner-1.0.3.tgz",
+ "integrity": "sha512-hBoA2zKuYW3lUnpx4K0vAn8j77YuYiwvP9sLQfieNS2pd5FkT20sMyPTDJnl9S+5T27ZJbwQRPiujwvDBwhZQg==",
+ "peerDependencies": {
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0"
+ }
+ },
"node_modules/source-map-js": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
diff --git a/package.json b/package.json
index 79d5381..7903df4 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,8 @@
"react-redux": "^8.1.2",
"react-router-dom": "^6.16.0",
"react-switch": "^7.0.0",
- "redux-persist": "^6.0.0"
+ "redux-persist": "^6.0.0",
+ "sonner": "^1.0.3"
},
"devDependencies": {
"@testing-library/jest-dom": "^6.1.3",
@@ -40,7 +41,7 @@
"eslint-plugin-react-refresh": "^0.3.5",
"eslint-plugin-unused-imports": "^3.0.0",
"jsdom": "^22.1.0",
- "postcss": "^8.4.30",
+ "postcss": "^8.4.31",
"sass": "^1.68.0",
"stylelint": "^15.10.3",
"stylelint-config-recess-order": "^4.3.0",
diff --git a/src/apps/sorting-visualizer/__tests__/hooks/use-algo.hook.spec.ts b/src/apps/sorting-visualizer/__tests__/hooks/use-algo.hook.spec.ts
index 67b322e..ee128d7 100644
--- a/src/apps/sorting-visualizer/__tests__/hooks/use-algo.hook.spec.ts
+++ b/src/apps/sorting-visualizer/__tests__/hooks/use-algo.hook.spec.ts
@@ -6,7 +6,7 @@ import {
import { renderHook, waitFor } from '@testing-library/react';
import { algoList } from '@/apps/sorting-visualizer/sorting-algorithms/algo-list';
-import { getRndmNumInRange } from '../../helpers/array-helpers';
+import { getRndmNumInRange } from '@/apps/sorting-visualizer/helpers/array-helpers';
import { initialArray } from '@/apps/sorting-visualizer/config';
import useAlgo from '@/apps/sorting-visualizer/hooks/use-algo.hook';
diff --git a/src/apps/sorting-visualizer/config.ts b/src/apps/sorting-visualizer/config.ts
index 279d982..2aaa6c5 100644
--- a/src/apps/sorting-visualizer/config.ts
+++ b/src/apps/sorting-visualizer/config.ts
@@ -3,6 +3,7 @@ import { algoList } from './sorting-algorithms/algo-list';
export const menuItems = algoList.map((item) => item.name).concat('all');
export const initialArray = [6, 8, 3, 5, 1, 9, 2, 7, 4];
export const numberGenerator = { min: 10, max: 40 };
+export const sortCompletionMessage = 'Sorting is complete';
export const cellCSS = {
size: 50,
diff --git a/src/apps/sorting-visualizer/layouts/all-algorithm.layout.tsx b/src/apps/sorting-visualizer/layouts/all-algorithm.layout.tsx
index 113a50c..8d5bc28 100644
--- a/src/apps/sorting-visualizer/layouts/all-algorithm.layout.tsx
+++ b/src/apps/sorting-visualizer/layouts/all-algorithm.layout.tsx
@@ -7,6 +7,8 @@ import Visualizer from '@/apps/sorting-visualizer/components/visualizer/visualiz
import { algoList } from '@/apps/sorting-visualizer/sorting-algorithms/algo-list';
import classes from './layout.module.scss';
import { setIsPlaying } from '@/apps/sorting-visualizer/store/sorting-visualizer.slice';
+import { sortCompletionMessage } from '../config';
+import { toast } from 'sonner';
import useCompletion from '@/apps/sorting-visualizer/hooks/use-completion.hook';
import { useEffect } from 'react';
@@ -26,6 +28,7 @@ function AllAlgorithmLayout() {
useEffect(() => {
if (isComplete) {
+ toast.success(sortCompletionMessage);
dispatch(setIsPlaying(null));
}
}, [dispatch, isComplete]);
diff --git a/src/apps/sorting-visualizer/layouts/main.layout.tsx b/src/apps/sorting-visualizer/layouts/main.layout.tsx
index 0f698df..c000230 100644
--- a/src/apps/sorting-visualizer/layouts/main.layout.tsx
+++ b/src/apps/sorting-visualizer/layouts/main.layout.tsx
@@ -2,6 +2,7 @@ import Controller from '@/apps/sorting-visualizer/components/controller/controll
import ModeIcon from '@/apps/sorting-visualizer/components/theme/mode-icon';
import Navbar from '@/apps/sorting-visualizer/components/navbar/navbar';
import { PropsWithChildren } from 'react';
+import { Toaster } from 'sonner';
import classes from './layout.module.scss';
import { menuItems } from '@/apps/sorting-visualizer/config';
@@ -12,6 +13,7 @@ function MainLayout({ children }: PropsWithChildren) {
{children}
+
);
}
diff --git a/src/apps/sorting-visualizer/layouts/single-algorithm.layout.tsx b/src/apps/sorting-visualizer/layouts/single-algorithm.layout.tsx
index 12736e6..8886760 100644
--- a/src/apps/sorting-visualizer/layouts/single-algorithm.layout.tsx
+++ b/src/apps/sorting-visualizer/layouts/single-algorithm.layout.tsx
@@ -5,6 +5,8 @@ import NoInput from '@/apps/sorting-visualizer/components/visualizer/no-input';
import Visualizer from '@/apps/sorting-visualizer/components/visualizer/visualizer';
import { algoList } from '@/apps/sorting-visualizer/sorting-algorithms/algo-list';
import { setIsPlaying } from '@/apps/sorting-visualizer/store/sorting-visualizer.slice';
+import { sortCompletionMessage } from '../config';
+import { toast } from 'sonner';
import useCompletion from '@/apps/sorting-visualizer/hooks/use-completion.hook';
import { useEffect } from 'react';
import { useParams } from 'react-router-dom';
@@ -17,11 +19,11 @@ function SingleAlgorithmLayout() {
const selectedAlgo =
algoList.find(({ name }) => name === algoName) ?? algoList[0];
-
const { onComplete, isComplete } = useCompletion(1, reset);
useEffect(() => {
if (isComplete) {
+ toast.success(sortCompletionMessage);
dispatch(setIsPlaying(null));
}
}, [dispatch, isComplete]);