Skip to content

Commit b01f868

Browse files
committed
refactor: Convert Pathfinder components from class to functional with hooks
Migrates node, grid, menu, and page components. Uses useRef for isRunning guard in async animations. Removes unused state and commented-out code.
1 parent 29437cd commit b01f868

4 files changed

Lines changed: 245 additions & 321 deletions

File tree

src/app/pathfinder/grid.jsx

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,24 @@
1-
import React, {Component} from 'react';
21
import Node from "./node";
32
import './grid.css';
4-
class Grid extends Component {
5-
state = {
6-
grid: this.props.grid
7-
}
83

9-
render() {
10-
return (
11-
<div className="Grid">
12-
{this.props.grid.map((row, rowidx) => {
13-
return (
14-
<div key={rowidx}>
15-
{row.map((node, nodeidx) => {
16-
const {row, col, isWall, visitedNode, } = node;
17-
return (
18-
<Node
19-
key={nodeidx}
20-
row={row}
21-
col={col}
22-
node={node}
23-
isWall={isWall}
24-
visitedNode={ visitedNode }
25-
onMouseDown = {this.props.onMouseDown}
26-
onMouseEnter = {this.props.onMouseEnter}
27-
onMouseUp = {this.props.onMouseUp}
28-
/>
29-
);
30-
})}
31-
</div>
32-
);
33-
})}
34-
</div>
35-
);
36-
}
4+
export default function Grid({ grid, onMouseDown, onMouseEnter, onMouseUp }) {
5+
return (
6+
<div className="Grid">
7+
{grid.map((row, rowidx) => (
8+
<div key={rowidx}>
9+
{row.map((node, nodeidx) => (
10+
<Node
11+
key={nodeidx}
12+
row={node.row}
13+
col={node.col}
14+
node={node}
15+
onMouseDown={onMouseDown}
16+
onMouseEnter={onMouseEnter}
17+
onMouseUp={onMouseUp}
18+
/>
19+
))}
20+
</div>
21+
))}
22+
</div>
23+
);
3724
}
38-
39-
export default Grid;

src/app/pathfinder/menu.jsx

Lines changed: 55 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,75 @@
11
import { CustomSelect } from '@/components/custom-select';
22
import { Button } from '@/components/ui/button';
33
import { Play, Grid3X3, Eraser, Trash2 } from 'lucide-react';
4-
import { Component } from 'react';
54

6-
class Menu extends Component {
7-
render() {
8-
const disabled = this.props.disable;
9-
return (
10-
<div className="w-64 bg-gray-100 p-4 space-y-6">
11-
<h2 className="text-lg font-semibold">Pathfinder</h2>
5+
export default function Menu({ onAlgoChanged, onVisualize, algorithms, mazes, onMazeChanged, onCreateMaze, onClearBoard, onClearPath, disabled }) {
6+
return (
7+
<div className="w-64 bg-gray-100 p-4 space-y-6">
8+
<h2 className="text-lg font-semibold">Pathfinder</h2>
129

10+
<CustomSelect
11+
title="Algorithm"
12+
options={algorithms}
13+
onChange={onAlgoChanged}
14+
disabled={disabled}
15+
/>
16+
17+
<div className="space-y-3">
18+
<div className="flex items-center gap-2">
19+
<div className="h-px flex-1 bg-gray-300" />
20+
<span className="text-xs font-medium text-gray-500 uppercase tracking-wider">Maze</span>
21+
<div className="h-px flex-1 bg-gray-300" />
22+
</div>
1323
<CustomSelect
14-
title="Algorithm"
15-
options={this.props.algorithms}
16-
onChange={this.props.onAlgoChanged}
24+
title="Division Type"
25+
options={mazes}
26+
onChange={onMazeChanged}
1727
disabled={disabled}
1828
/>
29+
<Button
30+
className="w-full"
31+
variant="outline"
32+
onClick={onCreateMaze}
33+
disabled={disabled}
34+
>
35+
<Grid3X3 /> Generate Maze
36+
</Button>
37+
</div>
1938

20-
<div className="space-y-3">
21-
<div className="flex items-center gap-2">
22-
<div className="h-px flex-1 bg-gray-300" />
23-
<span className="text-xs font-medium text-gray-500 uppercase tracking-wider">Maze</span>
24-
<div className="h-px flex-1 bg-gray-300" />
25-
</div>
26-
<CustomSelect
27-
title="Division Type"
28-
options={this.props.mazes}
29-
onChange={this.props.onMazeChanged}
30-
disabled={disabled}
31-
/>
39+
<div className="space-y-3">
40+
<div className="flex items-center gap-2">
41+
<div className="h-px flex-1 bg-gray-300" />
42+
<span className="text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</span>
43+
<div className="h-px flex-1 bg-gray-300" />
44+
</div>
45+
<Button
46+
className="w-full"
47+
onClick={onVisualize}
48+
disabled={disabled}
49+
>
50+
<Play /> Visualize
51+
</Button>
52+
<div className="flex gap-2">
3253
<Button
33-
className="w-full"
34-
variant="outline"
35-
onClick={this.props.onCreateMaze}
54+
className="flex-1"
55+
variant="secondary"
56+
size="sm"
57+
onClick={onClearPath}
3658
disabled={disabled}
3759
>
38-
<Grid3X3 /> Generate Maze
60+
<Eraser /> Path
3961
</Button>
40-
</div>
41-
42-
<div className="space-y-3">
43-
<div className="flex items-center gap-2">
44-
<div className="h-px flex-1 bg-gray-300" />
45-
<span className="text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</span>
46-
<div className="h-px flex-1 bg-gray-300" />
47-
</div>
4862
<Button
49-
className="w-full"
50-
onClick={this.props.onVisualize}
63+
className="flex-1"
64+
variant="secondary"
65+
size="sm"
66+
onClick={onClearBoard}
5167
disabled={disabled}
5268
>
53-
<Play /> Visualize
69+
<Trash2 /> Board
5470
</Button>
55-
<div className="flex gap-2">
56-
<Button
57-
className="flex-1"
58-
variant="secondary"
59-
size="sm"
60-
onClick={this.props.onClearPath}
61-
disabled={disabled}
62-
>
63-
<Eraser /> Path
64-
</Button>
65-
<Button
66-
className="flex-1"
67-
variant="secondary"
68-
size="sm"
69-
onClick={this.props.onClearBoard}
70-
disabled={disabled}
71-
>
72-
<Trash2 /> Board
73-
</Button>
74-
</div>
7571
</div>
7672
</div>
77-
);
78-
}
73+
</div>
74+
);
7975
}
80-
81-
export default Menu;

src/app/pathfinder/node.jsx

Lines changed: 21 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,22 @@
1-
import React, {Component} from 'react';
2-
import './node.css'
3-
class Node extends Component {
4-
static = {
5-
row: this.props.row,
6-
col: this.props.col
7-
}
8-
render() {
9-
const { row,col,isVisited, onMouseDown, onMouseEnter,onMouseUp } = this.props;
10-
return (
11-
<div
12-
id = {`node-${this.props.row}-${this.props.col}`}
13-
className={this.getClassName()}
14-
onMouseDown={() => onMouseDown(row,col)}
15-
onMouseEnter={() => onMouseEnter(row,col)}
16-
onMouseUp={() => onMouseUp(row,col)}
17-
/>
18-
);
19-
}
20-
getClassName(){
21-
if(this.props.node.isWall === true){
22-
return "node node-wall";
23-
} else if( this.props.node.isStartNode === true ){
24-
return "node node-start";
25-
} else if( this.props.node.isEndNode === true ){
26-
return "node node-end";
27-
} else if(this.props.node.ispathNode){
28-
return 'node node-shortest-path';
29-
}else if( this.props.node.isVisited === true ){
30-
return "node node-visited";
31-
} else{
32-
return "node";
33-
}
34-
}
35-
}
1+
import './node.css';
2+
3+
export default function Node({ row, col, node, onMouseDown, onMouseEnter, onMouseUp }) {
4+
const getClassName = () => {
5+
if (node.isWall) return "node node-wall";
6+
if (node.isStartNode) return "node node-start";
7+
if (node.isEndNode) return "node node-end";
8+
if (node.ispathNode) return "node node-shortest-path";
9+
if (node.isVisited) return "node node-visited";
10+
return "node";
11+
};
3612

37-
export default Node;
13+
return (
14+
<div
15+
id={`node-${row}-${col}`}
16+
className={getClassName()}
17+
onMouseDown={() => onMouseDown(row, col)}
18+
onMouseEnter={() => onMouseEnter(row, col)}
19+
onMouseUp={() => onMouseUp(row, col)}
20+
/>
21+
);
22+
}

0 commit comments

Comments
 (0)