mirror of
https://github.com/sotam0316/brain_dogfood.git
synced 2026-04-24 19:48:35 +09:00
128 lines
4.4 KiB
JavaScript
128 lines
4.4 KiB
JavaScript
/**
|
|
* SessionManager.js
|
|
* - 세션 라이프타임 관리 및 로그아웃 버튼 카운트다운 인터페이스
|
|
* - 사용자 활동(클릭, 키 입력) 시 타이머 초기화
|
|
*/
|
|
import { API } from '../api.js';
|
|
import { I18nManager } from '../utils/I18nManager.js';
|
|
|
|
export const SessionManager = {
|
|
state: {
|
|
timeoutMinutes: 60, // 기본값
|
|
remainingSeconds: 3600,
|
|
timerId: null,
|
|
logoutBtn: null,
|
|
baseText: ''
|
|
},
|
|
|
|
/**
|
|
* 초기화: 설정 로드 및 이벤트 바인딩
|
|
*/
|
|
async init() {
|
|
try {
|
|
const settings = await API.fetchSettings();
|
|
this.state.timeoutMinutes = settings.session_timeout || 60;
|
|
this.resetTimer();
|
|
|
|
this.state.logoutBtn = document.getElementById('logoutBtn');
|
|
if (this.state.logoutBtn) {
|
|
const textSpan = this.state.logoutBtn.querySelector('.text');
|
|
if (textSpan) {
|
|
// i18n 로딩이 늦을 경우를 위해 초기 텍스트 보관
|
|
this.state.baseText = textSpan.textContent.trim().split(' ')[0] || I18nManager.t('nav_logout');
|
|
console.log(`⏱️ SessionManager: Timer target found. Base text: ${this.state.baseText}`);
|
|
this.startCountdown();
|
|
} else {
|
|
console.error('❌ SessionManager: .text span not found in logoutBtn');
|
|
}
|
|
} else {
|
|
console.error('❌ SessionManager: logoutBtn not found');
|
|
}
|
|
|
|
// 사용자 활동 감지 이벤트 바인딩
|
|
this.bindActivityListeners();
|
|
|
|
console.log(`⏱️ SessionManager: Initialized with ${this.state.timeoutMinutes} min timeout.`);
|
|
} catch (err) {
|
|
console.error('❌ SessionManager Init Error:', err);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 타이머 시작 (1초마다 업데이트)
|
|
*/
|
|
startCountdown() {
|
|
if (this.state.timerId) clearInterval(this.state.timerId);
|
|
|
|
this.state.timerId = setInterval(() => {
|
|
this.state.remainingSeconds--;
|
|
|
|
if (this.state.remainingSeconds <= 0) {
|
|
this.handleTimeout();
|
|
} else {
|
|
this.updateUI();
|
|
}
|
|
}, 1000);
|
|
},
|
|
|
|
/**
|
|
* 타이머를 원복함 (활동 감지 시 호출)
|
|
*/
|
|
resetTimer() {
|
|
this.state.remainingSeconds = this.state.timeoutMinutes * 60;
|
|
this.updateUI();
|
|
},
|
|
|
|
/**
|
|
* UI 업데이트 (로그아웃 버튼 텍스트 변경)
|
|
*/
|
|
updateUI() {
|
|
if (!this.state.logoutBtn) return;
|
|
|
|
const minutes = Math.floor(this.state.remainingSeconds / 60);
|
|
const seconds = this.state.remainingSeconds % 60;
|
|
const timeStr = `(${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')})`;
|
|
|
|
const textSpan = this.state.logoutBtn.querySelector('.text');
|
|
if (textSpan) {
|
|
// i18n이 중간에 바뀔 수 있으므로 매번 새로 가져오는 것이 안전할 수 있음
|
|
const currentBase = I18nManager.t('nav_logout');
|
|
textSpan.textContent = `${currentBase} ${timeStr}`;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 활동 감지 리스너 등록
|
|
*/
|
|
bindActivityListeners() {
|
|
const resetAction = () => this.resetTimer();
|
|
|
|
// 클릭 및 키보드 입력 감지
|
|
window.addEventListener('mousedown', resetAction);
|
|
window.addEventListener('keydown', resetAction);
|
|
window.addEventListener('touchstart', resetAction);
|
|
|
|
// 추가적으로 API 요청이 발생할 때도 리셋되면 좋음 (api.js에서 처리 권장)
|
|
},
|
|
|
|
/**
|
|
* 타임아웃 설정을 갱신함 (설정 변경 시 호출 가능)
|
|
*/
|
|
updateTimeout(minutes) {
|
|
if (!minutes || isNaN(minutes)) return;
|
|
this.state.timeoutMinutes = parseInt(minutes);
|
|
this.resetTimer();
|
|
console.log(`⏱️ SessionManager: Timeout updated to ${this.state.timeoutMinutes} min.`);
|
|
},
|
|
|
|
/**
|
|
* 타임아웃 발생 시 처리
|
|
*/
|
|
handleTimeout() {
|
|
clearInterval(this.state.timerId);
|
|
console.warn('⌛ Session expired. Logging out...');
|
|
alert(I18nManager.t('msg_session_expired') || '세션이 만료되었습니다. 다시 로그인해주세요.');
|
|
window.location.href = '/logout';
|
|
}
|
|
};
|