diff --git a/api/wishes/wishesAPI.ts b/api/wishes/wishesAPI.ts index 28ec9556..a397291d 100644 --- a/api/wishes/wishesAPI.ts +++ b/api/wishes/wishesAPI.ts @@ -2,11 +2,16 @@ import PATH from '../../constant/path'; import { client } from '../common/axios'; import axios from 'axios'; import { SiteDataType } from '@/types/siteDataType'; -import { AccountInfoType, WishesDataInputType } from '@/types/common/input/wishesInput'; +import { + AccountInfoType, + BankInfoInputsType, + WishesDataInputType, +} from '@/types/common/input/wishesInput'; +import { UseFormReturn } from 'react-hook-form'; -export const createWishesLink = async (wishesData: WishesDataInputType) => { - const accessToken = localStorage.getItem('accessToken'); +const ACCESS_TOKEN = localStorage.getItem('accessToken'); +export const createWishesLink = async (wishesData: WishesDataInputType) => { const data = await client.post( `${PATH.API}/${PATH.V1}/${PATH.WISHES}`, { @@ -21,30 +26,29 @@ export const createWishesLink = async (wishesData: WishesDataInputType) => { { headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${accessToken}`, + Authorization: `Bearer ${ACCESS_TOKEN}`, }, }, ); return data; }; -export const editUserAccount = async (accountInfo: AccountInfoType, phone: string) => { - const accessToken = localStorage.getItem('accessToken'); - +export const editUserAccount = async ( + methods: UseFormReturn, +) => { const data = await client.put( `${PATH.API}/${PATH.V1}/${PATH.USER}/${PATH.ACCOUNT}`, { accountInfo: { - name: accountInfo.name, - bank: accountInfo.bankName, - account: accountInfo.account, + name: methods.getValues('name'), + bank: methods.getValues('bankName'), + account: methods.getValues('account'), }, - phone, }, { headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${accessToken}`, + Authorization: `Bearer ${ACCESS_TOKEN}`, }, }, ); diff --git a/components/common/alertTextBox.tsx b/components/common/alertTextBox.tsx index bf223337..39d2612f 100644 --- a/components/common/alertTextBox.tsx +++ b/components/common/alertTextBox.tsx @@ -1,20 +1,21 @@ import { ReactNode } from 'react'; -import { AlertIc } from '@/public/assets/icons'; +import { AlertSuccessIc, AlertWarningIc } from '@/public/assets/icons'; import theme from '@/styles/theme'; import styled from 'styled-components'; import Image from 'next/image'; interface AlertTextBoxProps { + alertSuccess?: boolean; children: ReactNode; } export default function AlertTextBox(props: AlertTextBoxProps) { - const { children } = props; + const { alertSuccess, children } = props; return ( - 경고 - {children} + 알림 아이콘 + {children} ); } @@ -25,9 +26,9 @@ const Styled = { align-items: center; margin-top: 1rem; `, - Text: styled.div` + Text: styled.span<{ alertSuccess?: boolean }>` margin-left: 0.6rem; ${theme.fonts.body12}; - color: ${theme.colors.warning_red}; + color: ${(props) => (props.alertSuccess ? theme.colors.dark_blue : theme.colors.warning_red)}; `, }; diff --git a/components/common/box/imageBox.tsx b/components/common/box/imageBox.tsx index 12b57c04..01f15b3b 100644 --- a/components/common/box/imageBox.tsx +++ b/components/common/box/imageBox.tsx @@ -28,6 +28,8 @@ const StyledImageBox = styled(StyledBox)<{ width?: number; height: number }>` //ImageBox Style System &.imageBox--textarea { + height: 16rem; + border-radius: 1rem; padding: 1.4rem 1.2rem; } @@ -39,8 +41,10 @@ const StyledImageBox = styled(StyledBox)<{ width?: number; height: number }>` justify-content: center; align-items: center; + padding: 0; + border-radius: 1.6rem; - object-fit: cover; + overflow: hidden; } `; diff --git a/components/common/box/index.tsx b/components/common/box/index.tsx index a08c458a..130ed3d3 100644 --- a/components/common/box/index.tsx +++ b/components/common/box/index.tsx @@ -5,18 +5,13 @@ import styled, { CSSProperties } from 'styled-components'; interface BoxProps { boxType?: BoxTypes; colorSystem: ColorSystemType; - boxStyled?: CSSProperties; children: React.ReactNode; } export default function Box(props: BoxProps) { - const { boxType, colorSystem, boxStyled, children } = props; + const { boxType, colorSystem, children } = props; - return ( - - {children} - - ); + return {children}; } type BoxSizeType = 'Small' | 'Half' | 'Large' | 'Image'; @@ -26,7 +21,7 @@ export const BoxSize: Record = { height: '4.6rem', }, Half: { - width: 'calc(100% / 2) - 0.5rem', + width: 'calc(100%/2)', height: '5rem', }, Large: { @@ -59,7 +54,7 @@ export const StyledBox = styled.div` } // Color System - &.gary1_white { + &.gray1_white { background-color: ${theme.colors.gray1}; color: ${theme.colors.white}; } diff --git a/components/common/box/inputBox.tsx b/components/common/box/inputBox.tsx index 54c65fbd..5e0127ad 100644 --- a/components/common/box/inputBox.tsx +++ b/components/common/box/inputBox.tsx @@ -13,8 +13,6 @@ interface InputBoxProps { export default function InputBox(props: PropsWithChildren) { const { width, boxType, colorSystem, children } = props; - console.log(boxType); - return ( {children} @@ -23,6 +21,8 @@ export default function InputBox(props: PropsWithChildren) { } const StyledInputBox = styled(StyledBox)<{ width?: string }>` + height: 5rem; + padding: 1rem 1rem 1rem 1.2rem; border: 0.1rem solid ${theme.colors.main_blue}; border-radius: 1rem; @@ -39,6 +39,16 @@ const StyledInputBox = styled(StyledBox)<{ width?: string }>` align-items: center; } + &.inputBox--calendar { + width: 16rem; + + display: flex; + justify-content: space-between; + align-items: center; + + ${theme.fonts.body14}; + } + &.inputBox--custom { width: ${(props) => props.width}; height: 5rem; diff --git a/components/common/box/itemImageBox.tsx b/components/common/box/itemImageBox.tsx index 47404409..ca351500 100644 --- a/components/common/box/itemImageBox.tsx +++ b/components/common/box/itemImageBox.tsx @@ -1,5 +1,6 @@ import Image from 'next/image'; import ImageBox from './imageBox'; +import styled from 'styled-components'; interface ItemImageBoxProps { src: string; @@ -10,7 +11,7 @@ export default function ItemImageBox(props: ItemImageBoxProps) { const { src, alt } = props; return ( - {alt} + {alt} ); } diff --git a/components/common/calendar/CalendarHeader.tsx b/components/common/calendar/CalendarHeader.tsx new file mode 100644 index 00000000..87c878b9 --- /dev/null +++ b/components/common/calendar/CalendarHeader.tsx @@ -0,0 +1,50 @@ +import styled from 'styled-components'; +import { getMonth, getYear } from 'date-fns'; +import { MONTHS } from '@/constant/dateList'; + + +interface CalendarHeaderProps { + date: Date; + changeYear: (year: number) => void; + changeMonth: (month: number) => void; +} + +export default function CalendarHeader(props: CalendarHeaderProps) { + const { date, changeYear, changeMonth } = props; + + // 연도 range + const years = Array.from( + { length: getYear(new Date()) + 6 - getYear(new Date()) }, + (_, index) => getYear(new Date()) + index, + ); + + return ( + + + 년   + + 월 + + ); +} + +const Styled = { + CalendarHeader: styled.div` + width: 100%; + `, +}; diff --git a/components/common/calendar/calendar.tsx b/components/common/calendar/calendar.tsx index f47b5030..b36f0d87 100644 --- a/components/common/calendar/calendar.tsx +++ b/components/common/calendar/calendar.tsx @@ -1,38 +1,65 @@ -import theme from '@/styles/theme'; -import styled from 'styled-components'; import Image from 'next/image'; -import CustomDatePicker from '../modal/CustomDatePicker'; +import { ko } from 'date-fns/locale'; import InputBox from '../box/inputBox'; +import styled from 'styled-components'; +import theme from '@/styles/theme'; +import { ColorSystemType } from '@/types/common/box/boxStyleType'; +import { UseFormReturn } from 'react-hook-form'; +import { WishesDataInputType } from '@/types/common/input/wishesInput'; +import { CalendarGreyIc, CalendarIc } from '@/public/assets/icons'; +import DatePicker from 'react-datepicker'; +import 'react-datepicker/dist/react-datepicker.css'; +import CalendarHeader from './CalendarHeader'; +import { getDate } from '@/utils/common/getDate'; interface CalendarProps { date: Date; - changeStartDate?: (value: Date) => void; - calendarIcon: any; + methods: UseFormReturn; + disable: boolean; + colorSystem: ColorSystemType; readOnly: boolean; } export default function Calendar(props: CalendarProps) { - const { date, changeStartDate, calendarIcon, readOnly } = props; + const { date, methods, disable, colorSystem, readOnly } = props; + + const handleChangeDate = (selectedDate: Date) => { + methods.setValue('startDate', selectedDate); + methods.setValue('endDate', getDate(selectedDate, 7)); + }; return ( - - - - 캘린더 아이콘 - + + + ( + + )} + locale={ko} + dateFormat="yyyy.MM.dd" + selected={new Date(date)} + onChange={handleChangeDate} + minDate={new Date()} + selectsEnd + readOnly={readOnly} + className="react-datepicker__input-container" + /> + {/* */} + + 캘린더 아이콘 ); } const Styled = { - CalendarWrapper: styled.div` + Wrapper: styled.div` display: flex; + justify-content: space-between; + align-items: center; width: 100%; height: 100%; ${theme.fonts.body12}; - - cursor: pointer; `, }; diff --git a/components/common/input/input.tsx b/components/common/input/input.tsx index 5d280262..212578a1 100644 --- a/components/common/input/input.tsx +++ b/components/common/input/input.tsx @@ -1,11 +1,12 @@ import theme from '@/styles/theme'; import { WishesDataInputType } from '@/types/common/input/wishesInput'; import { PropsWithChildren } from 'react'; -import { UseFormRegisterReturn } from 'react-hook-form'; +import { FieldError, UseFormRegisterReturn } from 'react-hook-form'; import styled from 'styled-components'; import InputBox from '../box/inputBox'; import { InputBoxTypes } from '@/types/common/box/boxStyleType'; import { CakesDataInputType } from '@/types/common/input/cakesInput'; +import AlertTextBox from '../alertTextBox'; interface InputProps { width?: string; @@ -13,26 +14,31 @@ interface InputProps { placeholder?: string; readOnly?: boolean; register: UseFormRegisterReturn; + errors?: FieldError; } export default function Input(props: PropsWithChildren) { - const { width, boxType, placeholder, readOnly, register, children } = props; + const { width, boxType, placeholder, readOnly, register, errors, children } = props; return ( - - - {children} - + <> + + + {children} + + {errors?.message && {errors.message}} + ); } -const StyledInput = styled.input` - ${theme.fonts.body12}; - color: ${theme.colors.dark_blue}; +export const StyledInput = styled.input` width: 100%; height: 100%; + + ${theme.fonts.body12}; + color: ${theme.colors.dark_blue}; `; diff --git a/components/common/mainView.tsx b/components/common/mainView.tsx index f29b252d..dc9c8756 100644 --- a/components/common/mainView.tsx +++ b/components/common/mainView.tsx @@ -4,7 +4,7 @@ import theme from '@/styles/theme'; import { KakaoLoginIc, WideArrowDownIc } from '@/public/assets/icons'; import { MainLoginImg } from '@/public/assets/images'; import GuideModal from '@/components/common/modal/GuideModal'; -import Modal from '@/components/common/modal/modal'; +import Modal from '@/components/common/modal'; import useModal from '@/hooks/common/useModal'; interface MainViewProps { diff --git a/components/common/modal/BankInput.tsx b/components/common/modal/BankInput.tsx index d879c14d..d45e4053 100644 --- a/components/common/modal/BankInput.tsx +++ b/components/common/modal/BankInput.tsx @@ -1,18 +1,19 @@ import useModal from '@/hooks/common/useModal'; -import Modal from './modal'; +import Modal from '.'; import BankModal from './BankModal'; import styled from 'styled-components'; import Button from '../button'; import { UseFormReturn } from 'react-hook-form'; import Input from '../input/input'; -import { WishesDataInputType } from '@/types/common/input/wishesInput'; +import { BankInfoInputsType } from '@/types/common/input/wishesInput'; import { ArrowDownIc } from '@/public/assets/icons'; import Image from 'next/image'; import { StyledBox } from '../box'; import theme from '@/styles/theme'; +import AlertTextBox from '../alertTextBox'; interface BankInputProps { - methods: UseFormReturn; + methods: UseFormReturn; } export default function BankInput(props: BankInputProps) { @@ -30,7 +31,7 @@ export default function BankInput(props: BankInputProps) { - + 더 보기 @@ -47,12 +48,14 @@ export default function BankInput(props: BankInputProps) { {'계좌번호 확인'} + + {/* 조건 기능 추가 */} + {/* {{true ? '정상 계좌입니다' : '존재하지 않는 계좌번호입니다'}} */} - {/* 기능구현 이후 수정해야하는 부분 */} {isOpen && ( - + )} diff --git a/components/common/modal/BankModal.tsx b/components/common/modal/BankModal.tsx index 52d66ffb..d661f859 100644 --- a/components/common/modal/BankModal.tsx +++ b/components/common/modal/BankModal.tsx @@ -2,17 +2,19 @@ import styled from 'styled-components'; import Image from 'next/image'; import theme from '@/styles/theme'; import { BANK_LIST } from '@/constant/bankList'; -import { UseFormRegisterReturn } from 'react-hook-form'; +import { BankInfoInputsType } from '@/types/common/input/wishesInput'; +import { UseFormReturn } from 'react-hook-form'; interface BankModalProps { handleToggle: () => void; - register: UseFormRegisterReturn<'bankName'>; + methods: UseFormReturn; } export default function BankModal(props: BankModalProps) { - const { handleToggle, register } = props; + const { handleToggle, methods } = props; const handleChangeBankName = (input: string) => { + methods.setValue('bankName', input); handleToggle(); }; @@ -22,7 +24,7 @@ export default function BankModal(props: BankModalProps) { {BANK_LIST.map((bank) => ( - + handleChangeBankName(bank.name)}> {`${bank.name} diff --git a/components/common/modal/CustomDatePicker.tsx b/components/common/modal/CustomDatePicker.tsx deleted file mode 100644 index 743e284c..00000000 --- a/components/common/modal/CustomDatePicker.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import styled from 'styled-components'; -import DatePicker from 'react-datepicker'; -import 'react-datepicker/dist/react-datepicker.css'; -import { ko } from 'date-fns/locale'; -import { getMonth, getYear, isBefore } from 'date-fns'; -import { MONTHS } from '@/constant/dateList'; - -interface CustomDatePickerProps { - date: Date; - changeStartDate?: (value: Date) => void; - readOnly: boolean; -} - -export default function CustomDatePicker(props: CustomDatePickerProps) { - const { date, changeStartDate, readOnly } = props; - - // 연도 range - const years = Array.from( - { length: getYear(new Date()) + 6 - getYear(new Date()) }, - (_, index) => getYear(new Date()) + index, - ); - - const handleDateChange = (date: Date) => { - const today = new Date(); - const yesterday = new Date(today.setDate(today.getDate() - 1)); - if (date && isBefore(date, yesterday)) { - // 선택한 날짜가 현재 날짜보다 예전인 경우 - alert('선택하신 날짜는 현재 날짜보다 이전입니다. 유효한 날짜를 선택해주세요.'); - return; - } - - changeStartDate && changeStartDate(date); - }; - - return ( - - ( - - - 년   - - 월 - - )} - locale={ko} - dateFormat="yyyy.MM.dd" - selected={new Date(date)} - onChange={handleDateChange} - selectsEnd - endDate={new Date(date)} - readOnly={readOnly} - /> - - ); -} - -const Styled = { - Container: styled.div` - display: flex; - justify-content: center; - align-items: center; - - cursor: pointer; - `, - - CalendarHeader: styled.div` - width: 100%; - `, -}; diff --git a/components/common/modal/TermsModal.tsx b/components/common/modal/TermsModal.tsx deleted file mode 100644 index d935b87c..00000000 --- a/components/common/modal/TermsModal.tsx +++ /dev/null @@ -1,164 +0,0 @@ -import { useEffect, useState } from 'react'; -import styled from 'styled-components'; -import Image from 'next/image'; -import theme from '@/styles/theme'; -import IconButton from '@/components/common/button/iconButton'; -import { CloseWhiteIc, DetailCloseIc, DetailOpenIc } from '@/public/assets/icons'; - -interface TermsModalProps { - handleToggle: () => void; - changeIsAgreed: (isChecked: boolean) => void; -} - -export default function TermsModal(props: TermsModalProps) { - const { handleToggle, changeIsAgreed } = props; - - const [isHidden, setIsHidden] = useState(true); - const [isChecked, setIsChecked] = useState(false); - - useEffect(() => { - changeIsAgreed(false); - }, []); - - const handleMoreViewToggle = () => { - setIsHidden(!isHidden); - }; - - const handleCheckbox = () => { - setIsChecked(!isChecked); - changeIsAgreed(!isChecked); - }; - - return ( - - - - - - - - - '조물주보다 생일선물주'는 카카오페이 결제 -
- 서비스를 연동하여 펀딩 총 금액의 3.4%를 -
- 수수료를 받고 있습니다. -
- 펀딩액 정산 시 차감되어 입금됩니다. -
- - - {isHidden ? ( - 자세히 보기 - ) : ( - 닫기 - )} - - {!isHidden && ( - - '조물주보다 생일선물주'는 사용자분들의 편리한 -
- 결제를 위해 카카오페이 결제를 연동하였습니다. -
- 이에 해당 서비스는 카카오페이 가맹점으로 다음과 -
- 같은 수수료 정책을 적용 받고 있습니다. -
-
- 1. 서비스 이용 수수료란, 카카오 페이구매 시
- 상품주문건별로 부과되는 수수료 입니다. -
- 2. 카카오페이 서비스 독립몰의 수수료는 최대
- 3.4%가 적용됩니다. -
※ 수수료는 부가세가 포함된 비율입니다. -
- )} - - - - 동의하고, 소원링크 생성하기 - -
-
-
- ); -} - -const Styled = { - Container: styled.div` - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - display: flex; - justify-content: center; - `, - - BoxContainer: styled.div` - display: flex; - flex-direction: column; - align-items: flex-end; - `, - - ContentContainer: styled.div` - position: relative; - width: 32rem; - background: ${theme.colors.pastel_blue}; - padding: 3rem 3.9rem; - border-radius: 1.6rem; - `, - - ButtonContainer: styled.div` - position: relative; - margin: 6.4rem 0 2.3rem; - `, - - About: styled.div` - font-family: 'Pretendard'; - font-weight: 700; - font-size: 14px; - line-height: 150%; - align-items: center; - text-align: center; - color: ${theme.colors.dark_blue}; - margin-bottom: 2rem; - `, - - AboutDetail: styled.div` - font-family: 'Pretendard'; - font-weight: 500; - font-size: 12px; - line-height: 150%; - align-items: center; - text-align: center; - color: ${theme.colors.dark_blue}; - opacity: 50%; - margin-top: 2rem; - `, - - CheckContainer: styled.div` - ${theme.fonts.body14}; - color: ${theme.colors.dark_blue}; - display: flex; - justify-content: center; - margin-top: 2.5rem; - `, - - DetailButton: styled.a` - display: flex; - justify-content: center; - `, - - Checkbox: styled.input.attrs({ type: 'checkbox' })` - width: 1.4rem; - height: 1.4rem; - border: 1px solid ${theme.colors.dark_blue}; - margin: 0 1rem 0.5rem; - cursor: pointer; - &:checked { - background-color: ${theme.colors.dark_blue}; - } - appearance: none; - `, -}; diff --git a/components/common/modal/modal.tsx b/components/common/modal/index.tsx similarity index 100% rename from components/common/modal/modal.tsx rename to components/common/modal/index.tsx diff --git a/components/main/button.tsx b/components/main/button.tsx deleted file mode 100644 index 324d0175..00000000 --- a/components/main/button.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import router from 'next/router'; -import theme from '@/styles/theme'; - -import ShareModal from '../common/modal/ShareModal'; -import useModal from '@/hooks/common/useModal'; -import Modal from '../common/modal/modal'; - -interface ButtonProps { - wishStatus: string; -} - -export default function Button(props: ButtonProps) { - const { wishStatus } = props; - const { isOpen, handleToggle } = useModal(); - - // const Button = () => { - // if (wishStatus === 'before') { - // return ( - // - // ); - // } else if (wishStatus === 'while') { - // return ( - // - // ); - // } else if (wishStatus === 'end') { - // return null; - // } else { - // return ( - // - // 소원 링크 생성하기 - // - // ); - // } - // }; - - const handleMovePage = () => { - router.push('/wishes'); - }; - - return ( - <> - {/* + ); + }; + return ( <>
- - + + + ); +} + +const Styled = { + ButtonWrapper: styled.div` + display: flex; + justify-content: space-between; + gap: 0.6rem; + + margin-bottom: 4.6rem; + `, +}; diff --git a/components/wishes/common/wishesStepTitle.tsx b/components/wishes/common/wishesStepTitle.tsx new file mode 100644 index 00000000..93ba8ce6 --- /dev/null +++ b/components/wishes/common/wishesStepTitle.tsx @@ -0,0 +1,35 @@ +import { WishesFormPresentIc } from '@/public/assets/icons'; +import theme from '@/styles/theme'; +import Image from 'next/image'; +import styled from 'styled-components'; + +interface WishesStepTitleProps { + title: string; +} + +export default function WishesStepTitle(props: WishesStepTitleProps) { + const { title } = props; + return ( + + 선물 이미지 + {title}, + + ); +} + +const Styled = { + Title: styled.h1` + ${theme.fonts.headline24_100}; + color: ${theme.colors.main_blue}; + + margin-left: 1rem; + `, + + TitleWrapper: styled.div` + display: flex; + + height: 2.4rem; + + margin: 2.4rem 0 2rem; + `, +}; diff --git a/components/wishes/wishesForm/BankInfo.tsx b/components/wishes/wishesForm/BankInfo.tsx index b11e5177..29b28c4a 100644 --- a/components/wishes/wishesForm/BankInfo.tsx +++ b/components/wishes/wishesForm/BankInfo.tsx @@ -1,20 +1,40 @@ import { editUserAccount, getUserAccount } from '@/api/wishes/wishesAPI'; import { useForm } from 'react-hook-form'; -import Button from '@/components/common/button'; import InputContainer from '@/components/common/input/inputContainer'; import BankInput from '@/components/common/modal/BankInput'; import { QUERY_KEY } from '@/constant/queryKey'; import { useCreateWishesLink } from '@/hooks/queries/wishes/useCreateWishesLink'; import { BankInfoInputsType } from '@/types/common/input/wishesInput'; -import { useRouter } from 'next/router'; import { useMutation, useQuery } from 'react-query'; -import styled, { CSSProperties } from 'styled-components'; +import styled from 'styled-components'; import CheckBox from '@/components/common/checkBox'; import useCheckBox from '@/hooks/common/useCheckBox'; import Input from '@/components/common/input/input'; -import Box from '@/components/common/box'; +import { StyledBox } from '@/components/common/box'; +import WishesStepTitle from '../common/wishesStepTitle'; +import WishesStepBtn from '../common/wishesStepBtn'; +import { ColorSystemType } from '@/types/common/box/boxStyleType'; +import theme from '@/styles/theme'; +import { useEffect } from 'react'; +import { validation } from '@/validation/input'; +import AlertTextBox from '@/components/common/alertTextBox'; + +interface BankInfoProps { + wishesStep: { + stepIndex: number; + prevState: boolean; + nextState: boolean; + changePrevState: (state: boolean) => void; + changeNextState: (state: boolean) => void; + handleNextStep: () => void; + handlePrevStep: () => void; + getNextBtnColor: (state: boolean) => ColorSystemType; + getPrevBtnColor: (state: boolean) => ColorSystemType; + }; +} -export default function BankInfo() { +export default function BankInfo(props: BankInfoProps) { + const { wishesStep } = props; const { data } = useQuery(QUERY_KEY.ITEM_DATA, getUserAccount); const methods = useForm({ @@ -31,69 +51,81 @@ export default function BankInfo() { const { postWishesData } = useCreateWishesLink(); - const router = useRouter(); - - // const { mutate } = useMutation( - // () => editUserAccount({ name, bankName, account }, getValues('phone')), - // { - // onSuccess: () => { - // router.push('/wishes/share'); - // }, - // }, - // ); + const { mutate } = useMutation(() => editUserAccount(methods), { + onSuccess: () => { + router.push('/wishes/share'); + }, + }); - const uploadAccount = () => {}; + useEffect(() => { + if ( + checkBoxState && + methods.getValues('name') && + methods.getValues('bankName') && + methods.getValues('account') && + methods.getValues('phone') && + validation.isCorrectPhoneNumber(methods.getValues('phone')) + ) { + wishesStep.changeNextState(true); + } else { + wishesStep.changeNextState(false); + } + }, [methods.watch()]); return ( - -
- - {'※ 계좌번호, 연락처에 대한 허위기재와 오기로 인해 발생되는 문제는 책임지지 않습니다.'} - - - - - - - - - - - + <> + + +
+ + {'※ 계좌번호, 연락처에 대한 허위기재와 오기로 인해 발생되는 문제는 책임지지 않습니다.'} + + + + + + + + + + + + {!validation.isIncludeHyphen(methods.watch('phone')) || + (!validation.isCorrectPhoneNumber(methods.watch('phone')) && + methods.watch('phone') !== '' && ( + {'올바른 연락처를 입력해주세요'} + ))} + - -
- - - - -
+
+ + {}} /> +
+ ); } -const BoxStyled: CSSProperties = { - display: 'flex', - flexDirection: 'column', - justifyContent: 'space-between', - - width: '100%', - height: '9.8rem', - padding: '1.2rem', +const GuideBox = styled(StyledBox)` + display: flex; + flex-direction: column; + justify-content: space-between; - fontSize: '14px', - fontFamily: 'Galmuri11', - lineHeight: '140%', + width: 100%; + height: 9.8rem; - textAlign: 'left', + ${theme.fonts.body14}; + text-align: left; - marginBottom: '2.4rem', -}; + margin-bottom: 2.4rem; + padding: 1.2rem; +`; const Styled = { Container: styled.div` diff --git a/components/wishes/wishesForm/Preview.tsx b/components/wishes/wishesForm/Preview.tsx index 524e7b15..8dbfb0ea 100644 --- a/components/wishes/wishesForm/Preview.tsx +++ b/components/wishes/wishesForm/Preview.tsx @@ -2,11 +2,6 @@ import InputContainer from '@/components/common/input/inputContainer'; import TextareaBox from '@/components/common/input/textareaBox'; import styled from 'styled-components'; import theme from '@/styles/theme'; -import Button from '@/components/common/button'; -import { useEffect, useState } from 'react'; -import Modal from '@/components/common/modal/modal'; -import TermsModal from '@/components/common/modal/TermsModal'; -import useModal from '@/hooks/common/useModal'; import { convertMoneyText } from '@/utils/common/convertMoneyText'; import { convertDateToString } from '@/utils/common/getDate'; import { useRecoilValue } from 'recoil'; @@ -15,60 +10,55 @@ import Input from '@/components/common/input/input'; import { UseFormReturn } from 'react-hook-form'; import { WishesDataInputType } from '@/types/common/input/wishesInput'; import ItemImageBox from '@/components/common/box/itemImageBox'; +import WishesStepTitle from '../common/wishesStepTitle'; +import WishesStepBtn from '../common/wishesStepBtn'; interface PreviewProps { methods: UseFormReturn; - handleNextStep: () => void; + wishesStep: { + stepIndex: number; + prevState: boolean; + nextState: boolean; + changePrevState: (state: boolean) => void; + changeNextState: (state: boolean) => void; + handleNextStep: () => void; + handlePrevStep: () => void; + getNextBtnColor: (state: boolean) => ColorSystemType; + getPrevBtnColor: (state: boolean) => ColorSystemType; + }; } export default function Preview(props: PreviewProps) { - const { methods, handleNextStep } = props; - - const wishesData = useRecoilValue(WishesData); - const { isOpen, handleToggle } = useModal(); - const [isAgreed, setIsAgreed] = useState(false); - - useEffect(() => { - isAgreed && handleNextStep(); - }, [isAgreed]); - - const changeIsAgreed = (isChecked: boolean) => { - setIsAgreed(isChecked); - }; + const { methods, wishesStep } = props; return ( - -
- - {convertDateToString(wishesData.startDate)}~{convertDateToString(wishesData.endDate)} - - - - - - 가격 : {convertMoneyText(String(wishesData.price))} - - - - - - - - - - - - - - -
- - - - -
+ <> + + +
+ + {/* {convertDateToString(wishesData.startDate)}~{convertDateToString(wishesData.endDate)} */} + + + + + + 가격 : {convertMoneyText(methods.getValues('price').toString())} + + + + + + + + + + +
+ + +
+ ); } diff --git a/components/wishes/wishesForm/UploadGift.tsx b/components/wishes/wishesForm/UploadGift.tsx index 8d5d91ea..4998631f 100644 --- a/components/wishes/wishesForm/UploadGift.tsx +++ b/components/wishes/wishesForm/UploadGift.tsx @@ -48,7 +48,10 @@ export default function UploadGift(props: UploadGiftProps) { - + ; - handleNextStep: () => void; + wishesStep: { + stepIndex: number; + prevState: boolean; + nextState: boolean; + changePrevState: (state: boolean) => void; + changeNextState: (state: boolean) => void; + handleNextStep: () => void; + handlePrevStep: () => void; + getNextBtnColor: (state: boolean) => ColorSystemType; + getPrevBtnColor: (state: boolean) => ColorSystemType; + }; } export default function WishesStep2(props: WishesStep2Props) { - const { methods, handleNextStep } = props; + const { methods, wishesStep } = props; - const [startDate, setStartDate] = useState(getDate(TODAY, 0)); + const [startDate, setStartDate] = useState(new Date()); const [endDate, setEndDate] = useState(getDate(startDate, 7)); useEffect(() => { setEndDate(getDate(startDate, 7)); }, [startDate]); + useEffect(() => { + if ( + methods.getValues('title') && + methods.getValues('hint').length !== 0 && + methods.getValues('hint').length <= 300 + ) { + wishesStep.changeNextState(true); + } else { + wishesStep.changeNextState(false); + } + }, [methods.watch()]); + const changeStartDate = (value: Date) => { setStartDate(value); }; - const nextStep = () => { - //아이템 데이터의 유효성 정보에 대한 체크 조건 추가해야됨 - - handleNextStep(); - }; + const onSubmit = () => {}; return ( - -
- - - - - - - - - - - {/* 시작일 */} - - + + +
+ + + + + + - - {/* 종료일 */} - - - - -
- - - - -
+
+ + + + {/* 시작일 */} + + {/* 종료일 */} + + + +
+ + +
+ ); } @@ -93,6 +111,9 @@ const Styled = { CalendarWrapper: styled.div` display: flex; justify-content: space-between; + gap: 0.6rem; + + width: 100%; `, ButtonWrapper: styled.div` diff --git a/components/wishes/wishesForm/WishesStep1.tsx b/components/wishes/wishesForm/WishesStep1.tsx index daa695af..dbe61e5c 100644 --- a/components/wishes/wishesForm/WishesStep1.tsx +++ b/components/wishes/wishesForm/WishesStep1.tsx @@ -1,8 +1,7 @@ import InputContainer from '@/components/common/input/inputContainer'; import ItemLink from './itemLink'; import { LIMIT_TEXT } from '@/constant/limitText'; -import { useState } from 'react'; -import Button from '@/components/common/button'; +import { PropsWithChildren, useEffect, useState } from 'react'; import styled from 'styled-components'; import useUploadItemInfo from '@/hooks/wishes/useUploadItemInfo'; import UploadTypeToggleBtn from '@/components/common/uploadTypeToggleBtn'; @@ -12,68 +11,106 @@ import Input from '@/components/common/input/input'; import InputLength from '@/components/common/input/inputLength'; import UploadGift from './UploadGift'; import SiteList from './SiteList'; +import { initial_RULES, validation } from '@/validation/input'; +import { ColorSystemType } from '@/types/common/box/boxStyleType'; +import WishesStepTitle from '../common/wishesStepTitle'; +import WishesStepBtn from '../common/wishesStepBtn'; interface WishesStep1Props { methods: UseFormReturn; - handleNextStep: () => void; + wishesStep: { + stepIndex: number; + prevState: boolean; + nextState: boolean; + changePrevState: (state: boolean) => void; + changeNextState: (state: boolean) => void; + handleNextStep: () => void; + handlePrevStep: () => void; + getNextBtnColor: (state: boolean) => ColorSystemType; + getPrevBtnColor: (state: boolean) => ColorSystemType; + }; } -export default function WishesStep1(props: WishesStep1Props) { - const { methods, handleNextStep } = props; +export default function WishesStep1(props: PropsWithChildren) { + const { methods, wishesStep } = props; const { imageFile, preSignedImageURL, uploadImageFile } = useUploadItemInfo(); const [isLinkLoadType, setIsLinkLoadType] = useState(true); //false : 링크 불러오기 true : 직접 불러오기 - const nextStep = () => { - handleNextStep(); - }; - const handleLoadTypeToggle = (state: boolean) => { setIsLinkLoadType(state); }; + useEffect(() => { + wishesStep.changeNextState(false); + + if (isLinkLoadType) { + if ( + validation.isCorrectSite(methods.getValues('linkURL')) && + methods.getValues('initial').length !== 0 && + methods.getValues('initial').length <= 15 + ) { + wishesStep.changeNextState(true); + } + } else { + if ( + methods.getValues('initial').length !== 0 && + methods.getValues('initial').length <= 15 && + imageFile && + methods.getValues('price') !== '' && + Number(methods.getValues('price')) <= 12000000 + ) { + wishesStep.changeNextState(true); + } + } + }, [methods.watch()]); + + const onSubmit = () => {}; + return ( - -
- - - {isLinkLoadType ? ( - <> - - - - ) : ( - + + +
+ - )} - - - - + + + + ) : ( + - - -
- - - - -
+ )} + + + + + + +
+ + +
+ ); } @@ -103,8 +140,4 @@ const Styled = { FileInput: styled.input` display: none; `, - - ButtonWrapper: styled.div` - margin-bottom: 4.6rem; - `, }; diff --git a/components/wishes/wishesForm/index.tsx b/components/wishes/wishesForm/index.tsx index f903269a..2fd6d10e 100644 --- a/components/wishes/wishesForm/index.tsx +++ b/components/wishes/wishesForm/index.tsx @@ -1,86 +1,40 @@ import WishesStep1 from './WishesStep1'; import styled from 'styled-components'; import theme from '@/styles/theme'; -import { WishesFormPresentIc } from '@/public/assets/icons'; -import Image from 'next/image'; import useWishesStep from '@/hooks/wishes/useWisehsStep'; import WishesStep2 from './WisehsStep2'; import Preview from './Preview'; import BankInfo from './BankInfo'; -import { useRouter } from 'next/router'; + import { useForm } from 'react-hook-form'; import { WishesDataInputType } from '@/types/common/input/wishesInput'; +import { getDate } from '@/utils/common/getDate'; export default function WishesFormContainer() { - const { stepIndex, handleNextStep, handlePrevStep } = useWishesStep(); - const router = useRouter(); - - const handleBackBtnClick = () => { - stepIndex === 1 ? router.back() : handlePrevStep(); - }; + const wishesStep = { ...useWishesStep() }; const methods = useForm({ defaultValues: { linkURL: '', imageURL: '', - price: 0, + price: '', initial: '', title: '', hint: '', - phone: '', - mobileCode: '', - name: '', - bankName: '', - account: '', + startDate: new Date(), + endDate: getDate(new Date(), 7), }, }); return ( - {/* Title */} - {/* - { - { - 1: 소원링크 생성하기, - 2: 소원링크 생성하기, - 3: 소원링크 화면 미리보기, - 4: 계좌번호 및 연락처 입력하기, - }[stepIndex] - } - */} - { { - 1: ( - <> - - 선물 이미지 - 소원링크 생성하기, - - - - ), - 2: ( - <> - - 선물 이미지 - 소원링크 생성하기, - - , - - ), - 3: ( - <> - - 선물 이미지 - 소원링크 화면 미리보기, - - , - - ), - - 4: , - }[stepIndex] + 1: , + 2: , + 3: , + 4: , + }[wishesStep.stepIndex] } ); diff --git a/components/wishes/wishesForm/itemLink.tsx b/components/wishes/wishesForm/itemLink.tsx index a30beff6..b05b938d 100644 --- a/components/wishes/wishesForm/itemLink.tsx +++ b/components/wishes/wishesForm/itemLink.tsx @@ -1,6 +1,6 @@ import theme from '@/styles/theme'; import styled from 'styled-components'; -import { validation } from '@/validation/input'; +import { REGEX, inputRules, linkURL_RULES, validation } from '@/validation/input'; import { useState } from 'react'; import { convertMoneyText } from '@/utils/common/convertMoneyText'; import { QUERY_KEY } from '@/constant/queryKey'; @@ -12,9 +12,10 @@ import Input from '@/components/common/input/input'; import { UseFormReturn } from 'react-hook-form'; import AlertTextBox from '@/components/common/alertTextBox'; import ItemImageBox from '@/components/common/box/itemImageBox'; +import { WishesDataInputType } from '@/types/common/input/wishesInput'; interface ItemLinkProps { - methods: UseFormReturn; + methods: UseFormReturn; } export default function ItemLink(props: ItemLinkProps) { @@ -56,6 +57,7 @@ export default function ItemLink(props: ItemLinkProps) { @@ -64,7 +66,11 @@ export default function ItemLink(props: ItemLinkProps) { )} {imageURL && ( - 가격 : {convertMoneyText(String(price))}원 + + + 가격 : {convertMoneyText(price)}원 + + )} ); @@ -83,4 +89,8 @@ const Styled = { cursor: pointer; margin: 0 1rem 1rem 0; `, + + ItemImageWrapper: styled.div` + margin-top: 1.2rem; + `, }; diff --git a/constant/siteList.ts b/constant/siteList.ts index bf0ecd54..3b37ffe9 100644 --- a/constant/siteList.ts +++ b/constant/siteList.ts @@ -1,4 +1,4 @@ -import { NaverShoppingLogoImg, TwentynineLogoImg } from '@/public/assets/images'; +import { TwentynineLogoImg } from '@/public/assets/images'; import { SiteDataType } from '@/types/siteDataType'; export const SITE_LIST = { @@ -9,11 +9,4 @@ export const SITE_LIST = { IMAGE_TAG: 'ewptmlp5', PRICE_TAG: 'ent7twr4', }, - // NAVER_SHOP: { - // NAME: 'naverShopping', - // LINK: 'https://shopping.naver.com/', - // LOGO: NaverShoppingLogoImg, - // IMAGE_TAG: 'image_thumb__IB9B3', // 맞는지 잘 모름... - // PRICE_TAG: 'lowestPrice_num__A5gM9', // 맞는지 잘 모름... - // }, }; diff --git a/hooks/mypage/useInitEditWishesInfo.tsx b/hooks/mypage/useInitEditWishesInfo.tsx deleted file mode 100644 index f40ecb34..00000000 --- a/hooks/mypage/useInitEditWishesInfo.tsx +++ /dev/null @@ -1,144 +0,0 @@ -import { getEditWishesInfo } from '@/api/mypage/mypageAPI'; -import { QUERY_KEY } from '@/constant/queryKey'; -import { useQuery } from 'react-query'; -import { useEffect, useState } from 'react'; -import useInput from '../common/useInput'; -import { getDate } from '@/utils/common/getDate'; -import useUploadItemInfo from '../wishes/useUploadItemInfo'; -import { LIMIT_TEXT } from '@/constant/limitText'; -import { useGetItemInfo } from '../queries/wishes/useGetItemInfo'; - -export default function useInitEditWishesInfo() { - const { data, isSuccess: isGetEditWishesInfoSuccess } = useQuery( - QUERY_KEY.USER, - getEditWishesInfo, - ); - - const wishesStatus = data?.status; - - const [title, handleChangeTitle, setTitle] = useInput('', LIMIT_TEXT[20]); - const [initial, handleChangeInitial, setInitial] = useInput('', LIMIT_TEXT[15]); - - const [startDate, setStartDate] = useState(new Date()); - const [endDate, setEndDate] = useState(new Date()); - - const [name, handleChangeName, setName] = useInput(''); - const [bankName, setBankName] = useState(''); - const [account, handleChangeAccount, setAccount] = useInput(''); - const [phone, handleChangePhone, setPhone] = useInput(''); - - const { - linkURL, - handleChangeLinkURL, - changeLinkURL, - imageURL, - changeImageURL, - price, - changePrice, - } = useGetItemInfo(); - - const { preSignedImageURL, setPreSignedImageURL, uploadImageFile } = useUploadItemInfo(); - const [isLinkLoadType, setIsLinkLoadType] = useState(true); //false : 링크 불러오기 true : 직접 불러오기 - const [selfInputPrice, handleChangeSelfInputPrice, setSelfInputPrice] = useInput( - '', - LIMIT_TEXT[15], - ); - const [hint, handleChangeHint, setHint] = useInput('', LIMIT_TEXT.DESCRIPTION); - - useEffect(() => { - if (data) { - setStartDate(data?.startDate); - setEndDate(data?.endDate); - setPhone(data?.phone); - setTitle(data?.title); - setHint(data?.hint); - setInitial(data?.initial); - changeLinkURL(data?.imageUrl); - setPreSignedImageURL(data?.imageUrl); - setSelfInputPrice(data?.price); - changeImageURL(data?.imageUrl); - changePrice(data?.price); - setName(data?.accountInfo?.name); - setBankName(data?.accountInfo?.bank); - setAccount(data?.accountInfo?.account); - } - }, [data]); - - useEffect(() => { - setEndDate(getDate(startDate, 7)); - }, [startDate]); - - const changeBankName = (input: string) => { - setBankName(input); - }; - - const changeStartDate = (value: Date) => { - setStartDate(value); - }; - - const handleLoadTypeToggle = (state: boolean) => { - setIsLinkLoadType(state); - }; - - return { - title: { - title, - handleChangeTitle, - }, - initial: { - initial, - handleChangeInitial, - }, - startDate: { - startDate, - changeStartDate, - }, - endDate, - bankInfo: { - name, - handleChangeName, - bankName, - changeBankName, - account, - handleChangeAccount, - }, - - phone: { - phone, - handleChangePhone, - }, - hint: { - hint, - handleChangeHint, - }, - itemLink: { - linkURL, - handleChangeLinkURL, - imageURL, - changeImageURL, - price, - changePrice, - }, - image: { - preSignedImageURL, - uploadImageFile, - }, - - isLinkLoadType: { - isLinkLoadType, - handleLoadTypeToggle, - }, - - selfInputPrice: { - selfInputPrice, - handleChangeSelfInputPrice, - }, - price: data?.price, - - wishesStatus, - - isGetEditWishesInfoSuccess, - - data, - }; -} diff --git a/hooks/wishes/useWisehsStep.ts b/hooks/wishes/useWisehsStep.ts index b75305ab..ec4bab11 100644 --- a/hooks/wishes/useWisehsStep.ts +++ b/hooks/wishes/useWisehsStep.ts @@ -1,15 +1,60 @@ -import { useState } from 'react'; +import { ColorSystemType } from '@/types/common/box/boxStyleType'; +import { useEffect, useState } from 'react'; export default function useWishesStep() { - const [stepIndex, setStepIndex] = useState(1); + const [stepIndex, setStepIndex] = useState(2); + const [prevState, setPrevState] = useState(false); + const [nextState, setNextState] = useState(false); + + useEffect(() => { + if (stepIndex === 1) { + setPrevState(false); + } else { + setPrevState(true); + } + }, [stepIndex]); const handleNextStep = () => { - setStepIndex((prev) => (prev += 1)); + if (stepIndex < 4) { + setStepIndex((prev) => (prev += 1)); + } }; const handlePrevStep = () => { - setStepIndex((prev) => (prev -= 1)); + if (stepIndex > 1) { + setStepIndex((prev) => (prev -= 1)); + } + + if (stepIndex === 2) { + setPrevState(false); + } + }; + + const changePrevState = (state: boolean) => { + setPrevState(state); + }; + + const changeNextState = (state: boolean) => { + setNextState(state); }; - return { stepIndex, handleNextStep, handlePrevStep }; + const getNextBtnColor = (state: boolean): ColorSystemType => { + return state ? 'mainBlue_white' : 'gray1_white'; + }; + + const getPrevBtnColor = (state: boolean): ColorSystemType => { + return state ? 'pastelBlue_mainBlue' : 'gray1_white'; + }; + + return { + stepIndex, + prevState, + nextState, + changePrevState, + changeNextState, + handleNextStep, + handlePrevStep, + getNextBtnColor, + getPrevBtnColor, + }; } diff --git a/public/assets/icons/alertSuccessIc.svg b/public/assets/icons/alertSuccessIc.svg new file mode 100644 index 00000000..760672c9 --- /dev/null +++ b/public/assets/icons/alertSuccessIc.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/assets/icons/alertIc.svg b/public/assets/icons/alertWarningIc.svg similarity index 100% rename from public/assets/icons/alertIc.svg rename to public/assets/icons/alertWarningIc.svg diff --git a/public/assets/icons/index.ts b/public/assets/icons/index.ts index 9cab52ca..b5ad3325 100644 --- a/public/assets/icons/index.ts +++ b/public/assets/icons/index.ts @@ -10,7 +10,8 @@ export { default as CloseSmallIc } from '@/public/assets/icons/closeSmallIc.svg' export { default as CalendarIc } from '@/public/assets/icons/calendarIc.svg'; export { default as CalendarGreyIc } from '@/public/assets/icons/calendarGreyIc.svg'; export { default as ArrowDownIc } from '@/public/assets/icons/arrowDownIc.svg'; -export { default as AlertIc } from '@/public/assets/icons/alertIc.svg'; +export { default as AlertWarningIc } from '@/public/assets/icons/alertWarningIc.svg'; +export { default as AlertSuccessIc } from '@/public/assets/icons/alertSuccessIc.svg'; export { default as LinkCopyIc } from '@/public/assets/icons/linkCopyIc.svg'; export { default as DetailCloseIc } from '@/public/assets/icons/detailCloseIc.svg'; export { default as DetailOpenIc } from '@/public/assets/icons/detailOpenIc.svg'; diff --git a/types/common/box/boxStyleType.ts b/types/common/box/boxStyleType.ts index e14f6c5b..29e3d52a 100644 --- a/types/common/box/boxStyleType.ts +++ b/types/common/box/boxStyleType.ts @@ -1,10 +1,13 @@ export type BoxTypes = 'half' | 'large' | 'iamge' | 'custom'; -export type InputBoxTypes = 'inputBox--half' | 'inputBox--large' | 'inputBox--custom'; +export type InputBoxTypes = + | 'inputBox--half' + | 'inputBox--large' + | 'inputBox--calendar' + | 'inputBox--custom'; export type BtnBoxTypes = 'btn--half' | 'btn--large' | 'btn--custom'; export type ImageBoxTypes = 'imageBox--textarea' | 'imageBox--image'; export type ColorSystemType = - | 'gary_white' | 'mainBlue_white' | 'yellow_black' | 'pastelBlue_white' @@ -13,4 +16,5 @@ export type ColorSystemType = | 'pastelBlue_darkBlue' | 'white_mainBlue' | 'gray1_gray2' + | 'gray1_white' | 'lightRed_warningRed'; diff --git a/types/common/input/wishesInput.ts b/types/common/input/wishesInput.ts index 4feb6bee..cda4067c 100644 --- a/types/common/input/wishesInput.ts +++ b/types/common/input/wishesInput.ts @@ -1,7 +1,7 @@ export interface WishesDataInputType extends BankInfoInputsType { linkURL: string; imageURL: string; - price: number; + price: string | number; initial: string; title: string; hint: string; diff --git a/validation/input.ts b/validation/input.ts index 6a6df8e2..30edd5d8 100644 --- a/validation/input.ts +++ b/validation/input.ts @@ -1,6 +1,7 @@ import { IMAGE_FILE_SIZE } from '@/constant/imageFileSize'; +import { LIMIT_TEXT } from '@/constant/limitText'; -const REGEX = Object.freeze({ +export const REGEX = Object.freeze({ NAVER_SHOPPING: /^http[s]?:\/\/search.shopping.naver.com/, TWENTY_NINE_STORE: /^http[s]?:\/\/product.29cm.co.kr/, //실제 29cm스토어에서 가져오는 주소값 TWENTY_NINE_SERVER: /^http[s]?:\/\/img.29cm.co.kr/, //서버에서 보내주는 주소값 @@ -35,3 +36,6 @@ export const validation = { if (input) return input.length < 10 || input.length > 14; }, }; + + + diff --git a/validation/rules.ts b/validation/rules.ts new file mode 100644 index 00000000..0555f7af --- /dev/null +++ b/validation/rules.ts @@ -0,0 +1,40 @@ +import { LIMIT_TEXT } from '@/constant/limitText'; +import { WishesDataInputType } from '@/types/common/input/wishesInput'; + +export const RULES: Record = { + linkURL: { + required: '필수 작성 항목입니다.', + pattern: { + value: /^http[s]?:\/\/product.29cm.co.kr/, + message: '정해진 사이트에서 링크를 가져와주세요!', + }, + minLength: 0, + }, + + initial: { + required: '초성을 입력해주세요.', + minLength: { + value: 0, + }, + maxLength: { + value: LIMIT_TEXT[15], + message: '15자 까지 입력이 가능합니다!', + }, + }, + price: {}, + imageURL: {}, + hint: {}, + startDate: {}, + endDate: {}, + title: {}, + phone: {}, + mobileCode: {}, + name: {}, + bankName: {}, + account: {}, +}; + +// const textRules = { +// required: 'Text is Required', +// validation: {}, +// };