Skip to content

Commit

Permalink
feat: 이용약관, 개인정보수집 동의 페이지 (#93)
Browse files Browse the repository at this point in the history
* feat: 이용약관, 개인정보수집 동의 페이지

* feat: 약관동의 페이지, 로그인 성공페이지 분리

* feat: 온보딩 페이지 로그인 여부 확인

* feat: 약관동의 시 mypage로 이동

* feat: 첫 로그인 유저 약관동의로 이동
  • Loading branch information
Youjiiin authored Feb 12, 2025
1 parent d7366a3 commit 13ce70c
Show file tree
Hide file tree
Showing 5 changed files with 275 additions and 5 deletions.
78 changes: 78 additions & 0 deletions packages/icon/CheckIconHome.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import type { ComponentPropsWithoutRef } from "react";

export const CheckIconHome = (props: ComponentPropsWithoutRef<"svg"> & { checked?: boolean }) => {
const { checked, ...rest } = props;

return checked ? (
// biome-ignore lint/a11y/noSvgWithoutTitle: <explanation>
<svg
width="25"
height="25"
viewBox="0 0 25 25"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...rest}
>
<g clipPath="url(#clip0_1693_12543)">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M25 12.5C25 19.375 19.375 25 12.5 25C5.625 25 0 19.375 0 12.5C0 5.625 5.625 0 12.5 0C19.375 0 25 5.625 25 12.5Z"
fill="url(#paint0_linear_1693_12543)"
/>
<path
d="M7.375 12.125L11.25 16L17.625 9.6875"
stroke="#F5F5F9"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
<defs>
<linearGradient
id="paint0_linear_1693_12543"
x1="0"
y1="12.5"
x2="25"
y2="12.5"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#7CACD2" />
<stop offset="1" stopColor="#A269FF" />
</linearGradient>
<clipPath id="clip0_1693_12543">
<rect width="25" height="25" fill="white" />
</clipPath>
</defs>
</svg>
) : (
<svg
width="25"
height="25"
viewBox="0 0 25 25"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...rest}
>
<g clipPath="url(#clip0_1693_12532)">
<path
d="M24.25 12.5C24.25 18.9608 18.9608 24.25 12.5 24.25C6.03921 24.25 0.75 18.9608 0.75 12.5C0.75 6.03921 6.03921 0.75 12.5 0.75C18.9608 0.75 24.25 6.03921 24.25 12.5Z"
stroke="#E7EAF1"
strokeWidth="1.5"
/>
<path
d="M7.375 12.125L11.25 16L17.625 9.6875"
stroke="#E7EAF1"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
<defs>
<clipPath id="clip0_1693_12532">
<rect width="25" height="25" fill="white" />
</clipPath>
</defs>
</svg>
);
};
4 changes: 4 additions & 0 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ import BookRecordPage from "./pages/BookRecordPage.tsx";
import BookRecordWritePage from "./pages/BookRecordWritePage.tsx";
import HomePage from "./pages/HomePage.tsx";
import { LoginPage } from "./pages/LoginPage.tsx";
import LoginSuccessPage from "./pages/LoginSuccessPage.tsx";
import Notification from "./pages/Notification.tsx";
import OnBoardingPage from "./pages/OnBoardingPage.tsx";
import ProfilePage from "./pages/ProfilePage.tsx";
import SettingPage from "./pages/SettingPage.tsx";
import TermsPrivacyConsentPage from "./pages/TermsPrivacyConsentPage.tsx";
import TimerPage from "./pages/TimerPage.tsx";

