From 09d88bda31bb208d8c2b2c851fd1e40c4f7d9cd6 Mon Sep 17 00:00:00 2001 From: Jiyoung Jung <72294509+Jungjjeong@users.noreply.github.com> Date: Fri, 30 Aug 2024 03:04:58 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20use=20cheer=20modal=20=ED=9B=85=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../molecules/cheer}/cheer-progress.tsx | 3 +- components/molecules/cheer/index.ts | 1 + features/record-detail/components/index.ts | 1 - .../sections/detail-cheer-fab.tsx | 75 +++-------- hooks/index.ts | 1 + hooks/use-cheer-bottom-sheet.ts | 116 ++++++++++++++++++ 6 files changed, 134 insertions(+), 63 deletions(-) rename {features/record-detail/components => components/molecules/cheer}/cheer-progress.tsx (97%) create mode 100644 hooks/use-cheer-bottom-sheet.ts diff --git a/features/record-detail/components/cheer-progress.tsx b/components/molecules/cheer/cheer-progress.tsx similarity index 97% rename from features/record-detail/components/cheer-progress.tsx rename to components/molecules/cheer/cheer-progress.tsx index f9635558..a98e4a58 100644 --- a/features/record-detail/components/cheer-progress.tsx +++ b/components/molecules/cheer/cheer-progress.tsx @@ -2,11 +2,10 @@ import { useEffect, useState } from 'react'; +import { DetailCheerItem } from '@/features/record-detail'; import { css, cx } from '@/styled-system/css'; import { flex } from '@/styled-system/patterns'; -import { DetailCheerItem } from '../types'; - type CheerProgress = { isOpen: boolean; onChangeOpen: (isOpen: boolean) => void; diff --git a/components/molecules/cheer/index.ts b/components/molecules/cheer/index.ts index 6ae792b8..2dd59cdb 100644 --- a/components/molecules/cheer/index.ts +++ b/components/molecules/cheer/index.ts @@ -1,2 +1,3 @@ export * from './cheer-bottom-sheet'; export * from './cheer-item'; +export * from './cheer-progress'; diff --git a/features/record-detail/components/index.ts b/features/record-detail/components/index.ts index aab1fba5..b6c8d243 100644 --- a/features/record-detail/components/index.ts +++ b/features/record-detail/components/index.ts @@ -1,5 +1,4 @@ export * from './cheer-modal'; -export * from './cheer-progress'; export * from './date-picker'; export * from './edit-button'; export * from './swim-description-item'; diff --git a/features/record-detail/sections/detail-cheer-fab.tsx b/features/record-detail/sections/detail-cheer-fab.tsx index a6c3d6ab..e4640bb3 100644 --- a/features/record-detail/sections/detail-cheer-fab.tsx +++ b/features/record-detail/sections/detail-cheer-fab.tsx @@ -1,34 +1,30 @@ 'use client'; -import { useState } from 'react'; - -import { CheerBottomSheet } from '@/components/molecules'; -import { useBottomSheet, useToast } from '@/hooks'; +import { CheerBottomSheet, CheerProgress } from '@/components/molecules'; +import { useCheerBottomSheet, useToast } from '@/hooks'; import { css } from '@/styled-system/css'; -import { useCheer, useCheerEligibility, useCheerPreviewList } from '../apis'; -import { CheerProgress } from '../components'; -import { initialCheerList } from '../data'; -import { DetailCheerItemSelected, RecordDetailType } from '../types'; +import { useCheerEligibility, useCheerPreviewList } from '../apis'; +import { RecordDetailType } from '../types'; export const DetailCheerFabSection = ({ data }: { data: RecordDetailType }) => { - const { mutate: mutateCheer } = useCheer(); + const { toast } = useToast(); + const { refetch: refetchCheer } = useCheerPreviewList(data.id); const { data: eligibilityData } = useCheerEligibility( data.id, data.isMyMemory, ); - - const [cheerList, setCheerList] = useState(initialCheerList); - const [selectedCheerItem, setSelectedCheerItem] = - useState(); - - const { toast } = useToast(); const { - isOpen: isOpenBottomSheet, - open: openBottomSheet, - close: closeBottomSheet, - } = useBottomSheet(); + cheerList, + selectedCheerItem, + handleClickCheerItem, + handleClickSendCheer, + handleChangeSelectedItem, + isOpenBottomSheet, + closeBottomSheet, + openBottomSheet, + } = useCheerBottomSheet({ memoryId: data.id, onRefetch: refetchCheer }); const handleClickFab = () => { if (!eligibilityData?.isRegistrable) { @@ -38,47 +34,6 @@ export const DetailCheerFabSection = ({ data }: { data: RecordDetailType }) => { openBottomSheet(); }; - - const handleClickCheerItem = (index: number) => { - setCheerList((prev) => - prev.map((item, idx) => - idx === index - ? { ...item, isSelected: !item.isSelected } - : { ...item, isSelected: false }, - ), - ); - }; - - const handleClickSendCheer = () => { - const selectedCheerItem = cheerList.find(({ isSelected }) => isSelected); - if (!selectedCheerItem) return; - - mutateCheer( - { - emoji: selectedCheerItem.emoji, - comment: selectedCheerItem.comment, - memoryId: data.id, - }, - { - onSuccess: ({ status, code, message }) => { - if (status === 400 || code === 'REACTION_4') { - alert(message); - return; - } - - void refetchCheer(); - setSelectedCheerItem(selectedCheerItem); - closeBottomSheet(); - }, - }, - ); - }; - - const handleChangeSelectedItem = (isOpen: boolean) => { - if (isOpen) return; - setSelectedCheerItem(undefined); - }; - const { isMyMemory } = data; return ( diff --git a/hooks/index.ts b/hooks/index.ts index 2292ce89..f24ac7b8 100644 --- a/hooks/index.ts +++ b/hooks/index.ts @@ -1,5 +1,6 @@ export * from './apis'; export * from './use-bottom-sheet'; +export * from './use-cheer-bottom-sheet'; export * from './use-dialog'; export * from './use-drag-scroll'; export * from './use-intersection-observer'; diff --git a/hooks/use-cheer-bottom-sheet.ts b/hooks/use-cheer-bottom-sheet.ts new file mode 100644 index 00000000..1b7c7f1b --- /dev/null +++ b/hooks/use-cheer-bottom-sheet.ts @@ -0,0 +1,116 @@ +'use client'; + +import { RefetchOptions } from '@tanstack/react-query'; +import { useState } from 'react'; + +import { DetailCheerItemSelected } from '@/features/record-detail'; +import { useCheer } from '@/features/record-detail/apis'; + +import { useBottomSheet } from './use-bottom-sheet'; + +const initialCheerList = [ + { + emoji: 'πŸ”₯', + comment: 'μ˜€λŠ˜λ„ νž˜λ‚΄μš”!', + isSelected: false, + }, + { + emoji: '🦭', + comment: 'λ¬Όκ°œμ„Έμš”?', + isSelected: false, + }, + { + emoji: '🏊', + isSelected: false, + }, + { + emoji: 'πŸ‘', + isSelected: false, + }, + { + emoji: 'πŸŠβ€β™‚οΈ', + comment: 'μ§„μ •ν•œ 수영인으둜 μΈμ •ν•©λ‹ˆλ‹€', + isSelected: false, + }, + { + emoji: 'πŸŠβ€β™‚οΈ', + comment: 'λ‹€μŒμ— 같이 μˆ˜μ˜ν•΄μš”', + isSelected: false, + }, + { + emoji: '😲', + comment: 'λŒ€λ‹¨ν•΄μš”!', + isSelected: false, + }, +]; + +type UseCheerBottomSheet = { + memoryId: number; + onRefetch: (options?: RefetchOptions) => Promise; +}; +export const useCheerBottomSheet = ({ + memoryId, + onRefetch, +}: UseCheerBottomSheet) => { + const { mutate: mutateCheer } = useCheer(); + const [cheerList, setCheerList] = useState(initialCheerList); + const [selectedCheerItem, setSelectedCheerItem] = + useState(); + + const { + isOpen: isOpenBottomSheet, + open: openBottomSheet, + close: closeBottomSheet, + } = useBottomSheet(); + + const handleClickCheerItem = (index: number) => { + setCheerList((prev) => + prev.map((item, idx) => + idx === index + ? { ...item, isSelected: !item.isSelected } + : { ...item, isSelected: false }, + ), + ); + }; + + const handleClickSendCheer = () => { + const selectedCheerItem = cheerList.find(({ isSelected }) => isSelected); + if (!selectedCheerItem) return; + + mutateCheer( + { + emoji: selectedCheerItem.emoji, + comment: selectedCheerItem.comment, + memoryId, + }, + { + onSuccess: ({ status, code, message }) => { + if (status === 400 || code === 'REACTION_4') { + alert(message); + return; + } + + setSelectedCheerItem(selectedCheerItem); + closeBottomSheet(); + void onRefetch?.(); + }, + }, + ); + }; + + const handleChangeSelectedItem = (isOpen: boolean) => { + if (isOpen) return; + setSelectedCheerItem(undefined); + }; + + return { + cheerList, + selectedCheerItem, + handleClickCheerItem, + handleClickSendCheer, + handleChangeSelectedItem, + isOpenBottomSheet, + openBottomSheet, + closeBottomSheet, + }; +};