Parcourir la source

뒤엎기 전 마지막 커밋

DESKTOP-T61HUSC\user il y a 4 mois
Parent
commit
01bf4fbee8
3 fichiers modifiés avec 847 ajouts et 4 suppressions
  1. 344 0
      assets/scss/mode-w-m.scss
  2. 2 4
      components/common/header.vue
  3. 501 0
      pages/view/common/mypage/index.vue

+ 344 - 0
assets/scss/mode-w-m.scss

@@ -6851,4 +6851,348 @@ z
     color: #fff!important;
     gap: 6px !important;
   }
+}
+
+// 마이페이지 스타일
+.mypage-container {
+  min-height: 100vh;
+  background: linear-gradient(135deg, #f8faff 0%, #f0f4ff 100%);
+  
+  .mypage-header {
+    position: relative;
+    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+    color: white;
+    padding: 60px 40px 40px;
+    border-radius: 0 0 30px 30px;
+    margin-bottom: 30px;
+    overflow: hidden;
+    
+    .header-bg {
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="20" cy="20" r="2" fill="rgba(255,255,255,0.1)"/><circle cx="80" cy="40" r="3" fill="rgba(255,255,255,0.08)"/><circle cx="40" cy="80" r="2" fill="rgba(255,255,255,0.12)"/></svg>');
+      opacity: 0.3;
+    }
+    
+    .header-content {
+      position: relative;
+      z-index: 2;
+    }
+    
+    .profile-section {
+      display: flex;
+      align-items: center;
+      gap: 30px;
+    }
+    
+    .profile-avatar {
+      .avatar-placeholder {
+        width: 120px;
+        height: 120px;
+        border-radius: 50%;
+        background: rgba(255, 255, 255, 0.2);
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        backdrop-filter: blur(10px);
+        border: 3px solid rgba(255, 255, 255, 0.3);
+        
+        i {
+          font-size: 60px;
+          color: rgba(255, 255, 255, 0.8);
+        }
+      }
+    }
+    
+    .profile-info {
+      flex: 1;
+      
+      .user-name {
+        font-size: 2.5rem;
+        font-weight: 700;
+        margin-bottom: 8px;
+        text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+      }
+      
+      .user-type {
+        font-size: 1.2rem;
+        opacity: 0.9;
+        margin-bottom: 20px;
+      }
+      
+      .user-stats {
+        display: flex;
+        gap: 40px;
+        
+        .stat-item {
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          
+          .stat-number {
+            font-size: 2rem;
+            font-weight: 700;
+            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+          }
+          
+          .stat-label {
+            font-size: 0.9rem;
+            opacity: 0.8;
+            margin-top: 4px;
+          }
+        }
+      }
+    }
+  }
+  
+  .dashboard-section {
+    padding: 0 40px 40px;
+    
+    .dashboard-cards {
+      display: grid;
+      grid-template-columns: 1fr 1fr 1fr;
+      gap: 30px;
+    }
+    
+    .dashboard-card {
+      background: white;
+      border-radius: 20px;
+      box-shadow: 0 8px 25px rgba(0, 0, 0, 0.08);
+      transition: all 0.3s ease;
+      overflow: hidden;
+      
+      &:hover {
+        transform: translateY(-5px);
+        box-shadow: 0 15px 35px rgba(0, 0, 0, 0.12);
+      }
+      
+      .card-header {
+        padding: 25px 30px 20px;
+        border-bottom: 1px solid #f0f0f0;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        
+        h3 {
+          font-size: 1.3rem;
+          font-weight: 600;
+          color: #333;
+        }
+        
+        i {
+          font-size: 1.5rem;
+          color: #667eea;
+        }
+      }
+      
+      .card-content {
+        padding: 25px 30px 30px;
+      }
+    }
+    
+    .quick-actions {
+      .action-buttons {
+        display: flex;
+        flex-direction: column;
+        gap: 15px;
+        
+        .action-btn {
+          background: linear-gradient(135deg, #f8faff 0%, #f0f4ff 100%) !important;
+          color: #667eea !important;
+          border: 1px solid #e8f0fe !important;
+          border-radius: 15px !important;
+          padding: 20px !important;
+          height: auto !important;
+          display: flex !important;
+          align-items: center !important;
+          justify-content: flex-start !important;
+          transition: all 0.3s ease !important;
+          
+          &:hover {
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
+            color: white !important;
+            transform: translateX(5px);
+            box-shadow: 0 8px 20px rgba(102, 126, 234, 0.3);
+          }
+          
+          i {
+            font-size: 1.2rem;
+            margin-right: 12px;
+          }
+          
+          span {
+            font-weight: 500;
+          }
+        }
+      }
+    }
+    
+    .recent-inquiries {
+      .inquiry-list {
+        .inquiry-item {
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          padding: 15px 0;
+          border-bottom: 1px solid #f5f5f5;
+          cursor: pointer;
+          transition: all 0.2s ease;
+          
+          &:hover {
+            background: #f8faff;
+            margin: 0 -15px;
+            padding: 15px;
+            border-radius: 10px;
+          }
+          
+          &:last-child {
+            border-bottom: none;
+          }
+          
+          .inquiry-info {
+            h4 {
+              font-size: 1rem;
+              font-weight: 500;
+              color: #333;
+              margin-bottom: 5px;
+              overflow: hidden;
+              text-overflow: ellipsis;
+              white-space: nowrap;
+              max-width: 200px;
+            }
+            
+            p {
+              font-size: 0.85rem;
+              color: #888;
+            }
+          }
+          
+          .inquiry-status {
+            .status-waiting,
+            .status-completed {
+              padding: 4px 12px;
+              border-radius: 20px;
+              font-size: 0.8rem;
+              font-weight: 500;
+            }
+          }
+        }
+        
+        .no-inquiries {
+          text-align: center;
+          padding: 40px 0;
+          color: #999;
+          
+          i {
+            font-size: 3rem;
+            margin-bottom: 15px;
+            display: block;
+          }
+        }
+      }
+      
+      .view-all {
+        text-align: center;
+        margin-top: 20px;
+        padding-top: 20px;
+        border-top: 1px solid #f0f0f0;
+      }
+    }
+    
+    .notifications {
+      .notification-list {
+        .notification-item {
+          display: flex;
+          align-items: flex-start;
+          gap: 15px;
+          padding: 15px 0;
+          
+          .notification-icon {
+            width: 40px;
+            height: 40px;
+            border-radius: 50%;
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            flex-shrink: 0;
+            
+            i {
+              color: white;
+              font-size: 1.1rem;
+            }
+          }
+          
+          .notification-content {
+            h4 {
+              font-size: 1rem;
+              font-weight: 500;
+              color: #333;
+              margin-bottom: 5px;
+            }
+            
+            p {
+              font-size: 0.9rem;
+              color: #666;
+              line-height: 1.4;
+            }
+          }
+        }
+      }
+    }
+  }
+  
+  // 반응형 디자인
+  @media (max-width: 1200px) {
+    .dashboard-section .dashboard-cards {
+      grid-template-columns: 1fr 1fr;
+      
+      .notifications {
+        grid-column: 1 / -1;
+      }
+    }
+  }
+  
+  @media (max-width: 768px) {
+    .mypage-header {
+      padding: 40px 20px 30px;
+      
+      .profile-section {
+        flex-direction: column;
+        text-align: center;
+        gap: 20px;
+      }
+      
+      .profile-avatar .avatar-placeholder {
+        width: 100px;
+        height: 100px;
+        
+        i {
+          font-size: 50px;
+        }
+      }
+      
+      .profile-info {
+        .user-name {
+          font-size: 2rem;
+        }
+        
+        .user-stats {
+          justify-content: center;
+        }
+      }
+    }
+    
+    .dashboard-section {
+      padding: 0 20px 40px;
+      
+      .dashboard-cards {
+        grid-template-columns: 1fr;
+        gap: 20px;
+      }
+    }
+  }
 }

+ 2 - 4
components/common/header.vue

@@ -292,12 +292,10 @@
     logout();
   };
 
-  const myPage = (userId) => {
+  const myPage = () => {
     router.push({
-      path: "/view/mng/mngAdd",
+      path: "/view/common/mypage",
     });
-    useDtStore.adminInfo.adminId = userId;
-    useDtStore.adminInfo.pageType = "U";
   };
 
   const withdrawal = () => {

+ 501 - 0
pages/view/common/mypage/index.vue

@@ -0,0 +1,501 @@
+<template>
+  <div class="mypage-container">
+    <!-- 헤더 섹션 -->
+    <div class="mypage-header">
+      <div class="header-bg"></div>
+      <div class="header-content">
+        <div class="profile-section">
+          <div class="profile-avatar">
+            <div class="avatar-placeholder">
+              <i class="mdi mdi-account"></i>
+            </div>
+          </div>
+          <div class="profile-info">
+            <h1 class="user-name">{{ useAtStore.auth.nickName || useAtStore.auth.companyName || '사용자' }}</h1>
+            <p class="user-type">{{ memberType === 'INFLUENCER' ? '인플루언서' : memberType === 'VENDOR' ? '벤더사' : '관리자' }}</p>
+            <div class="user-stats">
+              <div class="stat-item">
+                <span class="stat-number">{{ csList.length }}</span>
+                <span class="stat-label">문의 내역</span>
+              </div>
+              <div class="stat-item">
+                <span class="stat-number">{{ completedInquiries }}</span>
+                <span class="stat-label">답변 완료</span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 대시보드 섹션 -->
+    <div class="dashboard-section">
+      <div class="dashboard-cards">
+        <!-- 빠른 액션 카드 -->
+        <div class="dashboard-card quick-actions">
+          <div class="card-header">
+            <h3>빠른 작업</h3>
+            <i class="mdi mdi-lightning-bolt"></i>
+          </div>
+          <div class="card-content">
+            <div class="action-buttons">
+              <v-btn class="action-btn" @click="addLocated()">
+                <i class="mdi mdi-plus-circle"></i>
+                <span>문의 등록</span>
+              </v-btn>
+              <v-btn class="action-btn" @click="goToCS()">
+                <i class="mdi mdi-headset"></i>
+                <span>고객센터</span>
+              </v-btn>
+              <v-btn class="action-btn" @click="goToProfile()">
+                <i class="mdi mdi-account-edit"></i>
+                <span>프로필 수정</span>
+              </v-btn>
+            </div>
+          </div>
+        </div>
+
+        <!-- 최근 문의 카드 -->
+        <div class="dashboard-card recent-inquiries">
+          <div class="card-header">
+            <h3>최근 문의 내역</h3>
+            <i class="mdi mdi-message-text"></i>
+          </div>
+          <div class="card-content">
+            <div class="inquiry-list">
+              <div v-if="recentInquiries.length > 0">
+                <div 
+                  v-for="item in recentInquiries" 
+                  :key="item.SEQ" 
+                  class="inquiry-item"
+                  @click="toItemDetail(item.SEQ)"
+                >
+                  <div class="inquiry-info">
+                    <h4>{{ item.TITLE }}</h4>
+                    <p>{{ formatDate(item.REGDATE) }}</p>
+                  </div>
+                  <div class="inquiry-status">
+                    <span :class="getStatusClass(item.STATUS)">
+                      {{ item.STATUS == '0' ? '답변대기' : '답변완료' }}
+                    </span>
+                  </div>
+                </div>
+              </div>
+              <div v-else class="no-inquiries">
+                <i class="mdi mdi-message-outline"></i>
+                <p>등록된 문의가 없습니다</p>
+              </div>
+            </div>
+            <div class="view-all">
+              <v-btn variant="text" @click="goToCS()">전체 보기</v-btn>
+            </div>
+          </div>
+        </div>
+
+        <!-- 알림 카드 -->
+        <div class="dashboard-card notifications">
+          <div class="card-header">
+            <h3>알림</h3>
+            <i class="mdi mdi-bell"></i>
+          </div>
+          <div class="card-content">
+            <div class="notification-list">
+              <div class="notification-item">
+                <div class="notification-icon">
+                  <i class="mdi mdi-information"></i>
+                </div>
+                <div class="notification-content">
+                  <h4>서비스 업데이트</h4>
+                  <p>새로운 기능이 추가되었습니다!</p>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 문의 등록 팝업 -->
+    <v-dialog v-model="showInquiryModal" max-width="600px" persistent>
+      <v-card class="inquiry-modal">
+        <v-card-title class="modal-header">
+          <h3>문의 등록</h3>
+          <v-btn icon @click="closeModal" class="close-btn">
+            <v-icon>mdi-close</v-icon>
+          </v-btn>
+        </v-card-title>
+
+        <v-card-text class="modal-body">
+          <form @submit.prevent="submitInquiry">
+            <div class="form-group">
+              <label>문의 유형 <span class="required">*</span></label>
+              <v-select
+                v-model="inquiryForm.category"
+                :items="categoryOptions"
+                variant="outlined"
+                placeholder="문의 유형을 선택하세요"
+                class="custom-select"
+                :rules="[v => !!v || '문의 유형을 선택해주세요']"
+              ></v-select>
+            </div>
+
+            <div class="form-group">
+              <label>제목 <span class="required">*</span></label>
+              <v-text-field
+                v-model="inquiryForm.title"
+                variant="outlined"
+                placeholder="문의 제목을 입력하세요"
+                class="custom-input"
+                :rules="[v => !!v || '제목을 입력해주세요']"
+              ></v-text-field>
+            </div>
+
+            <div class="form-group">
+              <label>내용 <span class="required">*</span></label>
+              <v-textarea
+                v-model="inquiryForm.content"
+                variant="outlined"
+                placeholder="문의 내용을 상세히 입력해주세요"
+                rows="6"
+                class="custom-textarea"
+                :rules="[v => !!v || '내용을 입력해주세요']"
+              ></v-textarea>
+            </div>
+
+            <div class="form-group">
+              <label>첨부파일</label>
+              <v-file-input
+                v-model="inquiryForm.attachments"
+                variant="outlined"
+                placeholder="파일을 선택하세요"
+                hide-details=""
+                prepend-icon=""
+                append-inner-icon="mdi-paperclip"
+                class="custom-file-input mb--30"
+                accept="image/*,.pdf,.doc,.docx,.hwp"
+                multiple
+                show-size
+              ></v-file-input>
+              <p class="file-info">* 이미지, PDF, 문서 파일만 업로드 가능 (최대 10MB)</p>
+            </div>
+          </form>
+        </v-card-text>
+
+        <v-card-actions class="modal-footer">
+          <v-btn @click="closeModal" class="cancel-btn">취소</v-btn>
+          <v-btn @click="submitInquiry" class="submit-btn" :loading="isSubmitting">등록하기</v-btn>
+        </v-card-actions>
+      </v-card>
+    </v-dialog>
+  </div>
+</template>
+
+<script setup>
+import "@vuepic/vue-datepicker/dist/main.css";
+import dayjs from 'dayjs';
+  /************************************************************************
+|    레이아웃
+************************************************************************/
+  definePageMeta({
+    layout: "default",
+  });
+  /************************************************************************
+|   PROPS
+ ************************************************************************/
+  const props = defineProps({
+    propsData: {
+      type: Object,
+      default: () => {},
+    },
+  });
+  /************************************************************************
+|    스토어
+ ************************************************************************/
+  const useDtStore = useDetailStore();
+  const useAtStore = useAuthStore();
+  /************************************************************************
+|    전역
+ ************************************************************************/
+  const memberType = useAtStore.auth.memberType;
+  const searchModel = ref("");
+  const selectedRange = ref('all');
+  const searchStartDate = ref("");
+  const searchEndDate = ref("");
+  const dateOptions = [
+    { label: '오늘', value: 'today' },
+    { label: '7일', value: '7d' },
+    { label: '1개월', value: '1m' },
+    { label: '3개월', value: '3m' },
+    { label: '전체', value: 'all' },
+  ]
+  const datePickerFormat = "yyyy-MM-dd";
+  const filter = ref("");
+  const filderArr = ref([
+    { title: "전체", value: "" },
+    { title: "제목", value: "title" },
+    { title: "내용", value: "content" },
+    { title: "작성자", value: "writer" }
+  ]);
+  const { $toast, $log, $dayjs, $eventBus } = useNuxtApp();
+  const router = useRouter();
+  const pageId = computed(() => {
+    return '마이페이지';
+  });
+  const csList = ref([]);
+  
+  // 대시보드 관련 computed
+  const completedInquiries = computed(() => {
+    return csList.value.filter(item => item.STATUS === '1').length;
+  });
+  
+  const recentInquiries = computed(() => {
+    return csList.value.slice(0, 3); // 최근 3개만 표시
+  });
+
+  // 문의 등록 팝업 관련
+  const showInquiryModal = ref(false);
+  const isSubmitting = ref(false);
+  const inquiryForm = ref({
+    category: '',
+    title: '',
+    content: '',
+    attachments: []
+  });
+  const categoryOptions = ref([
+    { title: '기능문의', value: 'D' },
+    { title: '기타문의', value: 'E' }
+  ]);
+
+  /* eslint-disable */
+  /* prettier-ignore */
+
+  /************************************************************************
+|    함수(METHODS)
+************************************************************************/
+
+  const isRecentUpdate = (dateStr) => {
+    const today = new Date();
+    const updateDate = new Date(dateStr);
+    const diffDays = (today - updateDate) / (1000 * 60 * 60 * 24);
+    // 업데이트 날짜가 오늘 날짜 기준 최근 7일인지 확인
+    return diffDays <= 7;
+  }
+
+  const paginatedItems = computed(() => {
+    const start = (currentPage.value - 1) * itemsPerPage;
+    return csList.value.slice(start, start + itemsPerPage);
+  });
+
+  const setDateRange = (range) => {
+    const today = dayjs();
+
+    switch(range) {
+      case 'today' :
+        searchStartDate.value = today.format('YYYY-MM-DD');
+        searchEndDate.value = today.format('YYYY-MM-DD');
+        selectedRange.value = 'today';
+        break;
+      case '7d':
+        searchStartDate.value = today.subtract(7, 'day').format('YYYY-MM-DD');
+        searchEndDate.value = today.format('YYYY-MM-DD');
+        selectedRange.value = '7d';
+        break;
+      case '1m':
+        searchStartDate.value = today.subtract(1, 'month').format('YYYY-MM-DD');
+        searchEndDate.value = today.format('YYYY-MM-DD');
+        selectedRange.value = '1m';
+        break;
+      case '3m':
+        searchStartDate.value = today.subtract(3, 'month').format('YYYY-MM-DD');
+        searchEndDate.value = today.format('YYYY-MM-DD');
+        selectedRange.value = '3m';
+        break;
+      case 'all':
+        searchStartDate.value = "";
+        searchEndDate.value = today.format('YYYY-MM-DD');
+        selectedRange.value = 'all';
+        break
+    }
+  }
+
+  const addLocated = () => {
+    showInquiryModal.value = true;
+  };
+  
+  const goToCS = () => {
+    router.push('/view/common/cs');
+  };
+  
+  const goToProfile = () => {
+    $toast.info('프로필 수정 기능은 준비중입니다.');
+  };
+
+  const toItemDetail = (__EVENT) => {
+    router.push({
+      path: "/view/common/cs/detail",
+    });
+    useDtStore.boardInfo.seq = __EVENT;
+  };
+
+  const csListGet = async () => {
+    let _req = {
+      USER_SEQ : useAtStore.auth.seq,
+      keyword: '',
+      filter: '',
+      startDate: '',
+      endDate: ''
+    };
+    if(useAtStore.auth.seq == 2){
+      _req.USER_SEQ = 0;
+    }
+
+    await useAxios()
+      .post("/cs/list", _req)
+      .then((res) => {
+        csList.value = res.data;
+      });
+  };
+
+  const fnSearch = (__KEYWORD, __FILTER) => {
+    let _req = {
+      USER_SEQ: useAtStore.auth.seq,
+      filter: __FILTER,
+      keyword: __KEYWORD,
+      startDate: searchStartDate.value ? dayjs(searchStartDate.value).format('YYYY-MM-DD') : '',
+      endDate: searchEndDate.value ? dayjs(searchEndDate.value).format('YYYY-MM-DD') : ''
+    };
+
+    // 관리자인 경우 모든 문의 조회
+    if(useAtStore.auth.seq == 2){
+      _req.USER_SEQ = 0;
+    }
+
+    useAxios()
+      .post("/cs/search", _req)
+      .then((res) => {
+        csList.value = res.data;
+        currentPage.value = 1; // 검색 후 첫 페이지로 이동
+      })
+      .catch((error) => {
+        console.error('검색 실패:', error);
+        $toast.error('검색에 실패했습니다.');
+      });
+  };
+
+
+  const goToDeliveryDetail = (item) => {
+    // 제품 정보를 스토어에 저장
+    useDtStore.boardInfo.seq = item.SEQ;
+    useDtStore.boardInfo.pageType = "D";
+    
+    // 배송 관리 페이지로 이동
+    router.push({
+      path: "/view/common/deli/detail",
+      query: {
+        itemId: item.SEQ,
+        itemName: item.NAME,
+        price1: item.PRICE1,
+        price2: item.PRICE2 || item.PRICE1,
+        thumbFile: item.THUMB_FILE || ''
+      }
+    });
+  };
+
+  const getStatusClass = (status) => {
+    switch(status) {
+      case '0':
+        return 'status-waiting';
+      case '1':
+        return 'status-completed';
+    }
+  };
+
+  const formatDate = (dateStr) => {
+    if (!dateStr) return '';
+    const date = new Date(dateStr);
+    const year = date.getFullYear();
+    const month = String(date.getMonth() + 1).padStart(2, '0');
+    const day = String(date.getDate()).padStart(2, '0');
+    return `${year}.${month}.${day}`;
+  };
+
+  // 팝업 관련 함수들
+  const closeModal = () => {
+    showInquiryModal.value = false;
+    resetForm();
+  };
+
+  const resetForm = () => {
+    inquiryForm.value = {
+      category: '',
+      title: '',
+      content: '',
+      attachments: []
+    };
+  };
+
+  const submitInquiry = async () => {
+    // 폼 유효성 검사
+    if (!inquiryForm.value.category) {
+      $toast.error('문의 유형을 선택해주세요.');
+      return;
+    }
+    if (!inquiryForm.value.title) {
+      $toast.error('제목을 입력해주세요.');
+      return;
+    }
+    if (!inquiryForm.value.content) {
+      $toast.error('내용을 입력해주세요.');
+      return;
+    }
+
+    isSubmitting.value = true;
+    
+    try {
+      const formData = new FormData();
+      formData.append('USER_SEQ', useAtStore.auth.seq);
+      formData.append('CATEGORY', inquiryForm.value.category);
+      formData.append('TITLE', inquiryForm.value.title);
+      formData.append('CONTENT', inquiryForm.value.content);
+      
+      // 첨부파일 처리
+      if (inquiryForm.value.attachments && inquiryForm.value.attachments.length > 0) {
+        inquiryForm.value.attachments.forEach((file, index) => {
+          formData.append(`files[${index}]`, file);
+        });
+      }
+
+      await useAxios()
+        .post("/cs/reg", formData, {
+          headers: {
+            'Content-Type': 'multipart/form-data'
+          }
+        })
+        .then((res) => {
+          if (res.data.success) {
+            $toast.success('문의가 성공적으로 등록되었습니다.');
+            closeModal();
+            csListGet(); // 목록 새로고침
+          } else {
+            $toast.error('문의 등록에 실패했습니다.');
+          }
+        });
+    } catch (error) {
+      $toast.error('문의 등록 중 오류가 발생했습니다.');
+      console.error('Error submitting inquiry:', error);
+    } finally {
+      isSubmitting.value = false;
+    }
+  };
+
+  /************************************************************************
+|    WATCH
+************************************************************************/
+  onMounted(() => {
+    csListGet();
+
+    // 날짜 초기화
+    const today = dayjs();
+    searchEndDate.value = today.format('YYYY-MM-DD');
+  });
+</script>