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
8 changes: 6 additions & 2 deletions src/app/(pages)/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import LoginMainBigLogo from '@/public/svg/logo/login-main-big.svg';
import { redirect, useRouter } from 'next/navigation';
import { useAuthStore } from '@/lib/stores/auth-store';
import { useEffect } from 'react';
import { apiClient } from '@/lib/api/axios-client-config';

export default function LoginPage() {
const router = useRouter();
Expand All @@ -15,15 +16,18 @@ export default function LoginPage() {
kakaoAuthService.login();
};
const handleGuestLogin = async () => {
const token = 'guest';
const tokenResponse: { accessToken: string } = await apiClient({
url: '/test/auth/login',
method: 'POST',
});
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_ROUTE_URL}/api/cookie-set`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ token }),
body: JSON.stringify({ token: tokenResponse.accessToken }),
},
);
if (!response.ok) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import { toast } from 'sonner';
import MakeVideoStartIcon from '@/public/svg/make-video/make-video-start.svg';
import { GradientProgressBar } from '@/components/gradient-progress-bar';
import { useRouter } from 'next/navigation';
import {
createVideoGeneration,
} from '@/lib/api/video/video';
import { createVideoGeneration } from '@/lib/api/video/video';

export function VideoImageUpload() {
const router = useRouter();
Expand Down Expand Up @@ -57,19 +55,26 @@ export function VideoImageUpload() {
videoUrl: url,
})),
storeId: currentStore?.id ?? '',
}).then(response => {
if (!response.videoGenerationId) {
toast.error('영상 생성에 실패했습니다. 새로고침 후 다시 시도해주세요.');
})
.then(response => {
console.log('response:', response);
if (!response.videoGenerationId) {
toast.error(
'영상 생성에 실패했습니다. 새로고침 후 다시 시도해주세요.',
);
setIsProcessing(false);
return;
}
router.replace(
`/mypage/manage-video?generationId=${response.videoGenerationId}`,
);
})
.catch(() => {
toast.error(
'영상 생성에 실패했습니다. 새로고침 후 다시 시도해주세요.',
);
setIsProcessing(false);
return;
}
router.replace(
`/mypage/manage-video?generationId=${response.videoGenerationId}`,
);
}).catch(() => {
toast.error('영상 생성에 실패했습니다. 새로고침 후 다시 시도해주세요.');
setIsProcessing(false);
});
});
},
onUploadError: error => {
toast.error(error.message);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getVideo } from '@/lib/api/video/video';
import { VideoPlayer } from '../../../_components/manage-video/video-player';

export default async function VideoDetailPage({
Expand All @@ -7,10 +8,11 @@ export default async function VideoDetailPage({
}) {
const videoId = (await params).video_id;
console.log(videoId);
// const videoInfo = await getVideo(videoId);

return (
<section className='py-6 w-full h-[calc(100vh-220px)] min-h-0'>
<VideoPlayer videoId={videoId} />
<VideoPlayer />
</section>
);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FieldContainer } from '@/components/store-info';
import { VideoCheckDescription } from '../../../../_components/manage-video/video-check-description';
import { cn } from '@/lib/utils/cn';
import { VideoCheckButton } from '../../../../_components/manage-video/video-check-button';

const VIDEO_URL =
'https://f002.backblazeb2.com/file/creatomate-c8xg3hsxdu/6683c14f-7d35-45ea-9402-d87fd498f5a7.mp4';
Expand Down Expand Up @@ -30,6 +30,7 @@ export default async function VideoCheckPage({
</div>
</div>
<VideoCheckDescription />
<VideoCheckButton videoUrl={VIDEO_URL} />
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
'use client';

import { toast } from 'sonner';

export function VideoCheckButton({ videoUrl }: { videoUrl: string }) {
// 갤러리에 저장 (다운로드) 기능
const handleDownload = async () => {
try {
const response = await fetch(videoUrl);
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `shorts-table-video-${Date.now()}.mp4`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
toast.success('영상이 다운로드되었습니다!');
} catch (error) {
console.error('Download failed:', error);
toast.error('다운로드에 실패했습니다. 다시 시도해주세요.');
}
};

// 업로드 요청 (이메일 발송) 기능
const handleUploadRequest = async () => {
toast.success('업로드 요청이 완료되었습니다!');
};

return (
<div className='w-full h-auto flex items-center gap-2'>
<button
onClick={handleDownload}
className='flex-1 w-full px-5 py-2 h-14 text-bodySmall rounded-[15px] bg-gray200 text-gray600 hover:bg-gray300 transition-colors'
>
갤러리에 저장
</button>
<button
onClick={handleUploadRequest}
className='flex-1 w-full px-5 py-2 h-14 text-bodySmall rounded-[15px] bg-orange400 text-white000 hover:bg-orange500 transition-colors'
>
업로드 요청
</button>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
import { useState } from 'react';
import { LoadingSpinner } from '@/components/loading-spinner';
import { useRouter } from 'next/navigation';
import type { VideoResponse } from '@/types/api';

export function VideoPlayer({ videoId }: { videoId: string }) {
export function VideoPlayer() {
const router = useRouter();
const videoUrl =
'https://f002.backblazeb2.com/file/creatomate-c8xg3hsxdu/6683c14f-7d35-45ea-9402-d87fd498f5a7.mp4';
Expand Down Expand Up @@ -39,9 +40,7 @@ export function VideoPlayer({ videoId }: { videoId: string }) {
다시 만들기
</button>
<button
onClick={() =>
router.push(`/mypage/manage-video/${videoId}/video-check`)
}
onClick={() => router.push(`/mypage/manage-video/1/video-check`)}
className='flex-1 w-full h-10 min-mobile:h-14 text-bodySmall rounded-[8px] bg-orange400 text-white000 cursor-pointer'
>
다음
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export function VideoProgressHeader({
}: {
generationId: string;
}) {
const { status, progress } = useVideoGeneration(generationId);
const { status, progress, generatedVideoUrl, generatedVideoId } =
useVideoGeneration(generationId);

return (
<header className='mt-8 p-6 w-full h-auto flex flex-col items-start gap-1 bg-white000 border border-gray100 rounded-[15px] shadow-[0_4px_10px_0_rgba(154,159,160,0.15)]'>
Expand All @@ -28,7 +29,7 @@ export function VideoProgressHeader({
영상 제작이 완료되었어요!
</h2>
<Link
href={`/mypage/manage-video/${1}`}
href={`/mypage/manage-video/${generatedVideoId}`}
className='flex items-center'
>
<span className='text-labelLargeMid text-orange400'>
Expand Down
14 changes: 13 additions & 1 deletion src/hooks/use-video-generation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import { getVideoGenerationStatus } from '@/lib/api/video/video';

export function useVideoGeneration(initialGenerationId: string) {
const [generationId, setGenerationId] = useState<string | null>(null);
const [generatedVideoUrl, setGeneratedVideoUrl] = useState<string | null>(
null,
);
const [generatedVideoId, setGeneratedVideoId] = useState<string | null>(null);
const [status, setStatus] = useState<
'IDLE' | 'IN_PROGRESS' | 'FINISHED' | 'FAILED'
>('IDLE');
Expand All @@ -33,6 +37,8 @@ export function useVideoGeneration(initialGenerationId: string) {
const result = await getVideoGenerationStatus(generationId);
console.log('result:', result);
setStatus(result.status ?? 'IDLE');
setGeneratedVideoUrl(result.generatedVideoUrl ?? null);
setGeneratedVideoId(result.videoGenerationId ?? null);

// 상태별 프로그레스
const progressMap = {
Expand Down Expand Up @@ -65,5 +71,11 @@ export function useVideoGeneration(initialGenerationId: string) {
return () => clearInterval(interval);
}, [generationId]);

return { status, progress, hasActiveGeneration: !!generationId };
return {
status,
progress,
hasActiveGeneration: !!generationId,
generatedVideoUrl: generatedVideoUrl,
generatedVideoId: generatedVideoId,
};
}
4 changes: 2 additions & 2 deletions src/lib/api/axios-client-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:3000';
// 기본 axios 인스턴스 생성
const instance = axios.create({
baseURL: API_BASE_URL,
timeout: 10000,
timeout: 50000,
withCredentials: true,
});

// 토큰 검사를 하지 않을 경로들
const NO_AUTH_REQUIRED_PATHS = ['/auth/kakao-login'];
const NO_AUTH_REQUIRED_PATHS = ['/auth/kakao-login', '/test/auth/login'];

instance.interceptors.request.use(
async config => {
Expand Down
5 changes: 4 additions & 1 deletion src/lib/api/video/video.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ export const createVideoGeneration = (
* @summary 영상 조회
*/
export const getVideo = (videoId: string) => {
return apiClient<VideoResponse>({ url: `/videos/${videoId}`, method: 'GET' });
return apiClient<VideoResponse>({
url: `/videos/${videoId}`,
method: 'GET',
});
};
/**
* 영상 ID로 영상을 삭제합니다
Expand Down
4 changes: 4 additions & 0 deletions src/types/api/videoGenerationStatusResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ export interface VideoGenerationStatusResponse {
status?: VideoGenerationStatusResponseStatus;
/** 요청 생성 시간 */
createdAt?: string;
/** 생성된 영상 URL */
generatedVideoUrl?: string;
/** 오류 메시지 */
errorMessage?: string;
}
Loading