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
30 changes: 30 additions & 0 deletions src/api/vocabApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import axios from 'axios'

const vocabApi = axios.create({
baseURL: import.meta.env.VITE_VOCAB_API_URL,
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
})

// Request interceptor
vocabApi.interceptors.request.use(
(config) => {
return config
},
(error) => {
return Promise.reject(error)
}
)

// Response interceptor
vocabApi.interceptors.response.use(
(response) => response.data,
(error) => {
console.error('Vocab API Error:', error.response?.data || error.message)
return Promise.reject(error)
}
)

export default vocabApi
95 changes: 95 additions & 0 deletions src/domains/vocab/constants/vocabConstants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// 학습 레벨
export const LEVELS = {
BEGINNER: 'BEGINNER',
INTERMEDIATE: 'INTERMEDIATE',
ADVANCED: 'ADVANCED',
}

export const LEVEL_LABELS = {
[LEVELS.BEGINNER]: '초급',
[LEVELS.INTERMEDIATE]: '중급',
[LEVELS.ADVANCED]: '고급',
}

export const LEVEL_COLORS = {
[LEVELS.BEGINNER]: 'success',
[LEVELS.INTERMEDIATE]: 'warning',
[LEVELS.ADVANCED]: 'error',
}

// 카테고리
export const CATEGORIES = {
DAILY: 'DAILY',
BUSINESS: 'BUSINESS',
ACADEMIC: 'ACADEMIC',
}

export const CATEGORY_LABELS = {
[CATEGORIES.DAILY]: '일상',
[CATEGORIES.BUSINESS]: '비즈니스',
[CATEGORIES.ACADEMIC]: '학술',
}

// 학습 상태
export const WORD_STATUS = {
NEW: 'NEW',
LEARNING: 'LEARNING',
REVIEWING: 'REVIEWING',
MASTERED: 'MASTERED',
}

export const WORD_STATUS_LABELS = {
[WORD_STATUS.NEW]: '새 단어',
[WORD_STATUS.LEARNING]: '학습 중',
[WORD_STATUS.REVIEWING]: '복습 중',
[WORD_STATUS.MASTERED]: '암기 완료',
}

export const WORD_STATUS_COLORS = {
[WORD_STATUS.NEW]: 'default',
[WORD_STATUS.LEARNING]: 'warning',
[WORD_STATUS.REVIEWING]: 'info',
[WORD_STATUS.MASTERED]: 'success',
}

// 난이도
export const DIFFICULTY = {
EASY: 'EASY',
NORMAL: 'NORMAL',
HARD: 'HARD',
}

export const DIFFICULTY_LABELS = {
[DIFFICULTY.EASY]: '쉬움',
[DIFFICULTY.NORMAL]: '보통',
[DIFFICULTY.HARD]: '어려움',
}

// 시험 유형
export const TEST_TYPES = {
KOREAN_TO_ENGLISH: 'KOREAN_TO_ENGLISH',
ENGLISH_TO_KOREAN: 'ENGLISH_TO_KOREAN',
}

export const TEST_TYPE_LABELS = {
[TEST_TYPES.KOREAN_TO_ENGLISH]: '한국어 → 영어',
[TEST_TYPES.ENGLISH_TO_KOREAN]: '영어 → 한국어',
}

// TTS 음성
export const VOICE_TYPES = {
MALE: 'MALE',
FEMALE: 'FEMALE',
}

export const VOICE_LABELS = {
[VOICE_TYPES.MALE]: '남성',
[VOICE_TYPES.FEMALE]: '여성',
}

// 일일 학습 목표
export const DAILY_GOAL = {
NEW_WORDS: 50,
REVIEW_WORDS: 5,
TOTAL: 55,
}
5 changes: 5 additions & 0 deletions src/domains/vocab/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Services
export * from './services/vocabService'

// Constants
export * from './constants/vocabConstants'
91 changes: 91 additions & 0 deletions src/domains/vocab/services/vocabService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import vocabApi from '../../../api/vocabApi'

/**
* 단어 관리 API (#65)
*/
export const wordService = {
// 단어 목록 조회
getList: ({ level, category, limit = 20, cursor } = {}) =>
vocabApi.get('/vocab/words', { params: { level, category, limit, cursor } }),

// 단어 검색
search: ({ q, limit = 20, cursor } = {}) =>
vocabApi.get('/vocab/words/search', { params: { q, limit, cursor } }),

// 단어 상세 조회
getDetail: (wordId) =>
vocabApi.get(`/vocab/words/${wordId}`),
}

/**
* 일일 학습 API (#66)
*/
export const dailyService = {
// 오늘의 학습 단어 조회
getWords: (userId) =>
vocabApi.get(`/vocab/daily/${userId}`),

// 단어 학습 완료 표시
markLearned: (userId, wordId, isCorrect) =>
vocabApi.post(`/vocab/daily/${userId}/words/${wordId}/learned`, { isCorrect }),
}

/**
* 사용자 단어 학습 상태 API (#67)
*/
export const userWordService = {
// 학습 상태 조회
getList: (userId, { status, limit = 20, cursor } = {}) =>
vocabApi.get(`/vocab/users/${userId}/words`, { params: { status, limit, cursor } }),

// 학습 결과 업데이트 (정답/오답)
update: (userId, wordId, isCorrect) =>
vocabApi.put(`/vocab/users/${userId}/words/${wordId}`, { isCorrect }),

// 단어 태그 변경 (북마크/즐겨찾기/난이도)
updateTag: (userId, wordId, { bookmarked, favorite, difficulty }) =>
vocabApi.put(`/vocab/users/${userId}/words/${wordId}/tag`, { bookmarked, favorite, difficulty }),
}

/**
* 시험 API (#68)
*/
export const testService = {
// 시험 시작
start: (userId, { wordCount = 20, level, type = 'ENGLISH_TO_KOREAN' } = {}) =>
vocabApi.post(`/vocab/test/${userId}/start`, { wordCount, level, type }),

// 답안 제출
submit: (userId, testId, answers) =>
vocabApi.post(`/vocab/test/${userId}/submit`, { testId, answers }),

// 시험 결과 조회
getResults: (userId, { limit = 20, cursor } = {}) =>
vocabApi.get(`/vocab/test/${userId}/results`, { params: { limit, cursor } }),
}

/**
* 통계 API (#69)
*/
export const statsService = {
// 전체 학습 통계
getOverall: (userId) =>
vocabApi.get(`/vocab/stats/${userId}`),

// 일별 학습 통계
getDaily: (userId, { limit = 30 } = {}) =>
vocabApi.get(`/vocab/stats/${userId}/daily`, { params: { limit } }),

// 약점 분석
getWeakness: (userId) =>
vocabApi.get(`/vocab/stats/${userId}/weakness`),
}

/**
* 음성 API (TTS) (#70)
*/
export const voiceService = {
// 단어 발음 합성
synthesize: (wordId, text, voice = 'FEMALE') =>
vocabApi.post('/vocab/voice/synthesize', { wordId, text, voice }),
}