Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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/pages/game/game.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ const Game = () => {
}, [gameMatchData, setHeaderTitle]);

return (
<div className="relative h-full flex-col gap-[1.2rem] px-[1.6rem] pt-[2rem]">
<div className="relative h-full flex-col gap-[1.2rem] bg-gray-100 px-[1.6rem] pt-[2rem]">
{gameMatchData?.result?.map((match) => (
// TODO: 매칭 현황 상태가 [그룹원 모집중]인 카드만 노출
<button
Expand Down
20 changes: 19 additions & 1 deletion src/pages/home/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Button from '@components/button/button/button';
import { WEEK_CALENDAR_START_OFFSET } from '@components/calendar/constants/CALENDAR';
import Dialog from '@components/dialog/dialog';
import { TAB_TYPES, type TabType } from '@components/tab/tab/constants/tab-type';
import { CREATE_MATCH_TOAST_MESSAGE } from '@constants/error-toast';
import useAuth from '@hooks/use-auth';
import { useTabState } from '@hooks/use-tab-state';
import { gaEvent } from '@libs/analytics';
Expand All @@ -19,8 +20,9 @@ import { ROUTES } from '@routes/routes-config';
import { useMutation } from '@tanstack/react-query';
import { addDays, format } from 'date-fns';
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useLocation, useNavigate } from 'react-router-dom';
import { handleScrollLock } from '@/shared/utils/scroll-lock';
import { showErrorToast } from '@/shared/utils/show-error-toast';

// TODO: 선택 날짜 유지 로직 수정
// const getSelectedDateFromQuery = (searchParams: URLSearchParams, fallbackDate: Date): Date => {
Expand All @@ -32,6 +34,7 @@ import { handleScrollLock } from '@/shared/utils/scroll-lock';

const Home = () => {
const { activeType, changeTab } = useTabState();
const location = useLocation();
const navigate = useNavigate();
// const [searchParams, setSearchParams] = useSearchParams();
const entryDate = new Date();
Expand Down Expand Up @@ -68,6 +71,21 @@ const Home = () => {
gaEvent('home_enter', { from });
}, [needsMatchingSetup]);

useEffect(() => {
if (location.state?.shouldShowMatchCreatedToast) {
showErrorToast(CREATE_MATCH_TOAST_MESSAGE, {
offset: '8.8rem',
icon: false,
className: 'bg-sub-900 text-gray-black cap_14_sb',
});

navigate(location.pathname, {
replace: true,
state: {},
});
}
}, [location, navigate]);

// const syncSelectedDateToQuery = (date: Date) => {
// const nextParams = new URLSearchParams(searchParams);
// nextParams.set('date', format(date, 'yyyy-MM-dd'));
Expand Down
58 changes: 56 additions & 2 deletions src/pages/onboarding/components/complete-button-section.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,67 @@
import { matchMutations } from '@apis/match/match-mutations';
import { matchQueries } from '@apis/match/match-queries';
import Button from '@components/button/button/button';
import { gaEvent } from '@libs/analytics';
import { ROUTES } from '@routes/routes-config';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useNavigate } from 'react-router-dom';
import type { SelectedGame } from './date-select';

const CompleteButtonSection = () => {
interface CompleteButtonSectionProps {
pendingMatch: {
game: SelectedGame;
date: string;
type: 'single' | 'group';
};
}

const CompleteButtonSection = ({ pendingMatch }: CompleteButtonSectionProps) => {
const navigate = useNavigate();
const queryClient = useQueryClient();
const createMatchMutation = useMutation(matchMutations.CREATE_MATCH());

const handleGoToMate = () => {
Comment thread
bongtta marked this conversation as resolved.
navigate(ROUTES.HOME);
};

const handleCreate = () => {
if (createMatchMutation.isPending) return;

const matchType = pendingMatch.type === 'single' ? 'DIRECT' : 'GROUP';
const gaMatchType = pendingMatch.type === 'single' ? 'one_to_one' : 'group';

gaEvent('match_create_click', {
match_type: gaMatchType,
role: 'creator',
});

createMatchMutation.mutate(
{
gameId: pendingMatch.game.id,
matchType,
},
{
onSuccess: () => {
if (matchType === 'DIRECT') {
queryClient.invalidateQueries({
queryKey: matchQueries.SINGLE_MATCH_LIST(pendingMatch.date).queryKey,
});
} else {
queryClient.invalidateQueries({
queryKey: matchQueries.GROUP_MATCH_LIST(pendingMatch.date).queryKey,
});
}

navigate(ROUTES.HOME, {
state: {
shouldShowMatchCreatedToast: true,
},
});
},
},
);
};

return (
<div className="w-full">
<section className="w-full flex-row-between gap-[0.8rem] p-[1.6rem]">
Expand All @@ -24,7 +77,8 @@ const CompleteButtonSection = () => {
size="M"
variant="blue"
className="w-full"
onClick={handleGoToMate}
onClick={handleCreate}
disabled={createMatchMutation.isPending}
/>
</section>
</div>
Expand Down
14 changes: 11 additions & 3 deletions src/pages/onboarding/components/complete-group-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,20 @@ const CompleteGroupCard = ({ matchId }: { matchId: number }) => {
const { data } = useSuspenseQuery(matchQueries.GROUP_MATCH_RESULT(matchId));

const cardProps: CardProps = {
...data,
type: 'group',
id: data.id,
type: 'game',
nickname: data.nickname,
count: data.count,
imgUrl: Array.isArray(data.imgUrl) ? data.imgUrl : [data.imgUrl],
awayTeam: data.awayTeam,
homeTeam: data.homeTeam,
stadium: data.stadium,
date: data.date,
isGroup: true,
className: 'w-full',
};

return <Card isCreated {...cardProps} />;
return <Card {...cardProps} />;
};

export default CompleteGroupCard;
16 changes: 11 additions & 5 deletions src/pages/onboarding/components/complete-single-card.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import { matchQueries } from '@apis/match/match-queries';
import Card from '@components/card/match-card/card';
import type { CardProps, ChipColor } from '@components/card/match-card/types/card';
import type { CardProps } from '@components/card/match-card/types/card';
import { useSuspenseQuery } from '@tanstack/react-query';

const CompleteSingleCard = ({ matchId }: { matchId: number }) => {
const { data } = useSuspenseQuery(matchQueries.SINGLE_MATCH_RESULT(matchId));

const cardProps: CardProps = {
...data,
type: 'single',
id: data.id,
type: 'game',
nickname: data.nickname,
count: 1,
imgUrl: [data.imgUrl],
chips: [data.team, data.style] as ChipColor[],
awayTeam: data.awayTeam,
homeTeam: data.homeTeam,
stadium: data.stadium,
date: data.date,
isGroup: false,
className: 'w-full',
};

return <Card isCreated {...cardProps} />;
return <Card {...cardProps} />;
};

export default CompleteSingleCard;
41 changes: 31 additions & 10 deletions src/pages/onboarding/components/complete.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,47 @@
import { userQueries } from '@apis/user/user-queries';
import Card from '@components/card/match-card/card';
import type { CardProps } from '@components/card/match-card/types/card';
import { MATCHING_SUGGESTION_MESSAGE_TITLE } from '@pages/match/constants/matching';
import CompleteGroupCard from './complete-group-card';
import CompleteSingleCard from './complete-single-card';
import { useQuery } from '@tanstack/react-query';
import type { SelectedGame } from './date-select';

interface CompleteProps {
nickname: string;
matchId: number;
selectedGame: SelectedGame;
selectedDate: string;
type?: 'single' | 'group';
}

const Complete = ({ nickname, matchId, type }: CompleteProps) => {
const Complete = ({ selectedGame, selectedDate, type }: CompleteProps) => {
const { data } = useQuery({
...userQueries.USER_INFO(),
enabled: true,
});

const nickname = data?.nickname ?? '사용자';
const imgUrl = data?.imgUrl ?? '';

const cardProps: CardProps = {
id: selectedGame.id,
type: 'game',
nickname,
count: 1,
imgUrl: imgUrl ? [imgUrl] : [],
awayTeam: selectedGame.awayTeam,
homeTeam: selectedGame.homeTeam,
stadium: selectedGame.stadium,
date: selectedDate,
isGroup: type === 'group',
className: 'w-full',
};

return (
<div className="w-full flex-1 flex-col-between gap-[4rem] whitespace-pre-line pt-[6.45rem]">
<div className="w-full flex-col gap-[4rem] px-[1.6rem]">
<p className="title_24_sb text-center text-gray-black">
{MATCHING_SUGGESTION_MESSAGE_TITLE(nickname)}
</p>

{type === 'single' ? (
<CompleteSingleCard matchId={matchId} />
) : (
<CompleteGroupCard matchId={matchId} />
)}
<Card {...cardProps} />
</div>
</div>
);
Expand Down
12 changes: 10 additions & 2 deletions src/pages/onboarding/components/date-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,16 @@ import { format } from 'date-fns';
import { useState } from 'react';
import { showErrorToast } from '@/shared/utils/show-error-toast';

export interface SelectedGame {
id: number;
awayTeam: string;
homeTeam: string;
gameTime: string;
stadium: string;
}

interface DateSelectProps {
onComplete: (matchId: number) => void;
onComplete: (selected: { game: SelectedGame; date: string }) => void;
activeType: TabType;
}

Expand Down Expand Up @@ -71,7 +79,7 @@ const DateSelect = ({ onComplete, activeType }: DateSelectProps) => {
date={format(selectedDate ?? new Date(), 'yyyy-MM-dd')}
gameSchedule={data ?? []}
activeType={activeType}
fromOnboarding={true}
fromOnboarding
onComplete={onComplete}
/>
</div>
Expand Down
43 changes: 17 additions & 26 deletions src/pages/onboarding/onboarding.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { matchMutations } from '@apis/match/match-mutations';
import { userQueries } from '@apis/user/user-queries';
import Button from '@components/button/button/button';
import { TAB_TYPES } from '@components/tab/tab/constants/tab-type';
import { useFunnel } from '@hooks/use-funnel';
import Complete from '@pages/onboarding/components/complete';
import CompleteButtonSection from '@pages/onboarding/components/complete-button-section';
import DateSelect from '@pages/onboarding/components/date-select';
import DateSelect, { type SelectedGame } from '@pages/onboarding/components/date-select';
import Frequency from '@pages/onboarding/components/frequency';
import MatchingType from '@pages/onboarding/components/matching-type';
import OnboardingHeader from '@pages/onboarding/components/onboarding-header';
Expand All @@ -16,7 +15,7 @@ import ViewingStyle from '@pages/onboarding/components/viewing-style';
import { FIRST_FUNNEL_STEPS, NO_TEAM_OPTION } from '@pages/onboarding/constants/onboarding';
import { handleButtonClick, isButtonDisabled } from '@pages/onboarding/utils/onboarding-button';
import { ROUTES } from '@routes/routes-config';
import { useMutation, useSuspenseQuery } from '@tanstack/react-query';
import { useMutation } from '@tanstack/react-query';
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';

Expand All @@ -34,8 +33,9 @@ const Onboarding = () => {
MATCHING_TYPE: null,
});

const [createdMatch, setCreatedMatch] = useState<{
matchId: number;
const [pendingMatch, setPendingMatch] = useState<{
game: SelectedGame;
date: string;
type: 'single' | 'group';
} | null>(null);

Expand All @@ -44,7 +44,6 @@ const Onboarding = () => {
};

const navigate = useNavigate();

const { mutate } = useMutation(matchMutations.MATCH_CONDITION());

const handlePrev = () => {
Expand All @@ -60,11 +59,8 @@ const Onboarding = () => {
}
};

const { data: user } = useSuspenseQuery(userQueries.USER_INFO());
const nickname = user.nickname;

return (
<div className="h-full flex-col">
<div className="h-full flex-col bg-background">
<div className="sticky top-0 bg-background">
<OnboardingHeader onClick={handlePrev} />
{currentStep !== 'COMPLETE' && (
Expand Down Expand Up @@ -104,14 +100,6 @@ const Onboarding = () => {
/>
</Step>

{/* TODO: GENDER 단계 관련 전부 삭제 */}
{/* <Step name="GENDER">
<Gender
selectedOption={selections.GENDER}
onSelect={(option) => handleSelect('GENDER', option)}
/>
</Step> */}

<Step name="MATCHING_TYPE">
<MatchingType
selectedOption={selections.MATCHING_TYPE}
Expand All @@ -124,9 +112,10 @@ const Onboarding = () => {
activeType={
selections.MATCHING_TYPE === '1:1 매칭' ? TAB_TYPES.SINGLE : TAB_TYPES.GROUP
}
onComplete={(matchId) => {
setCreatedMatch({
matchId,
onComplete={({ game, date }) => {
setPendingMatch({
game,
date,
type: selections.MATCHING_TYPE === '1:1 매칭' ? 'single' : 'group',
});
goNext();
Expand All @@ -135,11 +124,11 @@ const Onboarding = () => {
</Step>

<Step name="COMPLETE">
{createdMatch && (
{pendingMatch && (
<Complete
nickname={nickname ?? ''}
matchId={createdMatch.matchId}
type={createdMatch.type}
selectedGame={pendingMatch.game}
selectedDate={pendingMatch.date}
type={pendingMatch.type}
/>
)}
</Step>
Expand All @@ -164,7 +153,9 @@ const Onboarding = () => {
/>
</div>
)}
{currentStep === 'COMPLETE' && <CompleteButtonSection />}
{currentStep === 'COMPLETE' && pendingMatch && (
<CompleteButtonSection pendingMatch={pendingMatch} />
)}
</div>
</div>
);
Expand Down
Loading
Loading