diff --git a/src/components/SocialPostingModal.tsx b/src/components/SocialPostingModal.tsx index 486f377..501c977 100644 --- a/src/components/SocialPostingModal.tsx +++ b/src/components/SocialPostingModal.tsx @@ -157,6 +157,7 @@ const SocialPostingModal: React.FC = ({ const [uploadVideoTitle, setUploadVideoTitle] = useState(''); const [uploadChannelName, setUploadChannelName] = useState(''); const [uploadIsScheduled, setUploadIsScheduled] = useState(false); + const [uploadScheduledAt, setUploadScheduledAt] = useState(null); // 드롭다운 외부 클릭 시 닫기 useEffect(() => { @@ -373,12 +374,13 @@ const SocialPostingModal: React.FC = ({ // 예약 업로드: 폴링 없이 바로 완료 처리 setUploadStatus('completed'); setUploadProgress(100); + setUploadScheduledAt(uploadResponse.scheduled_at ?? null); onClose(); resetForm(); } else { // 즉시 업로드: 완료될 때까지 폴링 const result = await waitForUploadComplete( - uploadResponse.upload_id, + uploadResponse.upload_id.toString(), (status, progress) => { setUploadStatus(status as UploadStatus); setUploadProgress(progress || 0); @@ -432,6 +434,7 @@ const SocialPostingModal: React.FC = ({ setUploadVideoTitle(''); setUploadChannelName(''); setUploadIsScheduled(false); + setUploadScheduledAt(null); }; const handleClose = () => { @@ -461,6 +464,7 @@ const SocialPostingModal: React.FC = ({ youtubeUrl={uploadYoutubeUrl} errorMessage={uploadErrorMessage} isScheduled={uploadIsScheduled} + scheduledAt={uploadScheduledAt} onGoToCalendar={onGoToCalendar} /> ); diff --git a/src/components/UploadProgressModal.tsx b/src/components/UploadProgressModal.tsx index 8572619..8aec55a 100644 --- a/src/components/UploadProgressModal.tsx +++ b/src/components/UploadProgressModal.tsx @@ -14,6 +14,7 @@ interface UploadProgressModalProps { youtubeUrl?: string; errorMessage?: string; isScheduled?: boolean; + scheduledAt?: string | null; onGoToCalendar?: () => void; } @@ -27,6 +28,7 @@ const UploadProgressModal: React.FC = ({ youtubeUrl, errorMessage, isScheduled = false, + scheduledAt, onGoToCalendar, }) => { const { t } = useTranslation(); @@ -148,6 +150,28 @@ const UploadProgressModal: React.FC = ({ {t('upload.viewOnYoutube')} )} + + {/* Scheduled conflict notice */} + {status === 'completed' && isScheduled && scheduledAt && ( +
+ + + + + + + {t('upload.scheduleConflict', { + time: new Date(scheduledAt).toLocaleString('ko-KR', { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: '2-digit', + minute: '2-digit', + }), + })} + +
+ )} {/* Footer */} diff --git a/src/locales/en.json b/src/locales/en.json index a6393c5..7b3c09b 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -154,8 +154,8 @@ "confirm": "OK", "close": "Close", "doNotClose": "Upload is in progress. Do not close this window.", - "goToCalendar": "View in Calendar" - }, + "goToCalendar": "View in Calendar", + "scheduleConflict": "Schedule adjusted to {{time}} due to a conflict." }, "landing": { "hero": { "searchTypeBusinessName": "Business Name", diff --git a/src/locales/ko.json b/src/locales/ko.json index 26a79ed..cde52e4 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -154,8 +154,8 @@ "confirm": "확인", "close": "닫기", "doNotClose": "업로드가 진행 중입니다. 창을 닫지 마세요.", - "goToCalendar": "캘린더에서 확인" - }, + "goToCalendar": "캘린더에서 확인", + "scheduleConflict": "예약 시간이 충돌하여 {{time}}으로 조정되었습니다." }, "landing": { "hero": { "searchTypeBusinessName": "업체명", diff --git a/src/types/api.ts b/src/types/api.ts index c3373e6..e055eef 100644 --- a/src/types/api.ts +++ b/src/types/api.ts @@ -412,9 +412,11 @@ export interface SocialUploadRequest { // 소셜 업로드 응답 export interface SocialUploadResponse { success: boolean; - upload_id: string; - status: 'pending' | 'uploading' | 'completed' | 'failed'; + upload_id: number; + platform: string; + status: string; message: string; + scheduled_at?: string | null; // 예약 업로드 충돌 시 실제 예약 시간 반환 } // 소셜 업로드 상태 조회 응답