Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
e1c0024
refactor: 밸런스게임 모바일 조회 페이지의 회원 정보 함수 수정
areumH Feb 6, 2025
ff7859c
refactor: 게임 생성 페이지의 이미지 삭제 함수 내에서 fileId가 undefined일 경우 null이 지정되도록 수정
areumH Feb 6, 2025
ead7442
feat: 게임 수정 클릭 시 게임 생성 페이지로 게임 값을 state로 넘겨주도록 구현
areumH Feb 6, 2025
4e2a70c
feat: 게임 값과 게임 세트 아이디를 함께 넘겨주어 수정 로직 연결
areumH Feb 10, 2025
7f269ba
refactor: 비회원 상태를 로컬 스토리지가 아닌 리덕스로 확인하도록 수정
areumH Feb 10, 2025
31db187
feat: 게임 삭제 로직 연결
areumH Feb 10, 2025
11ad597
feat: 밸런스게임 수정 페이지가 모바일이 아닐때만 접근되도록 구현
areumH Feb 10, 2025
59eef3e
feat: 이미지 업로드 응답 데이터에 타입 지정
areumH Feb 11, 2025
69e3da0
refactor: 게임 수정 시 이미지 삭제 로직 수정
areumH Feb 19, 2025
74f1f44
refactor: 게임의 서브 태그가 여러 개 입력이 가능하도록 로직 수정
areumH Feb 19, 2025
6813b27
refactor: ToastModal 컴포넌트에 모바일 스타일 추가
areumH Feb 19, 2025
9797d2f
refactor: 게임 서브 태그 개수 검증 추가 및 태그 내에서 검증하도록 로직 수정
areumH Feb 22, 2025
d4ffaf3
Merge branch 'dev' of https://github.com/CHZZK-Study/Balance-Talk-Fro…
areumH Feb 22, 2025
34d01af
refactor: 게임 서브 태그 컴포넌트에 key 값 추가
areumH Feb 22, 2025
e7c0e2f
refactor: 태그 검증 함수 일괄 처리 및 태그 등록 함수 수정
areumH Feb 24, 2025
bb5c1d7
Merge branch 'dev' of https://github.com/CHZZK-Study/Balance-Talk-Fro…
areumH Mar 5, 2025
cb28cc2
feat: 밸런스 게임 모달 텍스트 상수 적용 및 신고 모달 제시 연결
areumH Mar 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ const App: React.FC = () => {
/>
<Route
path={PATH.BALANCEGAME.EDIT()}
element={<BalanceGameEditPage />}
element={!isMobile && <BalanceGameEditPage />}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이런 표현 좋네요~

/>
<Route
path={PATH.CHANGE.PROFILE}
Expand Down
8 changes: 7 additions & 1 deletion src/components/atoms/ToastModal/ToastModal.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export const getToastModalColor = (
return style[bgColor];
};

export const toastModalStyling = css(typo.Main.SemiBold, {
export const toastModalStyling = css({
...typo.Main.SemiBold,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
Expand All @@ -29,6 +30,11 @@ export const toastModalStyling = css(typo.Main.SemiBold, {
padding: '20px 30px',
borderRadius: '35px',
boxShadow: '1px 1px 10px rgba(0, 0, 0, 0.07)',

'@media (max-width: 430px)': {
...typo.Mobile.Text.SemiBold_12,
padding: '14px 24px',
},
});

export const toastContainer = css({
Expand Down
13 changes: 8 additions & 5 deletions src/components/mobile/molecules/GameTagModal/GameTagModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { TAG_OPTIONS } from '@/constants/game';
import Modal from '@/components/mobile/atoms/Modal/Modal';
import Button from '@/components/mobile/atoms/Button/Button';
import Divider from '@/components/atoms/Divider/Divider';
import { validateGameTag } from '@/hooks/game/validateBalanceGameForm';
import * as S from './GameTagModal.style';

interface GameTagModalProps {
Expand All @@ -31,10 +32,13 @@ const GameTagModal = ({
};

const handleTagSubmit = () => {
if (currentMainTag) {
submitGame();
onClose?.();
}
if (!currentMainTag) return;

const { isValid } = validateGameTag(form);
if (!isValid) return;

submitGame();
onClose?.();
};

return (
Expand Down Expand Up @@ -70,7 +74,6 @@ const GameTagModal = ({
name="subTag"
css={S.inputStyling}
placeholder="ex. 너무어려운밸런스게임, 선택장애, 이상형"
maxLength={10}
value={form.subTag}
onChange={setSubTagValue}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState } from 'react';
import { BUTTON_TEXT, MAX_STAGE } from '@/constants/game';
import { GameSet } from '@/types/game';
import ToastModal from '@/components/atoms/ToastModal/ToastModal';
import Button from '@/components/mobile/atoms/Button/Button';
import GameStageLabel from '@/components/mobile/atoms/GameStageLabel/GameStageLabel';
Expand All @@ -12,7 +13,15 @@ import TempGameModal from '@/components/mobile/molecules/TempGameModal/TempGameM
import { usePostBalanceGameForm } from '@/hooks/game/usePostBalanceGameForm';
import * as S from './BalanceGameCreateSection.style';

const BalanceGameCreateSection = () => {
interface BalanceGameCreateSectionProps {
existingGame?: GameSet;
gameSetId?: number;
}

const BalanceGameCreateSection = ({
existingGame,
gameSetId,
Comment on lines +17 to +23
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 organisms의 props는 전부 옵셔널인데, default 설정이 없으면 어떻게 처리되고 있는지 궁금합니다!

Copy link
Collaborator Author

@areumH areumH Feb 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

게임이 존재할 때는 게임 수정, 존재하지 않을 때는 게임 생성이 수행됩니다!

}: BalanceGameCreateSectionProps) => {
const [gameStage, setGameStage] = useState<number>(0);

const [tagModalOpen, setTagModalOpen] = useState<boolean>(false);
Expand All @@ -34,7 +43,13 @@ const BalanceGameCreateSection = () => {
handleBalanceGame,
handleTempBalanceGame,
handleDraftButton,
} = usePostBalanceGameForm(gameStage, setGameStage, setTagModalOpen);
} = usePostBalanceGameForm(
gameStage,
setGameStage,
setTagModalOpen,
existingGame,
gameSetId,
);

return (
<form css={S.balanceGameStyling}>
Expand Down Expand Up @@ -79,7 +94,8 @@ const BalanceGameCreateSection = () => {
}}
onConfirm={() => {
handleDeleteImg(
form.games[gameStage].gameOptions[selectedOptionId].fileId,
form.games[gameStage].gameOptions[selectedOptionId].fileId ??
null,
selectedOptionId,
);
setImgDeleteModalOpen(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
} from '@/assets';
import { PATH } from '@/constants/path';
import { useNavigate } from 'react-router-dom';
import { useNewSelector } from '@/store';
import { selectAccessToken } from '@/store/auth';
import { useGameEndBookmark } from '@/hooks/game/useBalanceGameBookmark';
import useToastModal from '@/hooks/modal/useToastModal';
import ToastModal from '@/components/atoms/ToastModal/ToastModal';
Expand All @@ -29,7 +31,7 @@ const BalanceGameEndingSection = ({
isMyEndBookmark,
}: BalanceGameEndingSectionProps) => {
const navigate = useNavigate();
const isGuest = !localStorage.getItem('accessToken');
const isGuest = !useNewSelector(selectAccessToken);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리덕스로 일원화 한 점 아주 좋습니다~


const [shareModalOpen, setShareModalOpen] = useState<boolean>(false);
const { isVisible, modalText, showToastModal } = useToastModal();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export const subTagWrapper = css({
display: 'flex',
width: '100%',
marginBottom: '50px',
gap: '8px',
});

export const iconButtonWrapper = css({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import React, { useState, useEffect, useRef } from 'react';
import { MobileBookmarkDF, MobileBookmarkPR, MobileShare } from '@/assets';
import { useNavigate } from 'react-router-dom';
import { useNewSelector } from '@/store';
import { selectAccessToken } from '@/store/auth';
import { GameDetail, GameSet } from '@/types/game';
import { createArrayFromCommaString } from '@/utils/array';
import { PATH } from '@/constants/path';
import { ERROR, PROMPT } from '@/constants/message';
import MenuTap, { MenuItem } from '@/components/atoms/MenuTap/MenuTap';
import useToastModal from '@/hooks/modal/useToastModal';
import { VoteRecord } from '@/types/vote';
Expand All @@ -15,7 +19,10 @@ import ToastModal from '@/components/atoms/ToastModal/ToastModal';
import BalanceGameBox from '@/components/mobile/molecules/BalanceGameBox/BalanceGameBox';
import { useGuestGameVote } from '@/hooks/game/useBalanceGameVote';
import { useGameBookmark } from '@/hooks/game/useBalanceGameBookmark';
import ShareModal from '../../molecules/ShareModal/ShareModal';
import { useDeleteGameSetMutation } from '@/hooks/api/game/useDeleteGameSetMutation';
import ShareModal from '@/components/mobile/molecules/ShareModal/ShareModal';
import TextModal from '@/components/mobile/molecules/TextModal/TextModal';
import ReportModal from '@/components/mobile/molecules/ReportModal/ReportModal';
import * as S from './BalanceGameSection.style';

export interface BalanceGameSectionProps {
Expand Down Expand Up @@ -51,11 +58,13 @@ const BalanceGameSection = ({

const gameStages: GameDetail[] =
game?.gameDetailResponses ?? gameDefaultDetail;
const isGuest = !localStorage.getItem('accessToken');
const isGuest = !useNewSelector(selectAccessToken);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

옵셔널 체이닝을 통한 안전한 접근이 필요합니다.

game 객체가 undefined일 때 subTag 접근이 안전하도록 처리가 필요합니다.

다음과 같이 수정을 제안합니다:

- const subTagList = createArrayFromCommaString(game?.subTag ?? '');
+ const subTagList = game ? createArrayFromCommaString(game.subTag ?? '') : [];

Also applies to: 65-65


const [guestVotedList, setGuestVotedList] = useState<VoteRecord[]>([]);

const currentGame: GameDetail = gameStages[currentStage];
const subTagList = createArrayFromCommaString(game?.subTag ?? '');

const { handleGuestGameVote } = useGuestGameVote(
guestVotedList,
setGuestVotedList,
Expand All @@ -64,8 +73,16 @@ const BalanceGameSection = ({
game,
);

const [shareModalOpen, setShareModalOpen] = useState<boolean>(false);
const { isVisible, modalText, showToastModal } = useToastModal();
const { mutate: deleteBalanceGame } = useDeleteGameSetMutation();

const [activeModal, setActiveModal] = useState<
'reportGame' | 'reportText' | 'deleteText' | 'share' | 'none'
>('none');

const onCloseModal = () => {
setActiveModal('none');
};

useEffect(() => {
if (game && initialRender.current) {
Expand All @@ -89,6 +106,20 @@ const BalanceGameSection = ({
changeStage(1);
};

const handleGameDeleteButton = () => {
deleteBalanceGame(
{ gameSetId },
{
onSuccess: () => {
navigate('/');
},
onError: () => {
showToastModal(ERROR.DELETEGAME.FAIL);
},
},
);
};

const { handleBookmarkClick } = useGameBookmark(
isGuest,
isMyGame,
Expand All @@ -99,8 +130,28 @@ const BalanceGameSection = ({
game,
);

const myGameItem: MenuItem[] = [{ label: '수정' }, { label: '삭제' }];
const otherGameItem: MenuItem[] = [{ label: '신고' }];
const myGameItem: MenuItem[] = [
{
label: '수정',
onClick: () => {
navigate(`/${PATH.CREATE.GAME}`, { state: { game, gameSetId } });
},
},
{
label: '삭제',
onClick: () => {
setActiveModal('deleteText');
},
},
];
const otherGameItem: MenuItem[] = [
{
label: '신고',
onClick: () => {
setActiveModal('reportText');
},
},
];

return (
<div css={S.balanceGameStyling}>
Expand All @@ -111,17 +162,34 @@ const BalanceGameSection = ({
)}
<div css={S.centerStyling}>
<ShareModal
isOpen={shareModalOpen}
isOpen={activeModal === 'share'}
onConfirm={() => {}}
onClose={onCloseModal}
/>
<TextModal
text={PROMPT.GAME.DELETE}
isOpen={activeModal === 'deleteText'}
onConfirm={handleGameDeleteButton}
onClose={onCloseModal}
/>
<TextModal
text={PROMPT.GAME.REPORT}
isOpen={activeModal === 'reportText'}
onConfirm={() => setActiveModal('reportGame')}
onClose={onCloseModal}
/>
<ReportModal
isOpen={activeModal === 'reportGame'}
onConfirm={() => {}}
onClose={() => setShareModalOpen(false)}
onClose={onCloseModal}
/>
Comment on lines +181 to 185
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

ReportModal 컴포넌트에 대한 확인 핸들러 구현이 필요합니다.

ReportModal의 onConfirm 핸들러가 빈 함수로 설정되어 있습니다. 실제 신고 기능을 구현하거나 해당 기능이 아직 준비되지 않았다면 TODO 주석을 추가하는 것이 좋습니다.

- onConfirm={() => {}}
+ onConfirm={() => {
+   // TODO: 신고 API 연동 구현 필요
+ }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<ReportModal
isOpen={activeModal === 'reportGame'}
onConfirm={() => {}}
onClose={() => setShareModalOpen(false)}
onClose={onCloseModal}
/>
<ReportModal
isOpen={activeModal === 'reportGame'}
onConfirm={() => {
// TODO: 신고 API 연동 구현 필요
}}
onClose={onCloseModal}
/>

</div>
<div css={S.balancGameTopWrapper}>
<GameTag tag={game?.mainTag ?? ''} />
<div css={S.iconButtonWrapper}>
<IconButton
icon={<MobileShare />}
onClick={() => setShareModalOpen(true)}
onClick={() => setActiveModal('share')}
/>
<IconButton
icon={
Expand Down Expand Up @@ -164,7 +232,8 @@ const BalanceGameSection = ({
/>
</div>
<div css={S.subTagWrapper}>
{game.subTag && <GameTagChip tag={game.subTag} />}
{game.subTag &&
subTagList.map((tag) => <GameTagChip key={tag} tag={tag} />)}
</div>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import ShareModal from '@/components/molecules/ShareModal/ShareModal';
import LoginModal from '@/components/molecules/LoginModal/LoginModal';
import useToastModal from '@/hooks/modal/useToastModal';
import { useGameEndBookmark } from '@/hooks/game/useBalanceGameBookmark';
import { useNewSelector } from '@/store';
import { selectAccessToken } from '@/store/auth';
import * as S from './BalanceGameEndingBox.style';

export interface BalanceGameEndingBoxProps {
Expand All @@ -25,7 +27,7 @@ const BalanceGameEndingBox = ({
isMyEndBookmark,
}: BalanceGameEndingBoxProps) => {
const currentURL: string = window.location.href;
const isGuest = !localStorage.getItem('accessToken');
const isGuest = !useNewSelector(selectAccessToken);

const [loginModalOpen, setLoginModalOpen] = useState<boolean>(false);
const [shareModalOpen, setShareModalOpen] = useState<boolean>(false);
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/api/game/useCreateGameMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const useCreateGameMutation = (
queryClient.invalidateQueries({
queryKey: ['games'],
});
showToastModal(SUCCESS.CREATEGAME.CREATE, () => {
showToastModal(SUCCESS.GAME.CREATE, () => {
navigate(`/${PATH.BALANCEGAME.VIEW(gameId)}`);
});
},
Expand Down
Loading
Loading