Skip to content

Commit bc645f0

Browse files
authored
New: Implement Sorting Info Box, Notification System (#3)
* New: Implement Sorting Info Box, Notification System * Change theme from darkly to solar * Fix: Small DOM problem
1 parent 62d97d2 commit bc645f0

File tree

13 files changed

+145
-6
lines changed

13 files changed

+145
-6
lines changed

src/App.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { generateRandomArray } from './utils';
77
import { SettingsPanel } from './components/panels/SettingsPanel.tsx';
88
import { Navigation } from './components/navigation/Navigation.tsx';
99
import { ControlPanel } from './components/panels/ControlPanel.tsx';
10+
import { InfoCard } from './components/cards/InfoCard.tsx';
11+
import { SortSuccessToast } from './components/toasts/SortSuccessToast.tsx';
1012

1113
// todo: refactor the components, upcycle shared states
1214
export const App = () => {
@@ -15,6 +17,7 @@ export const App = () => {
1517
const [sortDelay, setSortDelay] = useState<number>(500);
1618
const [isSorting, setIsSorting] = useState<boolean>(false);
1719
const [array, setArray] = useState<number[]>(generateRandomArray(arraySize));
20+
const [showToast, setShowToast] = useState<boolean>(false);
1821

1922
// sort method refs
2023
const bubbleSortRef = useRef<(array: number[]) => void>(() => {}); // initialize with an empty function (ts error)
@@ -31,6 +34,10 @@ export const App = () => {
3134
setArray(array);
3235
}, [arraySize]);
3336

37+
const handleSortEnd = () => {
38+
setShowToast(true);
39+
};
40+
3441
const renderVisualizer = () => {
3542
switch (sortType) {
3643
case 'bubble':
@@ -43,6 +50,7 @@ export const App = () => {
4350
isSorting={isSorting}
4451
setIsSorting={setIsSorting}
4552
sortRef={bubbleSortRef}
53+
onSortEnd={handleSortEnd}
4654
/>
4755
);
4856
case 'selection':
@@ -55,6 +63,7 @@ export const App = () => {
5563
isSorting={isSorting}
5664
setIsSorting={setIsSorting}
5765
sortRef={selectionSortRef}
66+
onSortEnd={handleSortEnd}
5867
/>
5968
);
6069
case 'merge':
@@ -67,6 +76,7 @@ export const App = () => {
6776
isSorting={isSorting}
6877
setIsSorting={setIsSorting}
6978
sortRef={mergeSortRef}
79+
onSortEnd={handleSortEnd}
7080
/>
7181
);
7282
default:
@@ -79,6 +89,7 @@ export const App = () => {
7989
isSorting={isSorting}
8090
setIsSorting={setIsSorting}
8191
sortRef={bubbleSortRef}
92+
onSortEnd={handleSortEnd}
8293
/>
8394
);
8495
}
@@ -101,6 +112,7 @@ export const App = () => {
101112
isSorting={isSorting}
102113
/>
103114
</Row>
115+
<InfoCard sortType={sortType} />
104116
{renderVisualizer()}
105117
<ControlPanel
106118
isSorting={isSorting}
@@ -122,6 +134,7 @@ export const App = () => {
122134
}
123135
}}
124136
/>
137+
<SortSuccessToast show={showToast} setShow={setShowToast} />
125138
</Container>
126139
</>
127140
);

src/assets/styles/bootstrap.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// remove google web fonts
22
$web-font-path: false;
33

4-
@import "bootswatch/dist/darkly/variables";
4+
@import "bootswatch/dist/solar/variables";
55
@import "bootstrap/scss/bootstrap";
6-
@import "bootswatch/dist/darkly/bootswatch";
6+
@import "bootswatch/dist/solar/bootswatch";
77

88

src/components/cards/InfoCard.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import Card from 'react-bootstrap/Card';
2+
import { Col, Row } from 'react-bootstrap';
3+
import React from 'react';
4+
import { sorts } from '../../utils';
5+
6+
interface InfoCardProps {
7+
sortType: string;
8+
}
9+
10+
export const InfoCard: React.FC<InfoCardProps> = ({ sortType }) => {
11+
const sort = sorts[sortType];
12+
13+
return (
14+
<Card className="mt-5">
15+
<Card.Header>Info</Card.Header>
16+
<Card.Body>
17+
<Row>
18+
<Col md={9}>
19+
<h5>{sort.name}</h5>
20+
<div className="mt-3">{sort.description}</div>
21+
</Col>
22+
<Col md={3}>
23+
<h5>Time Complexity</h5>
24+
<Row className="mt-3">
25+
<Col>Worst Case:</Col>
26+
<Col>{sort.complexity.worst}</Col>
27+
</Row>
28+
<Row>
29+
<Col>Average Case:</Col>
30+
<Col>{sort.complexity.average}</Col>
31+
</Row>
32+
<Row>
33+
<Col>Best Case:</Col>
34+
<Col>{sort.complexity.best}</Col>
35+
</Row>
36+
</Col>
37+
</Row>
38+
</Card.Body>
39+
</Card>
40+
);
41+
};

src/components/navigation/Navigation.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ export const Navigation: React.FC<NavigationProps> = ({
99
isSorting,
1010
}) => {
1111
return (
12-
<Navbar collapseOnSelect expand="lg" className="bg-body-tertiary">
12+
<Navbar
13+
collapseOnSelect
14+
expand="lg"
15+
className="bg-primary"
16+
data-bs-theme="dark"
17+
>
1318
<Container fluid>
1419
<Navbar.Brand href="#">Sort Algorithm Visualizer</Navbar.Brand>
1520
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import Toast from 'react-bootstrap/Toast';
2+
import React from 'react';
3+
4+
interface SortSuccessToastProps {
5+
show: boolean;
6+
setShow: (show: boolean) => void;
7+
}
8+
9+
export const SortSuccessToast: React.FC<SortSuccessToastProps> = ({
10+
show,
11+
setShow,
12+
}) => {
13+
return (
14+
<Toast
15+
onClose={() => setShow(false)}
16+
show={show}
17+
delay={3000}
18+
autohide
19+
style={{ position: 'fixed', bottom: '20px', right: '20px' }}
20+
>
21+
<Toast.Header>
22+
<strong className="me-auto">Notification</strong>
23+
<small>Just now</small>
24+
</Toast.Header>
25+
<Toast.Body>Sorting completed successfully!</Toast.Body>
26+
</Toast>
27+
);
28+
};

src/components/visualizers/BubblesortVisualizer.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const BubblesortVisualizer: React.FC<VisualizerProps> = ({
1111
sortDelay,
1212
setIsSorting,
1313
sortRef,
14+
onSortEnd,
1415
}) => {
1516
const [currentJ, setCurrentJ] = useState<number | null>(null);
1617

@@ -46,6 +47,7 @@ export const BubblesortVisualizer: React.FC<VisualizerProps> = ({
4647
}
4748
}
4849
setIsSorting(false);
50+
onSortEnd();
4951
setCurrentJ(null);
5052
};
5153

@@ -74,7 +76,6 @@ export const BubblesortVisualizer: React.FC<VisualizerProps> = ({
7476

7577
return (
7678
<>
77-
<h1 className="mt-5 text-center">Bubblesort</h1>
7879
<Container ref={container} className="mt-5">
7980
<Row className="mt-5" style={{ marginBottom: 60 }}>
8081
<Col className="d-flex justify-content-center align-items-center">

src/components/visualizers/MergesortVisualizer.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export const MergeSortVisualizer: React.FC<VisualizerProps> = ({
1010
setArray,
1111
setIsSorting,
1212
sortRef,
13+
onSortEnd,
1314
}) => {
1415
const boxRefs = useRef<(HTMLDivElement | null)[]>([]);
1516
const container = useRef(null);
@@ -125,11 +126,11 @@ export const MergeSortVisualizer: React.FC<VisualizerProps> = ({
125126
setArray(sortedArray);
126127
tl.revert();
127128
setIsSorting(false);
129+
onSortEnd();
128130
};
129131

130132
return (
131133
<>
132-
<h1 className="mt-5 text-center">Merge Sort</h1>
133134
<Container ref={container} className="mt-5">
134135
<Row className="mt-5">
135136
{array.map((v, i) => (

src/components/visualizers/SelectionsortVisualizer.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const SelectionsortVisualizer: React.FC<VisualizerProps> = ({
1111
sortDelay,
1212
setIsSorting,
1313
sortRef,
14+
onSortEnd,
1415
}) => {
1516
const [currentI, setCurrentI] = useState<number | null>(null);
1617
const [currentJ, setCurrentJ] = useState<number | null>(null);
@@ -55,6 +56,7 @@ export const SelectionsortVisualizer: React.FC<VisualizerProps> = ({
5556
}
5657

5758
setIsSorting(false);
59+
onSortEnd();
5860
setCurrentI(null);
5961
setCurrentJ(null);
6062
setCurrentMin(null);
@@ -86,7 +88,6 @@ export const SelectionsortVisualizer: React.FC<VisualizerProps> = ({
8688

8789
return (
8890
<>
89-
<h1 className="mt-5 text-center">Selectionsort</h1>
9091
<Container ref={container} className="mt-5">
9192
<Row className="mt-5" style={{ marginBottom: 60 }}>
9293
<Col className="d-flex justify-content-center align-items-center">

src/interfaces/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export { type VisualizerProps } from './visualizers';
22
export { type SettingsPanelProps } from './settings';
33
export { type NavigationProps } from './navigation';
4+
export { type SortAlgorithm } from './sorts';

src/interfaces/sorts.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export interface SortAlgorithm {
2+
name: string;
3+
description: string;
4+
complexity: {
5+
best: string;
6+
average: string;
7+
worst: string;
8+
};
9+
}

src/interfaces/visualizers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ export interface VisualizerProps {
88
isSorting: boolean;
99
setIsSorting: (sorting: boolean) => void;
1010
sortRef: MutableRefObject<(array: number[]) => void>;
11+
onSortEnd: () => void;
1112
}

src/utils/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { sorts } from './sorts.ts';
2+
13
export const delay = (ms: number) => {
24
return new Promise((resolve) => setTimeout(resolve, ms));
35
};
@@ -9,3 +11,5 @@ export const generateRandomArray = (size: number): number[] => {
911
}
1012
return array;
1113
};
14+
15+
export { sorts };

src/utils/sorts.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { SortAlgorithm } from '../interfaces';
2+
3+
export const sorts: Record<string, SortAlgorithm> = {
4+
bubble: {
5+
name: 'Bubble Sort',
6+
description:
7+
'Bubble Sort is a simple sorting algorithm that repeatedly steps through the list, compares adjacent elements and swaps them if they are in the wrong order.',
8+
complexity: {
9+
best: 'O(n)',
10+
average: 'O(n²)',
11+
worst: 'O(n²)',
12+
},
13+
},
14+
selection: {
15+
name: 'Selection Sort',
16+
description:
17+
'Selection Sort is an in-place comparison sorting algorithm that divides the input list into two parts: the sublist of items already sorted and the sublist of items remaining to be sorted.',
18+
complexity: {
19+
best: 'O(n²)',
20+
average: 'O(n²)',
21+
worst: 'O(n²)',
22+
},
23+
},
24+
merge: {
25+
name: 'Merge Sort',
26+
description:
27+
'Merge Sort is a divide and conquer algorithm that divides the input array into two halves, calls itself for the two halves, and then merges the two sorted halves.',
28+
complexity: {
29+
best: 'O(n log n)',
30+
average: 'O(n log n)',
31+
worst: 'O(n log n)',
32+
},
33+
},
34+
};

0 commit comments

Comments
 (0)