jichoi / lms_front star
PsHooN7979 2024-08-09
Merge branch 'master' of http://210.180.118.83/jichoi/lms_front
@a0d7c101221dd4aa7a016ed9ec1709308a5cead3
client/views/pages/AppRouter.js
--- client/views/pages/AppRouter.js
+++ client/views/pages/AppRouter.js
@@ -211,6 +211,8 @@
             { path: '/C_ExamInsert.page', name: 'C_ExamInsert', component: C_ExamInsert },
             
             { path: '/RoadMap.page', name: 'RoadMap', component: RoadMap },
+            
+            { path: '/TextDetail.page', name: 'TextDetail', component: TextDetail },
         ],
     },
 ];
client/views/pages/teacher/TextDetail.vue
--- client/views/pages/teacher/TextDetail.vue
+++ client/views/pages/teacher/TextDetail.vue
@@ -1,64 +1,229 @@
 <template>
     <div class="title-box flex justify-between mb40">
-        <p class="title">지문 등록</p>
+        <p class="title">지문 상세 보기</p>
     </div>
-        <div class="board-wrap">
-            <div class="flex align-center mb20">
-                <label for="" class="title2">제목</label>
-                <input type="text" class="data-wrap">
-            </div>
-            <div class="flex align-center">
-                <label for="" class="title2">URL</label>
-                <input type="text" class="data-wrap">
-            </div>
-            <hr>
-            <div class="flex align-center">
-                <label for="" class="title2">스크립트</label>
-                <textarea name="" id="" class="data-wrap"></textarea>
-            </div>
+    <div class="board-wrap">
+        <div class="flex align-center mb20">
+            <label for="" class="title2">제목</label>
+            <input v-if="isEditing" type="text" v-model="post.textTtl" class=" data-wrap">
+            <p class="data-wrap" v-else>{{ post.textTtl }}</p>
         </div>
-        <div class="flex justify-between mt50">
-                <button type="button" title="글쓰기" class="new-btn"  @click="goToPage('TextList')">
-                    목록
-                </button>
-               <div class="flex">
-                    <button type="button" title="글쓰기" class="new-btn mr10"  >
-                        수정
-                    </button>
-                    <button type="button" title="글쓰기" class="new-btn"  >
-                        삭제
-                    </button>
-               </div>
+        <div class="flex align-center mb20">
+            <label for="" class="title2">URL</label>
+            <input v-if="isEditing" type="text" v-model="post.textUrl" class="data-wrap">
+            <p v-else class="data-wrap">{{ post.textUrl }}</p>
         </div>
+        <div class="flex align-center mb20" style="display: flex; flex-direction: row;">
+            <label class="title2">형식</label>
+            <label class="title2">
+                <input type="radio" v-model="post.textTypeId" value="1" class="data-wrap" :disabled="!isEditing"> 일반
+            </label>
+            <label class="title2">
+                <input type="radio" v-model="post.textTypeId" value="2" class="data-wrap" :disabled="!isEditing"> 대화
+            </label>
+            <label class="title2">
+                <input type="radio" v-model="post.textTypeId" value="3" class="data-wrap" :disabled="!isEditing"> 책 리스닝
+            </label>
+            <select v-if="isEditing" id="" v-model="post.bookId" @change="fetchUnits" class="ml20">
+                <option value="" disabled>교재를 선택하세요</option>
+                <option v-for="book in books" :key="book.book_id" :value="book.book_id">
+                    {{ book.book_nm }}
+                </option>
+            </select>
+            <label v-else for="" class="title2 flex align-center ml20" style="display: flex; width: 20rem;">교재:&nbsp;
+                <p class="title2">{{ post.bookName }}</p>
+            </label>
+                <select v-if="isEditing" name="" id="" v-model="post.unitId" class="ml20">
+                    <option value="" disabled>단원을 선택하세요</option>
+                    <option v-for="unit in units" :key="unit.unitId" :value="unit.unitId">
+                        {{ unit.unitName }}
+                    </option>
+                </select>
+            <label v-else  for="" class="title2 flex align-center ml20"
+                style="display: flex; width: 20rem; text-align: right;">단원:&nbsp;
+                <p class="title2">{{ post.unitName }}</p>
+            </label>
+        </div>
+        <hr>
+        <div class="flex align-center">
+            <label for="" class="title2">스크립트</label>
+            <textarea v-if="isEditing" v-model="post.textCnt" class="data-wrap"></textarea>
+            <p v-else class="data-wrap">{{ post.textCnt }}</p>
+        </div>
+    </div>
+    <div class="flex justify-between mt50">
+        <button type="button" title="목록으로" class="new-btn" @click="goToPage('TextList')">
+            목록
+        </button>
+        <div class="flex">
+            <button type="button" title="수정" class="new-btn mr10" @click="toggleEdit">
+                {{ isEditing ? '저장' : '수정' }}
+            </button>
+            <button type="button" title="삭제" class="new-btn" @click="deletePost">
+                삭제
+            </button>
+        </div>
+    </div>
 </template>
 
 <script>
