Skip to content

Commit 997aff4

Browse files
authored
refactor : Apply the headless component pattern to the start page (#44)
* refactor: Move files * refactor: Separation of UI and business logic about Background * refactor: Separation of UI and business logic about HelpModal * refactor: Add Container Component in main * refactor: Add Container Component in help modal * refactor: Use Alias * refactor: Move className Props from MainPage to BackgroundCanvasContainter * refactor: Use Spread Operation in Container Component * refactor: Change name from pagenation to pageIndicator * refactor: Change Component from BackgroundImage to BackgroundContainer in GameLayout * refactor : Delete importing BackgroundImg in GameLayout.tsx * refactor : Edit spline logic
1 parent 76e5f46 commit 997aff4

15 files changed

+220
-89
lines changed

client/src/components/ui/HelpContainer.tsx renamed to client/src/components/help/HelpButton.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import helpIcon from '@/assets/help-icon.svg';
33
import { Button } from '@/components/ui/Button';
44
import { useModal } from '@/hooks/useModal';
55

6-
const HelpRollingModal = lazy(() => import('@/components/modal/HelpRollingModal'));
6+
const HelpModalContainer = lazy(() => import('@/components/help/HelpModalContainer'));
77

88
const HelpContainer = () => {
99
const { isModalOpened, closeModal, openModal, handleKeyDown } = useModal();
@@ -19,7 +19,7 @@ const HelpContainer = () => {
1919
};
2020

2121
return (
22-
<nav className="fixed right-4 top-4 z-30 xs:right-8 xs:top-8">
22+
<section className="fixed right-4 top-4 z-30 xs:right-8 xs:top-8">
2323
<Button
2424
variant="transperent"
2525
size="icon"
@@ -33,10 +33,14 @@ const HelpContainer = () => {
3333

3434
{shouldLoadModal && (
3535
<Suspense fallback={null}>
36-
<HelpRollingModal isModalOpened={isModalOpened} handleCloseModal={closeModal} handleKeyDown={handleKeyDown} />
36+
<HelpModalContainer
37+
isModalOpened={isModalOpened}
38+
handleCloseModal={closeModal}
39+
handleKeyDown={handleKeyDown}
40+
/>
3741
</Suspense>
3842
)}
39-
</nav>
43+
</section>
4044
);
4145
};
4246

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import HelpModalUI from './HelpModalUI';
2+
import useHelpModal from '@/hooks/useHelpModal';
3+
import { HelpModalContainerProps } from '@/types/help.types';
4+
5+
const HelpModalContainer = ({ isModalOpened, handleCloseModal, handleKeyDown }: HelpModalContainerProps) => {
6+
const helpModalProps = useHelpModal(isModalOpened);
7+
return (
8+
<HelpModalUI
9+
{...helpModalProps}
10+
isModalOpened={isModalOpened}
11+
handleCloseModal={handleCloseModal}
12+
handleKeyDown={handleKeyDown}
13+
/>
14+
);
15+
};
16+
17+
export default HelpModalContainer;

client/src/components/ui/HelpPage.tsx renamed to client/src/components/help/HelpModalPage.tsx

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { useEffect } from 'react';
22
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
3+
import Indicator from './Indicator';
34
import { HelpPageProps } from '@/types/help.types';
45
import { cn } from '@/utils/cn';
56

6-
const HelpPage = ({ pageData, isModalOpened, dotLottieRefCallback, pagenation, setPageIndex }: HelpPageProps) => {
7+
const HelpPage = ({ pageData, isModalOpened, dotLottieRefCallback, pageIndicator, setPageIndex }: HelpPageProps) => {
78
useEffect(() => {
89
const loadAnimation = async () => {
910
const response = await fetch(pageData.img);
@@ -37,22 +38,7 @@ const HelpPage = ({ pageData, isModalOpened, dotLottieRefCallback, pagenation, s
3738
</div>
3839
</article>
3940
</section>
40-
<div className="relative top-5 flex flex-row items-center justify-center p-5">
41-
{pagenation.map((isSelect, i) => {
42-
return (
43-
<button
44-
key={i}
45-
className={cn(
46-
'mx-1.5 box-content h-2.5 w-2.5 rounded-full md:h-3 md:w-3',
47-
isSelect ? 'border-4 border-halfbaked-300 bg-chartreuseyellow-300' : 'bg-eastbay-600',
48-
)}
49-
onClick={() => {
50-
setPageIndex(i);
51-
}}
52-
/>
53-
);
54-
})}
55-
</div>
41+
<Indicator pageData={pageData} pageIndicator={pageIndicator} setPageIndex={setPageIndex} />
5642
</div>
5743
);
5844
};
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import HelpPage from './HelpModalPage';
2+
import left from '@/assets/left.svg';
3+
import right from '@/assets/right.svg';
4+
import { Modal } from '@/components/ui/Modal';
5+
import { HelpModalUIProps } from '@/types/help.types';
6+
7+
const HelpModalUI = ({
8+
isModalOpened,
9+
handleCloseModal,
10+
handleKeyDown,
11+
pageData,
12+
pageIndex,
13+
setPageIndex,
14+
pageIndicator,
15+
dotLottieRefCallback,
16+
handleTouchStart,
17+
handleTouchEnd,
18+
handleTouchMove,
19+
changePageIndex,
20+
}: HelpModalUIProps) => {
21+
return (
22+
<Modal
23+
isModalOpened={isModalOpened}
24+
closeModal={handleCloseModal}
25+
handleKeyDown={handleKeyDown}
26+
className="w-full max-w-screen-md"
27+
>
28+
<section
29+
className="flex md:p-7"
30+
onTouchStart={handleTouchStart}
31+
onTouchMove={handleTouchMove}
32+
onTouchEnd={handleTouchEnd}
33+
>
34+
<button className="relative -left-6 hidden md:block" onClick={() => changePageIndex(true)}>
35+
<img src={left} width={30} alt="이전 페이지 버튼" className="transition hover:brightness-75" />
36+
</button>
37+
<HelpPage
38+
pageData={pageData[pageIndex]}
39+
isModalOpened
40+
dotLottieRefCallback={dotLottieRefCallback}
41+
pageIndicator={pageIndicator}
42+
setPageIndex={setPageIndex}
43+
/>
44+
<button className="relative -right-6 hidden md:block" onClick={() => changePageIndex(false)}>
45+
<img src={right} width={30} alt="다음 페이지 버튼" className="transition hover:brightness-75" />
46+
</button>
47+
</section>
48+
</Modal>
49+
);
50+
};
51+
52+
export default HelpModalUI;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { useEffect } from 'react';
2+
import { IndicatorProps } from '@/types/help.types';
3+
import { cn } from '@/utils/cn';
4+
5+
const Indicator = ({ pageData, pageIndicator, setPageIndex }: IndicatorProps) => {
6+
useEffect(() => {
7+
const loadAnimation = async () => {
8+
const response = await fetch(pageData.img);
9+
const blob = await response.blob();
10+
pageData.cache = URL.createObjectURL(blob);
11+
};
12+
13+
if (!pageData.cache) {
14+
void loadAnimation();
15+
}
16+
}, [pageData.img]);
17+
18+
return (
19+
<div className="relative top-5 flex flex-row items-center justify-center p-5">
20+
{pageIndicator.map((isSelect, i) => {
21+
return (
22+
<button
23+
key={i}
24+
className={cn(
25+
'mx-1.5 box-content h-2.5 w-2.5 rounded-full md:h-3 md:w-3',
26+
isSelect ? 'border-4 border-halfbaked-300 bg-chartreuseyellow-300' : 'bg-eastbay-600',
27+
)}
28+
onClick={() => {
29+
setPageIndex(i);
30+
}}
31+
/>
32+
);
33+
})}
34+
</div>
35+
);
36+
};
37+
38+
export default Indicator;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import BackgroundCanvasUI from './BackgroundCanvasUI';
2+
import BackgroundImage from '@/components/main/BackgroundImage';
3+
import useBackgroundCanvas from '@/hooks/useBackgroundCanvas';
4+
5+
const BackgroundContainer = () => {
6+
const backgroundCanvasProps = useBackgroundCanvas();
7+
8+
return (
9+
<>
10+
<BackgroundImage className="-z-30" />
11+
<BackgroundCanvasUI className="pointer-events-auto absolute inset-0 -z-20" {...backgroundCanvasProps} />
12+
</>
13+
);
14+
};
15+
16+
export default BackgroundContainer;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { BackgroundCanvasUIProps } from '@/types/help.types';
2+
3+
const BackgroundCanvasUI = ({
4+
className,
5+
cursorCanvasRef,
6+
handleMouseLeave,
7+
handleMouseMove,
8+
}: BackgroundCanvasUIProps) => {
9+
return (
10+
<div className={className}>
11+
<canvas
12+
ref={cursorCanvasRef}
13+
className="absolute h-full w-full cursor-none"
14+
onMouseMove={handleMouseMove}
15+
onMouseLeave={handleMouseLeave}
16+
/>
17+
</div>
18+
);
19+
};
20+
21+
export default BackgroundCanvasUI;

client/src/components/ui/BackgroundImage.tsx renamed to client/src/components/main/BackgroundImage.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,7 @@ import tiny from '@/assets/background-tiny.png';
33
import { CDN } from '@/constants/cdn';
44
import { cn } from '@/utils/cn';
55

6-
interface BackgroundImageProps {
7-
className?: string;
8-
}
9-
10-
const BackgroundImage = ({ className }: BackgroundImageProps) => {
6+
const BackgroundImage = ({ className }: { className: string }) => {
117
const [isLoaded, setIsLoaded] = useState(false);
128

139
return (

client/src/hooks/canvas/useDrawingOperation.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,10 @@ export const useDrawingOperation = (
106106
}
107107
case 2: {
108108
// 두 점은 직선으로 연결
109+
const mid1x = (points[0].x + points[1].x) >> 1;
110+
const mid1y = (points[0].y + points[1].y) >> 1;
109111
ctx.moveTo(points[0].x, points[0].y);
110-
ctx.lineTo(points[1].x, points[1].y);
112+
ctx.lineTo(mid1x, mid1y);
111113
ctx.stroke();
112114
break;
113115
}

client/src/components/ui/BackgroundCanvas.tsx renamed to client/src/hooks/useBackgroundCanvas.tsx

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { CURSOR_LENGTH, CURSOR_WIDTH, DELETE_INTERVAL } from '@/constants/backgr
44
import { getCanvasContext } from '@/utils/getCanvasContext';
55
import { getDrawPoint } from '@/utils/getDrawPoint';
66

7-
const Background = ({ className }: { className: string }) => {
7+
const useBackgroundCanvas = () => {
88
const cursorCanvasRef = useRef<HTMLCanvasElement>(null);
99
const cursorAnimation = useRef<number>();
1010

@@ -21,8 +21,8 @@ const Background = ({ className }: { className: string }) => {
2121
const { canvas, ctx } = getCanvasContext(cursorCanvasRef);
2222

2323
const handleResize = () => {
24-
canvas.width = canvas.offsetWidth;
25-
canvas.height = canvas.offsetHeight;
24+
canvas.width = canvas.clientWidth;
25+
canvas.height = canvas.clientHeight;
2626
};
2727

2828
handleResize();
@@ -90,16 +90,11 @@ const Background = ({ className }: { className: string }) => {
9090
ctx.clearRect(0, 0, canvas.width, canvas.height);
9191
};
9292

93-
return (
94-
<div className={className}>
95-
<canvas
96-
ref={cursorCanvasRef}
97-
className="absolute h-full w-full cursor-none"
98-
onMouseMove={handleMouseMove}
99-
onMouseLeave={handleMouseLeave}
100-
/>
101-
</div>
102-
);
93+
return {
94+
cursorCanvasRef,
95+
handleMouseLeave,
96+
handleMouseMove,
97+
};
10398
};
10499

105-
export default Background;
100+
export default useBackgroundCanvas;

0 commit comments

Comments
 (0)