From 8318877113ef5f6a5745780edbac081e11cefee8 Mon Sep 17 00:00:00 2001 From: jaychang99 Date: Sun, 10 Sep 2023 19:37:38 +0900 Subject: [PATCH 01/19] =?UTF-8?q?fix:=20=EB=A9=94=EC=9D=B8=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EC=97=90=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=9A=A9=20AreaInput=20=EB=93=A4=EC=96=B4=EA=B0=84=20=EA=B2=83?= =?UTF-8?q?=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/index.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/index.tsx b/src/pages/index.tsx index b4e565c..d7da84e 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,6 +1,5 @@ import Head from "next/head"; import PageMarker from "components/pageMarker/PageMarker"; -import AreaInput from "components/inputs/AreaInput/AreaInput"; function Home() { return ( @@ -15,7 +14,6 @@ function Home() { title="푸드허브 메인 페이지" description="최근 추가된 맛집, 평점이 높은 맛집, 데일리 맛잘알 BEST 단체" /> - ); } From b1638809fd0e4306745d3ebc97991abaeea6baf7 Mon Sep 17 00:00:00 2001 From: jaychang99 Date: Sun, 10 Sep 2023 19:53:47 +0900 Subject: [PATCH 02/19] =?UTF-8?q?feat(Organization):=20=EB=A7=9B=EC=A7=91?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B8=B0=EB=B3=B8=20=EA=B3=A8?= =?UTF-8?q?=EA=B2=A9=20=EC=85=8B=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../restaurants/components/RestaurantForm.tsx | 13 +++++++++++++ .../restaurants.create/ViewRestaurantCreate.tsx | 14 ++++++++++++++ .../restaurants.edit/ViewRestaurantEdit.tsx | 14 ++++++++++++++ src/pages/restaurants/[restaurantId]/edit.tsx | 7 +++++++ .../index.tsx} | 0 src/pages/restaurants/create.tsx | 7 +++++++ 6 files changed, 55 insertions(+) create mode 100644 src/feature/restaurants/components/RestaurantForm.tsx create mode 100644 src/feature/restaurants/restaurants.create/ViewRestaurantCreate.tsx create mode 100644 src/feature/restaurants/restaurants.edit/ViewRestaurantEdit.tsx create mode 100644 src/pages/restaurants/[restaurantId]/edit.tsx rename src/pages/restaurants/{[restaurantId].tsx => [restaurantId]/index.tsx} (100%) create mode 100644 src/pages/restaurants/create.tsx diff --git a/src/feature/restaurants/components/RestaurantForm.tsx b/src/feature/restaurants/components/RestaurantForm.tsx new file mode 100644 index 0000000..4f971c2 --- /dev/null +++ b/src/feature/restaurants/components/RestaurantForm.tsx @@ -0,0 +1,13 @@ +import styled from "@emotion/styled"; + +interface Props { + isEditMode?: boolean; +} + +const RestaurantForm = ({ isEditMode = false }: Props) => { + return RestaurantForm; +}; + +export default RestaurantForm; + +const EmotionWrapper = styled.div``; diff --git a/src/feature/restaurants/restaurants.create/ViewRestaurantCreate.tsx b/src/feature/restaurants/restaurants.create/ViewRestaurantCreate.tsx new file mode 100644 index 0000000..92af3ba --- /dev/null +++ b/src/feature/restaurants/restaurants.create/ViewRestaurantCreate.tsx @@ -0,0 +1,14 @@ +import styled from "@emotion/styled"; +import RestaurantForm from "feature/restaurants/components/RestaurantForm"; + +const ViewRestaurantCreate = () => { + return ( + + + + ); +}; + +export default ViewRestaurantCreate; + +const EmotionWrapper = styled.div``; diff --git a/src/feature/restaurants/restaurants.edit/ViewRestaurantEdit.tsx b/src/feature/restaurants/restaurants.edit/ViewRestaurantEdit.tsx new file mode 100644 index 0000000..ee80978 --- /dev/null +++ b/src/feature/restaurants/restaurants.edit/ViewRestaurantEdit.tsx @@ -0,0 +1,14 @@ +import styled from "@emotion/styled"; +import RestaurantForm from "feature/restaurants/components/RestaurantForm"; + +const ViewRestaurantEdit = () => { + return ( + + + + ); +}; + +export default ViewRestaurantEdit; + +const EmotionWrapper = styled.div``; diff --git a/src/pages/restaurants/[restaurantId]/edit.tsx b/src/pages/restaurants/[restaurantId]/edit.tsx new file mode 100644 index 0000000..e6267c4 --- /dev/null +++ b/src/pages/restaurants/[restaurantId]/edit.tsx @@ -0,0 +1,7 @@ +import ViewRestaurantEdit from "feature/restaurants/restaurants.edit/ViewRestaurantEdit"; + +const PageRestaurantEdit = () => { + return ; +}; + +export default PageRestaurantEdit; diff --git a/src/pages/restaurants/[restaurantId].tsx b/src/pages/restaurants/[restaurantId]/index.tsx similarity index 100% rename from src/pages/restaurants/[restaurantId].tsx rename to src/pages/restaurants/[restaurantId]/index.tsx diff --git a/src/pages/restaurants/create.tsx b/src/pages/restaurants/create.tsx new file mode 100644 index 0000000..8e6889f --- /dev/null +++ b/src/pages/restaurants/create.tsx @@ -0,0 +1,7 @@ +import ViewRestaurantCreate from "feature/restaurants/restaurants.create/ViewRestaurantCreate"; + +const PageRestaurantCreate = () => { + return ; +}; + +export default PageRestaurantCreate; From 0bb2678285ba631c9288ae35b2b8ac2ba6bfe894 Mon Sep 17 00:00:00 2001 From: jaychang99 Date: Sun, 10 Sep 2023 20:30:49 +0900 Subject: [PATCH 03/19] =?UTF-8?q?feat(Restaurant):=20=EB=A7=9B=EC=A7=91=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20=ED=8F=BC=20=EA=B3=A8=EA=B2=A9=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../restaurants/components/RestaurantForm.tsx | 40 ++++++++++++++++++- .../formItems/FormItemRestaurantAddress.tsx | 9 +++++ .../formItems/FormItemRestaurantCapacity.tsx | 9 +++++ .../FormItemRestaurantCategoryId.tsx | 9 +++++ .../formItems/FormItemRestaurantComment.tsx | 9 +++++ .../formItems/FormItemRestaurantDelivery.tsx | 9 +++++ .../formItems/FormItemRestaurantImages.tsx | 9 +++++ .../formItems/FormItemRestaurantLink.tsx | 9 +++++ .../formItems/FormItemRestaurantName.tsx | 9 +++++ .../FormItemRestaurantOpeningHour.tsx | 9 +++++ .../formItems/FormItemRestaurantOrderTip.tsx | 9 +++++ .../FormItemRestaurantRecommendedMenu.tsx | 9 +++++ .../components/formItems/FormItemTagIds.tsx | 9 +++++ .../components/formItems/FormTitle.tsx | 18 +++++++++ 14 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 src/feature/restaurants/components/formItems/FormItemRestaurantAddress.tsx create mode 100644 src/feature/restaurants/components/formItems/FormItemRestaurantCapacity.tsx create mode 100644 src/feature/restaurants/components/formItems/FormItemRestaurantCategoryId.tsx create mode 100644 src/feature/restaurants/components/formItems/FormItemRestaurantComment.tsx create mode 100644 src/feature/restaurants/components/formItems/FormItemRestaurantDelivery.tsx create mode 100644 src/feature/restaurants/components/formItems/FormItemRestaurantImages.tsx create mode 100644 src/feature/restaurants/components/formItems/FormItemRestaurantLink.tsx create mode 100644 src/feature/restaurants/components/formItems/FormItemRestaurantName.tsx create mode 100644 src/feature/restaurants/components/formItems/FormItemRestaurantOpeningHour.tsx create mode 100644 src/feature/restaurants/components/formItems/FormItemRestaurantOrderTip.tsx create mode 100644 src/feature/restaurants/components/formItems/FormItemRestaurantRecommendedMenu.tsx create mode 100644 src/feature/restaurants/components/formItems/FormItemTagIds.tsx create mode 100644 src/feature/restaurants/components/formItems/FormTitle.tsx diff --git a/src/feature/restaurants/components/RestaurantForm.tsx b/src/feature/restaurants/components/RestaurantForm.tsx index 4f971c2..82868fd 100644 --- a/src/feature/restaurants/components/RestaurantForm.tsx +++ b/src/feature/restaurants/components/RestaurantForm.tsx @@ -1,13 +1,49 @@ import styled from "@emotion/styled"; +import Button from "components/button/Button"; +import FormItemRestaurantAddress from "feature/restaurants/components/formItems/FormItemRestaurantAddress"; +import FormItemRestaurantCapacity from "feature/restaurants/components/formItems/FormItemRestaurantCapacity"; +import FormItemRestaurantCategoryId from "feature/restaurants/components/formItems/FormItemRestaurantCategoryId"; +import FormItemRestaurantComment from "feature/restaurants/components/formItems/FormItemRestaurantComment"; +import FormItemRestaurantDelivery from "feature/restaurants/components/formItems/FormItemRestaurantDelivery"; +import FormItemRestaurantImages from "feature/restaurants/components/formItems/FormItemRestaurantImages"; +import FormItemRestaurantLink from "feature/restaurants/components/formItems/FormItemRestaurantLink"; +import FormItemRestaurantName from "feature/restaurants/components/formItems/FormItemRestaurantName"; +import FormItemRestaurantOpeningHour from "feature/restaurants/components/formItems/FormItemRestaurantOpeningHour"; +import FormItemRestaurantOrderTip from "feature/restaurants/components/formItems/FormItemRestaurantOrderTip"; +import FormItemRestaurantRecommendedMenu from "feature/restaurants/components/formItems/FormItemRestaurantRecommendedMenu"; +import FormItemTagIds from "feature/restaurants/components/formItems/FormItemTagIds"; +import FormTitle from "feature/restaurants/components/formItems/FormTitle"; interface Props { isEditMode?: boolean; } const RestaurantForm = ({ isEditMode = false }: Props) => { - return RestaurantForm; + return ( + + + + + + + + + + + + + + + + + ); }; export default RestaurantForm; -const EmotionWrapper = styled.div``; +const EmotionWrapper = styled.div` + button { + margin-top: 24px; + float: right; + } +`; diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantAddress.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantAddress.tsx new file mode 100644 index 0000000..330b361 --- /dev/null +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantAddress.tsx @@ -0,0 +1,9 @@ +import styled from "@emotion/styled"; + +const FormItemRestaurantAddress = () => { + return FormItemRestaurantAddress; +}; + +export default FormItemRestaurantAddress; + +const EmotionWrapper = styled.div``; diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantCapacity.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantCapacity.tsx new file mode 100644 index 0000000..1ec58a0 --- /dev/null +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantCapacity.tsx @@ -0,0 +1,9 @@ +import styled from "@emotion/styled"; + +const FormItemRestaurantCapacity = () => { + return FormItemRestaurantCapacity; +}; + +export default FormItemRestaurantCapacity; + +const EmotionWrapper = styled.div``; diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantCategoryId.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantCategoryId.tsx new file mode 100644 index 0000000..f2f48c1 --- /dev/null +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantCategoryId.tsx @@ -0,0 +1,9 @@ +import styled from "@emotion/styled"; + +const FormItemRestaurantCategoryId = () => { + return FormItemRestaurantCategoryId; +}; + +export default FormItemRestaurantCategoryId; + +const EmotionWrapper = styled.div``; diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantComment.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantComment.tsx new file mode 100644 index 0000000..7623765 --- /dev/null +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantComment.tsx @@ -0,0 +1,9 @@ +import styled from "@emotion/styled"; + +const FormItemRestaurantComment = () => { + return FormItemRestaurantComment; +}; + +export default FormItemRestaurantComment; + +const EmotionWrapper = styled.div``; diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantDelivery.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantDelivery.tsx new file mode 100644 index 0000000..28736fc --- /dev/null +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantDelivery.tsx @@ -0,0 +1,9 @@ +import styled from "@emotion/styled"; + +const FormItemRestaurantDelivery = () => { + return FormItemRestaurantDelivery; +}; + +export default FormItemRestaurantDelivery; + +const EmotionWrapper = styled.div``; diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantImages.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantImages.tsx new file mode 100644 index 0000000..1ac17cf --- /dev/null +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantImages.tsx @@ -0,0 +1,9 @@ +import styled from "@emotion/styled"; + +const FormItemRestaurantImages = () => { + return FormItemRestaurantImages; +}; + +export default FormItemRestaurantImages; + +const EmotionWrapper = styled.div``; diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantLink.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantLink.tsx new file mode 100644 index 0000000..cfb02cb --- /dev/null +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantLink.tsx @@ -0,0 +1,9 @@ +import styled from "@emotion/styled"; + +const FormItemRestaurantLink = () => { + return FormItemRestaurantLink; +}; + +export default FormItemRestaurantLink; + +const EmotionWrapper = styled.div``; diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantName.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantName.tsx new file mode 100644 index 0000000..b399f6b --- /dev/null +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantName.tsx @@ -0,0 +1,9 @@ +import styled from "@emotion/styled"; + +const FormItemRestaurantName = () => { + return FormItemRestaurantName; +}; + +export default FormItemRestaurantName; + +const EmotionWrapper = styled.div``; diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantOpeningHour.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantOpeningHour.tsx new file mode 100644 index 0000000..7f6c3ca --- /dev/null +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantOpeningHour.tsx @@ -0,0 +1,9 @@ +import styled from "@emotion/styled"; + +const FormItemRestaurantOpeningHour = () => { + return FormItemRestaurantOpeningHour; +}; + +export default FormItemRestaurantOpeningHour; + +const EmotionWrapper = styled.div``; diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantOrderTip.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantOrderTip.tsx new file mode 100644 index 0000000..6d14a63 --- /dev/null +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantOrderTip.tsx @@ -0,0 +1,9 @@ +import styled from "@emotion/styled"; + +const FormItemRestaurantOrderTip = () => { + return FormItemRestaurantOrderTip; +}; + +export default FormItemRestaurantOrderTip; + +const EmotionWrapper = styled.div``; diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantRecommendedMenu.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantRecommendedMenu.tsx new file mode 100644 index 0000000..33ebe72 --- /dev/null +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantRecommendedMenu.tsx @@ -0,0 +1,9 @@ +import styled from "@emotion/styled"; + +const FormItemRestaurantRecommendedMenu = () => { + return FormItemRestaurantRecommendedMenu; +}; + +export default FormItemRestaurantRecommendedMenu; + +const EmotionWrapper = styled.div``; diff --git a/src/feature/restaurants/components/formItems/FormItemTagIds.tsx b/src/feature/restaurants/components/formItems/FormItemTagIds.tsx new file mode 100644 index 0000000..99cc812 --- /dev/null +++ b/src/feature/restaurants/components/formItems/FormItemTagIds.tsx @@ -0,0 +1,9 @@ +import styled from "@emotion/styled"; + +const FormItemTagIds = () => { + return FormItemTagIds; +}; + +export default FormItemTagIds; + +const EmotionWrapper = styled.div``; diff --git a/src/feature/restaurants/components/formItems/FormTitle.tsx b/src/feature/restaurants/components/formItems/FormTitle.tsx new file mode 100644 index 0000000..e54626a --- /dev/null +++ b/src/feature/restaurants/components/formItems/FormTitle.tsx @@ -0,0 +1,18 @@ +import styled from "@emotion/styled"; + +interface Props { + isEditMode?: boolean; +} + +const FormTitle: React.FC = ({ isEditMode = false }) => { + return {isEditMode ? "맛집 수정" : "맛집 등록"}; +}; + +export default FormTitle; + +const EmotionWrapper = styled.h1` + font-size: 24px; + font-weight: 700; + margin-bottom: 36px; + line-height: 1.5; +`; From 49aee6dd2a28a5bc707241751f5b42b7f7ed8be1 Mon Sep 17 00:00:00 2001 From: jaychang99 Date: Sun, 10 Sep 2023 21:19:32 +0900 Subject: [PATCH 04/19] =?UTF-8?q?feat(Restaurant):=20=EB=A7=9B=EC=A7=91=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=20?= =?UTF-8?q?=EB=A7=9B=EC=A7=91=20=EC=9D=B4=EB=A6=84=20=EB=84=A3=EB=8A=94=20?= =?UTF-8?q?=EC=9D=B8=ED=92=8B=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constant/limit.ts | 9 +++++ .../restaurants/components/RestaurantForm.tsx | 15 +++++++- .../formItems/FormItemRestaurantName.tsx | 35 +++++++++++++++++-- .../constants/RestaurantFormInitialValues.ts | 20 +++++++++++ .../functions/validateRestaurantForm.ts | 19 ++++++++++ src/feature/restaurants/types/TFormValue.ts | 4 +++ .../types/TRestaurantFormCommonProps.ts | 7 ++++ .../types/TRestaurantFormValues.ts | 20 +++++++++++ 8 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 src/constant/limit.ts create mode 100644 src/feature/restaurants/constants/RestaurantFormInitialValues.ts create mode 100644 src/feature/restaurants/functions/validateRestaurantForm.ts create mode 100644 src/feature/restaurants/types/TFormValue.ts create mode 100644 src/feature/restaurants/types/TRestaurantFormCommonProps.ts create mode 100644 src/feature/restaurants/types/TRestaurantFormValues.ts diff --git a/src/constant/limit.ts b/src/constant/limit.ts new file mode 100644 index 0000000..9c41bbb --- /dev/null +++ b/src/constant/limit.ts @@ -0,0 +1,9 @@ +// 맛집 생성 관련 제약 +export const RESTAURANT_NAME_MAX_LENGTH = 10; // 맛집 이름 최대 길이 +export const RESTAURANT_COMMENT_MAX_LENGTH = 30; // 맛집 한줄평 최대 길이 +export const RESTAURANT_CAPACITY_MAX = 9999; // 맛집 수용인원 최대 수 +export const RESTAURANT_OPENING_HOUR_MAX = 30; // 맛집 운영 시간 최대 길이 +export const RESTAURANT_RECOMMENDED_MENU_MAX_COUNT = 10; // 맛집 추천 메뉴 최대 개수 +export const RESTAURANT_ORDER_TIP_MAX_LENGTH = 30; // 맛집 주문 팁 최대 길이 +export const RESTAURANT_LINK_MAX_LENGTH = 200; // 맛집 링크 최대 길이 +export const RESTAURANT_IMAGES_MAX_COUNT = 10; // 맛집 이미지 최대 개수 diff --git a/src/feature/restaurants/components/RestaurantForm.tsx b/src/feature/restaurants/components/RestaurantForm.tsx index 82868fd..16e8932 100644 --- a/src/feature/restaurants/components/RestaurantForm.tsx +++ b/src/feature/restaurants/components/RestaurantForm.tsx @@ -13,16 +13,29 @@ import FormItemRestaurantOrderTip from "feature/restaurants/components/formItems import FormItemRestaurantRecommendedMenu from "feature/restaurants/components/formItems/FormItemRestaurantRecommendedMenu"; import FormItemTagIds from "feature/restaurants/components/formItems/FormItemTagIds"; import FormTitle from "feature/restaurants/components/formItems/FormTitle"; +import { RESTAURANT_FORM_INITIAL_VALUES } from "feature/restaurants/constants/RestaurantFormInitialValues"; +import { TRestaurantFormValues } from "feature/restaurants/types/TRestaurantFormValues"; +import { useState } from "react"; interface Props { isEditMode?: boolean; } const RestaurantForm = ({ isEditMode = false }: Props) => { + const [formValues, setFormValues] = useState( + RESTAURANT_FORM_INITIAL_VALUES + ); + + const commonProps = { + isEditMode, + formValues, + setFormValues, + }; + return ( - + diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantName.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantName.tsx index b399f6b..c21dc6a 100644 --- a/src/feature/restaurants/components/formItems/FormItemRestaurantName.tsx +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantName.tsx @@ -1,7 +1,38 @@ +import { useCallback } from "react"; import styled from "@emotion/styled"; +import TextInput from "components/inputs/TextInput/TextInput"; +import { + validateRestaurantNameEmpty, + validateRestaurantNameLength, +} from "feature/restaurants/functions/validateRestaurantForm"; +import { TRestaurantFormCommonProps } from "feature/restaurants/types/TRestaurantFormCommonProps"; -const FormItemRestaurantName = () => { - return FormItemRestaurantName; +interface Props extends TRestaurantFormCommonProps {} + +const FormItemRestaurantName: React.FC = ({ formValues, setFormValues }) => { + const handleChangeName = useCallback( + (value: string, isValid: boolean) => { + setFormValues((prev) => ({ + ...prev, + name: { + value, + isValid, + }, + })); + }, + [setFormValues] + ); + + return ( + + + + ); }; export default FormItemRestaurantName; diff --git a/src/feature/restaurants/constants/RestaurantFormInitialValues.ts b/src/feature/restaurants/constants/RestaurantFormInitialValues.ts new file mode 100644 index 0000000..969e401 --- /dev/null +++ b/src/feature/restaurants/constants/RestaurantFormInitialValues.ts @@ -0,0 +1,20 @@ +import { TRestaurantFormValues } from "feature/restaurants/types/TRestaurantFormValues"; + +export const RESTAURANT_FORM_INITIAL_VALUES: TRestaurantFormValues = { + userId: 0, + name: { + value: "", + isValid: false, + }, + categoryId: 0, + tagIds: [0], + address: "", + link: "", + delivery: false, + comment: "", + capacity: 0, + openingHour: "", + recommendedMenu: "", + orderTip: "", + // 이미지는 따로 처리 +}; diff --git a/src/feature/restaurants/functions/validateRestaurantForm.ts b/src/feature/restaurants/functions/validateRestaurantForm.ts new file mode 100644 index 0000000..37e636e --- /dev/null +++ b/src/feature/restaurants/functions/validateRestaurantForm.ts @@ -0,0 +1,19 @@ +import { RESTAURANT_NAME_MAX_LENGTH } from "constant/limit"; + +// 맛집 이름 유효성 검사 조건을 정의합니다. +export const validateRestaurantNameLength = { + condition: (value: string): boolean => { + if (value?.length > RESTAURANT_NAME_MAX_LENGTH) return false; + return true; + }, + messageOnError: `맛집 이름은 ${RESTAURANT_NAME_MAX_LENGTH}자 이내로 입력해주세요.`, +}; + +export const validateRestaurantNameEmpty = { + condition: (value: string): boolean => { + if (!value) return false; + if (value?.length === 0) return false; + return true; + }, + messageOnError: "맛집 이름을 입력해주세요.", +}; diff --git a/src/feature/restaurants/types/TFormValue.ts b/src/feature/restaurants/types/TFormValue.ts new file mode 100644 index 0000000..709f311 --- /dev/null +++ b/src/feature/restaurants/types/TFormValue.ts @@ -0,0 +1,4 @@ +export type TFormValue = { + value: T; + isValid: boolean; +}; diff --git a/src/feature/restaurants/types/TRestaurantFormCommonProps.ts b/src/feature/restaurants/types/TRestaurantFormCommonProps.ts new file mode 100644 index 0000000..45e83f0 --- /dev/null +++ b/src/feature/restaurants/types/TRestaurantFormCommonProps.ts @@ -0,0 +1,7 @@ +import { TRestaurantFormValues } from "feature/restaurants/types/TRestaurantFormValues"; + +export interface TRestaurantFormCommonProps { + isEditMode?: boolean; + formValues: TRestaurantFormValues; + setFormValues: React.Dispatch>; +} diff --git a/src/feature/restaurants/types/TRestaurantFormValues.ts b/src/feature/restaurants/types/TRestaurantFormValues.ts new file mode 100644 index 0000000..ed0df97 --- /dev/null +++ b/src/feature/restaurants/types/TRestaurantFormValues.ts @@ -0,0 +1,20 @@ +import { TFormValue } from "feature/restaurants/types/TFormValue"; + +export type TRestaurantFormValues = { + userId: number; // 맛집 생성자의 id + name: TFormValue; // 맛집 이름 + categoryId: number; // 맛집 카테고리 id + tagIds: number[]; // 맛집 태그 id 배열 + address?: string; // 맛집 주소 + link?: string; // 맛집 링크 + delivery?: boolean; // 맛집 배달 여부 + comment?: string; // 맛집 한줄평 + capacity?: number; // 맛집 수용인원 + openingHour?: string; // 맛집 운영 시간 + recommendedMenu?: string; // 맛집 추천 메뉴 + orderTip?: string; // 맛집 주문 팁 + // 맛집 이미지 파일들의 uuid 배열 + files?: { + uuid: string; + }[]; +}; From c7322b55f7a1acf9fd0d7f825383403d4facfd89 Mon Sep 17 00:00:00 2001 From: jaychang99 Date: Sun, 10 Sep 2023 21:42:51 +0900 Subject: [PATCH 05/19] =?UTF-8?q?feat(Restaurant):=20=EB=A7=9B=EC=A7=91=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=20?= =?UTF-8?q?=EB=A7=9B=EC=A7=91=20=ED=95=9C=EC=A4=84=ED=8F=89=20=EB=84=A3?= =?UTF-8?q?=EB=8A=94=20=EC=9D=B8=ED=92=8B=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../restaurants/components/RestaurantForm.tsx | 6 +++- .../formItems/FormItemRestaurantComment.tsx | 31 +++++++++++++++++-- .../components/formItems/FormTitle.tsx | 1 - .../constants/RestaurantFormInitialValues.ts | 5 ++- .../functions/validateRestaurantForm.ts | 11 ++++++- .../types/TRestaurantFormValues.ts | 2 +- 6 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/feature/restaurants/components/RestaurantForm.tsx b/src/feature/restaurants/components/RestaurantForm.tsx index 16e8932..c1d1cab 100644 --- a/src/feature/restaurants/components/RestaurantForm.tsx +++ b/src/feature/restaurants/components/RestaurantForm.tsx @@ -36,7 +36,7 @@ const RestaurantForm = ({ isEditMode = false }: Props) => { - + @@ -55,6 +55,10 @@ const RestaurantForm = ({ isEditMode = false }: Props) => { export default RestaurantForm; const EmotionWrapper = styled.div` + display: flex; + flex-direction: column; + row-gap: 36px; + button { margin-top: 24px; float: right; diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantComment.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantComment.tsx index 7623765..9fdfca4 100644 --- a/src/feature/restaurants/components/formItems/FormItemRestaurantComment.tsx +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantComment.tsx @@ -1,7 +1,34 @@ import styled from "@emotion/styled"; +import TextInput from "components/inputs/TextInput/TextInput"; +import { validateRestaurantCommentLength } from "feature/restaurants/functions/validateRestaurantForm"; +import { TRestaurantFormCommonProps } from "feature/restaurants/types/TRestaurantFormCommonProps"; +import { useCallback } from "react"; -const FormItemRestaurantComment = () => { - return FormItemRestaurantComment; +interface Props extends TRestaurantFormCommonProps {} + +const FormItemRestaurantComment: React.FC = ({ setFormValues }) => { + const handleChangeName = useCallback( + (value: string, isValid: boolean) => { + setFormValues((prev) => ({ + ...prev, + comment: { + value, + isValid, + }, + })); + }, + [setFormValues] + ); + return ( + + + + ); }; export default FormItemRestaurantComment; diff --git a/src/feature/restaurants/components/formItems/FormTitle.tsx b/src/feature/restaurants/components/formItems/FormTitle.tsx index e54626a..9c9ae87 100644 --- a/src/feature/restaurants/components/formItems/FormTitle.tsx +++ b/src/feature/restaurants/components/formItems/FormTitle.tsx @@ -13,6 +13,5 @@ export default FormTitle; const EmotionWrapper = styled.h1` font-size: 24px; font-weight: 700; - margin-bottom: 36px; line-height: 1.5; `; diff --git a/src/feature/restaurants/constants/RestaurantFormInitialValues.ts b/src/feature/restaurants/constants/RestaurantFormInitialValues.ts index 969e401..adf578e 100644 --- a/src/feature/restaurants/constants/RestaurantFormInitialValues.ts +++ b/src/feature/restaurants/constants/RestaurantFormInitialValues.ts @@ -11,7 +11,10 @@ export const RESTAURANT_FORM_INITIAL_VALUES: TRestaurantFormValues = { address: "", link: "", delivery: false, - comment: "", + comment: { + value: "", + isValid: false, + }, capacity: 0, openingHour: "", recommendedMenu: "", diff --git a/src/feature/restaurants/functions/validateRestaurantForm.ts b/src/feature/restaurants/functions/validateRestaurantForm.ts index 37e636e..acf0f59 100644 --- a/src/feature/restaurants/functions/validateRestaurantForm.ts +++ b/src/feature/restaurants/functions/validateRestaurantForm.ts @@ -1,4 +1,4 @@ -import { RESTAURANT_NAME_MAX_LENGTH } from "constant/limit"; +import { RESTAURANT_COMMENT_MAX_LENGTH, RESTAURANT_NAME_MAX_LENGTH } from "constant/limit"; // 맛집 이름 유효성 검사 조건을 정의합니다. export const validateRestaurantNameLength = { @@ -17,3 +17,12 @@ export const validateRestaurantNameEmpty = { }, messageOnError: "맛집 이름을 입력해주세요.", }; + +// 맛집 한줄평 유효성 검사 조건을 정의합니다. +export const validateRestaurantCommentLength = { + condition: (value: string): boolean => { + if (value?.length > RESTAURANT_COMMENT_MAX_LENGTH) return false; + return true; + }, + messageOnError: `맛집 한줄평은 ${RESTAURANT_COMMENT_MAX_LENGTH}자 이내로 입력해주세요.`, +}; diff --git a/src/feature/restaurants/types/TRestaurantFormValues.ts b/src/feature/restaurants/types/TRestaurantFormValues.ts index ed0df97..5c5932c 100644 --- a/src/feature/restaurants/types/TRestaurantFormValues.ts +++ b/src/feature/restaurants/types/TRestaurantFormValues.ts @@ -8,7 +8,7 @@ export type TRestaurantFormValues = { address?: string; // 맛집 주소 link?: string; // 맛집 링크 delivery?: boolean; // 맛집 배달 여부 - comment?: string; // 맛집 한줄평 + comment?: TFormValue; // 맛집 한줄평 capacity?: number; // 맛집 수용인원 openingHour?: string; // 맛집 운영 시간 recommendedMenu?: string; // 맛집 추천 메뉴 From cc38f9a60f840fd4d72560da343b3720e0ea1eda Mon Sep 17 00:00:00 2001 From: jaychang99 Date: Sun, 10 Sep 2023 21:47:53 +0900 Subject: [PATCH 06/19] =?UTF-8?q?feat(Restaurant):=20=EB=A7=9B=EC=A7=91=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=20?= =?UTF-8?q?=EB=A7=9B=EC=A7=91=20=EC=A3=BC=EC=86=8C=20=EB=84=A3=EB=8A=94=20?= =?UTF-8?q?=EC=9D=B8=ED=92=8B=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constant/limit.ts | 1 + .../restaurants/components/RestaurantForm.tsx | 2 +- .../formItems/FormItemRestaurantAddress.tsx | 32 +++++++++++++++++-- .../constants/RestaurantFormInitialValues.ts | 5 ++- .../functions/validateRestaurantForm.ts | 15 ++++++++- .../types/TRestaurantFormValues.ts | 2 +- 6 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/constant/limit.ts b/src/constant/limit.ts index 9c41bbb..1d9a890 100644 --- a/src/constant/limit.ts +++ b/src/constant/limit.ts @@ -1,6 +1,7 @@ // 맛집 생성 관련 제약 export const RESTAURANT_NAME_MAX_LENGTH = 10; // 맛집 이름 최대 길이 export const RESTAURANT_COMMENT_MAX_LENGTH = 30; // 맛집 한줄평 최대 길이 +export const RESTAURANT_ADDRESS_MAX_LENGTH = 30; // 맛집 주소 최대 길이 export const RESTAURANT_CAPACITY_MAX = 9999; // 맛집 수용인원 최대 수 export const RESTAURANT_OPENING_HOUR_MAX = 30; // 맛집 운영 시간 최대 길이 export const RESTAURANT_RECOMMENDED_MENU_MAX_COUNT = 10; // 맛집 추천 메뉴 최대 개수 diff --git a/src/feature/restaurants/components/RestaurantForm.tsx b/src/feature/restaurants/components/RestaurantForm.tsx index c1d1cab..4e42dab 100644 --- a/src/feature/restaurants/components/RestaurantForm.tsx +++ b/src/feature/restaurants/components/RestaurantForm.tsx @@ -37,7 +37,7 @@ const RestaurantForm = ({ isEditMode = false }: Props) => { - + diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantAddress.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantAddress.tsx index 330b361..88a09b3 100644 --- a/src/feature/restaurants/components/formItems/FormItemRestaurantAddress.tsx +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantAddress.tsx @@ -1,7 +1,35 @@ import styled from "@emotion/styled"; +import TextInput from "components/inputs/TextInput/TextInput"; +import { validateRestaurantAddressLength } from "feature/restaurants/functions/validateRestaurantForm"; +import { TRestaurantFormCommonProps } from "feature/restaurants/types/TRestaurantFormCommonProps"; +import { useCallback } from "react"; -const FormItemRestaurantAddress = () => { - return FormItemRestaurantAddress; +interface Props extends TRestaurantFormCommonProps {} + +const FormItemRestaurantAddress: React.FC = ({ setFormValues }) => { + const handleChangeName = useCallback( + (value: string, isValid: boolean) => { + setFormValues((prev) => ({ + ...prev, + address: { + value, + isValid, + }, + })); + }, + [setFormValues] + ); + + return ( + + + + ); }; export default FormItemRestaurantAddress; diff --git a/src/feature/restaurants/constants/RestaurantFormInitialValues.ts b/src/feature/restaurants/constants/RestaurantFormInitialValues.ts index adf578e..02fe6da 100644 --- a/src/feature/restaurants/constants/RestaurantFormInitialValues.ts +++ b/src/feature/restaurants/constants/RestaurantFormInitialValues.ts @@ -8,7 +8,10 @@ export const RESTAURANT_FORM_INITIAL_VALUES: TRestaurantFormValues = { }, categoryId: 0, tagIds: [0], - address: "", + address: { + value: "", + isValid: false, + }, link: "", delivery: false, comment: { diff --git a/src/feature/restaurants/functions/validateRestaurantForm.ts b/src/feature/restaurants/functions/validateRestaurantForm.ts index acf0f59..9f8620e 100644 --- a/src/feature/restaurants/functions/validateRestaurantForm.ts +++ b/src/feature/restaurants/functions/validateRestaurantForm.ts @@ -1,4 +1,8 @@ -import { RESTAURANT_COMMENT_MAX_LENGTH, RESTAURANT_NAME_MAX_LENGTH } from "constant/limit"; +import { + RESTAURANT_ADDRESS_MAX_LENGTH, + RESTAURANT_COMMENT_MAX_LENGTH, + RESTAURANT_NAME_MAX_LENGTH, +} from "constant/limit"; // 맛집 이름 유효성 검사 조건을 정의합니다. export const validateRestaurantNameLength = { @@ -26,3 +30,12 @@ export const validateRestaurantCommentLength = { }, messageOnError: `맛집 한줄평은 ${RESTAURANT_COMMENT_MAX_LENGTH}자 이내로 입력해주세요.`, }; + +// 맛집 주소 유효성 검사 조건을 정의합니다. +export const validateRestaurantAddressLength = { + condition: (value: string): boolean => { + if (value?.length > RESTAURANT_ADDRESS_MAX_LENGTH) return false; + return true; + }, + messageOnError: `맛집 주소는 ${RESTAURANT_ADDRESS_MAX_LENGTH}자 이내로 입력해주세요.`, +}; diff --git a/src/feature/restaurants/types/TRestaurantFormValues.ts b/src/feature/restaurants/types/TRestaurantFormValues.ts index 5c5932c..f8afba3 100644 --- a/src/feature/restaurants/types/TRestaurantFormValues.ts +++ b/src/feature/restaurants/types/TRestaurantFormValues.ts @@ -5,7 +5,7 @@ export type TRestaurantFormValues = { name: TFormValue; // 맛집 이름 categoryId: number; // 맛집 카테고리 id tagIds: number[]; // 맛집 태그 id 배열 - address?: string; // 맛집 주소 + address?: TFormValue; // 맛집 주소 link?: string; // 맛집 링크 delivery?: boolean; // 맛집 배달 여부 comment?: TFormValue; // 맛집 한줄평 From 7346e65183d3065512138c5cc1b1eafa88fca94a Mon Sep 17 00:00:00 2001 From: jaychang99 Date: Sun, 17 Sep 2023 12:26:16 +0900 Subject: [PATCH 07/19] =?UTF-8?q?feat(Restaurant):=20=EB=A7=9B=EC=A7=91=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EC=8B=9C=20=EB=B0=B0=EB=8B=AC=20=EA=B0=80?= =?UTF-8?q?=EB=8A=A5=20=EC=97=AC=EB=B6=80=20=EC=B2=B4=ED=81=AC=EB=B0=95?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../checkbox/types/TCheckboxItem.ts | 4 ++ .../restaurants/components/RestaurantForm.tsx | 6 +-- .../formItems/FormItemRestaurantDelivery.tsx | 41 ++++++++++++++++++- .../formItems/typography/FormItemLabel.tsx | 21 ++++++++++ .../restaurantDeliveryCheckboxItemList.ts | 12 ++++++ 5 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 src/components/checkbox/types/TCheckboxItem.ts create mode 100644 src/feature/restaurants/components/formItems/typography/FormItemLabel.tsx create mode 100644 src/feature/restaurants/constants/restaurantDeliveryCheckboxItemList.ts diff --git a/src/components/checkbox/types/TCheckboxItem.ts b/src/components/checkbox/types/TCheckboxItem.ts new file mode 100644 index 0000000..80f5e4c --- /dev/null +++ b/src/components/checkbox/types/TCheckboxItem.ts @@ -0,0 +1,4 @@ +export type TCheckboxItem = { + name: string; + value: string; +}; diff --git a/src/feature/restaurants/components/RestaurantForm.tsx b/src/feature/restaurants/components/RestaurantForm.tsx index 4e42dab..41af1f2 100644 --- a/src/feature/restaurants/components/RestaurantForm.tsx +++ b/src/feature/restaurants/components/RestaurantForm.tsx @@ -38,7 +38,7 @@ const RestaurantForm = ({ isEditMode = false }: Props) => { - + @@ -47,7 +47,7 @@ const RestaurantForm = ({ isEditMode = false }: Props) => { - + ); }; @@ -59,7 +59,7 @@ const EmotionWrapper = styled.div` flex-direction: column; row-gap: 36px; - button { + button.submit { margin-top: 24px; float: right; } diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantDelivery.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantDelivery.tsx index 28736fc..fa0968a 100644 --- a/src/feature/restaurants/components/formItems/FormItemRestaurantDelivery.tsx +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantDelivery.tsx @@ -1,7 +1,44 @@ import styled from "@emotion/styled"; +import Checkbox from "components/checkbox/Checkbox"; +import { TRestaurantFormCommonProps } from "feature/restaurants/types/TRestaurantFormCommonProps"; +import { RESTAURANT_DELIVERY_CHECKBOX_ITEM_LIST } from "feature/restaurants/constants/restaurantDeliveryCheckboxItemList"; +import FormItemLabel from "feature/restaurants/components/formItems/typography/FormItemLabel"; +import { useCallback } from "react"; -const FormItemRestaurantDelivery = () => { - return FormItemRestaurantDelivery; +interface Props extends TRestaurantFormCommonProps {} + +const FormItemRestaurantDelivery: React.FC = ({ isEditMode, formValues, setFormValues }) => { + const handleCheckedItem = useCallback( + (value: string) => { + setFormValues((prev) => ({ + ...prev, + delivery: value === "true" ? true : false, + })); + }, + [setFormValues] + ); + + return ( + + 배달 가능 여부 + { + handleCheckedItem(checkedList); + }} + > + {RESTAURANT_DELIVERY_CHECKBOX_ITEM_LIST.map((item) => { + const { value, name } = item; + + return ( + + {name} + + ); + })} + + + ); }; export default FormItemRestaurantDelivery; diff --git a/src/feature/restaurants/components/formItems/typography/FormItemLabel.tsx b/src/feature/restaurants/components/formItems/typography/FormItemLabel.tsx new file mode 100644 index 0000000..6eae0a9 --- /dev/null +++ b/src/feature/restaurants/components/formItems/typography/FormItemLabel.tsx @@ -0,0 +1,21 @@ +import { ReactNode } from "react"; +import styled from "@emotion/styled"; + +interface Props { + children?: ReactNode; +} + +const FormItemLabel = ({ children }: Props) => { + return {children}; +}; + +export default FormItemLabel; + +const EmotionWrapper = styled.label` + display: block; + color: ${({ theme }) => theme.color.gray600}; + font-size: 16px; + font-weight: 300; + margin-left: 2px; + margin-bottom: 8px; +`; diff --git a/src/feature/restaurants/constants/restaurantDeliveryCheckboxItemList.ts b/src/feature/restaurants/constants/restaurantDeliveryCheckboxItemList.ts new file mode 100644 index 0000000..8273e64 --- /dev/null +++ b/src/feature/restaurants/constants/restaurantDeliveryCheckboxItemList.ts @@ -0,0 +1,12 @@ +import { TCheckboxItem } from "components/checkbox/types/TCheckboxItem"; + +export const RESTAURANT_DELIVERY_CHECKBOX_ITEM_LIST: TCheckboxItem[] = [ + { + name: "배달함", + value: "true", + }, + { + name: "배달 안함", + value: "false", + }, +]; From db9833d921c73e766df07995e50b9664afc550c5 Mon Sep 17 00:00:00 2001 From: jaychang99 Date: Sun, 17 Sep 2023 12:34:34 +0900 Subject: [PATCH 08/19] =?UTF-8?q?feat(Restaurant):=20=ED=8F=BC=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=20=EC=A0=84=EC=86=A1=20=EB=A1=9C=EC=A7=81=20=EB=AA=A8?= =?UTF-8?q?=ED=82=B9=EC=9A=A9=20console.log=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/feature/restaurants/components/RestaurantForm.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/feature/restaurants/components/RestaurantForm.tsx b/src/feature/restaurants/components/RestaurantForm.tsx index 41af1f2..4e95ca3 100644 --- a/src/feature/restaurants/components/RestaurantForm.tsx +++ b/src/feature/restaurants/components/RestaurantForm.tsx @@ -32,8 +32,13 @@ const RestaurantForm = ({ isEditMode = false }: Props) => { setFormValues, }; + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + console.log(formValues); + }; + return ( - + @@ -54,7 +59,7 @@ const RestaurantForm = ({ isEditMode = false }: Props) => { export default RestaurantForm; -const EmotionWrapper = styled.div` +const EmotionWrapper = styled.form` display: flex; flex-direction: column; row-gap: 36px; From 3dfa43c280aa7a437e4c7ebfee1a75a8f151d0ac Mon Sep 17 00:00:00 2001 From: jaychang99 Date: Sun, 17 Sep 2023 13:14:50 +0900 Subject: [PATCH 09/19] =?UTF-8?q?feat(Restaurant):=20tagIds=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=ED=95=98=EB=8A=94=20=EB=B6=80=EB=B6=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/radio/Radio.tsx | 14 +++++++-- src/components/radio/items/RadioGroup.tsx | 1 + src/components/radio/types/TRadioItem.ts | 5 +++ .../restaurants/components/RestaurantForm.tsx | 24 +++++++++++++- .../components/formItems/FormItemTagIds.tsx | 31 +++++++++++++++++-- .../constants/restaurantTagIdsItemList.ts | 30 ++++++++++++++++++ 6 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 src/components/radio/types/TRadioItem.ts create mode 100644 src/feature/restaurants/constants/restaurantTagIdsItemList.ts diff --git a/src/components/radio/Radio.tsx b/src/components/radio/Radio.tsx index 8320abe..92bcb97 100644 --- a/src/components/radio/Radio.tsx +++ b/src/components/radio/Radio.tsx @@ -8,9 +8,17 @@ interface Props { children: ReactNode; disabled?: boolean; initialValue?: boolean; // 첫 렌더링 시 체크 여부, 이후의 state 변화는 감지하지 않음 + className?: string; } -const Radio = ({ name, value, children, disabled = false, initialValue = false }: Props) => { +const Radio = ({ + name, + value, + children, + disabled = false, + initialValue = false, + className, +}: Props) => { const [checked, setChecked] = useState(initialValue); const onChangeRadio = (event: React.ChangeEvent) => { @@ -19,7 +27,7 @@ const Radio = ({ name, value, children, disabled = false, initialValue = false } return ( - diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantLink.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantLink.tsx index cfb02cb..6d8615f 100644 --- a/src/feature/restaurants/components/formItems/FormItemRestaurantLink.tsx +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantLink.tsx @@ -1,7 +1,33 @@ +import { useCallback } from "react"; import styled from "@emotion/styled"; +import TextInput from "components/inputs/TextInput/TextInput"; +import { TRestaurantFormCommonProps } from "feature/restaurants/types/TRestaurantFormCommonProps"; -const FormItemRestaurantLink = () => { - return FormItemRestaurantLink; +interface Props extends TRestaurantFormCommonProps {} + +const FormItemRestaurantLink: React.FC = ({ setFormValues }) => { + const handleChangeLink = useCallback( + (value: string, isValid: boolean) => { + setFormValues((prev) => ({ + ...prev, + link: { + value, + isValid, + }, + })); + }, + [setFormValues] + ); + + return ( + + + + ); }; export default FormItemRestaurantLink; diff --git a/src/feature/restaurants/constants/RestaurantFormInitialValues.ts b/src/feature/restaurants/constants/RestaurantFormInitialValues.ts index 12e9455..7c4349e 100644 --- a/src/feature/restaurants/constants/RestaurantFormInitialValues.ts +++ b/src/feature/restaurants/constants/RestaurantFormInitialValues.ts @@ -12,7 +12,10 @@ export const RESTAURANT_FORM_INITIAL_VALUES: TRestaurantFormValues = { value: "", isValid: false, }, - link: "", + link: { + value: "", + isValid: false, + }, delivery: false, comment: { value: "", diff --git a/src/feature/restaurants/types/TRestaurantFormValues.ts b/src/feature/restaurants/types/TRestaurantFormValues.ts index 4fea0e5..bd14064 100644 --- a/src/feature/restaurants/types/TRestaurantFormValues.ts +++ b/src/feature/restaurants/types/TRestaurantFormValues.ts @@ -6,7 +6,7 @@ export type TRestaurantFormValues = { categoryId: number; // 맛집 카테고리 id tagIds: number[]; // 맛집 태그 id 배열 address?: TFormValue; // 맛집 주소 - link?: string; // 맛집 링크 + link?: TFormValue; // 맛집 링크 delivery?: boolean; // 맛집 배달 여부 comment?: TFormValue; // 맛집 한줄평 capacity?: TFormValue; // 맛집 수용인원 From c5a6b712bb7c8c45dfacc1dcc043746718937e0e Mon Sep 17 00:00:00 2001 From: jaychang99 Date: Tue, 19 Sep 2023 21:47:13 +0900 Subject: [PATCH 14/19] =?UTF-8?q?feat(Restaurant):=20=EB=A7=9B=EC=A7=91=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=ED=8F=BC=EC=97=90=20=EB=A7=9B=EC=A7=91=20?= =?UTF-8?q?=EB=B6=84=EB=A5=98=20(=EC=96=91=EC=8B=9D,=20=EC=9D=BC=EC=8B=9D?= =?UTF-8?q?=20=EB=93=B1)=20=EC=B6=94=EA=B0=80=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=93=9C=EB=A1=AD=EB=8B=A4=EC=9A=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dropdown/types/TDropdownItem.ts | 4 +++ .../restaurants/components/RestaurantForm.tsx | 2 +- .../FormItemRestaurantCategoryId.tsx | 35 +++++++++++++++++-- .../constants/RestaurantFormInitialValues.ts | 2 +- .../restaurantCategoryIdDropdownList.ts | 32 +++++++++++++++++ .../types/TRestaurantFormValues.ts | 2 +- 6 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 src/components/dropdown/types/TDropdownItem.ts create mode 100644 src/feature/restaurants/constants/restaurantCategoryIdDropdownList.ts diff --git a/src/components/dropdown/types/TDropdownItem.ts b/src/components/dropdown/types/TDropdownItem.ts new file mode 100644 index 0000000..b029355 --- /dev/null +++ b/src/components/dropdown/types/TDropdownItem.ts @@ -0,0 +1,4 @@ +export type TDropdownItem = { + value: string; + label: string; +}; diff --git a/src/feature/restaurants/components/RestaurantForm.tsx b/src/feature/restaurants/components/RestaurantForm.tsx index fc7ffb2..84ca40c 100644 --- a/src/feature/restaurants/components/RestaurantForm.tsx +++ b/src/feature/restaurants/components/RestaurantForm.tsx @@ -70,7 +70,7 @@ const RestaurantForm = ({ isEditMode = false }: Props) => { - + diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantCategoryId.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantCategoryId.tsx index f2f48c1..a86533c 100644 --- a/src/feature/restaurants/components/formItems/FormItemRestaurantCategoryId.tsx +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantCategoryId.tsx @@ -1,7 +1,38 @@ import styled from "@emotion/styled"; +import Dropdown from "components/dropdown/Dropdown"; +import { RESTAURANT_CATEGORY_ID_DROPDOWN_LIST } from "feature/restaurants/constants/restaurantCategoryIdDropdownList"; +import { TRestaurantFormCommonProps } from "feature/restaurants/types/TRestaurantFormCommonProps"; -const FormItemRestaurantCategoryId = () => { - return FormItemRestaurantCategoryId; +interface Props extends TRestaurantFormCommonProps {} + +const { Option } = Dropdown; + +const FormItemRestaurantCategoryId: React.FC = ({ formValues, setFormValues }) => { + return ( + + { + setFormValues({ + ...formValues, + categoryId: value, + }); + }} + > + {RESTAURANT_CATEGORY_ID_DROPDOWN_LIST.map((item) => { + const { value, label } = item; + + return ( + + ); + })} + + + ); }; export default FormItemRestaurantCategoryId; diff --git a/src/feature/restaurants/constants/RestaurantFormInitialValues.ts b/src/feature/restaurants/constants/RestaurantFormInitialValues.ts index 7c4349e..81b67e5 100644 --- a/src/feature/restaurants/constants/RestaurantFormInitialValues.ts +++ b/src/feature/restaurants/constants/RestaurantFormInitialValues.ts @@ -6,7 +6,7 @@ export const RESTAURANT_FORM_INITIAL_VALUES: TRestaurantFormValues = { value: "", isValid: false, }, - categoryId: 0, + categoryId: "1", tagIds: [0], address: { value: "", diff --git a/src/feature/restaurants/constants/restaurantCategoryIdDropdownList.ts b/src/feature/restaurants/constants/restaurantCategoryIdDropdownList.ts new file mode 100644 index 0000000..b964737 --- /dev/null +++ b/src/feature/restaurants/constants/restaurantCategoryIdDropdownList.ts @@ -0,0 +1,32 @@ +import { TDropdownItem } from "components/dropdown/types/TDropdownItem"; + +export const RESTAURANT_CATEGORY_ID_DROPDOWN_LIST: TDropdownItem[] = [ + { + value: "1", + label: "일식", + }, + { + value: "2", + label: "중식", + }, + { + value: "3", + label: "양식", + }, + { + value: "4", + label: "한식", + }, + { + value: "5", + label: "분식", + }, + { + value: "6", + label: "카페", + }, + { + value: "7", + label: "기타", + }, +]; diff --git a/src/feature/restaurants/types/TRestaurantFormValues.ts b/src/feature/restaurants/types/TRestaurantFormValues.ts index bd14064..a8e67be 100644 --- a/src/feature/restaurants/types/TRestaurantFormValues.ts +++ b/src/feature/restaurants/types/TRestaurantFormValues.ts @@ -3,7 +3,7 @@ import { TFormValue } from "feature/restaurants/types/TFormValue"; export type TRestaurantFormValues = { userId: number; // 맛집 생성자의 id name: TFormValue; // 맛집 이름 - categoryId: number; // 맛집 카테고리 id + categoryId: string; // 맛집 카테고리 id tagIds: number[]; // 맛집 태그 id 배열 address?: TFormValue; // 맛집 주소 link?: TFormValue; // 맛집 링크 From 2e8f2ff20ca3507c2e8e97a7300658e252b23254 Mon Sep 17 00:00:00 2001 From: jaychang99 Date: Tue, 19 Sep 2023 21:55:12 +0900 Subject: [PATCH 15/19] =?UTF-8?q?feat(Restaurant):=20=EB=A7=9B=EC=A7=91?= =?UTF-8?q?=EC=97=90=20=EC=82=AC=EC=A7=84=20=EC=9E=85=EB=A0=A5=EA=B8=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../restaurants/components/RestaurantForm.tsx | 11 ++++++++++- .../formItems/FormItemRestaurantImages.tsx | 18 ++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/feature/restaurants/components/RestaurantForm.tsx b/src/feature/restaurants/components/RestaurantForm.tsx index 84ca40c..abee36c 100644 --- a/src/feature/restaurants/components/RestaurantForm.tsx +++ b/src/feature/restaurants/components/RestaurantForm.tsx @@ -26,6 +26,11 @@ type TTagId = { }; }; +type TImageInput = { + imageInput: { files: FileList }; + imageUrlInput: { value: string }; +}; + interface Props { isEditMode?: boolean; } @@ -46,7 +51,7 @@ const RestaurantForm = ({ isEditMode = false }: Props) => { console.log(formValues); // TODO: 더 나은 방식 생각해내기 - const target = event.target as typeof event.target & TTagId; + const target = event.target as typeof event.target & TTagId & TImageInput; const mood = target.mood.checked; const value = target.value.checked; @@ -57,6 +62,10 @@ const RestaurantForm = ({ isEditMode = false }: Props) => { console.log("value", value); console.log("kind", kind); console.log("liquor", liquor); + + // images + console.log("newly added images: ", target.imageInput.files); + console.log("exising Images: ", target.imageUrlInput.value); }; return ( diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantImages.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantImages.tsx index 1ac17cf..e0a29cf 100644 --- a/src/feature/restaurants/components/formItems/FormItemRestaurantImages.tsx +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantImages.tsx @@ -1,7 +1,21 @@ import styled from "@emotion/styled"; +import ImageInput from "components/inputs/ImageInput/ImageInput"; +import { RESTAURANT_IMAGES_MAX_COUNT } from "constant/limit"; -const FormItemRestaurantImages = () => { - return FormItemRestaurantImages; +interface Props { + existingImageUrlList?: string[]; +} + +const FormItemRestaurantImages: React.FC = ({ existingImageUrlList }) => { + return ( + + + + ); }; export default FormItemRestaurantImages; From eb2a5489c06b90f0db387b6aed0c4e89ee3773a1 Mon Sep 17 00:00:00 2001 From: jaychang99 Date: Tue, 19 Sep 2023 22:21:47 +0900 Subject: [PATCH 16/19] =?UTF-8?q?fix(TextInput):=20=EC=B5=9C=EC=B4=88=20?= =?UTF-8?q?=20value=20=EB=84=A3=EC=9D=80=20=EC=9D=B4=ED=9B=84=20=EA=B7=B8?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=B0=98=EC=9D=91=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EB=AA=BB=ED=95=98=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/inputs/TextInput/TextInput.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/inputs/TextInput/TextInput.tsx b/src/components/inputs/TextInput/TextInput.tsx index 074a23f..ea348d9 100644 --- a/src/components/inputs/TextInput/TextInput.tsx +++ b/src/components/inputs/TextInput/TextInput.tsx @@ -76,6 +76,11 @@ const TextInput: React.FC = ({ } }, [enteredValue, status, onTextChange]); + useEffect(() => { + // 비동기 API 호출로 인한 value 변경 시에만 실행 + setEnteredValue(value); + }, [value]); + return ( {label && {label}} From 6675322c02d4d0506556d77ae3e9bc4f2467d074 Mon Sep 17 00:00:00 2001 From: jaychang99 Date: Tue, 19 Sep 2023 22:31:09 +0900 Subject: [PATCH 17/19] =?UTF-8?q?feat(HashtagInput):=20=ED=95=B4=EC=8B=9C?= =?UTF-8?q?=ED=83=9C=EA=B7=B8=20=EC=9E=85=EB=A0=A5=EA=B8=B0=20=EA=B3=B5?= =?UTF-8?q?=ED=86=B5=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../inputs/HashtagInput/HashtagInput.tsx | 69 +++++++++++++++++++ .../inputs/HashtagInput/items/HashtagItem.tsx | 33 +++++++++ 2 files changed, 102 insertions(+) create mode 100644 src/components/inputs/HashtagInput/HashtagInput.tsx create mode 100644 src/components/inputs/HashtagInput/items/HashtagItem.tsx diff --git a/src/components/inputs/HashtagInput/HashtagInput.tsx b/src/components/inputs/HashtagInput/HashtagInput.tsx new file mode 100644 index 0000000..56b1fde --- /dev/null +++ b/src/components/inputs/HashtagInput/HashtagInput.tsx @@ -0,0 +1,69 @@ +import styled from "@emotion/styled"; +import HashtagItem from "components/inputs/HashtagInput/items/HashtagItem"; +import TextInput from "components/inputs/TextInput/TextInput"; +import { useCallback, useEffect, useState } from "react"; + +interface Props { + hashtagList: string[]; + setHashTagList: (hashtagList: string[]) => void; +} + +type TTextInput = { + value: string; + isValid: boolean; +}; + +const HashtagInput: React.FC = ({ hashtagList, setHashTagList }) => { + const [currentInput, setCurrentInput] = useState({ + value: "", + isValid: false, + }); + + useEffect(() => { + if (currentInput.value.includes(",") && currentInput.isValid) { + const newHashtagList = [...hashtagList, currentInput.value.replace(",", "")]; + setHashTagList(newHashtagList); + setCurrentInput({ value: "", isValid: false }); + } + }, [currentInput, hashtagList, setHashTagList]); + + const handleChangeCurrentInput = useCallback((value: string, isValid: boolean) => { + setCurrentInput({ value, isValid }); + }, []); + + const handleRemoveHashtag = useCallback( + (hashtag: string) => { + const newHashtagList = hashtagList.filter((item) => item !== hashtag); + setHashTagList(newHashtagList); + }, + [hashtagList, setHashTagList] + ); + + return ( + + +
    + {hashtagList.map((item) => ( + + {item} + + ))} +
