예약 업로드 충돌 시 실제 예약 시간 반환

main
김성경 2026-06-12 16:37:06 +09:00
parent cb68b2da97
commit 429c8d4708
5 changed files with 37 additions and 7 deletions

View File

@ -157,6 +157,7 @@ const SocialPostingModal: React.FC<SocialPostingModalProps> = ({
const [uploadVideoTitle, setUploadVideoTitle] = useState<string>('');
const [uploadChannelName, setUploadChannelName] = useState<string>('');
const [uploadIsScheduled, setUploadIsScheduled] = useState(false);
const [uploadScheduledAt, setUploadScheduledAt] = useState<string | null>(null);
// 드롭다운 외부 클릭 시 닫기
useEffect(() => {
@ -373,12 +374,13 @@ const SocialPostingModal: React.FC<SocialPostingModalProps> = ({
// 예약 업로드: 폴링 없이 바로 완료 처리
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<SocialPostingModalProps> = ({
setUploadVideoTitle('');
setUploadChannelName('');
setUploadIsScheduled(false);
setUploadScheduledAt(null);
};
const handleClose = () => {
@ -461,6 +464,7 @@ const SocialPostingModal: React.FC<SocialPostingModalProps> = ({
youtubeUrl={uploadYoutubeUrl}
errorMessage={uploadErrorMessage}
isScheduled={uploadIsScheduled}
scheduledAt={uploadScheduledAt}
onGoToCalendar={onGoToCalendar}
/>
);

View File

@ -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<UploadProgressModalProps> = ({
youtubeUrl,
errorMessage,
isScheduled = false,
scheduledAt,
onGoToCalendar,
}) => {
const { t } = useTranslation();
@ -148,6 +150,28 @@ const UploadProgressModal: React.FC<UploadProgressModalProps> = ({
{t('upload.viewOnYoutube')}
</a>
)}
{/* Scheduled conflict notice */}
{status === 'completed' && isScheduled && scheduledAt && (
<div className="upload-progress-schedule-notice">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<circle cx="12" cy="12" r="10" />
<line x1="12" y1="8" x2="12" y2="12" />
<line x1="12" y1="16" x2="12.01" y2="16" />
</svg>
<span>
{t('upload.scheduleConflict', {
time: new Date(scheduledAt).toLocaleString('ko-KR', {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
}),
})}
</span>
</div>
)}
</div>
{/* Footer */}

View File

@ -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",

View File

@ -154,8 +154,8 @@
"confirm": "확인",
"close": "닫기",
"doNotClose": "업로드가 진행 중입니다. 창을 닫지 마세요.",
"goToCalendar": "캘린더에서 확인"
},
"goToCalendar": "캘린더에서 확인",
"scheduleConflict": "예약 시간이 충돌하여 {{time}}으로 조정되었습니다." },
"landing": {
"hero": {
"searchTypeBusinessName": "업체명",

View File

@ -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; // 예약 업로드 충돌 시 실제 예약 시간 반환
}
// 소셜 업로드 상태 조회 응답