Skip to content

Commit

Permalink
[ feat ] 선물하기 페이지 기능구현
Browse files Browse the repository at this point in the history
  • Loading branch information
myeongheonhong committed Oct 29, 2024
1 parent 98ac0b7 commit 7980d9a
Show file tree
Hide file tree
Showing 39 changed files with 603 additions and 499 deletions.
Binary file added public/assets/images/AccountCopyCakeImg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions public/assets/images/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export { default as LogoImg } from '../images/logoImg.svg';
export { default as MainPageCakeImg } from '../images/mainPageCakeImg.png';
export { default as MainCakeListImg } from '../images/mainCakeListImg.png';

export { default as AccountCopyCakeImg } from '../images/AccountCopyCakeImg.png';

//생일선물을 주는 사람이 선택하는 선물 아이템 이미지
export { default as PresentItem1Img } from './presentItem/presentItem1Img.png';
export { default as PresentItem2Img } from './presentItem/presentItem2Img.png';
Expand Down
8 changes: 4 additions & 4 deletions src/api/wishes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ import {
import { client } from './common/axios';
import { API_VERSION_01, PATH_WISHES } from './path';
import { UseFormReturn } from 'react-hook-form';
import { SiteDataType } from '@/types/siteDataType';
import { WishesDataInputType } from '@/types/wishesType';
import { WishesLinkDataType } from '@/types/input';
import { getLoginUserCookiesData } from '@/utils/common/cookies';
import { WishesLinkResolverType } from '@/validation/wishes.validate';

/**
* 진행중인 소원 조회
Expand Down Expand Up @@ -46,7 +44,9 @@ export const getWishes = async () => {
/**
* 소원링크 생성
*/
export const postWishes = async (methods: UseFormReturn<WishesLinkDataType, any, undefined>) => {
export const postWishes = async (
methods: UseFormReturn<WishesLinkResolverType, any, undefined>,
) => {
const data = await client.post<WishesCreateResponseType>(
`${API_VERSION_01}${PATH_WISHES.DEFAULT}`,
{
Expand Down
11 changes: 10 additions & 1 deletion src/app/error.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
'use client';

import { RouterPathsType } from '@/components/Common/Hedaer';
import { useRouter } from 'next/navigation';
import { ReactNode } from 'react';

export default function ErrorPage({
alertMessage,
pathTo,
children,
}: {
alertMessage?: string;
pathTo?: RouterPathsType;
children?: ReactNode;
}) {
const router = useRouter();
if (alertMessage) {
alert(alertMessage);
window.location.replace('/');
if (pathTo) {
router.push(pathTo);
} else {
router.push('/');
}
}
return (
<>
Expand Down
1 change: 0 additions & 1 deletion src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import Header from '@/components/Common/Hedaer';
import MainPageContainer from '@/container/container';
import MainLayout from '@/layouts/MainLayout';
import { getLoginUserCookiesData } from '@/utils/common/cookies';
import { redirect } from 'next/navigation';

export default async function Home() {
const isLoggedIn = (await getLoginUserCookiesData()) ? true : false;
Expand Down
13 changes: 10 additions & 3 deletions src/app/present/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@ import Header from '@/components/Common/Hedaer';
import GivePresentPageContainer from '@/container/present/container';
import MainLayout from '@/layouts/MainLayout';

export default function GivePresentPage({
export type PresentStepType = 'present' | 'payment';

export default async function GivePresentPage({
params,
searchParams,
}: {
params: { id: string };
searchParams: { avatarCakeId: string };
searchParams: { presentStep: PresentStepType; avatarCakeId?: string; presentId?: string };
}) {
return (
<>
<Header backBtn />
<MainLayout>
<GivePresentPageContainer wishId={params.id} avatarCakeId={searchParams.avatarCakeId} />
<GivePresentPageContainer
wishId={params.id}
avatarCakeId={searchParams.avatarCakeId}
presentId={searchParams.presentId}
presentStep={searchParams.presentStep}
/>
</MainLayout>
</>
);
Expand Down
6 changes: 3 additions & 3 deletions src/app/wishes/create/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Loading from '@/app/loading';
import Header from '@/components/Common/Hedaer';
import WishesCreatePageContainer from '@/container/wishes/create/container';
import MainLayout from '@/layouts/MainLayout';
import { convertDecodeBase64 } from '@/utils/common/convert';
import { convertDecode } from '@/utils/common/convert';
import { Suspense } from 'react';

export type WishesCreateStepType = 'link' | 'account';
Expand All @@ -19,11 +19,11 @@ export default function WishesCreatePage({
return <ErrorPage />;
}

const decodeWishTitle = convertDecodeBase64(wishTitle);
const decodeWishTitle = convertDecode(wishTitle);

return (
<Suspense fallback={<Loading />}>
<Header backBtn />
<Header backBtn pathTo="/wishes" />
<MainLayout>
<WishesCreatePageContainer createStep={searchParams.step} wishTitle={decodeWishTitle} />
</MainLayout>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Common/Box/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ColorsTypes, FontsTypes } from '@/styles/styles';

import { CSSProperties, PropsWithChildren } from 'react';

interface BoxProps {
export interface BoxProps {
bgColor?: keyof ColorsTypes;
fontColor?: keyof ColorsTypes;
font?: keyof FontsTypes;
Expand Down
15 changes: 11 additions & 4 deletions src/components/Common/Button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,16 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
}

const Button = (props: PropsWithChildren<ButtonProps>) => {
const { disabled, bgColor, fontColor, font, styles, onClick, icon, children } = props;
const {
disabled,
bgColor = 'main_blue',
fontColor,
font = 'bitbit',
styles,
onClick,
icon,
children,
} = props;

const defaultStyle: CSSProperties = {
backgroundColor: disabled ? colors.gray2 : bgColor ? colors[bgColor] : colors.main_blue,
Expand All @@ -27,9 +36,7 @@ const Button = (props: PropsWithChildren<ButtonProps>) => {
<button
className={`flex justify-center items-center ${
icon ? 'gap-10px' : 'gap-0'
} w-full h-50 text-[20px] font-${font ? font : 'bitbit'} bg-${
bgColor ? bgColor : 'main_blue'
} rounded-xl`}
} w-full h-50 text-[20px] font-${font} bg-${bgColor} rounded-xl`}
disabled={disabled}
onClick={onClick}
style={combinedStyle}
Expand Down
1 change: 0 additions & 1 deletion src/components/Common/Calendar/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { ko } from 'date-fns/locale';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import CalendarHeader from './CalendarHeader';
import { getDate } from '@/utils/common/getDate';
import { CalendarGreyIc, CalendarIc } from '../../../../public/assets/icons';
import Box from '../Box';

Expand Down
17 changes: 12 additions & 5 deletions src/components/Common/Hedaer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,32 @@ import Image from 'next/image';
import { usePathname, useRouter } from 'next/navigation';
import { BackBtnIc, MenuIc } from '../../../public/assets/icons';

export type RouterPathsType = '/' | '/wishes' | `/wishes/${string}` | '/mypage';

interface HeaderProps {
backBtn?: boolean;
pathTo?: RouterPathsType;
mypageBtn?: boolean;
isLoggedIn?: boolean;
}

export default function Header(props: HeaderProps) {
const { backBtn, mypageBtn, isLoggedIn } = props;
const { backBtn, mypageBtn, pathTo, isLoggedIn } = props;
const pathname = usePathname();
const router = useRouter();

// if (pathname === '/' && isLoggedIn) {
// router.push('/wishes');
// }
function handleRouteBack() {
if (pathTo) {
router.push(pathTo);
} else {
router.back();
}
}

return (
<header className="flex justify-center w-full">
<div className="flex justify-between items-center min-w-375 max-w-500 w-full mt-2rem pt-16 px-22">
{backBtn && <Image src={BackBtnIc} alt="뒤로가기 아이콘" onClick={() => router.back()} />}
{backBtn && <Image src={BackBtnIc} alt="뒤로가기 아이콘" onClick={handleRouteBack} />}
<div></div>
{mypageBtn && pathname === '/wishes' && (
<Image src={MenuIc} alt="메뉴 아이콘" onClick={() => router.push('/mypage')} />
Expand Down
6 changes: 3 additions & 3 deletions src/components/Common/Input/inputText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@ import Box from '../Box';
interface InputTextProps extends InputHTMLAttributes<HTMLInputElement> {
register?: UseFormRegisterReturn;
boxStyles?: React.CSSProperties;
styles?: React.CSSProperties;
inputStyles?: React.CSSProperties;
onClick?: () => void;
children?: ReactNode;
}

export default function InputText({
register,
boxStyles,
styles,
inputStyles,
onClick,
readOnly,
children,
...rest
}: InputTextProps) {
return (
<Box bgColor="dark_green" fontColor="white" font="galmuri" styles={boxStyles}>
<div className="flex justify-between items-center w-full h-full " style={styles}>
<div className="flex justify-between items-center w-full h-full " style={inputStyles}>
<input
className="w-full h-full font-galmuri text-[14px] plachoder-gray2"
{...register}
Expand Down
10 changes: 3 additions & 7 deletions src/components/Common/Modal/BankModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,17 @@

import Image from 'next/image';
import { BANK_LIST } from '@/constant/bankList';
import { UseFormReturn } from 'react-hook-form';
import { WishesAccountDataType } from '@/types/input';



interface BankModalProps {
handleToggle: () => void;
methods: UseFormReturn<WishesAccountDataType, any, undefined>;
changeBank: (input: string) => void;
}

export default function BankModal(props: BankModalProps) {
const { handleToggle, methods } = props;
const { handleToggle, changeBank } = props;

const handleChangeBank = (input: string) => {
methods.setValue('bank', input);
changeBank(input);
handleToggle();
};

Expand Down
2 changes: 1 addition & 1 deletion src/components/Common/Modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default function Modal(props: PropsWithChildren<ModalProps>) {
}`}
onClick={handleToggle}
>
<div className="w-full h-full" onClick={(e) => e.stopPropagation()}>
<div className="w-auto h-auto" onClick={(e) => e.stopPropagation()}>
{children}
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/components/UI/CakeTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function CakesTree({
}) {
const numberOfRows = Math.max(4, Math.ceil(cakeList.length / 3));

const { toggleState, handleToggle, changeOpenState } = useToggle();
const { toggleState, handleToggle, changeToggleState } = useToggle();
const { selectedId: selectedPresentId, handleSelectOne } = useSelectItem();
const [cakePresentMessageData, setCakePresentMessageData] =
useState<CakePresentMessageDataType | null>(null);
Expand Down Expand Up @@ -60,7 +60,7 @@ export function CakesTree({
key={cake.name}
onClick={() => {
handleSelectOne(cake.presentId);
changeOpenState(true);
changeToggleState(true);
}}
style={{ width: '105%' }}
>
Expand Down
21 changes: 10 additions & 11 deletions src/components/UI/CheckBox.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
'use client';

import { PropsWithChildren } from 'react';
import { useFormContext, useWatch } from 'react-hook-form';
import useToggle from '@/hooks/common/useToggle';
import { PropsWithChildren, useEffect } from 'react';

interface CheckBoxProps<T> {
checkBoxText: string;
registerName?: keyof T;
changeCheckedState: (state: boolean) => void;
}

export default function CheckBox<T>(props: PropsWithChildren<CheckBoxProps<T>>) {
const { register, control } = useFormContext();
const { checkBoxText, registerName } = props;
const { checkBoxText, changeCheckedState } = props;
const { toggleState, handleToggle } = useToggle();

const checkState = useWatch({
control,
name: registerName as string,
});
useEffect(() => {
changeCheckedState(toggleState);
}, [toggleState]);

return (
<div className="flex items-center h-full">
<input
className="w-20 h-20"
type="checkbox"
{...register(registerName as string)}
onChange={handleToggle}
style={{
backgroundImage: `url(${
checkState ? '/assets/icons/checkedBoxIc.svg' : '/assets/icons/unCheckedBoxIc.svg'
toggleState ? '/assets/icons/checkedBoxIc.svg' : '/assets/icons/unCheckedBoxIc.svg'
})`,
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center',
Expand Down
38 changes: 20 additions & 18 deletions src/components/UI/DropDwonBox.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
import Image from 'next/image';
import { CSSProperties, ReactNode } from 'react';
import { PropsWithChildren } from 'react';
import { MainBlueArrowIc } from '../../../public/assets/icons';
import Box, { BoxProps } from '../Common/Box';

interface DropDownBoxProps extends BoxProps {
isOpen: boolean;
handleToggle: () => void;
}

export default function DropDwonBox({
isOpen,
handleToggle,
styles,
children,
}: {
isOpen: boolean;
handleToggle: () => void;
styles?: CSSProperties;
children: ReactNode;
}) {
...rest
}: PropsWithChildren<DropDownBoxProps>) {
return (
<div className="flex items-center gap-8 w-full h-full text-[14px]" style={styles}>
{children}
<div onClick={handleToggle}>
<Image
src={MainBlueArrowIc}
alt="화살표 아이콘"
className={`origin-center ${isOpen ? 'rotate-90' : '-rotate-90'}`}
/>
<Box {...rest}>
<div className="flex items-center gap-8 w-full h-full text-[14px]">
{rest.children}
<div onClick={handleToggle}>
<Image
src={MainBlueArrowIc}
alt="화살표 아이콘"
className={`origin-center ${isOpen ? 'rotate-90' : '-rotate-90'}`}
/>
</div>
</div>
</div>
</Box>
);
}
Loading

0 comments on commit 7980d9a

Please sign in to comment.