From 8ffa2c969aac98ce1328c04708a88bc6f6109199 Mon Sep 17 00:00:00 2001 From: deploy Date: Mon, 18 May 2026 01:11:47 +0000 Subject: [PATCH] feat: level selector (beginner/intermediate/advanced) + filter daily words by level --- src/api/index.js | 2 +- src/stores/session.js | 7 +++++++ src/views/HomeView.vue | 38 ++++++++++++++++++++++++++++++++++++++ src/views/LearnView.vue | 31 +++++++++++++++++++++++++------ 4 files changed, 71 insertions(+), 7 deletions(-) diff --git a/src/api/index.js b/src/api/index.js index 26f35c8..3194418 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -4,7 +4,7 @@ const api = axios.create({ baseURL: '/api' }) export const wordsApi = { getAll: (category, page = 1, limit = 50) => api.get('/words', { params: { category, page, limit } }), - getDaily: () => api.get('/words/daily'), + getDaily: (difficulty) => api.get('/words/daily', { params: { difficulty } }), getQuiz: (count = 5) => api.get('/words/quiz', { params: { count } }), getCategories: () => api.get('/words/categories'), } diff --git a/src/stores/session.js b/src/stores/session.js index 763791b..8a9ff77 100644 --- a/src/stores/session.js +++ b/src/stores/session.js @@ -7,5 +7,12 @@ export const useSessionStore = defineStore('session', { localStorage.setItem('session_id', id) return id })(), + level: localStorage.getItem('user_level') || 'beginner', }), + actions: { + setLevel(level) { + this.level = level + localStorage.setItem('user_level', level) + }, + }, }) diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 269d8fc..3169187 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -12,6 +12,23 @@ + +
+
📚 내 단어 수준
+
+ +
+
+
@@ -108,6 +125,16 @@ const levelNames = ['입문자','초보자','학습자','중급자','숙련자', const xpPct = computed(() => Math.min(100, Math.round((progress.value.xpProgress / progress.value.xpRange) * 100)) || 0) const earnedBadges = computed(() => (progress.value.allBadges || []).filter(b => b.earned)) +const diffLevels = [ + { value: 'beginner', emoji: '🌱', label: '초급', sub: 'Beginner' }, + { value: 'intermediate', emoji: '📘', label: '중급', sub: 'Intermediate' }, + { value: 'advanced', emoji: '🔥', label: '고급', sub: 'Advanced' }, +] + +const changeLevel = (lvl) => { + session.setLevel(lvl) +} + onMounted(async () => { const [q, s, p] = await Promise.all([ questApi.getToday(session.id), @@ -125,6 +152,17 @@ onMounted(async () => { background: linear-gradient(135deg, #667eea, #764ba2); color: white; border-radius: 12px; padding: 1.2rem 1.5rem; } +.level-btn { + flex: 1; display: flex; flex-direction: column; align-items: center; gap: 0.15rem; + padding: 0.6rem 0.4rem; border-radius: 10px; border: 2px solid #e2e8f0; + background: #f7fafc; cursor: pointer; transition: all 0.18s; + color: #4a5568; +} +.level-btn.active { + border-color: #667eea; background: linear-gradient(135deg,#ebf4ff,#f0ecff); + color: #553c9a; box-shadow: 0 2px 8px rgba(102,126,234,0.2); +} +.level-btn:hover:not(.active) { border-color: #a0aec0; background: #edf2f7; } .quick-card { background: white; border-radius: 12px; padding: 1.2rem; box-shadow: 0 2px 8px rgba(0,0,0,0.06); diff --git a/src/views/LearnView.vue b/src/views/LearnView.vue index b167eec..e59a5b5 100644 --- a/src/views/LearnView.vue +++ b/src/views/LearnView.vue @@ -8,8 +8,13 @@
📖

오늘의 단어 학습

-

오늘의 단어 {{ words.length }}개를 학습합니다

- +
+ + {{ levelMap[session.level]?.emoji }} {{ levelMap[session.level]?.label }} + + 수준 · {{ words.length }}개 +
+
@@ -115,11 +120,17 @@ const xpGained = ref(0) const totalXp = ref(0) const newBadges = ref([]) +const levelMap = { + beginner: { emoji: '🌱', label: '초급' }, + intermediate: { emoji: '📘', label: '중급' }, + advanced: { emoji: '🔥', label: '고급' }, +} + const badgeMap = { first_study: { emoji: '🌱', name: '첫 걸음' }, - words_50: { emoji: '📚', name: '단어 50' }, - words_100: { emoji: '🎓', name: '단어 100' }, - words_500: { emoji: '👑', name: '단어 500' }, + words_50: { emoji: '📚', name: '단어 50' }, + words_100: { emoji: '🎓', name: '단어 100' }, + words_500: { emoji: '👑', name: '단어 500' }, } const diffBadge = (d) => { @@ -131,7 +142,7 @@ const diffBadge = (d) => { let xpTimer = null onMounted(async () => { - const res = await wordsApi.getDaily() + const res = await wordsApi.getDaily(session.level) words.value = res.data loading.value = false }) @@ -176,6 +187,14 @@ const prev = () => {