createRoot(document.getElementById("root")!).render(
Expand Down Expand Up @@ -52,6 +54,8 @@ createRoot(document.getElementById("root")!).render(
<Route path="settings" element={<SettingPage />} />
<Route path="" element={<OnBoardingPage />} />
<Route path="login" element={<LoginPage />} />
<Route path="login/success" element={<LoginSuccessPage />} />
<Route path="login/agree" element={<TermsPrivacyConsentPage />} />
</Routes>
</OverlayProvider>
</BrowserRouter>
Expand Down
56 changes: 56 additions & 0 deletions src/pages/LoginSuccessPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { AspectRatio } from "@repo/design-system/AspectRatio";
import { Image } from "@repo/design-system/Image";
import { toast } from "@repo/design-system/Toast";
import { CenterStack } from "@repo/ui/CenterStack";
import { Stack } from "@repo/ui/Stack";
import { useEffect } from "react";
import { useNavigate } from "react-router";
import { authStore } from "~/entities/user/model/auth.store";
import { LOGO_ASSETS } from "~/shared/images/logo/logoImages";

export default function LoginSuccessPage() {
const navigate = useNavigate();

useEffect(() => {
const params = new URLSearchParams(window.location.search);
const accessToken = params.get("access_token");
const isNewUser = params.get("isNewUser");

if (accessToken) {
authStore.setAccessToken(accessToken);
if (isNewUser) {
navigate("/login/agree", { replace: true });
} else {
navigate("/home", { replace: true });
}
} else {
toast.main("로그인에 실패했습니다.", { duration: 1500 });
navigate("/");
}
}, [navigate]);

return (
<CenterStack className=" min-h-screen w-full bg-navy h-full gap-y-[100px]">
<CenterStack className=" w-full px-4">
<Stack className=" w-full">
<AspectRatio ratio={343 / 219}>
<Image
src={LOGO_ASSETS.MERCURY_LOGIN_LOGO_WEBP}
alt="mercury logo"
objectfit={"fill"}
/>
</AspectRatio>
</Stack>
<Stack className=" mt-[30px] pl-[66px] pr-[54px] w-full">
<AspectRatio ratio={255 / 52}>
<Image
src={LOGO_ASSETS.WORDMARKLOGO_DARKBG_WEBP}
alt="wordmark logo"
objectfit={"fill"}
/>
</AspectRatio>
</Stack>
</CenterStack>
</CenterStack>
);
}
25 changes: 20 additions & 5 deletions src/pages/OnBoardingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,28 @@ import { CenterStack } from "@repo/ui/CenterStack";
import { Flex } from "@repo/ui/Flex";
import { Spacing } from "@repo/ui/Spacing";
import { Stack } from "@repo/ui/Stack";
import { useEffect } from "react";
import { Link, useNavigate } from "react-router";
import { authStore } from "~/entities/user/model/auth.store";
import { LOGO_ASSETS } from "~/shared/images/logo/logoImages";
import { AppleButton } from "~/shared/ui/AppleButton";
import { GoogleButton } from "~/shared/ui/GoogleButton";
import { KakaoButton } from "~/shared/ui/KakaoButton";
import { openExternalUrl } from "~/shared/utils/openExternalUrl";

export default function OnBoardingPage() {
const navigate = useNavigate();

useEffect(() => {
const accessToken = authStore.getAccessToken();
if (accessToken) {
navigate("/home");
}
}, [navigate]);

return (
<CenterStack className=" min-h-screen w-full bg-navy h-full gap-y-[100px]">
<MercuryImageSection />
<SignUpSection />
<_SignUpSection />
</CenterStack>
);
}
Expand Down Expand Up @@ -59,7 +70,7 @@ const MercuryImageSection = () => {
);
};

const SignUpSection = () => {
const _SignUpSection = () => {
return (
<Stack className="gap-y-[14px] w-full items-center">
<Flex>
Expand All @@ -68,9 +79,9 @@ const SignUpSection = () => {
</Text>
</Flex>
<Center className=" gap-x-[18px] items-center w-full justify-center">
<KakaoButton onClick={() => toast.main("준비중인 기능이에요", { duration: 1500 })} />
{/* <KakaoButton onClick={() => toast.main("준비중인 기능이에요", { duration: 1500 })} /> */}
<AppleButton onClick={() => toast.main("준비중인 기능이에요", { duration: 1500 })} />
<GoogleButton onClick={() => toast.main("준비중인 기능이에요", { duration: 1500 })} />
<GoogleButton onClick={() => openExternalUrl(ONBOARDING_LINKS.GOOGLE_LOGIN)} />
</Center>
<Flex>
<Link
Expand All @@ -87,3 +98,7 @@ const SignUpSection = () => {
</Stack>
);
};

const ONBOARDING_LINKS = {
GOOGLE_LOGIN: "https://api.mercuryplanet.co.kr/oauth2/authorization/google",
};
117 changes: 117 additions & 0 deletions src/pages/TermsPrivacyConsentPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { AspectRatio } from "@repo/design-system/AspectRatio";
import { Button } from "@repo/design-system/Button";
import { FixedBottom } from "@repo/design-system/FixedBottom";
import { Image } from "@repo/design-system/Image";
import { Text } from "@repo/design-system/Text";
import { CheckIconHome } from "@repo/icon/CheckIconHome";
import { CenterStack } from "@repo/ui/CenterStack";
import { Flex } from "@repo/ui/Flex";
import { Stack } from "@repo/ui/Stack";
import { useState } from "react";
import { useNavigate } from "react-router";
import { LOGO_ASSETS } from "~/shared/images/logo/logoImages";
import { openExternalUrl } from "~/shared/utils/openExternalUrl";

export default function TermsPrivacyConsentPage() {
const navigate = useNavigate();
const [termsOfService, setTermsOfService] = useState(false);
const [privacyConsent, setPrivacyConsent] = useState(false);

const allChecked = termsOfService && privacyConsent;

const handleToggleAll = () => {
const currentlyAllChecked = termsOfService && privacyConsent;
setTermsOfService(!currentlyAllChecked);
setPrivacyConsent(!currentlyAllChecked);
};

const handleNotionClick = () => {
openExternalUrl(ONBOARDING_LINKS.TERMS_PRIVACY_CONSENT);
};

const handleConfirm = () => {
if (allChecked) {
navigate("/home");
}
};

return (
<CenterStack className=" min-h-screen w-full bg-navy h-full gap-y-[50px]">
<CenterStack className=" w-full px-4">
<Stack className=" w-full">
<AspectRatio ratio={343 / 219}>
<Image
src={LOGO_ASSETS.MERCURY_LOGIN_LOGO_WEBP}
alt="mercury logo"
objectfit={"fill"}
/>
</AspectRatio>
</Stack>
<Stack className=" mt-[30px] pl-[66px] pr-[54px] w-full">
<AspectRatio ratio={255 / 52}>
<Image
src={LOGO_ASSETS.WORDMARKLOGO_DARKBG_WEBP}
alt="wordmark logo"
objectfit={"fill"}
/>
</AspectRatio>
</Stack>
</CenterStack>

<Stack className="h-full w-full justify-between">
<Stack className="px-[67px] gap-[14px]">
<button className="" onClick={handleToggleAll}>
<Flex className="gap-[15px]">
<CheckIconHome checked={allChecked} />
<Text variant={"body/16_sb"} className="text-gray-100">
모두 동의하기
</Text>
</Flex>
</button>
<div className="h-[1px] w-full bg-gray-500"></div>

<button className="w-full" onClick={() => setTermsOfService((prev) => !prev)}>
<Flex className="gap-[15px] mb-[3px]">
<CheckIconHome checked={termsOfService} />
<Text variant={"body/16_sb"} className="text-gray-100">
(필수) 이용약관
</Text>
</Flex>
</button>

<button className="w-full" onClick={() => setPrivacyConsent((prev) => !prev)}>
<Flex className="gap-[15px]">
<CheckIconHome checked={privacyConsent} />
<Text variant={"body/16_sb"} className="text-gray-100">
(필수) 개인 정보 수집 / 이용 동의
</Text>
</Flex>
</button>
<button onClick={handleNotionClick}>
<Text variant={"caption/12_r"} className="text-gray-300 underline mt-[3px]">
이용약관 및 개인정보 처리방침
</Text>
</button>
</Stack>

<FixedBottom className="flex flex-col px-4 gap-[14px] bottom-[25px]">
{!allChecked && (
<Text variant="body/13_r" className="text-warning-red text-center">
필수 약관에 동의해 주세요
</Text>
)}
<Button
variant={allChecked ? "primary" : "gray"}
onClick={handleConfirm}
className={allChecked ? "" : "text-gray-400"}
>
확인
</Button>
</FixedBottom>
</Stack>
</CenterStack>
);
}
const ONBOARDING_LINKS = {
TERMS_PRIVACY_CONSENT: "https://mercuryplanet.notion.site/use-policy",
};

0 comments on commit 13ce70c

Please sign in to comment.