jichoi / lms_front star
홍아랑 홍아랑 2024-08-23
240823 홍아랑 정다정 지문,단어장,미니게임문제들 시퀀스 넘버 추가
@c233db491a023fae12546ef0a593ce1cb565622d
client/views/pages/AppStore.js
--- client/views/pages/AppStore.js
+++ client/views/pages/AppStore.js
@@ -2,244 +2,260 @@
 
 // Local storage에 상태를 저장하는 함수
 function saveStateToLocalStorage(state) {
-    localStorage.setItem('vuexState', JSON.stringify(state));
+  localStorage.setItem("vuexState", JSON.stringify(state));
 }
 
 // Local storage에서 상태를 불러오는 함수
 function loadStateFromLocalStorage() {
-    const savedState = localStorage.getItem('vuexState');
-    if (savedState) {
-        return JSON.parse(savedState);
-    }
-    return {
-        token: null,
-        userId: null,
-        authcd: null,
-        stdId: null,
-        schdlId: null,
-        bookId: null,
-        unitId: null,
-        unitNm: null,
-        LearningId: null,
+  const savedState = localStorage.getItem("vuexState");
+  if (savedState) {
+    return JSON.parse(savedState);
+  }
+  return {
+    token: null,
+    userId: null,
+    authcd: null,
+    stdId: null,
+    schdlId: null,
+    bookId: null,
+    unitId: null,
+    unitNm: null,
+    LearningId: null,
 
-        // 문제
-        currentLearningIds: [],
-        prblmTypeId: null,
-        currentLabel: null,
-        currentProblemIndex: 0,
-        allProblems: [],
+    // 문제
+    currentLearningIds: [],
+    prblmTypeId: null,
+    currentLabel: null,
+    currentProblemIndex: 0,
+    allProblems: [],
 
-        // 단어장
-        textId: null,
-        wdBookIdList: [],
-        currentWdBkIndex: 0,
-    };
+    // 단어장
+    textId: null,
+    wdBookIdList: [],
+    currentWdBkIndex: 0,
+
+    // 순서
+    seqNum: null,
+  };
 }
 
