jichoi / calendar star
최정임 최정임 03-13
250313 최정임
@bbd23694846301d4e52851a6c015480edf7b72b8
client/views/index.html
--- client/views/index.html
+++ client/views/index.html
@@ -12,6 +12,7 @@
     <link rel="stylesheet" href="../../client/resources/css/grid.css">
     <link rel="stylesheet" href="../../client/resources/css/style.css">
     <link rel="stylesheet" href="../../client/resources/css/responsive.css">
+    <link rel="stylesheet" href="../../client/resources/css/palette.scss">
     <title>테이큰소프트</title>
 </head>
 
client/views/index.js
--- client/views/index.js
+++ client/views/index.js
@@ -5,6 +5,8 @@
 import VueCookies from 'vue-cookies';
 import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client';
 import { provideApolloClient } from '@vue/apollo-composable'; // @vue/apollo-composable 사용
+import Antd from 'ant-design-vue';
+
 
 const httpLink = createHttpLink({
   uri: 'http://backend-example.codebootcamp.co.kr/graphql', // GraphQL 서버 주소
@@ -50,7 +52,8 @@
   vueApp
     .use(AppRouter)  // Vue Router 사용
     .use(Store)      // Vuex store 사용
-    .use(VueCookies)  // VueCookies 사용
+    .use(VueCookies)
+    .use(Antd)  // VueCookies 사용
     .config.globalProperties.$gapi = window.gapi;  // gapi를 전역 속성으로 설정
 
   // ApolloClient 제공
@@ -60,6 +63,7 @@
   vueApp.config.globalProperties.$cookies = VueCookies; // 쿠키 설정
   vueApp.$cookies.config("1d"); // 쿠키 만료일 설정
 
+
   vueApp.mount("#root"); // Vue 앱을 #root에 마운트
 }
 
client/views/layout/SideBar.vue
--- client/views/layout/SideBar.vue
+++ client/views/layout/SideBar.vue
@@ -11,17 +11,22 @@
     <ul class="d-flex profile">
 
       <li>
-        <a class="dropdown-item d-flex align-items-center" href="users-profile.html">
-          <i class="bi bi-person"></i>
-          <span>마이페이지</span>
-        </a>
+        <router-link to="/MyPage" class="nav-link " active-class="active"><i class="bi bi-grid"></i>
+          <span>마이페이지</span></router-link>
       </li>
 
       <li>
         <a class="dropdown-item d-flex align-items-center" href="#">
           <i class="bi bi-box-arrow-right"></i>
-          <router-link to="/Login" class="nav-link " active-class="active"><i class="bi bi-grid"></i>
-            <span>로그인</span></router-link>
+          <router-link v-if="!isLoggedIn" to="/Login" class="nav-link" active-class="active">
+      <i class="bi bi-grid"></i>
+      <span>로그인</span>
+    </router-link>
+
+    <router-link v-if="isLoggedIn" @click="handleLogout" class="nav-link" active-class="active">
+      <i class="bi bi-box-arrow-right"></i>
+      <span>로그아웃</span>
+    </router-link>
         </a>
       </li>
 
@@ -65,6 +70,10 @@
           <li>
             <router-link to="/HyugaList" class="nav-link " active-class="active"><i
                 class="bi bi-circle"></i><span>휴가내역</span></router-link>
+          </li>
+          <li>
+            <router-link to="/HyugaOk" class="nav-link " active-class="active"><i
+                class="bi bi-circle"></i><span>휴가승인</span></router-link>
           </li>
 
         </ul>
@@ -114,16 +123,30 @@
   name: "ProfileImage",
   data() {
     return {
+      isLoggedIn: false,
       userName: '',
       logo: "/client/resources/img/logo_t.png", // 경로를 Vue 프로젝트 구조에 맞게 설정
     };
   },
   methods: {
+    handleLogout() {
+      // Clear login-related data from localStorage
+      localStorage.removeItem('loggedInUser');
+      this.isLoggedIn = false; // Update login status
+      this.$router.push("/login"); // Redirect to login page after logout
+    },
     toggleSidebar() {
       // `toggle-sidebar` 클래스가 있으면 제거, 없으면 추가
       document.body.classList.toggle("toggle-sidebar");
     },
   },
+  created() {
+    // Check if there is any login data in localStorage
+    const loggedInUser = localStorage.getItem('loggedInUser');
+    if (loggedInUser) {
+      this.isLoggedIn = true;
+    }
+  },
   components: {
   },
 };
client/views/pages/AppRouter.js
--- client/views/pages/AppRouter.js
+++ client/views/pages/AppRouter.js
@@ -3,17 +3,19 @@
 import Main from '../pages/main/Main.vue';
 import Login from '../pages/User/Login.vue';
 import Join from '../pages/User/Join.vue';
+import MyPage from '../pages/User/MyPage.vue';
 
-import Main2 from '../pages/main/Main2.vue';
+// import Main2 from '../pages/main/Main2.vue';
 
-import HomeView from "../pages/HomeView.vue";
-import AboutView from "../pages/AboutView.vue";
+// import HomeView from "../pages/HomeView.vue";
+// import AboutView from "../pages/AboutView.vue";
 
 // 직원
 import ChuljangList from '../pages/Employee/ChuljangList.vue';
 import ChuljangInsert from '../pages/Employee/ChuljangInsert.vue';
 import HyugaList from '../pages/Employee/HyugaList.vue';
 import HyugaInsert from '../pages/Employee/HyugaInsert.vue';
+import HyugaOk from '../pages/Employee/HyugaOk.vue';
 import ProjectList from '../pages/Employee/ProjectList.vue';
 import ProjectInsert from '../pages/Employee/ProjectInsert.vue';
 // 관리자
@@ -28,11 +30,13 @@
     { path: '/', name: '/', component: Main},
     { path: '/Login', name: 'Login', component: Login},
     { path: '/Join', name: 'Join', component: Join},
+    { path: '/MyPage', name: 'MyPage', component: MyPage},
     
     { path: '/ChuljangList', name: 'ChuljangList', component: ChuljangList },
     { path: '/ChuljangInsert', name: 'ChuljangInsert', component: ChuljangInsert },
     { path: '/HyugaList', name: 'HyugaList', component: HyugaList },
     { path: '/HyugaInsert', name: 'HyugaInsert', component: HyugaInsert },
+    { path: '/HyugaOk', name: 'HyugaOk', component: HyugaOk },
     { path: '/ProjectInsert', name: 'ProjectInsert', component: ProjectInsert },
     { path: '/ProjectList', name: 'ProjectList', component: ProjectList },
     { path: '/DeptList', name: 'DeptList', component: DeptList },
client/views/pages/Employee/ChuljangInsert.vue
--- client/views/pages/Employee/ChuljangInsert.vue
+++ client/views/pages/Employee/ChuljangInsert.vue
@@ -8,14 +8,12 @@
       <div class="card-body">
 
         <!-- Multi Columns Form -->
-        <form class="row g-3  pt-3" @submit.prevent="handleSubmit">
-
+        <form class="row g-3 pt-3" @submit.prevent="handleSubmit">
 
           <div class="col-md-5">
             <label for="startDate" class="form-label">시작일</label>
             <div class="d-flex gap-1">
               <input type="date" class="form-control" id="startDate" v-model="startDate" />
