From 1d09800cc209ee85d9da4eec30763dea71b335b9 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Tue, 17 Dec 2024 08:52:23 +0900 Subject: [PATCH 1/6] =?UTF-8?q?refactor:=20set=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EC=A0=9C=EA=B1=B0=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Services/Benefit/index.tsx | 59 +++++++++++----------------- 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/src/pages/Services/Benefit/index.tsx b/src/pages/Services/Benefit/index.tsx index 49d7fe64..960dec6b 100644 --- a/src/pages/Services/Benefit/index.tsx +++ b/src/pages/Services/Benefit/index.tsx @@ -46,29 +46,18 @@ export default function BenefitPage() { setSelectedShop([...allId]); } }; - const openAddtionModal = () => { - setIsAdditionOpen(true); - }; - const closeAdditionModal = () => { - setIsAdditionOpen(false); - }; - const openCreateModal = () => { - setIsCreateOpen(true); - }; - const closeCreateModal = () => { - setIsCreateOpen(false); - }; - const openDeleteModal = () => { - if (selected) setIsDeleteOpen(true); - }; - const closeDeleteModal = () => { - setIsDeleteOpen(false); - }; - const openModifyModal = () => { - setIsModifyOpen(true); - }; - const closeModifyModal = () => { - setIsModifyOpen(false); + + const handleModal = (setOpenModal: React.Dispatch>, type: string, state: 'open' | 'close') => { + if (type === 'delete' && state === 'open') { + if (selected) setOpenModal(true); + return; + } + + if (state === 'open') { + setOpenModal(true); + } else { + setOpenModal(false); + } }; return ( @@ -88,13 +77,13 @@ export default function BenefitPage() { width={600} footer={null} open={isDeleteOpne} - onCancel={closeDeleteModal} - onClick={openDeleteModal} + onCancel={() => handleModal(setIsDeleteOpen, 'delete', 'close')} + onClick={() => handleModal(setIsDeleteOpen, 'delete', 'open')} isDelete > handleModal(setIsDeleteOpen, 'delete', 'close')} /> handleModal(setIsModifyOpen, 'modify', 'close')} + onClick={() => handleModal(setIsModifyOpen, 'modify', 'open')} destroyOnClose isDelete key={selected} > handleModal(setIsModifyOpen, 'modify', 'close')} selected={selected} /> @@ -120,10 +109,10 @@ export default function BenefitPage() { width={900} footer open={isCreateOpen} - onCancel={closeCreateModal} - onClick={openCreateModal} + onCancel={() => handleModal(setIsCreateOpen, 'create', 'close')} + onClick={() => handleModal(setIsCreateOpen, 'create', 'open')} > - + handleModal(setIsCreateOpen, 'create', 'close')} /> @@ -145,10 +134,10 @@ export default function BenefitPage() { width={750} footer open={isAdditionOpen} - onCancel={closeAdditionModal} - onClick={openAddtionModal} + onCancel={() => handleModal(setIsAdditionOpen, 'addition', 'close')} + onClick={() => handleModal(setIsAdditionOpen, 'addition', 'open')} > - + handleModal(setIsAdditionOpen, 'addition', 'close')} /> From 266b337bbe7570eec5bed419c66ba5fc6edb3d99 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Tue, 17 Dec 2024 10:26:17 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=ED=98=9C=ED=83=9D=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EB=B7=B0=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Services/Benefit/index.style.tsx | 45 ++++++++++++---------- src/pages/Services/Benefit/index.tsx | 30 ++++++++++----- 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/pages/Services/Benefit/index.style.tsx b/src/pages/Services/Benefit/index.style.tsx index dd9f3d30..34b593cb 100644 --- a/src/pages/Services/Benefit/index.style.tsx +++ b/src/pages/Services/Benefit/index.style.tsx @@ -33,32 +33,37 @@ export const Wrapper = styled.div` `; -export const ShopContainer = styled.div` +export const Row = styled.tr<{ isclicked: boolean }>` display: grid; - grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr; - grid-template-rows: repeat(auto-fill, 80px); - place-items: center; + grid-template-columns: 40% 60%; + cursor: pointer; + width: 100%; + height: 50px; + border: ${(props) => (props.isclicked ? '1px solid rgba(129, 173, 255, 0.8) ' : '1px solid #f0f0f0')}; `; -export const Button = styled.button<{ isclicked: boolean }>` - cursor: pointer; - width: 150px; +export const HeaderRow = styled.tr` + display: grid; + grid-template-columns: 40% 60%; + width: 100%; height: 50px; - background: #fff; - text-align: center; - transition: scale 0.2s; - border: ${(props) => (props.isclicked ? '4px solid rgba(129, 173, 255, 0.8) ' : 'none')}; - border-radius: 10px; + border: 1px solid #f0f0f0; +`; + +export const HeaderItem = styled.th` + padding: 15px; +`; + +export const TitleItem = styled.td` + padding: 15px; +`; - &:active { - scale: 0.95; - } +export const DetailItem = styled.td` + padding: 15px; `; -export const ShopListContainer = styled.div` - background: #ddd; - padding: 25px; - height: 60%; +export const ShopList = styled.table` width: 100%; - overflow-y: auto; + border-spacing: 0 10px; + border-collapse: collapse; `; diff --git a/src/pages/Services/Benefit/index.tsx b/src/pages/Services/Benefit/index.tsx index 960dec6b..1a937c3e 100644 --- a/src/pages/Services/Benefit/index.tsx +++ b/src/pages/Services/Benefit/index.tsx @@ -141,21 +141,33 @@ export default function BenefitPage() { - - {selected ? ( - + {selected ? ( + + + + 상점명 + 상세정보 + + + {data?.shops.map((shop) => ( - onShopClick(shop.id)} key={shop.id} > - {shop.name} - + + {shop.name} + + + {shop.detail} + + ))} - - ) : null} - + + + + ) : null} ); From 3ddf0a6a9bd7f78f78448bdda022a9d91f5970ff Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Tue, 17 Dec 2024 10:26:39 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=ED=98=9C=ED=83=9D=20=EC=83=81?= =?UTF-8?q?=EC=A0=90=20=EC=B6=94=EA=B0=80=ED=95=98=EA=B8=B0=20=EB=B0=98?= =?UTF-8?q?=EC=98=81=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/benefit.model.ts | 17 +++++- .../components/AdditionalModal/index.style.ts | 24 +++----- .../components/AdditionalModal/index.tsx | 61 ++++++++++++++----- src/store/api/benefit/index.ts | 4 +- 4 files changed, 71 insertions(+), 35 deletions(-) diff --git a/src/model/benefit.model.ts b/src/model/benefit.model.ts index 78c84517..146f4e3b 100644 --- a/src/model/benefit.model.ts +++ b/src/model/benefit.model.ts @@ -12,7 +12,7 @@ export interface BenefitCategoryContent { export interface GetBenefitShopsResponse { count: number; - shops: Shops[]; + shops: ShopInfo[]; } export interface Shops { @@ -20,6 +20,11 @@ export interface Shops { name: string; } +export interface ShopInfo extends Shops { + shop_benefit_map_id: number; + detail: string; +} + export interface SearchResponse { benefit_shops: Shops[]; non_benefit_shops: Shops[] @@ -41,7 +46,15 @@ export interface DeleteShopsRequest { id: number; } -export interface AddShopRequest extends DeleteShopsRequest {} +export interface ShopDetail { + shop_id: number; + detail: string; +} + +export interface AddShopRequest { + id: number; + shop_details: ShopDetail[]; +} export interface ModifyBenefitRequest { body: CreateBenefitRequest; diff --git a/src/pages/Services/Benefit/components/AdditionalModal/index.style.ts b/src/pages/Services/Benefit/components/AdditionalModal/index.style.ts index 2fb1146e..ff75c1d1 100644 --- a/src/pages/Services/Benefit/components/AdditionalModal/index.style.ts +++ b/src/pages/Services/Benefit/components/AdditionalModal/index.style.ts @@ -4,19 +4,6 @@ export const SearchWrapper = styled.div` position: relative; `; -export const SelectContainer = styled.div` - display: grid; - grid-template-columns: 1fr 1fr 1fr; - grid-template-rows: repeat(auto-fill, 50px); - place-items: center; - width: 100%; - height: 600px; - overflow: auto; - padding: 25px; - border: 0.5px solid #eeeeeeff; - background: #eee; -`; - export const FlexColumn = styled.div` display: flex; flex-direction: column; @@ -54,12 +41,12 @@ export const ButtonContent = styled.span` `; export const ButtonWrapper = styled.div` - display: relative; + position: relative; `; export const DeleteButtonWrapper = styled.button` position: absolute; - top: -10px; + top: -15px; left: -10px; background: none; border: none; @@ -72,3 +59,10 @@ export const FlexRight = styled.div` justify-content: flex-end; margin-top: 10px `; + +export const DetailInput = styled.input` + width: 100%; + height: 100%; + border: none; + outline: none; +`; diff --git a/src/pages/Services/Benefit/components/AdditionalModal/index.tsx b/src/pages/Services/Benefit/components/AdditionalModal/index.tsx index 09c1fd66..0dee0c59 100644 --- a/src/pages/Services/Benefit/components/AdditionalModal/index.tsx +++ b/src/pages/Services/Benefit/components/AdditionalModal/index.tsx @@ -6,17 +6,25 @@ import { useAddBenefitShopsMutation, useSearchShopsQuery } from 'store/api/benef import { Shops } from 'model/benefit.model'; import { MinusCircleOutlined, UploadOutlined } from '@ant-design/icons'; import * as S from './index.style'; +// eslint-disable-next-line +import * as Style from '../../index.style'; interface Props { id: number | undefined; closeAdditionModal: () => void; } +interface ShopDetail { + shop_id: number; + detail: string; +} + const { Search } = Input; export default function AdditionalModal({ id, closeAdditionModal }: Props) { const [keyword, setKeyword] = useState(''); const [isFocus, setIsFocus] = useState(false); const [shops, setShops] = useState([]); + const [details, setDetails] = useState([]); const searchRef = useRef(null); const userInput = (e: React.ChangeEvent) => { setKeyword(e.target.value); @@ -45,8 +53,7 @@ export default function AdditionalModal({ id, closeAdditionModal }: Props) { return; } if (id) { - const requestBody = shops.map((shop) => shop.id); - await addShopMutation({ id, shop_ids: requestBody }) + await addShopMutation({ id, shop_details: details }) .then(() => { message.success('상점을 추가했습니다.'); setShops([]); @@ -56,6 +63,17 @@ export default function AdditionalModal({ id, closeAdditionModal }: Props) { } }; + const handleDetail = (e: React.ChangeEvent, shopId: number) => { + const { value } = e.target; + const shopDetail = details.find((shop) => shop.shop_id === shopId); + if (shopDetail) { + const filteredDetail = details.filter((shop) => shop.shop_id !== shopId); + setDetails([...filteredDetail, { shop_id: shopId, detail: value }]); + } else { + setDetails((prev) => [...prev, { shop_id: shopId, detail: value }]); + } + }; + if (isError) message.error('상점을 추가할 수 없습니다.'); return ( @@ -87,20 +105,31 @@ export default function AdditionalModal({ id, closeAdditionModal }: Props) { 선택 상점 - - {shops.map((shop) => ( - - - - ))} - + + + + 상점명 + 상세정보 + + + + {shops.map((shop) => ( + + + + cancelAddShop(shop.id)}> + + + {shop.name} + + + + handleDetail(e, shop.id)} /> + + + ))} + + + + + ); +} diff --git a/src/pages/Services/Benefit/index.style.tsx b/src/pages/Services/Benefit/index.style.tsx index 34b593cb..f411c5c0 100644 --- a/src/pages/Services/Benefit/index.style.tsx +++ b/src/pages/Services/Benefit/index.style.tsx @@ -6,6 +6,7 @@ export const Container = styled.div` display: flex; align-items: center; flex-direction: column; + min-width: 1500px; `; export const SideContainer = styled.div` @@ -52,10 +53,12 @@ export const HeaderRow = styled.tr` export const HeaderItem = styled.th` padding: 15px; + border-right: 1px solid #f0f0f0; `; export const TitleItem = styled.td` padding: 15px; + border-right: 1px solid #f0f0f0; `; export const DetailItem = styled.td` diff --git a/src/pages/Services/Benefit/index.tsx b/src/pages/Services/Benefit/index.tsx index 1a937c3e..525075bf 100644 --- a/src/pages/Services/Benefit/index.tsx +++ b/src/pages/Services/Benefit/index.tsx @@ -9,6 +9,7 @@ import AdditionalModal from './components/AdditionalModal'; import CreationModal from './components/CreationModal'; import DeleteBenefitCategoryModal from './components/DeleteBenefitCategoryModal'; import ModifyModal from './components/ModifyModal'; +import BenefitDetailModifyModal from './components/BenefitDetailModifyModal'; export default function BenefitPage() { const [selected, setSelected] = useState(); @@ -20,6 +21,7 @@ export default function BenefitPage() { const [isCreateOpen, setIsCreateOpen] = useState(false); const [isDeleteOpne, setIsDeleteOpen] = useState(false); const [isModifyOpen, setIsModifyOpen] = useState(false); + const [isBenefitDetailOpen, setIsBenefitDetailOpen] = useState(false); const [selectedShop, setSelectedShop] = useState([]); const onShopClick = (id: number) => { setSelectedShop((prev) => { @@ -128,6 +130,23 @@ export default function BenefitPage() { + handleModal(setIsBenefitDetailOpen, 'benefitDetail', 'close')} + onClick={() => { + if (selectedShop.length === 0) return; + handleModal(setIsBenefitDetailOpen, 'benefitDetail', 'open'); + }} + > + selectedShop.includes(shop.id))} + closeBenefitModifyModal={() => handleModal(setIsBenefitDetailOpen, 'benefitDetail', 'close')} + /> + [{ type: 'benefit' }], }), + modifyBenefitDetails: builder.mutation({ + query({ modify_details }) { + return { + url: 'admin/benefit', + method: 'put', + body: { modify_details }, + }; + }, + invalidatesTags: () => [{ type: 'benefit' }], + }), }), }); export const { useGetBenefitCategoryQuery, useGetBenefitShopsQuery, useSearchShopsQuery, useCreateBenefitCategoryMutation, useDeleteBenefitCategoryMutation, useDeleteBenefitShopsMutation, - useAddBenefitShopsMutation, useModifyBenefitCategoryMutation, + useAddBenefitShopsMutation, useModifyBenefitCategoryMutation, useModifyBenefitDetailsMutation, } = benefitApi; From 20badd4e0dcc2540669414228a291d63ea7fc6e9 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Tue, 17 Dec 2024 17:05:33 +0900 Subject: [PATCH 5/6] =?UTF-8?q?refactor:=20=EC=9D=B8=ED=84=B0=EB=9E=99?= =?UTF-8?q?=EC=85=98=EC=97=90=20=EB=94=B0=EB=A5=B8=20state=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Services/Benefit/components/AdditionalModal/index.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/Services/Benefit/components/AdditionalModal/index.tsx b/src/pages/Services/Benefit/components/AdditionalModal/index.tsx index 19ea208d..e6f59ee1 100644 --- a/src/pages/Services/Benefit/components/AdditionalModal/index.tsx +++ b/src/pages/Services/Benefit/components/AdditionalModal/index.tsx @@ -46,7 +46,9 @@ export default function AdditionalModal({ id, closeAdditionModal }: Props) { }; const cancelAddShop = (shopId: number) => { const filteredShop = shops.filter((shop) => shop.id !== shopId); + const filteredDetail = details.filter((shop) => shop.shop_id !== shopId); setShops(filteredShop); + setDetails(filteredDetail); }; const ConfirmAddShop = async () => { From 07d0a660e2abd1074801923288b0c5b9b23b8e5a Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Tue, 17 Dec 2024 17:11:53 +0900 Subject: [PATCH 6/6] =?UTF-8?q?refactor:=20=EC=88=98=EC=A0=95=20=EC=8B=9C?= =?UTF-8?q?=20=EC=B4=88=EA=B8=B0=EA=B0=92=20=EB=B3=B4=EC=9D=B4=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Benefit/components/BenefitDetailModifyModal/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pages/Services/Benefit/components/BenefitDetailModifyModal/index.tsx b/src/pages/Services/Benefit/components/BenefitDetailModifyModal/index.tsx index 29d2cc1d..04f7aacc 100644 --- a/src/pages/Services/Benefit/components/BenefitDetailModifyModal/index.tsx +++ b/src/pages/Services/Benefit/components/BenefitDetailModifyModal/index.tsx @@ -101,7 +101,10 @@ export default function BenefitDetailModifyModal({ closeBenefitModifyModal, shop - handleDetail(e, shop.shop_id)} /> + handleDetail(e, shop.shop_id)} + value={details.find((detail) => detail.shop_id === shop.shop_id)?.detail} + /> ))}