feat: 체크리스트 이미지 미리보기 기능 구현
- 체크리스트 섹션에 이미지 썸네일 미리보기 추가 (16x16) - 대시보드 상단 체크리스트 카드에 이미지 미리보기 기능 추가 - 이미지 클릭 시 전체 화면 모달로 확대 보기 - 백엔드 image_url 컬럼을 TEXT 타입으로 변경하여 Base64 이미지 지원 - 파일 업로드를 이미지만 지원하도록 단순화 (file_url, file_name 제거) - 422 validation 오류 해결 및 상세 로깅 추가 - 체크리스트 렌더링 누락 문제 해결
This commit is contained in:
@@ -22,6 +22,9 @@ class ApiClient {
|
||||
// 인증 토큰 추가
|
||||
if (this.token) {
|
||||
config.headers['Authorization'] = `Bearer ${this.token}`;
|
||||
console.log('API 요청에 토큰 포함:', this.token.substring(0, 20) + '...');
|
||||
} else {
|
||||
console.warn('API 요청에 토큰이 없습니다!');
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -30,7 +33,14 @@ class ApiClient {
|
||||
if (!response.ok) {
|
||||
if (response.status === 401) {
|
||||
// 토큰 만료 시 로그아웃
|
||||
this.logout();
|
||||
console.error('인증 실패 - 토큰 제거 후 로그인 페이지로 이동');
|
||||
// 토큰만 제거하고 페이지 리로드는 하지 않음
|
||||
localStorage.removeItem('authToken');
|
||||
localStorage.removeItem('currentUser');
|
||||
// 무한 루프 방지: 이미 index.html이 아닌 경우만 리다이렉트
|
||||
if (!window.location.pathname.endsWith('index.html') && window.location.pathname !== '/') {
|
||||
window.location.href = 'index.html';
|
||||
}
|
||||
throw new Error('인증이 만료되었습니다. 다시 로그인해주세요.');
|
||||
}
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
@@ -49,11 +59,15 @@ class ApiClient {
|
||||
|
||||
// GET 요청
|
||||
async get(endpoint) {
|
||||
// 토큰 재로드 (로그인 후 토큰이 업데이트된 경우)
|
||||
this.token = localStorage.getItem('authToken');
|
||||
return this.request(endpoint, { method: 'GET' });
|
||||
}
|
||||
|
||||
// POST 요청
|
||||
async post(endpoint, data) {
|
||||
// 토큰 재로드
|
||||
this.token = localStorage.getItem('authToken');
|
||||
return this.request(endpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data)
|
||||
@@ -62,6 +76,8 @@ class ApiClient {
|
||||
|
||||
// PUT 요청
|
||||
async put(endpoint, data) {
|
||||
// 토큰 재로드
|
||||
this.token = localStorage.getItem('authToken');
|
||||
return this.request(endpoint, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data)
|
||||
@@ -70,11 +86,15 @@ class ApiClient {
|
||||
|
||||
// DELETE 요청
|
||||
async delete(endpoint) {
|
||||
// 토큰 재로드
|
||||
this.token = localStorage.getItem('authToken');
|
||||
return this.request(endpoint, { method: 'DELETE' });
|
||||
}
|
||||
|
||||
// 파일 업로드
|
||||
async uploadFile(endpoint, formData) {
|
||||
// 토큰 재로드
|
||||
this.token = localStorage.getItem('authToken');
|
||||
return this.request(endpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -112,7 +132,9 @@ const AuthAPI = {
|
||||
|
||||
if (response.access_token) {
|
||||
api.setToken(response.access_token);
|
||||
localStorage.setItem('currentUser', JSON.stringify(response.user));
|
||||
// 사용자 정보가 있으면 저장, 없으면 기본값 사용
|
||||
const user = response.user || { username: 'hyungi', full_name: 'Administrator' };
|
||||
localStorage.setItem('currentUser', JSON.stringify(user));
|
||||
}
|
||||
|
||||
return response;
|
||||
@@ -135,21 +157,42 @@ const AuthAPI = {
|
||||
|
||||
// Todo 관련 API
|
||||
const TodoAPI = {
|
||||
async getTodos(filter = 'all') {
|
||||
const params = filter !== 'all' ? `?status=${filter}` : '';
|
||||
return api.get(`/todos${params}`);
|
||||
async getTodos(status = null, category = null) {
|
||||
let url = '/todos/';
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (status && status !== 'all') params.append('status', status);
|
||||
if (category && category !== 'all') params.append('category', category);
|
||||
|
||||
if (params.toString()) {
|
||||
url += '?' + params.toString();
|
||||
}
|
||||
|
||||
return api.get(url);
|
||||
},
|
||||
|
||||
async createTodo(todoData) {
|
||||
return api.post('/todos', todoData);
|
||||
return api.post('/todos/', todoData);
|
||||
},
|
||||
|
||||
async updateTodo(id, todoData) {
|
||||
return api.put(`/todos/${id}`, todoData);
|
||||
return api.put(`/todos/${id}/`, todoData);
|
||||
},
|
||||
|
||||
async deleteTodo(id) {
|
||||
return api.delete(`/todos/${id}`);
|
||||
return api.delete(`/todos/${id}/`);
|
||||
},
|
||||
|
||||
async completeTodo(id) {
|
||||
return api.put(`/todos/${id}/`, { status: 'completed' });
|
||||
},
|
||||
|
||||
async getTodayTodos() {
|
||||
return api.get('/calendar/today/');
|
||||
},
|
||||
|
||||
async getTodoById(id) {
|
||||
return api.get(`/todos/${id}/`);
|
||||
},
|
||||
|
||||
async uploadImage(imageFile) {
|
||||
|
||||
Reference in New Issue
Block a user