-              <!-- 시간 선택을 위한 select 사용 -->
               <select class="form-control" id="startTime" v-model="startTime">
                 <option value="09:00">09:00</option>
                 <option value="10:00">10:00</option>
@@ -35,7 +33,6 @@
             <label for="endDate" class="form-label">종료일</label>
             <div class="d-flex gap-1">
               <input type="date" class="form-control" id="endDate" v-model="endDate" />
-              <!-- 종료 시간을 위한 select 사용 -->
               <select class="form-control" id="endTime" v-model="endTime">
                 <option value="09:00">09:00</option>
                 <option value="10:00">10:00</option>
@@ -50,30 +47,34 @@
               </select>
             </div>
           </div>
+
           <div class="col-12">
-            <label for="prvonsh" class="form-label">출장지</label>
-            <input type="text" class="form-control" id="prvonsh" v-model="reason" />
+            <label for="where" class="form-label">출장지</label>
+            <input type="text" class="form-control" id="where" v-model="where" />
           </div>
+
           <div class="col-12">
-            <label for="prvonsh" class="form-label">출장목적</label>
-            <input type="text" class="form-control" id="prvonsh" v-model="reason" />
+            <label for="purpose" class="form-label">출장목적</label>
+            <input type="text" class="form-control" id="purpose" v-model="purpose" />
           </div>
+
           <div class="col-6">
-            <label for="prvonsh" class="form-label">동행자</label>
+            <label for="member" class="form-label">동행자</label>
             <div class="search-bar d-flex gap-2">
-              <form class="search-form d-flex  align-items-center" method="POST" action="#"
+              <form class="search-form d-flex align-items-center" method="POST" action="#"
                 @submit.prevent="updateMember">
-                <input type="text" v-model="searchQuery" name="query" placeholder="Search" title="Enter search keyword">
-                <button type="submit" title="Search"><i class="bi bi-search"></i></button>
+                <input type="text" v-model="searchQuery" name="query" placeholder="Search" title="Enter search keyword" />
+                <button type="submit" title="Search"><PlusOutlined /></button>
               </form>
-              <input type="text" class="select-member" :value="selectedMember.join(' ')" readonly>
+              <input type="text" class="select-member" :value="selectedMember.join(' ')" readonly />
             </div>
           </div>
 
           <div class="text-end">
-            <button type="submit" class="btn btn-primary">승인요청</button>
-            <button type="reset" class="btn btn-secondary">취소</button>
+            <button type="submit" class="btn primary">승인요청</button>
+            <button type="reset" class="btn secondary">취소</button>
           </div>
+
         </form><!-- End Multi Columns Form -->
 
       </div>
@@ -83,38 +84,41 @@
 
 <script>
 import { useAuthStore } from '../../stores/authStore';
+import { PlusOutlined } from '@ant-design/icons-vue';
+
 export default {
   data() {
     const today = new Date().toISOString().split('T')[0];
     return {
-      searchQuery: '',
-      selectedMember: [],
       startDate: today,
-      startTime: "09:00", // 기본 시작 시간 09:00
+      startTime: '09:00',
       endDate: today,
-      endTime: "18:00", // 기본 종료 시간 18:00
-      allDay: false, // 종일 여부
-      dayCount: 1, // 사용 휴가일 계산
-      reason: "", // 사유
+      endTime: '18:00',
+      where: '',
+      purpose: '',
+      selectedMember: [],
+      searchQuery: '', 
     };
   },
+  components: {
+    PlusOutlined,
+  },
   computed: {
-    // Pinia Store의 상태를 가져옵니다.
     loginUser() {
       const authStore = useAuthStore();
       return authStore.getLoginUser;
     },
   },
+
   methods: {
     updateMember() {
-        // Add the search query to the selectedMembers array if it's not empty
-        if (this.searchQuery.trim()) {
-          this.selectedMember.push(this.searchQuery.trim());
-        }
-        // Clear the search query after adding it to selectedMembers
-        this.searchQuery = '';
-      },
-    // 폼 검증 메서드
+      // Add the search query to the selectedMembers array if it's not empty
+      if (this.searchQuery.trim()) {
+        this.selectedMember.push(this.searchQuery.trim());
+      }
+      // Clear the search query after adding it to selectedMembers
+      this.searchQuery = '';
+    },
     validateForm() {
       // 필수 입력 필드 체크
       if (
@@ -122,8 +126,8 @@
         this.startTime &&
         this.endDate &&
         this.endTime &&
-        this.dayCount > 0 &&
-        this.reason.trim() !== ""
+        this.where &&
+        this.purpose.trim() !== ""
       ) {
         this.isFormValid = true;
       } else {
@@ -160,19 +164,35 @@
     handleSubmit() {
       this.validateForm(); // 제출 시 유효성 확인
       if (this.isFormValid) {
+        localStorage.setItem('ChuljangFormData', JSON.stringify(this.$data));
         alert("승인 요청이 완료되었습니다.");
         // 추가 처리 로직 (API 요청 등)
       } else {
         alert("모든 필드를 올바르게 작성해주세요.");
       }
     },
+    loadFormData() {
+      const savedData = localStorage.getItem('ChuljangFormData');
+      if (savedData) {
+        this.$data = JSON.parse(savedData);
+      }
+    },
+  },
+  mounted() {
+    // Load the saved form data when the page is loaded
+    this.loadFormData();
   },
   watch: {
     startDate: 'calculateDayCount',
     startTime: 'calculateDayCount',
     endDate: 'calculateDayCount',
     endTime: 'calculateDayCount',
-    reason: "validateForm",
+    where: 'validateForm', 
+    purpose: "validateForm", 
   },
 };
 </script>
+
+<style scoped>
+/* 필요한 스타일 추가 */
+</style>
client/views/pages/Employee/ChuljangList.vue
--- client/views/pages/Employee/ChuljangList.vue
+++ client/views/pages/Employee/ChuljangList.vue
@@ -58,18 +58,18 @@
               </thead>
               <!-- 동적으로 <td> 생성 -->
               <tbody>
-                <tr v-for="(item, index) in ChuljangData" :key="item.startDate + index">
+                <tr v-for="(item, index) in ChuljangFormData" :key=" index">
   <td>
     <div class="form-check">
       <label class="form-check-label" for="acceptTerms">{{ index + 1 }}</label>
       <input v-model="item.acceptTerms" class="form-check-input" type="checkbox" />
     </div>
   </td>
-  <td><input type="date" v-model="item.startDate" /></td>
-  <td><input type="date" v-model="item.endDate" /></td>
-  <td><input type="text" v-model="item.where" /></td>
-  <td><input type="text" v-model="item.purpose" /></td>
-  <td ><input type="text" v-model="item.member" />
+  <td>{{ item.startDate }}</td>
+  <td>{{ item.endDate }}</td>
+  <td>{{ item.where }}</td>
+  <td>{{ item.purpose }}</td>
+  <td >{{ item.selectedMember }}
     
   </td>
 </tr>
@@ -94,11 +94,6 @@
       months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], // 월 목록
       selectedYear: '',
       selectedMonth: '',
