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
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ function ResultClient({ tournamentId, isGuest = false, isApp = false }: ResultCl
open={isShareDialogOpen}
onOpenChange={setIsShareDialogOpen}
tournamentId={tournamentId}
initialPlayLinkExpiresAt={tournamentData.completed.playLinkExpiresAt}
/>

<ReceiptShareDialog
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ type PlateShareDialogProps = {
open: boolean;
onOpenChange: (open: boolean) => void;
tournamentId: number;
/** 서버 응답의 playLinkExpiresAt — 아직 생성 전이면 undefined */
initialPlayLinkExpiresAt?: string;
};

const buildPlayLinkUrl = (tournamentId: number) => {
Expand All @@ -27,25 +25,20 @@ const buildPlayLinkUrl = (tournamentId: number) => {
return `${window.location.origin}${path}`;
};

function PlateShareDialog({
open,
onOpenChange,
tournamentId,
initialPlayLinkExpiresAt,
}: PlateShareDialogProps) {
function PlateShareDialog({ open, onOpenChange, tournamentId }: PlateShareDialogProps) {
const { postPlayLinkMutation, isPostPlayLinkPending } = usePostPlayLink(tournamentId);

// 이미 만들어진 플레이 링크가 있으면 mutation 건너뛰고 바로 공유한다.
const hasExistingPlayLink = Boolean(initialPlayLinkExpiresAt);

const handleSendPlayLink = async () => {
if (!hasExistingPlayLink) {
try {
await postPlayLinkMutation();
} catch {
/** 안내는 usePostPlayLink 훅 레벨 onError 가 담당 — 여기선 공유 플로우만 중단 */
return;
}
/**
* 생성 API 가 멱등하므로 상태를 따지지 않고 항상 호출한다.
* 미생성이면 만들고, 만료됐으면 새로 발급하고, 살아 있으면 기존 만료시각을 그대로 준다.
* 클라가 만료 여부를 판단하려 들면 죽은 링크를 그대로 공유하게 된다.
*/
try {
await postPlayLinkMutation();
} catch {
/** 안내는 usePostPlayLink 훅 레벨 onError 가 담당 — 여기선 공유 플로우만 중단 */
return;
}

const result = await share({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMutation } from '@tanstack/react-query';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';

import { isGlobalNetError } from '@/utils/apiError';
Expand All @@ -7,16 +7,22 @@ import { getApiErrorMessage } from '@/utils/getApiErrorMessage';
import { postPlayLink } from '../_apis/postPlayLink';

export const usePostPlayLink = (tournamentId: number) => {
const queryClient = useQueryClient();

const { mutateAsync: postPlayLinkMutation, isPending: isPostPlayLinkPending } = useMutation({
mutationFn: () => postPlayLink(tournamentId),
/** 만료됐다면 새 기한을 받으므로 상세에 들고 있던 만료시각을 갱신한다 */
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['tournament', tournamentId] });
},
/** 문구는 훅 레벨에서만 — 호출부(mutateAsync catch)에서 토스트하면 전역 fallback 과 겹친다 */
onError: error => {
Comment thread
coderabbitai[bot] marked this conversation as resolved.
if (isGlobalNetError(error)) return;

/**
* 403: 플레이 링크로 참여한 토너먼트는 공유 링크 생성 불가
* 403: 플레이 링크로 참여한 토너먼트·주최자가 아닌 경우
* 404: 토너먼트 존재하지 않음
* 409: COMPLETED 아닌 토너먼트·이미 생성된 플레이 링크
* 409: COMPLETED 아닌 토너먼트
*/
toast.error(getApiErrorMessage(error));
},
Expand Down
Loading