+import axios from "axios";
 import SvgIcon from '@jamescoyle/vue-icon';
-import { mdiMagnify} from '@mdi/js';
-
+import { mdiMagnify } from '@mdi/js';
 
 export default {
-    data () {
+    data() {
         return {
             mdiMagnify: mdiMagnify,
+            post: {
+                textId: "",
+                textTtl: "",
+                textCnt: "",
+                textUrl: "",
+                textTypeId: "",
+                bookId: "",
+                unitId: "",
+                bookName: "",  
+                unitName: ""
+            },
+            books: [],  
+            units: [], 
+            isEditing: false
+        };
+    },
+    computed: {
+        textId() {
+            return this.$route.query.textId;
+        },
+        selectedBookName() {
+            const book = this.books.find(book => book.book_id === this.post.bookId);
+            return book ? book.book_nm : '';
+        },
+        selectedUnitName() {
+            const unit = this.units.find(unit => unit.unit_id === this.post.unitId);
+            return unit ? unit.unit_nm : '';
         }
     },
     methods: {
         goToPage(page) {
-         this.$router.push({ name: page });
-      },
-    },
-    watch: {
+            this.$router.push({ name: page });
+        },
+        fetchPostDetail() {
+            const textId = this.$route.query.textId;
+            axios.post('/text/selectOneText.json', { textId }, {
+                headers: {
+                    "Content-Type": "application/json; charset=UTF-8",
+                }
+            })
+                .then(response => {
+                    if (response.data && response.data[0]) {
+                        this.post.textId = response.data[0].text_id;
+                        this.post.textTtl = response.data[0].text_ttl;
+                        this.post.textCnt = response.data[0].text_cnt;
+                        this.post.textUrl = response.data[0].text_url;
+                        this.post.textTypeId = response.data[0].text_type_id;
+                        this.post.bookId = response.data[0].book_id;
+                        this.post.unitId = response.data[0].unit_id;
+                        this.post.bookName = response.data[0].book_name;
+                        this.post.unitName = response.data[0].unit_name;
+                    } else {
+                        this.error = "Failed to fetch post details.";
+                    }
+                })
+                .catch(error => {
+                    console.error("Error fetching post detail:", error);
+                    this.error = "Failed to fetch post details.";
+                });
+        },
+        dataInsert() {
+            this.newPost = {
+                textId: this.post.textId,
+                textTtl: this.post.textTtl,
+                textCnt: this.post.textCnt,
+                textUrl: this.post.textUrl,
+                textTypeId: this.post.textTypeId,
+                bookId: this.post.bookId,
+                unitId: this.post.unitId
+            };
+            console.log(this.newPost)
 
-    },
-    computed: {
-       
-    },
-    components:{
-        SvgIcon
+            axios.post("/text/textUpdate.json", this.newPost, {
+                headers: {
+                    "Content-Type": "application/json; charset=UTF-8",
+                }
+            })
+                .then(response => {
+                    alert(response.data.message);
+                    this.fetchPostDetail();
+                })
+                .catch(error => {
+                    console.log("dataInsert - error:", error.response.data);
+                    alert("게시글 등록에 오류가 발생했습니다.");
+                });
+        },
+        toggleEdit() {
+            if (this.isEditing) {
+                this.dataInsert();
+                this.isEditing = false;
+            } else {
+                this.isEditing = true;
+                this.fetchBooks();
+            }
+        },
+        deletePost() {
+            axios.post("/text/textDelete.json", { textId: this.textId }, {
+                headers: {
+                    "Content-Type": "application/json; charset=UTF-8",
+                }
+            })
+                .then(response => {
+                    alert(response.data.message);
+                    this.goToPage('TextList');
+                })
+                .catch(error => {
+                    console.error("Error deleting post:", error);
+                    alert("게시글 삭제에 오류가 발생했습니다.");
+                });
+        },
+        fetchBooks() {
+            axios.post("/book/findAll.json", {}, {
+                headers: {
+                    "Content-Type": "application/json; charset=UTF-8",
+                }
+            })
+                .then(response => {
+                    this.books = response.data;  
+                })
+                .catch(error => {
+                    console.error("fetchBooks - error:", error);
+                    alert("교재 목록을 불러오는 중 오류가 발생했습니다.");
+                });
+        },
+        fetchUnits() {
+            if (!this.post.bookId) return;  
+
+            axios.post("/unit/unitList.json", { bookId: this.post.bookId }, {
+                headers: {
+                    "Content-Type": "application/json; charset=UTF-8",
+                }
+            })
+                .then(response => {
+                    this.units = response.data;  
+                })
+                .catch(error => {
+                    console.error("fetchUnits - error:", error);
+                    alert("단원 목록을 불러오는 중 오류가 발생했습니다.");
+                });
+        }
     },
     mounted() {
-        console.log('Main2 mounted');
+        this.fetchPostDetail();
+    },
+    components: {
+        SvgIcon
     }
-}
-</script>
(No newline at end of file)
+};
+</script>
+
+<style scoped> 
+</style>
client/views/pages/teacher/TextInsert.vue
--- client/views/pages/teacher/TextInsert.vue
+++ client/views/pages/teacher/TextInsert.vue
@@ -1,63 +1,221 @@
+
 <template>
     <div class="title-box flex justify-between mb40">
         <p class="title">지문 등록</p>
     </div>
