From 2801f949ff0ace2fbbcfec61bcaf09b2b2643659 Mon Sep 17 00:00:00 2001 From: "(hoooooony)" <(cjh41820@gmail.com)> Date: Wed, 10 Apr 2024 21:06:51 +0900 Subject: [PATCH 01/12] =?UTF-8?q?feat:=20=EC=82=AC=EC=9E=A5=EB=8B=98=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=BD=94=EC=9D=B8=EA=B3=BC=20?= =?UTF-8?q?=EB=98=91=EA=B0=99=EC=9D=B4=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/shop/index.ts | 2 + src/assets/svg/mystore/hidden-info-arrow.svg | 3 + src/assets/svg/mystore/see-info-arrow.svg | 3 + .../Modal/ImageModal/ImageModal.module.scss | 108 +++++++++++++++ .../ImageModal/hooks/useModalKeyboardEvent.ts | 26 ++++ .../common/Modal/ImageModal/index.tsx | 69 ++++++++++ src/component/common/Modal/PortalProvider.tsx | 73 ++++++++++ src/index.tsx | 9 +- src/model/shopInfo/myShopInfo.ts | 14 ++ src/page/MyShopPage/MyShopPage.module.scss | 27 ++++ .../EventTable/EventTable.module.scss | 3 + .../components/EventCard.module.scss | 80 +++++++++++ .../EventTable/components/index.tsx | 65 +++++++++ .../components/EventTable/index.tsx | 44 ++++++ .../MenuTable/MenuTable.module.scss | 125 ++++++++++++++++++ .../MyShopPage/components/MenuTable/index.tsx | 125 ++++++++++++++++++ src/page/MyShopPage/index.tsx | 52 +++++++- src/utils/constant/menu.ts | 25 ++++ src/utils/hooks/useModalPortal.ts | 14 ++ src/utils/hooks/useMoveScroll.ts | 19 +++ 20 files changed, 878 insertions(+), 8 deletions(-) create mode 100644 src/assets/svg/mystore/hidden-info-arrow.svg create mode 100644 src/assets/svg/mystore/see-info-arrow.svg create mode 100644 src/component/common/Modal/ImageModal/ImageModal.module.scss create mode 100644 src/component/common/Modal/ImageModal/hooks/useModalKeyboardEvent.ts create mode 100644 src/component/common/Modal/ImageModal/index.tsx create mode 100644 src/component/common/Modal/PortalProvider.tsx create mode 100644 src/page/MyShopPage/components/EventTable/EventTable.module.scss create mode 100644 src/page/MyShopPage/components/EventTable/components/EventCard.module.scss create mode 100644 src/page/MyShopPage/components/EventTable/components/index.tsx create mode 100644 src/page/MyShopPage/components/EventTable/index.tsx create mode 100644 src/page/MyShopPage/components/MenuTable/MenuTable.module.scss create mode 100644 src/page/MyShopPage/components/MenuTable/index.tsx create mode 100644 src/utils/constant/menu.ts create mode 100644 src/utils/hooks/useModalPortal.ts create mode 100644 src/utils/hooks/useMoveScroll.ts diff --git a/src/api/shop/index.ts b/src/api/shop/index.ts index 8c01cb54..590ce3a7 100644 --- a/src/api/shop/index.ts +++ b/src/api/shop/index.ts @@ -39,3 +39,5 @@ export const modifyMenu = (menuId:number, param:NewMenu) => accessClient.put(`/o export const putShop = (id: number, data: OwnerShop) => accessClient.put(`/owner/shops/${id}`, data); export const deleteMenu = (menuId:number) => accessClient.delete(`/owner/shops/menus/${menuId}`); + +export const getStoreEventList = (id : string) => accessClient.get(`금방 만들어준데요./${id}`); diff --git a/src/assets/svg/mystore/hidden-info-arrow.svg b/src/assets/svg/mystore/hidden-info-arrow.svg new file mode 100644 index 00000000..6b3cc1e5 --- /dev/null +++ b/src/assets/svg/mystore/hidden-info-arrow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/assets/svg/mystore/see-info-arrow.svg b/src/assets/svg/mystore/see-info-arrow.svg new file mode 100644 index 00000000..5826e6b6 --- /dev/null +++ b/src/assets/svg/mystore/see-info-arrow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/component/common/Modal/ImageModal/ImageModal.module.scss b/src/component/common/Modal/ImageModal/ImageModal.module.scss new file mode 100644 index 00000000..bde5f372 --- /dev/null +++ b/src/component/common/Modal/ImageModal/ImageModal.module.scss @@ -0,0 +1,108 @@ +@use "src/utils/styles/mediaQuery" as media; + +.background { + position: fixed; + display: flex; + justify-content: center; + align-items: center; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0 0 0 / 70%); + z-index: 21; +} + +.image { + max-width: 574px; + max-height: 100%; + position: fixed; + margin: auto; + + @include media.media-breakpoint-down(mobile) { + & { + max-width: calc(100% - 68px); + max-height: calc(100% - 100px); + } + } +} + +.arrow-button { + width: 60px; + height: 60px; + outline: none; + border: 0; + z-index: 23; + background-size: 24px 24px; + background-position: 50% 50%; + background-repeat: no-repeat; + background-color: #252525; + border-radius: 50%; + box-sizing: border-box; + position: fixed; + top: calc((100vh - 60px) / 2); + cursor: pointer; + + &:hover { + background-color: #f7941e; + } + + @include media.media-breakpoint-down(mobile) { + & { + width: 24px; + height: 24px; + background-color: transparent; + top: calc((100vh - 24px) / 2); + } + + &:hover { + background-color: transparent; + } + } + + &--next { + background-image: url("https://static.koreatech.in/assets/img/next-arrow.png"); + right: 50px; + + @include media.media-breakpoint-down(mobile) { + right: 10px; + } + } + + &--prev { + background-image: url("https://static.koreatech.in/assets/img/prev-arrow.png"); + left: 50px; + + @include media.media-breakpoint-down(mobile) { + left: 10px; + } + } +} + +.close { + border: 0; + outline: 0; + position: fixed; + background-color: rgba(0 0 0 / 0%); + top: 33px; + right: 62px; + width: 33px; + height: 41px; + cursor: pointer; + background-image: url("https://static.koreatech.in/assets/img/close.png"); + + @include media.media-breakpoint-down(mobile) { + & { + top: 20px; + right: 20px; + width: 24px; + height: 24px; + background-size: 24px; + background-color: transparent; + } + + &:hover { + background-color: transparent; + } + } +} diff --git a/src/component/common/Modal/ImageModal/hooks/useModalKeyboardEvent.ts b/src/component/common/Modal/ImageModal/hooks/useModalKeyboardEvent.ts new file mode 100644 index 00000000..3070f309 --- /dev/null +++ b/src/component/common/Modal/ImageModal/hooks/useModalKeyboardEvent.ts @@ -0,0 +1,26 @@ +import React from 'react'; + +interface KeyboardEventProps { + onClose: () => void + onChangeImageIndex: (move: number) => void +} + +function useModalKeyboardEvent({ onClose, onChangeImageIndex }: KeyboardEventProps) { + React.useEffect(() => { + function pressKey(event: KeyboardEvent) { + if (event.code === 'Escape') { + onClose(); + } else if (event.code === 'ArrowLeft') { + onChangeImageIndex(-1); + } else if (event.code === 'ArrowRight') { + onChangeImageIndex(1); + } + } + window.addEventListener('keydown', pressKey, true); + return () => { + window.removeEventListener('keydown', pressKey, true); + }; + }, [onClose, onChangeImageIndex]); +} + +export default useModalKeyboardEvent; diff --git a/src/component/common/Modal/ImageModal/index.tsx b/src/component/common/Modal/ImageModal/index.tsx new file mode 100644 index 00000000..2eeefae3 --- /dev/null +++ b/src/component/common/Modal/ImageModal/index.tsx @@ -0,0 +1,69 @@ +import React from 'react'; +import cn from 'utils/ts/className'; +import styles from './ImageModal.module.scss'; +import useModalKeyboardEvent from './hooks/useModalKeyboardEvent'; + +export interface ImageModalProps { + imageList: string[] + imageIndex: number + onClose: () => void +} + +function ImageModal({ + imageList, + imageIndex, + onClose, +}: ImageModalProps) { + const [selectedIndex, setSelectedIndex] = React.useState(imageIndex); + const onChangeImageIndex = React.useCallback((move: number) => { + if (move < 0) { + return (selectedIndex !== 0 && ( + setSelectedIndex(selectedIndex + move) + )); + } + return (selectedIndex !== imageList.length - 1 && ( + setSelectedIndex(selectedIndex + move) + )); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedIndex]); // imageList 의존성 불필요 + + useModalKeyboardEvent({ onClose, onChangeImageIndex }); + + React.useEffect(() => { + const body = document.querySelector('body'); + body!.style.overflow = 'hidden'; + + return () => { body!.style.overflow = 'auto'; }; + }, []); + + return ( +
+ {selectedIndex !== 0 && ( +
+ ); +} + +export default ImageModal; diff --git a/src/component/common/Modal/PortalProvider.tsx b/src/component/common/Modal/PortalProvider.tsx new file mode 100644 index 00000000..3ec5a9c5 --- /dev/null +++ b/src/component/common/Modal/PortalProvider.tsx @@ -0,0 +1,73 @@ +import React, { ReactNode } from 'react'; +import ReactDOM from 'react-dom'; + +export interface Portal { + close: () => void; +} + +interface OpenOptions { + appendTo?: Element; + onClose?: () => void; +} + +type OpenFunc = ( + element: ((portal: Portal) => React.ReactElement) | React.ReactElement, + options?: OpenOptions +) => void; + +type CloseFunc = () => void; + +export interface PortalManager { + open: OpenFunc; + close: CloseFunc; +} + +export const PortalContext = React.createContext( + undefined, +); + +interface ProviderProps { + children: ReactNode +} + +const PortalProvider = function PortalProvider({ children }: ProviderProps) { + const [modalPortal, setModalPortal] = React.useState(); + + const open: OpenFunc = React.useCallback((element, options = {}) => { + const { + onClose, + } = options; + + const close: CloseFunc = () => setModalPortal(undefined); + + const portal: Portal = { + close: () => { + close(); + onClose?.(); + }, + }; + + const portalElement = ( + typeof element === 'function' ? element(portal) : element); + + const privatePortal: ReactNode = portalElement; + + setModalPortal(privatePortal); + }, []); + + const portalOption = React.useMemo(() => ({ + open, + close: () => setModalPortal(undefined), + }), [open]); + + return ( + + { children } + <> + { ReactDOM.createPortal(modalPortal, document.body) } + + + ); +}; + +export default PortalProvider; diff --git a/src/index.tsx b/src/index.tsx index c59f20c5..72ca962a 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,6 +3,7 @@ import ReactDOM from 'react-dom/client'; import './index.scss'; import { BrowserRouter } from 'react-router-dom'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import PortalProvider from 'component/common/Modal/PortalProvider'; import { ZodError } from 'zod'; import ErrorBoundary from 'component/common/ErrorBoundary'; import App from './App'; @@ -30,9 +31,11 @@ const queryClient = new QueryClient({ root.render( - - - + + + + + , ); diff --git a/src/model/shopInfo/myShopInfo.ts b/src/model/shopInfo/myShopInfo.ts index f48d1cee..41a7473c 100644 --- a/src/model/shopInfo/myShopInfo.ts +++ b/src/model/shopInfo/myShopInfo.ts @@ -58,3 +58,17 @@ export type MyShopInfoRes = z.infer; export interface MyShopParam { id: number; } + +export const StoreEvent = z.object({ + title: z.string(), + content: z.string(), + thumbnail_image: z.string(), + start_date: z.string(), + end_date: z.string(), +}); +export type StoreEvent = z.infer; +export const StoreEventResponse = z.object({ + events: z.array(StoreEvent), +}); + +export type StoreEventResponse = z.infer; diff --git a/src/page/MyShopPage/MyShopPage.module.scss b/src/page/MyShopPage/MyShopPage.module.scss index 7a7134fe..999e713b 100644 --- a/src/page/MyShopPage/MyShopPage.module.scss +++ b/src/page/MyShopPage/MyShopPage.module.scss @@ -1,3 +1,5 @@ +@use "src/utils/styles/mediaQuery" as media; + .container { width: 1131px; margin: 0 auto; @@ -86,3 +88,28 @@ a { text-decoration: none; } + +.tap { + display: grid; + grid-template-columns: 1fr 1fr; + border-bottom: 1.5px solid #eee; + + &__type { + font-size: 20px; + font-weight: 600; + border: none; + background: none; + padding: 10px 0; + color: #8e8e8e; + cursor: pointer; + + &--active { + color: #175c8e; + border-bottom: 1.5px solid #175c8e; + } + + @include media.media-breakpoint-down(mobile) { + font-size: 16px; + } + } +} diff --git a/src/page/MyShopPage/components/EventTable/EventTable.module.scss b/src/page/MyShopPage/components/EventTable/EventTable.module.scss new file mode 100644 index 00000000..a4ce72ce --- /dev/null +++ b/src/page/MyShopPage/components/EventTable/EventTable.module.scss @@ -0,0 +1,3 @@ +.eventContainer { + padding: 5px 24px; +} diff --git a/src/page/MyShopPage/components/EventTable/components/EventCard.module.scss b/src/page/MyShopPage/components/EventTable/components/EventCard.module.scss new file mode 100644 index 00000000..97adbfb2 --- /dev/null +++ b/src/page/MyShopPage/components/EventTable/components/EventCard.module.scss @@ -0,0 +1,80 @@ +.eventCard { + padding: 10px 0; + display: flex; + gap: 16px; + + &--nonHidden { + padding: 10px 0; + display: flex; + gap: 16px; + flex-direction: column; + } +} + +.eventThumbail { + width: 72px; + height: 80px; + border-radius: 5px; + + &--nonHidden { + width: 100%; + height: auto; + } +} + +.event-info { + &__header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 5px; + } +} + +.arrow-button { + border: 0; + background-color: transparent; + padding-bottom: 5px; + white-space: nowrap; + display: flex; + align-items: center; + gap: 4px; + color: #8e8e8e; + font-size: 12px; +} + +.title { + color: #000; + font-size: 16px; + font-weight: 500; + line-height: normal; +} + +/* stylelint-disable value-no-vendor-prefix */ +.eventContent { + max-height: 28px; + max-width: 239px; + margin-top: 8px; + overflow: hidden; + color: #8e8e8e; + text-overflow: ellipsis; + font-size: 12px; + line-height: normal; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + + &--nonHidden { + display: block; + max-height: none; + } +} +/* stylelint-enable value-no-vendor-prefix */ + +.eventUpdatedAt { + margin-top: 6px; + color: #8e8e8e; + font-size: 12px; + font-style: normal; + line-height: 15.3px; +} diff --git a/src/page/MyShopPage/components/EventTable/components/index.tsx b/src/page/MyShopPage/components/EventTable/components/index.tsx new file mode 100644 index 00000000..02b4146d --- /dev/null +++ b/src/page/MyShopPage/components/EventTable/components/index.tsx @@ -0,0 +1,65 @@ +import { useState } from 'react'; +import { ReactComponent as SeeInfoArrow } from 'assets/svg/mystore/see-info-arrow.svg'; +import { ReactComponent as HiddenInfoArrow } from 'assets/svg/mystore/hidden-info-arrow.svg'; +import cn from 'utils/ts/className'; +import { StoreEvent } from 'model/shopInfo/myShopInfo'; +import styles from './EventCard.module.scss'; + +export default function EventCard({ event }: { event: StoreEvent }) { + const [hiddenInfo, setHiddenInfo] = useState(true); + const toggleHiddenInfo = (state:boolean) => { + if (state) { + setHiddenInfo(false); + } else setHiddenInfo(true); + }; + return ( +
+ {event.thumbnail_image ? ( + {event.title} + ) : ( + KOIN service logo + )} +
+
+
{event.title}
+ +
+
+ {event.content} +
+
{event.start_date}
+
+
+ ); +} diff --git a/src/page/MyShopPage/components/EventTable/index.tsx b/src/page/MyShopPage/components/EventTable/index.tsx new file mode 100644 index 00000000..b70977be --- /dev/null +++ b/src/page/MyShopPage/components/EventTable/index.tsx @@ -0,0 +1,44 @@ +// import { useParams } from 'react-router-dom'; +import { StoreEvent } from 'model/shopInfo/myShopInfo'; +import EventCard from './components'; +// import useStoreMenus from './hooks/useStoreEventList'; +import styles from './EventTable.module.scss'; + +export default function EventTable() { + // const params = useParams(); + // const { storeEventList } = useStoreMenus(params.id!); + + const testList = { + events: [ + { + title: '대박 할인! 모든 상품 50% OFF', + content: '이번 주말만! 모든 상품을 반값에 제공합니다. 지금 바로 최고의 딜을 놓치지 마세요!', + thumbnail_image: 'https://marketplace.canva.com/EAFvpxry27Y/2/0/1600w/canva-%EB%B6%84%ED%99%8D-%ED%8C%8C%EB%9E%91-%ED%8F%AC%ED%86%A0-%EC%9D%B8%EC%A6%9D-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%9D%B8%EC%8A%A4%ED%83%80%EA%B7%B8%EB%9E%A8-%EA%B2%8C%EC%8B%9C%EB%AC%BC-9YfoHCV2VnQ.jpg', + start_date: '2024.01.01', + end_date: '2024.01.01', + }, + { + title: '신메뉴 출시 기념 이벤트', + content: '새롭게 출시한 메뉴를 첫 주문하시는 모든 고객님께 특별 사은품을 드립니다. 맛있는 신메뉴와 함께 즐거운 식사 시간을 가지세요!', + thumbnail_image: '', + start_date: '2024.01.01', + end_date: '2024.01.01', + }, + { + title: '마감 임박! 재고 정리 대방출', + content: '시즌 마감 상품을 정리합니다! 재고가 소진될 때까지 최고 70% 할인을 제공하니, 이 기회를 놓치지 마세요!', + thumbnail_image: '', + start_date: '2024.01.01', + end_date: '2024.01.01', + }, + ], + }; + + return ( +
+ {testList && testList.events.map((event: StoreEvent) => ( + + ))} +
+ ); +} diff --git a/src/page/MyShopPage/components/MenuTable/MenuTable.module.scss b/src/page/MyShopPage/components/MenuTable/MenuTable.module.scss new file mode 100644 index 00000000..64375680 --- /dev/null +++ b/src/page/MyShopPage/components/MenuTable/MenuTable.module.scss @@ -0,0 +1,125 @@ +@use "src/utils/styles/mediaQuery" as media; + +.categories { + display: flex; + gap: 13px; + margin: 16px 0; + + @include media.media-breakpoint-down(mobile) { + margin: 16px 0 0 10px; + } + + &__tag { + padding: 8px 12px; + background-color: transparent; + border: 1px solid #cacaca; + border-radius: 4px; + color: #cacaca; + cursor: pointer; + + &--active { + background-color: #175c8e; + border: 1px solid #175c8e; + color: #ffff; + } + } +} + +.menu { + @include media.media-breakpoint-down(mobile) { + padding: 10px; + border-bottom: 6px solid #f5f5f5; + + &:last-child { + border-bottom: none; + } + } + + &__title { + display: flex; + align-items: center; + gap: 8px; + font-size: 18px; + font-weight: 600; + color: #4590bb; + padding: 10px 0; + } +} + +.menu-info { + display: grid; + grid-template-columns: repeat(2, 1fr); + padding: 20px; + border-bottom: 1px solid #eee; + + &:last-child { + border-bottom: none; + } + + &:hover { + background-color: #eee; + } + + &__card { + display: flex; + flex-direction: column; + justify-content: center; + + &:nth-child(2) { + justify-content: center; + } + + span:nth-child(1) { + font-size: 16px; + font-weight: 600; + padding-bottom: 20px; + + @include media.media-breakpoint-down(mobile) { + padding-bottom: 12px; + width: 250px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + word-break: break-all; + } + } + + span:nth-child(2) { + color: #175c8e; + + @include media.media-breakpoint-down(mobile) { + font-size: 14px; + } + } + } +} + +.image { + display: flex; + justify-content: center; + + &:not(:first-child) { + display: none; + } + + &__button { + border: none; + background-color: transparent; + cursor: pointer; + + img { + width: 69px; + height: 69px; + } + } +} + +.empty-image { + display: flex; + justify-content: center; + align-items: center; + + img { + width: 69px; + } +} diff --git a/src/page/MyShopPage/components/MenuTable/index.tsx b/src/page/MyShopPage/components/MenuTable/index.tsx new file mode 100644 index 00000000..1e4f192c --- /dev/null +++ b/src/page/MyShopPage/components/MenuTable/index.tsx @@ -0,0 +1,125 @@ +import { useState } from 'react'; +import { MenuCategory } from 'model/shopInfo/menuCategory'; +import cn from 'utils/ts/className'; +import useMoveScroll from 'utils/hooks/useMoveScroll'; +import MENU_CATEGORY from 'utils/constant/menu'; +import styles from './MenuTable.module.scss'; + +interface MenuTableProps { + storeMenuCategories: MenuCategory[]; + onClickImage: (img: string[], index: number) => void; +} + +function MenuTable({ storeMenuCategories, onClickImage }: MenuTableProps) { + const [categoryType, setCateogoryType] = useState(storeMenuCategories[0].name); + const { elementsRef, onMoveToElement } = useMoveScroll(); + + return ( + <> +
    + {storeMenuCategories.map((menuCategories, index) => ( +
  • + +
  • + ))} +
+
+ {storeMenuCategories.map((menuCategories, index) => ( +
{ elementsRef.current[index] = element; }} + > + {MENU_CATEGORY.map((category) => ( + category.name === menuCategories.name && ( +
+ {category.name} + {menuCategories.name} +
+ ) + ))} + {menuCategories.menus.map((menu) => ( + menu.option_prices === null ? ( +
+ {menu.image_urls.length > 0 ? ( + menu.image_urls.map((img, idx) => ( +
+ +
+ ))) : ( +
+ KOIN service logo +
+ )} +
+ {menu.name} + + {!!menu.single_price && ( + menu.single_price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') + )} + 원 + +
+
+ ) : ( + menu.option_prices.map((item) => ( +
+ {menu.image_urls.length > 0 ? ( + menu.image_urls.map((img, idx) => ( +
+ +
+ ))) : ( +
+ KOIN service logo +
+ )} +
+ {`${menu.name} - ${item.option}`} + + {item.price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')} + 원 + +
+
+ )) + ) + ))} +
+ ))} +
+ + ); +} + +export default MenuTable; diff --git a/src/page/MyShopPage/index.tsx b/src/page/MyShopPage/index.tsx index 977f284b..9a0ff6e1 100644 --- a/src/page/MyShopPage/index.tsx +++ b/src/page/MyShopPage/index.tsx @@ -4,11 +4,17 @@ import useMediaQuery from 'utils/hooks/useMediaQuery'; import { Link, useNavigate } from 'react-router-dom'; import useBooleanState from 'utils/hooks/useBooleanState'; import { useEffect, useState } from 'react'; +import cn from 'utils/ts/className'; +import { Portal } from 'component/common/Modal/PortalProvider'; +import useModalPortal from 'utils/hooks/useModalPortal'; import showToast from 'utils/ts/showToast'; +import ImageModal from 'component/common/Modal/ImageModal'; import CatagoryMenuList from './components/CatagoryMenuList'; import StoreInfo from './components/ShopInfo'; import styles from './MyShopPage.module.scss'; import EditShopInfoModal from './components/EditShopInfoModal'; +import MenuTable from './components/MenuTable'; +import EventTable from './components/EventTable'; export default function MyShopPage() { const { isMobile } = useMediaQuery(); @@ -32,6 +38,9 @@ export default function MyShopPage() { setIsSuccess(false); } + const [tapType, setTapType] = useState('메뉴'); + const portalManager = useModalPortal(); + useEffect(() => { refetchShopData(); }, [refetchShopData, isEditShopInfoModalOpen]); @@ -42,6 +51,12 @@ export default function MyShopPage() { } }, [shopData, navigate, isLoading]); + const onClickImage = (img: string[], index: number) => { + portalManager.open((portalOption: Portal) => ( + + )); + }; + if (isMobile && shopData && isEditShopInfoModalOpen) { return ( <> @@ -81,12 +96,39 @@ export default function MyShopPage() { setIsSuccess={setIsSuccess} /> )} - {menusData && menusData.menu_categories.map((category) => ( - + + + + {tapType === '메뉴' ? ( + menusData && menusData.menu_categories.length > 0 && ( + - ))} + ) + ) + : ( + + )} ) : (
diff --git a/src/utils/constant/menu.ts b/src/utils/constant/menu.ts new file mode 100644 index 00000000..151b2345 --- /dev/null +++ b/src/utils/constant/menu.ts @@ -0,0 +1,25 @@ +// 추후 추천, 메인, 세트, 사이드로 변경 예정 +const MENU_CATEGORY = [ + { + id: 1, + name: '이벤트 메뉴', + img: 'https://static.koreatech.in/assets/img/event-menu.png', + }, + { + id: 2, + name: '대표 메뉴', + img: 'https://static.koreatech.in/assets/img/representative-menu.png', + }, + { + id: 3, + name: '사이드 메뉴', + img: 'https://static.koreatech.in/assets/img/side-menu.png', + }, + { + id: 4, + name: '세트 메뉴', + img: 'https://static.koreatech.in/assets/img/set-menu.png', + }, +]; + +export default MENU_CATEGORY; diff --git a/src/utils/hooks/useModalPortal.ts b/src/utils/hooks/useModalPortal.ts new file mode 100644 index 00000000..e1abfe69 --- /dev/null +++ b/src/utils/hooks/useModalPortal.ts @@ -0,0 +1,14 @@ +import React from 'react'; +import { PortalContext } from 'component/common/Modal/PortalProvider'; + +const useModalPortal = () => { + const context = React.useContext(PortalContext); + + if (!context) { + throw new Error('usePortals must be used within a PortalProvider'); + } + + return context; +}; + +export default useModalPortal; diff --git a/src/utils/hooks/useMoveScroll.ts b/src/utils/hooks/useMoveScroll.ts new file mode 100644 index 00000000..693a68cc --- /dev/null +++ b/src/utils/hooks/useMoveScroll.ts @@ -0,0 +1,19 @@ +import { useRef } from 'react'; + +/** + * 페이지 내에서 특정 요소로 스크롤 이동 + * @return {elements, onMoveToElement} + * - elements: 이동할 요소들의 배열 + * - onMoveToElement: 인덱스에 해당하는 요소로 이동 + */ +export default function useMoveScroll() { + const elementsRef = useRef>([]); + + const onMoveToElement = (index: number) => { + if (elementsRef.current[index]) { + elementsRef.current[index]?.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + }; + + return { elementsRef, onMoveToElement }; +} From 1e608914713f588a8d016776d7df37a365700036 Mon Sep 17 00:00:00 2001 From: "(hoooooony)" <(cjh41820@gmail.com)> Date: Wed, 10 Apr 2024 21:11:20 +0900 Subject: [PATCH 02/12] =?UTF-8?q?fix=20:=EB=A9=94=EB=89=B4=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/constant/menu.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/constant/menu.ts b/src/utils/constant/menu.ts index 151b2345..d824d465 100644 --- a/src/utils/constant/menu.ts +++ b/src/utils/constant/menu.ts @@ -2,12 +2,12 @@ const MENU_CATEGORY = [ { id: 1, - name: '이벤트 메뉴', + name: '추천 메뉴', img: 'https://static.koreatech.in/assets/img/event-menu.png', }, { id: 2, - name: '대표 메뉴', + name: '메인 메뉴', img: 'https://static.koreatech.in/assets/img/representative-menu.png', }, { From efcf0de88f121a416612fa57044437ee9c7c9151 Mon Sep 17 00:00:00 2001 From: "(hoooooony)" <(cjh41820@gmail.com)> Date: Wed, 10 Apr 2024 22:34:48 +0900 Subject: [PATCH 03/12] =?UTF-8?q?feat=20:=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B2=84=ED=8A=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/svg/mystore/add-event-icon.svg | 8 +++++ src/assets/svg/mystore/edit-event-icon.svg | 8 +++++ src/index.scss | 1 + .../EventTable/EventTable.module.scss | 27 ++++++++++++++++ .../EventTable/components/index.tsx | 1 + .../components/EventTable/index.tsx | 32 +++++++++++++++++++ 6 files changed, 77 insertions(+) create mode 100644 src/assets/svg/mystore/add-event-icon.svg create mode 100644 src/assets/svg/mystore/edit-event-icon.svg diff --git a/src/assets/svg/mystore/add-event-icon.svg b/src/assets/svg/mystore/add-event-icon.svg new file mode 100644 index 00000000..10474b0f --- /dev/null +++ b/src/assets/svg/mystore/add-event-icon.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/assets/svg/mystore/edit-event-icon.svg b/src/assets/svg/mystore/edit-event-icon.svg new file mode 100644 index 00000000..9ec58a53 --- /dev/null +++ b/src/assets/svg/mystore/edit-event-icon.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/index.scss b/src/index.scss index 6a51a47a..f4a020e9 100644 --- a/src/index.scss +++ b/src/index.scss @@ -32,3 +32,4 @@ button { -webkit-tap-highlight-color: rgb(0 0 0 / 0%); -webkit-tap-highlight-color: transparent; } + diff --git a/src/page/MyShopPage/components/EventTable/EventTable.module.scss b/src/page/MyShopPage/components/EventTable/EventTable.module.scss index a4ce72ce..2b9bb0fa 100644 --- a/src/page/MyShopPage/components/EventTable/EventTable.module.scss +++ b/src/page/MyShopPage/components/EventTable/EventTable.module.scss @@ -1,3 +1,30 @@ .eventContainer { padding: 5px 24px; } + +.manage-event-button-container { + padding: 16px 0 18px 0; + display: flex; + gap: 9px; +} + +button { + display: flex; + justify-content: center; + align-items: center; + gap: 8px; + height: 32px; + width: 100%; + border-radius: 5px; + background-color: #F5F5F5; + color: #4B4B4B; + font-size: 14px; + + &:hover { + background-color: #CACACA; + } +} + +.edit-menubar{ + background-color: #FAFAFA; +} \ No newline at end of file diff --git a/src/page/MyShopPage/components/EventTable/components/index.tsx b/src/page/MyShopPage/components/EventTable/components/index.tsx index 02b4146d..48531582 100644 --- a/src/page/MyShopPage/components/EventTable/components/index.tsx +++ b/src/page/MyShopPage/components/EventTable/components/index.tsx @@ -7,6 +7,7 @@ import styles from './EventCard.module.scss'; export default function EventCard({ event }: { event: StoreEvent }) { const [hiddenInfo, setHiddenInfo] = useState(true); + const toggleHiddenInfo = (state:boolean) => { if (state) { setHiddenInfo(false); diff --git a/src/page/MyShopPage/components/EventTable/index.tsx b/src/page/MyShopPage/components/EventTable/index.tsx index b70977be..0fa2e644 100644 --- a/src/page/MyShopPage/components/EventTable/index.tsx +++ b/src/page/MyShopPage/components/EventTable/index.tsx @@ -1,5 +1,8 @@ // import { useParams } from 'react-router-dom'; import { StoreEvent } from 'model/shopInfo/myShopInfo'; +import { useState } from 'react'; +import { ReactComponent as EditEventIcon } from 'assets/svg/mystore/edit-event-icon.svg'; +import { ReactComponent as AddEventIcon } from 'assets/svg/mystore/add-event-icon.svg'; import EventCard from './components'; // import useStoreMenus from './hooks/useStoreEventList'; import styles from './EventTable.module.scss'; @@ -7,6 +10,7 @@ import styles from './EventTable.module.scss'; export default function EventTable() { // const params = useParams(); // const { storeEventList } = useStoreMenus(params.id!); + const [editMenu, setEditMenu] = useState(false); const testList = { events: [ @@ -36,6 +40,34 @@ export default function EventTable() { return (
+
+ {editMenu ? ( +
+
+ 전체 +
+
+ ) : ( +
+ + +
+ )} +
{testList && testList.events.map((event: StoreEvent) => ( ))} From 89eec71d05c24c22e2ae8388f05c87784e3fdc60 Mon Sep 17 00:00:00 2001 From: "(hoooooony)" <(cjh41820@gmail.com)> Date: Thu, 11 Apr 2024 00:11:08 +0900 Subject: [PATCH 04/12] =?UTF-8?q?fix:=EB=B2=84=ED=8A=BC=20css=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.scss | 3 +++ .../MyShopPage/components/EventTable/EventTable.module.scss | 2 +- src/page/MyShopPage/components/EventTable/index.tsx | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/index.scss b/src/index.scss index f4a020e9..4cdd1b45 100644 --- a/src/index.scss +++ b/src/index.scss @@ -33,3 +33,6 @@ button { -webkit-tap-highlight-color: transparent; } +ul { + list-style:none +} \ No newline at end of file diff --git a/src/page/MyShopPage/components/EventTable/EventTable.module.scss b/src/page/MyShopPage/components/EventTable/EventTable.module.scss index 2b9bb0fa..5803547c 100644 --- a/src/page/MyShopPage/components/EventTable/EventTable.module.scss +++ b/src/page/MyShopPage/components/EventTable/EventTable.module.scss @@ -8,7 +8,7 @@ gap: 9px; } -button { +.manage-event-button { display: flex; justify-content: center; align-items: center; diff --git a/src/page/MyShopPage/components/EventTable/index.tsx b/src/page/MyShopPage/components/EventTable/index.tsx index 0fa2e644..7d1c8bbe 100644 --- a/src/page/MyShopPage/components/EventTable/index.tsx +++ b/src/page/MyShopPage/components/EventTable/index.tsx @@ -51,7 +51,7 @@ export default function EventTable() {
-
setSinglePrice(Number(e.target.value))} + value={singlePrice === 0 || singlePrice === null ? '' : singlePrice} + onChange={(e) => setSinglePrice(e.target.value === '' ? 0 : Number(e.target.value))} />

From d3b8b50ce872d7a1a7f14ffcd0ac3df4fe018d3e Mon Sep 17 00:00:00 2001 From: "(hoooooony)" <(cjh41820@gmail.com)> Date: Thu, 11 Apr 2024 12:33:23 +0900 Subject: [PATCH 06/12] =?UTF-8?q?feat:=20menubar=20Ui=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/svg/mystore/check.svg | 3 ++ src/assets/svg/mystore/complete-icon.svg | 9 ++++ src/assets/svg/mystore/delete-icon.svg | 9 ++++ src/assets/svg/mystore/non-check-circle.svg | 4 ++ src/assets/svg/mystore/non-check.svg | 4 ++ .../EventTable/EventTable.module.scss | 35 +++++++++++++ .../EventTable/components/index.tsx | 2 +- .../components/EventTable/index.tsx | 51 ++++++++++++++++--- 8 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 src/assets/svg/mystore/check.svg create mode 100644 src/assets/svg/mystore/complete-icon.svg create mode 100644 src/assets/svg/mystore/delete-icon.svg create mode 100644 src/assets/svg/mystore/non-check-circle.svg create mode 100644 src/assets/svg/mystore/non-check.svg diff --git a/src/assets/svg/mystore/check.svg b/src/assets/svg/mystore/check.svg new file mode 100644 index 00000000..2859e568 --- /dev/null +++ b/src/assets/svg/mystore/check.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/assets/svg/mystore/complete-icon.svg b/src/assets/svg/mystore/complete-icon.svg new file mode 100644 index 00000000..35064db5 --- /dev/null +++ b/src/assets/svg/mystore/complete-icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svg/mystore/delete-icon.svg b/src/assets/svg/mystore/delete-icon.svg new file mode 100644 index 00000000..3647042f --- /dev/null +++ b/src/assets/svg/mystore/delete-icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svg/mystore/non-check-circle.svg b/src/assets/svg/mystore/non-check-circle.svg new file mode 100644 index 00000000..d9f58a7c --- /dev/null +++ b/src/assets/svg/mystore/non-check-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/assets/svg/mystore/non-check.svg b/src/assets/svg/mystore/non-check.svg new file mode 100644 index 00000000..a0ec575b --- /dev/null +++ b/src/assets/svg/mystore/non-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/page/MyShopPage/components/EventTable/EventTable.module.scss b/src/page/MyShopPage/components/EventTable/EventTable.module.scss index 5803547c..017a2452 100644 --- a/src/page/MyShopPage/components/EventTable/EventTable.module.scss +++ b/src/page/MyShopPage/components/EventTable/EventTable.module.scss @@ -26,5 +26,40 @@ } .edit-menubar{ + display: flex; + justify-content: space-between; + background-color: #FAFAFA; + padding: 11px 15px; + border-bottom: 1px solid #EEE; +} + +.select-all-button { + display: flex; + flex-direction: column; + align-items: center; + gap: 3px; background-color: #FAFAFA; + color: #8E8E8E; + font-size: 12px; +} + +.edit-menubar--button { + display: flex; + gap: 16px; +} + +.edit-menubar--button button { + display: flex; + justify-content: center; + align-items: center; + gap: 5px; + padding: 6px 8px; + border-radius: 5px; + background: #FAFAFA; + color: #8E8E8E; + font-size: 14px; + + &:hover { + background: #EEE; + } } \ No newline at end of file diff --git a/src/page/MyShopPage/components/EventTable/components/index.tsx b/src/page/MyShopPage/components/EventTable/components/index.tsx index 48531582..01b033a9 100644 --- a/src/page/MyShopPage/components/EventTable/components/index.tsx +++ b/src/page/MyShopPage/components/EventTable/components/index.tsx @@ -59,7 +59,7 @@ export default function EventCard({ event }: { event: StoreEvent }) { > {event.content}
-
{event.start_date}
+
{event.start_date.replace(/-/g, '.')}
); diff --git a/src/page/MyShopPage/components/EventTable/index.tsx b/src/page/MyShopPage/components/EventTable/index.tsx index 7d1c8bbe..15a27a36 100644 --- a/src/page/MyShopPage/components/EventTable/index.tsx +++ b/src/page/MyShopPage/components/EventTable/index.tsx @@ -3,6 +3,10 @@ import { StoreEvent } from 'model/shopInfo/myShopInfo'; import { useState } from 'react'; import { ReactComponent as EditEventIcon } from 'assets/svg/mystore/edit-event-icon.svg'; import { ReactComponent as AddEventIcon } from 'assets/svg/mystore/add-event-icon.svg'; +import { ReactComponent as NonCheckCircle } from 'assets/svg/mystore/non-check-circle.svg'; +import { ReactComponent as DeleteIcon } from 'assets/svg/mystore/delete-icon.svg'; +import { ReactComponent as Check } from 'assets/svg/mystore/check.svg'; +import { ReactComponent as CompleteIcon } from 'assets/svg/mystore/complete-icon.svg'; import EventCard from './components'; // import useStoreMenus from './hooks/useStoreEventList'; import styles from './EventTable.module.scss'; @@ -11,6 +15,7 @@ export default function EventTable() { // const params = useParams(); // const { storeEventList } = useStoreMenus(params.id!); const [editMenu, setEditMenu] = useState(false); + const [selectAll, setSelectAll] = useState(false); const testList = { events: [ @@ -39,12 +44,42 @@ export default function EventTable() { }; return ( -
+ <>
{editMenu ? (
-
- 전체 +
+ +
+
+ + +
) : ( @@ -68,9 +103,11 @@ export default function EventTable() {
)}
- {testList && testList.events.map((event: StoreEvent) => ( - - ))} -
+
+ {testList && testList.events.map((event: StoreEvent) => ( + + ))} +
+ ); } From 33d2e4b663540e3b15e4f033103607d347c308a4 Mon Sep 17 00:00:00 2001 From: "(hoooooony)" <(cjh41820@gmail.com)> Date: Thu, 11 Apr 2024 14:58:49 +0900 Subject: [PATCH 07/12] =?UTF-8?q?feat:=20event=EB=B6=88=EB=9F=AC=EC=98=A4?= =?UTF-8?q?=EA=B8=B0=20api=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/shop/index.ts | 9 +++-- src/model/shopInfo/myShopInfo.ts | 6 +++- .../EventTable/components/index.tsx | 4 +-- .../components/EventTable/index.tsx | 34 ++----------------- src/query/KeyFactory/shopKeys.ts | 1 + src/query/shop.ts | 15 ++++++-- 6 files changed, 31 insertions(+), 38 deletions(-) diff --git a/src/api/shop/index.ts b/src/api/shop/index.ts index 590ce3a7..dd77efab 100644 --- a/src/api/shop/index.ts +++ b/src/api/shop/index.ts @@ -1,4 +1,6 @@ -import { MyShopListRes, MyShopInfoRes, MyShopParam } from 'model/shopInfo/myShopInfo'; +import { + MyShopListRes, MyShopInfoRes, MyShopParam, EventListParam, StoreEventResponse, +} from 'model/shopInfo/myShopInfo'; import { MonoMenu, MenuInfoRes } from 'model/shopInfo/menuCategory'; import { ShopListRes } from 'model/shopInfo/allShopInfo'; import { accessClient, client } from 'api'; @@ -40,4 +42,7 @@ export const putShop = (id: number, data: OwnerShop) => accessClient.put(`/owner export const deleteMenu = (menuId:number) => accessClient.delete(`/owner/shops/menus/${menuId}`); -export const getStoreEventList = (id : string) => accessClient.get(`금방 만들어준데요./${id}`); +export const getStoreEventList = async (param : EventListParam) => { + const { data } = await accessClient.get(`/owner/shops/${param.id}/event`); + return StoreEventResponse.parse(data); +}; diff --git a/src/model/shopInfo/myShopInfo.ts b/src/model/shopInfo/myShopInfo.ts index 41a7473c..8dad40f4 100644 --- a/src/model/shopInfo/myShopInfo.ts +++ b/src/model/shopInfo/myShopInfo.ts @@ -59,10 +59,14 @@ export interface MyShopParam { id: number; } +export interface EventListParam { + id : number; +} + export const StoreEvent = z.object({ title: z.string(), content: z.string(), - thumbnail_image: z.string(), + thumbnail_images: z.array(z.string()), start_date: z.string(), end_date: z.string(), }); diff --git a/src/page/MyShopPage/components/EventTable/components/index.tsx b/src/page/MyShopPage/components/EventTable/components/index.tsx index 01b033a9..76e37e65 100644 --- a/src/page/MyShopPage/components/EventTable/components/index.tsx +++ b/src/page/MyShopPage/components/EventTable/components/index.tsx @@ -20,9 +20,9 @@ export default function EventCard({ event }: { event: StoreEvent }) { [styles['eventCard--nonHidden']]: hiddenInfo === false, })} > - {event.thumbnail_image ? ( + {event.thumbnail_images ? ( {event.title}
@@ -104,7 +76,7 @@ export default function EventTable() { )}
- {testList && testList.events.map((event: StoreEvent) => ( + {evnetList && evnetList.events.map((event: StoreEvent) => ( ))}
diff --git a/src/query/KeyFactory/shopKeys.ts b/src/query/KeyFactory/shopKeys.ts index 76599bca..0b652b8c 100644 --- a/src/query/KeyFactory/shopKeys.ts +++ b/src/query/KeyFactory/shopKeys.ts @@ -4,4 +4,5 @@ export const shopKeys = { myShopList: (myShopQueryKey: string | undefined) => [...shopKeys.all, 'myShop', myShopQueryKey] as const, myShopInfo: (shopId: number) => [...shopKeys.all, 'myShopInfo', shopId] as const, myMenuInfo: (shopId: number) => [...shopKeys.all, 'myMenuInfo', shopId] as const, + eventList: (shopId: number) => [...shopKeys.all, 'eventList', shopId] as const, }; diff --git a/src/query/shop.ts b/src/query/shop.ts index 504477e4..d20098de 100644 --- a/src/query/shop.ts +++ b/src/query/shop.ts @@ -2,7 +2,7 @@ import { useMutation, useQuery, useQueryClient, useSuspenseQuery, } from '@tanstack/react-query'; import { - getMyShopList, getShopInfo, getMenuInfoList, addMenu, + getMyShopList, getShopInfo, getMenuInfoList, addMenu, getStoreEventList, } from 'api/shop'; import useUserStore from 'store/user'; import useAddMenuStore from 'store/addMenu'; @@ -51,8 +51,19 @@ const useMyShop = () => { }, }); + const { data: evnetList } = useQuery({ + queryKey: shopKeys.eventList(shopId), + queryFn: () => getStoreEventList({ id: shopId }), + }); return { - shopData, menusData, addMenuMutation, addMenuError, refetchShopData, isLoading, categoryList, + shopData, + menusData, + addMenuMutation, + addMenuError, + refetchShopData, + isLoading, + categoryList, + evnetList, }; }; From fda4212da253c5cbe185a1b7e35f6a111e09cf6f Mon Sep 17 00:00:00 2001 From: "(hoooooony)" <(cjh41820@gmail.com)> Date: Thu, 11 Apr 2024 15:34:48 +0900 Subject: [PATCH 08/12] =?UTF-8?q?refactore:=20=EC=9D=B4=EB=B2=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1=20=EC=99=84=EB=A3=8C=20=ED=9B=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/MyShopPage/components/EventTable/index.tsx | 7 ++++--- src/query/event.ts | 12 ++++++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/page/MyShopPage/components/EventTable/index.tsx b/src/page/MyShopPage/components/EventTable/index.tsx index bd43b771..9d7e6bb9 100644 --- a/src/page/MyShopPage/components/EventTable/index.tsx +++ b/src/page/MyShopPage/components/EventTable/index.tsx @@ -1,5 +1,6 @@ import { StoreEvent } from 'model/shopInfo/myShopInfo'; import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; import useMyShop from 'query/shop'; import { ReactComponent as EditEventIcon } from 'assets/svg/mystore/edit-event-icon.svg'; import { ReactComponent as AddEventIcon } from 'assets/svg/mystore/add-event-icon.svg'; @@ -11,10 +12,10 @@ import EventCard from './components'; import styles from './EventTable.module.scss'; export default function EventTable() { - const { evnetList } = useMyShop(); + const { shopData, evnetList } = useMyShop(); const [editMenu, setEditMenu] = useState(false); const [selectAll, setSelectAll] = useState(false); - + const navigate = useNavigate(); return ( <>
@@ -67,7 +68,7 @@ export default function EventTable() { + )} {event.thumbnail_images ? ( ([]); + + const toggleSelectEvent = (id: number): void => { + setSelectedEventIds((prev : number[]) => ( + prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id] + )); + }; const navigate = useNavigate(); + useEffect(() => { + if (selectAll && eventList) { + setSelectedEventIds(eventList.events.map((event : StoreEvent) => event.event_id)); + } else { + setSelectedEventIds([]); + } + }, [selectAll, eventList]); return ( <>
@@ -35,6 +50,11 @@ export default function EventTable() {
- {evnetList && evnetList.events.map((event: StoreEvent) => ( - + {eventList && eventList.events.map((event: StoreEvent) => ( + toggleSelectEvent(event.event_id)} + /> ))}
diff --git a/src/query/shop.ts b/src/query/shop.ts index d20098de..b3828831 100644 --- a/src/query/shop.ts +++ b/src/query/shop.ts @@ -51,7 +51,7 @@ const useMyShop = () => { }, }); - const { data: evnetList } = useQuery({ + const { data: eventList } = useQuery({ queryKey: shopKeys.eventList(shopId), queryFn: () => getStoreEventList({ id: shopId }), }); @@ -63,7 +63,7 @@ const useMyShop = () => { refetchShopData, isLoading, categoryList, - evnetList, + eventList, }; }; From d8b5c3f50ba4dc12d871a14bb453c92545b32628 Mon Sep 17 00:00:00 2001 From: "(hoooooony)" <(cjh41820@gmail.com)> Date: Thu, 11 Apr 2024 18:21:45 +0900 Subject: [PATCH 10/12] =?UTF-8?q?fix=20:=20css=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/MyShopPage/components/EventTable/EventTable.module.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/src/page/MyShopPage/components/EventTable/EventTable.module.scss b/src/page/MyShopPage/components/EventTable/EventTable.module.scss index b293fb3f..017a2452 100644 --- a/src/page/MyShopPage/components/EventTable/EventTable.module.scss +++ b/src/page/MyShopPage/components/EventTable/EventTable.module.scss @@ -1,6 +1,5 @@ .eventContainer { padding: 5px 24px; - width: 100%; } .manage-event-button-container { From 661152c45322c309f988e5dc849bd3387b19bc43 Mon Sep 17 00:00:00 2001 From: "(hoooooony)" <(cjh41820@gmail.com)> Date: Thu, 11 Apr 2024 18:35:29 +0900 Subject: [PATCH 11/12] =?UTF-8?q?fix=20:=20lint=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.scss | 4 +-- .../EventTable/EventTable.module.scss | 26 +++++++++---------- .../components/EventCard.module.scss | 6 ++--- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/index.scss b/src/index.scss index 4cdd1b45..fe5382b1 100644 --- a/src/index.scss +++ b/src/index.scss @@ -34,5 +34,5 @@ button { } ul { - list-style:none -} \ No newline at end of file + list-style: none; +} diff --git a/src/page/MyShopPage/components/EventTable/EventTable.module.scss b/src/page/MyShopPage/components/EventTable/EventTable.module.scss index 017a2452..afce81be 100644 --- a/src/page/MyShopPage/components/EventTable/EventTable.module.scss +++ b/src/page/MyShopPage/components/EventTable/EventTable.module.scss @@ -3,7 +3,7 @@ } .manage-event-button-container { - padding: 16px 0 18px 0; + padding: 16px 0 18px; display: flex; gap: 9px; } @@ -16,21 +16,21 @@ height: 32px; width: 100%; border-radius: 5px; - background-color: #F5F5F5; - color: #4B4B4B; + background-color: #f5f5f5; + color: #4b4b4b; font-size: 14px; &:hover { - background-color: #CACACA; + background-color: #cacaca; } } -.edit-menubar{ +.edit-menubar { display: flex; justify-content: space-between; - background-color: #FAFAFA; + background-color: #fafafa; padding: 11px 15px; - border-bottom: 1px solid #EEE; + border-bottom: 1px solid #eee; } .select-all-button { @@ -38,8 +38,8 @@ flex-direction: column; align-items: center; gap: 3px; - background-color: #FAFAFA; - color: #8E8E8E; + background-color: #fafafa; + color: #8e8e8e; font-size: 12px; } @@ -55,11 +55,11 @@ gap: 5px; padding: 6px 8px; border-radius: 5px; - background: #FAFAFA; - color: #8E8E8E; + background: #fafafa; + color: #8e8e8e; font-size: 14px; &:hover { - background: #EEE; + background: #eee; } -} \ No newline at end of file +} diff --git a/src/page/MyShopPage/components/EventTable/components/EventCard.module.scss b/src/page/MyShopPage/components/EventTable/components/EventCard.module.scss index 9b758bce..da0e454d 100644 --- a/src/page/MyShopPage/components/EventTable/components/EventCard.module.scss +++ b/src/page/MyShopPage/components/EventTable/components/EventCard.module.scss @@ -26,7 +26,7 @@ .event-info { width: 100%; - + &__header { display: flex; align-items: center; @@ -88,5 +88,5 @@ position: absolute; top: 2px; left: -7px; - background-color:transparent; -} \ No newline at end of file + background-color: transparent; +} From fe6735965ad016e3d10d8d2d893c49701273a0b1 Mon Sep 17 00:00:00 2001 From: "(hoooooony)" <(cjh41820@gmail.com)> Date: Thu, 11 Apr 2024 19:02:14 +0900 Subject: [PATCH 12/12] =?UTF-8?q?feat=20:=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/shop/index.ts | 2 ++ .../components/EventTable/index.tsx | 8 ++++++- src/query/event.ts | 21 ++++++++++++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/api/shop/index.ts b/src/api/shop/index.ts index f6f930db..f38de607 100644 --- a/src/api/shop/index.ts +++ b/src/api/shop/index.ts @@ -48,3 +48,5 @@ export const getStoreEventList = async (param : EventListParam) => { return StoreEventResponse.parse(data); }; export const addEvent = (id: string, eventInfo: EventInfo) => accessClient.post(`owner/shops/${id}/event`, eventInfo); + +export const deleteEvent = (shopId: number, eventId:number) => accessClient.delete(`owner/shops/${shopId}/events/${eventId}`); diff --git a/src/page/MyShopPage/components/EventTable/index.tsx b/src/page/MyShopPage/components/EventTable/index.tsx index 77b9731f..32c877e3 100644 --- a/src/page/MyShopPage/components/EventTable/index.tsx +++ b/src/page/MyShopPage/components/EventTable/index.tsx @@ -8,6 +8,7 @@ import { ReactComponent as NonCheckCircle } from 'assets/svg/mystore/non-check-c import { ReactComponent as DeleteIcon } from 'assets/svg/mystore/delete-icon.svg'; import { ReactComponent as Check } from 'assets/svg/mystore/check.svg'; import { ReactComponent as CompleteIcon } from 'assets/svg/mystore/complete-icon.svg'; +import { useDeleteEvent } from 'query/event'; import showToast from 'utils/ts/showToast'; import EventCard from './components'; import styles from './EventTable.module.scss'; @@ -17,6 +18,7 @@ export default function EventTable() { const [editMenu, setEditMenu] = useState(false); const [selectAll, setSelectAll] = useState(false); const [selectedEventIds, setSelectedEventIds] = useState([]); + const { mutate: deleteEvent } = useDeleteEvent(shopData!.id, selectedEventIds); const toggleSelectEvent = (id: number): void => { setSelectedEventIds((prev : number[]) => ( @@ -31,6 +33,7 @@ export default function EventTable() { setSelectedEventIds([]); } }, [selectAll, eventList]); + return ( <>
@@ -62,7 +65,10 @@ export default function EventTable() {