Skip to content

Commit

Permalink
MARA-23 친구 냉장고 화면 구현 (#7)
Browse files Browse the repository at this point in the history
* feat: 컴포넌트 분리

* feat: 스타일 및 순서 모달 추가

* feat: 친구 냉장고 페이지 추가

* chore: 이미지 예시 추가
  • Loading branch information
a-honey authored Jan 27, 2024
1 parent 748c168 commit 0af5d89
Show file tree
Hide file tree
Showing 19 changed files with 21,066 additions and 826 deletions.
20,121 changes: 20,121 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

Binary file added src/assets/profile.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: 1 addition & 1 deletion src/components/atoms/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interface ButtonProps {
const Button: React.FC<ButtonProps> = ({ text, className, onClick }) => {
return (
<button
className={` text-white p-18 gap-12 rounded-12 heading4-semibold ${className}`}
className={`text-white p-18 gap-12 rounded-12 heading4-semibold ${className}`}
onClick={onClick}
>
{text}
Expand Down
45 changes: 45 additions & 0 deletions src/components/atoms/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -325,3 +325,48 @@ export const TrashcanSVG: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (
</defs>
</svg>
);

export const SearchSVG: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9.16667 15.8333C12.8486 15.8333 15.8333 12.8486 15.8333 9.16667C15.8333 5.48477 12.8486 2.5 9.16667 2.5C5.48477 2.5 2.5 5.48477 2.5 9.16667C2.5 12.8486 5.48477 15.8333 9.16667 15.8333Z"
stroke="#9299AA"
stroke-width="1.66667"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M17.5002 17.4998L13.9169 13.9165"
stroke="#9299AA"
stroke-width="1.66667"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);

export const ArrowRightGray: React.FC<React.SVGProps<SVGSVGElement>> = (
props,
) => (
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M5 14L11 8L5 2"
stroke="#CCCFD7"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
5 changes: 4 additions & 1 deletion src/components/atoms/ModalBottom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ const ModalBox: React.FC<ModalBoxProps> = ({ children, blackClickHandler }) => {
onClick={blackClickHandler}
>
<div
className="w-full max-w-[480px] min-h-[500px] pt-[40px] mb-[-24px] bg-white p-[20px] rounded-[24px]"
className="w-full max-w-[480px] pt-[40px] mb-[-24px] bg-white p-[20px] pb-[40px] rounded-[24px]"
onClick={handleWhiteContentClick}
>
<div className="relative">
<div className="absolute top-[-16px] right-[200px] left-[200px] h-[4px] bg-gray-500 rounded-[100px]"></div>
</div>
{children}
</div>
</div>
Expand Down
25 changes: 17 additions & 8 deletions src/components/atoms/SearchInput.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
import React from 'react';
import { SearchSVG } from './Icon';

interface SearchInputProps {
searchKeyword: string;
onChangeHandler: () => void;
onClickHandler: () => void;
className: string;
searchKeyword?: string;
onChange?: () => void;
onClick?: () => void;
className?: string;
placeholder?: string;
}

const SearchInput: React.FC<SearchInputProps> = ({
searchKeyword,
onClickHandler,
onChangeHandler,
onClick,
placeholder,
onChange,
className,
}) => {
return (
<div
className={`flex items-center justify-center w-full bg-primary2 text-white p-18 gap-12 rounded-12 heading4-semibold ${className}`}
className={`flex items-center justify-center w-full bg-gray1 text-white p-18 gap-12 rounded-12 heading4-semibold ${className}`}
>
<input onChange={onChangeHandler} value={searchKeyword} />
<input
className="w-full bg-gray1 text"
placeholder={placeholder}
onChange={onChange}
value={searchKeyword}
/>
<SearchSVG width={20} height={20} />
</div>
);
};
Expand Down
1 change: 1 addition & 0 deletions src/components/atoms/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export { default as ModalBottom } from './ModalBottom';
export { default as ModalCenter } from './ModalCenter';
export { default as Toggle } from './Toggle';
export { default as ToastMessage } from './ToastMessage';
export { default as SearchInput } from './SearchInput';
38 changes: 38 additions & 0 deletions src/components/molecules/FriendsFridgeItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import Link from 'next/link';
import React from 'react';
import profileImg from '@/assets/profile.png';
import Image from 'next/image';
import { ArrowRightGray } from '../atoms/Icon';

interface FriendsFridgeItemProps {
name: string;
ingredientCount: number;
linkTo: string;
}

const FriendsFridgeItem: React.FC<FriendsFridgeItemProps> = ({
name,
ingredientCount,
linkTo,
}) => {
return (
<div className="w-full flex items-center justify-between">
<div className="flex gap-[12px]">
<div>
<Image src={profileImg} alt={`누군가의 프로필`} />
</div>
<div className="flex flex-col">
<div className="heading4-semibold text-gray7">{name}</div>
<div className="body2-medium text-gray5">
냉장고 저장 목록 {ingredientCount}
</div>
</div>
</div>
<Link href={`${linkTo}`}>
<ArrowRightGray />
</Link>
</div>
);
};

export default FriendsFridgeItem;
1 change: 1 addition & 0 deletions src/components/molecules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export { default as FridgeTab } from './FridgeTab';
export { default as Counter } from './Counter';
export { default as IngredientAddItemContainer } from './IngredientAddItemContainer';
export { default as FridgeListItem } from './FridgeListItem';
export { default as FriendsFridgeItem } from './FriendsFridgeItem';
14 changes: 8 additions & 6 deletions src/components/organisms/FridgeInfoBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AllowBottom } from '../atoms/Icon';

const FridgeInfoBox: React.FC<{
toggleIsOpenFridgeListModal: () => void;
toggleIsOpenIngredientAddModal: () => void;
toggleIsOpenIngredientAddModal?: () => void;
}> = ({ toggleIsOpenFridgeListModal, toggleIsOpenIngredientAddModal }) => {
return (
<div className="flex justify-between items-end mb-[28px]">
Expand All @@ -18,11 +18,13 @@ const FridgeInfoBox: React.FC<{
<AllowBottom />
</div>
</div>
<Button
className="rounded-6 w-[100px] p-[10px] body1-semibold bg-primary2"
text="식자재 추가"
onClick={toggleIsOpenIngredientAddModal}
/>
{toggleIsOpenIngredientAddModal && (
<Button
className="rounded-6 w-[100px] p-[10px] body1-semibold bg-primary2"
text="식자재 추가"
onClick={toggleIsOpenIngredientAddModal}
/>
)}
</div>
);
};
Expand Down
22 changes: 14 additions & 8 deletions src/components/organisms/FridgeListModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { FridgeListItem } from '../molecules';
import { PlusSVG, TrashcanSVG } from '../atoms/Icon';

const FridgeListModal: React.FC<{
isMyFridgeList?: boolean;
toggleIsOpenFridgeListModal: () => void;
}> = ({ toggleIsOpenFridgeListModal }) => {
}> = ({ toggleIsOpenFridgeListModal, isMyFridgeList }) => {
const [currentFridgeName, setCurrentFridgeName] = useState('기본 냉장고');
const FRIDGE_NAME_LIST = ['기본 냉장고', '김치 냉장고', '주류 냉장고'];

return (
<ModalBottom blackClickHandler={toggleIsOpenFridgeListModal}>
<div>
Expand All @@ -27,15 +29,19 @@ const FridgeListModal: React.FC<{
/>
))}

<button className="flex justify-center items-center h-[64px] border-2 rounded-[12px] text-gray3">
<PlusSVG />
냉장고 추가
</button>
{!isMyFridgeList && (
<button className="flex justify-center items-center h-[64px] border-2 rounded-[12px] text-gray3">
<PlusSVG />
냉장고 추가
</button>
)}
</div>
<div className="flex w-full gap-[8px]">
<button className="p-[13px] border-2 border-2 rounded-[12px]">
<TrashcanSVG />
</button>
{!isMyFridgeList && (
<button className="p-[13px] border-2 border-2 rounded-[12px]">
<TrashcanSVG />
</button>
)}
<Button className="flex-grow bg-primary2" text="이동하기" />
</div>
</ModalBottom>
Expand Down
35 changes: 35 additions & 0 deletions src/components/organisms/FriendsFridgeList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';
import { SearchInput, WhiteBox } from '../atoms';
import { FriendsFridgeItem } from '../molecules';
import { AllowBottom } from '../atoms/Icon';

const FriendsFridgeList: React.FC<{
toggleIsOpenOrderListModal: () => void;
}> = ({ toggleIsOpenOrderListModal }) => {
return (
<div className="mt-[37px]">
<div className="mb-[19.5px] flex justify-between">
<div className="heading2-semibold text-gray8">
친구 목록<span className="heading2-bold text-primary3">13</span>
</div>
<div
className="flex items-center gap-[6px]"
onClick={toggleIsOpenOrderListModal}
>
<div>등록순</div>
<AllowBottom />
</div>
</div>
<WhiteBox>
<SearchInput placeholder="친구의 이름을 입력하세요" />
<div className="w-full flex flex-col gap-[24px]">
<FriendsFridgeItem name="김지수" ingredientCount={13} linkTo="#" />
<FriendsFridgeItem name="김지수" ingredientCount={13} linkTo="#" />
<FriendsFridgeItem name="김지수" ingredientCount={13} linkTo="#" />
</div>
</WhiteBox>
</div>
);
};

export default FriendsFridgeList;
44 changes: 44 additions & 0 deletions src/components/organisms/FriendsRecentBoard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import { GreenArrowButton, WhiteBox } from '../atoms';
import { AppleIcon } from '@/components/atoms/IngredientIcons';
import Link from 'next/link';

const FriendsRecentBoard: React.FC = () => {
const INGREDIENT_LIST = [
{ isToday: true },
{ isToday: false },
{ isToday: false },
];
return (
<WhiteBox className="flex">
<div className="text-primary2 body2-semibold">최신근황</div>
<div className="text-center text-gray8">
김지수님이
<br />
토마토를 추가했어요!
</div>
<div className="text-gray6 body2-medium">
그밖에 신선한 재료를 구경할 수 있어요.
</div>
<div className="flex w-full justify-center gap-[6px]">
{INGREDIENT_LIST.map((ingredient) => (
<div
className={`flex flex-col items-center gap-[9.5px] ${ingredient.isToday ? 'bg-[#FFD5C6]' : 'bg-gray1'} p-[12px] rounded-[12px]`}
>
<AppleIcon width={38} height={38} />
<div
className={`body2-semibold ${ingredient.isToday ? 'text-point3' : ''}`}
>
오늘 추가
</div>
</div>
))}
</div>
<Link className="w-full" href="/friend/12">
<GreenArrowButton className="bg-primary2" text="친구 냉장고 보러가기" />
</Link>
</WhiteBox>
);
};

export default FriendsRecentBoard;
35 changes: 35 additions & 0 deletions src/components/organisms/OrderListModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';
import { Button, ModalBottom } from '../atoms';
import { EmptyRadioSVG, FullRadioSVG } from '../atoms/Icon';

const OrderListModal: React.FC<{
currentOrder: string;
toggleIsOpenOrderListModal: () => void;
}> = ({ toggleIsOpenOrderListModal, currentOrder }) => {
const ORDER_LIST = ['등록순', '이름순'];

return (
<ModalBottom blackClickHandler={toggleIsOpenOrderListModal}>
<div className="w-full">
{ORDER_LIST.map((order) => (
<div className="flex flex-row items-center justify-between h-[70px]">
{currentOrder === order ? (
<>
<div className="heading3-semibold">{order}</div>
<FullRadioSVG />
</>
) : (
<>
<div className="heading3-semibold text-gray5">{order}</div>
<EmptyRadioSVG />
</>
)}
</div>
))}
</div>
<Button className="w-full bg-primary2" text="선택 완료" />
</ModalBottom>
);
};

export default OrderListModal;
3 changes: 3 additions & 0 deletions src/components/organisms/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ export { default as FridgeBoard } from './FridgeBoard';
export { default as FridgeInfoBox } from './FridgeInfoBox';
export { default as IngredientAddModal } from './IngredientAddModal';
export { default as FridgeListModal } from './FridgeListModal';
export { default as FriendsRecentBoard } from './FriendsRecentBoard';
export { default as FriendsFridgeList } from './FriendsFridgeList';
export { default as OrderListModal } from './OrderListModal';
37 changes: 37 additions & 0 deletions src/pages/friend/[id]/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {
FridgeBoard,
FridgeInfoBox,
FridgeListModal,
} from '@/components/organisms';
import Header from '@/components/organisms/Header';
import { type NextPage } from 'next';
import { useState } from 'react';

const FriendIdPage: NextPage = () => {
const [isOpenFridgeListModal, setIsOpenFridgeListModal] = useState(false);

const toggleIsOpenFridgeListModal: () => void = () => {
setIsOpenFridgeListModal((prev) => !prev);
};

return (
<>
{isOpenFridgeListModal && (
<FridgeListModal
isMyFridgeList
toggleIsOpenFridgeListModal={toggleIsOpenFridgeListModal}
/>
)}
<div className={'pt-[52px] min-h-screen'}>
<Header headerTitle={'친구 냉장고'} />
<section className={`flex flex-col min-h-screen p-20 bg-gray1`}>
<FridgeInfoBox
toggleIsOpenFridgeListModal={toggleIsOpenFridgeListModal}
/>
<FridgeBoard />
</section>
</div>
</>
);
};
export default FriendIdPage;
Loading

0 comments on commit 0af5d89

Please sign in to comment.