-      ChuljangData: [
-      { startDate: '', endDate: '', where: '대구', purpose: '',  acceptTerms: false },
-      { startDate: '', endDate: '', where: '경산', acceptTerms: false },
-        // 더 많은 데이터 추가...
-      ],
       filteredData: [],
     };
   },
@@ -152,6 +147,17 @@
       this.currentPage = page;
     },
   },
+  created() {
+  // 로컬스토리지에서 기존 데이터가 있으면 불러오기
+  const storedData = localStorage.getItem('ChuljangFormData');
+  console.log(storedData);
+  if (storedData) {
+    // Parse the data and wrap it in an array
+    const parsedData = JSON.parse(storedData);
+    // Ensure the data is in an array format
+    this.ChuljangFormData = Array.isArray(parsedData) ? parsedData : [parsedData];
+  }
+},
   mounted() {
     
     // 처음에는 모든 데이터를 표시
client/views/pages/Employee/HyugaInsert.vue
--- client/views/pages/Employee/HyugaInsert.vue
+++ client/views/pages/Employee/HyugaInsert.vue
@@ -11,7 +11,7 @@
         <form class="row g-3  pt-3" @submit.prevent="handleSubmit">
           <div class="col-md-9">
             <label for="inputName5" class="form-label">구분</label>
-            <select id="inputState" class="form-select">
+            <select id="category" class="form-select" v-model="category">
               <option selected>연차</option>
               <option>반차</option>
               <option>병가</option>
@@ -68,7 +68,7 @@
 
           <div class="col-12">
             <label for="prvonsh" class="form-label">사유</label>
-            <input type="text" class="form-control" id="prvonsh" v-model="reason" />
+            <input type="text" class="form-control" id="reason" v-model="reason" />
           </div>
 
           <div class="text-end">
@@ -92,8 +92,8 @@
       startTime: "09:00", // 기본 시작 시간 09:00
       endDate: today,
       endTime: "18:00", // 기본 종료 시간 18:00
-      allDay: false, // 종일 여부
-      dayCount: 1, // 사용 휴가일 계산
+      category: "", 
+      dayCount: 1, 
       reason: "", // 사유
     };
   },
@@ -109,6 +109,7 @@
     validateForm() {
       // 필수 입력 필드 체크
       if (
+        this.category &&
         this.startDate &&
         this.startTime &&
         this.endDate &&
@@ -151,12 +152,25 @@
     handleSubmit() {
       this.validateForm(); // 제출 시 유효성 확인
       if (this.isFormValid) {
+        localStorage.setItem('HyugaFormData', JSON.stringify(this.$data));
         alert("승인 요청이 완료되었습니다.");
         // 추가 처리 로직 (API 요청 등)
       } else {
         alert("모든 필드를 올바르게 작성해주세요.");
       }
     },
+    loadFormData() {
+      const savedData = localStorage.getItem('HyugaFormData');
+      if (savedData) {
+        this.$data = JSON.parse(savedData);
+      }
+      console.log(loadFormData)
+    },
+    
+  },
+  mounted() {
+    // Load the saved form data when the page is loaded
+    this.loadFormData();
   },
   watch: {
   startDate: 'calculateDayCount',
@@ -164,6 +178,7 @@
   endDate: 'calculateDayCount',
   endTime: 'calculateDayCount',
   reason: "validateForm",
+  category: 'category',
   },
 };
 </script>
client/views/pages/Employee/HyugaList.vue
--- client/views/pages/Employee/HyugaList.vue
+++ client/views/pages/Employee/HyugaList.vue
@@ -7,29 +7,18 @@
     <div class="row">
       <!-- 해당년도 연차 수 -->
       <!-- 전체 -->
-      <div class="col-xxl-2 col-md-3">
-        <button type="button" class="btn btn-secondary mb-2">
+      <div class="col-xxl-2 col-md-3 mb-2">
+        <button type="button" class="btn btn-secondary ">
           전체 <span class="badge bg-white text-secondary">12개</span>
-              </button>
-        
+        </button>
+        <button type="button" class="btn btn-success ">
+          사용 <span class="badge bg-white text-success">1개</span>
+        </button>
+        <button type="button" class="btn btn-warning">
+          미사용 <span class="badge bg-white text-warning">1개</span>
+        </button>
       </div>
       <!-- End 전체 -->
-
-      <!-- 사용 -->
-      <div class="col-xxl-2 col-md-3">
-        <button type="button" class="btn btn-success mb-2">
-          사용 <span class="badge bg-white text-success">1개</span>
-              </button>
-      </div>
-      <!-- End 사용 -->
-
-      <!-- 미사용 -->
-      <div class="col-xxl-2 col-xl-3">
-        <button type="button" class="btn btn-warning mb-2">
-          미사용 <span class="badge bg-white text-warning">1개</span>
-              </button>
-      </div>
-      <!-- End 미사용 -->
 
       <div class="col-lg-12">
         <div class="card">
@@ -77,7 +66,7 @@
               </thead>
               <!-- 동적으로 <td> 생성 -->
               <tbody>
-                <tr v-for="(item, index) in filteredData" :key="index">
+                <tr v-for="(item, index) in HyugaFormData" :key="index">
                   <td>
                     <div class="form-check">
                       <label class="form-check-label" for="acceptTerms">{{ index + 1 }}</label>
@@ -87,7 +76,7 @@
                   <td>{{ item.category }}</td>
                   <td>{{ item.startDate }}</td>
                   <td>{{ item.endDate }}</td>
-                  <td>{{ item.usedDays }}</td>
+                  <td>{{ item.dayCount }}</td>
                   <td>{{ item.reason }}</td>
                   <td>{{ item.approvalStatus ? '승인' : '대기' }}</td>
                 </tr>
@@ -111,11 +100,6 @@
       months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], // 월 목록
       selectedYear: '',
       selectedMonth: '',
-      vacationData: [
-        { category: '연차', startDate: '2023-01-01', endDate: '2023-01-03', usedDays: 2, reason: '휴식', approvalStatus: true, acceptTerms: false },
-        { category: '병가', startDate: '2024-02-10', endDate: '2024-02-12', usedDays: 2, reason: '병원', approvalStatus: false, acceptTerms: false },
-        { category: '병가', startDate: '2025-01-10', endDate: '2024-02-12', usedDays: 2, reason: '병원', approvalStatus: false, acceptTerms: false },
-      ],
       filteredData: [],
     };
   },
