Skip to content

Commit 33bf4fa

Browse files
committed
feat: 서비스 종료 dialog 홈화면에 배치
1 parent 619050a commit 33bf4fa

File tree

4 files changed

+110
-5
lines changed

4 files changed

+110
-5
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"class-variance-authority": "^0.7.1",
2424
"clsx": "^2.1.1",
2525
"date-fns": "^3.0.0",
26-
"es-hangul": "^2.3.2",
26+
"es-hangul": "^2.3.8",
2727
"framer-motion": "^12.4.7",
2828
"js-cookie": "^3.0.5",
2929
"keen-slider": "^6.8.6",
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { Button } from "@/components/ui/button";
2+
import {
3+
Dialog,
4+
DialogContent,
5+
DialogHeader,
6+
DialogTitle,
7+
} from "@/components/ui/dialog";
8+
import { useEffect, useState } from "react";
9+
10+
const SERVICE_END_DIALOG_STORAGE_KEY = "serviceEndDialogDontShow";
11+
12+
interface ServiceEndDialogProps {
13+
value: boolean;
14+
onButtonClick: () => void;
15+
}
16+
17+
export function ServiceEndDialog({
18+
value,
19+
onButtonClick,
20+
}: ServiceEndDialogProps) {
21+
const [open, setOpen] = useState(false);
22+
const [dontShowAgain, setDontShowAgain] = useState(false);
23+
24+
useEffect(() => {
25+
setOpen(value);
26+
}, [value]);
27+
28+
const handleButtonClick = () => {
29+
if (dontShowAgain) {
30+
localStorage.setItem(SERVICE_END_DIALOG_STORAGE_KEY, "true");
31+
}
32+
onButtonClick();
33+
};
34+
35+
return (
36+
<Dialog open={open} onOpenChange={setOpen}>
37+
<DialogContent className="w-[328px] rounded-[24px] border-none bg-component-gray-secondary px-4 pt-6 pb-4">
38+
<div>
39+
<div className="text-[24px] font-bold text-gray-normal mb-4 text-center">
40+
서비스 종료 안내
41+
</div>
42+
<div className="mb-2 text-center text-b3 text-gray-neutral whitespace-pre-line">
43+
{`그동안 SPURT를 이용해 주셔서 진심으로 감사합니다.
44+
SPURT는 2026년 2월 20일부로 서비스를 종료하게 되었습니다.
45+
서비스 종료 이후에는 앱 이용이 불가하며,
46+
관련 데이터 또한 모두 안전하게 삭제될 예정입니다.
47+
48+
그동안 이용해 주셔서 정말 감사합니다.
49+
50+
SPURT 팀 드림`}
51+
</div>
52+
</div>
53+
<div className="flex items-center justify-end gap-2 mb-3">
54+
<label
55+
htmlFor="dontShowAgain"
56+
className="text-c2 text-gray-neutral cursor-pointer flex items-center gap-2"
57+
>
58+
<input
59+
id="dontShowAgain"
60+
type="checkbox"
61+
checked={dontShowAgain}
62+
onChange={(e) => setDontShowAgain(e.target.checked)}
63+
className="w-4 h-4 rounded border-gray-normal cursor-pointer"
64+
/>
65+
다시 보지 않기
66+
</label>
67+
</div>
68+
<Button
69+
size="md"
70+
variant="primary"
71+
className="w-full"
72+
onClick={handleButtonClick}
73+
>
74+
확인
75+
</Button>
76+
</DialogContent>
77+
</Dialog>
78+
);
79+
}
80+
81+
export function shouldShowServiceEndDialog(): boolean {
82+
if (typeof window === "undefined") return true;
83+
const dontShow = localStorage.getItem(SERVICE_END_DIALOG_STORAGE_KEY);
84+
return dontShow !== "true";
85+
}

src/app/(protected)/(root)/page.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ import AllTaskTabWrapper from "./_components/allTaskTabWrapper/AllTaskTabWrapper
1616
import Footer from "./_components/footer/Footer";
1717
import Header from "./_components/header/Header";
1818
import TodayTaskTabWrapper from "./_components/todayTaskTabWrapper/TodayTaskTabWrapper";
19+
import {
20+
ServiceEndDialog,
21+
shouldShowServiceEndDialog,
22+
} from "./_components/serviceEndDialog/ServiceEndDialog";
1923

2024
const HomePageContent = () => {
2125
const router = useRouter();
@@ -51,6 +55,7 @@ const HomePageContent = () => {
5155
const [isFailedDialogOpen, setIsFailedDialogOpen] = useState(false);
5256
const [personaId, setPersonaId] = useState<number | undefined>(undefined);
5357
const [isCreateSheetOpen, setIsCreateSheetOpen] = useState(false);
58+
const [isServiceEndDialogOpen, setIsServiceEndDialogOpen] = useState(false);
5459

5560
const searchParams = useSearchParams();
5661
const [taskName, setTaskName] = useState("");
@@ -114,6 +119,10 @@ const HomePageContent = () => {
114119
setIsFailedDialogOpen(false);
115120
};
116121

122+
const handleServiceEndDialogButtonClick = () => {
123+
setIsServiceEndDialogOpen(false);
124+
};
125+
117126
const handleTabChange = useCallback((tab: "today" | "all") => {
118127
setActiveTab(tab);
119128
}, []);
@@ -175,6 +184,12 @@ const HomePageContent = () => {
175184
}
176185
}, [searchParams]);
177186

187+
useEffect(() => {
188+
if (shouldShowServiceEndDialog()) {
189+
setIsServiceEndDialogOpen(true);
190+
}
191+
}, []);
192+
178193
return (
179194
<>
180195
<div className="flex flex-col overflow-hidden bg-background-primary">
@@ -253,6 +268,11 @@ const HomePageContent = () => {
253268
isOpen={isCreateSheetOpen}
254269
onClose={handleCloseCreateSheet}
255270
/>
271+
272+
<ServiceEndDialog
273+
value={isServiceEndDialogOpen}
274+
onButtonClick={handleServiceEndDialogButtonClick}
275+
/>
256276
</>
257277
);
258278
};

0 commit comments

Comments
 (0)