-        <div class="board-wrap">
-            <div class="flex align-center mb20">
-                <label for="" class="title2">제목</label>
-                <input type="text" class="data-wrap">
-            </div>
-            <div class="flex align-center">
-                <label for="" class="title2">URL</label>
-                <input type="text" class="data-wrap">
-            </div>
-            <hr>
-            <div class="flex align-center">
-                <label for="" class="title2">스크립트</label>
-                <textarea name="" id="" class="data-wrap"></textarea>
-            </div>
+    <div class="board-wrap">
+        <div class="flex align-center mb20">
+            <label for="" class="title2">제목</label>
+            <input type="text" class="data-wrap" v-model="newData.textTtl">
         </div>
-        <div class="flex justify-between mt50">
-                <button type="button" title="글쓰기" class="new-btn"  @click="goToPage('TextList')">
-                    목록
-                </button>
-               <div class="flex">
-                    <button type="button" title="글쓰기" class="new-btn mr10"  >
-                        취소
-                    </button>
-                    <button type="button" title="글쓰기" class="new-btn"  >
-                        등록
-                    </button>
-               </div>
+        <div class="flex align-center mb20">
+            <label for="" class="title2">URL</label>
+            <input type="text" class="data-wrap" v-model="newData.textUrl">
         </div>
+        <div class="flex align-center">
+            <label class="title2">형식</label>
+            <label class="title2">
+                <input type="radio" v-model="newData.textTypeId" value="1" class="data-wrap"> 일반
+            </label>
+            <label class="title2">
+                <input type="radio" v-model="newData.textTypeId" value="2" class="data-wrap"> 대화
+            </label>
+            <label class="title2">
+                <input type="radio" v-model="newData.textTypeId" value="3" class="data-wrap"> 책 리스닝
+            </label>
+            <select name="" id="" v-model="newData.bookId" @change="fetchUnits" class="ml20">
+                <option value="" disabled>교재를 선택하세요</option>
+                <option v-for="book in books" :key="book.book_id" :value="book.book_id">
+                    {{ book.book_nm }}
+                </option>
+            </select>
+            <select name="" id="" v-model="newData.unitId" class="ml20">
+                <option value="" disabled>단원을 선택하세요</option>
+                <option v-for="unit in units" :key="unit.unitId" :value="unit.unitId">
+                    {{ unit.unitName }}
+                </option>
+            </select>
+        </div>
+        <hr>
+        <div class="flex align-center">
+            <label for="" class="title2">스크립트</label>
+            <textarea name="" id="" class="data-wrap" v-model="newData.textCnt"></textarea>
+        </div>
+    </div>
+    <div class="flex justify-between mt50">
+        <button type="button" title="글쓰기" class="new-btn" @click="goToPage('TextList')">
+            목록
+        </button>
+        <div class="flex">
+            <button type="button" title="글쓰기" class="new-btn mr10" @click="handleButtonAction">
+                작성
+            </button>
+        </div>
+    </div>
 </template>
 
 <script>
+import axios from "axios";
 import SvgIcon from '@jamescoyle/vue-icon';