@@ -123,54 +107,64 @@
   },
   methods: {
     deletePending() {
-    // 선택된 항목만 필터링하여 삭제
-    const selectedItems = this.vacationData.filter(item => item.acceptTerms);
+      // 선택된 항목만 필터링하여 삭제
+      const selectedItems = this.vacationData.filter(item => item.acceptTerms);
 
-    // 승인된 항목인지 확인하여 삭제할 수 없으면 경고
-    const nonDeletableItems = selectedItems.filter(item => item.approvalStatus === true);
-    
-    // 삭제할 수 없는 항목이 있으면 경고
-    if (nonDeletableItems.length > 0) {
-      alert("승인된 건은 삭제할 수 없습니다.");
-      return;  // 승인된 항목이 있으면 삭제를 진행하지 않음
-    }
+      // 승인된 항목인지 확인하여 삭제할 수 없으면 경고
+      const nonDeletableItems = selectedItems.filter(item => item.approvalStatus === true);
 
-    // 승인된 항목이 없으면 삭제 진행
-    if (selectedItems.length > 0) {
-      this.vacationData = this.vacationData.filter(item => !item.acceptTerms);
-      alert(`${selectedItems.length}개의 항목이 삭제되었습니다.`);
-    } else {
-      alert("선택된 항목이 없습니다.");
-    }
-  },
+      // 삭제할 수 없는 항목이 있으면 경고
+      if (nonDeletableItems.length > 0) {
+        alert("승인된 건은 삭제할 수 없습니다.");
+        return;  // 승인된 항목이 있으면 삭제를 진행하지 않음
+      }
+
+      // 승인된 항목이 없으면 삭제 진행
+      if (selectedItems.length > 0) {
+        this.vacationData = this.vacationData.filter(item => !item.acceptTerms);
+        alert(`${selectedItems.length}개의 항목이 삭제되었습니다.`);
+      } else {
+        alert("선택된 항목이 없습니다.");
+      }
+    },
     // 날짜 필터 적용
     filterData() {
-    // 전체 선택 시 필터링 없이 모든 데이터를 표시
-    if (!this.selectedYear && !this.selectedMonth) {
-      this.filteredData = this.vacationData;
-    } else {
-      // 선택된 연도와 월에 맞게 필터링
-      this.filteredData = this.vacationData.filter(item => {
-        const itemYear = new Date(item.startDate).getFullYear();
-        const itemMonth = new Date(item.startDate).getMonth() + 1; // 월은 0부터 시작하므로 1을 더해줍니다.
+      // 전체 선택 시 필터링 없이 모든 데이터를 표시
+      if (!this.selectedYear && !this.selectedMonth) {
+        this.filteredData = this.vacationData;
+      } else {
+        // 선택된 연도와 월에 맞게 필터링
+        this.filteredData = this.vacationData.filter(item => {
+          const itemYear = new Date(item.startDate).getFullYear();
+          const itemMonth = new Date(item.startDate).getMonth() + 1; // 월은 0부터 시작하므로 1을 더해줍니다.
 
-        return (
-          (!this.selectedYear || itemYear === parseInt(this.selectedYear)) &&
-          (!this.selectedMonth || itemMonth === parseInt(this.selectedMonth))
-        );
-      });
-    }
-  },
-  
+          return (
+            (!this.selectedYear || itemYear === parseInt(this.selectedYear)) &&
+            (!this.selectedMonth || itemMonth === parseInt(this.selectedMonth))
+          );
+        });
+      }
+    },
+    
 
   },
+  created() {
+      // 로컬스토리지에서 기존 데이터가 있으면 불러오기
+      const storedData = localStorage.getItem('HyugaFormData');
+      console.log(storedData);
+      if (storedData) {
+        // Parse the data and wrap it in an array
+        const parsedData = JSON.parse(storedData);
+        // Ensure the data is in an array format
+        this.HyugaFormData = Array.isArray(parsedData) ? parsedData : [parsedData];
+      }
+    },
   mounted() {
     const currentYear = new Date().getFullYear();
-    this.selectedYear = currentYear; 
+    this.selectedYear = currentYear;
     // 처음에는 현재년도 데이터를 표시
-    this.filteredData = this.vacationData.filter(item => new Date(item.startDate).getFullYear() === currentYear);
   },
-  
+
 };
 </script>
 
 
client/views/pages/Employee/HyugaOk.vue (added)
+++ client/views/pages/Employee/HyugaOk.vue
@@ -0,0 +1,171 @@
+<template>
+  <div class="pagetitle">
+    <h2>휴가승인</h2>
+  </div>
+  <!-- End Page Title -->
+  <section class="section">
+    <div class="row">
+      <!-- 해당년도 연차 수 -->
+      <!-- 전체 -->
+      <div class="col-xxl-2 col-md-3 mb-2">
+        <button type="button" class="btn btn-secondary ">
+          전체 <span class="badge bg-white text-secondary">12개</span>
+        </button>
+        <button type="button" class="btn btn-success ">
+          사용 <span class="badge bg-white text-success">1개</span>
+        </button>
+        <button type="button" class="btn btn-warning">
+          미사용 <span class="badge bg-white text-warning">1개</span>
+        </button>
+      </div>
+      <!-- End 전체 -->
+
+      <div class="col-lg-12">
+        <div class="card">
+          <div class="card-body">
+            <h5 class="card-title">휴가내역</h5>
+            <div class="d-flex pb-3 justify-content-between ">
+
+              <div class="datatable-search d-flex gap-1 ">
+                <div class="col-xxl-5 col-md-3">
+                  <select class="form-select " v-model="selectedYear">
+                    <option value="">전체</option>
+                    <option v-for="year in years" :key="year" :value="year">{{ year }}</option>
+                  </select>
+                </div>
+                <div class="col-xxl-5 col-md-3">
+                  <select class="form-select" v-model="selectedMonth">
+                    <option value="">월</option>
+                    <option v-for="month in months" :key="month" :value="month">{{ month }}</option>
+                  </select>
+                </div>
+                <button type="button" class="btn btn-outline-secondary col-xxl-5 col-xl-3"
+                  @click="filterData">조회</button>
+
+              </div>
+              <div class="d-flex justify-content-end ">
+                <button type="button" class="btn btn-outline-secondary" @click="deletePending">
+                  삭제
+                </button>
+              </div>
+
+            </div>
+            <!-- Table  -->
+            <table id="myTable" class="table datatable table-hover">
+              <!-- 동적으로 <th> 생성 -->
+              <thead>
+                <tr>
+                  <th>No</th>
+                  <th>구분</th>
+                  <th data-type="date" data-format="YYYY/DD/MM">시작일자</th>
+                  <th data-type="date" data-format="YYYY/DD/MM">종료일자</th>
+                  <th>사용일</th>
+                  <th>사유</th>
+                  <th>승인여부</th>
+                </tr>
+              </thead>
+              <!-- 동적으로 <td> 생성 -->
+              <tbody>
+                <tr v-for="(item, index) in HyugaFormData" :key="index">
+                  <td>
+                    <div class="form-check">
+                      <label class="form-check-label" for="acceptTerms">{{ index + 1 }}</label>
+                      <input v-model="item.acceptTerms" class="form-check-input" type="checkbox" />
+                    </div>
+                  </td>
+                  <td>{{ item.category }}</td>
+                  <td>{{ item.startDate }}</td>
+                  <td>{{ item.endDate }}</td>
+                  <td>{{ item.dayCount }}</td>
+                  <td>{{ item.reason }}</td>
+                  <td>{{ item.approvalStatus ? '승인' : '대기' }}</td>
+                </tr>
+              </tbody>
+            </table>
+            <!-- End Table -->
+          </div>
+        </div>
+      </div>
+    </div>
+  </section>
+</template>
+
+<script>
+import { DataTable } from 'simple-datatables'
+export default {
+  data() {
+    return {
+      // 데이터 초기화
+      years: [2023, 2024, 2025], // 연도 목록
+      months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], // 월 목록
+      selectedYear: '',
+      selectedMonth: '',
+      filteredData: [],
+    };
+  },
+  computed: {
+  },
+  methods: {
+    deletePending() {
+      // 선택된 항목만 필터링하여 삭제
+      const selectedItems = this.vacationData.filter(item => item.acceptTerms);
+
+      // 승인된 항목인지 확인하여 삭제할 수 없으면 경고
+      const nonDeletableItems = selectedItems.filter(item => item.approvalStatus === true);
+
+      // 삭제할 수 없는 항목이 있으면 경고
+      if (nonDeletableItems.length > 0) {
+        alert("승인된 건은 삭제할 수 없습니다.");
+        return;  // 승인된 항목이 있으면 삭제를 진행하지 않음
+      }
+
+      // 승인된 항목이 없으면 삭제 진행
+      if (selectedItems.length > 0) {
+        this.vacationData = this.vacationData.filter(item => !item.acceptTerms);
+        alert(`${selectedItems.length}개의 항목이 삭제되었습니다.`);
+      } else {
+        alert("선택된 항목이 없습니다.");
+      }
+    },
+    // 날짜 필터 적용
+    filterData() {
+      // 전체 선택 시 필터링 없이 모든 데이터를 표시
+      if (!this.selectedYear && !this.selectedMonth) {
+        this.filteredData = this.vacationData;
+      } else {
+        // 선택된 연도와 월에 맞게 필터링
+        this.filteredData = this.vacationData.filter(item => {
+          const itemYear = new Date(item.startDate).getFullYear();
+          const itemMonth = new Date(item.startDate).getMonth() + 1; // 월은 0부터 시작하므로 1을 더해줍니다.
+
+          return (
+            (!this.selectedYear || itemYear === parseInt(this.selectedYear)) &&
+            (!this.selectedMonth || itemMonth === parseInt(this.selectedMonth))
+          );
+        });
+      }
+    },
+    
+
+  },
+  created() {
+      // 로컬스토리지에서 기존 데이터가 있으면 불러오기
+      const storedData = localStorage.getItem('HyugaFormData');
+      console.log(storedData);
+      if (storedData) {
+        // Parse the data and wrap it in an array
+        const parsedData = JSON.parse(storedData);
+        // Ensure the data is in an array format
+        this.HyugaFormData = Array.isArray(parsedData) ? parsedData : [parsedData];
+      }
+    },
+  mounted() {
+    const currentYear = new Date().getFullYear();
+    this.selectedYear = currentYear;
+    // 처음에는 현재년도 데이터를 표시
+  },
+
+};
+</script>
+
+<style scoped></style>
client/views/pages/Employee/ProjectInsert.vue
--- client/views/pages/Employee/ProjectInsert.vue
+++ client/views/pages/Employee/ProjectInsert.vue
@@ -42,7 +42,7 @@
               <form class="search-form d-flex  align-items-center" method="POST" action="#"
                 @submit.prevent="updateMember">
                 <input type="text" v-model="searchQuery" name="query" placeholder="Search" title="Enter search keyword">
