From b8522c725e2c4237f7cbb63d6b875f32b3b3eec6 Mon Sep 17 00:00:00 2001 From: jerry Date: Tue, 10 Dec 2024 15:24:24 +0900 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20=EA=B2=BD=EB=A0=A5=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=ED=95=AD=EB=AA=A9=20=20UI=20=EB=B3=80=EA=B2=BD=20-?= =?UTF-8?q?=20chip=20->=20dropwdown?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CoffeechatForm/MyInfoForm/index.tsx | 54 ++++++++++++++++--- .../upload/CoffeechatForm/constants.ts | 14 ++--- 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/src/components/coffeechat/upload/CoffeechatForm/MyInfoForm/index.tsx b/src/components/coffeechat/upload/CoffeechatForm/MyInfoForm/index.tsx index 93437b03f..a9623d33d 100644 --- a/src/components/coffeechat/upload/CoffeechatForm/MyInfoForm/index.tsx +++ b/src/components/coffeechat/upload/CoffeechatForm/MyInfoForm/index.tsx @@ -1,10 +1,11 @@ import styled from '@emotion/styled'; +import { SelectV2 } from '@sopt-makers/ui'; import { Controller, useFormContext } from 'react-hook-form'; import { COFFEECHAT_MOBILE_MEDIA_QUERY } from '@/components/coffeechat/mediaQuery'; -import ChipField from '@/components/coffeechat/upload/CoffeechatForm/ChipField'; -import { CAREER_LEVEL } from '@/components/coffeechat/upload/CoffeechatForm/constants'; +import { CAREER_LEVEL_OPTIONS } from '@/components/coffeechat/upload/CoffeechatForm/constants'; import { CoffeechatFormContent } from '@/components/coffeechat/upload/CoffeechatForm/types'; +import FormItem from '@/components/common/form/FormItem'; import FormTitle from '@/components/common/form/FormTitle'; import TextFieldLineBreak from '@/components/common/form/TextFieldLineBreak'; import Responsive from '@/components/common/Responsive'; @@ -25,12 +26,35 @@ export default function MyInfoForm() { > 경력 - + + + ( + + + option.value === field.value)} + onChange={(value) => field.onChange([value])} + > + + + + + {CAREER_LEVEL_OPTIONS.map((option) => ( + + ))} + + + + + )} + /> +
@@ -82,3 +106,17 @@ const CareerWrapper = styled.article` flex-direction: column; gap: 12px; `; + +const CareerOptionContainer = styled.div` + .member-career { + width: 312px; + + button { + width: 312px; + + div { + width: 312px; + } + } + } +`; diff --git a/src/components/coffeechat/upload/CoffeechatForm/constants.ts b/src/components/coffeechat/upload/CoffeechatForm/constants.ts index 656a4644c..8f3616ddf 100644 --- a/src/components/coffeechat/upload/CoffeechatForm/constants.ts +++ b/src/components/coffeechat/upload/CoffeechatForm/constants.ts @@ -1,10 +1,10 @@ -export const CAREER_LEVEL = [ - '아직 없어요', - '인턴 경험만 있어요', - '주니어 (0-3년)', - '미들 (4-8년)', - '시니어 (9년 이상)', - '창업 중', +export const CAREER_LEVEL_OPTIONS = [ + { label: '아직 없어요', value: '아직 없어요' }, + { label: '인턴 경험만 있어요', value: '인턴 경험만 있어요' }, + { label: '주니어 (0-3년)', value: '주니어 (0-3년)' }, + { label: '미들 (4-8년)', value: '미들 (4-8년)' }, + { label: '시니어 (9년 이상)', value: '시니어 (9년 이상)' }, + { label: '창업 중', value: '창업 중' }, ] as const; export const COFFECHAT_SECTION = ['SOPT 활동', '기획', '디자인', '프론트', '백엔드', '앱 개발', '기타'] as const; From 03d89cc5a0ccbc589bebace1ff62927e29cf7776 Mon Sep 17 00:00:00 2001 From: jerry Date: Thu, 12 Dec 2024 12:45:36 +0900 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20MO=EC=97=90=EC=84=9C=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=20=EA=B0=80=EB=8A=A5=ED=95=9C=20BottomSheetSelect=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BottomSheetSelect/index.tsx | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 src/components/coffeechat/upload/CoffeechatForm/BottomSheetSelect/index.tsx diff --git a/src/components/coffeechat/upload/CoffeechatForm/BottomSheetSelect/index.tsx b/src/components/coffeechat/upload/CoffeechatForm/BottomSheetSelect/index.tsx new file mode 100644 index 000000000..5bc99965b --- /dev/null +++ b/src/components/coffeechat/upload/CoffeechatForm/BottomSheetSelect/index.tsx @@ -0,0 +1,149 @@ +import styled from '@emotion/styled'; +import { colors } from '@sopt-makers/colors'; +import { fonts } from '@sopt-makers/fonts'; +import { IconCheck, IconChevronDown } from '@sopt-makers/icons'; +import { Button } from '@sopt-makers/ui'; +import { useEffect, useState } from 'react'; + +import { zIndex } from '@/styles/zIndex'; + +interface Option { + label: string; + value: string; +} + +interface BottomSheetSelectProps { + options: Option[]; + value: string | string[] | null | undefined; + placeholder: string; + onChange: (value: string) => void; +} +const BottomSheetSelect = ({ options, value, placeholder, onChange }: BottomSheetSelectProps) => { + const [open, setOpen] = useState(false); + const [selectedValue, setSelectedValue] = useState(value); + const [temporaryValue, setTemporaryValue] = useState(value); + + const handleOpen = () => setOpen(true); + const handleClose = () => setOpen(false); + + const handleOptionSelect = (value: string) => { + setTemporaryValue(value); + }; + + const handleConfirm = () => { + setSelectedValue(temporaryValue); + if (temporaryValue !== '') onChange(temporaryValue as string); + + handleClose(); + }; + + useEffect(() => { + if (open) { + document.body.style.overflow = 'hidden'; + } else { + document.body.style.overflow = ''; + } + + return () => { + document.body.style.overflow = ''; + }; + }, [open]); + + return ( + + + {selectedValue !== null ?

{selectedValue}

:

{placeholder}

} + +
+ + {open && ( + <> + + + + {options.map((option) => ( + handleOptionSelect(option.value)}> + {option.label} + {temporaryValue === option.value && } + + ))} + + + + + )} +
+ ); +}; +export default BottomSheetSelect; + +const Container = styled.div` + position: relative; + width: 100%; +`; + +const InputField = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + border-radius: 10px; + background-color: ${colors.gray800}; + cursor: pointer; + padding: 11px 16px; + ${fonts.BODY_16_M}; +`; + +const Overlay = styled.div` + position: fixed; + top: 0; + left: 0; + z-index: ${zIndex.헤더}; + background-color: rgb(15 15 18 / 80%); + width: 100%; + height: 100%; +`; + +const BottomSheet = styled.section` + position: fixed; + bottom: 0; + z-index: ${zIndex.헤더}; + margin-bottom: 12px; + border-radius: 16px; + background-color: ${colors.gray800}; + padding: 16px; + width: calc(100% - 40px); +`; + +const OptionList = styled.ul` + margin: 0 0 16px; + padding: 0; + max-height: 300px; + overflow-y: auto; + list-style: none; +`; + +const OptionItem = styled.li` + display: flex; + align-items: center; + justify-content: space-between; + border-radius: 4px; + cursor: pointer; + padding: 10px; + height: 44px; + ${fonts.BODY_14_M} +`; + +const CheckedIcon = styled(IconCheck)` + width: 24px; + height: 24px; + color: ${colors.success}; +`; From e51c98df6622731bde49037a15c232942eefb951 Mon Sep 17 00:00:00 2001 From: jerry Date: Thu, 12 Dec 2024 12:47:41 +0900 Subject: [PATCH 3/8] =?UTF-8?q?feat:=20=EA=B2=BD=EB=A0=A5=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=ED=95=AD=EB=AA=A9=20UI=20=EB=B3=80=EA=B2=BD=20-=20?= =?UTF-8?q?chip=20->=20PC:=20dropdown,=20MO:=20bottomsheet=20=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CoffeechatForm/MyInfoForm/index.tsx | 74 +++++++++++++------ .../upload/CoffeechatForm/constants.ts | 1 + 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/src/components/coffeechat/upload/CoffeechatForm/MyInfoForm/index.tsx b/src/components/coffeechat/upload/CoffeechatForm/MyInfoForm/index.tsx index a9623d33d..2bcd5a826 100644 --- a/src/components/coffeechat/upload/CoffeechatForm/MyInfoForm/index.tsx +++ b/src/components/coffeechat/upload/CoffeechatForm/MyInfoForm/index.tsx @@ -3,12 +3,14 @@ import { SelectV2 } from '@sopt-makers/ui'; import { Controller, useFormContext } from 'react-hook-form'; import { COFFEECHAT_MOBILE_MEDIA_QUERY } from '@/components/coffeechat/mediaQuery'; +import BottomSheetSelect from '@/components/coffeechat/upload/CoffeechatForm/BottomSheetSelect'; import { CAREER_LEVEL_OPTIONS } from '@/components/coffeechat/upload/CoffeechatForm/constants'; import { CoffeechatFormContent } from '@/components/coffeechat/upload/CoffeechatForm/types'; import FormItem from '@/components/common/form/FormItem'; import FormTitle from '@/components/common/form/FormTitle'; import TextFieldLineBreak from '@/components/common/form/TextFieldLineBreak'; import Responsive from '@/components/common/Responsive'; +import { MOBILE_MEDIA_QUERY } from '@/styles/mediaQuery'; export default function MyInfoForm() { const { @@ -32,26 +34,37 @@ export default function MyInfoForm() { name='memberInfo.career' control={control} render={({ field }) => ( - - - option.value === field.value)} - onChange={(value) => field.onChange([value])} - > - - - - - {CAREER_LEVEL_OPTIONS.map((option) => ( - - ))} - - - - + <> + + + option.value === field.value)} + onChange={(value) => field.onChange(value)} + > + + + + + {CAREER_LEVEL_OPTIONS.map((option) => ( + + ))} + + + + + + field.onChange(value)} + /> + + + )} /> @@ -108,7 +121,7 @@ const CareerWrapper = styled.article` `; const CareerOptionContainer = styled.div` - .member-career { + .option-container { width: 312px; button { @@ -119,4 +132,23 @@ const CareerOptionContainer = styled.div` } } } + + @media ${MOBILE_MEDIA_QUERY} { + .option-container { + width: 100%; + + ul { + margin-bottom: 24px; + max-height: 400px !important; + } + + button { + width: 100%; + + div { + width: 100%; + } + } + } + } `; diff --git a/src/components/coffeechat/upload/CoffeechatForm/constants.ts b/src/components/coffeechat/upload/CoffeechatForm/constants.ts index 8f3616ddf..fffcc76dd 100644 --- a/src/components/coffeechat/upload/CoffeechatForm/constants.ts +++ b/src/components/coffeechat/upload/CoffeechatForm/constants.ts @@ -6,6 +6,7 @@ export const CAREER_LEVEL_OPTIONS = [ { label: '시니어 (9년 이상)', value: '시니어 (9년 이상)' }, { label: '창업 중', value: '창업 중' }, ] as const; +export type CareerLevelOptions = typeof CAREER_LEVEL_OPTIONS; export const COFFECHAT_SECTION = ['SOPT 활동', '기획', '디자인', '프론트', '백엔드', '앱 개발', '기타'] as const; From 969b12829fda77bd0a87bd49d9ca16b792d3a1c9 Mon Sep 17 00:00:00 2001 From: jerry Date: Thu, 12 Dec 2024 12:49:49 +0900 Subject: [PATCH 4/8] =?UTF-8?q?feat:=20=EC=BB=A4=ED=94=BC=EC=B1=97=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=20=EB=B0=A9=EC=8B=9D=20UI=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20-=20MO=EC=97=90=EC=84=9C=20dropdown=20->=20bottomsh?= =?UTF-8?q?eet=20=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CoffeechatInfoForm/index.tsx | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx b/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx index 833b7c404..7b78479db 100644 --- a/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx +++ b/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx @@ -3,6 +3,7 @@ import { SelectV2, TextArea } from '@sopt-makers/ui'; import { Controller, useFormContext } from 'react-hook-form'; import { COFFEECHAT_MOBILE_MEDIA_QUERY } from '@/components/coffeechat/mediaQuery'; +import BottomSheetSelect from '@/components/coffeechat/upload/CoffeechatForm/BottomSheetSelect'; import ChipField from '@/components/coffeechat/upload/CoffeechatForm/ChipField'; import { COFFECHAT_SECTION, @@ -124,23 +125,33 @@ export default function CoffeechatInfoForm() { name='coffeeChatInfo.meetingType' control={control} render={({ field }) => ( -
- option.value === field.value)} - onChange={(value) => field.onChange(value)} - > - - - - - {MEETING_TYPE_OPTIONS.map((option) => ( - - ))} - - -
+ <> + + option.value === field.value)} + onChange={(value) => field.onChange(value)} + > + + + + + {MEETING_TYPE_OPTIONS.map((option) => ( + + ))} + + + + + field.onChange(value)} + /> + + )} /> From c6ca0caaaf35af9f34fcec6bbeb32b329a995d32 Mon Sep 17 00:00:00 2001 From: jerry Date: Thu, 12 Dec 2024 12:50:40 +0900 Subject: [PATCH 5/8] =?UTF-8?q?fix:=20=EC=9E=90=EA=B8=B0=EC=86=8C=EA=B0=9C?= =?UTF-8?q?=20=ED=95=AD=EB=AA=A9)=20=ED=95=84=EC=88=98=20->=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=ED=95=AD=EB=AA=A9=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/coffeechat/page/CoffeechatUploadPage.tsx | 2 +- .../coffeechat/upload/CoffeechatForm/MyInfoForm/index.tsx | 4 +--- src/components/coffeechat/upload/CoffeechatForm/schema.ts | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/coffeechat/page/CoffeechatUploadPage.tsx b/src/components/coffeechat/page/CoffeechatUploadPage.tsx index 71db31cbe..8d1c68d9b 100644 --- a/src/components/coffeechat/page/CoffeechatUploadPage.tsx +++ b/src/components/coffeechat/page/CoffeechatUploadPage.tsx @@ -81,7 +81,7 @@ export default function CoffeechatUploadPage({ uploadType, form, onSubmit }: Cof aside={
- - 자기소개 - + 자기소개 typeof value === 'string' || (Array.isArray(value) && value.length > 0), ) .required('경력을 선택해주세요'), - introduction: yup.string().required('자기소개를 입력해주세요'), }); const coffeeChatInfoSchema = yup.object().shape({ From 369862c17da3d0713243ace417bf1e5c3c660a86 Mon Sep 17 00:00:00 2001 From: jerry Date: Thu, 12 Dec 2024 12:58:42 +0900 Subject: [PATCH 6/8] =?UTF-8?q?refactor:=20MO:=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EB=B6=84=EC=95=BC,=20=EC=BB=A4=ED=94=BC=EC=B1=97=20=EC=A3=BC?= =?UTF-8?q?=EC=A0=9C=20=EB=B0=8F=20=EC=86=8C=EA=B0=9C=20=EC=84=B9=EC=85=98?= =?UTF-8?q?=20chip=20md->sm=EC=9C=BC=EB=A1=9C=20=EC=82=AC=EC=9D=B4?= =?UTF-8?q?=EC=A6=88=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coffeechat/upload/CoffeechatForm/ChipField/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/coffeechat/upload/CoffeechatForm/ChipField/index.tsx b/src/components/coffeechat/upload/CoffeechatForm/ChipField/index.tsx index acd250e81..9362b24a4 100644 --- a/src/components/coffeechat/upload/CoffeechatForm/ChipField/index.tsx +++ b/src/components/coffeechat/upload/CoffeechatForm/ChipField/index.tsx @@ -53,7 +53,7 @@ export default function ChipField({ field, errorMessage, chipList, isSingleSelec - + {chip} From f940635dac9f3fcdeabe669b86cf5c4a850f712e Mon Sep 17 00:00:00 2001 From: jerry Date: Thu, 12 Dec 2024 13:04:05 +0900 Subject: [PATCH 7/8] =?UTF-8?q?chore:=20=EC=BB=A4=ED=94=BC=EC=B1=97=20?= =?UTF-8?q?=EC=A3=BC=EC=A0=9C=20=EB=B0=8F=20=EC=86=8C=EA=B0=9C=20=ED=95=AD?= =?UTF-8?q?=EB=AA=A9)=20placeholder=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CoffeechatForm/CoffeechatInfoForm/index.tsx | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx b/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx index 7b78479db..7b922e2d6 100644 --- a/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx +++ b/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx @@ -84,12 +84,7 @@ export default function CoffeechatInfoForm() { value={field.value ?? ''} maxLength={1000} fixedHeight={189} - lineBreakPlaceholder={[ - '• PM과 서비스기획자로 일하는 방법', - '• 포트폴리오 준비 및 작성 노하우', - '• 직무 전환 시 준비할 것들', - '• 당근, 토스, 넥슨, 하나은행, LG전자 면접 후기', - ]} + lineBreakPlaceholder={['• PM과 서비스 기획자로 일하는 방법', '• 앱잼 전 미리 준비하면 좋은 것']} isError={!!errors.coffeeChatInfo?.topic} errorMessage={errors.coffeeChatInfo?.topic?.message} onChange={(e) => field.onChange(e.target.value)} @@ -101,12 +96,7 @@ export default function CoffeechatInfoForm() { value={field.value ?? ''} maxLength={1000} fixedHeight={176} - lineBreakPlaceholder={[ - '• PM과 서비스기획자로 일하는 방법', - '• 포트폴리오 준비 및 작성 노하우', - '• 직무 전환 시 준비할 것들', - '• 당근, 토스, 넥슨, 하나은행, LG전자 면접 후기', - ]} + lineBreakPlaceholder={['• PM과 서비스 기획자로 일하는 방법', '• 앱잼 전 미리 준비하면 좋은 것']} isError={!!errors.coffeeChatInfo?.topic} errorMessage={errors.coffeeChatInfo?.topic?.message} onChange={(e) => field.onChange(e.target.value)} From 98578864f2eee1b8cef8046dfde7640a3a8f1e3d Mon Sep 17 00:00:00 2001 From: jerry Date: Thu, 12 Dec 2024 13:17:17 +0900 Subject: [PATCH 8/8] =?UTF-8?q?chore:=20=EA=B2=BD=EB=A0=A5=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=ED=95=AD=EB=AA=A9=20dropdown=20=EC=82=AC=EC=9D=B4?= =?UTF-8?q?=EC=A6=88=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coffeechat/upload/CoffeechatForm/MyInfoForm/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/coffeechat/upload/CoffeechatForm/MyInfoForm/index.tsx b/src/components/coffeechat/upload/CoffeechatForm/MyInfoForm/index.tsx index 98fcb894e..763062f2d 100644 --- a/src/components/coffeechat/upload/CoffeechatForm/MyInfoForm/index.tsx +++ b/src/components/coffeechat/upload/CoffeechatForm/MyInfoForm/index.tsx @@ -39,7 +39,7 @@ export default function MyInfoForm() { option.value === field.value)} onChange={(value) => field.onChange(value)}