From 9dc41495f0574825ff97ec5cc2ca07135e1c953c Mon Sep 17 00:00:00 2001 From: gimdogyun Date: Wed, 20 Nov 2024 13:02:20 +0900 Subject: [PATCH 1/5] feat: post image - #147 --- src/api/imageApi.ts | 63 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/src/api/imageApi.ts b/src/api/imageApi.ts index 5a9c755..eca2d31 100644 --- a/src/api/imageApi.ts +++ b/src/api/imageApi.ts @@ -1,12 +1,50 @@ import { useMutation } from "@tanstack/react-query"; -import { needAuthDefaultApi } from "@api/axiosInstance"; +import { externalApi, needAuthDefaultApi } from "@api/axiosInstance"; +type ImageKeyPrefix = "FARM" | "FARM_REVIEW" | "PRODUCT" | "PRODUCT_REVIEW" | "MEMBER_PROFILE" | "PRODUCT_INTRO"; + +const getImageUpdatePresignedUrl = async (keyPrefix: ImageKeyPrefix) => + needAuthDefaultApi.get("/api/s3/presigned-url-put", { params: { keyPrefix } }); + +const putImage2S3 = async (presignedUrl: string, image: File) => { + const formData = new FormData(); + formData.append("image", image as Blob); + + return externalApi.put(presignedUrl, formData, { + headers: { + "Content-Type": "multipart/form-data", + }, + }); +}; + +const putImage = async (type: ImageKeyPrefix, image: File) => { + const getPresignedUrlResponse = await getImageUpdatePresignedUrl(type); + if (!getPresignedUrlResponse.data) { + throw new Error("Failed to get presigned URL"); + } + const { presignedPutUrl, keyName, objectUrl } = getPresignedUrlResponse.data; + const putImageResponse = await putImage2S3(presignedPutUrl, image); + if (putImageResponse.status === 200) { + return { + imageUrl: objectUrl, + objectKey: keyName, + }; + } + throw new Error("Failed to put image"); +}; + +type PostImageProps = { + type: ImageKeyPrefix; + image: File; + referenceId: number; +}; const usePostImage = () => { - const fetcher = (img: string) => { - const formData = new FormData(); - formData.append("image", img); - return needAuthDefaultApi.post("/api/images", formData).then(res => res.data); - }; + const fetcher = async ({ type, image, referenceId }: PostImageProps) => + needAuthDefaultApi.post("/api/images", { + ...(await putImage(type, image)), + type, + referenceId, + }); return useMutation({ mutationFn: fetcher, @@ -14,6 +52,17 @@ const usePostImage = () => { }); }; -const usePostImages = () => null; +const usePostImages = () => { + const fetcher = async (images: PostImageProps[]) => { + const promises = images.map(image => putImage(image.type, image.image)); + const results = await Promise.all(promises); + return needAuthDefaultApi.post("/api/images", results); + }; + + return useMutation({ + mutationFn: fetcher, + onSuccess: data => data, + }); +}; export { usePostImage, usePostImages }; From 6b90de3ed16cb978ced31851a69551707869ffbd Mon Sep 17 00:00:00 2001 From: gimdogyun Date: Wed, 20 Nov 2024 13:10:26 +0900 Subject: [PATCH 2/5] fix: disabled best Schedule - #147 --- .../features/SchedulePage/BestScheduleSection.tsx | 10 +++++++++- .../features/SchedulePage/ScheduleCard.tsx | 14 +++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/components/features/SchedulePage/BestScheduleSection.tsx b/src/components/features/SchedulePage/BestScheduleSection.tsx index d9a5068..2240eb6 100644 --- a/src/components/features/SchedulePage/BestScheduleSection.tsx +++ b/src/components/features/SchedulePage/BestScheduleSection.tsx @@ -8,7 +8,15 @@ const BestScheduleSection = () => ( 이번주 Best - + ({ + ...item, + disabled: true, + }))} + columns={2} + gap="20px" + ItemComponent={ScheduleCard} + /> ); diff --git a/src/components/features/SchedulePage/ScheduleCard.tsx b/src/components/features/SchedulePage/ScheduleCard.tsx index be926cb..bc8f555 100644 --- a/src/components/features/SchedulePage/ScheduleCard.tsx +++ b/src/components/features/SchedulePage/ScheduleCard.tsx @@ -4,11 +4,11 @@ import ImageCard, { ImageCardProps } from "@components/common/ImageCard"; import { Schedule } from "@type/index"; type ScheduleCardProps = ImageCardProps & { - item: Schedule; + item: Schedule & { disabled?: boolean }; }; const ScheduleCard = ({ item, ...props }: ScheduleCardProps) => ( - + ( brightness: item?.mainImage ? 1 : 0.6, }} bgImg={item.mainImage} - _hover={{ - transform: "scale(1.05)", - }} + _hover={ + !item?.disabled + ? { + transform: "scale(1.05)", + } + : {} + } > From 276c3f5f9df0763c0d58b4e13552df012362d182 Mon Sep 17 00:00:00 2001 From: gimdogyun Date: Wed, 20 Nov 2024 13:24:22 +0900 Subject: [PATCH 3/5] feat: get farms - #147 --- src/api/farmApi.ts | 7 +-- .../features/SchedulePage/ScheduleCard.tsx | 2 +- src/mocks/mockItem/mockSchedule.ts | 43 ++++++++++++++++--- src/pages/SchedulePage/index.tsx | 6 ++- src/types/index.ts | 6 ++- 5 files changed, 50 insertions(+), 14 deletions(-) diff --git a/src/api/farmApi.ts b/src/api/farmApi.ts index 266d025..ff04e7f 100644 --- a/src/api/farmApi.ts +++ b/src/api/farmApi.ts @@ -34,12 +34,13 @@ const useGetFarm = () => { }); }; -const useGetFarms = () => { +const useGetFarms = (categoryId: number | null = 0) => { const fetcher = () => defaultApi.get(`/api/farms`).then(({ data }) => data); + const categoryFetcher = () => defaultApi.get(`/api/farms/category/${categoryId}`).then(({ data }) => data); return useQuery({ - queryKey: ["farms"], - queryFn: fetcher, + queryKey: ["farms", categoryId], + queryFn: categoryId !== 0 ? categoryFetcher : fetcher, }); }; diff --git a/src/components/features/SchedulePage/ScheduleCard.tsx b/src/components/features/SchedulePage/ScheduleCard.tsx index bc8f555..cdd7a54 100644 --- a/src/components/features/SchedulePage/ScheduleCard.tsx +++ b/src/components/features/SchedulePage/ScheduleCard.tsx @@ -27,7 +27,7 @@ const ScheduleCard = ({ item, ...props }: ScheduleCardProps) => ( > - {item.farm.address} + {item.address} {item.name} diff --git a/src/mocks/mockItem/mockSchedule.ts b/src/mocks/mockItem/mockSchedule.ts index 729538d..1b7afa8 100644 --- a/src/mocks/mockItem/mockSchedule.ts +++ b/src/mocks/mockItem/mockSchedule.ts @@ -1,6 +1,5 @@ import mockImage1 from "@assets/Image/Farm/Best1.png"; import mockImage2 from "@assets/Image/Farm/Best2.png"; -import mockFarms from "@mocks/mockItem/mockFarms"; import { Schedule } from "@type/index"; const mockSchedule: Schedule[] = [ @@ -8,33 +7,63 @@ const mockSchedule: Schedule[] = [ id: 1, name: "건호네 포도따기 체험", mainImage: mockImage1, - farm: mockFarms[0], + address: "부산진구 개금동", + addressDetail: "123-456", + latitude: 35.123456, + longitude: 129.123456, + description: + "가끔 지민은 학교에서 심각하게 집에 가고싶을 때마다 달달한 복숭아 아이스티를 마시며 향수병을 달랩니다.", }, { id: 2, name: "도균이네 가지따기 체험", mainImage: mockImage2, - farm: mockFarms[4], + address: "부산 장전동", + addressDetail: "123-456", + latitude: 35.123456, + longitude: 129.123456, + description: + "가끔 지민은 학교에서 심각하게 집에 가고싶을 때마다 달달한 복숭아 아이스티를 마시며 향수병을 달랩니다.", }, { id: 3, name: "영훈이네 사과따기 체험", - farm: mockFarms[1], + address: "경남 양산시 덕게동", + addressDetail: "123-456", + latitude: 35.123456, + longitude: 129.123456, + description: + "가끔 지민은 학교에서 심각하게 집에 가고싶을 때마다 달달한 복숭아 아이스티를 마시며 향수병을 달랩니다.", }, { id: 4, name: "영훈이네 사과따기 체험", - farm: mockFarms[1], + address: "경남 양산시 덕게동", + addressDetail: "123-456", + latitude: 35.123456, + longitude: 129.123456, + description: + "가끔 지민은 학교에서 심각하게 집에 가고싶을 때마다 달달한 복숭아 아이스티를 마시며 향수병을 달랩니다.", }, { id: 5, name: "영훈이네 사과따기 체험", - farm: mockFarms[1], + address: "경남 양산시 덕게동", + addressDetail: "123-456", + latitude: 35.123456, + longitude: 129.123456, + description: + "가끔 지민은 학교에서 심각하게 집에 가고싶을 때마다 달달한 복숭아 아이스티를 마시며 향수병을 달랩니다.", }, { id: 6, name: "영훈이네 사과따기 체험", - farm: mockFarms[1], + address: "경남 양산시 덕게동", + addressDetail: "123-456", + latitude: 35.123456, + longitude: 129.123456, + description: + "가끔 지민은 학교에서 심각하게 집에 가고싶을 때마다 달달한 복숭아 아이스티를 마시며 향수병을 달랩니다.", }, ]; diff --git a/src/pages/SchedulePage/index.tsx b/src/pages/SchedulePage/index.tsx index fa40ac9..b1a88e1 100644 --- a/src/pages/SchedulePage/index.tsx +++ b/src/pages/SchedulePage/index.tsx @@ -1,16 +1,18 @@ import { useState } from "react"; import { Flex } from "@chakra-ui/react"; +import { useGetFarms } from "@api/farmApi"; import GridView from "@components/ItemView/GridView"; import BestScheduleSection from "@components/features/SchedulePage/BestScheduleSection"; import ScheduleCard from "@components/features/SchedulePage/ScheduleCard"; import ScheduleCategory from "@components/features/SchedulePage/ScheduleCategory"; import size from "@constants/size"; -import mockSchedule from "@mocks/mockItem/mockSchedule"; import { FarmCategory } from "@type/index"; const SchedulePage = () => { const [category, setCategory] = useState(null); + const { data: schedules } = useGetFarms(category?.id); + return ( { setCategory(ct)} /> - + ); diff --git a/src/types/index.ts b/src/types/index.ts index ca29c5f..304fb89 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -32,7 +32,11 @@ export type Review = Item & { export type Schedule = Item & { name: string; - farm: Farm; + address: string; + addressDetail: string; + latitude: number; + longitude: number; + description: string; mainImage?: string; }; From 939e0c2c90e503f668d4a788a80c586779e700f3 Mon Sep 17 00:00:00 2001 From: gimdogyun Date: Wed, 20 Nov 2024 16:34:52 +0900 Subject: [PATCH 4/5] feat: product category - #147 --- src/api/productApi.ts | 7 ++-- .../MyPage/Order/CancelOrderModal.tsx | 4 +-- .../features/MyPage/Order/RefundModal.tsx | 4 +-- .../features/MyPage/Order/useGetProduct.tsx | 14 -------- .../features/RegisterPage/Farmer.tsx | 5 ++- .../ProductList/ProductFilter/index.tsx | 35 ++++++++++++------- .../StorePage/ProductList/ProductsView.tsx | 6 ++-- .../features/StorePage/ProductList/index.tsx | 4 +-- 8 files changed, 38 insertions(+), 41 deletions(-) delete mode 100644 src/components/features/MyPage/Order/useGetProduct.tsx diff --git a/src/api/productApi.ts b/src/api/productApi.ts index 3e91d80..c14f1b7 100644 --- a/src/api/productApi.ts +++ b/src/api/productApi.ts @@ -19,12 +19,13 @@ type ProductData = { subDesc3: string; }; -const useGetProducts = () => { +const useGetProducts = (categoryId = 0) => { const fetcher = () => defaultApi.get(`/api/products`).then(({ data }) => data); + const categoryFetcher = () => defaultApi.get(`/api/categories/${categoryId}`).then(({ data }) => data); return useQuery({ - queryKey: ["products"], - queryFn: fetcher, + queryKey: ["products", categoryId], + queryFn: categoryId ? categoryFetcher : fetcher, }); }; diff --git a/src/components/features/MyPage/Order/CancelOrderModal.tsx b/src/components/features/MyPage/Order/CancelOrderModal.tsx index a211704..5c8df63 100644 --- a/src/components/features/MyPage/Order/CancelOrderModal.tsx +++ b/src/components/features/MyPage/Order/CancelOrderModal.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from "react"; import { Flex, ModalBody, ModalHeader, ModalCloseButton, Button, Text, Divider } from "@chakra-ui/react"; +import { useGetProductDetail } from "@api/productApi"; import BasicModal from "@components/common/modal/BasicModal"; -import useGetProduct from "./useGetProduct"; interface CancelOrderModalProps { isOpen: boolean; @@ -18,7 +18,7 @@ const CancelOrderModal: React.FC = ({ maxH = "800px", productId, }) => { - const { data: productData } = useGetProduct(productId); + const { data: productData } = useGetProductDetail(productId); const [totalRefundAmount, setTotalRefundAmount] = useState(0); diff --git a/src/components/features/MyPage/Order/RefundModal.tsx b/src/components/features/MyPage/Order/RefundModal.tsx index 7813e4a..5bd0f5c 100644 --- a/src/components/features/MyPage/Order/RefundModal.tsx +++ b/src/components/features/MyPage/Order/RefundModal.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from "react"; import { Flex, ModalBody, ModalHeader, ModalCloseButton, Button, Text, Divider } from "@chakra-ui/react"; +import { useGetProductDetail } from "@api/productApi"; import BasicModal from "@components/common/modal/BasicModal"; -import useGetProduct from "./useGetProduct"; interface RefundModalProps { isOpen: boolean; @@ -12,7 +12,7 @@ interface RefundModalProps { } const RefundModal: React.FC = ({ isOpen, onClose, maxW = "600px", maxH = "800px", productId }) => { - const { data: productData } = useGetProduct(productId); + const { data: productData } = useGetProductDetail(productId); const [totalRefundAmount, setTotalRefundAmount] = useState(0); diff --git a/src/components/features/MyPage/Order/useGetProduct.tsx b/src/components/features/MyPage/Order/useGetProduct.tsx deleted file mode 100644 index 0eb104a..0000000 --- a/src/components/features/MyPage/Order/useGetProduct.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { useQuery } from "@tanstack/react-query"; -import { defaultApi } from "@api/axiosInstance"; - -const useGetProduct = (productId: number) => { - const fetcher = () => defaultApi.get(`/product/${productId}`).then(({ data }) => data); - - return useQuery({ - queryKey: ["product", productId], - queryFn: fetcher, - enabled: !!productId, - }); -}; - -export default useGetProduct; diff --git a/src/components/features/RegisterPage/Farmer.tsx b/src/components/features/RegisterPage/Farmer.tsx index 57ffe5e..24b8d17 100644 --- a/src/components/features/RegisterPage/Farmer.tsx +++ b/src/components/features/RegisterPage/Farmer.tsx @@ -3,6 +3,7 @@ import { useNavigate } from "react-router-dom"; import { Button, Text, Flex, Input, Image } from "@chakra-ui/react"; import { useCreateFarmer } from "@api/emailApi"; import call from "@assets/logo/Call.png"; +import useLogin from "@hooks/useLogin"; type FarmerData = { name: string; @@ -26,10 +27,12 @@ const Farmer = () => { const { mutateAsync: createFarmer } = useCreateFarmer(); const navigate = useNavigate(); + const { refreshLogin } = useLogin(); + const handleRegister = () => { createFarmer(farmerData) .then(() => { - navigate("/"); + refreshLogin().then(() => navigate("/")); }) .catch(() => { alert("농부 등록에 실패했습니다."); diff --git a/src/components/features/StorePage/ProductList/ProductFilter/index.tsx b/src/components/features/StorePage/ProductList/ProductFilter/index.tsx index 66c6bb3..7b31e8b 100644 --- a/src/components/features/StorePage/ProductList/ProductFilter/index.tsx +++ b/src/components/features/StorePage/ProductList/ProductFilter/index.tsx @@ -1,24 +1,33 @@ import { Divider, Flex, Text } from "@chakra-ui/react"; +import { useGetProductCategories } from "@api/categoryApi"; import ProductGroupView from "@components/features/StorePage/ProductList/ProductFilter/ProductGroupView"; -import { ProductFilterItem } from "@components/features/StorePage/ProductList/ProductFilter/type"; import productGroup from "@constants/productGroup"; import useFilters, { UseFilters } from "@hooks/useFilters"; +import { encodeCategory } from "@utils/categoryParser"; type ProductFilterProps = { - items?: ProductFilterItem[]; filterState?: UseFilters; }; -const ProductFilter = ({ items = [], filterState = useFilters() }: ProductFilterProps) => ( - - - 필터 - - - {productGroup.map(group => ( - - ))} - -); +const ProductFilter = ({ filterState = useFilters() }: ProductFilterProps) => { + const { data: productCategories } = useGetProductCategories(); + + return ( + + + 필터 + + + {productGroup.map(group => ( + + ))} + + ); +}; export default ProductFilter; diff --git a/src/components/features/StorePage/ProductList/ProductsView.tsx b/src/components/features/StorePage/ProductList/ProductsView.tsx index 691d04d..1898017 100644 --- a/src/components/features/StorePage/ProductList/ProductsView.tsx +++ b/src/components/features/StorePage/ProductList/ProductsView.tsx @@ -1,6 +1,6 @@ +import { useGetProducts } from "@api/productApi"; import GridView, { GridViewProps } from "@components/ItemView/GridView"; import ProductCard from "@components/features/StorePage/ProductCard"; -import mockProducts from "@mocks/mockItem/mockProducts"; import { Product } from "@type/index"; type ProductsViewProps = { @@ -8,9 +8,9 @@ type ProductsViewProps = { } & Omit, "items" | "ItemComponent">; const ProductsView = ({ filters, ...props }: ProductsViewProps) => { - const filteredProducts = mockProducts.filter(() => filters.length === 0); + const { data: products } = useGetProducts(filters[0] ? Number(filters[0]) : 0); - return ; + return ; }; export default ProductsView; diff --git a/src/components/features/StorePage/ProductList/index.tsx b/src/components/features/StorePage/ProductList/index.tsx index abb04fc..6209d36 100644 --- a/src/components/features/StorePage/ProductList/index.tsx +++ b/src/components/features/StorePage/ProductList/index.tsx @@ -2,15 +2,13 @@ import { Flex } from "@chakra-ui/react"; import ProductFilter from "@components/features/StorePage/ProductList/ProductFilter"; import ProductsView from "@components/features/StorePage/ProductList/ProductsView"; import useFilters from "@hooks/useFilters"; -import mockCategory from "@mocks/mockItem/mockCategory"; -import { encodeCategory } from "@utils/categoryParser"; const ProductList = () => { const productFilterState = useFilters(); return ( - + From f09d5f8d946a1ce31b8cb572f60686b42ff7cd27 Mon Sep 17 00:00:00 2001 From: gimdogyun Date: Wed, 20 Nov 2024 16:38:27 +0900 Subject: [PATCH 5/5] feat: product link - #147 --- .../SchedulePage/BestScheduleSection.tsx | 1 - .../features/SchedulePage/ScheduleCard.tsx | 6 +++--- .../features/StorePage/ProductCard.tsx | 10 +++++----- .../StorePage/ProductList/ProductsView.tsx | 8 +++++++- src/pages/SchedulePage/index.tsx | 12 ++++++++++-- src/pages/SellerPage/SellerProductList.tsx | 18 ++++++++++-------- 6 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/components/features/SchedulePage/BestScheduleSection.tsx b/src/components/features/SchedulePage/BestScheduleSection.tsx index 2240eb6..f81be3e 100644 --- a/src/components/features/SchedulePage/BestScheduleSection.tsx +++ b/src/components/features/SchedulePage/BestScheduleSection.tsx @@ -11,7 +11,6 @@ const BestScheduleSection = () => ( ({ ...item, - disabled: true, }))} columns={2} gap="20px" diff --git a/src/components/features/SchedulePage/ScheduleCard.tsx b/src/components/features/SchedulePage/ScheduleCard.tsx index cdd7a54..18611fb 100644 --- a/src/components/features/SchedulePage/ScheduleCard.tsx +++ b/src/components/features/SchedulePage/ScheduleCard.tsx @@ -4,11 +4,11 @@ import ImageCard, { ImageCardProps } from "@components/common/ImageCard"; import { Schedule } from "@type/index"; type ScheduleCardProps = ImageCardProps & { - item: Schedule & { disabled?: boolean }; + item: Schedule & { link?: string }; }; const ScheduleCard = ({ item, ...props }: ScheduleCardProps) => ( - + ( }} bgImg={item.mainImage} _hover={ - !item?.disabled + item.link ? { transform: "scale(1.05)", } diff --git a/src/components/features/StorePage/ProductCard.tsx b/src/components/features/StorePage/ProductCard.tsx index 1f15241..115453c 100644 --- a/src/components/features/StorePage/ProductCard.tsx +++ b/src/components/features/StorePage/ProductCard.tsx @@ -1,17 +1,17 @@ import { Link } from "react-router-dom"; -import { Flex, Text } from "@chakra-ui/react"; +import { Box, Flex, Text } from "@chakra-ui/react"; import Avatar from "@components/common/Avatar"; import Card, { CardProps } from "@components/common/Card"; import Image from "@components/common/Image"; import { Product } from "@type/index"; export type ProductCardProps = { - item: Product; + item: Product & { link?: string }; } & CardProps; const ProductCard = ({ item, ...props }: ProductCardProps) => ( - - + + {item.name} @@ -34,7 +34,7 @@ const ProductCard = ({ item, ...props }: ProductCardProps) => ( {item.farm.name} - + ); export default ProductCard; diff --git a/src/components/features/StorePage/ProductList/ProductsView.tsx b/src/components/features/StorePage/ProductList/ProductsView.tsx index 1898017..7c17f47 100644 --- a/src/components/features/StorePage/ProductList/ProductsView.tsx +++ b/src/components/features/StorePage/ProductList/ProductsView.tsx @@ -10,7 +10,13 @@ type ProductsViewProps = { const ProductsView = ({ filters, ...props }: ProductsViewProps) => { const { data: products } = useGetProducts(filters[0] ? Number(filters[0]) : 0); - return ; + return ( + ({ ...p, link: `/store/${p.id}` }))} + ItemComponent={ProductCard} + {...props} + /> + ); }; export default ProductsView; diff --git a/src/pages/SchedulePage/index.tsx b/src/pages/SchedulePage/index.tsx index b1a88e1..ab3bd4b 100644 --- a/src/pages/SchedulePage/index.tsx +++ b/src/pages/SchedulePage/index.tsx @@ -6,7 +6,7 @@ import BestScheduleSection from "@components/features/SchedulePage/BestScheduleS import ScheduleCard from "@components/features/SchedulePage/ScheduleCard"; import ScheduleCategory from "@components/features/SchedulePage/ScheduleCategory"; import size from "@constants/size"; -import { FarmCategory } from "@type/index"; +import { FarmCategory, Schedule } from "@type/index"; const SchedulePage = () => { const [category, setCategory] = useState(null); @@ -24,7 +24,15 @@ const SchedulePage = () => { setCategory(ct)} /> - + ({ + ...s, + link: `/schedule/${s.id}`, + }))} + ItemComponent={ScheduleCard} + columns={3} + gap="10" + /> ); diff --git a/src/pages/SellerPage/SellerProductList.tsx b/src/pages/SellerPage/SellerProductList.tsx index 2d58f34..d8ca983 100644 --- a/src/pages/SellerPage/SellerProductList.tsx +++ b/src/pages/SellerPage/SellerProductList.tsx @@ -1,19 +1,21 @@ -import { useNavigate } from "react-router-dom"; import { Box } from "@chakra-ui/react"; import GridView from "@components/ItemView/GridView"; import Card from "@components/common/Card"; -import ProductCard, { ProductCardProps } from "@components/features/StorePage/ProductCard"; +import ProductCard from "@components/features/StorePage/ProductCard"; import mockProducts from "@mocks/mockItem/mockProducts"; -const EditProductCard = (props: ProductCardProps) => { - const navigate = useNavigate(); - return navigate(`/seller/product-edit/${props?.item.id}`)} />; -}; - const SellerProductListPage = () => ( - + ({ + ...p, + link: `/seller/product-edit/${p.id}`, + }))} + ItemComponent={ProductCard} + columns={3} + gap="10" + /> );