-                <button type="submit" title="Search"><i class="bi bi-search"></i></button>
+                <button type="submit" title="Search"><PlusOutlined /></button>
               </form>
               <input type="text" class="select-member" :value="selectedMember.join(' ')" >
             </div>
@@ -61,7 +61,7 @@
               <form class="search-form d-flex  align-items-center" method="POST" action="#"
                 @submit.prevent="updateMember">
                 <input type="text" v-model="searchQuery" name="query" placeholder="Search" title="Enter search keyword">
-                <button type="submit" title="Search"><i class="bi bi-search"></i></button>
+                <button type="submit" title="Search"><PlusOutlined /></button>
               </form>
               <input type="text" class="select-member" :value="selectedMember.join(' ')" >
             </div>
@@ -89,6 +89,8 @@
 
 <script>
 import { useAuthStore } from '../../stores/authStore';
+import { PlusOutlined } from '@ant-design/icons-vue';
+
 export default {
   data() {
     const today = new Date().toISOString().split('T')[0];
@@ -108,6 +110,9 @@
       reason: "", // Notes or remarks
     };
   },
+  components: {
+    PlusOutlined,
+  },
   computed: {
     // Pinia Store의 상태를 가져옵니다.
     loginUser() {
client/views/pages/Manager/NoticeInsert.vue
--- client/views/pages/Manager/NoticeInsert.vue
+++ client/views/pages/Manager/NoticeInsert.vue
@@ -5,176 +5,183 @@
   <section class="section">
     <div class="card">
       <div class="card-body pt-3">
-        <table class="form-table" style="width: 100%;">
-          <tbody>
-            <tr>
-              <th class="text-lf">
-                <span>제목</span>
-              </th>
-              <td>
-                <input
-                  type="text"
-                  class="form-control"
-                  placeholder="제목을 입력하세요."
-                />
-              </td>
-            </tr>
-            <tr class="border-top">
-              <th colspan="4" class="text-lf">
-                <span>내용</span>
-              </th>
-            </tr>
-            <tr style="max-height: 600px">
-              <td colspan="4" style="height: 100%" class="pt-0">
-                <ckeditor :editor="editor" v-model="editorData"></ckeditor>
-              </td>
-            </tr>
+        <form @submit.prevent="handleSubmit">
+          <table class="form-table" style="width: 100%;">
+            <tbody>
+              <tr>
+                <th class="text-lf">
+                  <span>제목</span>
+                </th>
+                <td>
+                  <input type="text" class="form-control" placeholder="제목을 입력하세요." v-model="title" required />
+                </td>
+              </tr>
+              <tr class="border-top">
+                <th colspan="4" class="text-lf">
+                  <span>내용</span>
+                </th>
+              </tr>
+              <tr style="max-height: 600px">
+                <td colspan="4" style="height: 100%" class="pt-0">
+                  <ckeditor :editor="editor" required></ckeditor>
+                  <textarea name="" id="" v-model="editorData"></textarea>
+                </td>
+              </tr>
 
-            <!-- 첨부파일 -->
-            <tr class="border-top">
-              <th class="text-lf">
-                첨부파일
-              </th>
-              <td colspan="2">
-                <div class="gd-12 pr0">
-                  <div class="gd-2 pl0 pr0">
-                    <label for="file" class="btn btn-outline-primary">파일찾기</label>
-                    <input
-                      type="file"
-                      id="file"
-                      ref="file"
-                      @change="handleFileInsert"
-                      multiple
-                    />
+              <!-- 첨부파일 -->
+              <tr class="border-top">
+                <th class="text-lf">
+                  첨부파일
+                </th>
+                <td colspan="2">
+                  <div class="gd-12 pr0">
+                    <div class="gd-2 pl0 pr0">
+                      <label for="file" class="btn btn-outline-primary">파일찾기</label>
+                      <input type="file" id="file" ref="file" multiple />
+                    </div>
                   </div>
-                </div>
-              </td>
-            </tr>
+                </td>
+              </tr>
 
-            <!-- 공지글 -->
-            <tr class="border-top">
-              <th class="text-lf">
-                공지글
-              </th>
-              <td colspan="3">
-                <div class="d-flex no-gutters">
-                  <div class="col-md-4">
-                    <input
-                      type="radio"
-                      name="notice"
-                      id="notice-y"
-                      class="mr5"
-                      value="Y"
-                    />
-                    <label for="notice-y">사용</label>
+              <!-- 공지글 -->
+              <tr class="border-top">
+                <th class="text-lf">
+                  공지글
+                </th>
+                <td colspan="3">
+                  <div class="d-flex no-gutters">
+                    <div class="col-md-4">
+                      <input type="radio" name="notice" id="notice-y" class="mr5" value="Y" v-model="notice" required />
+                      <label for="notice-y">사용</label>
+                    </div>
+                    <div class="col-md-4">
+                      <input type="radio" name="notice" id="notice-n" class="mr5" value="N" v-model="notice" required />
+                      <label for="notice-n">미사용</label>
+                    </div>
                   </div>
-                  <div class="col-md-4">
-                    <input
-                      type="radio"
-                      name="notice"
-                      id="notice-n"
-                      class="mr5"
-                      value="N"
-                    />
-                    <label for="notice-n">미사용</label>
-                  </div>
-                </div>
-              </td>
-            </tr>
+                </td>
+              </tr>
 
-            <!-- 공지글 게시기간 -->
-            <tr class="border-top">
-              <th class="text-lf">
-                공지글 게시기간
-              </th>
-              <td colspan="3">
-                <div class="d-flex no-gutters">
-                  <div class="col-md-4">
-                    <input
-                      type="datetime-local"
-                      class="form-control"
-                    />
+              <!-- 공지글 게시기간 -->
+              <tr class="border-top">
+                <th class="text-lf">
+                  공지글 게시기간
+                </th>
+                <td colspan="3">
+                  <div class="d-flex no-gutters">
+                    <div class="col-md-4">
+                      <input type="datetime-local" class="form-control" v-model="startDate" :disabled="notice === 'N'"
+                        required />
+                    </div>
+                    <div class="pd-1">-</div>
+                    <div class="col-md-4">
+                      <input type="datetime-local" class="form-control" v-model="endDate" :disabled="notice === 'N'"
+                        required />
+                    </div>
                   </div>
-                  <div class="pd-1">-</div>
-                  <div class="col-md-4">
-                    <input
-                      type="datetime-local"
-                      class="form-control"
-                    />
-                  </div>
-                </div>
-              </td>
-            </tr>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+          <div class="text-end">
+            <button class="btn btn-primary" type="submit">등록</button>
+            <button class="btn btn-secondary" @click="handleCancel">취소</button>
+          </div>
+        </form>
 
-            <!-- 비밀글 -->
-            <tr class="border-top">
-              <th class="text-lf">
-                비밀글
-              </th>
-              <td colspan="3">
-                <div class="d-flex no-gutters">
-                  <div class="col-md-4">
-                    <input
-                      type="radio"
-                      name="private"
-                      id="private-y"
-                      class="mr5"
-                      value="Y"
-                    />
-                    <label for="private-y">사용</label>
-                  </div>
-                  <div class="col-md-4">
-                    <input
-                      type="radio"
-                      name="private"
-                      id="private-n"
-                      class="mr5"
-                      value="N"
-                    />
-                    <label for="private-n">미사용</label>
-                  </div>
-                </div>
-              </td>
-            </tr>
-          </tbody>
-        </table>
-        <div class="text-end">
-          <button class="btn btn-primary" @click="handleInsert">
-            {{ notice == null ? "등록" : "수정" }}
-          </button>
-          <button class="btn btn-secondary" @click="handleCancel">취소</button>
-        </div>
+
       </div>
     </div>
   </section>
 </template>
 
 <script>
-
 import CKEditor from '@ckeditor/ckeditor5-vue';
 import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
 
 export default {
   components: {
-    ckeditor: CKEditor
+    ckeditor: CKEditor,
   },
   data() {
+    console.log(localStorage.getItem('testKey'));
+    const today = new Date().toISOString().split('T')[0];
+    const todayDatetime = new Date().toISOString().slice(0, 16); // To include time for datetime-local
     return {
-      editor: ClassicEditor,  // Editor build to use
-      editorData: '',         // Data for editor content
+      editor: ClassicEditor,
+      editorData: '', // Data for the editor
+      title: '', // Bind to title input
+      notice: '', // Bind to notice radio buttons
+      startDate: todayDatetime, // Bind to start date
+      endDate: todayDatetime, // Bind to end date
+      isFormValid: true, // To track form validation status
     };
   },
   methods: {
     handleInsert() {
-      console.log('Editor Data:', this.editorData);
+      console.log('Form Data:', {
+        title: this.title,
+        editorData: this.editorData,
+        notice: this.notice,
+        startDate: this.startDate,
+        endDate: this.endDate,
+      });
     },
     handleCancel() {
-      // Your cancel logic
+      // Reset form fields
+      this.title = '';
+      this.editorData = '';
+      this.notice = '';
+      this.startDate = this.endDate = new Date().toISOString().slice(0, 16);
+      // Optionally remove from localStorage
+      localStorage.removeItem('formData');
+    },
+    handleSubmit() {
+      console.log('handleSubmit called');
+      // Validate the form before submission
+      this.validateForm();
+      if (this.isFormValid) {
+        // Save form data to localStorage
+        const formData = {
+          title: this.title,
+          editorData: this.editorData,
+          notice: this.notice,
+          startDate: this.startDate,
+          endDate: this.endDate,
+        };
+        localStorage.setItem('formData', JSON.stringify(formData));
+        alert('등록되었습니다.');
+        // Add further logic here (e.g., API call)
+      } else {
+        alert('모든 필드를 올바르게 작성해주세요.');
+      }
+    },
+    validateForm() {
+      // Check if all required fields are filled
+      this.isFormValid = !!(
+        this.title &&
+        this.editorData &&
+        this.notice &&
+        this.startDate &&
+        this.endDate
+      );
+    },
+    loadFormData() {
+      const savedData = localStorage.getItem('formData');
+      console.log('savedData:', savedData);
+      if (savedData) {
+        const formData = JSON.parse(savedData);
+        this.title = formData.title || '';
+        this.editorData = formData.editorData || '';
+        this.notice = formData.notice || '';
+        this.startDate = formData.startDate || '';
+        this.endDate = formData.endDate || '';
+      }
     },
   },
   mounted() {
-  console.log(CKEditor); // Check if CKEditor is properly imported and available
-}
+    this.loadFormData(); // Load saved data from localStorage
+  },
 };
 </script>
 
@@ -183,9 +190,11 @@
 th {
   padding: 1rem;
 }
+
 th {
   width: 10rem;
 }
+
 #file {
   position: absolute;
   width: 0;
@@ -194,8 +203,10 @@
   overflow: hidden;
   border: 0;
 }
