class RestModal { constructor() { this.restTime = 5; // 기본 5분 this.currentTime = this.restTime * 60; // 초 단위 this.timer = null; this.config = null; this.currentSaying = null; this.autoZzim = false; // 기본 추천 활동 목록 (백엔드 연결 실패 시 사용) this.defaultActivities = [ "🚶‍♀️ 가벼운 산책을 해보세요", "💧 물 한 잔을 마시며 수분을 보충하세요", "🧘‍♀️ 심호흡을 하며 명상을 해보세요", "🤸‍♀️ 간단한 스트레칭으로 몸을 풀어보세요", "👀 눈 운동을 하며 눈의 피로를 풀어보세요", "🚽 화장실을 다녀오세요", "🌱 창밖을 보며 자연을 감상해보세요", "📱 잠시 휴대폰을 내려놓고 마음을 비워보세요", "☕ 따뜻한 차 한 잔을 마셔보세요", "🎵 좋아하는 음악을 들으며 휴식하세요", "📚 짧은 글이나 명언을 읽어보세요", "🤝 동료나 가족과 간단한 대화를 나누세요", "🧴 손 마사지나 목 마사지를 해보세요", "🏃‍♀️ 제자리에서 가볍게 몸을 움직여보세요", "🍎 건강한 간식을 드세요" ]; this.activities = []; // 백엔드에서 가져온 활동 목록 } async init() { try { await this.loadSettings(); await this.loadConfig(); this.setupEventListeners(); await this.loadRestActivities(); this.showRandomActivity(); await this.loadRandomSaying(); this.startTimer(); } catch (error) { console.error('[RestModal] 초기화 실패:', error); } } async loadSettings() { try { const result = await chrome.storage.local.get('time_alarm_settings'); const settings = result.time_alarm_settings || {}; this.restTime = settings.restTime || 5; this.autoZzim = settings.autoZzim || false; this.currentTime = this.restTime * 60; console.log('[RestModal] 설정 로드:', { restTime: this.restTime, autoZzim: this.autoZzim }); } catch (error) { console.error('[RestModal] 설정 로드 실패:', error); } } async loadConfig() { try { const result = await chrome.storage.local.get('settings_config'); this.config = result.settings_config || {}; console.log('[RestModal] 설정 정보 로드:', this.config); } catch (error) { console.error('[RestModal] 설정 정보 로드 실패:', error); } } setupEventListeners() { // 닫기 버튼 document.getElementById('closeBtn').addEventListener('click', () => { this.closeModal(); }); // 건너뛰기 버튼 document.getElementById('skipBtn').addEventListener('click', () => { this.closeModal(); }); // ESC 키로 닫기 document.addEventListener('keydown', (e) => { if (e.key === 'Escape') { this.closeModal(); } }); } async loadRestActivities() { try { if (!this.config.ACCESS_TOKEN) { throw new Error('Access token not found'); } const SUPABASE_URL = this.config.SUPABASE_URL || "http://146.56.101.199:8000"; const SUPABASE_ANON_KEY = this.config.SUPABASE_ANON_KEY || "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE"; // public.events 테이블에서 event_type이 'rest_time'인 데이터 가져오기 const apiUrl = `${SUPABASE_URL}/rest/v1/events?select=message&event_type=eq.rest_time&order=created_at.desc&limit=50`; console.log('[RestModal] 추천활동 API 호출:', apiUrl); const response = await fetch(apiUrl, { method: 'GET', headers: { 'apikey': SUPABASE_ANON_KEY, 'Authorization': `Bearer ${this.config.ACCESS_TOKEN}`, 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error(`API 호출 실패: ${response.status}`); } const events = await response.json(); if (events && events.length > 0) { // message 필드에서 JSON 파싱하여 활동 목록 생성 this.activities = []; events.forEach(event => { try { // message 필드가 JSON 형식인 경우 파싱 const messageData = JSON.parse(event.message); // 활동 텍스트 추출 (다양한 형식 지원) if (messageData.activity) { this.activities.push(messageData.activity); } else if (messageData.text) { this.activities.push(messageData.text); } else if (typeof messageData === 'string') { this.activities.push(messageData); } } catch (parseError) { // JSON 파싱 실패 시 문자열 그대로 사용 if (typeof event.message === 'string' && event.message.trim()) { this.activities.push(event.message); } } }); console.log('[RestModal] 백엔드에서 추천활동 로드 완료:', this.activities.length + '개'); } else { throw new Error('추천활동 데이터가 없습니다'); } } catch (error) { console.error('[RestModal] 추천활동 로드 실패:', error); // 기본 활동 목록 사용 this.activities = [...this.defaultActivities]; console.log('[RestModal] 기본 추천활동 사용:', this.activities.length + '개'); } } showRandomActivity() { if (this.activities.length === 0) { this.activities = [...this.defaultActivities]; } const randomActivity = this.activities[Math.floor(Math.random() * this.activities.length)]; document.getElementById('activitySuggestion').innerHTML = randomActivity; } async loadRandomSaying() { try { if (!this.config.ACCESS_TOKEN) { throw new Error('Access token not found'); } const SUPABASE_URL = this.config.SUPABASE_URL || "http://146.56.101.199:8000"; const SUPABASE_ANON_KEY = this.config.SUPABASE_ANON_KEY || "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE"; // 최근 1달 이내의 승인된 어록 가져오기 const oneMonthAgo = new Date(); oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1); const apiUrl = `${SUPABASE_URL}/rest/v1/tanya_sayings?select=*,sayings_cat(saying_cat),sayings_target(target)&created_at=gte.${oneMonthAgo.toISOString()}&admin_approval=eq.true&order=created_at.desc&limit=50`; console.log('[RestModal] 어록 API 호출:', apiUrl); const response = await fetch(apiUrl, { method: 'GET', headers: { 'apikey': SUPABASE_ANON_KEY, 'Authorization': `Bearer ${this.config.ACCESS_TOKEN}`, 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error(`API 호출 실패: ${response.status}`); } const sayings = await response.json(); if (sayings && sayings.length > 0) { // 랜덤하게 하나 선택 const randomSaying = sayings[Math.floor(Math.random() * sayings.length)]; this.currentSaying = randomSaying; // 어록 표시 const sayingContent = document.getElementById('sayingContent'); const sayingAuthor = document.getElementById('sayingAuthor'); sayingContent.innerHTML = `"${randomSaying.saying}"`; // 카테고리와 대상 정보 표시 const category = randomSaying.sayings_cat?.saying_cat || ''; const target = randomSaying.sayings_target?.target || ''; const dateStr = new Date(randomSaying.created_at).toLocaleDateString('ko-KR'); sayingAuthor.innerHTML = `${category} ${target ? `• ${target}` : ''} • ${dateStr}`; console.log('[RestModal] 어록 로드 완료:', randomSaying); } else { throw new Error('어록이 없습니다'); } } catch (error) { console.error('[RestModal] 어록 로드 실패:', error); // 기본 메시지 표시 document.getElementById('sayingContent').innerHTML = '"열심히 일한 당신, 잠시 휴식을 취하며 에너지를 충전하세요!"'; document.getElementById('sayingAuthor').innerHTML = '타냐 • 휴식 메시지'; } } startTimer() { this.updateTimerDisplay(); this.updateProgressBar(); this.timer = setInterval(() => { this.currentTime--; this.updateTimerDisplay(); this.updateProgressBar(); if (this.currentTime <= 0) { this.onTimerComplete(); } }, 1000); } updateTimerDisplay() { const minutes = Math.floor(this.currentTime / 60); const seconds = this.currentTime % 60; const display = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; document.getElementById('timerDisplay').textContent = display; } updateProgressBar() { const totalTime = this.restTime * 60; const elapsed = totalTime - this.currentTime; const percentage = (elapsed / totalTime) * 100; document.getElementById('progressFill').style.width = `${percentage}%`; } async onTimerComplete() { clearInterval(this.timer); // 완료 메시지 표시 this.showCompletionMessage(); // 3초 후 자동 닫기 setTimeout(() => { this.closeModal(); }, 3000); } showCompletionMessage() { const modalContainer = document.querySelector('.modal-container'); modalContainer.innerHTML = `
🚀

휴식 완료!

이제 다시 열심히 월매출 1억을 향해 달려가세요!

💪 화이팅! 성공은 바로 앞에 있습니다!
`; } closeModal() { if (this.timer) { clearInterval(this.timer); } // 창 닫기 window.close(); } } // 페이지 로드 시 휴식 모달 초기화 document.addEventListener('DOMContentLoaded', () => { const restModal = new RestModal(); restModal.init(); });