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
35 changes: 20 additions & 15 deletions design-system/ui/modals/QrModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ interface QrModalProps {
ticketName: string; // 티켓 이름
price: number; // 티켓 가격
orderStatus: string; // 티켓 승인 여부
eventType: 'ONLINE' | 'OFFLINE'; // 이벤트 타입
isCheckIn: boolean; // 참가자 체크인 여부
isCountdownChecked: boolean;
remainDays: string; //d-day
Expand All @@ -37,10 +38,10 @@ const QrModal = ({
ticketName,
price,
orderStatus,
eventType,
isCheckIn,
isCountdownChecked,
remainDays,

onClick,
}: QrModalProps) => {
const formattedPrice = price.toLocaleString();
Expand All @@ -59,16 +60,19 @@ const QrModal = ({

<div className="absolute top-0 left-0 w-full h-full flex flex-col justify-between items-center px-4 py-4">
<div className="flex items-center justify-center h-1/2 w-full">
{ticketQrCode ? (
<img
src={`data:image/png;base64,${ticketQrCode}`}
alt="QR Code"
className="w-60 h-60 "
// breakpoint 추가 필요
/>
{eventType === 'ONLINE' ? (
<div className="w-40 h-40 flex items-center justify-center bg-deDayBgLight rounded-md border border-deDayTextDark text-deDayTextDark text-sm text-center px-4">
온라인 이벤트는
<br /> QR코드가 발급되지
<br /> 않습니다.
</div>
) : ticketQrCode ? (
<img src={`data:image/png;base64,${ticketQrCode}`} alt="QR Code" className="w-60 h-60" />
) : (
<div className="w-40 h-40 flex items-center justify-center bg-deDayBgLight rounded-md border border-deDayTextDark text-deDayTextDark text-sm text-center px-4">
주최자의 승인이 완료되면 QR이 발급됩니다.
주최자의 승인이
<br /> 완료되면 QR이
<br /> 발급됩니다.
</div>
)}
</div>
Expand All @@ -81,33 +85,35 @@ const QrModal = ({
<div className="space-y-1 text-deDayTextDark">
<IconText
size="xSmall"
iconPath={<img src={qr_calendar} alt="qr_calendar" className='mr-1' />}
iconPath={<img src={qr_calendar} alt="qr_calendar" className="mr-1" />}
children={formattedDate}
className="text-11"
></IconText>
<IconText
size="xSmall"
iconPath={<img src={qr_location} alt="qr_location" className='mr-1' />}
iconPath={<img src={qr_location} alt="qr_location" className="mr-1" />}
children={location}
className="text-11"
></IconText>
<IconText
size="xSmall"
iconPath={<img src={qr_ticket} alt="qr_ticket" className='mr-1' />}
iconPath={<img src={qr_ticket} alt="qr_ticket" className="mr-1" />}
children={ticketName}
className="text-11"
></IconText>
<span className="text-sm font-bold">{formattedPrice}원</span>
<hr />
<IconText
size="xSmall"
iconPath={<img src={orderStatus === 'COMPLETED' ? qr_check : qr_pending} alt="qr_check" className='mr-1' />}
iconPath={
<img src={orderStatus === 'COMPLETED' ? qr_check : qr_pending} alt="qr_check" className="mr-1" />
}
children={orderStatus === 'COMPLETED' ? '승인됨' : '대기 중'}
className="text-11"
></IconText>
<IconText
size="xSmall"
iconPath={<img src={isCheckIn ? qr_check : qr_pending} alt="qr_check" className='mr-1' />}
iconPath={<img src={isCheckIn ? qr_check : qr_pending} alt="qr_check" className="mr-1" />}
children={isCheckIn ? '체크인 완료' : '체크인 미완료'}
className="text-11"
></IconText>
Expand All @@ -121,6 +127,5 @@ const QrModal = ({
</div>
</div>
);

};
export default QrModal;
6 changes: 1 addition & 5 deletions src/features/event/hooks/usePresignedUrlHook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const getPresignedUrl = async (dto: PresignedUrlRequest) => {
const response = await axiosClient.get<ApiResponse<PresignedUrlResponse>>('/generate-presigned-url', {
params: dto,
});
console.log('Presigned URL 응답:', response.data.result?.preSignedUrl);

return response.data.result?.preSignedUrl;
} catch (error) {
Expand All @@ -21,14 +20,12 @@ const getPresignedUrl = async (dto: PresignedUrlRequest) => {
export const putS3Image = async ({ url, file }: { url: string; file: File }) => {
try {
delete axiosClient.defaults.headers.common.Authorization;
console.log('업로드할 URL:', url);
await axios.put(url, file, {
headers: {
'Content-Type': 'image/webp',
},
});
} catch (error) {
console.error('S3 업로드 실패:', error);
} catch {
alert('이미지 업로드에 실패했습니다.');
throw new Error('Failed to upload image');
}
Comment on lines +28 to 31
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

파일 업로드 에러 처리 개선 필요

파일 업로드 관련 에러는 네트워크 문제, 권한 문제, 파일 크기 제한 등 다양한 원인이 있을 수 있습니다. 에러 정보를 완전히 제거하면 사용자 지원 시 문제 해결이 어려워질 수 있습니다.

-  } catch {
+  } catch (error) {
+    console.error('S3 이미지 업로드 실패:', error);
     alert('이미지 업로드에 실패했습니다.');
     throw new Error('Failed to upload image');
   }
📝 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
} catch {
alert('이미지 업로드에 실패했습니다.');
throw new Error('Failed to upload image');
}
} catch (error) {
console.error('S3 이미지 업로드 실패:', error);
alert('이미지 업로드에 실패했습니다.');
throw new Error('Failed to upload image');
}
🤖 Prompt for AI Agents
In src/features/event/hooks/usePresignedUrlHook.ts around lines 28 to 31, the
catch block for file upload errors currently does not capture or log the
specific error details, which can hinder troubleshooting. Modify the catch block
to accept the error object, then log or handle the error details appropriately
before alerting the user and throwing a new error. This will preserve useful
error information for debugging and support.

Expand All @@ -45,7 +42,6 @@ export const uploadFile = async (file: File) => {
}

const url = presignedUrlResponse;
console.log('Presigned URL:', url);

await putS3Image({ url, file: webFile });

Expand Down
16 changes: 2 additions & 14 deletions src/features/event/ui/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,13 @@ const EventDatePicker = ({
isLabel = false,
}: DatePickerProps) => {
const [startDate, setStartDate] = useState<Date | null>(
eventState?.startDate
? new Date(eventState.startDate)
: initialStartDate
? new Date(initialStartDate)
: new Date()
eventState?.startDate ? new Date(eventState.startDate) : initialStartDate ? new Date(initialStartDate) : new Date()
);

const [endDate, setEndDate] = useState<Date | null>(
eventState?.endDate
? new Date(eventState.endDate)
: initialEndDate
? new Date(initialEndDate)
: new Date()
eventState?.endDate ? new Date(eventState.endDate) : initialEndDate ? new Date(initialEndDate) : new Date()
);

console.log('startDate', startDate);
console.log('endDate', endDate);

const [startTime, setStartTime] = useState<string>(
extractTimeFromDateString(eventState?.startDate || initialStartDate, '06:00')
);
Expand Down Expand Up @@ -86,7 +75,6 @@ const EventDatePicker = ({
}
}, [eventState?.startDate, eventState?.endDate, initialStartDate, initialEndDate]);


const generateTimeOptions = () => {
const options = [];
for (let i = 0; i < 24; i++) {
Expand Down
6 changes: 2 additions & 4 deletions src/features/event/ui/ShareEventModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ const ShareEventModal = ({
const handleKakaoShare = async () => {
try {
await shareToKakao(title, description, eventImageUrl, eventUrl);
} catch (error) {
console.error('카카오 공유 실패:', error);
} catch {
alert('카카오 공유하기에 실패했습니다.');
}
};
Expand All @@ -89,8 +88,7 @@ const ShareEventModal = ({
navigator.clipboard
.writeText(eventUrl)
.then(() => alert('링크가 복사되었습니다!'))
.catch(err => {
console.error('복사 실패:', err);
.catch(() => {
alert('링크 복사에 실패했습니다.');
});
} else {
Expand Down
9 changes: 2 additions & 7 deletions src/features/event/ui/TimePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,8 @@ const parseUtcToKst = (utcString: string): Date => {
const TimePicker = ({ value, onChange }: TimePickerProps) => {
const initialKstDate = value ? parseUtcToKst(value) : new Date();
const [selectedDate, setSelectedDate] = useState<Date | null>(initialKstDate);
const [selectedHour, setSelectedHour] = useState<string>(
initialKstDate.getHours().toString().padStart(2, '0')
);
const [selectedMinute, setSelectedMinute] = useState<string>(
initialKstDate.getMinutes().toString().padStart(2, '0')
);
const [selectedHour, setSelectedHour] = useState<string>(initialKstDate.getHours().toString().padStart(2, '0'));
const [selectedMinute, setSelectedMinute] = useState<string>(initialKstDate.getMinutes().toString().padStart(2, '0'));

useEffect(() => {
if (value) {
Expand All @@ -47,7 +43,6 @@ const TimePicker = ({ value, onChange }: TimePickerProps) => {
const localString = `${year}-${month}-${day}T${hour}:${minute}:00`;

onChange(localString);
console.log(localString);
}
}, [selectedDate, selectedHour, selectedMinute]);

Expand Down
2 changes: 0 additions & 2 deletions src/features/ticket/hooks/useTicketOptionForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,6 @@ export const useTicketOptionForm = () => {
const handleSave = () => {
let isValid = true;

console.log('Clicked!');

if (state.question.title.trim() === '') {
dispatch({
type: 'SET_WARNING',
Expand Down
11 changes: 0 additions & 11 deletions src/features/ticket/hooks/useTicketOptionHook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ export const useTicketOptions = (ticketId: number) => {
export const useCreateTicketOptionAnswers = () => {
return useMutation<ApiResponse<null>, Error, TicketOptionAnswerRequest>({
mutationFn: createTicketOptionAnswers,
onSuccess: () => {
console.log('티켓 옵션 응답 전송 성공');
},
onError: () => {
alert('티켓 옵션 응답 전송 중 오류가 발생했습니다.');
},
Expand Down Expand Up @@ -177,10 +174,6 @@ export const useAttachTicketOptionMutation = () => {
onSuccess: (_data, variables) => {
// 티켓별 옵션 목록 쿼리 리패칭
queryClient.invalidateQueries({ queryKey: ['attachedTicketOptions', variables.ticketId] });
console.log('티켓 옵션이 성공적으로 부착되었습니다.');
},
onError: () => {
console.log('티켓 옵션 부착에 실패했습니다. 다시 시도해주세요.');
},
});
};
Expand All @@ -194,10 +187,6 @@ export const useDetachTicketOptionMutation = () => {
onSuccess: (_data, variables) => {
// 티켓별 옵션 목록 쿼리 리패칭
queryClient.invalidateQueries({ queryKey: ['attachedTicketOptions', variables.ticketId] });
console.log('티켓에 부착된 티켓 옵션이 성공적으로 부착 취소되었습니다.');
},
onError: () => {
console.log('티켓에 부착된 티켓 옵션 부착 취소에 실패했습니다. 다시 시도해주세요.');
},
});
};
5 changes: 2 additions & 3 deletions src/pages/dashboard/ui/EventDetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ const EventDetailPage = () => {
const [referenceLinks, setReferenceLinks] = useState<Link[]>([]);

const queryClient = useQueryClient();

useEffect(() => {
console.log(data?.result.bannerImageUrl)
if (data?.result) {
setHostChannelId(data.result.hostChannelId || 0);
setBannerImageUrl(prev => prev || data.result.bannerImageUrl || '');
Expand Down Expand Up @@ -73,7 +72,7 @@ const EventDetailPage = () => {
<div className="flex flex-col gap-5 mt-8 px-7">
<h1 className="text-center text-xl font-bold mb-5">이벤트 상세 정보</h1>
<FileUpload value={bannerImageUrl} onChange={setBannerImageUrl} useDefaultImage={false} />
<TextEditor value={description} onChange={setDescription}/>
<TextEditor value={description} onChange={setDescription} />
<LinkInput value={referenceLinks} onChange={setReferenceLinks} />
</div>
<div className="w-full p-7">
Expand Down
5 changes: 2 additions & 3 deletions src/pages/dashboard/ui/EventInfoPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ const EventInfoPage = () => {
queryClient.invalidateQueries({ queryKey: ['eventDetail', data.result.id] });
navigate(`/dashboard/${data?.result.id}`);
},
onError: error => {
console.error('Error details:', error);
onError: () => {
alert('저장에 실패했습니다.');
},
});
Expand All @@ -93,7 +92,7 @@ const EventInfoPage = () => {

return (
// <DashboardLayout centerContent={title}>
<DashboardLayout centerContent={"DASHBOARD"}>
<DashboardLayout centerContent={'DASHBOARD'}>
<div className="flex flex-col gap-5 mt-8 px-7">
<h1 className="text-center text-xl font-bold mb-5">이벤트 기본 정보</h1>
<DefaultTextField
Expand Down
3 changes: 1 addition & 2 deletions src/pages/event/ui/host/HostSelectionPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ const HostSelectionPage = ({ onNext, currentStep, onValidationChange }: HostSele
}
},
onError: error => {
console.error('호스트 삭제 실패:', error);
alert(`${error.message}`);
},
});
Expand All @@ -61,7 +60,7 @@ const HostSelectionPage = ({ onNext, currentStep, onValidationChange }: HostSele
<button className="flex justify-center items-center w-12 h-12 md:w-14 md:h-14 bg-gray2 rounded-full">
<IconButton
iconPath={<img src={AddButton} alt="추가 버튼" className="w-6 h-6 md:w-7 md:h-7" />}
onClick={() => { }}
onClick={() => {}}
/>
</button>
<span className="font-bold text-base md:text-xl ml-4">채널 새로 만들기</span>
Expand Down
59 changes: 28 additions & 31 deletions src/pages/join/AuthCallback.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,35 @@
import { useNavigate, useSearchParams } from "react-router-dom";
import useAuthStore from "../../app/provider/authStore";
import { useEffect } from "react";
import { useUserInfo } from "../../features/join/hooks/useUserHook";
import { useNavigate, useSearchParams } from 'react-router-dom';
import useAuthStore from '../../app/provider/authStore';
import { useEffect } from 'react';
import { useUserInfo } from '../../features/join/hooks/useUserHook';

const AuthCallback = () => {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const status = searchParams.get('status'); // 'new' or 'existing'
const { login, setName, closeModal } = useAuthStore();
const { data } = useUserInfo();
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const status = searchParams.get('status'); // 'new' or 'existing'
const { login, setName, closeModal } = useAuthStore();
const { data } = useUserInfo();

useEffect(() => {
const handleAuth = async () => {
if (!data) return;
try {
closeModal();
if (status === 'new') {
navigate('/join/agreement');
} else {
login();
setName(data?.name || "사용자");
navigate('/');
}
} catch (error) {
console.error('인증 처리 실패', error);
navigate('/');
}
};
handleAuth();
}, [data, navigate, login, status, setName, closeModal]);
useEffect(() => {
const handleAuth = async () => {
if (!data) return;
try {
closeModal();
if (status === 'new') {
navigate('/join/agreement');
} else {
login();
setName(data?.name || '사용자');
navigate('/');
}
} catch {
navigate('/');
}
};
handleAuth();
}, [data, navigate, login, status, setName, closeModal]);

return <div className="text-center mt-32 text-lg font-bold">로그인 중입니다...</div>;
return <div className="text-center mt-32 text-lg font-bold">로그인 중입니다...</div>;
};

export default AuthCallback;


3 changes: 1 addition & 2 deletions src/pages/join/InfoInputPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,8 @@ const InfoInputPage = () => {
}
);
},
onError: err => {
onError: () => {
alert('정보 업데이트에 실패했습니다. 다시 시도해주세요.');
console.error(err);
},
});
};
Expand Down
Loading