-
 export default createStore({
-    state: loadStateFromLocalStorage(),
-    getters: {
-        getUserInfo(state) {
-            return {
-                userId: state.userId,
-                userNm: state.userNm,
-                authcd: state.authcd,
-            };
-        },
-        getStdId(state) {
-            return state.stdId;
-        },
-        getSchdlId(state) {
-            return state.schdlId;
-        },
-        getBookId(state) {
-            return state.bookId;
-        },
-        getUnitId(state) {
-            return state.unitId;
-        },
-        getLearningId(state) {
-            return state.learningId;
-        },
-        getTextId(state) {
-            return state.textId;
-        },
-
-        // 문제
-        currentLearningId(state) {
-            return state.currentLearningIds[state.currentProblemIndex];
-        },
-        currentLabel: (state) => state.currentLabel,
-        currentProblemIndex: (state) => state.currentProblemIndex,
-        prblmTypeId: (state) => state.prblmTypeId,
-        getAllProblems(state) {
-            return state.allProblems;
-        },
-
-        // 단어장
-        getWdBookIdList(state) {
-            return state.wdBookIdList;
-        },
-        getCurrentWdBkIndex: (state) => state.currentWdBkIndex,
+  state: loadStateFromLocalStorage(),
+  getters: {
+    getUserInfo(state) {
+      return {
+        userId: state.userId,
+        userNm: state.userNm,
+        authcd: state.authcd,
+      };
     },
-    mutations: {
-        setToken(state, token) {
-            state.token = token;
-        },
-        clearToken(state) {
-            state.token = null;
-            state.userId = null;
-            state.userNm = null;
-            state.authcd = null;
-            state.stdId = null;
-            state.schdlId = null;
-            state.bookId = null;
-            state.unitId = null;
-            state.learningId = null;
-            saveStateToLocalStorage(state);
-        },
-        setUser(state, userId) {
-            state.userId = userId;
-            saveStateToLocalStorage(state);
-        },
-        setUserNm(state, userNm) {
-            state.userNm = userNm;
-            saveStateToLocalStorage(state);
-        },
-        setAuthcd(state, authcd) {
-            state.authcd = authcd;
-            saveStateToLocalStorage(state);
-        },
-        setStdId(state, stdId) {
-            state.stdId = stdId;
-            saveStateToLocalStorage(state);
-        },
-        setSchdlId(state, schdlId) {
-            state.schdlId = schdlId;
-            saveStateToLocalStorage(state);
-        },
-        setBookId(state, bookId) {
-            state.bookId = bookId;
-            saveStateToLocalStorage(state);
-        },
-        setUnitId(state, unitId) {
-            state.unitId = unitId;
-            saveStateToLocalStorage(state);
-        },
-        setLearningId(state, learningId) {
-            state.learningId = learningId;
-            saveStateToLocalStorage(state);
-        },
-        setTextId(state, textId) {
-            state.textId = textId;
-            saveStateToLocalStorage(state);
-        },
-
-        // 문제
-        setLearningData(state, payload) {
-            state.currentLearningIds = payload.learning_id; // Array of IDs
-            state.currentLabel = payload.label;
-            state.currentProblemIndex = 0; // Reset to the first problem
-            state.prblmTypeId = payload.prblmTypeId;
-            saveStateToLocalStorage(state);
-        },
-        incrementProblemIndex(state) {
-            if (state.currentProblemIndex < state.currentLearningIds.length - 1) {
-                state.currentProblemIndex++;
-                saveStateToLocalStorage(state);
-            }
-        },
-        decrementProblemIndex(state) {
-            if (state.currentProblemIndex > 0) {
-                state.currentProblemIndex--;
-                saveStateToLocalStorage(state);
-            }
-        },
-        saveOrUpdateProblem(state, problemData) {
-            const existingProblemIndex = state.allProblems.findIndex(
-                problem => problem.prblmNumber === problemData.prblmNumber
-            );
-
-            if (existingProblemIndex !== -1) {
-                // 문제 데이터 업데이트
-                state.allProblems[existingProblemIndex] = problemData;
-            } else {
-                // 새로운 문제 추가
-                state.allProblems.push(problemData);
-            }
-        },
-
-        // 단어장
-        setWdBookIdList(state, wdBookIdList) {
-            state.wdBookIdList = wdBookIdList;
-            saveStateToLocalStorage(state);
-        },
-        setCurrentWdBkIndex(state, currentWdBkIndex) {
-            state.currentWdBkIndex = currentWdBkIndex;
-            saveStateToLocalStorage(state);
-        }
+    getStdId(state) {
+      return state.stdId;
     },
-    actions: {
-        login({ commit }, token) {
-            commit("setToken", token);
-            localStorage.setItem("token", token);
-        },
-        logout({ commit }) {
-            commit("clearToken");
-            localStorage.removeItem("token");
-        },
-        updateStdId({ commit }, payload) {
-            return new Promise((resolve) => {
-                commit("setStdId", payload);
-                resolve();
-            });
-        },
-        updateSchdlId({ commit }, payload) {
-            return new Promise((resolve) => {
-                commit("setSchdlId", payload);
-                resolve();
-            });
-        },
-        updateBookId({ commit }, payload) {
-            return new Promise((resolve) => {
-                commit("setBookId", payload);
-                resolve();
-            });
-        },
-        updateUnitId({ commit }, payload) {
-            return new Promise((resolve) => {
-                commit("setUnitId", payload);
-                resolve();
-            });
-        },
-        updateLearningId({ commit }, learningId) {
-            commit("setLearningId", learningId);
-        },
-        updateLearningData({ commit }, payload) {
-            commit("setLearningData", payload);
-        },
-        updateTextId({ commit }, textId) {
-            commit("setTextId", textId);
-        },
-
-        // 문제
-        goToNextProblem({ commit }) {
-            commit("incrementProblemIndex");
-        },
-        goToPreviousProblem({ commit }) {
-            commit("decrementProblemIndex");
-        },
-        saveProblemData({ commit }, problemData) {
-            commit('saveOrUpdateProblem', problemData);
-        },
-
-        // 단어장
-        updateWdBookIdList({ commit }, wdBookIdList) {
-            commit('setWdBookIdList', wdBookIdList);
-        },
-        updateCurrentWdBkIndex({ commit }, currentWdBkIndex) {
-            commit('setCurrentWdBkIndex', currentWdBkIndex);
-        }
+    getSchdlId(state) {
+      return state.schdlId;
     },
+    getBookId(state) {
+      return state.bookId;
+    },
+    getUnitId(state) {
+      return state.unitId;
+    },
+    getLearningId(state) {
+      return state.learningId;
+    },
+    getTextId(state) {
+      return state.textId;
+    },
+
+    // 문제
+    currentLearningId(state) {
+      return state.currentLearningIds[state.currentProblemIndex];
+    },
+    currentLabel: (state) => state.currentLabel,
+    currentProblemIndex: (state) => state.currentProblemIndex,
+    seqNum: (state) => state.seqNum,
+    prblmTypeId: (state) => state.prblmTypeId,
+    getAllProblems(state) {
+      return state.allProblems;
+    },
+
+    // 단어장
+    getWdBookIdList(state) {
+      return state.wdBookIdList;
+    },
+    getCurrentWdBkIndex: (state) => state.currentWdBkIndex,
+  },
+  mutations: {
+    setToken(state, token) {
+      state.token = token;
+    },
+    clearToken(state) {
+      state.token = null;
+      state.userId = null;
+      state.userNm = null;
+      state.authcd = null;
+      state.stdId = null;
+      state.schdlId = null;
+      state.bookId = null;
+      state.unitId = null;
+      state.learningId = null;
+      saveStateToLocalStorage(state);
+    },
+    setUser(state, userId) {
+      state.userId = userId;
+      saveStateToLocalStorage(state);
+    },
+    setUserNm(state, userNm) {
+      state.userNm = userNm;
+      saveStateToLocalStorage(state);
+    },
+    setAuthcd(state, authcd) {
+      state.authcd = authcd;
+      saveStateToLocalStorage(state);
+    },
+    setStdId(state, stdId) {
+      state.stdId = stdId;
+      saveStateToLocalStorage(state);
+    },
+    setSchdlId(state, schdlId) {
+      state.schdlId = schdlId;
+      saveStateToLocalStorage(state);
+    },
+    setBookId(state, bookId) {
+      state.bookId = bookId;
+      saveStateToLocalStorage(state);
+    },
+    setUnitId(state, unitId) {
+      state.unitId = unitId;
+      saveStateToLocalStorage(state);
+    },
+    setLearningId(state, learningId) {
+      state.learningId = learningId;
+      saveStateToLocalStorage(state);
+    },
+    setTextId(state, textId) {
+      state.textId = textId;
+      saveStateToLocalStorage(state);
+    },
+
+    // 순서
+    // setSeqNum(state, seqNum) {
+    //   state.seqNum = seqNum;
+    //   saveStateToLocalStorage(state);
+    // },
+
+    // 문제
+    setLearningData(state, payload) {
+      state.currentLearningIds = payload.learning_id; // Array of IDs
+      state.currentLabel = payload.label;
+      state.currentProblemIndex = 0; // Reset to the first problem
+      state.prblmTypeId = payload.prblmTypeId;
+      // 순서
+      state.seqNum = payload.seqNum;
+      saveStateToLocalStorage(state);
+    },
+    incrementProblemIndex(state) {
+      if (state.currentProblemIndex < state.currentLearningIds.length - 1) {
+        state.currentProblemIndex++;
+        saveStateToLocalStorage(state);
+      }
+    },
+    decrementProblemIndex(state) {
+      if (state.currentProblemIndex > 0) {
+        state.currentProblemIndex--;
+        saveStateToLocalStorage(state);
+      }
+    },
+    saveOrUpdateProblem(state, problemData) {
+      const existingProblemIndex = state.allProblems.findIndex(
+        (problem) => problem.prblmNumber === problemData.prblmNumber
+      );
+
+      if (existingProblemIndex !== -1) {
+        // 문제 데이터 업데이트
+        state.allProblems[existingProblemIndex] = problemData;
+      } else {
+        // 새로운 문제 추가
+        state.allProblems.push(problemData);
+      }
+    },
+
+    // 단어장
+    setWdBookIdList(state, wdBookIdList) {
+      state.wdBookIdList = wdBookIdList;
+      saveStateToLocalStorage(state);
+    },
+    setCurrentWdBkIndex(state, currentWdBkIndex) {
+      state.currentWdBkIndex = currentWdBkIndex;
+      saveStateToLocalStorage(state);
+    },
+  },
+  actions: {
+    login({ commit }, token) {
+      commit("setToken", token);
+      localStorage.setItem("token", token);
+    },
+    logout({ commit }) {
+      commit("clearToken");
+      localStorage.removeItem("token");
+    },
+    updateStdId({ commit }, payload) {
+      return new Promise((resolve) => {
+        commit("setStdId", payload);
+        resolve();
+      });
+    },
+    updateSchdlId({ commit }, payload) {
+      return new Promise((resolve) => {
+        commit("setSchdlId", payload);
+        resolve();
+      });
+    },
+    updateBookId({ commit }, payload) {
+      return new Promise((resolve) => {
+        commit("setBookId", payload);
+        resolve();
+      });
+    },
+    updateUnitId({ commit }, payload) {
+      return new Promise((resolve) => {
+        commit("setUnitId", payload);
+        resolve();
+      });
+    },
+    updateLearningId({ commit }, learningId) {
+      commit("setLearningId", learningId);
+    },
+    updateLearningData({ commit }, payload) {
+      commit("setLearningData", payload);
+    },
+    updateTextId({ commit }, textId) {
+      commit("setTextId", textId);
+    },
+
+    // 문제
+    goToNextProblem({ commit }) {
+      commit("incrementProblemIndex");
+    },
+    goToPreviousProblem({ commit }) {
+      commit("decrementProblemIndex");
+    },
+    saveProblemData({ commit }, problemData) {
+      commit("saveOrUpdateProblem", problemData);
+    },
+
+    // 단어장
+    updateWdBookIdList({ commit }, wdBookIdList) {
+      commit("setWdBookIdList", wdBookIdList);
+    },
+    updateCurrentWdBkIndex({ commit }, currentWdBkIndex) {
+      commit("setCurrentWdBkIndex", currentWdBkIndex);
+    },
+
+    // 순서
+    // updateSeqNum({ commit }) {
+    //   commit("setSeqNum", seqNum);
+    // },
+  },
 });
client/views/pages/main/Chapter/Chapter1_2.vue
--- client/views/pages/main/Chapter/Chapter1_2.vue
+++ client/views/pages/main/Chapter/Chapter1_2.vue
@@ -1,157 +1,188 @@
 <template>
-    <div id="Chapter1_2" class="content-wrap">
-        <div style="margin: 30px 0px 50px; width: 20%">
-            <router-link to="/MyPlan.page">
-                <div class="logo mb25"><img src="../../../../resources/img/logo2.png" alt="" /></div>
-            </router-link>
+  <div id="Chapter1_2" class="content-wrap">
+    <div style="margin: 30px 0px 50px; width: 20%">
+      <router-link to="/MyPlan.page">
+        <div class="logo mb25">
+          <img src="../../../../resources/img/logo2.png" alt="" />
         </div>
-        <div class="title-box mb25 flex align-center mt40" style="justify-content: space-between">
-            <div>
-                <span class="title mr40">1. Hello WORLD</span>
-                <span class="subtitle">my name is dd</span>
-            </div>
-            <button class="completeBtn" @click="complete">학습 종료</button>
-        </div>
-        <div class="flex justify-between align-center">
-            <div class="pre-btn" @click="goToPage('Chapter1_1')"><img src="../../../../resources/img/left.png" alt="" /></div>
-            <div class="content title-box">
-                <p class="title mt25 title-bg">step1. Hello WORLD</p>
-                <div class="flex justify-center">
-                    <div class="readGroup">
-                        <h4>각 인물들의 대화를 집중해서 읽어보세요</h4>
-                        <div>
-                            <div class="textbox">
-                                <article v-for="(line, index) in combinedLines" :key="index" :class="['flex', 'align-start', 'mb10', { 'justify-end': index % 2 !== 0 }]">
-                                    <div v-if="index % 2 === 0" class="icon mr40">
-                                        <img src="../../../../resources/img/img37_s.png" alt="" />
-                                        <p class="name">{{ speakerA_name }}</p>
-                                    </div>
-                                    <p v-if="index % 2 === 0" class="read">{{ line }}</p>
-
-                                    <p v-if="index % 2 !== 0" class="read mr40">{{ line }}</p>
-                                    <div v-if="index % 2 !== 0" class="icon">
-                                        <img src="../../../../resources/img/img37_s.png" alt="" />
-                                        <p class="name">{{ speakerB_name }}</p>
-                                    </div>
-                                </article>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-            <div class="next-btn" @click="goToPage('Chapter1_3')"><img src="../../../../resources/img/right.png" alt="" /></div>
-        </div>
-        <TextToImage />
+      </router-link>
     </div>
+    <div
+      class="title-box mb25 flex align-center mt40"
+      style="justify-content: space-between"
+    >
+      <div>
+        <span class="title mr40">1. Hello WORLD</span>
+        <span class="subtitle">my name is dd</span>
+      </div>
+      <button class="completeBtn" @click="complete">학습 종료</button>
+    </div>
+    <div class="flex justify-between align-center">
+      <div class="pre-btn" @click="goToPage('Chapter1_1')">
+        <img src="../../../../resources/img/left.png" alt="" />
+      </div>
+      <div class="content title-box">
+        <p class="title mt25 title-bg">step1. Hello WORLD</p>
+        <div class="flex justify-center">
+          <div class="readGroup">
+            <h4>각 인물들의 대화를 집중해서 읽어보세요</h4>
+            <div>
+              <div class="textbox">
+                <article
+                  v-for="(line, index) in combinedLines"
+                  :key="index"
+                  :class="[
+                    'flex',
+                    'align-start',
+                    'mb10',
+                    { 'justify-end': index % 2 !== 0 },
+                  ]"
+                >
+                  <div v-if="index % 2 === 0" class="icon mr40">
+                    <img src="../../../../resources/img/img37_s.png" alt="" />
+                    <p class="name">{{ speakerA_name }}</p>
+                  </div>
+                  <p v-if="index % 2 === 0" class="read">{{ line }}</p>
+
+                  <p v-if="index % 2 !== 0" class="read mr40">{{ line }}</p>
+                  <div v-if="index % 2 !== 0" class="icon">
+                    <img src="../../../../resources/img/img37_s.png" alt="" />
+                    <p class="name">{{ speakerB_name }}</p>
+                  </div>
+                </article>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="next-btn" @click="goToNextPage">
+        <img src="../../../../resources/img/right.png" alt="" />
+      </div>
+    </div>
+    <TextToImage />
+  </div>
 </template>
 
 <script>
 import TextToImage from "../../../component/TextToImage.vue";
 import axios from "axios";
 export default {
-    data() {
-        return {
-            text_data: null, // 받아온 지문 정보
-            speakerA_name: null,
-            speakerB_name: null,
-            speakerA: [],
-            speakerB: [],
-        };
-    },
-    methods: {
-        complete() {
-            const { unit_id, book_id } = this.$route.query;
-            this.$router.push({ name: "Dashboard", query: { value: 1, unit_id, book_id } });
-        },
-        goToPage(page) {
-            this.$router.push({ name: page });
-        },
-        // 대화 지문 API
-        async fetchText() {
-            axios({
-                url: "/text/selectOneText.json",
-                method: "post",
-                headers: {
-                    "Content-Type": "application/json; charset=UTF-8",
-                },
-                data: {
-                    textId: this.textId,
-                },
-            })
-                .then((response) => {
-                    this.text_data = response.data[0].text_cnt;
-                    this.splitConversation();
-                })
-                .catch((err) => {
-                    console.log("지문 에러 : ", err);
-                });
-        },
-        // 대화 지문 split
-        splitConversation() {
-            const lines = this.text_data.split("/");
-            const speakers = {};
+  data() {
+    return {
+      text_data: null, // 받아온 지문 정보
+      speakerA_name: null,
+      speakerB_name: null,
+      speakerA: [],
+      speakerB: [],
 
-            lines.forEach((line) => {
-                const [speaker, message] = line.trim().split(":");
-
-                if (!speakers.speakerA_name && !speakers.speakerB_name) {
-                    // 첫 번째 발화자를 speakerA_name으로 설정
-                    speakers.speakerA_name = speaker.trim();
-                    this.speakerA.push(message.trim());
-                } else if (speakers.speakerA_name && !speakers.speakerB_name && speakers.speakerA_name !== speaker.trim()) {
-                    // 두 번째 발화자를 speakerB_name으로 설정
-                    speakers.speakerB_name = speaker.trim();
-                    this.speakerB.push(message.trim());
-                } else if (speaker.trim() === speakers.speakerA_name) {
-                    // speakerA_name에 내용 추가
-                    this.speakerA.push(message.trim());
-                } else if (speaker.trim() === speakers.speakerB_name) {
-                    // speakerB_name에 내용 추가
-                    this.speakerB.push(message.trim());
-                }
-            });
-
-            this.speakerA_name = speakers.speakerA_name;
-            this.speakerB_name = speakers.speakerB_name;
+      seq: this.$store.getters.seqNum,
+    };
+  },
+  methods: {
+    complete() {
+      const { unit_id, book_id } = this.$route.query;
+      this.$router.push({
+        name: "Dashboard",
+        query: { value: this.seq, unit_id, book_id },
+      });
+    },
+    goToPage(page) {
+      this.$router.push({ name: page });
+    },
+    goToNextPage() {
+      alert("지문 학습 완료");
+      this.complete();
+    },
+    // 대화 지문 API
+    async fetchText() {
+      axios({
+        url: "/text/selectOneText.json",
+        method: "post",
+        headers: {
+          "Content-Type": "application/json; charset=UTF-8",
         },
-    },
-    watch: {},
-    computed: {
-        textId() {
-            //console.log("지문 화면 아이디 : ", this.$store.getters.getTextId);
-            return this.$store.getters.getTextId;
+        data: {
+          textId: this.textId,
         },
-        combinedLines() {
-            const maxLength = Math.max(this.speakerA.length, this.speakerB.length);
-            const lines = [];
+      })
+        .then((response) => {
+          this.text_data = response.data[0].text_cnt;
+          this.splitConversation();
+        })
+        .catch((err) => {
+          console.log("지문 에러 : ", err);
+        });
+    },
+    // 대화 지문 split
+    splitConversation() {
+      const lines = this.text_data.split("/");
+      const speakers = {};
 
-            for (let i = 0; i < maxLength; i++) {
-                if (i < this.speakerA.length) {
-                    lines.push(this.speakerA[i]);
-                }
-                if (i < this.speakerB.length) {
-                    lines.push(this.speakerB[i]);
-                }
-            }
-            return lines;
-        },
+      lines.forEach((line) => {
+        const [speaker, message] = line.trim().split(":");
+
+        if (!speakers.speakerA_name && !speakers.speakerB_name) {
+          // 첫 번째 발화자를 speakerA_name으로 설정
+          speakers.speakerA_name = speaker.trim();
+          this.speakerA.push(message.trim());
+        } else if (
+          speakers.speakerA_name &&
+          !speakers.speakerB_name &&
+          speakers.speakerA_name !== speaker.trim()
+        ) {
+          // 두 번째 발화자를 speakerB_name으로 설정
+          speakers.speakerB_name = speaker.trim();
+          this.speakerB.push(message.trim());
+        } else if (speaker.trim() === speakers.speakerA_name) {
+          // speakerA_name에 내용 추가
+          this.speakerA.push(message.trim());
+        } else if (speaker.trim() === speakers.speakerB_name) {
+          // speakerB_name에 내용 추가
+          this.speakerB.push(message.trim());
+        }
+      });
+
+      this.speakerA_name = speakers.speakerA_name;
+      this.speakerB_name = speakers.speakerB_name;
     },
-    components: {
-        TextToImage: TextToImage,
+  },
+  watch: {},
+  computed: {
+    textId() {
+      //console.log("지문 화면 아이디 : ", this.$store.getters.getTextId);
+      return this.$store.getters.getTextId;
     },
-    mounted() {
-        this.fetchText();
+    combinedLines() {
+      const maxLength = Math.max(this.speakerA.length, this.speakerB.length);
+      const lines = [];
+
+      for (let i = 0; i < maxLength; i++) {
+        if (i < this.speakerA.length) {
+          lines.push(this.speakerA[i]);
+        }
+        if (i < this.speakerB.length) {
+          lines.push(this.speakerB[i]);
+        }
+      }
+      return lines;
     },
+  },
+  components: {
+    TextToImage: TextToImage,
+  },
+  mounted() {
+    this.fetchText();
+  },
 };
 </script>
 
 <style>
 .completeBtn {
-    margin-right: 100px;
-    background-color: #ffba08;
-    padding: 10px 30px;
-    border-radius: 10px;
-    font-size: 28px;
-    font-family: "ONEMobilePOPOTF";
+  margin-right: 100px;
+  background-color: #ffba08;
+  padding: 10px 30px;
+  border-radius: 10px;
+  font-size: 28px;
+  font-family: "ONEMobilePOPOTF";
 }
 </style>
client/views/pages/main/Chapter/Chapter1_3.vue
--- client/views/pages/main/Chapter/Chapter1_3.vue
+++ client/views/pages/main/Chapter/Chapter1_3.vue
@@ -1,104 +1,121 @@
 <template>
-    <div id="Chapter1" class="content-wrap">
-        <div style="margin: 30px 0px 50px; width: 20%">
-            <router-link to="/MyPlan.page">
-                <div class="logo mb25"><img src="../../../../resources/img/logo2.png" alt="" /></div>
-            </router-link>
+  <div id="Chapter1" class="content-wrap">
+    <div style="margin: 30px 0px 50px; width: 20%">
+      <router-link to="/MyPlan.page">
+        <div class="logo mb25">
+          <img src="../../../../resources/img/logo2.png" alt="" />
         </div>
-        <div class="title-box mb25 flex align-center mt40" style="justify-content: space-between">
-            <div>
-                <span class="title mr40">1. Hello WORLD</span>
-                <span class="subtitle">my name is dd</span>
-            </div>
-            <button class="completeBtn" @click="complete">학습 종료</button>
-        </div>
-        <div class="flex justify-between align-center">
-            <div class="pre-btn" @click="goToPage('Chapter1_2')"><img src="../../../../resources/img/left.png" alt="" /></div>
-            <div class="content title-box">
-                <div class="listenGroup">
-                    <p class="title mt25 title-bg">step1. Hello WORLD</p>
-                    <!--
+      </router-link>
+    </div>
+    <div
+      class="title-box mb25 flex align-center mt40"
+      style="justify-content: space-between"
+    >
+      <div>
+        <span class="title mr40">1. Hello WORLD</span>
+        <span class="subtitle">my name is dd</span>
+      </div>
+      <button class="completeBtn" @click="complete">학습 종료</button>
+    </div>
+    <div class="flex justify-between align-center">
+      <div class="pre-btn" @click="goToPage('Chapter1_2')">
+        <img src="../../../../resources/img/left.png" alt="" />
+      </div>
+      <div class="content title-box">
+        <div class="listenGroup">
+          <p class="title mt25 title-bg">step1. Hello WORLD</p>
+          <!--
                     <img class="bg" src="../../../../resources/img/img39_s.png" data-num="1" />
                     -->
-                    <img class="bg" :src="img_src" />
-                </div>
-            </div>
-            <div class="next-btn" @click="goToPage('Chapter2')"><img src="../../../../resources/img/right.png" alt="" /></div>
+          <img class="bg" :src="img_src" />
         </div>
-        <TextToImage />
+      </div>
+      <div class="next-btn" @click="goToNextPage">
+        <img src="../../../../resources/img/right.png" alt="" />
+      </div>
     </div>
+    <TextToImage />
+  </div>
 </template>
 
 <script>
 import TextToImage from "../../../component/TextToImage.vue";
 import axios from "axios";
 export default {
-    data() {
-        return {
-            text_data: null,
-            img_src: null,
-        };
+  data() {
+    return {
+      text_data: null,
+      img_src: null,
+      seq: this.$store.getters.seqNum,
+    };
+  },
+  methods: {
+    complete() {
+      const { unit_id, book_id } = this.$route.query;
+      this.$router.push({
+        name: "Dashboard",
+        query: { value: this.seq, unit_id, book_id },
+      });
     },
-    methods: {
-        complete() {
-            const { unit_id, book_id } = this.$route.query;
-            this.$router.push({ name: "Dashboard", query: { value: 1, unit_id, book_id } });
-        },
-        goToPage(page) {
-            this.$router.push({ name: page });
-        },
-        // 지문 API
-        async fetchText() {
-            axios({
-                url: "/text/selectOneText.json",
-                method: "post",
-                headers: {
-                    "Content-Type": "application/json; charset=UTF-8",
-                },
-                data: {
-                    textId: this.textId,
-                },
-            })
-                .then((response) => {
-                    this.text_data = response.data[0];
-                    console.log("지문 데이터 : ", this.text_data);
-                    this.img_src = this.fetchImage(this.text_data.file_rpath);
-                })
-                .catch((err) => {
-                    console.log("지문 에러 : ", err);
-                });
-        },
-        // 이미지 불러오기
-        fetchImage(fileRpath) {
-            return "http://165.229.169.113:9080/" + fileRpath;
-        },
+    goToPage(page) {
+      this.$router.push({ name: page });
     },
-    watch: {},
-    computed: {
-        textId() {
-            //console.log("지문 화면 아이디 : ", this.$store.getters.getTextId);
-            return this.$store.getters.getTextId;
+    goToNextPage() {
+      alert("지문 학습 완료");
+      this.complete();
+    },
+    // 지문 API
+    async fetchText() {
+      axios({
+        url: "/text/selectOneText.json",
+        method: "post",
+        headers: {
+          "Content-Type": "application/json; charset=UTF-8",
         },
+        data: {
+          textId: this.textId,
+        },
+      })
+        .then((response) => {
+          this.text_data = response.data[0];
+          console.log("지문 데이터 : ", this.text_data);
+          this.img_src = this.fetchImage(this.text_data.file_rpath);
+        })
+        .catch((err) => {
+          console.log("지문 에러 : ", err);
+        });
     },
-    components: {
-        TextToImage: TextToImage,
+    // 이미지 불러오기
+    fetchImage(fileRpath) {
+      return "http://165.229.169.113:9080/" + fileRpath;
     },
-    mounted() {
-        this.fetchText();
+  },
+  watch: {},
+  computed: {
+    textId() {
+      //console.log("지문 화면 아이디 : ", this.$store.getters.getTextId);
+      return this.$store.getters.getTextId;
     },
+  },
+  components: {
+    TextToImage: TextToImage,
+  },
+  mounted() {
+    this.fetchText();
+  },
 };
 </script>
 <style scoped>
 .listenGroup .textbox {
-    width: 900px;
+  width: 900px;
 }
 
 .completeBtn {
-    margin-right: 100px;
-    background-color: #ffba08;
-    padding: 10px 30px;
-    border-radius: 10px;
-    font-size: 28px;
-    font-family: "ONEMobilePOPOTF";
+  margin-right: 100px;
+  background-color: #ffba08;
+  padding: 10px 30px;
+  border-radius: 10px;
+  font-size: 28px;
+  font-family: "ONEMobilePOPOTF";
 }
 </style>
client/views/pages/main/Chapter/Chapter2_10.vue
--- client/views/pages/main/Chapter/Chapter2_10.vue
+++ client/views/pages/main/Chapter/Chapter2_10.vue
@@ -126,6 +126,8 @@
       problemData: [],
       // problemArr: [],
       answerArr: [],
+
+      seq: this.$store.getters.seqNum,
     };
   },
   methods: {
@@ -133,7 +135,7 @@
       const { unit_id, book_id } = this.$route.query;
       this.$router.push({
         name: "Dashboard",
-        query: { value: 3, unit_id, book_id },
+        query: { value: this.seq, unit_id, book_id },
       });
     },
     goToPage(page) {
@@ -170,7 +172,9 @@
         this.goToPage(this.problemType);
       } else {
         // 마지막 문제면 이동
-        this.goToPage("Chapter4");
+        // this.goToPage("Chapter4");
+        alert("문제 학습 완료");
+        this.complete();
       }
     },
     previousProblem() {
client/views/pages/main/Chapter/Chapter2_11.vue
--- client/views/pages/main/Chapter/Chapter2_11.vue
+++ client/views/pages/main/Chapter/Chapter2_11.vue
@@ -103,6 +103,8 @@
       prblm_id: [],
       unit_id: null,
       dataList: [],
+
+      seq: this.$store.getters.seqNum,
     };
   },
   methods: {
@@ -110,7 +112,7 @@
       const { unit_id, book_id } = this.$route.query;
       this.$router.push({
         name: "Dashboard",
-        query: { value: 3, unit_id, book_id },
+        query: { value: this.seq, unit_id, book_id },
       });
     },
     goToPage(page) {
@@ -190,7 +192,9 @@
         this.goToPage(this.problemType);
       } else {
         // 마지막 문제면 이동
-        this.goToPage("Chapter4");
+        // this.goToPage("Chapter4");
+        alert("문제 학습 완료");
+        this.complete();
       }
     },
     previousProblem() {
client/views/pages/main/Chapter/Chapter2_13.vue
--- client/views/pages/main/Chapter/Chapter2_13.vue
+++ client/views/pages/main/Chapter/Chapter2_13.vue
@@ -145,6 +145,8 @@
       problemData: [],
       // problemArr: [],
       answerArr: [],
+
+      seq: this.$store.getters.seqNum,
     };
   },
   methods: {
@@ -152,7 +154,7 @@
       const { unit_id, book_id } = this.$route.query;
       this.$router.push({
         name: "Dashboard",
-        query: { value: 3, unit_id, book_id },
+        query: { value: this.seq, unit_id, book_id },
       });
     },
     goToPage(page) {
@@ -200,7 +202,9 @@
         this.goToPage(this.problemType);
       } else {
         // 마지막 문제면 이동
-        this.goToPage("Chapter4");
+        // this.goToPage("Chapter4");
+        alert("문제 학습 완료");
+        this.complete();
       }
     },
     previousProblem() {
client/views/pages/main/Chapter/Chapter2_2.vue
--- client/views/pages/main/Chapter/Chapter2_2.vue
+++ client/views/pages/main/Chapter/Chapter2_2.vue
@@ -45,7 +45,9 @@
             <button class="popTxt" v-for="(item, index) in items" :key="index">
               <div class="listenGroup">
                 <img :src="item.imgSrc1" />
-                <p class="textbox"><img :src="item.imgSrc" style="height: 150px;"/></p>
+                <p class="textbox">
+                  <img :src="item.imgSrc" style="height: 150px" />
+                </p>
               </div>
               <div
                 class="listenGroup"
@@ -68,7 +70,7 @@
 </template>
 
 <script>
-import axios from 'axios';
+import axios from "axios";
 
 export default {
   data() {
@@ -82,13 +84,16 @@
       currentWdBkIndex: 0, // 현재 단어장 인덱스
       wdBookTypeIdState: "", // 이동할 페이지 타입 id
       wordBookType: "", // 이동할 페이지
+
+      seq: this.$store.getters.seqNum,
     };
   },
   methods: {
     pageSetting() {
       this.currentWdBkIndex = this.$store.getters.getCurrentWdBkIndex; // 현재 단어장 인덱스
       this.wdBookIdList = this.$store.getters.getWdBookIdList; // 단어컨텐츠의 단어장 id 리스트
-      this.wdBookId = this.$store.getters.getWdBookIdList[this.currentWdBkIndex] // 현재 단어장 콘텐츠 인덱스에 대한 단어장 id
+      this.wdBookId =
+        this.$store.getters.getWdBookIdList[this.currentWdBkIndex]; // 현재 단어장 콘텐츠 인덱스에 대한 단어장 id
       console.log(this.wdBookId);
 
       this.fetchWordList();
@@ -96,7 +101,7 @@
 
     async fetchWordList() {
       try {
-        const response = await axios.post('/word/getWordsByBookId.json', {
+        const response = await axios.post("/word/getWordsByBookId.json", {
           wdBookId: this.wdBookId,
         });
 
@@ -108,7 +113,10 @@
             file_mng_id: word.fileMngId,
           });
 
-          const fileRpath = fileResponse.data.list.length > 0 ? fileResponse.data.list[0].fileRpath : null;
+          const fileRpath =
+            fileResponse.data.list.length > 0
+              ? fileResponse.data.list[0].fileRpath
+              : null;
           console.log("각 단어의 fileRpath: ", fileRpath);
 
           // items 배열에 새로운 항목 추가
@@ -116,16 +124,15 @@
             imgSrc1: "client/resources/img/img49_s.png",
             imgSrc2: "client/resources/img/img50_s.png",
             imgSrc: "http://165.229.169.113:9080/" + fileRpath, // 받아온 fileRpath로 이미지 설정
-            isSecondImageVisible: false, 
+            isSecondImageVisible: false,
             title: word.wdNm,
           });
         });
 
         // 모든 요청이 완료될 때까지 대기
         await Promise.all(requests);
-
       } catch (error) {
-        console.error('단어 목록을 불러오는 중 오류 발생:', error);
+        console.error("단어 목록을 불러오는 중 오류 발생:", error);
       }
     },
 
@@ -134,38 +141,39 @@
         alert("단어장 첫번째 페이지 입니다");
       } else {
         this.currentWdBkIndex--;
-        this.$store.dispatch('updateCurrentWdBkIndex', this.currentWdBkIndex);
+        this.$store.dispatch("updateCurrentWdBkIndex", this.currentWdBkIndex);
 
         try {
           const response = await axios.post("/wordbook/find.json", {
-            wdBookId: this.$store.getters.getWdBookIdList[this.currentWdBkIndex]
+            wdBookId:
+              this.$store.getters.getWdBookIdList[this.currentWdBkIndex],
           });
           this.wdBookTypeIdState = response.data.wdBookTypeId;
           console.log("이전 단어장 타입 id: ", this.wdBookTypeIdState);
 
           switch (this.wdBookTypeIdState) {
             case "1":
-                this.wordBookType = "Chapter2";
-                break;
+              this.wordBookType = "Chapter2";
+              break;
             case "2":
-                this.wordBookType = "Chapter2_3";
-                break;
+              this.wordBookType = "Chapter2_3";
+              break;
             case "3":
-                this.wordBookType = "Chapter2_2";
-                break;
+              this.wordBookType = "Chapter2_2";
+              break;
             case "4":
-                this.wordBookType = "Chapter2_9";
-                break;
+              this.wordBookType = "Chapter2_9";
+              break;
             case "5":
-                this.wordBookType = "Chapter2_4";
-                break;
+              this.wordBookType = "Chapter2_4";
+              break;
             default:
-                this.wordBookType = null;
+              this.wordBookType = null;
           }
-          
-          this.goToPage(this.wordBookType); 
+
+          this.goToPage(this.wordBookType);
         } catch (error) {
-          console.error('단어장 정보 불러오는 중 오류 발생:', error);
+          console.error("단어장 정보 불러오는 중 오류 발생:", error);
         }
       }
     },
@@ -173,48 +181,54 @@
     async goToNextPage() {
       if (this.currentWdBkIndex + 1 >= this.wdBookIdList.length) {
         alert("단어장 마지막 페이지 입니다");
+        this.complete();
       } else {
         this.currentWdBkIndex++;
-        this.$store.dispatch('updateCurrentWdBkIndex', this.currentWdBkIndex);
+        this.$store.dispatch("updateCurrentWdBkIndex", this.currentWdBkIndex);
 
         try {
           const response = await axios.post("/wordbook/find.json", {
-            wdBookId: this.$store.getters.getWdBookIdList[this.currentWdBkIndex]
+            wdBookId:
+              this.$store.getters.getWdBookIdList[this.currentWdBkIndex],
           });
           this.wdBookTypeIdState = response.data.wdBookTypeId;
           console.log("다음 단어장 타입 id: ", this.wdBookTypeIdState);
 
           switch (this.wdBookTypeIdState) {
             case "1":
-                this.wordBookType = "Chapter2";
-                break;
+              this.wordBookType = "Chapter2";
+              break;
             case "2":
-                this.wordBookType = "Chapter2_3";
-                break;
+              this.wordBookType = "Chapter2_3";
+              break;
             case "3":
-                this.wordBookType = "Chapter2_2";
-                break;
+              this.wordBookType = "Chapter2_2";
+              break;
             case "4":
-                this.wordBookType = "Chapter2_9";
-                break;
+              this.wordBookType = "Chapter2_9";
+              break;
             case "5":
-                this.wordBookType = "Chapter2_4";
-                break;
+              this.wordBookType = "Chapter2_4";
+              break;
             default:
-                this.wordBookType = null;
+              this.wordBookType = null;
           }
-          
-          this.goToPage(this.wordBookType); 
+
+          this.goToPage(this.wordBookType);
         } catch (error) {
-          console.error('단어장 정보 불러오는 중 오류 발생:', error);
+          console.error("단어장 정보 불러오는 중 오류 발생:", error);
         }
       }
     },
 
     complete() {
       const { unit_id, book_id } = this.$route.query;
-      this.$router.push({ name: 'Dashboard', query: { value: 2, unit_id, book_id } });
+      this.$router.push({
+        name: "Dashboard",
+        query: { value: this.seq, unit_id, book_id },
+      });
     },
+
     goToPage(page) {
       this.$router.push({ name: page });
     },
client/views/pages/main/Chapter/Chapter2_3.vue
--- client/views/pages/main/Chapter/Chapter2_3.vue
+++ client/views/pages/main/Chapter/Chapter2_3.vue
@@ -1,412 +1,437 @@
 <template>
-    <div id="Chapter2_2" class="content-wrap">
-        <div style="margin: 30px 0px 50px; width: 20%">
-            <router-link to="/MyPlan.page">
-                <div class="logo mb25">
-                    <img src="../../../../resources/img/logo2.png" alt="" />
-                </div>
-            </router-link>
+  <div id="Chapter2_2" class="content-wrap">
+    <div style="margin: 30px 0px 50px; width: 20%">
+      <router-link to="/MyPlan.page">
+        <div class="logo mb25">
+          <img src="../../../../resources/img/logo2.png" alt="" />
         </div>
-        <div class="title-box mb25 flex align-center mt40" style="justify-content: space-between">
-            <div>
-                <span class="title mr40">1. Hello WORLD</span>
-                <span class="subtitle">my name is dd</span>
-            </div>
-            <button class="completeBtn" @click="complete">학습 종료</button>
-        </div>
-        <div class="flex justify-between align-center">
-            <div class="pre-btn" @click="goToPage('Chapter2')"> <!-- @click="goToPrevPage" -->
-                <img src="../../../../resources/img/left.png" alt="" />
-            </div>
-            <div class="content title-box">
-                <p class="subtitle2"></p>
-                <p class="title mt25 title-bg">STEP 2 - 단어로 공부하는 영어</p>
-                <div class="flex align-center mb30">
-                    <p class="subtitle2 mr20">다음을 듣고 따라 말하세요.</p>
-                    <!-- <button><img src="../../../../resources/img/btn10_s.png" alt="">
-         </button> -->
-                </div>
-
-                <div class="imgGroup box23">
-                    <div class="con">
-                        <img :src="currentCon.imgSrc" alt="" style="height: 150px;"/>
-                        <p class="title3">
-                            <em class="yellow">{{ currentCon.titleEm }}</em
-                            >{{ currentCon.title }}
-                        </p>
-                        <div class="flex align-center justify-center mt10">
-                            <p class="yellow-box-big">{{ currentCon.boxText }}</p>
-                            <span class="subtitle3">{{ currentCon.subtitle }}</span>
-                        </div>
-                        <div class="flex justify-center">
-                            <div class="btnGroup mt50 flex justify-between">
-                                <button
-                                    class="popTxt"
-                                    v-for="(item, index) in items"
-                                    :key="index"
-                                    @click="updateContent(index)"
-                                    :class="{ active: selectedIndex === index }"
-                                >
-                                    <img :src="item.imgSrc1" />
-                                    <img :src="item.imgSrc2" v-if="selectedIndex === index" style="display: block" />
-                                </button>
-                            </div>
-                        </div>
-                    </div>
-
-                    <div class="flex justify-center">
-                        <div class="readGroup">
-                            <section>
-                                <div class="imgGroup flex justify-center">
-                                    <!-- 녹음 버튼 -->
-                                    <div :class="['mic-btn', { notRecording: !isRecording }]" @click="toggleRecording">
-                                        <img src="../../../../resources/img/btn11_s.png" alt="" />
-                                    </div>
-                                </div>
-                                <article>
-                                    <p ref="speakText" class="speakText mb25">위의 버튼을 누른 후 단어를 말해보세요!</p>
-                                </article>
-                            </section>
-                        </div>
-                    </div>
-                </div>
-            </div>
-            <div class="next-btn" @click="goToPage('Chapter2_2')"> <!-- @click="goToNextPage" -->
-                <img src="../../../../resources/img/right.png" alt="" />
-            </div>
-        </div>
+      </router-link>
     </div>
+    <div
+      class="title-box mb25 flex align-center mt40"
+      style="justify-content: space-between"
+    >
+      <div>
+        <span class="title mr40">1. Hello WORLD</span>
+        <span class="subtitle">my name is dd</span>
+      </div>
+      <button class="completeBtn" @click="complete">학습 종료</button>
+    </div>
+    <div class="flex justify-between align-center">
+      <div class="pre-btn" @click="goToPage('Chapter2')">
+        <!-- @click="goToPrevPage" -->
+        <img src="../../../../resources/img/left.png" alt="" />
+      </div>
+      <div class="content title-box">
+        <p class="subtitle2"></p>
+        <p class="title mt25 title-bg">STEP 2 - 단어로 공부하는 영어</p>
+        <div class="flex align-center mb30">
+          <p class="subtitle2 mr20">다음을 듣고 따라 말하세요.</p>
+          <!-- <button><img src="../../../../resources/img/btn10_s.png" alt="">
+         </button> -->
+        </div>
+
+        <div class="imgGroup box23">
+          <div class="con">
+            <img :src="currentCon.imgSrc" alt="" style="height: 150px" />
+            <p class="title3">
+              <em class="yellow">{{ currentCon.titleEm }}</em
+              >{{ currentCon.title }}
+            </p>
+            <div class="flex align-center justify-center mt10">
+              <p class="yellow-box-big">{{ currentCon.boxText }}</p>
+              <span class="subtitle3">{{ currentCon.subtitle }}</span>
+            </div>
+            <div class="flex justify-center">
+              <div class="btnGroup mt50 flex justify-between">
+                <button
+                  class="popTxt"
+                  v-for="(item, index) in items"
+                  :key="index"
+                  @click="updateContent(index)"
+                  :class="{ active: selectedIndex === index }"
+                >
+                  <img :src="item.imgSrc1" />
+                  <img
+                    :src="item.imgSrc2"
+                    v-if="selectedIndex === index"
+                    style="display: block"
+                  />
+                </button>
+              </div>
+            </div>
+          </div>
+
+          <div class="flex justify-center">
+            <div class="readGroup">
+              <section>
+                <div class="imgGroup flex justify-center">
+                  <!-- 녹음 버튼 -->
+                  <div
+                    :class="['mic-btn', { notRecording: !isRecording }]"
+                    @click="toggleRecording"
+                  >
+                    <img src="../../../../resources/img/btn11_s.png" alt="" />
+                  </div>
+                </div>
+                <article>
+                  <p ref="speakText" class="speakText mb25">
+                    위의 버튼을 누른 후 단어를 말해보세요!
+                  </p>
+                </article>
+              </section>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="next-btn" @click="goToNextPage">
+        <!-- @click="goToNextPage" -->
+        <img src="../../../../resources/img/right.png" alt="" />
+      </div>
+    </div>
+  </div>
 </template>
 
 <script>
-import axios from 'axios';
-import { mdiStop } from '@mdi/js';
+import axios from "axios";
+import { mdiStop } from "@mdi/js";
 export default {
-    data() {
-        return {
-            items: [],
-            currentCon: {
-                imgSrc: '',
-                titleEm: '',
-                title: '',
-                boxText: '명',
-                subtitle: '',
-            },
-            selectedIndex: 0,
-            timer: '00',
-            intervalId: null,
+  data() {
+    return {
+      items: [],
+      currentCon: {
+        imgSrc: "",
+        titleEm: "",
+        title: "",
+        boxText: "명",
+        subtitle: "",
+      },
+      selectedIndex: 0,
+      timer: "00",
+      intervalId: null,
 
-            isRecording: false, // 녹음 중 여부
-            mediaRecorder: null,
-            audioChunks: [], // 녹음된 오디오 데이터
-            audioBlob: null, // 오디오 Blob 객체
-            stream: null, // MediaStream 객체
+      isRecording: false, // 녹음 중 여부
+      mediaRecorder: null,
+      audioChunks: [], // 녹음된 오디오 데이터
+      audioBlob: null, // 오디오 Blob 객체
+      stream: null, // MediaStream 객체
 
-            path: mdiStop,
-            nowWord: 'cloud',
+      path: mdiStop,
+      nowWord: "cloud",
 
-            wdBookId: "WORD_BOOK_000000000000043",
-            wdBookIdList: [], // 단어 컨텐츠의 단어장 id 리스트
-            currentWdBkIndex: 0, // 현재 단어장 인덱스
-            wdBookTypeIdState: "", // 이동할 페이지 타입 id
-            wordBookType: "", // 이동할 페이지
-        };
+      wdBookId: "WORD_BOOK_000000000000043",
+      wdBookIdList: [], // 단어 컨텐츠의 단어장 id 리스트
+      currentWdBkIndex: 0, // 현재 단어장 인덱스
+      wdBookTypeIdState: "", // 이동할 페이지 타입 id
+      wordBookType: "", // 이동할 페이지
+
+      seq: this.$store.getters.seqNum,
+    };
+  },
+  methods: {
+    pageSetting() {
+      this.currentWdBkIndex = this.$store.getters.getCurrentWdBkIndex; // 현재 단어장 인덱스
+      this.wdBookIdList = this.$store.getters.getWdBookIdList; // 단어컨텐츠의 단어장 id 리스트
+      this.wdBookId =
+        this.$store.getters.getWdBookIdList[this.currentWdBkIndex]; // 현재 단어장 콘텐츠 인덱스에 대한 단어장 id
+
+      // this.fetchWordList();
     },
-    methods: {
-        pageSetting() {
-            this.currentWdBkIndex = this.$store.getters.getCurrentWdBkIndex; // 현재 단어장 인덱스
-            this.wdBookIdList = this.$store.getters.getWdBookIdList; // 단어컨텐츠의 단어장 id 리스트
-            this.wdBookId = this.$store.getters.getWdBookIdList[this.currentWdBkIndex] // 현재 단어장 콘텐츠 인덱스에 대한 단어장 id
 
-            // this.fetchWordList();
-        },
+    async goToPrevPage() {
+      if (this.currentWdBkIndex - 1 < 0) {
+        alert("단어장 첫번째 페이지 입니다");
+      } else {
+        this.currentWdBkIndex--;
+        this.$store.dispatch("updateCurrentWdBkIndex", this.currentWdBkIndex);
 
-        async goToPrevPage() {
-            if (this.currentWdBkIndex - 1 < 0) {
-                alert("단어장 첫번째 페이지 입니다");
-            } else {
-                this.currentWdBkIndex--;
-                this.$store.dispatch('updateCurrentWdBkIndex', this.currentWdBkIndex);
+        try {
+          const response = await axios.post("/wordbook/find.json", {
+            wdBookId:
+              this.$store.getters.getWdBookIdList[this.currentWdBkIndex],
+          });
+          this.wdBookTypeIdState = response.data.wdBookTypeId;
+          console.log("이전 단어장 타입 id: ", this.wdBookTypeIdState);
 
-                try {
-                    const response = await axios.post("/wordbook/find.json", {
-                        wdBookId: this.$store.getters.getWdBookIdList[this.currentWdBkIndex]
-                    });
-                    this.wdBookTypeIdState = response.data.wdBookTypeId;
-                    console.log("이전 단어장 타입 id: ", this.wdBookTypeIdState);
+          switch (this.wdBookTypeIdState) {
+            case "1":
+              this.wordBookType = "Chapter2";
+              break;
+            case "2":
+              this.wordBookType = "Chapter2_3";
+              break;
+            case "3":
+              this.wordBookType = "Chapter2_2";
+              break;
+            case "4":
+              this.wordBookType = "Chapter2_9";
+              break;
+            case "5":
+              this.wordBookType = "Chapter2_4";
+              break;
+            default:
+              this.wordBookType = null;
+          }
 
-                    switch (this.wdBookTypeIdState) {
-                        case "1":
-                            this.wordBookType = "Chapter2";
-                            break;
-                        case "2":
-                            this.wordBookType = "Chapter2_3";
-                            break;
-                        case "3":
-                            this.wordBookType = "Chapter2_2";
-                            break;
-                        case "4":
-                            this.wordBookType = "Chapter2_9";
-                            break;
-                        case "5":
-                            this.wordBookType = "Chapter2_4";
-                            break;
-                        default:
-                            this.wordBookType = null;
-                    }
-                    
-                    this.goToPage(this.wordBookType); 
-                } catch (error) {
-                    console.error('단어장 정보 불러오는 중 오류 발생:', error);
-                }
-            }
-        },
-
-        async goToNextPage() {
-            if (this.currentWdBkIndex + 1 >= this.wdBookIdList.length) {
-                alert("단어장 마지막 페이지 입니다");
-            } else {
-                this.currentWdBkIndex++;
-                this.$store.dispatch('updateCurrentWdBkIndex', this.currentWdBkIndex);
-
-                try {
-                    const response = await axios.post("/wordbook/find.json", {
-                        wdBookId: this.$store.getters.getWdBookIdList[this.currentWdBkIndex]
-                    });
-                    this.wdBookTypeIdState = response.data.wdBookTypeId;
-                    console.log("다음 단어장 타입 id: ", this.wdBookTypeIdState);
-
-                    switch (this.wdBookTypeIdState) {
-                        case "1":
-                            this.wordBookType = "Chapter2";
-                            break;
-                        case "2":
-                            this.wordBookType = "Chapter2_3";
-                            break;
-                        case "3":
-                            this.wordBookType = "Chapter2_2";
-                            break;
-                        case "4":
-                            this.wordBookType = "Chapter2_9";
-                            break;
-                        case "5":
-                            this.wordBookType = "Chapter2_4";
-                            break;
-                        default:
-                            this.wordBookType = null;
-                    }
-                    
-                    this.goToPage(this.wordBookType); 
-                } catch (error) {
-                    console.error('단어장 정보 불러오는 중 오류 발생:', error);
-                }
-            }
-        },
-
-        complete() {
-            const { unit_id, book_id } = this.$route.query;
-            this.$router.push({ name: 'Dashboard', query: { value: 2, unit_id, book_id } });
-        },
-        goToPage(page) {
-            this.$router.push({ name: page });
-        },
-        updateContent(index) {
-            this.selectedIndex = index;
-            this.currentCon = this.items[index].con;
-            console.log(this.currentCon.imgSrc);
-            this.startTimer();
-        },
-        startTimer() {
-            if (this.intervalId) {
-                clearInterval(this.intervalId);
-            }
-            this.timer = 5;
-            this.intervalId = setInterval(() => {
-                if (this.timer > 0) {
-                    this.timer--;
-                } else {
-                    clearInterval(this.intervalId);
-                }
-            }, 1000);
-        },
-        // 녹음 시작/중지 토글
-        async toggleRecording() {
-            if (this.isRecording) {
-                console.log('녹음 그만!');
-                this.stopRecording(); // 녹음 중이면 중지
-            } else {
-                console.log('녹음 시작!');
-                await this.startRecording(); // 녹음 중이 아니면 녹음 시작
-            }
-        },
-        // 녹음 시작
-        async startRecording() {
-            this.audioChunks = []; // 오디오 초기화
-            this.stream = await navigator.mediaDevices.getUserMedia({ audio: true });
-            this.mediaRecorder = new MediaRecorder(this.stream);
-            this.mediaRecorder.ondataavailable = (event) => {
-                this.audioChunks.push(event.data); // 녹음 데이터 저장
-            };
-            this.mediaRecorder.onstop = () => {
-                this.audioBlob = new Blob(this.audioChunks, { type: 'audio/wav' });
-
-                /******************************/
-                // this.audioURL = URL.createObjectURL(this.audioBlob); // 오디오 URL 생성
-                // console.log('Audio URL:', this.audioURL);
-                /******************************/
-
-                console.log('Recorded Audio Blob:', this.audioBlob); // 콘솔에 Blob 확인
-                this.sendAudioToServer(); // 서버로 오디오 전송
-            };
-            this.mediaRecorder.start(); // 녹음 시작
-            this.isRecording = true; // 녹음 상태 변경
-        },
-
-        // 녹음 중지
-        stopRecording() {
-            this.mediaRecorder.stop(); // 녹음 중단
-
-            if (this.stream) {
-                this.stream.getTracks().forEach((track) => track.stop()); // 스트림의 모든 트랙 중지
-            }
-
-            this.isRecording = false; // 녹음 상태 변경
-        },
-
-        // 오디오 전송
-        async sendAudioToServer() {
-            const formData = new FormData();
-            formData.append('file', this.audioBlob, 'recording.wav');
-            try {
-                const response = await axios.post('/api/speechToText.json', formData, {
-                    headers: {
-                        'Content-Type': 'multipart/form-data',
-                    },
-                });
-
-                this.transcription = response.data.trim().toLowerCase();
-                this.nowWord = this.nowWord.toLowerCase();
-
-                console.log('지금 단어: ', this.nowWord);
-                console.log('녹음 결과: ', this.transcription);
-
-                if (this.transcription === this.nowWord) {
-                    this.$refs.speakText.innerText = '정답입니다! 잘했어요';
-                } else {
-                    this.$refs.speakText.innerText = '다시 말해보세요!';
-                }
-            } catch (error) {
-                console.log('파일 전송 실패: ', error);
-            }
-        },
-
-        // 단어 리스트를 서버에서 받아와 items에 적용하는 메서드
-        async fetchWordList() {
-            try {
-                const response = await axios.post('/word/getWordsByBookId.json', {
-                    wdBookId: this.wdBookId,
-                });
-
-                this.wordList = response.data;
-
-                const requests = this.wordList.map(async (word, index) => {
-                    // fileRpath를 받아오기 위한 요청
-                    const fileResponse = await axios.post('/file/find.json', {
-                        file_mng_id: word.fileMngId,
-                    });
-
-                    // fileResponse.data.list에서 fileRpath 값을 추출하여 imgSrc에 설정
-                    const fileRpath = fileResponse.data.list.length > 0 ? fileResponse.data.list[0].fileRpath : null;
-                    const imgSrc = fileRpath ? `http://165.229.169.113:9080/${fileRpath}` : '';
-
-                    return {
-                        imgSrc1: `client/resources/img/img53_${6 + index}_35s.png`,
-                        imgSrc2: `client/resources/img/img53_${1 + index}_35s.png`,
-                        con: {
-                            imgSrc, // fileRpath를 imgSrc에 설정
-                            titleEm: word.wdNm.charAt(0), // 단어의 첫 글자
-                            title: word.wdNm.slice(1), // 단어의 나머지 부분
-                            boxText: '명',
-                            subtitle: word.wdMnng, // 단어의 의미
-                        },
-                    };
-                });
-
-                // 모든 요청이 완료될 때까지 대기
-                this.items = await Promise.all(requests);
-
-                // items 리스트의 첫 번째 항목을 currentCon에 설정
-                if (this.items.length > 0) {
-                    this.currentCon = this.items[0].con;
-                    this.nowWord = this.currentCon.titleEm + this.currentCon.title;
-                }
-
-            } catch (error) {
-                console.error('단어 목록을 불러오는 중 오류 발생:', error);
-            }
-        },
-
-    },
-    watch: {
-        transcription: null, // 서버에서 받아온 텍스트 결과
-        currentCon: {
-            handler(newValue) {
-                // Update nowWord when currentCon changes
-                this.nowWord = newValue.titleEm + newValue.title;
-            },
-            deep: true, // Watch for deep changes in currentCon
-        },
-    },
-    mounted() {
-        // this.pageSetting();
-        this.fetchWordList();
-    },
-    beforeDestroy() {
-        if (this.intervalId) {
-            clearInterval(this.intervalId);
+          this.goToPage(this.wordBookType);
+        } catch (error) {
+          console.error("단어장 정보 불러오는 중 오류 발생:", error);
         }
+      }
     },
+
+    async goToNextPage() {
+      if (this.currentWdBkIndex + 1 >= this.wdBookIdList.length) {
+        alert("단어장 마지막 페이지 입니다");
+      } else {
+        this.currentWdBkIndex++;
+        this.$store.dispatch("updateCurrentWdBkIndex", this.currentWdBkIndex);
+
+        try {
+          const response = await axios.post("/wordbook/find.json", {
+            wdBookId:
+              this.$store.getters.getWdBookIdList[this.currentWdBkIndex],
+          });
+          this.wdBookTypeIdState = response.data.wdBookTypeId;
+          console.log("다음 단어장 타입 id: ", this.wdBookTypeIdState);
+
+          switch (this.wdBookTypeIdState) {
+            case "1":
+              this.wordBookType = "Chapter2";
+              break;
+            case "2":
+              this.wordBookType = "Chapter2_3";
+              break;
+            case "3":
+              this.wordBookType = "Chapter2_2";
+              break;
+            case "4":
+              this.wordBookType = "Chapter2_9";
+              break;
+            case "5":
+              this.wordBookType = "Chapter2_4";
+              break;
+            default:
+              this.wordBookType = null;
+          }
+
+          this.goToPage(this.wordBookType);
+        } catch (error) {
+          console.error("단어장 정보 불러오는 중 오류 발생:", error);
+        }
+      }
+    },
+
+    complete() {
+      const { unit_id, book_id } = this.$route.query;
+      this.$router.push({
+        name: "Dashboard",
+        query: { value: this.seq, unit_id, book_id },
+      });
+    },
+    goToPage(page) {
+      this.$router.push({ name: page });
+    },
+    updateContent(index) {
+      this.selectedIndex = index;
+      this.currentCon = this.items[index].con;
+      console.log(this.currentCon.imgSrc);
+      this.startTimer();
+    },
+    startTimer() {
+      if (this.intervalId) {
+        clearInterval(this.intervalId);
+      }
+      this.timer = 5;
+      this.intervalId = setInterval(() => {
+        if (this.timer > 0) {
+          this.timer--;
+        } else {
+          clearInterval(this.intervalId);
+        }
+      }, 1000);
+    },
+    // 녹음 시작/중지 토글
+    async toggleRecording() {
+      if (this.isRecording) {
+        console.log("녹음 그만!");
+        this.stopRecording(); // 녹음 중이면 중지
+      } else {
+        console.log("녹음 시작!");
+        await this.startRecording(); // 녹음 중이 아니면 녹음 시작
+      }
+    },
+    // 녹음 시작
+    async startRecording() {
+      this.audioChunks = []; // 오디오 초기화
+      this.stream = await navigator.mediaDevices.getUserMedia({ audio: true });
+      this.mediaRecorder = new MediaRecorder(this.stream);
+      this.mediaRecorder.ondataavailable = (event) => {
+        this.audioChunks.push(event.data); // 녹음 데이터 저장
+      };
+      this.mediaRecorder.onstop = () => {
+        this.audioBlob = new Blob(this.audioChunks, { type: "audio/wav" });
+
+        /******************************/
+        // this.audioURL = URL.createObjectURL(this.audioBlob); // 오디오 URL 생성
+        // console.log('Audio URL:', this.audioURL);
+        /******************************/
+
+        console.log("Recorded Audio Blob:", this.audioBlob); // 콘솔에 Blob 확인
+        this.sendAudioToServer(); // 서버로 오디오 전송
+      };
+      this.mediaRecorder.start(); // 녹음 시작
+      this.isRecording = true; // 녹음 상태 변경
+    },
+
+    // 녹음 중지
+    stopRecording() {
+      this.mediaRecorder.stop(); // 녹음 중단
+
+      if (this.stream) {
+        this.stream.getTracks().forEach((track) => track.stop()); // 스트림의 모든 트랙 중지
+      }
+
+      this.isRecording = false; // 녹음 상태 변경
+    },
+
+    // 오디오 전송
+    async sendAudioToServer() {
+      const formData = new FormData();
+      formData.append("file", this.audioBlob, "recording.wav");
+      try {
+        const response = await axios.post("/api/speechToText.json", formData, {
+          headers: {
+            "Content-Type": "multipart/form-data",
+          },
+        });
+
+        this.transcription = response.data.trim().toLowerCase();
+        this.nowWord = this.nowWord.toLowerCase();
+
+        console.log("지금 단어: ", this.nowWord);
+        console.log("녹음 결과: ", this.transcription);
+
+        if (this.transcription === this.nowWord) {
+          this.$refs.speakText.innerText = "정답입니다! 잘했어요";
+        } else {
+          this.$refs.speakText.innerText = "다시 말해보세요!";
+        }
+      } catch (error) {
+        console.log("파일 전송 실패: ", error);
+      }
+    },
+
+    // 단어 리스트를 서버에서 받아와 items에 적용하는 메서드
+    async fetchWordList() {
+      try {
+        const response = await axios.post("/word/getWordsByBookId.json", {
+          wdBookId: this.wdBookId,
+        });
+
+        this.wordList = response.data;
+
+        const requests = this.wordList.map(async (word, index) => {
+          // fileRpath를 받아오기 위한 요청
+          const fileResponse = await axios.post("/file/find.json", {
+            file_mng_id: word.fileMngId,
+          });
+
+          // fileResponse.data.list에서 fileRpath 값을 추출하여 imgSrc에 설정
+          const fileRpath =
+            fileResponse.data.list.length > 0
+              ? fileResponse.data.list[0].fileRpath
+              : null;
+          const imgSrc = fileRpath
+            ? `http://165.229.169.113:9080/${fileRpath}`
+            : "";
+
+          return {
+            imgSrc1: `client/resources/img/img53_${6 + index}_35s.png`,
+            imgSrc2: `client/resources/img/img53_${1 + index}_35s.png`,
+            con: {
+              imgSrc, // fileRpath를 imgSrc에 설정
+              titleEm: word.wdNm.charAt(0), // 단어의 첫 글자
+              title: word.wdNm.slice(1), // 단어의 나머지 부분
+              boxText: "명",
+              subtitle: word.wdMnng, // 단어의 의미
+            },
+          };
+        });
+
+        // 모든 요청이 완료될 때까지 대기
+        this.items = await Promise.all(requests);
+
+        // items 리스트의 첫 번째 항목을 currentCon에 설정
+        if (this.items.length > 0) {
+          this.currentCon = this.items[0].con;
+          this.nowWord = this.currentCon.titleEm + this.currentCon.title;
+        }
+      } catch (error) {
+        console.error("단어 목록을 불러오는 중 오류 발생:", error);
+      }
+    },
+  },
+  watch: {
+    transcription: null, // 서버에서 받아온 텍스트 결과
+    currentCon: {
+      handler(newValue) {
+        // Update nowWord when currentCon changes
+        this.nowWord = newValue.titleEm + newValue.title;
+      },
+      deep: true, // Watch for deep changes in currentCon
+    },
+  },
+  mounted() {
+    // this.pageSetting();
+    this.fetchWordList();
+  },
+  beforeDestroy() {
+    if (this.intervalId) {
+      clearInterval(this.intervalId);
+    }
+  },
 };
 </script>
 
 <style scoped>
 .popTxt img {
-    position: absolute;
-    top: 0;
-    left: 0;
+  position: absolute;
+  top: 0;
+  left: 0;
 }
 
 .box23 {
-    display: flex;
-    align-items: center;
-    gap: 80px;
-    justify-content: center;
+  display: flex;
+  align-items: center;
+  gap: 80px;
+  justify-content: center;
 }
 
 .mic-btn {
-    cursor: pointer;
+  cursor: pointer;
 }
 
 .mic-btn.notRecording {
-    background-image: none;
-    cursor: pointer;
+  background-image: none;
+  cursor: pointer;
 }
 
 .speakText {
-    background-color: #fff8e9;
-    border: 0;
+  background-color: #fff8e9;
+  border: 0;
 }
 
 .speakText span {
-    font-size: 28px;
+  font-size: 28px;
 }
 
 .completeBtn {
-    margin-right: 100px;
-    background-color: #ffba08;
-    padding: 10px 30px;
-    border-radius: 10px;
-    font-size: 28px;
-    font-family: 'ONEMobilePOPOTF';
+  margin-right: 100px;
+  background-color: #ffba08;
+  padding: 10px 30px;
+  border-radius: 10px;
+  font-size: 28px;
+  font-family: "ONEMobilePOPOTF";
 }
 </style>
client/views/pages/main/Chapter/Chapter2_4.vue
--- client/views/pages/main/Chapter/Chapter2_4.vue
+++ client/views/pages/main/Chapter/Chapter2_4.vue
@@ -47,7 +47,7 @@
                 />
                 <div class="textbox">
                   <div style="height: 80%; line-height: 200px">
-                    <img :src="item.imgSrc" alt="" style="width: 120px;" />
+                    <img :src="item.imgSrc" alt="" style="width: 120px" />
                   </div>
                   <p class="subtitle3" style="height: 20%">{{ item.title }}</p>
                 </div>
@@ -90,20 +90,23 @@
       currentWdBkIndex: 0, // 현재 단어장 인덱스
       wdBookTypeIdState: "", // 이동할 페이지 타입 id
       wordBookType: "", // 이동할 페이지
+
+      seq: this.$store.getters.seqNum,
     };
   },
   methods: {
     pageSetting() {
       this.currentWdBkIndex = this.$store.getters.getCurrentWdBkIndex; // 현재 단어장 인덱스
       this.wdBookIdList = this.$store.getters.getWdBookIdList; // 단어컨텐츠의 단어장 id 리스트
-      this.wdBookId = this.$store.getters.getWdBookIdList[this.currentWdBkIndex] // 현재 단어장 콘텐츠 인덱스에 대한 단어장 id
+      this.wdBookId =
+        this.$store.getters.getWdBookIdList[this.currentWdBkIndex]; // 현재 단어장 콘텐츠 인덱스에 대한 단어장 id
 
       this.fetchWordList();
     },
-    
+
     async fetchWordList() {
       try {
-        const response = await axios.post('/word/getWordsByBookId.json', {
+        const response = await axios.post("/word/getWordsByBookId.json", {
           wdBookId: this.wdBookId,
         });
 
@@ -115,7 +118,10 @@
             file_mng_id: word.fileMngId,
           });
 
-          const fileRpath = fileResponse.data.list.length > 0 ? fileResponse.data.list[0].fileRpath : null;
+          const fileRpath =
+            fileResponse.data.list.length > 0
+              ? fileResponse.data.list[0].fileRpath
+              : null;
           console.log("각 단어의 fileRpath: ", fileRpath);
 
           // items 배열에 새로운 항목 추가
@@ -129,9 +135,8 @@
 
         // 모든 요청이 완료될 때까지 대기
         await Promise.all(requests);
-
       } catch (error) {
-        console.error('단어 목록을 불러오는 중 오류 발생:', error);
+        console.error("단어 목록을 불러오는 중 오류 발생:", error);
       }
     },
 
@@ -140,38 +145,39 @@
         alert("단어장 첫번째 페이지 입니다");
       } else {
         this.currentWdBkIndex--;
-        this.$store.dispatch('updateCurrentWdBkIndex', this.currentWdBkIndex);
+        this.$store.dispatch("updateCurrentWdBkIndex", this.currentWdBkIndex);
 
         try {
           const response = await axios.post("/wordbook/find.json", {
-            wdBookId: this.$store.getters.getWdBookIdList[this.currentWdBkIndex]
+            wdBookId:
+              this.$store.getters.getWdBookIdList[this.currentWdBkIndex],
           });
           this.wdBookTypeIdState = response.data.wdBookTypeId;
           console.log("이전 단어장 타입 id: ", this.wdBookTypeIdState);
 
           switch (this.wdBookTypeIdState) {
             case "1":
-                this.wordBookType = "Chapter2";
-                break;
+              this.wordBookType = "Chapter2";
+              break;
             case "2":
-                this.wordBookType = "Chapter2_3";
-                break;
+              this.wordBookType = "Chapter2_3";
+              break;
             case "3":
-                this.wordBookType = "Chapter2_2";
-                break;
+              this.wordBookType = "Chapter2_2";
+              break;
             case "4":
-                this.wordBookType = "Chapter2_9";
-                break;
+              this.wordBookType = "Chapter2_9";
+              break;
             case "5":
-                this.wordBookType = "Chapter2_4";
-                break;
+              this.wordBookType = "Chapter2_4";
+              break;
             default:
-                this.wordBookType = null;
+              this.wordBookType = null;
           }
-          
-          this.goToPage(this.wordBookType); 
+
+          this.goToPage(this.wordBookType);
         } catch (error) {
-          console.error('단어장 정보 불러오는 중 오류 발생:', error);
+          console.error("단어장 정보 불러오는 중 오류 발생:", error);
         }
       }
     },
@@ -179,48 +185,54 @@
     async goToNextPage() {
       if (this.currentWdBkIndex + 1 >= this.wdBookIdList.length) {
         alert("단어장 마지막 페이지 입니다");
+        this.complete();
       } else {
         this.currentWdBkIndex++;
-        this.$store.dispatch('updateCurrentWdBkIndex', this.currentWdBkIndex);
+        this.$store.dispatch("updateCurrentWdBkIndex", this.currentWdBkIndex);
 
         try {
           const response = await axios.post("/wordbook/find.json", {
-            wdBookId: this.$store.getters.getWdBookIdList[this.currentWdBkIndex]
+            wdBookId:
+              this.$store.getters.getWdBookIdList[this.currentWdBkIndex],
           });
           this.wdBookTypeIdState = response.data.wdBookTypeId;
           console.log("다음 단어장 타입 id: ", this.wdBookTypeIdState);
 
           switch (this.wdBookTypeIdState) {
             case "1":
-                this.wordBookType = "Chapter2";
-                break;
+              this.wordBookType = "Chapter2";
+              break;
             case "2":
-                this.wordBookType = "Chapter2_3";
-                break;
+              this.wordBookType = "Chapter2_3";
+              break;
             case "3":
-                this.wordBookType = "Chapter2_2";
-                break;
+              this.wordBookType = "Chapter2_2";
+              break;
             case "4":
-                this.wordBookType = "Chapter2_9";
-                break;
+              this.wordBookType = "Chapter2_9";
+              break;
             case "5":
-                this.wordBookType = "Chapter2_4";
-                break;
+              this.wordBookType = "Chapter2_4";
+              break;
             default:
-                this.wordBookType = null;
+              this.wordBookType = null;
           }
-          
-          this.goToPage(this.wordBookType); 
+
+          this.goToPage(this.wordBookType);
         } catch (error) {
-          console.error('단어장 정보 불러오는 중 오류 발생:', error);
+          console.error("단어장 정보 불러오는 중 오류 발생:", error);
         }
       }
     },
 
     complete() {
       const { unit_id, book_id } = this.$route.query;
-      this.$router.push({ name: 'Dashboard', query: { value: 2, unit_id, book_id } });
+      this.$router.push({
+        name: "Dashboard",
+        query: { value: this.seq, unit_id, book_id },
+      });
     },
+
     goToPage(page) {
       this.$router.push({ name: page });
     },
client/views/pages/main/Chapter/Chapter2_5.vue
--- client/views/pages/main/Chapter/Chapter2_5.vue
+++ client/views/pages/main/Chapter/Chapter2_5.vue
@@ -7,14 +7,15 @@
         </div>
       </router-link>
     </div>
-    <div class="title-box mb25 flex align-center mt40" style="
-    justify-content: space-between;
-">
+    <div
+      class="title-box mb25 flex align-center mt40"
+      style="justify-content: space-between"
+    >
       <div>
         <span class="title mr40">1. Hello WORLD</span>
         <span class="subtitle">my name is dd</span>
       </div>
-      <button class="completeBtn" @click="complete"> 학습 종료 </button>
+      <button class="completeBtn" @click="complete">학습 종료</button>
     </div>
     <div class="flex justify-between align-center">
       <div class="pre-btn" @click="previousProblem()">
@@ -38,7 +39,12 @@
           <!-- <p class="title1 mb40" style="color: #464749;">The sun rises in the east and sets in the west. It is very hot during summer.</p>
               <img src="../../../../resources/img/img65_37s.png" alt=""> -->
 
-          <img class="exampleImg" :src="imgUrl" reloadable="true" alt="example img" />
+          <img
+            class="exampleImg"
+            :src="imgUrl"
+            reloadable="true"
+            alt="example img"
+          />
 
           <!-- 정답 칸 -->
           <div class="dropGroup flex align-center justify-center mt30">
@@ -46,10 +52,22 @@
 
             <!-- 드롭 가능한 영역 -->
             <div class="dropContainer" id="targetContainer">
-              <div v-for="(slot, index) in answerLength" :key="index" class="dropSlot" @dragover.prevent
-                @drop="onDrop($event, index)">
-                <div class="dropSlot-inner" draggable="true" @dragstart="onDragStart($event, userAnswer[index], index)">
-                  <img src="../../../../resources/img/img64_37s.png" alt="answer slot" />
+              <div
+                v-for="(slot, index) in answerLength"
+                :key="index"
+                class="dropSlot"
+                @dragover.prevent
+                @drop="onDrop($event, index)"
+              >
+                <div
+                  class="dropSlot-inner"
+                  draggable="true"
+                  @dragstart="onDragStart($event, userAnswer[index], index)"
+                >
+                  <img
+                    src="../../../../resources/img/img64_37s.png"
+                    alt="answer slot"
+                  />
                   <div v-if="userAnswer[index]" class="dropped-char">
                     {{ userAnswer[index].toUpperCase() }}
                   </div>
@@ -62,9 +80,16 @@
 
           <!-- 드래그 가능한 버튼 -->
           <div class="dragGroup mt40" id="sourceContainer">
-            <button v-for="(char, index) in choiceCharacters" :key="index" draggable="true"
-              @dragstart="onDragStart($event, char)">
-              <img src="../../../../resources/img/img63_37s_2.png" alt="drag letter" />
+            <button
+              v-for="(char, index) in choiceCharacters"
+              :key="index"
+              draggable="true"
+              @dragstart="onDragStart($event, char)"
+            >
+              <img
+                src="../../../../resources/img/img63_37s_2.png"
+                alt="drag letter"
+              />
               <p>{{ char.toUpperCase() }}</p>
             </button>
           </div>
@@ -96,14 +121,18 @@
       prblm_id: [],
       unit_id: null,
       dataList: [],
+
+      seq: this.$store.getters.seqNum,
     };
   },
-  computed: {
-  },
+  computed: {},
   methods: {
     complete() {
       const { unit_id, book_id } = this.$route.query;
-      this.$router.push({ name: 'Dashboard', query: { value: 3, unit_id, book_id } });
+      this.$router.push({
+        name: "Dashboard",
+        query: { value: this.seq, unit_id, book_id },
+      });
     },
     goToPage(page) {
       this.$router.push({ name: page });
@@ -124,7 +153,7 @@
       if (this.userAnswer[index] === "") {
         this.userAnswer.splice(index, 1, this.draggedChar);
         const charIndex = this.choiceCharacters.indexOf(this.draggedChar);
-        console.log(charIndex)
+        console.log(charIndex);
         if (charIndex > -1) {
           this.choiceCharacters.splice(charIndex, 1); // 드래그한 문자를 choice에서 제거
         }
@@ -155,20 +184,24 @@
       const prblmId = this.currentLearningId.prblm_id;
 
       try {
-        const res = await axios.post("problem/problemInfo.json", {
-          prblmId: prblmId,
-        }, {
-          headers: {
-            "Content-Type": "application/json; charset=UTF-8",
+        const res = await axios.post(
+          "problem/problemInfo.json",
+          {
+            prblmId: prblmId,
           },
-        });
+          {
+            headers: {
+              "Content-Type": "application/json; charset=UTF-8",
+            },
+          }
+        );
 
         console.log("problem - response : ", res.data);
         this.dataList = res.data.problem;
         this.problemDetail = res.data.problemDetail[0];
         this.example = this.dataList.prblmExpln;
         this.answer = this.problemDetail.prblmDtlExpln;
-        this.choice = this.answer ? this.shuffleString(this.answer) : '';
+        this.choice = this.answer ? this.shuffleString(this.answer) : "";
         this.splitExample();
         this.initializeUserAnswer();
         this.choiceCharacters = this.choice.split("");
@@ -185,22 +218,26 @@
       }
     },
     shuffleString(string) {
-      const array = string.split('');
+      const array = string.split("");
       for (let i = array.length - 1; i > 0; i--) {
         const j = Math.floor(Math.random() * (i + 1));
         [array[i], array[j]] = [array[j], array[i]];
       }
-      return array.join('');
+      return array.join("");
     },
     async findFile(file_mng_id) {
       try {
-        const res = await axios.post("/file/find.json", {
-          file_mng_id: file_mng_id,
-        }, {
-          headers: {
-            "Content-Type": "application/json; charset=UTF-8",
+        const res = await axios.post(
+          "/file/find.json",
+          {
+            file_mng_id: file_mng_id,
           },
-        });
+          {
+            headers: {
+              "Content-Type": "application/json; charset=UTF-8",
+            },
+          }
+        );
         return res.data.list[0];
       } catch (error) {
         console.log("result - error : ", error);
@@ -211,21 +248,26 @@
       const problemData = {
         prblmImfo: this.currentLearningId,
         prblmNumber: this.currentProblemIndex,
-        prblmAns: this.selectedButton
-      }
-      this.$store.dispatch('saveProblemData', problemData);
-      if (this.currentProblemIndex < this.$store.state.currentLearningIds.length - 1) {
-        this.$store.dispatch('goToNextProblem');
+        prblmAns: this.selectedButton,
+      };
+      this.$store.dispatch("saveProblemData", problemData);
+      if (
+        this.currentProblemIndex <
+        this.$store.state.currentLearningIds.length - 1
+      ) {
+        this.$store.dispatch("goToNextProblem");
         this.handleProblemDetail(this.currentLearningId);
         this.goToPage(this.problemType);
       } else {
         // 마지막 문제면 이동
-        this.goToPage("Chapter4")
+        // this.goToPage("Chapter4");
+        alert("문제 학습 완료");
+        this.complete();
       }
     },
     previousProblem() {
       if (this.currentProblemIndex > 0) {
-        this.$store.dispatch('goToPreviousProblem');
+        this.$store.dispatch("goToPreviousProblem");
         this.handleProblemDetail(this.currentLearningId);
         this.goToPage(this.problemType);
       }
@@ -295,17 +337,17 @@
     },
     isPreviousButtonDisabled() {
       return this.currentProblemIndex === 0;
-    }
+    },
   },
   created() {
-    console.log('Current Learning ID:', this.currentLearningId);
-    console.log('Current Label:', this.currentLabel);
-    console.log('Current Problem Index:', this.currentProblemIndex);
+    console.log("Current Learning ID:", this.currentLearningId);
+    console.log("Current Label:", this.currentLabel);
+    console.log("Current Problem Index:", this.currentProblemIndex);
 
     // Fetch or process the current problem based on `currentLearningId`
   },
   mounted() {
-    this.getProblem()
+    this.getProblem();
   },
 };
 </script>
@@ -379,6 +421,6 @@
   padding: 10px 30px;
   border-radius: 10px;
   font-size: 28px;
-  font-family: 'ONEMobilePOPOTF';
+  font-family: "ONEMobilePOPOTF";
 }
 </style>
client/views/pages/main/Chapter/Chapter2_6.vue
--- client/views/pages/main/Chapter/Chapter2_6.vue
+++ client/views/pages/main/Chapter/Chapter2_6.vue
@@ -141,6 +141,8 @@
       prblm_id: [],
       problemData: [],
       answerArr: [],
+
+      seq: this.$store.getters.seqNum,
     };
   },
   methods: {
@@ -148,7 +150,7 @@
       const { unit_id, book_id } = this.$route.query;
       this.$router.push({
         name: "Dashboard",
-        query: { value: 3, unit_id, book_id },
+        query: { value: this.seq, unit_id, book_id },
       });
     },
     goToPage(page) {
@@ -236,7 +238,9 @@
         this.goToPage(this.problemType);
       } else {
         // 마지막 문제면 이동
-        this.goToPage("Chapter4");
+        // this.goToPage("Chapter4");
+        alert("문제 학습 완료");
+        this.complete();
       }
     },
     previousProblem() {
client/views/pages/main/Chapter/Chapter2_7.vue
--- client/views/pages/main/Chapter/Chapter2_7.vue
+++ client/views/pages/main/Chapter/Chapter2_7.vue
@@ -116,6 +116,8 @@
       problemData: [],
       problemArr: [],
       answerArr: [],
+
+      seq: this.$store.getters.seqNum,
     };
   },
   methods: {
@@ -123,7 +125,7 @@
       const { unit_id, book_id } = this.$route.query;
       this.$router.push({
         name: "Dashboard",
-        query: { value: 4, unit_id, book_id },
+        query: { value: this.seq, unit_id, book_id },
       });
     },
     goToPage(page) {
@@ -228,7 +230,9 @@
         this.goToPage(this.problemType);
       } else {
         // 마지막 문제면 이동
-        this.goToPage("Chapter4");
+        // this.goToPage("Chapter4");
+        alert("문제 학습 완료");
+        this.complete();
       }
     },
     previousProblem() {
client/views/pages/main/Chapter/Chapter2_8.vue
--- client/views/pages/main/Chapter/Chapter2_8.vue
+++ client/views/pages/main/Chapter/Chapter2_8.vue
@@ -118,6 +118,7 @@
       answerArr: [],
 
       // prblmArr: [],
+      seq: this.$store.getters.seqNum,
     };
   },
   methods: {
@@ -125,7 +126,7 @@
       const { unit_id, book_id } = this.$route.query;
       this.$router.push({
         name: "Dashboard",
-        query: { value: 11, unit_id, book_id },
+        query: { value: this.seq, unit_id, book_id },
       });
     },
     goToPage(page) {
@@ -199,7 +200,10 @@
         this.goToPage(this.problemType);
       } else {
         // 마지막 문제면 이동
-        this.goToPage("Chapter4");
+        // this.goToPage("Chapter4");
+        alert("문제 학습 완료");
+        this.complete();
+        // this.goToPage("Dashboard");
       }
     },
     previousProblem() {
client/views/pages/main/Chapter/Chapter2_9.vue
--- client/views/pages/main/Chapter/Chapter2_9.vue
+++ client/views/pages/main/Chapter/Chapter2_9.vue
@@ -45,14 +45,14 @@
               />
               <div class="vocaGroup">
                 <div
-                  v-for="(word) in wordList"
+                  v-for="word in wordList"
                   :key="word.wdId"
                   class="flex justify-between mb80 word-item"
                 >
                   <article class="flex align-center">
                     <div class="imgGroup mr30">
                       <img
-                        :src= word.fileRpath
+                        :src="word.fileRpath"
                         data-num="1"
                         class="ink"
                         style="width: 150px"
@@ -124,7 +124,7 @@
 </template>
 
 <script>
-import axios from 'axios';
+import axios from "axios";
 
 export default {
   data() {
@@ -137,17 +137,20 @@
       currentWdBkIndex: 0, // 현재 단어장 인덱스
       wdBookTypeIdState: "", // 이동할 페이지 타입 id
       wordBookType: "", // 이동할 페이지
+
+      seq: this.$store.getters.seqNum,
     };
   },
   methods: {
     pageSetting() {
       this.currentWdBkIndex = this.$store.getters.getCurrentWdBkIndex; // 현재 단어장 인덱스
       this.wdBookIdList = this.$store.getters.getWdBookIdList; // 단어컨텐츠의 단어장 id 리스트
-      this.wdBookId = this.$store.getters.getWdBookIdList[this.currentWdBkIndex] // 현재 단어장 콘텐츠 인덱스에 대한 단어장 id
+      this.wdBookId =
+        this.$store.getters.getWdBookIdList[this.currentWdBkIndex]; // 현재 단어장 콘텐츠 인덱스에 대한 단어장 id
 
       this.fetchWordList();
     },
-    
+
     async fetchWordList() {
       try {
         const response = await axios.post("/word/getWordsByBookId.json", {
@@ -162,7 +165,10 @@
             file_mng_id: word.fileMngId,
           });
 
-          const fileRpath = fileResponse.data.list.length > 0 ? fileResponse.data.list[0].fileRpath : null;
+          const fileRpath =
+            fileResponse.data.list.length > 0
+              ? fileResponse.data.list[0].fileRpath
+              : null;
           console.log("각 단어의 fileRpath: ", fileRpath);
 
           word.fileRpath = "http://165.229.169.113:9080/" + fileRpath; // fileRpath 값을 해당 객체에 추가
@@ -179,44 +185,44 @@
       }
     },
 
-
     async goToPrevPage() {
       if (this.currentWdBkIndex - 1 < 0) {
         alert("단어장 첫번째 페이지 입니다");
       } else {
         this.currentWdBkIndex--;
-        this.$store.dispatch('updateCurrentWdBkIndex', this.currentWdBkIndex);
+        this.$store.dispatch("updateCurrentWdBkIndex", this.currentWdBkIndex);
 
         try {
           const response = await axios.post("/wordbook/find.json", {
-            wdBookId: this.$store.getters.getWdBookIdList[this.currentWdBkIndex]
+            wdBookId:
+              this.$store.getters.getWdBookIdList[this.currentWdBkIndex],
           });
           this.wdBookTypeIdState = response.data.wdBookTypeId;
           console.log("이전 단어장 타입 id: ", this.wdBookTypeIdState);
 
           switch (this.wdBookTypeIdState) {
             case "1":
-                this.wordBookType = "Chapter2";
-                break;
+              this.wordBookType = "Chapter2";
+              break;
             case "2":
-                this.wordBookType = "Chapter2_3";
-                break;
+              this.wordBookType = "Chapter2_3";
+              break;
             case "3":
-                this.wordBookType = "Chapter2_2";
-                break;
+              this.wordBookType = "Chapter2_2";
+              break;
             case "4":
-                this.wordBookType = "Chapter2_9";
-                break;
+              this.wordBookType = "Chapter2_9";
+              break;
             case "5":
-                this.wordBookType = "Chapter2_4";
-                break;
+              this.wordBookType = "Chapter2_4";
+              break;
             default:
-                this.wordBookType = null;
+              this.wordBookType = null;
           }
-          
-          this.goToPage(this.wordBookType); 
+
+          this.goToPage(this.wordBookType);
         } catch (error) {
-          console.error('단어장 정보 불러오는 중 오류 발생:', error);
+          console.error("단어장 정보 불러오는 중 오류 발생:", error);
         }
       }
     },
@@ -224,47 +230,52 @@
     async goToNextPage() {
       if (this.currentWdBkIndex + 1 >= this.wdBookIdList.length) {
         alert("단어장 마지막 페이지 입니다");
+        this.complete();
       } else {
         this.currentWdBkIndex++;
-        this.$store.dispatch('updateCurrentWdBkIndex', this.currentWdBkIndex);
+        this.$store.dispatch("updateCurrentWdBkIndex", this.currentWdBkIndex);
 
         try {
           const response = await axios.post("/wordbook/find.json", {
-            wdBookId: this.$store.getters.getWdBookIdList[this.currentWdBkIndex]
+            wdBookId:
+              this.$store.getters.getWdBookIdList[this.currentWdBkIndex],
           });
           this.wdBookTypeIdState = response.data.wdBookTypeId;
           console.log("다음 단어장 타입 id: ", this.wdBookTypeIdState);
 
           switch (this.wdBookTypeIdState) {
             case "1":
-                this.wordBookType = "Chapter2";
-                break;
+              this.wordBookType = "Chapter2";
+              break;
             case "2":
-                this.wordBookType = "Chapter2_3";
-                break;
+              this.wordBookType = "Chapter2_3";
+              break;
             case "3":
-                this.wordBookType = "Chapter2_2";
-                break;
+              this.wordBookType = "Chapter2_2";
+              break;
             case "4":
-                this.wordBookType = "Chapter2_9";
-                break;
+              this.wordBookType = "Chapter2_9";
+              break;
             case "5":
-                this.wordBookType = "Chapter2_4";
-                break;
+              this.wordBookType = "Chapter2_4";
+              break;
             default:
-                this.wordBookType = null;
+              this.wordBookType = null;
           }
-          
-          this.goToPage(this.wordBookType); 
+
+          this.goToPage(this.wordBookType);
         } catch (error) {
-          console.error('단어장 정보 불러오는 중 오류 발생:', error);
+          console.error("단어장 정보 불러오는 중 오류 발생:", error);
         }
       }
     },
 
     complete() {
       const { unit_id, book_id } = this.$route.query;
-      this.$router.push({ name: 'Dashboard', query: { value: 2, unit_id, book_id } });
+      this.$router.push({
+        name: "Dashboard",
+        query: { value: this.seq, unit_id, book_id },
+      });
     },
     goToPage(page) {
       this.$router.push({ name: page });
client/views/pages/main/Dashboard.vue
--- client/views/pages/main/Dashboard.vue
+++ client/views/pages/main/Dashboard.vue
@@ -1,219 +1,626 @@
 <template>
-    <p class="title1" v-if="state === 'finish'">오늘 공부를 다했어요! 너무 고생했어요!</p>
-    <p class="title1" v-else-if="state === 'notRegistered'">지금은 학습 루트가 등록이 안됐어요! 학습 일정에서 학습루트를 등록해볼까요?</p>
-    <p class="title1" v-else-if="state === 'noProblem'">교재에 등록된 문제가 없습니다.</p>
-    <div v-else class="main">
-        <div class="race-wrap">
-            <div class="title-box">
-                <p class="title" style="margin-top: 7rem">{{ titleUnitName }}</p>
-                <p class="subtitle">{{ titleBookName }}</p>
-            </div>
-            <div class="race-box">
-                <div class="rabbit-start"><img src="../../../resources/img/img09_s.png" alt="" :style="{ display: rabbitPos[0] ? 'block' : 'none' }" /></div>
-                <div class="rcon flex justify-end mb5">
-                    <div class="race-btn" @click="[storeLearningId(labeledItems[0])]">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt="" :style="{ display: rabbitPos[1] ? 'block' : 'none' }" /></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="1">
-                            <img :src="labeledItems[0].label.length >= 4 ? item.imgSrc3 : item.imgSrc1" :style="{ display: !rabbitCompl[1] ? 'block' : 'none' }" />
-                            <img :src="labeledItems[0].label.length >= 4 ? item.imgSrc4 : item.imgSrc2" :style="{ display: rabbitCompl[1] ? 'block' : 'none' }" />
-                        </button>
-                        <p>{{ labeledItems[0].label }}</p>
-                    </div>
-                    <div class="race-btn" @click="[storeLearningId(labeledItems[1])]">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt="" :style="{ display: rabbitPos[2] ? 'block' : 'none' }" /></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="2">
-                            <img :src="labeledItems[1].label.length >= 4 ? item.imgSrc3 : item.imgSrc1" :style="{ display: !rabbitCompl[2] ? 'block' : 'none' }" />
-                            <img :src="labeledItems[1].label.length >= 4 ? item.imgSrc4 : item.imgSrc2" :style="{ display: rabbitCompl[2] ? 'block' : 'none' }" />
-                        </button>
-                        <p>{{ labeledItems[1].label }}</p>
-                    </div>
-                </div>
-                <div class="lcon flex justify-between mb5">
-                    <div class="race-btn" @click="[storeLearningId(labeledItems[6])]">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt="" :style="{ display: rabbitPos[7] ? 'block' : 'none' }" /></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="7">
-                            <img :src="labeledItems[6].label.length >= 4 ? item.imgSrc3 : item.imgSrc1" :style="{ display: !rabbitCompl[7] ? 'block' : 'none' }" />
-                            <img :src="labeledItems[6].label.length >= 4 ? item.imgSrc4 : item.imgSrc2" :style="{ display: rabbitCompl[7] ? 'block' : 'none' }" />
-                        </button>
-                        <p>{{ labeledItems[6].label }}</p>
-                    </div>
-                    <div class="race-btn" @click="[goToPage('Chapter2_8'), storeLearningId(labeledItems[5].learning_id)]">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt="" :style="{ display: rabbitPos[6] ? 'block' : 'none' }" /></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="6">
-                            <img :src="labeledItems[5].label.length >= 4 ? item.imgSrc3 : item.imgSrc1" :style="{ display: !rabbitCompl[6] ? 'block' : 'none' }" />
-                            <img :src="labeledItems[5].label.length >= 4 ? item.imgSrc4 : item.imgSrc2" :style="{ display: rabbitCompl[6] ? 'block' : 'none' }" />
-                        </button>
-                        <p>{{ labeledItems[5].label }}</p>
-                    </div>
-                    <div class="race-btn" @click="[storeLearningId(labeledItems[4])]">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt="" :style="{ display: rabbitPos[5] ? 'block' : 'none' }" /></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="5">
-                            <img :src="labeledItems[4].label.length >= 4 ? item.imgSrc3 : item.imgSrc1" :style="{ display: !rabbitCompl[5] ? 'block' : 'none' }" />
-                            <img :src="labeledItems[4].label.length >= 4 ? item.imgSrc4 : item.imgSrc2" :style="{ display: rabbitCompl[5] ? 'block' : 'none' }" />
-                        </button>
-                        <p>{{ labeledItems[4].label }}</p>
-                    </div>
-                    <div class="race-btn" @click="[storeLearningId(labeledItems[3])]">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt="" :style="{ display: rabbitPos[4] ? 'block' : 'none' }" /></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="4">
-                            <img :src="labeledItems[3].label.length >= 4 ? item.imgSrc3 : item.imgSrc1" :style="{ display: !rabbitCompl[4] ? 'block' : 'none' }" />
-                            <img :src="labeledItems[3].label.length >= 4 ? item.imgSrc4 : item.imgSrc2" :style="{ display: rabbitCompl[4] ? 'block' : 'none' }" />
-                        </button>
-                        <p>{{ labeledItems[3].label }}</p>
-                    </div>
-                    <div class="race-btn" @click="[storeLearningId(labeledItems[2])]">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt="" :style="{ display: rabbitPos[3] ? 'block' : 'none' }" /></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="3">
-                            <img :src="labeledItems[2].label.length >= 4 ? item.imgSrc3 : item.imgSrc1" :style="{ display: !rabbitCompl[3] ? 'block' : 'none' }" />
-                            <img :src="labeledItems[2].label.length >= 4 ? item.imgSrc4 : item.imgSrc2" :style="{ display: rabbitCompl[3] ? 'block' : 'none' }" />
-                        </button>
-                        <p>{{ labeledItems[2].label }}</p>
-                    </div>
-                </div>
-                <div class="rcon flex">
-                    <div class="race-btn" @click="[goToPage('Chapter8'), storeLearningId(labeledItems[7].learning_id)]">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt="" :style="{ display: rabbitPos[8] ? 'block' : 'none' }" /></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="8">
-                            <img :src="labeledItems[7].label.length >= 4 ? item.imgSrc3 : item.imgSrc1" :style="{ display: !rabbitCompl[8] ? 'block' : 'none' }" />
-                            <img :src="labeledItems[7].label.length >= 4 ? item.imgSrc4 : item.imgSrc2" :style="{ display: rabbitCompl[8] ? 'block' : 'none' }" />
-                        </button>
-                        <p class="long">{{ labeledItems[7].label }}</p>
-                    </div>
-                    <div class="race-btn" @click="[storeLearningId(labeledItems[8])]">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt="" :style="{ display: rabbitPos[9] ? 'block' : 'none' }" /></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="9">
-                            <img :src="labeledItems[8].label.length >= 4 ? item.imgSrc3 : item.imgSrc1" :style="{ display: !rabbitCompl[9] ? 'block' : 'none' }" />
-                            <img :src="labeledItems[8].label.length >= 4 ? item.imgSrc4 : item.imgSrc2" :style="{ display: rabbitCompl[9] ? 'block' : 'none' }" />
-                        </button>
-                        <p>{{ labeledItems[8].label }}</p>
-                    </div>
-                    <div class="race-btn" @click="[goToPage('Chapter10'), storeLearningId(labeledItems[9].learning_id)]">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt="" :style="{ display: rabbitPos[10] ? 'block' : 'none' }" /></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="10">
-                            <img :src="labeledItems[9].label.length >= 4 ? item.imgSrc3 : item.imgSrc1" :style="{ display: !rabbitCompl[10] ? 'block' : 'none' }" />
-                            <img :src="labeledItems[9].label.length >= 4 ? item.imgSrc4 : item.imgSrc2" :style="{ display: rabbitCompl[10] ? 'block' : 'none' }" />
-                        </button>
-                        <p>{{ labeledItems[9].label }}</p>
-                    </div>
-
-                    <div class="race-btn" @click="[goToPage('Chapter2_8'), storeLearningId(labeledItems[10].learning_id)]">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt="" :style="{ display: rabbitPos[11] ? 'block' : 'none' }" /></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImageAndShowPopup(index, '11')" data-num="11">
-                            <img :src="labeledItems[10].label.length >= 4 ? item.imgSrc3 : item.imgSrc1" :style="{ display: !rabbitCompl[11] ? 'block' : 'none' }" />
-                            <img :src="labeledItems[10].label.length >= 4 ? item.imgSrc4 : item.imgSrc2" :style="{ display: rabbitCompl[11] ? 'block' : 'none' }" />
-                        </button>
-                        <p class="long">{{ labeledItems[10].label }}</p>
-                    </div>
-                </div>
-                <div class="race-btn">
-                    <div class="rabbit-running" style="display: flex">
-                        <img class="rabbit-end" src="../../../resources/img/img138_72s.png" alt="" :style="{ display: rabbitEnd ? 'block' : 'none' }" />
-                        <img class="fireworks-end" src="../../../resources/img/fireworks.gif" alt="" :style="{ display: rabbitEnd ? 'block' : 'none' }" />
-                    </div>
-                </div>
-            </div>
-
-            <!-- 팝업 -->
-            <div v-show="searchOpen2" class="popup-wrap">
-                <div class="popup-box">
-                    <button type="button" class="popup-close-btn" style="position: absolute; top: 10px; right: 10px" @click="closeModal">
-                        <svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon>
-                    </button>
-
-                    <div class="mb30 text-ct">
-                        <p class="title1 mb20">1단원이 끝났습니다!</p>
-                        <p class="title1"><em class="yellow">기념사진</em>을 촬영하러 가요</p>
-                    </div>
-                    <div class="flex justify-center">
-                        <button type="button" title="사진촬영" class="new-btn" @click="openCameraModal">사진 촬영</button>
-                    </div>
-                </div>
-            </div>
-            <!-- 카메라 모달 -->
-            <article v-show="showCameraModal" class="popup-wrap">
-                <div class="popup-box" style="top: 500px; left: 500px">
-                    <div class="flex mb10 justify-between">
-                        <p class="popup-title">사진 촬영</p>
-                        <button type="button" class="popup-close-btn" @click="closeModal">
-                            <svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon>
-                        </button>
-                    </div>
-                    <div class="box">
-                        <div style="width: 100%">
-                            <div id="container" ref="container">
-                                <video v-if="!photoTaken" autoplay="true" ref="modalVideoElement" class="mirrored" @canplay="onVideoLoaded" style="position: absolute; height: 100%"></video>
-                                <img src="../../../resources/img/camera-rabbit.png" class="camera-rabbit" style="position: absolute" />
-                                <canvas ref="canvas" style="pointer-events: none"></canvas>
-                            </div>
-                        </div>
-                    </div>
-                    <div class="flex justify-center mt20">
-                        <button class="new-btn" @click="takePhoto">사진 찍기</button>
-                    </div>
-                </div>
-            </article>
+  <p class="title1" v-if="state === 'finish'">
+    오늘 공부를 다했어요! 너무 고생했어요!
+  </p>
+  <p class="title1" v-else-if="state === 'notRegistered'">
+    지금은 학습 루트가 등록이 안됐어요! 학습 일정에서 학습루트를 등록해볼까요?
+  </p>
+  <p class="title1" v-else-if="state === 'noProblem'">
+    교재에 등록된 문제가 없습니다.
+  </p>
+  <div v-else class="main">
+    <div class="race-wrap">
+      <div class="title-box">
+        <p class="title" style="margin-top: 7rem">{{ titleUnitName }}</p>
+        <p class="subtitle">{{ titleBookName }}</p>
+      </div>
+      <div class="race-box">
+        <div class="rabbit-start">
+          <img
+            src="../../../resources/img/img09_s.png"
+            alt=""
+            :style="{ display: rabbitPos[0] ? 'block' : 'none' }"
+          />
         </div>
-
-        <div class="complete-wrap myphoto">
-            <button class="login-btn mt10" type="submit" style="width: 100%" @click="finishSchedule">
-                <img src="../../../resources/img/btn07_s.png" alt="" style="width: 100%; height: 100px" />
-                <p>학습 종료하기</p>
+        <div class="rcon flex justify-end mb5">
+          <div class="race-btn" @click="[storeLearningId(labeledItems[0])]">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[1] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="1"
+            >
+              <img
+                :src="
+                  labeledItems[0].label.length >= 4
+                    ? item.imgSrc3
+                    : item.imgSrc1
+                "
+                :style="{ display: !rabbitCompl[1] ? 'block' : 'none' }"
+              />
+              <img
+                :src="
+                  labeledItems[0].label.length >= 4
+                    ? item.imgSrc4
+                    : item.imgSrc2
+                "
+                :style="{ display: rabbitCompl[1] ? 'block' : 'none' }"
+              />
             </button>
-            <h2 class="mb40 mt10">이 단원을 끝낸 친구들</h2>
-
-            <article class="flex-column">
-                <div class="flex-row">
-                    <div class="flex" style="gap: 5px; flex-wrap: wrap">
-                        <div v-for="(image, index) in images" :key="image.fileId" @click="buttonSearch(image)" class="photo" style="margin-bottom: 5px">
-                            <img :src="image.url" :alt="image.fileNm" reloadable="true" style="height: 100%" />
-                        </div>
-                    </div>
-                </div>
-            </article>
-            <article class="popup-wrap" v-show="searchOpen">
-                <div class="popup-box" style="top: 50%">
-                    <div class="flex mb10 justify-between">
-                        <button type="button" class="popup-close-btn" @click="closeModal">
-                            <svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon>
-                        </button>
-                    </div>
-                    <div class="box">
-                        <div style="width: 910px; height: 680px">
-                            <img :src="selectedImage.image" alt="Image" @error="onImageError" reloadable="true" />
-                        </div>
-                    </div>
-                    <div class="flex justify-between mt20">
-                        <div class="text flex">
-                            <p class="title2 date ml30">{{ selectedImage.date }}</p>
-                            <span class="title1 ml30"
-                                >{{ selectedImage.unit }}을 마친 <em class="yellow">{{ selectedImage.name }}</em
-                                >친구</span
-                            >
-                        </div>
-                        <div class="title2 flex align-center" style="gap: 10px">
-                            <svg-icon
-                                v-if="!isHeartFilled"
-                                type="mdi"
-                                :path="mdiHeartOutline"
-                                @click="toggleHeart(selectedImage.heart, selectedImage.fileMngId)"
-                                style="color: #ffba08; cursor: pointer"
-                            ></svg-icon>
-                            <svg-icon
-                                v-if="isHeartFilled"
-                                type="mdi"
-                                :path="mdiHeart"
-                                @click="toggleHeart(selectedImage.heart, selectedImage.fileMngId)"
-                                style="color: #ffba08; cursor: pointer"
-                            ></svg-icon>
-                            <p>
-                                <em class="yellow">{{ selectedImage.heart }}</em>
-                            </p>
-                        </div>
-                    </div>
-                </div>
-            </article>
+            <p>{{ labeledItems[0].label }}</p>
+          </div>
+          <div class="race-btn" @click="[storeLearningId(labeledItems[1])]">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[2] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="2"
+            >
+              <img
+                :src="
+                  labeledItems[1].label.length >= 4
+                    ? item.imgSrc3
+                    : item.imgSrc1
+                "
+                :style="{ display: !rabbitCompl[2] ? 'block' : 'none' }"
+              />
+              <img
+                :src="
+                  labeledItems[1].label.length >= 4
+                    ? item.imgSrc4
+                    : item.imgSrc2
+                "
+                :style="{ display: rabbitCompl[2] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[1].label }}</p>
+          </div>
         </div>
+        <div class="lcon flex justify-between mb5">
+          <div class="race-btn" @click="[storeLearningId(labeledItems[6])]">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[7] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="7"
+            >
+              <img
+                :src="
+                  labeledItems[6].label.length >= 4
+                    ? item.imgSrc3
+                    : item.imgSrc1
+                "
+                :style="{ display: !rabbitCompl[7] ? 'block' : 'none' }"
+              />
+              <img
+                :src="
+                  labeledItems[6].label.length >= 4
+                    ? item.imgSrc4
+                    : item.imgSrc2
+                "
+                :style="{ display: rabbitCompl[7] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[6].label }}</p>
+          </div>
+          <div
+            class="race-btn"
+            @click="
+              [
+                goToPage('Chapter2_8'),
+                storeLearningId(labeledItems[5].learning_id),
+              ]
+            "
+          >
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[6] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="6"
+            >
+              <img
+                :src="
+                  labeledItems[5].label.length >= 4
+                    ? item.imgSrc3
+                    : item.imgSrc1
+                "
+                :style="{ display: !rabbitCompl[6] ? 'block' : 'none' }"
+              />
+              <img
+                :src="
+                  labeledItems[5].label.length >= 4
+                    ? item.imgSrc4
+                    : item.imgSrc2
+                "
+                :style="{ display: rabbitCompl[6] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[5].label }}</p>
+          </div>
+          <div class="race-btn" @click="[storeLearningId(labeledItems[4])]">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[5] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="5"
+            >
+              <img
+                :src="
+                  labeledItems[4].label.length >= 4
+                    ? item.imgSrc3
+                    : item.imgSrc1
+                "
+                :style="{ display: !rabbitCompl[5] ? 'block' : 'none' }"
+              />
+              <img
+                :src="
+                  labeledItems[4].label.length >= 4
+                    ? item.imgSrc4
+                    : item.imgSrc2
+                "
+                :style="{ display: rabbitCompl[5] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[4].label }}</p>
+          </div>
+          <div class="race-btn" @click="[storeLearningId(labeledItems[3])]">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[4] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="4"
+            >
+              <img
+                :src="
+                  labeledItems[3].label.length >= 4
+                    ? item.imgSrc3
+                    : item.imgSrc1
+                "
+                :style="{ display: !rabbitCompl[4] ? 'block' : 'none' }"
+              />
+              <img
+                :src="
+                  labeledItems[3].label.length >= 4
+                    ? item.imgSrc4
+                    : item.imgSrc2
+                "
+                :style="{ display: rabbitCompl[4] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[3].label }}</p>
+          </div>
+          <div class="race-btn" @click="[storeLearningId(labeledItems[2])]">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[3] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="3"
+            >
+              <img
+                :src="
+                  labeledItems[2].label.length >= 4
+                    ? item.imgSrc3
+                    : item.imgSrc1
+                "
+                :style="{ display: !rabbitCompl[3] ? 'block' : 'none' }"
+              />
+              <img
+                :src="
+                  labeledItems[2].label.length >= 4
+                    ? item.imgSrc4
+                    : item.imgSrc2
+                "
+                :style="{ display: rabbitCompl[3] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[2].label }}</p>
+          </div>
+        </div>
+        <div class="rcon flex">
+          <div
+            class="race-btn"
+            @click="
+              [
+                goToPage('Chapter8'),
+                storeLearningId(labeledItems[7].learning_id),
+              ]
+            "
+          >
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[8] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="8"
+            >
+              <img
+                :src="
+                  labeledItems[7].label.length >= 4
+                    ? item.imgSrc3
+                    : item.imgSrc1
+                "
+                :style="{ display: !rabbitCompl[8] ? 'block' : 'none' }"
+              />
+              <img
+                :src="
+                  labeledItems[7].label.length >= 4
+                    ? item.imgSrc4
+                    : item.imgSrc2
+                "
+                :style="{ display: rabbitCompl[8] ? 'block' : 'none' }"
+              />
+            </button>
+            <p class="long">{{ labeledItems[7].label }}</p>
+          </div>
+          <div class="race-btn" @click="[storeLearningId(labeledItems[8])]">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[9] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="9"
+            >
+              <img
+                :src="
+                  labeledItems[8].label.length >= 4
+                    ? item.imgSrc3
+                    : item.imgSrc1
+                "
+                :style="{ display: !rabbitCompl[9] ? 'block' : 'none' }"
+              />
+              <img
+                :src="
+                  labeledItems[8].label.length >= 4
+                    ? item.imgSrc4
+                    : item.imgSrc2
+                "
+                :style="{ display: rabbitCompl[9] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[8].label }}</p>
+          </div>
+          <div
+            class="race-btn"
+            @click="
+              [
+                goToPage('Chapter10'),
+                storeLearningId(labeledItems[9].learning_id),
+              ]
+            "
+          >
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[10] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="10"
+            >
+              <img
+                :src="
+                  labeledItems[9].label.length >= 4
+                    ? item.imgSrc3
+                    : item.imgSrc1
+                "
+                :style="{ display: !rabbitCompl[10] ? 'block' : 'none' }"
+              />
+              <img
+                :src="
+                  labeledItems[9].label.length >= 4
+                    ? item.imgSrc4
+                    : item.imgSrc2
+                "
+                :style="{ display: rabbitCompl[10] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[9].label }}</p>
+          </div>
+
+          <div
+            class="race-btn"
+            @click="
+              [
+                goToPage('Chapter2_8'),
+                storeLearningId(labeledItems[10].learning_id),
+              ]
+            "
+          >
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[11] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImageAndShowPopup(index, '11')"
+              data-num="11"
+            >
+              <img
+                :src="
+                  labeledItems[10].label.length >= 4
+                    ? item.imgSrc3
+                    : item.imgSrc1
+                "
+                :style="{ display: !rabbitCompl[11] ? 'block' : 'none' }"
+              />
+              <img
+                :src="
+                  labeledItems[10].label.length >= 4
+                    ? item.imgSrc4
+                    : item.imgSrc2
+                "
+                :style="{ display: rabbitCompl[11] ? 'block' : 'none' }"
+              />
+            </button>
+            <p class="long">{{ labeledItems[10].label }}</p>
+          </div>
+        </div>
+        <div class="race-btn">
+          <div class="rabbit-running" style="display: flex">
+            <img
+              class="rabbit-end"
+              src="../../../resources/img/img138_72s.png"
+              alt=""
+              :style="{ display: rabbitEnd ? 'block' : 'none' }"
+            />
+            <img
+              class="fireworks-end"
+              src="../../../resources/img/fireworks.gif"
+              alt=""
+              :style="{ display: rabbitEnd ? 'block' : 'none' }"
+            />
+          </div>
+        </div>
+      </div>
+
+      <!-- 팝업 -->
+      <div v-show="searchOpen2" class="popup-wrap">
+        <div class="popup-box">
+          <button
+            type="button"
+            class="popup-close-btn"
+            style="position: absolute; top: 10px; right: 10px"
+            @click="closeModal"
+          >
+            <svg-icon
+              type="mdi"
+              :path="mdiWindowClose"
+              class="close-btn"
+            ></svg-icon>
+          </button>
+
+          <div class="mb30 text-ct">
+            <p class="title1 mb20">1단원이 끝났습니다!</p>
+            <p class="title1">
+              <em class="yellow">기념사진</em>을 촬영하러 가요
+            </p>
+          </div>
+          <div class="flex justify-center">
+            <button
+              type="button"
+              title="사진촬영"
+              class="new-btn"
+              @click="openCameraModal"
+            >
+              사진 촬영
+            </button>
+          </div>
+        </div>
+      </div>
+      <!-- 카메라 모달 -->
+      <article v-show="showCameraModal" class="popup-wrap">
+        <div class="popup-box" style="top: 500px; left: 500px">
+          <div class="flex mb10 justify-between">
+            <p class="popup-title">사진 촬영</p>
+            <button type="button" class="popup-close-btn" @click="closeModal">
+              <svg-icon
+                type="mdi"
+                :path="mdiWindowClose"
+                class="close-btn"
+              ></svg-icon>
+            </button>
+          </div>
+          <div class="box">
+            <div style="width: 100%">
+              <div id="container" ref="container">
+                <video
+                  v-if="!photoTaken"
+                  autoplay="true"
+                  ref="modalVideoElement"
+                  class="mirrored"
+                  @canplay="onVideoLoaded"
+                  style="position: absolute; height: 100%"
+                ></video>
+                <img
+                  src="../../../resources/img/camera-rabbit.png"
+                  class="camera-rabbit"
+                  style="position: absolute"
+                />
+                <canvas ref="canvas" style="pointer-events: none"></canvas>
+              </div>
+            </div>
+          </div>
+          <div class="flex justify-center mt20">
+            <button class="new-btn" @click="takePhoto">사진 찍기</button>
+          </div>
+        </div>
+      </article>
     </div>
+
+    <div class="complete-wrap myphoto">
+      <button
+        class="login-btn mt10"
+        type="submit"
+        style="width: 100%"
+        @click="finishSchedule"
+      >
+        <img
+          src="../../../resources/img/btn07_s.png"
+          alt=""
+          style="width: 100%; height: 100px"
+        />
+        <p>학습 종료하기</p>
+      </button>
+      <h2 class="mb40 mt10">이 단원을 끝낸 친구들</h2>
+
+      <article class="flex-column">
+        <div class="flex-row">
+          <div class="flex" style="gap: 5px; flex-wrap: wrap">
+            <div
+              v-for="(image, index) in images"
+              :key="image.fileId"
+              @click="buttonSearch(image)"
+              class="photo"
+              style="margin-bottom: 5px"
+            >
+              <img
+                :src="image.url"
+                :alt="image.fileNm"
+                reloadable="true"
+                style="height: 100%"
+              />
+            </div>
+          </div>
+        </div>
+      </article>
+      <article class="popup-wrap" v-show="searchOpen">
+        <div class="popup-box" style="top: 50%">
+          <div class="flex mb10 justify-between">
+            <button type="button" class="popup-close-btn" @click="closeModal">
+              <svg-icon
+                type="mdi"
+                :path="mdiWindowClose"
+                class="close-btn"
+              ></svg-icon>
+            </button>
+          </div>
+          <div class="box">
+            <div style="width: 910px; height: 680px">
+              <img
+                :src="selectedImage.image"
+                alt="Image"
+                @error="onImageError"
+                reloadable="true"
+              />
+            </div>
+          </div>
+          <div class="flex justify-between mt20">
+            <div class="text flex">
+              <p class="title2 date ml30">{{ selectedImage.date }}</p>
+              <span class="title1 ml30"
+                >{{ selectedImage.unit }}을 마친
+                <em class="yellow">{{ selectedImage.name }}</em
+                >친구</span
+              >
+            </div>
+            <div class="title2 flex align-center" style="gap: 10px">
+              <svg-icon
+                v-if="!isHeartFilled"
+                type="mdi"
+                :path="mdiHeartOutline"
+                @click="
+                  toggleHeart(selectedImage.heart, selectedImage.fileMngId)
+                "
+                style="color: #ffba08; cursor: pointer"
+              ></svg-icon>
+              <svg-icon
+                v-if="isHeartFilled"
+                type="mdi"
+                :path="mdiHeart"
+                @click="
+                  toggleHeart(selectedImage.heart, selectedImage.fileMngId)
+                "
+                style="color: #ffba08; cursor: pointer"
+              ></svg-icon>
+              <p>
+                <em class="yellow">{{ selectedImage.heart }}</em>
+              </p>
+            </div>
+          </div>
+        </div>
+      </article>
+    </div>
+  </div>
 </template>
 
 <script>
@@ -227,726 +634,781 @@
 import { mapActions } from "vuex";
 
 export default {
-    data() {
-        return {
-            items: [
-                {
-                    imgSrc1: "client/resources/img/img11_1_s.png",
-                    imgSrc2: "client/resources/img/img12_1_s.png",
-                    imgSrc3: "client/resources/img/img11_2_s.png",
-                    imgSrc4: "client/resources/img/img12_2_s.png",
-                    isSecondImageVisible: false,
-                },
-            ],
-            mdiMagnify: mdiMagnify,
-            mdiWindowClose: mdiWindowClose,
-            mdiHeart: mdiHeart,
-            mdiHeartOutline: mdiHeartOutline,
-            showModal: false,
-            searchOpen: false, // 사진 상세보기 모달창
-            searchOpen2: false, // 단원 마친 후, 사진 촬영 여부 선택 모달창
-            showCameraModal: false, // 카메라 모달창
-            photoTaken: false,
-            photo: null, //캡쳐 사진
-            stream: null,
+  data() {
+    return {
+      items: [
+        {
+          imgSrc1: "client/resources/img/img11_1_s.png",
+          imgSrc2: "client/resources/img/img12_1_s.png",
+          imgSrc3: "client/resources/img/img11_2_s.png",
+          imgSrc4: "client/resources/img/img12_2_s.png",
+          isSecondImageVisible: false,
+        },
+      ],
+      mdiMagnify: mdiMagnify,
+      mdiWindowClose: mdiWindowClose,
+      mdiHeart: mdiHeart,
+      mdiHeartOutline: mdiHeartOutline,
+      showModal: false,
+      searchOpen: false, // 사진 상세보기 모달창
+      searchOpen2: false, // 단원 마친 후, 사진 촬영 여부 선택 모달창
+      showCameraModal: false, // 카메라 모달창
+      photoTaken: false,
+      photo: null, //캡쳐 사진
+      stream: null,
 
-            roadmapData: [],
-            labeledItems: [],
+      roadmapData: [],
+      labeledItems: [],
 
-            problemCounter: 0,
-            wordCounter: 0,
-            textCounter: 0,
-            evalCounter: 0,
-            book_id: null,
-            unit_id: null,
+      problemCounter: 0,
+      wordCounter: 0,
+      textCounter: 0,
+      evalCounter: 0,
+      book_id: null,
+      unit_id: null,
 
-            schedules: [],
-            nowSchedule: "",
-            state: "",
-            rabbitPos: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            rabbitCompl: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            rabbitEnd: false,
+      schedules: [],
+      nowSchedule: "",
+      state: "",
+      rabbitPos: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+      rabbitCompl: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+      rabbitEnd: false,
 
-            titleUnitName: "",
-            titleBookName: "",
+      titleUnitName: "",
+      titleBookName: "",
 
-            images: [],
+      images: [],
 
-            selectedImage: [
-                {
-                    image: "",
-                    unit: "",
-                    date: "",
-                    name: "",
-                    heart: "",
-                    fileMngId: "",
-                },
-            ],
+      selectedImage: [
+        {
+          image: "",
+          unit: "",
+          date: "",
+          name: "",
+          heart: "",
+          fileMngId: "",
+        },
+      ],
 
-            isHeartFilled: false, // 하트가 채워졌는지 여부
+      isHeartFilled: false, // 하트가 채워졌는지 여부
 
-            problemType: null,
-            wordBookType: null,
-            wordContentList: [],
-        };
+      problemType: null,
+      wordBookType: null,
+      wordContentList: [],
+    };
+  },
+  methods: {
+    toggleHeart(heart, fileMngId) {
+      this.isHeartFilled = !this.isHeartFilled; // 하트 상태 토글
+
+      if (this.isHeartFilled) var calHeart = heart + 1;
+      else var calHeart = heart - 1;
+
+      // 하트 수를 증가시키기 위한 API 요청
+      axios
+        .post("/photo/likeUpdate.json", {
+          likeData: calHeart,
+          fileMngId: fileMngId,
+        })
+        .then((response) => {
+          this.selectedImage.heart = calHeart;
+        })
+        .catch((error) => {
+          console.error("Error updating heart:", error);
+        });
     },
-    methods: {
-        toggleHeart(heart, fileMngId) {
-            this.isHeartFilled = !this.isHeartFilled; // 하트 상태 토글
+    checkAndFetchData() {
+      console.log("받은 Book ID:", this.getBookId);
+      console.log("받은 Unit ID:", this.getUnitId);
+      const book_id = this.getBookId;
+      const unit_id = this.getUnitId;
 
-            if (this.isHeartFilled) var calHeart = heart + 1;
-            else var calHeart = heart - 1;
+      if (!book_id || !unit_id) {
+        console.error("book_id 또는 unit_id가 설정되지 않았습니다.");
+        return;
+      }
+      this.fetchImage(unit_id);
+      this.fetchSchedule(unit_id, book_id);
+      this.fetchRoadmapData(unit_id, book_id);
+      this.fetchRabbit();
 
-            // 하트 수를 증가시키기 위한 API 요청
-            axios
-                .post("/photo/likeUpdate.json", {
-                    likeData: calHeart,
-                    fileMngId: fileMngId,
-                })
-                .then((response) => {
-                    this.selectedImage.heart = calHeart;
-                })
-                .catch((error) => {
-                    console.error("Error updating heart:", error);
-                });
+      this.unit_id = unit_id;
+      this.book_id = book_id;
+
+      if (this.$route.query.reCapture == "true") {
+        this.openCameraModal();
+      }
+
+      this.searchStdId();
+    },
+
+    //은진
+    buttonSearch(image) {
+      this.isHeartFilled = false;
+      this.selectedImage.name = image.stdId;
+      this.selectedImage.image = image.url;
+      this.selectedImage.unit = this.titleUnitName;
+      this.selectedImage.date = image.fileRegDate.split(" ")[0];
+      this.selectedImage.heart = image.likeData;
+      this.selectedImage.fileMngId = image.fileMngId;
+      this.searchOpen = true;
+    },
+    fetchImage(unit_id) {
+      axios({
+        url: "/photo/photoUnitList.json",
+        method: "post",
+        headers: {
+          "Content-Type": "application/json; charset=UTF-8",
         },
-        checkAndFetchData() {
-            console.log("받은 Book ID:", this.getBookId);
-            console.log("받은 Unit ID:", this.getUnitId);
-            const book_id = this.getBookId;
-            const unit_id = this.getUnitId;
-
-            if (!book_id || !unit_id) {
-                console.error("book_id 또는 unit_id가 설정되지 않았습니다.");
-                return;
-            }
-            this.fetchImage(unit_id);
-            this.fetchSchedule(unit_id, book_id);
-            this.fetchRoadmapData(unit_id, book_id);
-            this.fetchRabbit();
-
-            this.unit_id = unit_id;
-            this.book_id = book_id;
-
-            if (this.$route.query.reCapture == "true") {
-                this.openCameraModal();
-            }
-
-            this.searchStdId();
+        data: {
+          unitId: unit_id,
+          sclsId: "1",
         },
+      })
+        .then((response) => {
+          this.file = response.data;
 
-        //은진
-        buttonSearch(image) {
-            this.isHeartFilled = false;
-            this.selectedImage.name = image.stdId;
-            this.selectedImage.image = image.url;
-            this.selectedImage.unit = this.titleUnitName;
-            this.selectedImage.date = image.fileRegDate.split(" ")[0];
-            this.selectedImage.heart = image.likeData;
-            this.selectedImage.fileMngId = image.fileMngId;
-            this.searchOpen = true;
-        },
-        fetchImage(unit_id) {
-            axios({
-                url: "/photo/photoUnitList.json",
-                method: "post",
-                headers: {
-                    "Content-Type": "application/json; charset=UTF-8",
-                },
-                data: {
-                    unitId: unit_id,
-                    sclsId: "1",
-                },
+          const findFilePromises = this.file.map((f) =>
+            this.findFile(f.file_mng_id)
+          );
+
+          return Promise.all(findFilePromises);
+        })
+        .then((fileResults) => {
+          this.images = this.file
+            .map((file, index) => {
+              const result = fileResults[index];
+              if (result) {
+                return {
+                  url: "http://165.229.169.113:9080/" + `${result.fileRpath}`,
+                  fileId: result.fileId,
+                  fileNm: result.fileNm,
+                  fileRegDate: result.regDt,
+                  likeData: file.like_data,
+                  stdId: file.user_nm,
+                  fileMngId: result.fileMngId,
+                };
+              }
+              return null;
             })
-                .then((response) => {
-                    this.file = response.data;
+            .filter((image) => image !== null);
+        })
+        .catch((error) => {
+          console.error("Error fetching images:", error);
+        });
+    },
+    async findFile(file_mng_id) {
+      try {
+        const res = await axios({
+          url: "/file/find.json",
+          method: "post",
+          headers: {
+            "Content-Type": "application/json; charset=UTF-8",
+          },
+          data: {
+            file_mng_id: file_mng_id,
+          },
+        });
+        return res.data.list[0];
+      } catch (error) {
+        console.log("result - error : ", error);
+        return null;
+      }
+    },
+    goToPageImg(page) {
+      const canvas = document.querySelector("canvas");
+      const dataURL = canvas.toDataURL("image/png");
 
-                    const findFilePromises = this.file.map((f) => this.findFile(f.file_mng_id));
+      this.$router.push({
+        name: page,
+        query: { image: encodeURIComponent(dataURL) },
+      });
+    },
 
-                    return Promise.all(findFilePromises);
-                })
-                .then((fileResults) => {
-                    this.images = this.file
-                        .map((file, index) => {
-                            const result = fileResults[index];
-                            if (result) {
-                                return {
-                                    url: "http://165.229.169.113:9080/" + `${result.fileRpath}`,
-                                    fileId: result.fileId,
-                                    fileNm: result.fileNm,
-                                    fileRegDate: result.regDt,
-                                    likeData: file.like_data,
-                                    stdId: file.user_nm,
-                                    fileMngId: result.fileMngId,
-                                };
-                            }
-                            return null;
-                        })
-                        .filter((image) => image !== null);
-                })
-                .catch((error) => {
-                    console.error("Error fetching images:", error);
-                });
-        },
-        async findFile(file_mng_id) {
-            try {
-                const res = await axios({
-                    url: "/file/find.json",
-                    method: "post",
-                    headers: {
-                        "Content-Type": "application/json; charset=UTF-8",
-                    },
-                    data: {
-                        file_mng_id: file_mng_id,
-                    },
-                });
-                return res.data.list[0];
-            } catch (error) {
-                console.log("result - error : ", error);
-                return null;
-            }
-        },
-        goToPageImg(page) {
-            const canvas = document.querySelector("canvas");
-            const dataURL = canvas.toDataURL("image/png");
+    fetchRabbit() {
+      for (var i = 0; i < 12; i++) {
+        this.rabbitPos[i] = false;
+      }
 
-            this.$router.push({ name: page, query: { image: encodeURIComponent(dataURL) } });
-        },
+      if (this.$route.query.value) {
+        this.rabbitPos[parseInt(this.$route.query.value, 10) + 1] = true;
+        for (var i = 0; i < this.$route.query.value; i++) {
+          this.rabbitCompl[i + 1] = true;
+        }
 
-        fetchRabbit() {
-            for (var i = 0; i < 12; i++) {
-                this.rabbitPos[i] = false;
-            }
-
-            if (this.$route.query.value) {
-                this.rabbitPos[parseInt(this.$route.query.value, 10) + 1] = true;
-                for (var i = 0; i < this.$route.query.value; i++) {
-                    this.rabbitCompl[i + 1] = true;
-                }
-
-                if (this.$route.query.value === "11") {
-                    this.rabbitEnd = true;
-                    setTimeout(() => {
-                        this.searchOpen2 = true;
-                    }, 1000);
-                }
-            } else this.rabbitPos[0] = true;
-        },
-        fetchSchedule(unit_id, book_id) {
-            axios({
-                url: "/schedule/selectSchedule.json",
-                method: "post",
-                headers: {
-                    "Content-Type": "application/json; charset=UTF-8",
-                },
-                data: {
-                    stdId: "2",
-                },
-            })
-                .then((response) => {
-                    this.schedules = response.data;
-
-                    if (this.schedules.length == 0) {
-                        this.state = "notRegistered";
-                    } else {
-                        const allFinished = this.schedules.every((schedule) => schedule.finish === "T");
-                        if (allFinished) {
-                            this.state = "finish";
-                        } else {
-                            this.nowSchedule = this.schedules.find((schedule) => schedule.finish === null || schedule.finish === "F");
-                            if (this.nowSchedule) {
-                                this.fetchRoadmapData(unit_id, book_id);
-                                this.state = "studying";
-                            } else {
-                                this.state = "notRegistered";
-                            }
-                        }
-                    }
-                })
-                .catch((error) => {
-                    console.error("Error fetching roadmap data:", error);
-                });
-        },
-        finishSchedule() {
-            axios({
-                url: "/schedule/scheduleUpdate.json",
-                method: "post",
-                headers: {
-                    "Content-Type": "application/json; charset=UTF-8",
-                },
-                data: {
-                    scheduleId: this.nowSchedule.schdl_id,
-                    finish: "T",
-                },
-            })
-                .then((response) => {
-                    const nextSchedule = this.schedules.find((schedule) => schedule.schdl_id > this.nowSchedule.schdl_id);
-                    alert("학습을 완료했습니다!");
-
-                    if (nextSchedule) {
-                        this.nowSchedule = nextSchedule;
-                        this.fetchSchedule(nextSchedule.unit_id, nextSchedule.book_id);
-                        this.fetchRoadmapData(nextSchedule.unit_id, nextSchedule.book_id);
-                        this.$router.push({ name: "Dashboard", query: { unit_id: nextSchedule.unit_id, book_id: nextSchedule.book_id } });
-                    } else {
-                        alert("모든 학습을 완료했습니다!");
-                        this.state = "finish";
-                    }
-                })
-                .catch((error) => {
-                    console.error("Error updating schedule:", error);
-                });
-        },
-        fetchRoadmapData(unit_id, book_id) {
-            axios({
-                url: "/unitLearning/find.json",
-                method: "post",
-                headers: {
-                    "Content-Type": "application/json; charset=UTF-8",
-                },
-                data: {
-                    unit_id: unit_id,
-                    book_id: book_id,
-                },
-            })
-                .then((response) => {
-                    if (response.data.length != 0) {
-                        this.roadmapData = response.data;
-                        this.titleUnitName = this.roadmapData[0].unit_nm;
-                        this.titleBookName = this.roadmapData[0].book_nm;
-                        this.labeledItems = this.processedRoadmap;
-                    } else {
-                        this.state = "noProblem";
-                    }
-                })
-                .catch((error) => {
-                    this.state = "noProblem";
-                    console.error("Error fetching roadmap data:", error);
-                });
-        },
-        toggleImage(index) {
-            this.items[index].isSecondImageVisible = !this.items[index].isSecondImageVisible;
-        },
-        ShowPopup() {
-            this.searchOpen2 = true; // 촬영 여부 묻는 모달창 열기
-        },
-        goToPage(page) {
-            // const { unit_id, book_id } = this.$route.query;
-            // this.$router.push({ name: page, query: { unit_id, book_id } });
-            this.$router.push({ name: page });
-        },
-        storeLearningId(labeledItems) {
-            this.$store.dispatch("updateLearningData", labeledItems);
-            this.$store.dispatch("updateLearningId", labeledItems.learning_id); // 단어장에 사용중..
-            console.log("레이블된 아이템: ", labeledItems);
-            if (labeledItems.label.startsWith("문제")) {
-                this.handleProblemDetail(this.$store.getters.currentLearningId);
-                this.goToPage(this.problemType);
-            } else if (labeledItems.label.startsWith("단어장")) {
-                this.handleWordBookContent(this.$store.getters.getLearningId);
-            }
-
-            if (labeledItems.label.startsWith("지문")) {
-                //console.log("지문 아이디 : ", labeledItems.learning_id);
-                this.$store.dispatch("updateTextId", labeledItems.learning_id);
-                this.fetchTextType(labeledItems.learning_id);
-            }
-        },
-        handleWordBookContent(item) {
-            console.log("처리할 단어장 콘텐츠 id: ", item);
-
-            // 단어장 ID 가져오기
-            axios
-                .post("/wordContent/selectWordContent.json", {
-                    wordContentId: item,
-                })
-                .then((response) => {
-                    this.wordContentList = response.data;
-
-                this.$store.dispatch('updateWdBookIdList', this.wordContentList.map(content => content.wd_book_id));
-                this.$store.dispatch('updateCurrentWdBkIndex', 0);
-                console.log("저장한 단어장 id 리스트: ", this.$store.getters.getWdBookIdList);
-
-                // 단어장 ID 리스트에서 첫 번째 단어장 ID를 사용
-                const wdBookId = this.wordContentList[0].wd_book_id;
-
-                    // 단어장 정보 가져오기
-                    return axios.post("/wordbook/find.json", {
-                        wdBookId: wdBookId,
-                    });
-                })
-                .then((response) => {
-                    const wordbookData = response.data;
-
-                    // 단어장 타입에 따라 페이지 설정
-                    if (wordbookData && wordbookData.wdBookTypeId) {
-                        switch (wordbookData.wdBookTypeId) {
-                            case "1":
-                                this.wordBookType = "Chapter2";
-                                break;
-                            case "2":
-                                this.wordBookType = "Chapter2_3";
-                                break;
-                            case "3":
-                                this.wordBookType = "Chapter2_2";
-                                break;
-                            case "4":
-                                this.wordBookType = "Chapter2_9";
-                                break;
-                            case "5":
-                                this.wordBookType = "Chapter2_4";
-                                break;
-                            default:
-                                this.wordBookType = null;
-                        }
-                    } else {
-                        console.error("wdBookTypeId가 없습니다.");
-                        this.wordBookType = null;
-                    }
-
-                    console.log("현재 단어장 타입: ", this.wordBookType);
-                    this.goToPage(this.wordBookType);
-                })
-                .catch((error) => {
-                    console.error("단어장 정보를 불러오는 중 오류 발생:", error);
-                    this.wordBookType = null;
-                });
-        },
-        // 지문 type 불러오기
-        fetchTextType(text_id) {
-            axios({
-                url: "/text/selectOneText.json",
-                method: "post",
-                headers: {
-                    "Content-Type": "application/json; charset=UTF-8",
-                },
-                data: {
-                    textId: text_id,
-                },
-            })
-                .then((response) => {
-                    const text_type_id = response.data[0].text_type_id;
-                    // console.log("지문 유형 아이디 : ", text_type_id);
-                    if (text_type_id === "2") {
-                        this.goToPage("Chapter1_2");
-                    } else if (text_type_id === "3") {
-                        this.goToPage("Chapter1_3");
-                    }
-                })
-                .catch((err) => {
-                    console.log("지문 에러 : ", err);
-                });
-        },
-        handleProblemDetail(item) {
-            if (item.prblm_type_id === "prblm_type_001") {
-                this.problemType = "Chapter3";
-            } else if (item.prblm_type_id === "prblm_type_002") {
-                this.problemType = "Chapter3_1";
-            } else if (item.prblm_type_id === "prblm_type_003") {
-                this.problemType = "Chapter3_2";
-            } else if (item.prblm_type_id === "prblm_type_004") {
-                this.problemType = "Chapter3_3";
-            } else if (item.prblm_type_id === "prblm_type_005") {
-                this.problemType = "Chapter3_3_1";
-            } else if (item.prblm_type_id === "prblm_type_006") {
-                this.problemType = "Chapter3_4";
-            } else if (item.prblm_type_id === "prblm_type_007") {
-                this.problemType = "Chapter3_5";
-            } else if (item.prblm_type_id === "prblm_type_008") {
-                this.problemType = "Chapter3_6";
-            } else if (item.prblm_type_id === "prblm_type_009") {
-                this.problemType = "Chapter3_7";
-            } else if (item.prblm_type_id === "prblm_type_010") {
-                this.problemType = "Chapter3_8";
-            } else if (item.prblm_type_id === "prblm_type_011") {
-                this.problemType = "Chapter3_9";
-            } else if (item.prblm_type_id === "prblm_type_012") {
-                this.problemType = "Chapter3_10";
-            } else if (item.prblm_type_id === "prblm_type_013") {
-                this.problemType = "Chapter3_11";
-            } else if (item.prblm_type_id === "prblm_type_014") {
-                this.problemType = "Chapter3_12";
-            } else if (item.prblm_type_id === "prblm_type_015") {
-                this.problemType = "Chapter3_13";
-            } else if (item.prblm_type_id === "prblm_type_016") {
-                this.problemType = "Chapter3_14";
-            } else if (item.prblm_type_id === "prblm_type_017") {
-                this.problemType = "Chapter3_15";
-            } else if (item.prblm_type_id === "prblm_type_018") {
-                this.problemType = "Chapter2_8";
-            } else if (item.prblm_type_id === "prblm_type_019") {
-                this.problemType = "Chapter2_7";
-            } else if (item.prblm_type_id === "prblm_type_020") {
-                this.problemType = "Chapter2_5";
-            } else if (item.prblm_type_id === "prblm_type_021") {
-                this.problemType = "Chapter2_6";
-            } else if (item.prblm_type_id === "prblm_type_022") {
-                this.problemType = "Chapter2_10";
-            } else if (item.prblm_type_id === "prblm_type_023") {
-                this.problemType = "Chapter2_11";
-            } else if (item.prblm_type_id === "prblm_type_024") {
-                this.problemType = "Chapter2_13";
-            }
-        },
-        openCameraModal() {
-            this.closeModal();
-
-            this.showCameraModal = true;
-            navigator.mediaDevices
-                .getUserMedia({ video: true })
-                .then((stream) => {
-                    const modalVideo = this.$refs.modalVideoElement;
-                    modalVideo.srcObject = stream;
-                    this.stream = stream;
-                })
-                .catch((error) => {
-                    console.log("error>>>>>>>>", error);
-                    alert("웹캠이 필요한 기능입니다!");
-                    this.closeModal(); // 모달창을 닫음
-                });
-        },
-        closeModal() {
-            this.searchOpen = false;
-            this.searchOpen2 = false;
-            this.showCameraModal = false;
-            this.photoTaken = false;
-            this.photo = null;
-
-            //스트림 종료
-            if (this.stream) {
-                let tracks = this.stream.getTracks();
-                tracks.forEach((track) => track.stop());
-                this.stream = null;
-            }
-        },
-
-        onVideoLoaded() {
-            const video = this.$refs.modalVideoElement;
-            const canvas = this.$refs.canvas;
-            const ctx = canvas.getContext("2d");
-
-            canvas.width = video.videoWidth;
-            canvas.height = video.videoHeight;
-        },
-        takePhoto() {
-            const video = this.$refs.modalVideoElement;
-            const canvas = this.$refs.canvas;
-            const ctx = canvas.getContext("2d");
-
-            ctx.save(); // 현재 상태 저장
-
-            // 캔버스 좌우 반전
-            ctx.scale(-1, 1);
-            ctx.drawImage(video, -canvas.width, 0, canvas.width, canvas.height);
-
-            ctx.restore();
-
-            const overlayImg = new Image();
-            overlayImg.src = "client/resources/img/camera-rabbit.png";
-            overlayImg.onload = () => {
-                const overlayWidth = canvas.width * 0.4;
-                const overlayHeight = (overlayImg.height / overlayImg.width) * overlayWidth;
-                const overlayX = canvas.width - overlayWidth;
-                const overlayY = canvas.height - overlayHeight;
-
-                // 오버레이 이미지 그리기
-                ctx.drawImage(overlayImg, overlayX, overlayY, overlayWidth, overlayHeight);
-
-                // 사진 저장 함수 호출
-                const dataURL = canvas.toDataURL("image/png");
-                this.$router.push({ name: "PhotoEdit", query: { image: encodeURIComponent(dataURL), unit_id: this.unit_id, book_id: this.book_id } });
-            };
-        },
-
-        buttonSearch2() {
+        if (this.$route.query.value === "11") {
+          this.rabbitEnd = true;
+          setTimeout(() => {
             this.searchOpen2 = true;
-        },
-        closeBtn() {
-            this.searchOpen = false;
-        },
-
-        // 유저 아이디를 unit 아이디를 통해 가져오기
-        searchStdId() {
-            const userInfo = this.$store.getters.getUserInfo;
-            axios({
-                url: "/userclass/searchStdId.json",
-                method: "post",
-                headers: {
-                    "Content-Type": "application/json; charset=UTF-8",
-                },
-                data: {
-                    userId: userInfo.userId,
-                    unitId: this.unit_id,
-                },
-            })
-                .then((response) => {
-                    this.$store.commit('setStdId', response.data);
-                })
-                .catch((err) => {
-                    console.log("지문 에러 : ", err);
-                });
-        },
-
+          }, 1000);
+        }
+      } else this.rabbitPos[0] = true;
     },
-    components: {
-        SvgIcon,
-    },
-    mounted() {
-        console.log("main mounted");
-        this.checkAndFetchData();
-        // const { book_id, unit_id } = this.$route.query;
-    },
-    watch: {
-        getBookId(newBookId) {
-            this.checkAndFetchData();
+    fetchSchedule(unit_id, book_id) {
+      axios({
+        url: "/schedule/selectSchedule.json",
+        method: "post",
+        headers: {
+          "Content-Type": "application/json; charset=UTF-8",
         },
-        getUnitId(newUnitId) {
-            this.checkAndFetchData();
+        data: {
+          stdId: "2",
         },
+      })
+        .then((response) => {
+          this.schedules = response.data;
+
+          if (this.schedules.length == 0) {
+            this.state = "notRegistered";
+          } else {
+            const allFinished = this.schedules.every(
+              (schedule) => schedule.finish === "T"
+            );
+            if (allFinished) {
+              this.state = "finish";
+            } else {
+              this.nowSchedule = this.schedules.find(
+                (schedule) =>
+                  schedule.finish === null || schedule.finish === "F"
+              );
+              if (this.nowSchedule) {
+                this.fetchRoadmapData(unit_id, book_id);
+                this.state = "studying";
+              } else {
+                this.state = "notRegistered";
+              }
+            }
+          }
+        })
+        .catch((error) => {
+          console.error("Error fetching roadmap data:", error);
+        });
     },
-    computed: {
-        ...mapGetters(["getBookId", "getUnitId"]),
+    finishSchedule() {
+      axios({
+        url: "/schedule/scheduleUpdate.json",
+        method: "post",
+        headers: {
+          "Content-Type": "application/json; charset=UTF-8",
+        },
+        data: {
+          scheduleId: this.nowSchedule.schdl_id,
+          finish: "T",
+        },
+      })
+        .then((response) => {
+          const nextSchedule = this.schedules.find(
+            (schedule) => schedule.schdl_id > this.nowSchedule.schdl_id
+          );
+          alert("학습을 완료했습니다!");
 
-        processedRoadmap() {
-            let problemCounter = 0;
-            let wordCounter = 0;
-            let textCounter = 0;
-            let evalCounter = 0;
-
-            return this.roadmapData.map((item) => {
-                if (item.wd_cnt_id !== null) {
-                    wordCounter++;
-                    return { label: `단어장${wordCounter}`, learning_id: item.wd_cnt_id };
-                } else if (item.text_id !== null) {
-                    textCounter++;
-                    return { label: `지문${textCounter}`, learning_id: item.text_id };
-                } else if (item.eval_id !== null) {
-                    evalCounter++;
-                    return { label: evalCounter === 1 ? "중간평가" : "최종평가", learning_id: item.eval_id };
-                } else {
-                    problemCounter++;
-                    return { label: `문제${problemCounter}`, learning_id: item.prblm_id };
-                }
+          if (nextSchedule) {
+            this.nowSchedule = nextSchedule;
+            this.fetchSchedule(nextSchedule.unit_id, nextSchedule.book_id);
+            this.fetchRoadmapData(nextSchedule.unit_id, nextSchedule.book_id);
+            this.$router.push({
+              name: "Dashboard",
+              query: {
+                unit_id: nextSchedule.unit_id,
+                book_id: nextSchedule.book_id,
+              },
             });
+          } else {
+            alert("모든 학습을 완료했습니다!");
+            this.state = "finish";
+          }
+        })
+        .catch((error) => {
+          console.error("Error updating schedule:", error);
+        });
+    },
+    fetchRoadmapData(unit_id, book_id) {
+      axios({
+        url: "/unitLearning/find.json",
+        method: "post",
+        headers: {
+          "Content-Type": "application/json; charset=UTF-8",
         },
+        data: {
+          unit_id: unit_id,
+          book_id: book_id,
+        },
+      })
+        .then((response) => {
+          if (response.data.length != 0) {
+            this.roadmapData = response.data;
+            this.titleUnitName = this.roadmapData[0].unit_nm;
+            this.titleBookName = this.roadmapData[0].book_nm;
+            this.labeledItems = this.processedRoadmap;
+          } else {
+            this.state = "noProblem";
+          }
+        })
+        .catch((error) => {
+          this.state = "noProblem";
+          console.error("Error fetching roadmap data:", error);
+        });
     },
-    beforeDestroy() {
-        // 컴포넌트가 파괴되기 전에 리스너 제거
-        window.removeEventListener("resize", this.updateCanvasRect);
-        this.$refs.canvas.removeEventListener("click", this.handleCanvasClick);
+    toggleImage(index) {
+      this.items[index].isSecondImageVisible =
+        !this.items[index].isSecondImageVisible;
     },
+    ShowPopup() {
+      this.searchOpen2 = true; // 촬영 여부 묻는 모달창 열기
+    },
+    goToPage(page) {
+      // const { unit_id, book_id } = this.$route.query;
+      // this.$router.push({ name: page, query: { unit_id, book_id } });
+      this.$router.push({ name: page });
+    },
+    storeLearningId(labeledItems) {
+      this.$store.dispatch("updateLearningData", labeledItems);
+      this.$store.dispatch("updateLearningId", labeledItems.learning_id); // 단어장에 사용중..
+
+      console.log("레이블된 아이템: ", labeledItems);
+      if (labeledItems.label.startsWith("문제")) {
+        this.handleProblemDetail(this.$store.getters.currentLearningId);
+        this.goToPage(this.problemType);
+      } else if (labeledItems.label.startsWith("단어장")) {
+        this.handleWordBookContent(this.$store.getters.getLearningId);
+      }
+
+      if (labeledItems.label.startsWith("지문")) {
+        //console.log("지문 아이디 : ", labeledItems.learning_id);
+        this.$store.dispatch("updateTextId", labeledItems.learning_id);
+        this.fetchTextType(labeledItems.learning_id);
+      }
+    },
+    handleWordBookContent(item) {
+      console.log("처리할 단어장 콘텐츠 id: ", item);
+
+      // 단어장 ID 가져오기
+      axios
+        .post("/wordContent/selectWordContent.json", {
+          wordContentId: item,
+        })
+        .then((response) => {
+          this.wordContentList = response.data;
+
+          this.$store.dispatch(
+            "updateWdBookIdList",
+            this.wordContentList.map((content) => content.wd_book_id)
+          );
+          this.$store.dispatch("updateCurrentWdBkIndex", 0);
+          console.log(
+            "저장한 단어장 id 리스트: ",
+            this.$store.getters.getWdBookIdList
+          );
+
+          // 단어장 ID 리스트에서 첫 번째 단어장 ID를 사용
+          const wdBookId = this.wordContentList[0].wd_book_id;
+
+          // 단어장 정보 가져오기
+          return axios.post("/wordbook/find.json", {
+            wdBookId: wdBookId,
+          });
+        })
+        .then((response) => {
+          const wordbookData = response.data;
+
+          // 단어장 타입에 따라 페이지 설정
+          if (wordbookData && wordbookData.wdBookTypeId) {
+            switch (wordbookData.wdBookTypeId) {
+              case "1":
+                this.wordBookType = "Chapter2";
+                break;
+              case "2":
+                this.wordBookType = "Chapter2_3";
+                break;
+              case "3":
+                this.wordBookType = "Chapter2_2";
+                break;
+              case "4":
+                this.wordBookType = "Chapter2_9";
+                break;
+              case "5":
+                this.wordBookType = "Chapter2_4";
+                break;
+              default:
+                this.wordBookType = null;
+            }
+          } else {
+            console.error("wdBookTypeId가 없습니다.");
+            this.wordBookType = null;
+          }
+
+          console.log("현재 단어장 타입: ", this.wordBookType);
+          this.goToPage(this.wordBookType);
+        })
+        .catch((error) => {
+          console.error("단어장 정보를 불러오는 중 오류 발생:", error);
+          this.wordBookType = null;
+        });
+    },
+    // 지문 type 불러오기
+    fetchTextType(text_id) {
+      axios({
+        url: "/text/selectOneText.json",
+        method: "post",
+        headers: {
+          "Content-Type": "application/json; charset=UTF-8",
+        },
+        data: {
+          textId: text_id,
+        },
+      })
+        .then((response) => {
+          const text_type_id = response.data[0].text_type_id;
+          // console.log("지문 유형 아이디 : ", text_type_id);
+          if (text_type_id === "2") {
+            this.goToPage("Chapter1_2");
+          } else if (text_type_id === "3") {
+            this.goToPage("Chapter1_3");
+          }
+        })
+        .catch((err) => {
+          console.log("지문 에러 : ", err);
+        });
+    },
+    handleProblemDetail(item) {
+      if (item.prblm_type_id === "prblm_type_001") {
+        this.problemType = "Chapter3";
+      } else if (item.prblm_type_id === "prblm_type_002") {
+        this.problemType = "Chapter3_1";
+      } else if (item.prblm_type_id === "prblm_type_003") {
+        this.problemType = "Chapter3_2";
+      } else if (item.prblm_type_id === "prblm_type_004") {
+        this.problemType = "Chapter3_3";
+      } else if (item.prblm_type_id === "prblm_type_005") {
+        this.problemType = "Chapter3_3_1";
+      } else if (item.prblm_type_id === "prblm_type_006") {
+        this.problemType = "Chapter3_4";
+      } else if (item.prblm_type_id === "prblm_type_007") {
+        this.problemType = "Chapter3_5";
+      } else if (item.prblm_type_id === "prblm_type_008") {
+        this.problemType = "Chapter3_6";
+      } else if (item.prblm_type_id === "prblm_type_009") {
+        this.problemType = "Chapter3_7";
+      } else if (item.prblm_type_id === "prblm_type_010") {
+        this.problemType = "Chapter3_8";
+      } else if (item.prblm_type_id === "prblm_type_011") {
+        this.problemType = "Chapter3_9";
+      } else if (item.prblm_type_id === "prblm_type_012") {
+        this.problemType = "Chapter3_10";
+      } else if (item.prblm_type_id === "prblm_type_013") {
+        this.problemType = "Chapter3_11";
+      } else if (item.prblm_type_id === "prblm_type_014") {
+        this.problemType = "Chapter3_12";
+      } else if (item.prblm_type_id === "prblm_type_015") {
+        this.problemType = "Chapter3_13";
+      } else if (item.prblm_type_id === "prblm_type_016") {
+        this.problemType = "Chapter3_14";
+      } else if (item.prblm_type_id === "prblm_type_017") {
+        this.problemType = "Chapter3_15";
+      } else if (item.prblm_type_id === "prblm_type_018") {
+        this.problemType = "Chapter2_8";
+      } else if (item.prblm_type_id === "prblm_type_019") {
+        this.problemType = "Chapter2_7";
+      } else if (item.prblm_type_id === "prblm_type_020") {
+        this.problemType = "Chapter2_5";
+      } else if (item.prblm_type_id === "prblm_type_021") {
+        this.problemType = "Chapter2_6";
+      } else if (item.prblm_type_id === "prblm_type_022") {
+        this.problemType = "Chapter2_10";
+      } else if (item.prblm_type_id === "prblm_type_023") {
+        this.problemType = "Chapter2_11";
+      } else if (item.prblm_type_id === "prblm_type_024") {
+        this.problemType = "Chapter2_13";
+      }
+    },
+    openCameraModal() {
+      this.closeModal();
+
+      this.showCameraModal = true;
+      navigator.mediaDevices
+        .getUserMedia({ video: true })
+        .then((stream) => {
+          const modalVideo = this.$refs.modalVideoElement;
+          modalVideo.srcObject = stream;
+          this.stream = stream;
+        })
+        .catch((error) => {
+          console.log("error>>>>>>>>", error);
+          alert("웹캠이 필요한 기능입니다!");
+          this.closeModal(); // 모달창을 닫음
+        });
+    },
+    closeModal() {
+      this.searchOpen = false;
+      this.searchOpen2 = false;
+      this.showCameraModal = false;
+      this.photoTaken = false;
+      this.photo = null;
+
+      //스트림 종료
+      if (this.stream) {
+        let tracks = this.stream.getTracks();
+        tracks.forEach((track) => track.stop());
+        this.stream = null;
+      }
+    },
+
+    onVideoLoaded() {
+      const video = this.$refs.modalVideoElement;
+      const canvas = this.$refs.canvas;
+      const ctx = canvas.getContext("2d");
+
+      canvas.width = video.videoWidth;
+      canvas.height = video.videoHeight;
+    },
+    takePhoto() {
+      const video = this.$refs.modalVideoElement;
+      const canvas = this.$refs.canvas;
+      const ctx = canvas.getContext("2d");
+
+      ctx.save(); // 현재 상태 저장
+
+      // 캔버스 좌우 반전
+      ctx.scale(-1, 1);
+      ctx.drawImage(video, -canvas.width, 0, canvas.width, canvas.height);
+
+      ctx.restore();
+
+      const overlayImg = new Image();
+      overlayImg.src = "client/resources/img/camera-rabbit.png";
+      overlayImg.onload = () => {
+        const overlayWidth = canvas.width * 0.4;
+        const overlayHeight =
+          (overlayImg.height / overlayImg.width) * overlayWidth;
+        const overlayX = canvas.width - overlayWidth;
+        const overlayY = canvas.height - overlayHeight;
+
+        // 오버레이 이미지 그리기
+        ctx.drawImage(
+          overlayImg,
+          overlayX,
+          overlayY,
+          overlayWidth,
+          overlayHeight
+        );
+
+        // 사진 저장 함수 호출
+        const dataURL = canvas.toDataURL("image/png");
+        this.$router.push({
+          name: "PhotoEdit",
+          query: {
+            image: encodeURIComponent(dataURL),
+            unit_id: this.unit_id,
+            book_id: this.book_id,
+          },
+        });
+      };
+    },
+
+    buttonSearch2() {
+      this.searchOpen2 = true;
+    },
+    closeBtn() {
+      this.searchOpen = false;
+    },
+
+    // 유저 아이디를 unit 아이디를 통해 가져오기
+    searchStdId() {
+      const userInfo = this.$store.getters.getUserInfo;
+      axios({
+        url: "/userclass/searchStdId.json",
+        method: "post",
+        headers: {
+          "Content-Type": "application/json; charset=UTF-8",
+        },
+        data: {
+          userId: userInfo.userId,
+          unitId: this.unit_id,
+        },
+      })
+        .then((response) => {
+          this.$store.commit("setStdId", response.data);
+        })
+        .catch((err) => {
+          console.log("지문 에러 : ", err);
+        });
+    },
+  },
+  components: {
+    SvgIcon,
+  },
+  mounted() {
+    console.log("main mounted");
+    this.checkAndFetchData();
+    // const { book_id, unit_id } = this.$route.query;
+  },
+  watch: {
+    getBookId(newBookId) {
+      this.checkAndFetchData();
+    },
+    getUnitId(newUnitId) {
+      this.checkAndFetchData();
+    },
+  },
+  computed: {
+    ...mapGetters(["getBookId", "getUnitId"]),
+
+    processedRoadmap() {
+      let problemCounter = 0;
+      let wordCounter = 0;
+      let textCounter = 0;
+      let evalCounter = 0;
+
+      return this.roadmapData.map((item) => {
+        if (item.wd_cnt_id !== null) {
+          wordCounter++;
+          return {
+            label: `단어장${wordCounter}`,
+            learning_id: item.wd_cnt_id,
+            seqNum: item.seq,
+          };
+        } else if (item.text_id !== null) {
+          textCounter++;
+          return {
+            label: `지문${textCounter}`,
+            learning_id: item.text_id,
+            seqNum: item.seq,
+          };
+        } else if (item.eval_id !== null) {
+          evalCounter++;
+          return {
+            label: evalCounter === 1 ? "중간평가" : "최종평가",
+            learning_id: item.eval_id,
+            seqNum: item.seq,
+          };
+        } else {
+          problemCounter++;
+          return {
+            label: `문제${problemCounter}`,
+            learning_id: item.prblm_id,
+            seqNum: item.seq,
+          };
+        }
+      });
+    },
+  },
+  beforeDestroy() {
+    // 컴포넌트가 파괴되기 전에 리스너 제거
+    window.removeEventListener("resize", this.updateCanvasRect);
+    this.$refs.canvas.removeEventListener("click", this.handleCanvasClick);
+  },
 };
 </script>
 
 <style scoped>
 .body {
-    width: 1435px;
-    height: auto;
-    margin: 0 auto;
+  width: 1435px;
+  height: auto;
+  margin: 0 auto;
 }
 
 #container {
-    position: relative;
-    margin: auto;
-    border: 10px #333 solid;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    z-index: 100;
+  position: relative;
+  margin: auto;
+  border: 10px #333 solid;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 100;
 }
 
 video {
-    width: 100%;
-    height: auto;
-    background-color: #666;
+  width: 100%;
+  height: auto;
+  background-color: #666;
 }
 
 .mirrored {
-    transform: scaleX(-1);
+  transform: scaleX(-1);
 }
 
 .new-btn:disabled {
-    background-color: #fff3d7;
-    cursor: not-allowed;
+  background-color: #fff3d7;
+  cursor: not-allowed;
 }
 
 .sticker {
-    position: absolute;
-    cursor: move;
+  position: absolute;
+  cursor: move;
 }
 
 .sticker-handle {
-    width: 15px;
-    height: 15px;
-    background: rgba(255, 255, 255, 0.521);
-    position: absolute;
-    bottom: 0;
-    right: 0;
-    cursor: nwse-resize;
-    font-size: 13px;
-    font-weight: bolder;
-    color: rgb(63, 63, 63);
+  width: 15px;
+  height: 15px;
+  background: rgba(255, 255, 255, 0.521);
+  position: absolute;
+  bottom: 0;
+  right: 0;
+  cursor: nwse-resize;
+  font-size: 13px;
+  font-weight: bolder;
+  color: rgb(63, 63, 63);
 }
 
 .sticker-delete {
-    position: absolute;
-    top: 0;
-    right: 0;
-    background: rgba(255, 0, 0, 0.425);
-    color: white;
-    padding: 5px;
-    cursor: pointer;
+  position: absolute;
+  top: 0;
+  right: 0;
+  background: rgba(255, 0, 0, 0.425);
+  color: white;
+  padding: 5px;
+  cursor: pointer;
 }
 
 .toolbar {
-    display: flex;
-    justify-content: center;
-    margin-top: 10px;
+  display: flex;
+  justify-content: center;
+  margin-top: 10px;
 }
 
 .toolbar button {
-    margin: 5px;
-    padding: 5px 10px;
-    cursor: pointer;
+  margin: 5px;
+  padding: 5px 10px;
+  cursor: pointer;
 }
 
 .toolbar input {
-    margin: 5px;
+  margin: 5px;
 }
 
 .rabbit-end {
-    cursor: pointer;
-    display: block;
-    position: absolute;
-    bottom: 0px;
-    left: -15px;
-    z-index: 10000;
+  cursor: pointer;
+  display: block;
+  position: absolute;
+  bottom: 0px;
+  left: -15px;
+  z-index: 10000;
 }
 
 .rabbit-running {
-    position: absolute;
-    bottom: 40px;
-    right: 110px;
-    z-index: 10000;
-    transform: scaleX(-1);
-    transition: all 0.5s ease-in-out;
+  position: absolute;
+  bottom: 40px;
+  right: 110px;
+  z-index: 10000;
+  transform: scaleX(-1);
+  transition: all 0.5s ease-in-out;
 }
 
 .fireworks-end {
-    position: absolute;
-    bottom: 70px;
-    left: -40px;
-    width: 20rem;
+  position: absolute;
+  bottom: 70px;
+  left: -40px;
+  width: 20rem;
 }
 
 .camera-rabbit {
-    position: absolute;
-    right: 0;
-    bottom: 0;
-    width: 40%;
+  position: absolute;
+  right: 0;
+  bottom: 0;
+  width: 40%;
 }
 
 .race-btn p {
-    width: auto;
+  width: auto;
 }
 </style>
Add a comment
List