From 024bcf63237a478c1d32c3b8da4037f9ba6c2606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=ED=98=84=EC=9A=B0?= Date: Mon, 11 Dec 2023 20:18:06 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat(login):=20login=ED=8D=BC=EB=84=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs:[#13, #14] --- component/Funnel/LoginFunnel.tsx | 46 +++++++++++++++++++++ component/Funnel/MainFunnel.tsx | 69 ++++++++++++++++++++++++++++++++ src/app/page.tsx | 60 ++++----------------------- src/app/signup/page.tsx | 2 +- utils/hooks/useFunnel.ts | 4 +- 5 files changed, 125 insertions(+), 56 deletions(-) create mode 100644 component/Funnel/LoginFunnel.tsx create mode 100644 component/Funnel/MainFunnel.tsx diff --git a/component/Funnel/LoginFunnel.tsx b/component/Funnel/LoginFunnel.tsx new file mode 100644 index 0000000..cfa4d77 --- /dev/null +++ b/component/Funnel/LoginFunnel.tsx @@ -0,0 +1,46 @@ +"use client"; +import { ButtonGroup, Text } from "@chakra-ui/react"; +import MainButton from "../button/MainButton"; +import Image from "next/image"; +import { useRouter } from "next/navigation"; + +const LoginFunnel = () => { + const router = useRouter(); + return ( + <> + 식선생 + + + {}}> + 다음으로 + + router.push("/signup")} + cursor={"pointer"} + > + 체험하기 + + + + ); +}; + +export default LoginFunnel; diff --git a/component/Funnel/MainFunnel.tsx b/component/Funnel/MainFunnel.tsx new file mode 100644 index 0000000..d1b92eb --- /dev/null +++ b/component/Funnel/MainFunnel.tsx @@ -0,0 +1,69 @@ +"use client"; +import { Box, ButtonGroup, Heading, Text } from "@chakra-ui/react"; +import Image from "next/image"; +import MainButton from "../../component/button/MainButton"; +import { useRouter } from "next/navigation"; +import { Dispatch, SetStateAction } from "react"; + +interface MainFunnelPropsType { + setFunnel: Dispatch>; +} + +const MainFunnel = ({ setFunnel }: MainFunnelPropsType) => { + const router = useRouter(); + + return ( + <> + 식선생 + + + 살빼려면 +
+ 오늘 얼마만큼 운동해야하지? +
+ + 오늘 먹은 음식을 식선생에게 외쳐보세요!
+ 필요 운동량과 안찌는 식단을 한번에 알려드려요 +
+
+ + + { + setFunnel("login"); + }} + > + 다음으로 + + + + ); +}; + +export default MainFunnel; diff --git a/src/app/page.tsx b/src/app/page.tsx index 879ef97..dcd5c3a 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,11 +1,11 @@ "use client"; -import { Box, ButtonGroup, Flex, Heading, Text } from "@chakra-ui/react"; -import MainButton from "../../component/button/MainButton"; -import { useRouter } from "next/navigation"; -import Image from "next/image"; +import { Flex } from "@chakra-ui/react"; +import { useFunnel } from "../../utils/hooks/useFunnel"; +import MainFunnel from "../../component/Funnel/MainFunnel"; +import LoginFunnel from "../../component/Funnel/LoginFunnel"; export default function Home() { - const router = useRouter(); + const { funnel, setFunnel } = useFunnel("main"); return ( - 식선생 - - - 살빼려면 -
- 오늘 얼마만큼 운동해야하지? -
- - 오늘 먹은 음식을 식선생에게 외쳐보세요!
- 필요 운동량과 안찌는 식단을 한번에 알려드려요 -
-
- - - { - router.push("/signup"); - }} - > - 다음으로 - - + {funnel === "main" && } + {funnel === "login" && }
); } diff --git a/src/app/signup/page.tsx b/src/app/signup/page.tsx index e8e4145..3531524 100644 --- a/src/app/signup/page.tsx +++ b/src/app/signup/page.tsx @@ -8,7 +8,7 @@ import UserAgreementForm from "../../../component/form/UserAgreementForm"; const Page = () => { const [progress, setProgress] = useState(33.3); - const { funnel, setFunnel } = useFunnel(); + const { funnel, setFunnel } = useFunnel("userInfo"); return ( <> { - const [funnel, setFunnel] = useState("userInfo"); +export const useFunnel = (state: string) => { + const [funnel, setFunnel] = useState(state); return { funnel, setFunnel }; }; From 93dda4f2d2c7cf2aaafaeeccb2a7cde1d2838692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=ED=98=84=EC=9A=B0?= Date: Mon, 11 Dec 2023 20:56:41 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat(agreement)=20:=20=EC=95=BD=EA=B4=80?= =?UTF-8?q?=EB=8F=99=EC=9D=98=20checkbox?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs:[#4,#5] --- component/button/MainButton.tsx | 1 + component/form/UserAgreementForm.tsx | 88 +++++++++++++++++++++++++++- src/app/signup/page.tsx | 10 +++- 3 files changed, 94 insertions(+), 5 deletions(-) diff --git a/component/button/MainButton.tsx b/component/button/MainButton.tsx index 30221cb..b99db25 100644 --- a/component/button/MainButton.tsx +++ b/component/button/MainButton.tsx @@ -9,6 +9,7 @@ const MainButton = ({ children, w, h, onClick }: ButtonProps) => { borderRadius={"12px"} w={w} h={h} + maxW={"390px"} onClick={onClick} > {children} diff --git a/component/form/UserAgreementForm.tsx b/component/form/UserAgreementForm.tsx index 5d8cded..cd3ddeb 100644 --- a/component/form/UserAgreementForm.tsx +++ b/component/form/UserAgreementForm.tsx @@ -1,5 +1,12 @@ -import { Box, ButtonGroup, Flex, Heading, RadioGroup } from "@chakra-ui/react"; -import React from "react"; +import { + Box, + ButtonGroup, + Checkbox, + Flex, + Heading, + VStack, +} from "@chakra-ui/react"; +import React, { useState } from "react"; import MainButton from "../button/MainButton"; interface UserAgreementFormPropsType { @@ -7,6 +14,10 @@ interface UserAgreementFormPropsType { } const UserAgreementForm = ({ setFunnel }: UserAgreementFormPropsType) => { + const [checkedItems, setCheckedItems] = useState([false, false, false]); + const allChecked = checkedItems.every(Boolean); + const isIndeterminate = checkedItems.some(Boolean) && !allChecked; + return ( @@ -15,13 +26,84 @@ const UserAgreementForm = ({ setFunnel }: UserAgreementFormPropsType) => { color={"#000000"} fontSize={"24px"} fontWeight={"semibold"} + lineHeight={"35px"} > - 서비스를 이용하시려면 + 식선생을 이용하시려면
약관 동의가 필요해요.
+ + + + setCheckedItems([ + e.target.checked, + e.target.checked, + e.target.checked, + ]) + } + > + 모두 동의합니다. + + + + setCheckedItems([ + e.target.checked, + checkedItems[1], + checkedItems[2], + ]) + } + > + (필수) 서비스 이용 약관 동의 + + + setCheckedItems([ + checkedItems[0], + e.target.checked, + checkedItems[2], + ]) + } + > + (필수) 개인 정보 수집 및 이용 동의 + + + setCheckedItems([ + checkedItems[0], + checkedItems[1], + e.target.checked, + ]) + } + > + (필수) 만 14세 이상입니다 + + + { - + {funnel === "userInfo" && ( )} From d38061adb45509e21eabc29f01e8a7cf021a71fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=ED=98=84=EC=9A=B0?= Date: Mon, 11 Dec 2023 21:56:08 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat(form)=20:=20form=20layout=20=EA=B5=AC?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs:[#4,#5] --- component/Funnel/LoginFunnel.tsx | 8 +- component/Funnel/MainFunnel.tsx | 5 +- component/button/MainButton.tsx | 3 +- component/form/UserAgreementForm.tsx | 11 +-- component/form/UserInfoForm.tsx | 126 +++++++++++++-------------- component/form/UserPhysicForm.tsx | 43 ++++++--- src/app/page.tsx | 5 +- src/app/signup/page.tsx | 16 ++-- 8 files changed, 121 insertions(+), 96 deletions(-) diff --git a/component/Funnel/LoginFunnel.tsx b/component/Funnel/LoginFunnel.tsx index cfa4d77..e23a926 100644 --- a/component/Funnel/LoginFunnel.tsx +++ b/component/Funnel/LoginFunnel.tsx @@ -16,13 +16,13 @@ const LoginFunnel = () => { /> {}}> diff --git a/component/Funnel/MainFunnel.tsx b/component/Funnel/MainFunnel.tsx index d1b92eb..cd97bc5 100644 --- a/component/Funnel/MainFunnel.tsx +++ b/component/Funnel/MainFunnel.tsx @@ -10,8 +10,6 @@ interface MainFunnelPropsType { } const MainFunnel = ({ setFunnel }: MainFunnelPropsType) => { - const router = useRouter(); - return ( <> { { +const MainButton = ({ children, w, h, onClick, alignSelf }: ButtonProps) => { return ( diff --git a/component/form/UserAgreementForm.tsx b/component/form/UserAgreementForm.tsx index cd3ddeb..f83c8ea 100644 --- a/component/form/UserAgreementForm.tsx +++ b/component/form/UserAgreementForm.tsx @@ -19,8 +19,8 @@ const UserAgreementForm = ({ setFunnel }: UserAgreementFormPropsType) => { const isIndeterminate = checkedItems.some(Boolean) && !allChecked; return ( - - + <> + { 동의하고 시작하기 - + ); }; diff --git a/component/form/UserInfoForm.tsx b/component/form/UserInfoForm.tsx index d2c50df..74dd30b 100644 --- a/component/form/UserInfoForm.tsx +++ b/component/form/UserInfoForm.tsx @@ -1,7 +1,7 @@ "use client"; -import { useForm } from "react-hook-form"; import { Box, + Button, ButtonGroup, Flex, FormControl, @@ -12,7 +12,6 @@ import { useRadio, useRadioGroup, } from "@chakra-ui/react"; -import { useParams } from "next/navigation"; import MainInput from "../input/MainInput"; import MainButton from "../button/MainButton"; @@ -28,11 +27,11 @@ function RadioCard(props: any) { { return ( <> - - - - 반가워요! - - - 기본정보를 입력해주세요 - - - - - - 이름 - - - - - - 성별 - - - {options.map((value) => { - const radio = getRadioProps({ value }); - return ( - - {value} - - ); - })} - - - - + - { - setFunnel("userPhysics"); - setProgress((oldState) => oldState + 33.3); - }} - > - 다음으로 - - - + 기본정보를 입력해주세요 + + + 성별에 맞는 대사량기준으로 알려드려요 + + + + + + 이름 + + + + + + 성별 + + + {options.map((value) => { + const radio = getRadioProps({ value }); + return ( + + {value} + + ); + })} + + + + + { + setFunnel("userPhysics"); + setProgress((oldState) => oldState + 33.3); + }} + > + 다음으로 + + ); }; diff --git a/component/form/UserPhysicForm.tsx b/component/form/UserPhysicForm.tsx index cd3a6e5..8ea3514 100644 --- a/component/form/UserPhysicForm.tsx +++ b/component/form/UserPhysicForm.tsx @@ -3,7 +3,6 @@ import MainButton from "../button/MainButton"; import { Box, ButtonGroup, - Flex, FormControl, FormLabel, HStack, @@ -25,11 +24,8 @@ const UserPhysicForm = ({ setProgress, }: UserPhysicsFormPropsType) => { return ( - - - - 거의 다 왔어요! - + <> + 신체정보를 입력해주세요 + + 개인 맞춤으로 알려드려요 + - - + + 나이 @@ -55,7 +60,7 @@ const UserPhysicForm = ({ - + @@ -66,7 +71,7 @@ const UserPhysicForm = ({ - + 체중 @@ -77,12 +82,24 @@ const UserPhysicForm = ({ + + + 목표 체중 + + + + + kg + + + - + ); }; diff --git a/src/app/page.tsx b/src/app/page.tsx index dcd5c3a..d45a21c 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -10,8 +10,11 @@ export default function Home() { { isAnimated={true} value={progress} /> - {funnel === "userInfo" && ( @@ -34,7 +38,7 @@ const Page = () => { {funnel === "userAgreement" && ( )} - + ); }; From f9ff02ab9bafe0290928882e8a771610e8841ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=ED=98=84=EC=9A=B0?= Date: Mon, 11 Dec 2023 22:02:57 +0900 Subject: [PATCH 4/5] =?UTF-8?q?feat(button)=20:=20=EC=95=BD=EA=B4=80?= =?UTF-8?q?=EB=8F=99=EC=9D=98=20=EB=B2=84=ED=8A=BC=20=EC=B2=B4=ED=81=AC?= =?UTF-8?q?=EC=8B=9C=20=EB=B2=84=ED=8A=BC=20=ED=99=9C=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs:[#4,#5] --- component/button/MainButton.tsx | 10 +++++++++- component/form/UserAgreementForm.tsx | 7 ++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/component/button/MainButton.tsx b/component/button/MainButton.tsx index 5a550ae..42d8aee 100644 --- a/component/button/MainButton.tsx +++ b/component/button/MainButton.tsx @@ -1,7 +1,14 @@ import { Button, ButtonProps } from "@chakra-ui/react"; import React from "react"; -const MainButton = ({ children, w, h, onClick, alignSelf }: ButtonProps) => { +const MainButton = ({ + children, + w, + h, + onClick, + alignSelf, + isDisabled, +}: ButtonProps) => { return ( diff --git a/component/form/UserAgreementForm.tsx b/component/form/UserAgreementForm.tsx index f83c8ea..e53b4a0 100644 --- a/component/form/UserAgreementForm.tsx +++ b/component/form/UserAgreementForm.tsx @@ -18,6 +18,7 @@ const UserAgreementForm = ({ setFunnel }: UserAgreementFormPropsType) => { const allChecked = checkedItems.every(Boolean); const isIndeterminate = checkedItems.some(Boolean) && !allChecked; + console.log(); return ( <> @@ -111,7 +112,11 @@ const UserAgreementForm = ({ setFunnel }: UserAgreementFormPropsType) => { margin={"0 auto"} justifyContent={"center"} > - + ele).length !== 3} + > 동의하고 시작하기 From a6988f0c560362a8db31dc329936905c84cd5fc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=ED=98=84=EC=9A=B0?= Date: Mon, 11 Dec 2023 22:56:39 +0900 Subject: [PATCH 5/5] =?UTF-8?q?feat(form)=20:=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20form=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20?= =?UTF-8?q?=EA=B2=80=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs:[#4,#5] --- component/button/MainButton.tsx | 2 + component/form/UserInfoForm.tsx | 60 +++++++++++++++---------- component/form/UserPhysicForm.tsx | 73 +++++++++++++++++++++---------- component/input/MainInput.tsx | 8 +++- src/app/signup/page.tsx | 3 +- 5 files changed, 99 insertions(+), 47 deletions(-) diff --git a/component/button/MainButton.tsx b/component/button/MainButton.tsx index 42d8aee..cae3513 100644 --- a/component/button/MainButton.tsx +++ b/component/button/MainButton.tsx @@ -8,6 +8,7 @@ const MainButton = ({ onClick, alignSelf, isDisabled, + type, }: ButtonProps) => { return ( diff --git a/component/form/UserInfoForm.tsx b/component/form/UserInfoForm.tsx index 74dd30b..590fcc8 100644 --- a/component/form/UserInfoForm.tsx +++ b/component/form/UserInfoForm.tsx @@ -1,9 +1,7 @@ "use client"; import { Box, - Button, ButtonGroup, - Flex, FormControl, FormLabel, HStack, @@ -14,6 +12,7 @@ import { } from "@chakra-ui/react"; import MainInput from "../input/MainInput"; import MainButton from "../button/MainButton"; +import { SubmitHandler, useForm } from "react-hook-form"; function RadioCard(props: any) { const { getInputProps, getRadioProps } = useRadio(props); @@ -54,11 +53,22 @@ interface UserInfoFormPropsType { const UserInfoForm = ({ setFunnel, setProgress }: UserInfoFormPropsType) => { const options = ["남성", "여성"]; - const { getRootProps, getRadioProps } = useRadioGroup({ + const { getRootProps, getRadioProps, value } = useRadioGroup({ name: "gender", - onChange: console.log, }); + interface SignUpFormType { + userName: string; + } + + const { handleSubmit, register } = useForm(); + + const onSubmit: SubmitHandler = (data) => { + console.log(data, value); + setFunnel("userPhysics"); + setProgress((oldState) => oldState + 33.3); + }; + const group = getRootProps(); return ( @@ -78,6 +88,7 @@ const UserInfoForm = ({ setFunnel, setProgress }: UserInfoFormPropsType) => { { 이름 - + @@ -104,25 +120,23 @@ const UserInfoForm = ({ setFunnel, setProgress }: UserInfoFormPropsType) => { })} - - - { - setFunnel("userPhysics"); - setProgress((oldState) => oldState + 33.3); - }} + - 다음으로 - - + + 다음으로 + + + ); }; diff --git a/component/form/UserPhysicForm.tsx b/component/form/UserPhysicForm.tsx index 8ea3514..2182c3c 100644 --- a/component/form/UserPhysicForm.tsx +++ b/component/form/UserPhysicForm.tsx @@ -13,6 +13,7 @@ import { InputRightElement, Text, } from "@chakra-ui/react"; +import { SubmitHandler, useForm } from "react-hook-form"; interface UserPhysicsFormPropsType { setFunnel: React.Dispatch>; @@ -23,6 +24,20 @@ const UserPhysicForm = ({ setFunnel, setProgress, }: UserPhysicsFormPropsType) => { + interface PhysicsFormType { + age: number; + height: number; + weight: number; + targetWeight: number; + } + + const { handleSubmit, register } = useForm(); + + const onSubmit: SubmitHandler = (data) => { + console.log(data); + setFunnel("userAgreement"); + setProgress((oldState) => oldState + 33.3); + }; return ( <> @@ -40,6 +55,7 @@ const UserPhysicForm = ({ 만 - + @@ -65,7 +86,12 @@ const UserPhysicForm = ({ 키 - + cm @@ -76,7 +102,12 @@ const UserPhysicForm = ({ 체중 - + kg @@ -87,31 +118,29 @@ const UserPhysicForm = ({ 목표 체중 - + kg - - - { - setFunnel("userAgreement"); - setProgress((oldState) => oldState + 33.3); - }} + - 다음으로 - - + + 다음으로 + + + ); }; diff --git a/component/input/MainInput.tsx b/component/input/MainInput.tsx index 3ebd0db..c5cc238 100644 --- a/component/input/MainInput.tsx +++ b/component/input/MainInput.tsx @@ -1,7 +1,12 @@ import { Input, InputProps, border } from "@chakra-ui/react"; import React from "react"; +import { UseFormRegisterReturn } from "react-hook-form"; -const MainInput = ({ h, w, placeholder }: InputProps) => { +interface MainInputPropsType extends InputProps { + register: UseFormRegisterReturn; +} + +const MainInput = ({ h, w, placeholder, register }: MainInputPropsType) => { return ( { borderRadius={"12px"} placeholder={placeholder} focusBorderColor={"black"} + {...register} /> ); }; diff --git a/src/app/signup/page.tsx b/src/app/signup/page.tsx index b3d0e10..e5cacab 100644 --- a/src/app/signup/page.tsx +++ b/src/app/signup/page.tsx @@ -5,10 +5,12 @@ import { Flex, Progress } from "@chakra-ui/react"; import { useFunnel } from "../../../utils/hooks/useFunnel"; import UserPhysicForm from "../../../component/form/UserPhysicForm"; import UserAgreementForm from "../../../component/form/UserAgreementForm"; +import { SubmitHandler, useForm } from "react-hook-form"; const Page = () => { const [progress, setProgress] = useState(33.3); const { funnel, setFunnel } = useFunnel("userInfo"); + return ( <> { value={progress} />