Skip to content

Commit a108b2e

Browse files
committed
refactor
1 parent 1369459 commit a108b2e

34 files changed

+362
-238
lines changed

.prettierrc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
"bracketSpacing": true,
99
"endOfLine": "lf",
1010
"singleQuote": true,
11-
"plugins": ["prettier-plugin-tailwindcss"],
11+
"plugins": ["prettier-plugin-tailwindcss", "@trivago/prettier-plugin-sort-imports"],
12+
"importOrder": ["(^react|react|vite)", "<THIRD_PARTY_MODULES>", "@/components/", "@/types", "^[./]"],
13+
"importOrderSeparation": true,
14+
"importOrderGroupNamespaceSpecifiers": true,
15+
"importOrderSortSpecifiers": true,
1216
"jsxSingleQuote": false,
1317
"overrides": [
1418
{

README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@
1313
The user must choose two numbers according to the game rules.
1414

1515
3. **Adjacent Numbers:**
16-
- The user can only select adjacent numbers either vertically or horizontally.
17-
- Adjacent numbers are those with no unresolved cells between them.
18-
- The user can also select consecutive numbers in a row (e.g., the last number in the 1st row and the first number in the next row).
16+
17+
- The user can only select adjacent numbers either vertically or horizontally.
18+
- Adjacent numbers are those with no unresolved cells between them.
19+
- The user can also select consecutive numbers in a row (e.g., the last number in the 1st row and the first number in the next row).
1920

2021
4. **Ignoring Resolved Cells:**
21-
All resolved cells are ignored when checking for adjacency.
22+
All resolved cells are ignored when checking for adjacency.
2223

2324
![Screenshot](public/moves.png)
2425

@@ -34,8 +35,8 @@ All resolved cells are ignored when checking for adjacency.
3435

3536
7. **Booster Counter K:**
3637
For each successful selection, the game adds a booster counter K, which multiplies the points.
37-
- The counter can reach up to x100.
38-
- The counter resets to 1 after 5 seconds of inactivity.
38+
- The counter can reach up to x100.
39+
- The counter resets to 1 after 5 seconds of inactivity.
3940

4041
### Shuffle Feature
4142

global.d.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,3 @@ declare global {
1212
declare global {
1313
type FC<T = object> = FunctionComponent<PropsWithChildren<T>>;
1414
}
15-
16-
declare module '*.module.css' {
17-
const value: { [className: string]: string };
18-
export default value;
19-
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"react-dom": "^18.3.1"
1818
},
1919
"devDependencies": {
20+
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
2021
"@types/howler": "^2.2.11",
2122
"@types/node": "^20.12.12",
2223
"@types/react": "^18.3.2",

src/components/app.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { DEFAULT_BOARD_SIZE } from '@/config/const';
2+
import { useApp } from '@/hooks/use-app';
3+
4+
import { Board } from '@/components/board/board';
5+
import { Footer } from '@/components/layout/footer/footer';
6+
import { Heading } from '@/components/layout/heading/heading';
7+
import { Score } from '@/components/layout/score/score';
8+
import { Winner } from '@/components/winner/winner';
9+
10+
export const App = () => {
11+
const { isWin, board, score, boosterK, shuffle, shuffleCount, resetGame, requestSolver, boardRef } = useApp();
12+
return (
13+
<main className="main">
14+
{isWin ? (
15+
<Winner score={score} onReset={resetGame} />
16+
) : (
17+
<section>
18+
<header className="header">
19+
<Heading onReset={resetGame} onShuffle={shuffle} canShuffle={!!shuffleCount && !isWin} size={DEFAULT_BOARD_SIZE} />
20+
<Score value={score} multiplier={boosterK} />
21+
</header>
22+
<Board ref={boardRef} board={board} size={DEFAULT_BOARD_SIZE} onSolve={requestSolver} />
23+
</section>
24+
)}
25+
<Footer />
26+
</main>
27+
);
28+
};

src/components/app/app.module.css

Lines changed: 0 additions & 54 deletions
This file was deleted.

src/components/app/app.tsx

Lines changed: 0 additions & 65 deletions
This file was deleted.

src/components/grid/grid.tsx renamed to src/components/board/board.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,35 @@
11
import { forwardRef } from 'react';
2-
import { Cell } from '@/components/cell/cell';
2+
33
import { DEFAULT_BOARD_SIZE } from '@/config/const';
4+
import { useBoard } from '@/hooks/use-board';
45
import { cn } from '@/lib/utils';
5-
import { useGrid } from '@/hooks/use-grid';
6-
import type { TBoard, TGridSize } from '@/types/game';
6+
7+
import { Cell } from '@/components/cell/cell';
8+
9+
import type { TBoard, TBoardSize } from '@/types/game';
710

811
// Styles
9-
import s from './grid.module.css';
12+
import s from './board.module.css';
1013

1114
interface IProps {
1215
className?: string;
13-
size: TGridSize;
16+
size: TBoardSize;
1417
board: TBoard;
1518
onSolve: (score: number, remainCount: number) => void;
1619
}
1720

18-
export const Grid = forwardRef<HTMLDivElement, IProps>(({ className, ...props }, ref) => {
19-
const { selectedCells, solvedCells, handleCellClick } = useGrid(props);
21+
export const Board = forwardRef<HTMLDivElement, IProps>(({ className, ...props }, ref) => {
22+
const { selectedCells, solvedCells, handleCellClick } = useBoard(props);
2023
return (
2124
<div ref={ref} className={cn(s.wrapper, className)} style={{ grid: `auto / repeat(${DEFAULT_BOARD_SIZE.cols}, 1fr)` }}>
2225
{props.board.map((row, i) =>
2326
row.map((cell, j) => (
2427
<Cell
2528
key={`${i}-${j}`}
26-
coords={cell.coordinates}
29+
position={cell.coordinates}
2730
value={cell.value}
2831
selected={selectedCells.includes(cell.coordinates)}
29-
passed={solvedCells.includes(cell.coordinates)}
32+
solved={solvedCells.includes(cell.coordinates)}
3033
onClick={handleCellClick}
3134
/>
3235
)),

src/components/cell/cell.tsx

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,20 @@
1-
import { useCallback } from 'react';
1+
import { cn } from '@/lib/utils';
2+
3+
import type { TCoordinates } from '@/types/game';
24

35
// Styles
4-
import { cn } from '@/lib/utils';
56
import s from './cell.module.css';
6-
import type { TCoordinates } from '@/types/game';
77

88
interface IProps {
9-
coords: [number, number];
9+
position: TCoordinates;
1010
onClick?: (coords: TCoordinates) => void;
1111
value?: number;
1212
selected?: boolean;
13-
passed?: boolean;
13+
solved?: boolean;
1414
}
1515

16-
export const Cell: FC<IProps> = ({ coords, value, selected, passed, onClick }) => {
17-
const handleSelect = useCallback(() => {
18-
onClick?.(coords);
19-
}, [onClick, coords]);
20-
21-
return (
22-
<div onClick={handleSelect} className={cn(s.cell, selected && s.selected, passed && s.passed)}>
23-
{value}
24-
</div>
25-
);
26-
};
16+
export const Cell: FC<IProps> = ({ position, value, selected, solved, onClick }) => (
17+
<div onClick={() => onClick?.(position)} className={cn(s.cell, selected && s.selected, solved && s.passed)}>
18+
{value}
19+
</div>
20+
);

src/components/footer/footer.module.css

Lines changed: 0 additions & 4 deletions
This file was deleted.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/* styles */
2+
.footer {
3+
@apply pt-2 text-[12px] text-slate-500 opacity-40 transition-opacity;
4+
&:hover {
5+
@apply text-slate-200 opacity-100;
6+
}
7+
}

src/components/heading/heading.module.css renamed to src/components/layout/heading/heading.module.css

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
&.shuffle {
1414
@apply absolute
15-
bottom-8
1615
right-5
16+
top-5
1717
flex
1818
size-9
1919
items-center
@@ -22,6 +22,11 @@
2222
border-2
2323
p-1.5
2424
text-white;
25+
26+
&:global {
27+
will-change: transform;
28+
animation: pop 0.35s ease-in-out 0.3s both;
29+
}
2530
}
2631
}
2732

src/components/heading/heading.tsx renamed to src/components/layout/heading/heading.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { Shuffle } from 'lucide-react';
2-
import { TGridSize } from '@/types/game';
2+
33
import { cn } from '@/lib/utils';
44

5+
import { TBoardSize } from '@/types/game';
6+
57
// Styles
68
import s from './heading.module.css';
79

810
interface IProps {
9-
size: TGridSize;
11+
size: TBoardSize;
1012
onReset: () => void;
1113
onShuffle: () => void;
1214
canShuffle: boolean;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
.wrapper {
2+
@apply flex
3+
min-h-[80vh]
4+
flex-col justify-center gap-2
5+
text-center text-4xl text-white;
6+
}
7+
8+
.icon {
9+
@apply relative top-5 text-[120px];
10+
11+
&:global {
12+
will-change: transform, filter;
13+
animation: pop 0.35s ease-in-out both;
14+
}
15+
}
16+
17+
.text {
18+
@apply text-2xl font-black tracking-widest;
19+
text-shadow:
20+
0 0 10px rgba(0, 0, 0, 1),
21+
0 5px 5px rgba(0, 0, 0, 1);
22+
23+
&:global {
24+
will-change: transform;
25+
animation: fadeInUp 0.35s ease-in-out 0.1s both;
26+
}
27+
}
28+
29+
.score {
30+
@apply relative my-3 bg-gradient-to-r from-primary
31+
to-orange-400 bg-clip-text text-7xl font-black tracking-tighter text-transparent;
32+
33+
&:global {
34+
will-change: transform;
35+
animation: fadeInDown 0.35s ease-in-out 0.1s both;
36+
}
37+
}
38+
39+
.button {
40+
@apply btn text-2xl font-bold tracking-tight;
41+
42+
&:global {
43+
will-change: transform;
44+
animation: fadeInUp 0.35s ease-in-out 0.3s both;
45+
}
46+
}

0 commit comments

Comments
 (0)