+
 .ckeditor {
   width: 100%;
-  height: 300px;  /* Adjust height as needed */
+  height: 300px;
+  /* Adjust height as needed */
 }
 </style>
client/views/pages/Manager/NoticeList.vue
--- client/views/pages/Manager/NoticeList.vue
+++ client/views/pages/Manager/NoticeList.vue
@@ -64,7 +64,7 @@
               </thead>
               <!-- 동적으로 <td> 생성 -->
               <tbody>
-                <tr v-for="(item, index) in ChuljangData" :key="item.startDate + index">
+                <tr v-for="(item, index) in filteredData" :key="item.startDate + index">
   <td>
     <div class="form-check">
       <label class="form-check-label" for="acceptTerms">{{ index + 1 }}</label>
@@ -88,7 +88,6 @@
 </template>
 
 <script>
-import { DataTable } from 'simple-datatables'
 export default {
   data() {
     return {
@@ -97,11 +96,6 @@
       levels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], // 월 목록
       selectedDept: '',
       selectedlevel: '',
-      ChuljangData: [
-      { startDate: '', endDate: '', where: '대구', purpose: '',  acceptTerms: false },
-      { startDate: '', endDate: '', where: '경산', acceptTerms: false },
-        // 더 많은 데이터 추가...
-      ],
       filteredData: [],
     };
   },
