149 lines
4.1 KiB
Vue
149 lines
4.1 KiB
Vue
<template>
|
|
<div class="container-xxl flex-grow-1 container-p-y">
|
|
|
|
<div class="card">
|
|
<!-- 타이틀, 검색 -->
|
|
<div class="row mt-4">
|
|
<div class="col-6">
|
|
<h5 class="mb-0">용어집</h5>
|
|
</div>
|
|
<div class="col-6">
|
|
<SearchBar @update:data="search"/>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 단어 갯수, 작성하기 -->
|
|
<div class="mt-4">
|
|
단어 : {{ filteredList.length }}
|
|
<WriteButton @click="toggleWriteForm" />
|
|
</div>
|
|
|
|
<!-- ㄱ ㄴ ㄷ ㄹ -->
|
|
<div>
|
|
<DictAlphabetFilter/>
|
|
</div>
|
|
|
|
<!-- 카테고리 -->
|
|
<div v-if="cateList.length" class="mt-5">
|
|
<CategoryBtn :lists="cateList" />
|
|
</div>
|
|
|
|
<!-- 작성 -->
|
|
<div v-if="isWriteVisible" class="mt-5">
|
|
<DictWrite @close="isWriteVisible = false" />
|
|
</div>
|
|
|
|
<!-- 용어 리스트 -->
|
|
<div class="mt-10">
|
|
<!-- 로딩 중일 때 -->
|
|
<div v-if="loading">로딩 중...</div>
|
|
|
|
<!-- 에러 메시지 -->
|
|
<div v-if="error" class="error">{{ error }}</div>
|
|
|
|
<!-- 단어 목록 -->
|
|
<ul v-if="filteredList.length" class="px-0 list-unstyled">
|
|
<DictCard
|
|
v-for="item in filteredList"
|
|
:key="item.WRDDICSEQ"
|
|
:item="item"
|
|
/>
|
|
</ul>
|
|
|
|
<!-- 데이터가 없을 때 -->
|
|
<div v-else-if="!loading && !error">용어집의 용어가 없습니다.</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, watchEffect, computed } from 'vue';
|
|
import axios from '@api';
|
|
import SearchBar from '@c/search/SearchBar.vue';
|
|
import WriteButton from '@c/button/WriteBtn.vue';
|
|
import CategoryBtn from '@/components/category/CategoryBtn.vue';
|
|
import DictCard from '@/components/wordDict/DictCard.vue';
|
|
import DictWrite from '@/components/wordDict/DictWrite.vue';
|
|
import DictAlphabetFilter from '@/components/wordDict/DictAlphabetFilter.vue';
|
|
|
|
|
|
// 공통
|
|
const loading = ref(false);
|
|
const error = ref('');
|
|
|
|
// 용어집
|
|
const wordList = ref([]);
|
|
// 카테고리
|
|
const cateList = ref([]);
|
|
|
|
// 검색
|
|
const searchText = ref('');
|
|
|
|
// 작성
|
|
const isWriteVisible = ref(false);
|
|
|
|
// 용어집 및 카테고리 목록 통합 API 호출
|
|
const fetchAllData = async () => {
|
|
loading.value = true;
|
|
error.value = '';
|
|
try {
|
|
// 용어집
|
|
const wordResponse = await axios.get('worddict/getWordList');
|
|
wordList.value = wordResponse.data.data.data;
|
|
console.log('용어집 데이터:', wordList.value);
|
|
// 카테고리
|
|
const categoryResponse = await axios.get('worddict/getWordCategory');
|
|
cateList.value = categoryResponse.data.data;
|
|
console.log('카테고리 데이터:', cateList.value);
|
|
} catch (err) {
|
|
error.value = '데이터를 가져오는 중 문제가 발생했습니다.';
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
// 검색
|
|
const search = (e) => {
|
|
const trimmedSearchText = e.trim();
|
|
if (trimmedSearchText.length === 0) {
|
|
alert('검색어를 입력해주세요.');
|
|
return;
|
|
}
|
|
searchText.value = trimmedSearchText;
|
|
};
|
|
|
|
// 검색
|
|
const filteredList = computed(() =>
|
|
wordList.value.filter(item =>
|
|
item.WRDDICTTL.toLowerCase().includes(searchText.value.toLowerCase())
|
|
)
|
|
);
|
|
|
|
// 작성 toggle
|
|
const toggleWriteForm = () => {
|
|
isWriteVisible.value = !isWriteVisible.value;
|
|
};
|
|
|
|
// `watchEffect`로 API 호출
|
|
watchEffect(() => {
|
|
fetchAllData();
|
|
});
|
|
|
|
</script>
|
|
|
|
<style scoped>
|
|
|
|
.card > div {
|
|
padding: 0 30px
|
|
}
|
|
|
|
.error {
|
|
color: red;
|
|
font-weight: bold;
|
|
}
|
|
</style>
|