From 8a634b47ba8129ca2b905be8545c34aabe9dc5f4 Mon Sep 17 00:00:00 2001 From: "Ahyeon, Jung" <75254185+a-honey@users.noreply.github.com> Date: Mon, 26 Feb 2024 00:07:06 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=8B=9D=EC=9E=90=EC=9E=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95,=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F=20=EC=8B=9D?= =?UTF-8?q?=EC=9E=90=EC=9E=AC=20=EC=B6=94=EA=B0=80=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=8A=A4=ED=81=AC=EB=A1=A4=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 냉장고 조회 * feat: 카운트 api * fix: 친구 id로 리스트 조회 * fix: 기타 작업 * feat: 식자재 업데이트, 삭제 api * feat: 로그아웃 훅, 친구 근황 수정 * feat: 메뉴 react-draggble * feat: 카테고리 클릭하면 스크롤 이동 --- package.json | 1 + src/components/atoms/Container.tsx | 4 +- src/components/atoms/Lottie.tsx | 7 +- .../molecules/IngredientItemBox.tsx | 27 +++-- src/components/organisms/FridgeBoard.tsx | 98 ++++++++++++---- src/components/organisms/FridgeInfoBox.tsx | 6 +- src/components/organisms/FridgeListModal.tsx | 2 +- .../organisms/FriendsFridgeList.tsx | 7 +- .../organisms/FriendsRecentBoard.tsx | 8 +- src/components/organisms/IngredientBoard.tsx | 2 +- ...edientAddModal.tsx => IngredientModal.tsx} | 93 ++++++++++++--- src/components/organisms/index.ts | 2 +- .../templates/AddFriendTemplate.tsx | 4 +- src/hooks/queries/fridge/index.ts | 2 + .../queries/fridge/useDeleteIngredientById.ts | 21 ++++ .../queries/fridge/useGetFridgeContentById.ts | 9 +- .../queries/fridge/useGetIngredientById.ts | 6 +- .../queries/fridge/useGetMyIngredient.ts | 14 +++ src/hooks/queries/fridge/usePostIngredient.ts | 4 +- .../queries/fridge/usePutIngredientById.ts | 31 +++++ .../queries/friends/useGetFriendsNews.ts | 1 + .../queries/home/useGetMyIngredientSummary.ts | 9 +- src/hooks/queries/mypage/index.ts | 1 + src/hooks/queries/mypage/useGetCount.ts | 14 +++ .../mypage/useGetMyIngredientsCount.ts | 2 +- src/hooks/queries/queryKeys.ts | 8 +- src/hooks/useLogout.ts | 12 ++ src/pages/fridge/add/index.tsx | 108 +++++++++++++----- src/pages/fridge/index.tsx | 13 +-- src/pages/friend/[id]/index.tsx | 14 +-- src/pages/friends/index.tsx | 22 +++- src/pages/home/index.tsx | 8 +- src/pages/mypage/account/index.tsx | 7 +- src/pages/mypage/index.tsx | 15 +-- src/pages/share/index.tsx | 2 +- src/types/common/index.d.ts | 2 + src/types/fridge/index.d.ts | 1 + yarn.lock | 13 +++ 38 files changed, 457 insertions(+), 143 deletions(-) rename src/components/organisms/{IngredientAddModal.tsx => IngredientModal.tsx} (66%) create mode 100644 src/hooks/queries/fridge/useDeleteIngredientById.ts create mode 100644 src/hooks/queries/fridge/useGetMyIngredient.ts create mode 100644 src/hooks/queries/fridge/usePutIngredientById.ts create mode 100644 src/hooks/queries/mypage/useGetCount.ts create mode 100644 src/hooks/useLogout.ts diff --git a/package.json b/package.json index 2389fe1..245878a 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "next": "14.0.3", "react": "^18", "react-dom": "^18", + "react-draggable": "^4.4.6", "react-error-boundary": "^4.0.12", "recoil": "^0.7.7", "swiper": "^11.0.6" diff --git a/src/components/atoms/Container.tsx b/src/components/atoms/Container.tsx index 0d3aca7..14cf524 100644 --- a/src/components/atoms/Container.tsx +++ b/src/components/atoms/Container.tsx @@ -3,11 +3,13 @@ import React from 'react'; interface ContainerProps { children: React.ReactNode; className?: string; + id?: string; } -const Container: React.FC = ({ children, className }) => { +const Container: React.FC = ({ children, className, id }) => { return (
{children} diff --git a/src/components/atoms/Lottie.tsx b/src/components/atoms/Lottie.tsx index caa66fd..ad32cf5 100644 --- a/src/components/atoms/Lottie.tsx +++ b/src/components/atoms/Lottie.tsx @@ -1,10 +1,11 @@ import React from 'react'; -import Lottie from 'lottie-react'; -import animationData from './../../assets/lottie.json'; +// import Lottie from 'lottie-react'; +// import animationData from './../../assets/lottie.json'; const LottieComponent = () => { return ( - + // +
로딩중
); }; diff --git a/src/components/molecules/IngredientItemBox.tsx b/src/components/molecules/IngredientItemBox.tsx index 5a8c059..320a081 100644 --- a/src/components/molecules/IngredientItemBox.tsx +++ b/src/components/molecules/IngredientItemBox.tsx @@ -1,11 +1,12 @@ import React from 'react'; import { IngredientDateTag } from '../atoms'; -import { AppleIcon } from '@/components/atoms/IngredientIcons'; import type { IngredientDetailType } from '@/types/fridge'; +import Image from 'next/image'; -const IngredientItemBox: React.FC<{ data?: IngredientDetailType }> = ({ - data, -}) => { +const IngredientItemBox: React.FC<{ + data?: IngredientDetailType; + handleDetailIngreditentId?: (id: number) => void; +}> = ({ data, handleDetailIngreditentId }) => { const addDate = new Date(data?.addDate as string); const expirationDate = new Date(data?.expirationDate as string); const today = new Date(); @@ -15,11 +16,23 @@ const IngredientItemBox: React.FC<{ data?: IngredientDetailType }> = ({ ); return ( -
+
{ + if (handleDetailIngreditentId) { + handleDetailIngreditentId(data?.ingredientDetailId ?? 0); + } + }} + >
- + {data?.name
-
{data?.name ?? '사과'}
+
{data?.name ?? ''}
{`${addDate.getFullYear()}년 ${addDate.getMonth() + 1}월 ${addDate.getDay()}일 저장`}
diff --git a/src/components/organisms/FridgeBoard.tsx b/src/components/organisms/FridgeBoard.tsx index ab69412..cf65fbf 100644 --- a/src/components/organisms/FridgeBoard.tsx +++ b/src/components/organisms/FridgeBoard.tsx @@ -1,38 +1,90 @@ import React, { useState } from 'react'; import { Container } from '@/components/atoms'; import { EmptyBox, FridgeTab, IngredientItemBox } from '@/components/molecules'; -import type { IngredientDetailType } from '@/types/fridge'; +import { IngredientModal } from '.'; +import { + Modal, + ModalOverlay, + ModalBody, + ModalContent, + useDisclosure, +} from '@chakra-ui/react'; +import { useGetFridgeContentById } from '@/hooks/queries/fridge'; -const FridgeBoard: React.FC<{ data?: IngredientDetailType[] | null }> = ({ - data, -}) => { +const FridgeBoard: React.FC<{ fridgeId: number }> = ({ fridgeId }) => { + const [detailIngredientId, setDetailIngredientId] = useState(0); const [currentTabName, setCurrentTabName] = useState<'냉장' | '냉동'>('냉장'); + const data = useGetFridgeContentById( + Number(fridgeId), + currentTabName === '냉장' ? 'FREEZING' : 'REFRIGERATION', + )?.content; + + const { + isOpen: isOpenIngredientModal, + onOpen: onOpenIngredientModal, + onClose: onCloseIngredientModal, + } = useDisclosure(); + const handleTabNameChange: (tabName: '냉장' | '냉동') => void = (tabName) => { setCurrentTabName(tabName); }; + const handleDetailIngreditentId = (id: number) => { + setDetailIngredientId(id); + onOpenIngredientModal(); + }; + return ( - - - {data && data.length !== 0 ? ( -
- {data.map((ingredient) => ( - - ))} -
- ) : ( -
- -
+ <> + {isOpenIngredientModal && ( + + + + + + + + )} -
+ + + {data && data.length !== 0 ? ( +
+ {data.map((ingredient) => ( + + ))} +
+ ) : ( +
+ +
+ )} +
+ ); }; diff --git a/src/components/organisms/FridgeInfoBox.tsx b/src/components/organisms/FridgeInfoBox.tsx index 17041fa..0aa9ab1 100644 --- a/src/components/organisms/FridgeInfoBox.tsx +++ b/src/components/organisms/FridgeInfoBox.tsx @@ -13,12 +13,14 @@ const FridgeInfoBox: React.FC<{ return (
-
{userName}님의
+
+ {userName ?? '사용자정보없음'} 님의 +
-
{name}
+
{name ?? '냉장고를 선택해주세요'}
{ void router.push( ownerId - ? `/friend/${ownerId}?fridgeid=${id}` + ? `/friend/${ownerId}?fridgeid=${id}&name=${name}` : `fridge/?fridgeid=${id}&name=${name}`, ); onCloseFridgeListModal(); diff --git a/src/components/organisms/FriendsFridgeList.tsx b/src/components/organisms/FriendsFridgeList.tsx index f6e420e..146fc63 100644 --- a/src/components/organisms/FriendsFridgeList.tsx +++ b/src/components/organisms/FriendsFridgeList.tsx @@ -1,17 +1,19 @@ -import { SearchInput, Container } from '../atoms'; +import { Container } from '../atoms'; import { AngleIcon } from '@/assets/icons'; import { FriendsFridgeItem } from '../molecules'; import React from 'react'; +import { useGetMyFriendsCount } from '@/hooks/queries/mypage'; const FriendsFridgeList: React.FC<{ toggleIsOpenOrderListModal: () => void; }> = ({ toggleIsOpenOrderListModal }) => { + const count = useGetMyFriendsCount(); return (
- 친구 목록13 + 친구 목록 {count}
-
diff --git a/src/components/organisms/FriendsRecentBoard.tsx b/src/components/organisms/FriendsRecentBoard.tsx index 56bff43..48e2ee7 100644 --- a/src/components/organisms/FriendsRecentBoard.tsx +++ b/src/components/organisms/FriendsRecentBoard.tsx @@ -8,12 +8,12 @@ const FriendsRecentBoard: React.FC<{ friendNews: FriendObjectType }> = ({ friendNews, }) => { return ( - +
최신근황
-
+
{friendNews.nickname} 님이
- 토마토를 추가했어요! + {friendNews.friendRefrigeratorIngredientGroupList[0].name}를 추가했어요!
그밖에 신선한 재료를 구경할 수 있어요. @@ -38,7 +38,7 @@ const FriendsRecentBoard: React.FC<{ friendNews: FriendObjectType }> = ({
diff --git a/src/components/organisms/IngredientBoard.tsx b/src/components/organisms/IngredientBoard.tsx index 507faa0..91d5af3 100644 --- a/src/components/organisms/IngredientBoard.tsx +++ b/src/components/organisms/IngredientBoard.tsx @@ -11,7 +11,7 @@ const TermBoard: React.FC = () => { {ingredientSummary && ingredientSummary.length !== 0 ? (
{ingredientSummary.map((data) => ( - + ))}
) : ( diff --git a/src/components/organisms/IngredientAddModal.tsx b/src/components/organisms/IngredientModal.tsx similarity index 66% rename from src/components/organisms/IngredientAddModal.tsx rename to src/components/organisms/IngredientModal.tsx index 4dc0118..2d8269a 100644 --- a/src/components/organisms/IngredientAddModal.tsx +++ b/src/components/organisms/IngredientModal.tsx @@ -1,21 +1,31 @@ -import { BoxIcon, CalendarIcon, FreezerIcon, MemoIcon } from '@/assets/icons'; +import { + BoxIcon, + CalendarIcon, + FreezerIcon, + MemoIcon, + TrashcanIcon, +} from '@/assets/icons'; import { Button, Toggle } from '@/components/atoms'; import { Counter, IngredientAddItemContainer } from '../molecules'; import React, { useState } from 'react'; import useToast from '@/hooks/useToast'; import ModalContainer from '../atoms/ModalContainer'; import { + useDeleteIngredientById, useGetIngredientById, + useGetMyIngredient, usePostIngredient, } from '@/hooks/queries/fridge'; import Image from 'next/image'; import type { PostIngredientBodyType } from '@/hooks/queries/fridge/usePostIngredient'; import { useRouter } from 'next/router'; +import usePutIngredientById from '@/hooks/queries/fridge/usePutIngredientById'; -const IngredientAddModal: React.FC<{ +const IngredientModal: React.FC<{ id: number; - toggleIsOpenIngredientAddModal: () => void; -}> = ({ id, toggleIsOpenIngredientAddModal }) => { + isDetailModal?: boolean; + toggleIsOpenIngredientModal: () => void; +}> = ({ id, toggleIsOpenIngredientModal, isDetailModal = false }) => { const router = useRouter(); const today = new Date(); @@ -24,7 +34,7 @@ const IngredientAddModal: React.FC<{ const { showToast } = useToast(); const onSuccess = () => { - toggleIsOpenIngredientAddModal(); + toggleIsOpenIngredientModal(); showToast('식자재 추가가 완료되었습니다.', 'success'); }; @@ -34,7 +44,9 @@ const IngredientAddModal: React.FC<{ name as string, ); - const data = useGetIngredientById(id); + const data = isDetailModal + ? useGetMyIngredient(id) + : useGetIngredientById(id); const expirationDate = new Date(today); expirationDate.setDate(today.getDate() + (data?.expirationDays ?? 0)); @@ -43,15 +55,30 @@ const IngredientAddModal: React.FC<{ refrigeratorId: Number(fridgeid), ingredientId: id, name: data?.name ?? '', - quantity: 0, - location: 'FREEZING', + quantity: data?.quantity ?? 0, + location: data?.location ?? 'FREEZING', memo: '', addDate: today, - expirationDate, - isDeleted: true, + expirationDate: data?.expirationDate + ? new Date(data?.expirationDate) + : expirationDate, + isDeleted: false, }); - const [isInFreezer, setIsInFreezer] = useState(false); + const deleteIngredient = useDeleteIngredientById( + id, + Number(fridgeid), + reqBody?.location, + ); + const putIngredient = usePutIngredientById( + id, + Number(fridgeid), + reqBody?.location, + ); + + const [isInFreezer, setIsInFreezer] = useState( + reqBody?.location === 'REFRIGERATION', + ); const toggleIsInFreezer: () => void = () => { setIsInFreezer((prev) => !prev); @@ -60,7 +87,7 @@ const IngredientAddModal: React.FC<{ const handleSubmit: () => void = () => { postIngredient.mutate({ ...reqBody, - location: isInFreezer ? 'FREEZING' : 'FREEZING', + location: isInFreezer ? 'REFRIGERATION' : 'FREEZING', }); }; @@ -151,14 +178,44 @@ const IngredientAddModal: React.FC<{ />
- +
+ ) : ( +
); }; -export default IngredientAddModal; +export default IngredientModal; diff --git a/src/components/organisms/index.ts b/src/components/organisms/index.ts index 872be92..d4ddc79 100644 --- a/src/components/organisms/index.ts +++ b/src/components/organisms/index.ts @@ -1,7 +1,7 @@ export { default as IngredientBoard } from './IngredientBoard'; export { default as FridgeBoard } from './FridgeBoard'; export { default as FridgeInfoBox } from './FridgeInfoBox'; -export { default as IngredientAddModal } from './IngredientAddModal'; +export { default as IngredientModal } from './IngredientModal'; export { default as FridgeListModal } from './FridgeListModal'; export { default as FriendsRecentBoard } from './FriendsRecentBoard'; export { default as FriendsFridgeList } from './FriendsFridgeList'; diff --git a/src/components/templates/AddFriendTemplate.tsx b/src/components/templates/AddFriendTemplate.tsx index fb3d71f..d4466fc 100644 --- a/src/components/templates/AddFriendTemplate.tsx +++ b/src/components/templates/AddFriendTemplate.tsx @@ -32,7 +32,7 @@ const AddFriendTemplate: React.FC = () => { }; const onAddFriend = () => { - if (friendInviteCode.length < 8) { + if (friendInviteCode.length < 9) { setWarningVisible(true); } else { addFriendship.mutate({ inviteCode: friendInviteCode }); @@ -75,7 +75,7 @@ const AddFriendTemplate: React.FC = () => { />
{warningVisible ? ( - + ) : null} } diff --git a/src/hooks/queries/fridge/index.ts b/src/hooks/queries/fridge/index.ts index 1aa9c0e..e5369c2 100644 --- a/src/hooks/queries/fridge/index.ts +++ b/src/hooks/queries/fridge/index.ts @@ -5,3 +5,5 @@ export { default as useGetMyIngredients } from './useGetMyIngredients'; export { default as useGetFridgeContentById } from './useGetFridgeContentById'; export { default as useDeleteFridgeById } from './useDeleteFridgeById'; export { default as usePutFridgeById } from './usePutFridgeById'; +export { default as useGetMyIngredient } from './useGetMyIngredient'; +export { default as useDeleteIngredientById } from './useDeleteIngredientById'; diff --git a/src/hooks/queries/fridge/useDeleteIngredientById.ts b/src/hooks/queries/fridge/useDeleteIngredientById.ts new file mode 100644 index 0000000..c10630a --- /dev/null +++ b/src/hooks/queries/fridge/useDeleteIngredientById.ts @@ -0,0 +1,21 @@ +import { queryClient } from '@/pages/_app'; +import { queryKeys } from '../queryKeys'; +import { useBaseMutation } from '../useBaseMutation'; + +const useDeleteIngredientById = ( + id: number, + fridgeId: number, + location: string, +) => { + const onSuccess = () => { + void queryClient.invalidateQueries(); + }; + return useBaseMutation( + queryKeys.MY_FRIDGE_CONTENT(fridgeId, location), + `/ingrs/detail/${id}`, + onSuccess, + 'DELETE', + ); +}; + +export default useDeleteIngredientById; diff --git a/src/hooks/queries/fridge/useGetFridgeContentById.ts b/src/hooks/queries/fridge/useGetFridgeContentById.ts index 1ac2849..6632beb 100644 --- a/src/hooks/queries/fridge/useGetFridgeContentById.ts +++ b/src/hooks/queries/fridge/useGetFridgeContentById.ts @@ -7,13 +7,16 @@ interface FridgeContentType { content: IngredientDetailType[]; } -const useGetFridgeContentById = (id: number) => { +const useGetFridgeContentById = ( + id: number, + location: 'REFRIGERATION' | 'FREEZING', +) => { // 무한스크롤 or useSuspenseQuery로 변경 해야함 const { data } = useQuery({ - queryKey: queryKeys.MY_FRIDGE_CONTENT(id), + queryKey: queryKeys.MY_FRIDGE_CONTENT(id, location), queryFn: async () => { return await fetchData( - `/ingrs/detail/refrig/${id}`, + `/ingrs/detail/refrig/${id}?location=${location}`, true, ); }, diff --git a/src/hooks/queries/fridge/useGetIngredientById.ts b/src/hooks/queries/fridge/useGetIngredientById.ts index c3c9f30..1b9aef4 100644 --- a/src/hooks/queries/fridge/useGetIngredientById.ts +++ b/src/hooks/queries/fridge/useGetIngredientById.ts @@ -1,12 +1,16 @@ import { queryKeys } from '../queryKeys'; import { useBaseQuery } from '../useBaseQuery'; -interface IngredientType { +export interface IngredientType { ingredientId: 0; category: string; name: string; iconImage: string; expirationDays: number; + location?: 'FREEZING' | 'REFRIGERATION'; + quantity?: number; + addDate?: string; + expirationDate?: string; } const useGetIngredientById = (id: number) => { diff --git a/src/hooks/queries/fridge/useGetMyIngredient.ts b/src/hooks/queries/fridge/useGetMyIngredient.ts new file mode 100644 index 0000000..b634dbf --- /dev/null +++ b/src/hooks/queries/fridge/useGetMyIngredient.ts @@ -0,0 +1,14 @@ +import { queryKeys } from '../queryKeys'; +import { useBaseQuery } from '../useBaseQuery'; +import type { IngredientType } from './useGetIngredientById'; + +const useGetMyIngredient = (id: number) => { + const { data } = useBaseQuery( + queryKeys.MY_INGREDIENT_ID(id), + `/ingrs/detail/${id}`, + ); + + return data?.data; +}; + +export default useGetMyIngredient; diff --git a/src/hooks/queries/fridge/usePostIngredient.ts b/src/hooks/queries/fridge/usePostIngredient.ts index 43b28d0..71cece1 100644 --- a/src/hooks/queries/fridge/usePostIngredient.ts +++ b/src/hooks/queries/fridge/usePostIngredient.ts @@ -7,11 +7,11 @@ export interface PostIngredientBodyType { ingredientId: number; name: string; quantity: number; - location: 'FREEZING'; + location: 'FREEZING' | 'REFRIGERATION'; memo: string; addDate: Date; expirationDate: Date; - isDeleted: true; + isDeleted: boolean; } const usePostIngredient = (fn: () => void, fridgeid: string, name: string) => { diff --git a/src/hooks/queries/fridge/usePutIngredientById.ts b/src/hooks/queries/fridge/usePutIngredientById.ts new file mode 100644 index 0000000..8be4829 --- /dev/null +++ b/src/hooks/queries/fridge/usePutIngredientById.ts @@ -0,0 +1,31 @@ +import type { LocationEnum } from '@/types/common'; +import { queryKeys } from '../queryKeys'; +import { useBaseMutation } from '../useBaseMutation'; +import { queryClient } from '@/pages/_app'; + +export interface FridgeBodyType { + name: string; + quantity: number; + location: LocationEnum; + memo: string; + addDate: Date; + expirationDate: Date; + isDeleted: boolean; +} + +const usePutIngredientById = ( + id: number, + fridgeId: number, + location: string, +) => { + const onSuccess = () => { + void queryClient.invalidateQueries(); + }; + return useBaseMutation( + queryKeys.MY_FRIDGE_CONTENT(fridgeId, location), + `/ingrs/detail/${id}`, + onSuccess, + 'PUT', + ); +}; +export default usePutIngredientById; diff --git a/src/hooks/queries/friends/useGetFriendsNews.ts b/src/hooks/queries/friends/useGetFriendsNews.ts index 9652d04..7fd661a 100644 --- a/src/hooks/queries/friends/useGetFriendsNews.ts +++ b/src/hooks/queries/friends/useGetFriendsNews.ts @@ -3,6 +3,7 @@ import { queryKeys } from '../queryKeys'; import { useBaseQuery } from '../useBaseQuery'; export interface FriendObjectType { + userId: number; nickname: string; refrigeratorId: number; friendRefrigeratorIngredientGroupList: IngredientType[]; diff --git a/src/hooks/queries/home/useGetMyIngredientSummary.ts b/src/hooks/queries/home/useGetMyIngredientSummary.ts index 52e1194..bd16f85 100644 --- a/src/hooks/queries/home/useGetMyIngredientSummary.ts +++ b/src/hooks/queries/home/useGetMyIngredientSummary.ts @@ -1,14 +1,9 @@ +import type { IngredientDetailType } from '@/types/fridge'; import { queryKeys } from '../queryKeys'; import { useBaseQuery } from '../useBaseQuery'; -interface IngredientType { - id: number; - name: string; - iconImage: string; -} - const useGetMyIngredientSummary = () => { - const { data } = useBaseQuery( + const { data } = useBaseQuery( queryKeys.INGREDIENTS_RECENT(), '/ingrs/detail/recent', ); diff --git a/src/hooks/queries/mypage/index.ts b/src/hooks/queries/mypage/index.ts index 9dc6662..cd1240b 100644 --- a/src/hooks/queries/mypage/index.ts +++ b/src/hooks/queries/mypage/index.ts @@ -1,3 +1,4 @@ export { default as useGetMe } from './useGetMe'; export { default as useGetMyFriendsCount } from './useGetMyFriendsCount'; export { default as useGetMyIngredientsCount } from './useGetMyIngredientsCount'; +export { default as useGetCount } from './useGetCount'; diff --git a/src/hooks/queries/mypage/useGetCount.ts b/src/hooks/queries/mypage/useGetCount.ts new file mode 100644 index 0000000..fc45842 --- /dev/null +++ b/src/hooks/queries/mypage/useGetCount.ts @@ -0,0 +1,14 @@ +import { queryKeys } from '../queryKeys'; +import { useBaseQuery } from '../useBaseQuery'; + +const useGetCount = () => { + const { data } = useBaseQuery<{ + ingredientCount: number; + shareCount: number; + friendCount: number; + }>(queryKeys.COUNT(), `/users/me/statistics`, true); + + return data?.data; +}; + +export default useGetCount; diff --git a/src/hooks/queries/mypage/useGetMyIngredientsCount.ts b/src/hooks/queries/mypage/useGetMyIngredientsCount.ts index 59ecb27..b38d558 100644 --- a/src/hooks/queries/mypage/useGetMyIngredientsCount.ts +++ b/src/hooks/queries/mypage/useGetMyIngredientsCount.ts @@ -4,7 +4,7 @@ import { useBaseQuery } from '../useBaseQuery'; const useGetMyIngredientsCount = () => { const { data } = useBaseQuery( queryKeys.MY_INGREDIENTS_COUNT(), - `/ingrs/detail/count?day=5`, + `/ingrs/detail/count?day=7`, true, ); diff --git a/src/hooks/queries/queryKeys.ts b/src/hooks/queries/queryKeys.ts index 948a213..2cbe173 100644 --- a/src/hooks/queries/queryKeys.ts +++ b/src/hooks/queries/queryKeys.ts @@ -5,10 +5,16 @@ import type { } from '@/types/friendship'; export const queryKeys = { + COUNT: () => ['count'], MY_FRIDGE_LIST: () => ['my_fridge_list'], MY_FRIENDS_COUNT: () => ['my_friends_count'], - MY_FRIDGE_CONTENT: (id: number) => ['my_fridge', id], + MY_FRIDGE_CONTENT: (id: number, location: string) => [ + 'my_fridge', + id, + location, + ], MY_INGREDIENTS_COUNT: () => ['my_ingredient_count'], + MY_INGREDIENT_ID: (id: number) => ['my-ingredient', id], MY_FRIENDS_NEWS: () => ['my_friends_news'], INGREDIENT_LIST: () => ['ingredient_list'], INGREDIENT_ID: (id: number) => ['ingredient', id], diff --git a/src/hooks/useLogout.ts b/src/hooks/useLogout.ts new file mode 100644 index 0000000..73f5836 --- /dev/null +++ b/src/hooks/useLogout.ts @@ -0,0 +1,12 @@ +import { useRouter } from 'next/router'; + +const useLogout = () => { + const router = useRouter(); + return () => { + localStorage.removeItem('accessToken'); + localStorage.removeItem('refreshToken'); + router.push('/login'); + }; +}; + +export default useLogout; diff --git a/src/pages/fridge/add/index.tsx b/src/pages/fridge/add/index.tsx index 22d37e7..35faa8c 100644 --- a/src/pages/fridge/add/index.tsx +++ b/src/pages/fridge/add/index.tsx @@ -1,7 +1,7 @@ import type { NextPage } from 'next'; -import { Header, IngredientAddModal } from '@/components/organisms'; +import { Header, IngredientModal } from '@/components/organisms'; import { Container } from '../../../components/atoms'; -import { useState } from 'react'; +import { useRef, useState } from 'react'; import { useGetIngredientList } from '@/hooks/queries/fridge'; import Image from 'next/image'; import { @@ -11,29 +11,65 @@ import { ModalContent, useDisclosure, } from '@chakra-ui/react'; +import Draggable from 'react-draggable'; +import type { DraggableEvent } from 'react-draggable'; const FridgePage: NextPage = () => { const [ingredientId, setIngredientId] = useState(null); const { - isOpen: isOpenIngredientAddModal, - onOpen: onOpenIngredientAddModal, - onClose: onCloseIngredientAddModal, + isOpen: isOpenIngredientModal, + onOpen: onOpenIngredientModal, + onClose: onCloseIngredientModal, } = useDisclosure(); const [currentCategory, setCurrentCategory] = useState('전체'); + const categoryRef = useRef(null); + + const handleCategoryClick = (category: string) => { + setCurrentCategory(category); + const categoryComponent = document.getElementById(category); + + if (categoryComponent) { + const labelPosition = categoryComponent.getBoundingClientRect().top; + + window.scrollTo({ + top: window.scrollY + labelPosition - 300, + behavior: 'smooth', + }); + } + }; const data = useGetIngredientList(); + const [scrollX, setScrollX] = useState(0); + + const containerWidth = 1400; + const maxScrollX = containerWidth - window.innerWidth; + + const handleDrag = ( + e: DraggableEvent, + { deltaX }: { deltaX: number }, + ): void => { + const newScrollX = scrollX - deltaX; + if (newScrollX > maxScrollX) { + setScrollX(maxScrollX); + } else if (newScrollX < maxScrollX) { + setScrollX(0); + } else { + setScrollX(newScrollX); + } + }; + return ( <> - {isOpenIngredientAddModal && ( + {isOpenIngredientModal && ( - + { margin={0} > - @@ -53,24 +89,40 @@ const FridgePage: NextPage = () => { )}
-
-
- {['전체', ...(data?.map((item) => item.category) as string[])].map( - (category) => ( -
{ - setCurrentCategory(category); - }} - className={`${category === currentCategory ? 'bg-primary2 text-white' : 'bg-white text-gray4'} cursor-pointer body1-semibold pt-[6px] pb-[6px] pl-[18px] pr-[18px] rounded-[20px]`} - > - {category} -
- ), - )} +
+
+ +
+ {['전체', ...(data?.map((item) => item.category) ?? [])].map( + (category) => ( +
{ + handleCategoryClick(category); + }} + className={`${category === currentCategory ? 'bg-primary2 text-white' : 'bg-white text-gray4'} cursor-pointer body1-semibold pt-[6px] pb-[6px] pl-[18px] pr-[18px] rounded-[20px]`} + style={{ whiteSpace: 'nowrap' }} + data-category={category} + > + {category} +
+ ), + )} +
+
{data?.map((items) => ( - +
    {items.ingredientGroupList.map((item) => ( @@ -78,7 +130,7 @@ const FridgePage: NextPage = () => { key={item.id} onClick={() => { setIngredientId(item.id); - onOpenIngredientAddModal(); + onOpenIngredientModal(); }} className="flex flex-col items-center" > diff --git a/src/pages/fridge/index.tsx b/src/pages/fridge/index.tsx index d5e7a88..73a3e3a 100644 --- a/src/pages/fridge/index.tsx +++ b/src/pages/fridge/index.tsx @@ -13,7 +13,6 @@ import { useDisclosure, } from '@chakra-ui/react'; import { useGetMe } from '@/hooks/queries/mypage'; -import { useGetFridgeContentById } from '@/hooks/queries/fridge'; import { useRouter } from 'next/router'; import { useEffect } from 'react'; @@ -29,12 +28,6 @@ const FridgePage: NextPage = () => { const { fridgeid: fridgeId } = router.query; - // if (!fridgeId) { - // onOpenFridgeListModal(); - // } - - const data = useGetFridgeContentById(Number(fridgeId))?.content; - useEffect(() => { if (!fridgeId) { onOpenFridgeListModal(); @@ -65,13 +58,15 @@ const FridgePage: NextPage = () => {
    -
    +
    - +
    diff --git a/src/pages/friend/[id]/index.tsx b/src/pages/friend/[id]/index.tsx index dbd2b3e..412c4d7 100644 --- a/src/pages/friend/[id]/index.tsx +++ b/src/pages/friend/[id]/index.tsx @@ -14,7 +14,6 @@ import { } from '@chakra-ui/react'; import { useEffect, useState } from 'react'; import { useRouter } from 'next/router'; -import { useGetFridgeContentById } from '@/hooks/queries/fridge'; const FriendIdPage: NextPage = () => { const router = useRouter(); const [nickname, setNickName] = useState(''); @@ -24,14 +23,12 @@ const FriendIdPage: NextPage = () => { onClose: onCloseFridgeListModal, } = useDisclosure(); - const { id: fridgeId, name } = router.query; + const { id: userId, fridgeid: fridgeId, name } = router.query; if (!fridgeId) { onOpenFridgeListModal(); } - const data = useGetFridgeContentById(Number(fridgeId))?.content; - useEffect(() => { setNickName(name as string); }, []); @@ -53,22 +50,23 @@ const FriendIdPage: NextPage = () => { margin={0} > - {/* 친구 아이디 넣어야함 */}
    -
    +
    - +
    diff --git a/src/pages/friends/index.tsx b/src/pages/friends/index.tsx index c53ea3c..b95d809 100644 --- a/src/pages/friends/index.tsx +++ b/src/pages/friends/index.tsx @@ -20,8 +20,12 @@ import 'swiper/css/pagination'; import 'swiper/css/scrollbar'; import { Container } from '@/components/atoms'; import { EmptyBox } from '@/components/molecules'; +import { PlusIcon } from '@/assets/icons'; +import { useRouter } from 'next/router'; const FriendsPage: NextPage = () => { + const router = useRouter(); + const { isOpen: isOpenOrderListModal, onOpen: onOpenOrderListModal, @@ -52,8 +56,22 @@ const FriendsPage: NextPage = () => {
    -
    -
    +
    { + router.push('/mypage/friendship'); + }} + /> + } + /> +
    {friendsNewsList && friendsNewsList.length !== 0 ? ( {friendsNewsList.map((friendNews) => ( diff --git a/src/pages/home/index.tsx b/src/pages/home/index.tsx index 9843331..8b13e8e 100644 --- a/src/pages/home/index.tsx +++ b/src/pages/home/index.tsx @@ -25,11 +25,13 @@ const Home: NextPage = () => {
    } /> -
    +
    {!!ingredientCount && ( - + )} -
    +
    } text="내 냉장고" diff --git a/src/pages/mypage/account/index.tsx b/src/pages/mypage/account/index.tsx index 7e3ff84..e8773c7 100644 --- a/src/pages/mypage/account/index.tsx +++ b/src/pages/mypage/account/index.tsx @@ -1,14 +1,19 @@ import Header from '@/components/organisms/Header'; +import useLogout from '@/hooks/useLogout'; import { type NextPage } from 'next'; const FriendsListPage: NextPage = () => { + const logout = useLogout(); + return (
    -
    로그아웃
    +
    탈퇴하기
    diff --git a/src/pages/mypage/index.tsx b/src/pages/mypage/index.tsx index 199d6ad..d4491c6 100644 --- a/src/pages/mypage/index.tsx +++ b/src/pages/mypage/index.tsx @@ -15,11 +15,7 @@ import { QuestionIcon, SettingIcon, } from '@/assets/icons'; -import { - useGetMe, - useGetMyFriendsCount, - useGetMyIngredientsCount, -} from '@/hooks/queries/mypage'; +import { useGetCount, useGetMe } from '@/hooks/queries/mypage'; import { returnProfileImg } from '@/utils/returnProfileImg'; const GENERAGE_NAV_LIST = [ @@ -49,9 +45,8 @@ const ETC_NAV_LIST = [ const Mypage: NextPage = () => { const data = useGetMe(); - const myFriendsCount = useGetMyFriendsCount(); - const myIngredientsCount = useGetMyIngredientsCount(); + const count = useGetCount(); return (
    @@ -78,11 +73,11 @@ const Mypage: NextPage = () => {
    - +
    - +
    - +
    diff --git a/src/pages/share/index.tsx b/src/pages/share/index.tsx index d4686d4..ae98b53 100644 --- a/src/pages/share/index.tsx +++ b/src/pages/share/index.tsx @@ -23,7 +23,7 @@ import { useObserver } from '@/hooks/useObserver'; const TABS: TabLabel[] = [ { label: '나눔 신청', value: 'SHARE_START' }, { label: '나눔 중', value: 'SHARE_IN_PROGRESS' }, - { label: '나눔 완료', value: 'SHARE_COMPLETE' }, + { label: '나눔 완료', value: 'SHARE_END' }, ]; const SORT_TYPES: SortLabel[] = [ diff --git a/src/types/common/index.d.ts b/src/types/common/index.d.ts index 5015f2d..f08f5d1 100644 --- a/src/types/common/index.d.ts +++ b/src/types/common/index.d.ts @@ -21,3 +21,5 @@ export interface IngredientType { name: string; iconImage: string; } + +export type LocationEnum = 'FREEZING' | 'REFRIGERATION'; diff --git a/src/types/fridge/index.d.ts b/src/types/fridge/index.d.ts index e97f18f..9c3e6bc 100644 --- a/src/types/fridge/index.d.ts +++ b/src/types/fridge/index.d.ts @@ -5,6 +5,7 @@ export interface IngredientType { export interface IngredientDetailType { ingredientDetailId: number; + iconImage: string; name: string; quantity: number; location: string; diff --git a/yarn.lock b/yarn.lock index 6f1b243..cdd84f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5613,6 +5613,11 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== +clsx@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" + integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -10100,6 +10105,14 @@ react-dom@^18: loose-envify "^1.1.0" scheduler "^0.23.0" +react-draggable@^4.4.6: + version "4.4.6" + resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.6.tgz#63343ee945770881ca1256a5b6fa5c9f5983fe1e" + integrity sha512-LtY5Xw1zTPqHkVmtM3X8MUOxNDOUhv/khTgBgrUvwaS064bwVvxT+q5El0uUFNx5IEPKXuRejr7UqLwBIg5pdw== + dependencies: + clsx "^1.1.1" + prop-types "^15.8.1" + react-element-to-jsx-string@^15.0.0: version "15.0.0" resolved "https://registry.yarnpkg.com/react-element-to-jsx-string/-/react-element-to-jsx-string-15.0.0.tgz#1cafd5b6ad41946ffc8755e254da3fc752a01ac6"