@@ -116,26 +110,55 @@
    
     deletePending() {
     // 선택된 항목만 필터링하여 삭제
-    const selectedItems = this.ChuljangData.filter(item => item.acceptTerms);
+    const selectedItems = this.NoticegData.filter(item => item.acceptTerms);
 
     // 승인된 항목이 없으면 삭제 진행
     if (selectedItems.length > 0) {
-      this.ChuljangData = this.ChuljangData.filter(item => !item.acceptTerms);
+      this.NoticegData = this.NoticegData.filter(item => !item.acceptTerms);
       alert(`${selectedItems.length}개의 항목이 삭제되었습니다.`);
     } else {
       alert("선택된 항목이 없습니다.");
     }
   },
+  filterData() {
+      this.filteredData = this.NoticegData.filter(item => {
+        const matchesDept = this.selectedDept ? item.where.includes(this.selectedDept) : true;
+        const matchesQuery = this.searchQuery ? item.theme.includes(this.searchQuery) : true;
+        return matchesDept && matchesQuery;
+      });
+    },
    
     // 페이지 변경
     changePage(page) {
       this.currentPage = page;
     },
+    loadFormData() {
+      const savedData = localStorage.getItem('formData');
+      console.log(savedData)
+      if (savedData) {
+        const formData = JSON.parse(savedData);
+        this.NoticeData = formData.map(item => ({
+          ...item,
+          acceptTerms: false, // 추가적인 필드 (체크박스)
+        }));
+        this.filteredData = [...this.NoticeData]; // 필터링된 데이터 초기화
+      }
+    },
+  },
+  created() {
+    // 로컬스토리지에서 UserInfoData 불러오기
+    const storedUserInfo = localStorage.getItem('formData');
+    console.log(storedUserInfo);
+    if (storedUserInfo) {
+      // 로컬스토리지에서 데이터를 가져와 UserInfoData에 설정
+      const parsedData = JSON.parse(storedUserInfo);
+      this.UserInfo = Array.isArray(parsedData) ? parsedData : [parsedData];
+    } 
   },
   mounted() {
     
     // 처음에는 모든 데이터를 표시
-    this.filteredData = this.ChuljangData;
+    this.filteredData = this.NoticegData;
   
   },
 };
 
client/views/pages/User/MyPage.vue (added)
+++ client/views/pages/User/MyPage.vue
@@ -0,0 +1,142 @@
+<template>
+  <div class="container">
+
+        <div class="d-flex justify-content-center py-4">
+          <a href="index.html" class="logo d-flex align-items-center w-auto">
+            <!-- <span class="d-none d-lg-block"> <img :src="logo" alt=""></span> -->
+          </a>
+        </div><!-- End Logo -->
+
+        <div class="card mb-3">
+
+          <div class="card-body">
+
+            <div class=" pb-2">
+              <h2 class="card-title text-center pb-0 fs-4">마이페이지</h2>
+            </div>
+
+            <form class="row g-3 needs-validation "  :class="{ 'was-validated': formSubmitted }" @submit.prevent="handleRegister" novalidate>
+              <div class="col-12">
+                <label for="yourName" class="form-label">이름</label>
+                <input  v-model="name" type="text" name="name" class="form-control" id="yourName" required>
+                <div class="invalid-feedback">이름을 입력해주세요.</div>
+              </div>
+              <div class="col-12">
+            <label for="yourdept" class="form-label">부서</label>
+            <select v-model="dept" id="inputState" class="form-select">
+              <option value="" disabled selected>부서를 선택하세요</option>
+      <option v-for="(item, index) in DeptData" :key="index" :value="item.deptNM">
+        {{ item.deptNM }}
+      </option>
+            </select>
+          </div>
+          <div class="col-12">
+                <label for="yourlevel" class="form-label">직급</label>
+                <select v-model="level" id="yourlevel" class="form-select">
+                  <option value="" disabled selected>직급을 선택하세요</option>
+              <option value="level0">계약직(인턴)</option>
+              <option value="level1">사원</option>
+              <option value="level2">주임</option>
+              <option value="level3">대리</option>
+              <option value="level4">과장</option>
+            </select>
+              </div>
+              <div class="col-12">
+                <label for="youremail" class="form-label">Email</label>
+                <div class="input-group has-validation">
+                  <input  v-model="email" type="text" name="username" class="form-control" id="youremail" required readonly>
+                  <div class="invalid-feedback">회사 이메일을 입력해주세요.</div>
+                </div>
+              </div>
+
+              <div class="col-12">
+                <label for="yourPassword" class="form-label">비밀번호 변경</label>
+                <input  v-model="password" type="password" name="password" class="form-control" id="yourPassword" required > 
+                <div class="invalid-feedback">비밀번호를 입력해주세요.</div>
+              </div>
+
+              <div class="col-12">
+                <div class="form-check">
+                  <!-- <input v-model="acceptTerms"  class="form-check-input" name="terms" type="checkbox" value="" id="acceptTerms" required> -->
+                  <!-- <label class="form-check-label" for="acceptTerms">이용약관에 동의합니다.</label> -->
+                  <div class="invalid-feedback">이용약관에 동의하셔야 합니다.</div>
+                </div>
+              </div>
+              <div class="col-12">
+                <button class="btn btn-primary w-100"  type="submit">수정</button>
+              </div>
+            </form>
+
+          </div>
+        </div>
+  </div>
+
+  </template>
+  
+  <script>
+    export default {
+  data() {
+    return {
+      name: '',
+      email: '',
+      password: '',
+      dept: '',
+      level: '',
+      acceptTerms: false,
+      formSubmitted: false,
+      logo: "/client/resources/img/logo_t.png", // 경로를 Vue 프로젝트 구조에 맞게 설정
+    };
+  },
+  methods: {
+    handleRegister() {
+      this.formSubmitted = true; 
+      // 이메일과 비밀번호가 빈 값이 아니어야 한다
+      if (!this.email.includes('@')) {
+    alert('이메일은 @를 포함해야 합니다.');
+    return; // Stop further processing if email is invalid
+  }
+
+  console.log('Email:', this.email);
+  console.log('Password:', this.password);
+  console.log('Name:', this.name);
+  console.log('Accept Terms:', this.acceptTerms);
+      if (this.email && this.password && this.name && this.acceptTerms && this.dept && this.level ) {
+        // 로컬 스토리지에 회원가입 정보 저장
+        const userData = {
+          name: this.name,
+          email: this.email,
+          password: this.password,
+          dept: this.dept,
+          level: this.level,
+        };
+
+        console.log('User Data to be saved:', userData);
+        try {
+      localStorage.setItem("UserInfo", JSON.stringify(userData));
+      alert('회원가입이 완료되었습니다!');
+      
+      // Redirect to login page
+      this.$router.push("/login");
+    } catch (error) {
+      console.error("Error saving to localStorage:", error);
+      alert("회원가입 중 오류가 발생했습니다.");
+    }
+      } else {
+        alert("모든 필드를 입력해주세요.");
+      }
+    },
+  },
+  created() {
+    // 로컬스토리지에서 데이터 불러오기
+    const storedData = localStorage.getItem('DeptData');
+    if (storedData) {
+      this.DeptData = JSON.parse(storedData);
+    }
+  },
+};
+  </script>
+  
+  <style scoped>
+
+  </style>
+  (파일 끝에 줄바꿈 문자 없음)
 
