diff --git a/app/calendar/page.tsx b/app/calendar/page.tsx new file mode 100644 index 0000000..6432119 --- /dev/null +++ b/app/calendar/page.tsx @@ -0,0 +1,345 @@ +'use client' + +import { useState, useEffect } from 'react' +import Script from 'next/script' + +interface GoogleOAuthResponse { + access_token: string +} + +interface GoogleTokenClient { + requestAccessToken: () => void +} + +interface GoogleTokenClientConfig { + client_id: string + scope: string + callback: (response: GoogleOAuthResponse) => void +} + +interface CalendarEventResponse { + id: string + summary: string + htmlLink: string + startDateTime: string + endDateTime: string +} + +declare global { + interface Window { + google?: { + accounts: { + oauth2: { + initTokenClient: (config: GoogleTokenClientConfig) => GoogleTokenClient + } + } + } + } +} + +export default function CalendarPage() { + const [accessToken, setAccessToken] = useState(null) + + // 기본값: 현재 시간과 1시간 후 + const getDefaultDateTime = () => { + const now = new Date() + const oneHourLater = new Date(now.getTime() + 60 * 60 * 1000) + + const formatDateTime = (date: Date) => { + const year = date.getFullYear() + const month = String(date.getMonth() + 1).padStart(2, '0') + const day = String(date.getDate()).padStart(2, '0') + const hours = String(date.getHours()).padStart(2, '0') + const minutes = String(date.getMinutes()).padStart(2, '0') + return `${year}-${month}-${day}T${hours}:${minutes}` + } + + return { + start: formatDateTime(now), + end: formatDateTime(oneHourLater) + } + } + + const defaultTimes = getDefaultDateTime() + + const [formData, setFormData] = useState({ + summary: '', + description: '', + location: '', + startDateTime: defaultTimes.start, + endDateTime: defaultTimes.end, + calendarId: 'primary', + }) + const [loading, setLoading] = useState(false) + const [result, setResult] = useState(null) + const [error, setError] = useState(null) + const [googleLoaded, setGoogleLoaded] = useState(false) + + useEffect(() => { + if (googleLoaded && window.google) { + const client = window.google.accounts.oauth2.initTokenClient({ + client_id: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || '', + scope: 'https://www.googleapis.com/auth/calendar', + callback: (response: GoogleOAuthResponse) => { + if (response.access_token) { + setAccessToken(response.access_token) + setError(null) + } + }, + }) + + const button = document.getElementById('google-signin-button') + if (button) { + button.onclick = () => { + client.requestAccessToken() + } + } + } + }, [googleLoaded]) + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + if (!accessToken) { + setError('먼저 Google 로그인이 필요합니다') + return + } + + setLoading(true) + setError(null) + setResult(null) + + try { + const apiUrl = process.env.NEXT_PUBLIC_STASH_API_URL + const response = await fetch(`${apiUrl}/api/calendar/events`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${accessToken}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + summary: formData.summary, + description: formData.description || null, + location: formData.location || null, + startDateTime: formData.startDateTime, + endDateTime: formData.endDateTime, + timeZone: 'Asia/Seoul', + attendees: [], + calendarId: formData.calendarId || null, + }), + }) + + if (!response.ok) { + const errorData = await response.json() + throw new Error(errorData.message || '캘린더 이벤트 생성 실패') + } + + const data = await response.json() + setResult(data) + // 폼 초기화 (새로운 기본값으로) + const newDefaultTimes = getDefaultDateTime() + setFormData({ + summary: '', + description: '', + location: '', + startDateTime: newDefaultTimes.start, + endDateTime: newDefaultTimes.end, + calendarId: 'primary', + }) + } catch (err) { + setError(err instanceof Error ? err.message : '오류가 발생했습니다') + } finally { + setLoading(false) + } + } + + return ( + <> +