fix: add pagination to WordsView (50 words per page)
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 9s

This commit is contained in:
deploy 2026-05-15 10:46:24 +00:00
parent f8eaaedcab
commit 75036d3d82
2 changed files with 45 additions and 20 deletions

View File

@ -3,7 +3,7 @@ import axios from 'axios'
const api = axios.create({ baseURL: '/api' })
export const wordsApi = {
getAll: (category) => api.get('/words', { params: { category } }),
getAll: (category, page = 1, limit = 50) => api.get('/words', { params: { category, page, limit } }),
getDaily: () => api.get('/words/daily'),
getQuiz: (count = 5) => api.get('/words/quiz', { params: { count } }),
getCategories: () => api.get('/words/categories'),

View File

@ -8,20 +8,30 @@
</button>
</div>
<div v-if="loading" class="loading">불러오는 중...</div>
<div v-else class="card-grid">
<div v-for="word in words" :key="word.id" class="card word-card">
<div style="display:flex;justify-content:space-between;align-items:flex-start">
<div class="word-en">{{ word.english }}</div>
<span class="badge badge-blue">{{ word.difficulty }}</span>
</div>
<div v-if="word.pronunciation" class="word-pron">[{{ word.pronunciation }}]</div>
<div class="word-ko">{{ word.korean }}</div>
<div v-if="word.example_en" class="word-example">
{{ word.example_en }}<br/>
<span style="color:#a0aec0">{{ word.example_ko }}</span>
</div>
<div v-else>
<div style="margin-bottom:1rem;color:#718096;font-size:0.875rem">
전체 {{ total }} 단어 {{ (page - 1) * limit + 1 }}{{ Math.min(page * limit, total) }}번째
</div>
<div class="card-grid">
<div v-for="word in words" :key="word.id" class="card word-card">
<div style="display:flex;justify-content:space-between;align-items:flex-start">
<div class="word-en">{{ word.english }}</div>
<span class="badge badge-blue">{{ word.difficulty }}</span>
</div>
<div v-if="word.pronunciation" class="word-pron">[{{ word.pronunciation }}]</div>
<div class="word-ko">{{ word.korean }}</div>
<div v-if="word.example_en" class="word-example">
{{ word.example_en }}<br/>
<span style="color:#a0aec0">{{ word.example_ko }}</span>
</div>
</div>
<div v-if="!words.length" class="empty">단어가 없습니다</div>
</div>
<div v-if="totalPages > 1" style="display:flex;justify-content:center;align-items:center;gap:0.75rem;margin-top:2rem">
<button class="btn btn-secondary" :disabled="page <= 1" @click="changePage(page - 1)">이전</button>
<span style="color:#4a5568;font-size:0.9rem">{{ page }} / {{ totalPages }}</span>
<button class="btn btn-secondary" :disabled="page >= totalPages" @click="changePage(page + 1)">다음</button>
</div>
<div v-if="!words.length" class="empty">단어가 없습니다</div>
</div>
</div>
</template>
@ -36,18 +46,33 @@ const words = ref([])
const categories = ref([])
const selected = ref('')
const loading = ref(false)
const page = ref(1)
const total = ref(0)
const totalPages = ref(1)
const limit = 50
const select = async (cat) => {
selected.value = cat
const fetchWords = async (cat, p) => {
loading.value = true
const res = await wordsApi.getAll(cat || undefined)
words.value = res.data
const res = await wordsApi.getAll(cat || undefined, p, limit)
words.value = res.data.data
total.value = res.data.total
totalPages.value = res.data.totalPages
page.value = p
loading.value = false
}
const select = async (cat) => {
selected.value = cat
await fetchWords(cat, 1)
}
const changePage = async (p) => {
await fetchWords(selected.value, p)
window.scrollTo({ top: 0, behavior: 'smooth' })
}
onMounted(async () => {
const [w, c] = await Promise.all([wordsApi.getAll(), wordsApi.getCategories()])
words.value = w.data
const [, c] = await Promise.all([fetchWords('', 1), wordsApi.getCategories()])
categories.value = c.data
questApi.complete({ session_id: session.id, type: 'word' })
})