eslint.config.mjs (added)
+++ eslint.config.mjs
@@ -0,0 +1,12 @@
+import globals from "globals";
+import pluginJs from "@eslint/js";
+import pluginReact from "eslint-plugin-react";
+
+
+/** @type {import('eslint').Linter.Config[]} */
+export default [
+  {files: ["**/*.{js,mjs,cjs,jsx}"]},
+  {languageOptions: { globals: globals.browser }},
+  pluginJs.configs.recommended,
+  pluginReact.configs.flat.recommended,
+];(파일 끝에 줄바꿈 문자 없음)
package-lock.json
--- package-lock.json
+++ package-lock.json
This diff is too big to display.
package.json
--- package.json
+++ package.json
@@ -1,5 +1,7 @@
 {
   "dependencies": {
+    "@ant-design/icons": "^5.6.1",
+    "@ant-design/icons-vue": "^7.0.1",
     "@apollo/client": "^3.13.1",
     "@babel/cli": "7.19.3",
     "@babel/core": "7.19.3",
@@ -10,7 +12,9 @@
     "@fullcalendar/daygrid": "^6.1.15",
     "@fullcalendar/vue3": "^6.1.15",
     "@vue/apollo-composable": "^4.2.1",
+    "ant-design-vue": "^4.2.6",
     "babel-loader": "8.2.5",
+    "bootstrap": "^5.3.3",
     "css-loader": "6.7.1",
     "express": "4.18.1",
     "file-loader": "6.2.0",
@@ -25,13 +29,13 @@
     "realgrid": "^2.8.8",
     "rehackt": "^0.1.0",
     "simple-datatables": "^9.2.1",
+    "typeorm": "^0.3.21",
     "url-loader": "4.1.1",
     "vue": "^3.5.13",
     "vue-apollo": "^3.1.2",
     "vue-cookies": "^1.8.6",
     "vue-loader": "^17.0.0",
     "vue-router": "4.1.5",
-    "vue-style-loader": "4.1.3",
     "vue3-sfc-loader": "^0.8.4",
     "vuex": "^4.1.0",
     "webpack": "5.74.0",
@@ -46,5 +50,14 @@
     "linux-dev": "export NODE_ENV=development&&node ./server/modules/web/server.js",
     "webpack-build": "webpack",
     "webpack-build-watch": "webpack --watch"
+  },
+  "devDependencies": {
+    "@eslint/js": "^9.21.0",
+    "eslint": "^9.21.0",
+    "eslint-plugin-react": "^7.37.4",
+    "globals": "^16.0.0",
+    "sass": "^1.85.1",
+    "sass-loader": "^16.0.5",
+    "vue-style-loader": "^4.1.3"
   }
 }
webpack.config.js
--- webpack.config.js
+++ webpack.config.js
@@ -1,7 +1,7 @@
 const path = require('path');
 const { VueLoaderPlugin } = require("vue-loader");
 
-const {PROJECT_NAME, BASE_DIR, SERVICE_STATUS} = require('./Global');
+const { PROJECT_NAME, BASE_DIR, SERVICE_STATUS } = require('./Global');
 
 module.exports = {
   name: PROJECT_NAME,
@@ -13,38 +13,49 @@
   },
 
   module: {
-    rules: [{
-      test: /\.vue?$/,
-      loader: 'vue-loader',
-    }, {
-      test: /\.(js|jsx)?$/,
-      loader: 'babel-loader',
-    }, 
-    {
-      test: /\.css$/,
-      use: ['vue-style-loader', 'css-loader']
-    },
-     {
-      test: /\.(jpe?g|png|gif|svg|ttf|eot|woff|woff2)$/i,
-      use: [{
-        loader:'url-loader',
-        options:{
-          limit:8192,
-          fallback:require.resolve('file-loader')
-        }
-      }]
-    }],
+    rules: [
+      {
+        test: /\.vue$/,
+        loader: 'vue-loader',
+      },
+      {
+        test: /\.(js|jsx)$/,
+        loader: 'babel-loader',
+      },
+      {
+        test: /\.(css|scss)$/,
+        use: [
+          'vue-style-loader',  // Injects styles into the DOM
+          'css-loader',         // Resolves CSS imports
+          'sass-loader'         // Compiles SCSS to CSS
+        ]
+      },
+      {
+        test: /\.(jpe?g|png|gif|svg|ttf|eot|woff|woff2)$/i,
+        use: [{
+          loader: 'url-loader',
+          options: {
+            limit: 8192, // Images smaller than 8KB will be inlined as base64
+            fallback: require.resolve('file-loader') // For larger images, fall back to file-loader
+          }
+        }]
+      }
+    ],
   },
 
-  plugins: [new VueLoaderPlugin()],
+  plugins: [
+    new VueLoaderPlugin(), // Ensures vue files are properly compiled
+  ],
 
   output: {
-    path: `${BASE_DIR}/client/build`,	// __dirname: webpack.config.js 파일이 위치한 경로
-    filename: 'bundle.js'
+    path: path.resolve(BASE_DIR, 'client/build'),  // Absolute path for the output folder
+    filename: 'bundle.js', // The name of the output JavaScript bundle
   },
+
   resolve: {
     alias: {
       'realgrid': path.resolve(__dirname, 'node_modules/realgrid/dist/realgrid.js'),
     },
+    extensions: ['.js', '.vue', '.json', '.scss'] // Added '.scss' for convenience
   },
-}
(파일 끝에 줄바꿈 문자 없음)
+};
Add a comment
List