-import { mdiMagnify} from '@mdi/js';
+import { mdiMagnify } from '@mdi/js';
 
 
 export default {
-    data () {
+    computed: {
+        textId() {
+            return this.$route.query.textId;
+        }
+    },
+    data() {
         return {
             mdiMagnify: mdiMagnify,
+            post: null,
+            newData: {
+                textId: "",
+                textTtl: "",
+                textCnt: "",
+                textUrl: "",
+                textTypeId: "",
+                //fileMngId:"",
+                // userId:"".
+                bookId: "",
+                unitId: ""
+            },
+            books: [],  
+            units: [],  
         }
     },
     methods: {
         goToPage(page) {
-         this.$router.push({ name: page });
-      },
+            this.$router.push({ name: page });
+        }, fetchPostDetail() {
+            const textId = this.$route.query.textId
+            axios({
+                url: `/text/selectOneText.json`,
+                method: "post",
+                headers: {
+                    "Content-Type": "application/json; charset=UTF-8",
+                },
+                data: { "textId": textId }
+            })
+                .then(response => {
+                    if (response.data && response.data[0]) {
+                        this.post = response.data[0];
+                        this.editTitle = this.post.title;
+                        this.editContent = this.post.content;
+                        console.log(this.post);
+                    } else {
+                        this.error = "Failed to fetch post details.";
+                    }
+                })
+                .catch(error => {
+                    console.error("Error fetching post detail:", error);
+                    this.error = "Failed to fetch post details.";
+                });
+        }, dataInsert() {
+            const vm = this;
+            axios({
+                url: "/text/insertText.json",
+                method: "post",
+                headers: {
+                    "Content-Type": "application/json; charset=UTF-8",
+                },
+                data: vm.newData,
+            })
+                .then(response => {
+                    alert(response.data.message);
+                    this.goToPage('TextList')
+                })
+                .catch(error => {
+                    console.log("dataInsert - error : ", error.response.data);
+                    alert("게시글 등록에 오류가 발생했습니다.");
+                });
+        },
+        handleButtonAction() {
+            if (!this.newData.textTtl) {
+                alert("제목을 입력해 주세요.");
+                return;
+            }
+
+            if (!this.newData.textUrl) {
+                alert("url을 입력해 주세요.");
+                return;
+            }
+
+            if (!this.newData.textTypeId) {
+                alert("지문 형식을 입력해 주세요.");
+                return;
+            }
+
+            if (!this.newData.bookId) {
+                alert("교재를 선택해 주세요.");
+                return;
+            }
+
+            if (!this.newData.unitId) {
+                alert("단원을 선택해 주세요.");
+                return;
+            }
+
+            if (!this.newData.textCnt) {
+                alert("내용을 입력해 주세요.");
+                return;
+            }
+
+            this.dataInsert();
+        },
+        fetchBooks() {
+            axios({
+                url: "/book/findAll.json",
+                method: "post",
+                headers: {
+                    "Content-Type": "application/json; charset=UTF-8",
+                },
+            })
+                .then(response => {
+                    console.log(response.data)
+                    this.books = response.data;  
+                })
+                .catch(error => {
+                    console.error("fetchBooks - error: ", error);
+                    alert("교재 목록을 불러오는 중 오류가 발생했습니다.");
+                });
+        },
+        fetchUnits() {
+            if (!this.newData.bookId) return;  
+
+            axios({
+                url: "/unit/unitList.json",
+                method: "post",
+                headers: {
+                    "Content-Type": "application/json; charset=UTF-8",
+                },
+                data: {
+                    "bookId": this.newData.bookId
+                },
+            })
+                .then(response => {
+                    console.log(response.data)
+                    this.units = response.data;  
+                })
+                .catch(error => {
+                    console.error("fetchUnits - error: ", error);
+                    alert("단원 목록을 불러오는 중 오류가 발생했습니다.");
+                });
+        },
     },
     watch: {
 
     },
     computed: {
-       
+
     },
-    components:{
+    components: {
         SvgIcon
     },
     mounted() {
+        this.fetchPostDetail();
+        this.fetchBooks();  
         console.log('Main2 mounted');
     }
 }
client/views/pages/teacher/TextList.vue
--- client/views/pages/teacher/TextList.vue
+++ client/views/pages/teacher/TextList.vue
@@ -1,75 +1,109 @@
 <template>
     <div class="title-box flex justify-between mb40 myplan">
         <p class="title">지문</p>
-        <select name="" id="">
-            <option value="">A 교재</option>
+        <select name="" id="" v-model="selectedBook" @change="fetchUnits">
+            <option value="" disabled>교재를 선택하세요</option>
+            <option v-for="book in books" :key="book.book_id" :value="book.book_id">
+                {{ book.book_nm }}
+            </option>
         </select>
     </div>
-        <label for="" class="title2">단원</label>
-        <div class="unit-pagination flex mt10 mb20" style="gap: 10px;">
-            <button class="selected-btn">1</button>
-            <button>2</button>
-            <button>3</button>
-        </div>
+    <label for="" class="title2">단원</label>
+    <div class="unit-pagination flex mt10 mb20" style="gap: 10px;">
+        <button 
+            v-for="(unit, index) in units" 
+            :key="index" 
+            :class="{ 'selected-btn': selectedUnit === unit.unitId }"
+            @click="selectUnit(unit.unitId)">
+            {{ unit.unitName }}
+        </button>
+    </div>
     <div class="search-wrap flex justify-end mb20">
-            <select name="" id="" class="mr10 data-wrap">
-                <option value="">전체</option>
-            </select>
-                <input  type="text" placeholder="검색하세요.">
-                <button type="button" title="위원회 검색">
-                    <img src="../../../resources/img/look_t.png" alt="">
-                </button>
-        </div>
-        <div class="table-wrap">
-            <table>
-                <thead>
+        <select name="" id="" class="mr10 data-wrap" style="width: 15rem;" v-model="option">
+            <option value="" disabled>검색유형</option>
+            <option v-for="g in optionList" :key="g.value" :value="g.value">{{ g.text }}</option>
+        </select>
+        <input type="text" placeholder="검색하세요." v-model="keyword">
+        <button type="button" title="위원회 검색" @click="search">
+            <img src="../../../resources/img/look_t.png" alt="">
+        </button>
+    </div>
+    <div class="table-wrap">
+        <table>
+            <thead>
+                <tr>
                     <td>No.</td>
                     <td>제목</td>
                     <td>내용</td>
                     <td>작성자</td>
                     <td>등록일</td>
-                </thead>
-                <tbody>
-                    <tr @click="goToPage('TextDetail')">
-                        <td></td>
-                        <td></td>
-                        <td></td>
-                        <td></td>
-                        <td></td>
-                    </tr>
-                </tbody>
-            </table>
-            <article class="table-pagination flex justify-center align-center mb20 mt30" style="gap: 10px;">
-                    <button><img src="../../../resources/img/btn27_90t_normal.png" alt=""></button>
-                    <button class="selected-btn">1</button>
-                    <button>2</button>
-                    <button>3</button>
-                    <button><img src="../../../resources/img/btn28_90t_normal.png" alt=""></button>
-                </article>
-                <div class="flex justify-end ">
-                <button type="button" title="등록" class="new-btn" @click="goToPage('TextInsert')">
-                    등록
-                </button>
+                </tr>
+            </thead>
+            <tbody>
+                <tr v-for="(post, index) in posts" :key="index" class="post"
+                    @click="goToPage('TextDetail', post.textId)">
+                    <td>{{ index + 1 + (currentPage - 1) * pageSize }}</td>
+                    <td>{{ post.textTtl.slice(0, 20) }}{{ post.textTtl.length > 20 ? '...' : '' }}</td>
+                    <td>{{ post.textCnt.slice(0, 20) }}{{ post.textCnt.length > 20 ? '...' : '' }}</td>
+                    <td>{{ post.userId }}</td>
+                    <td>{{ post.regDt }}</td>
+                </tr>
+            </tbody>
+        </table>
+        <article class="table-pagination flex justify-center align-center mb20 mt30" style="gap: 10px;">
+            <button @click="changePage(currentPage - 1)" :disabled="currentPage === 1">
+                <img src="../../../resources/img/btn27_90t_normal.png" alt="Previous">
+            </button>
+            <button v-for="page in totalPages" :key="page" @click="changePage(page)"
+                :class="{ 'selected-btn': currentPage === page }">
+                {{ page }}
+            </button>
+            <button @click="changePage(currentPage + 1)" :disabled="currentPage === totalPages">
+                <img src="../../../resources/img/btn28_90t_normal.png" alt="Next">
+            </button>
+        </article>
+        <div class="flex justify-end">
+            <button type="button" title="등록" class="new-btn" @click="goToPage('TextInsert')">
+                등록
+            </button>
         </div>
-        </div>
+    </div>
 </template>
 
 <script>
+import axios from "axios";
 import SvgIcon from '@jamescoyle/vue-icon';
-import { mdiMagnify} from '@mdi/js';
-
+import { mdiMagnify } from '@mdi/js';
 
 export default {
-    data () {
+    data() {
         return {
             mdiMagnify: mdiMagnify,
-        }
+            posts: [],
+            currentPage: 1,
+            pageSize: 10,
+            totalPosts: 0,
+            option: "",
+            keyword: "",
+            books: [], 
+            selectedBook: "", 
+            optionList: [
+                { text: "번호", value: "textId" },
+                { text: "제목", value: "textTtl" },
+                { text: "내용", value: "textCnt" },
+                { text: "작성자", value: "userId" },
+                { text: "등록일", value: "regDt" },
+            ],
+            units: [], 
+            selectedUnit: null, 
+            searching: false,
+        };
     },
     methods: {
-        goToPage(page) {
-         this.$router.push({ name: page });
-      },
-      showConfirm(type) {
+        goToPage(page, textId) {
+            this.$router.push({ name: page, query: { textId } });
+        },
+        showConfirm(type) {
             let message = '';
             if (type === 'cancel') {
                 message = '삭제하시겠습니까?';
@@ -83,19 +117,110 @@
                 this.goBack();
             }
         },
+        selectUnit(unitId) {
+            this.selectedUnit = unitId;
+            this.fetchData();  
+        },
+        search() {
+            if (!this.option) {
+                alert("검색유형을 선택해 주세요")
+            } else {
+                this.currentPage = 1; 
+                this.searching = true;
+                this.fetchData();  
+            }
+        },
+        fetchData() {
+            const idx = (this.currentPage - 1) * this.pageSize;
+            axios({
+                url: "/text/textSearch.json",
+                method: "post",
+                headers: {
+                    "Content-Type": "application/json; charset=UTF-8",
+                },
+                data: {
+                    "option": this.option,
+                    "keyword": this.keyword,
+                    "pageSize": this.pageSize,
+                    "startIndex": idx,
+                    "unitId": this.selectedUnit  
+                },
+            })
+                .then(response => {
+                    this.posts = response.data.list;
+                    if (!this.searching || this.keyword === "") {
+                        this.totalPosts = response.data.totalText;
+                    } else if (this.searching) {
+                        this.totalPosts = response.data.resultCount;
+                    }
+                    this.posts.forEach(post => {
+                        let regDt = post.regDt;
+                        let date = new Date(regDt);
+                        post.regDt = date.toISOString().split('T')[0];
+                    });
+                })
+                .catch(error => {
+                    console.error("fetchData - error: ", error);
+                    alert("검색 중 오류가 발생했습니다.");
+                });
+        },
+        changePage(page) {
+            if (page > 0 && page <= this.totalPages) {
+                this.currentPage = page;
+                this.fetchData();
+            }
+        },
+        fetchBooks() {
+            axios({
+                url: "/book/findAll.json",
+                method: "post",
+                headers: {
+                    "Content-Type": "application/json; charset=UTF-8",
+                },
+            })
+                .then(response => {
+                    console.log(response.data)
+                    this.books = response.data;  
+                })
+                .catch(error => {
+                    console.error("fetchBooks - error: ", error);
+                    alert("교재 목록을 불러오는 중 오류가 발생했습니다.");
+                });
+        },
+        fetchUnits() {
+            if (!this.selectedBook) return; 
 
-    },
-    watch: {
-
+            axios({
+                url: "/unit/unitList.json",
+                method: "post",
+                headers: {
+                    "Content-Type": "application/json; charset=UTF-8",
+                },
+                data: {
+                    "bookId": this.selectedBook
+                },
+            })
+                .then(response => {
+                    console.log(response.data)
+                    this.units = response.data; 
+                })
+                .catch(error => {
+                    console.error("fetchUnits - error: ", error);
+                    alert("단원 목록을 불러오는 중 오류가 발생했습니다.");
+                });
+        },
     },
     computed: {
-       
+        totalPages() {
+            return Math.ceil(this.totalPosts / this.pageSize);
+        }
     },
-    components:{
+    components: {
         SvgIcon
     },
     mounted() {
-        console.log('Main2 mounted');
+        this.fetchBooks(); // Fetch books when the component is mounted
+        this.fetchData(); // Fetch data for the default view
     }
-}
-</script>
(No newline at end of file)
+};
+</script>
Add a comment
List