+
+ ); +}; + +export default HashtagInput; + +const EmotionWrapper = styled.div` + ul.hashtag-container { + margin-top: 8px; + display: flex; + flex-wrap: wrap; + row-gap: 8px; + } +`; diff --git a/src/components/inputs/HashtagInput/items/HashtagItem.tsx b/src/components/inputs/HashtagInput/items/HashtagItem.tsx new file mode 100644 index 0000000..feec3f1 --- /dev/null +++ b/src/components/inputs/HashtagInput/items/HashtagItem.tsx @@ -0,0 +1,33 @@ +import styled from "@emotion/styled"; +import { LiHTMLAttributes, ReactNode, useCallback } from "react"; + +interface Props extends Omit, "onClick"> { + children: ReactNode; + onClick: (hashtag: string) => void; +} + +const HashtagItem = ({ children, onClick, ...props }: Props) => { + const handleClickHashtag = useCallback(() => { + onClick(typeof children === "string" ? children : ""); + }, [children, onClick]); + + return ( + + {children} + + ); +}; + +export default HashtagItem; + +const EmotionWrapper = styled.li` + position: relative; + display: inline-block; + padding: 4px 8px; + + border-radius: 4px; + margin-right: 8px; + font-size: 12px; + background-color: ${({ theme }) => theme.color.primary200}; + color: ${({ theme }) => theme.color.primary700}; +`; From 64ed0dffc1c01dfdaf1b0a37f6658c4d27f28045 Mon Sep 17 00:00:00 2001 From: jaychang99 Date: Tue, 19 Sep 2023 22:32:16 +0900 Subject: [PATCH 18/19] =?UTF-8?q?feat(Restaurant):=20=EB=A7=9B=EC=A7=91=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=ED=8F=BC=EC=97=90=20=EC=B6=94=EC=B2=9C=20?= =?UTF-8?q?=EB=A9=94=EB=89=B4=20=EB=93=B1=EB=A1=9D=ED=95=A0=20=EC=88=98=20?= =?UTF-8?q?=EC=9E=88=EB=8F=84=EB=A1=9D=20HashtagInput=20=EC=9D=B4=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../restaurants/components/RestaurantForm.tsx | 2 +- .../FormItemRestaurantRecommendedMenu.tsx | 24 +++++++++++++++++-- .../constants/RestaurantFormInitialValues.ts | 2 +- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/feature/restaurants/components/RestaurantForm.tsx b/src/feature/restaurants/components/RestaurantForm.tsx index abee36c..2811963 100644 --- a/src/feature/restaurants/components/RestaurantForm.tsx +++ b/src/feature/restaurants/components/RestaurantForm.tsx @@ -78,7 +78,7 @@ const RestaurantForm = ({ isEditMode = false }: Props) => { - + diff --git a/src/feature/restaurants/components/formItems/FormItemRestaurantRecommendedMenu.tsx b/src/feature/restaurants/components/formItems/FormItemRestaurantRecommendedMenu.tsx index 33ebe72..4566fce 100644 --- a/src/feature/restaurants/components/formItems/FormItemRestaurantRecommendedMenu.tsx +++ b/src/feature/restaurants/components/formItems/FormItemRestaurantRecommendedMenu.tsx @@ -1,7 +1,27 @@ import styled from "@emotion/styled"; +import HashtagInput from "components/inputs/HashtagInput/HashtagInput"; +import FormItemLabel from "feature/restaurants/components/formItems/typography/FormItemLabel"; +import { TRestaurantFormCommonProps } from "feature/restaurants/types/TRestaurantFormCommonProps"; -const FormItemRestaurantRecommendedMenu = () => { - return FormItemRestaurantRecommendedMenu; +interface Props extends TRestaurantFormCommonProps {} + +const FormItemRestaurantRecommendedMenu: React.FC = ({ formValues, setFormValues }) => { + const setHashtagList = (hashtagList: string[]) => { + setFormValues({ + ...formValues, + recommendedMenu: JSON.stringify(hashtagList), + }); + }; + + return ( + + 추천 메뉴 + + + ); }; export default FormItemRestaurantRecommendedMenu; diff --git a/src/feature/restaurants/constants/RestaurantFormInitialValues.ts b/src/feature/restaurants/constants/RestaurantFormInitialValues.ts index 81b67e5..48dffe7 100644 --- a/src/feature/restaurants/constants/RestaurantFormInitialValues.ts +++ b/src/feature/restaurants/constants/RestaurantFormInitialValues.ts @@ -29,7 +29,7 @@ export const RESTAURANT_FORM_INITIAL_VALUES: TRestaurantFormValues = { value: "", isValid: false, }, - recommendedMenu: "", + recommendedMenu: "[]", orderTip: { value: "", isValid: false, From d5e1ae211922e175e1d60f1b373bdc4e62c8cb4d Mon Sep 17 00:00:00 2001 From: jaychang99 Date: Tue, 19 Sep 2023 22:35:46 +0900 Subject: [PATCH 19/19] =?UTF-8?q?feat(HashtagInput):=20=ED=95=B4=EC=8B=9C?= =?UTF-8?q?=ED=83=9C=EA=B7=B8=20=EC=9E=85=EB=A0=A5=EA=B8=B0=EC=97=90=20pla?= =?UTF-8?q?ceholder=20=EC=B6=94=EA=B0=80=ED=95=98=EA=B2=8C=20=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/inputs/HashtagInput/HashtagInput.tsx | 4 +++- .../formItems/FormItemRestaurantRecommendedMenu.tsx | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/inputs/HashtagInput/HashtagInput.tsx b/src/components/inputs/HashtagInput/HashtagInput.tsx index 56b1fde..be20873 100644 --- a/src/components/inputs/HashtagInput/HashtagInput.tsx +++ b/src/components/inputs/HashtagInput/HashtagInput.tsx @@ -6,6 +6,7 @@ import { useCallback, useEffect, useState } from "react"; interface Props { hashtagList: string[]; setHashTagList: (hashtagList: string[]) => void; + placeholder?: string; } type TTextInput = { @@ -13,7 +14,7 @@ type TTextInput = { isValid: boolean; }; -const HashtagInput: React.FC = ({ hashtagList, setHashTagList }) => { +const HashtagInput: React.FC = ({ hashtagList, setHashTagList, placeholder }) => { const [currentInput, setCurrentInput] = useState({ value: "", isValid: false, @@ -42,6 +43,7 @@ const HashtagInput: React.FC = ({ hashtagList, setHashTagList }) => { return ( = ({ formValues, setFor 추천 메뉴