Explorar el Código

브랜드사 분기처리, 공동구매 수정/등록/마감/조회 완료, 엑셀 업로드 작업 필요

DESKTOP-T61HUSC\user hace 4 meses
padre
commit
d3f34f853c

+ 1 - 1
assets/scss/default.scss

@@ -36,7 +36,7 @@
     }
 
     .main{
-      padding:1.625rem;
+      padding: 20px;
       width:calc(100%);     
 
       .data--list--wrap{

+ 1 - 1
assets/scss/main.scss

@@ -144,7 +144,7 @@ section {
 
 body {
   line-height: 1;
-  min-width: 1920px;
+  //min-width: 1920px;
 }
 
 ol,

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

@@ -2,6 +2,628 @@
 /**********************************************
 | 2024-08-26 김민정 :
 **********************************************/
+
+// ========== 아이템 추가 페이지 스타일 ==========
+.modern-item-add {
+  min-height: 100vh;
+  background: linear-gradient(135deg, #f8fafc 0%, #e3f2fd 100%);
+
+  .page-header {
+    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+    padding: 3rem 2rem 2rem 2rem;
+    margin-bottom: 2rem;
+    position: relative;
+    overflow: hidden;
+
+    &::before {
+      content: '';
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      background: radial-gradient(circle at 20% 80%, rgba(255,255,255,0.1) 0%, transparent 50%);
+      pointer-events: none;
+    }
+
+    .header-content {
+      max-width: 1200px;
+      margin: 0 auto;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      position: relative;
+      z-index: 2;
+
+      .title-section {
+        .page-title {
+          color: white;
+          font-size: 2.5rem;
+          font-weight: 700;
+          margin: 0 0 0.5rem 0;
+          letter-spacing: -0.02em;
+        }
+
+        .page-subtitle {
+          color: rgba(255,255,255,0.8);
+          font-size: 1.1rem;
+          margin: 0;
+          font-weight: 300;
+        }
+      }
+
+      .breadcrumb-section {
+        .breadcrumb {
+          display: flex;
+          align-items: center;
+          background: rgba(255,255,255,0.1);
+          backdrop-filter: blur(10px);
+          border-radius: 25px;
+          padding: 0.75rem 1.25rem;
+          border: 1px solid rgba(255,255,255,0.2);
+
+          .breadcrumb-item {
+            color: rgba(255,255,255,0.8);
+            font-size: 0.9rem;
+            font-weight: 500;
+            transition: all 0.3s ease;
+
+            &.active {
+              color: white;
+              font-weight: 600;
+            }
+          }
+
+          .breadcrumb-divider {
+            color: rgba(255,255,255,0.5);
+            margin: 0 0.75rem;
+            font-size: 1rem;
+          }
+        }
+      }
+    }
+  }
+
+  .main-content {
+    .form-container {
+      background: white;
+      border-radius: 16px;
+      box-shadow: 0 4px 20px rgba(0,0,0,0.08);
+      overflow: hidden;
+      margin-bottom: 2rem;
+
+      .modern-form {
+        .form-section {
+          padding: 2rem;
+
+          .section-title {
+            display: flex;
+            align-items: center;
+            gap: 0.75rem;
+            font-size: 1.25rem;
+            font-weight: 600;
+            color: #2d3748;
+            margin-bottom: 1.5rem;
+            padding-bottom: 1rem;
+            border-bottom: 2px solid #e2e8f0;
+
+            i {
+              color: #667eea;
+              font-size: 1.5rem;
+            }
+          }
+          .form-field-group{
+            display: flex;
+            width: 100%;
+            gap: 1rem;
+            &.group--2{
+              .form-field{
+                width: calc(50% - 0.5rem);
+              }
+            }
+          }
+
+          .form-field {
+            margin-bottom: 20px;
+
+            .field-label {
+              display: block;
+              font-size: 1rem;
+              font-weight: 600;
+              color: #374151;
+              margin-bottom: 0.75rem;
+
+              .required-mark {
+                color: #ef4444;
+                margin-left: 0.25rem;
+                font-weight: 700;
+              }
+            }
+
+            .field-content {
+              &.df--type{
+                display: flex;
+                gap: 1rem;
+              }
+              &.w--50{
+                width: calc(50% - 0.5rem);
+              }
+              .display-value {
+                padding: 0.875rem 1rem;
+                background: #f8fafc;
+                border: 1px solid #e2e8f0;
+                border-radius: 8px;
+                color: #374151;
+                font-weight: 500;
+
+                &.date-range {
+                  display: flex;
+                  width: 100%;
+                  align-items: center;
+                  gap: 0.5rem;
+                  &.w--50{
+                    width: calc(50% - 0.5rem);
+                  }
+                  i {
+                    color: #667eea;
+                  }
+                }
+
+                &.link-display {
+                  .external-link {
+                    display: flex;
+                    align-items: center;
+                    gap: 0.5rem;
+                    color: #667eea;
+                    text-decoration: none;
+                    font-weight: 500;
+                    transition: all 0.3s ease;
+
+                    &:hover {
+                      color: #764ba2;
+                      text-decoration: underline;
+                    }
+
+                    i {
+                      font-size: 1.1rem;
+                    }
+                  }
+
+                  .no-data {
+                    color: #9ca3af;
+                    font-style: italic;
+                  }
+                }
+              }
+
+              .modern-input {
+                .v-field {
+                  border-radius: 8px;
+                  border: 2px solid #e5e7eb;
+                  background: #fafafa;
+                  transition: all 0.3s ease;
+
+                  &:hover {
+                    border-color: #d1d5db;
+                    background: #fff;
+                  }
+
+                  &.v-field--focused {
+                    border-color: #667eea;
+                    background: #fff;
+                    box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
+                  }
+                }
+              }
+
+              .date-picker-wrapper {
+                .date-picker-group {
+                  display: flex;
+                  align-items: center;
+
+                  .date-picker-item {
+                    .modern-date-picker {
+                      width: 100%;
+                      
+                      .dp__input {
+                        border: 2px solid #e5e7eb;
+                        border-radius: 8px;
+                        font-size: 16px;
+                        padding: 16px;
+                        background: #fafafa;
+                        transition: all 0.3s ease;
+
+                        &:hover {
+                          border-color: #d1d5db;
+                          background: #fff;
+                        }
+
+                        &:focus {
+                          border-color: #667eea;
+                          background: #fff;
+                          box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
+                        }
+                      }
+                    }
+                  }
+
+                  .date-separator {
+                    color: #6b7280;
+                    font-weight: 600;
+                    padding: 0 0.5rem;
+                  }
+                }
+              }
+
+              .selector-wrapper {
+                display: flex;
+                align-items: center;
+                gap: 1rem;
+
+                .selector-input {
+                  flex: 1;
+                }
+
+              }
+              .selector-btn {
+                height: 100%;
+                border-radius: 8px;
+                font-weight: 600;
+                padding: 0.8rem 1.5rem;
+                white-space: nowrap;
+                border: 2px solid #667eea;
+                
+                i {
+                  margin-right: 0.5rem;
+                }
+
+                &:hover {
+                  color: white;
+                  transform: translateY(-1px);
+                  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
+                }
+              }
+              .closed-btn {
+                height: 100%;
+                border-radius: 8px;
+                font-weight: 600;
+                padding: 0.8rem 1.5rem;
+                white-space: nowrap;
+                background: white !important;
+                color: #b00020 !important;
+                border: 2px solid #b00020 !important;
+                transition: all 0.3s ease;
+                
+                i {
+                  margin-right: 0.5rem;
+                }
+
+                &:hover {
+                  transform: translateY(-1px);
+                  box-shadow: 0 4px 12px rgba(220, 38, 38, 0.3);
+                }
+              }
+            }
+          }
+        }
+      }
+      .v-field__outline__start{
+        border: none;
+      }
+      .v-field__outline__end{
+        border: none;
+      }
+    }
+
+    .action-buttons {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+
+      .button-group {
+        display: flex;
+        gap: 1rem;
+
+        .action-btn {
+          border-radius: 8px;
+          font-weight: 600;
+          height: auto;
+          padding: 0.8rem 1.5rem;
+          background-color: #fff;
+          transition: all 0.3s ease;
+
+          i {
+            margin-right: 0.5rem;
+          }
+
+          &.primary {
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+            color: white;
+            border: none;
+
+            &:hover {
+              transform: translateY(-2px);
+              box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
+            }
+          }
+
+          &.secondary {
+            &:hover {
+              background: #f3f4f6;
+              transform: translateY(-1px);
+            }
+          }
+
+          &.danger {
+            &:hover {
+              background: #fef2f2;
+              transform: translateY(-1px);
+            }
+          }
+        }
+      }
+    }
+  }
+
+}
+
+// ========== 인플루언서 모달 전역 스타일 ==========
+.modern-modal {
+  .modal-card {
+    border-radius: 16px !important;
+    overflow: hidden;
+
+    .modal-header {
+      font-size: 1rem;
+      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
+      color: white !important;
+      padding: 1.2rem 1.2rem !important;
+      display: flex !important;
+      justify-content: space-between !important;
+      align-items: center !important;
+
+      .modal-title {
+        display: flex !important;
+        align-items: center !important;
+        gap: 0.75rem !important;
+        font-size: 1rem !important;
+        font-weight: 600 !important;
+
+        i {
+          font-size: 1.2rem !important;
+        }
+      }
+
+      .close-btn {
+        color: rgba(255,255,255,0.8) !important;
+        
+        &:hover {
+          color: white !important;
+          background: rgba(255,255,255,0.1) !important;
+        }
+      }
+    }
+
+    .modal-content {
+      padding: 1.2rem !important;
+
+      .search-section {
+        margin-bottom: 1.2rem;
+
+        .v-field__outline__start{
+          border: none;
+        }
+        .v-field__outline__end{
+          border: none;
+        }
+
+        .search-input {
+          .v-field {
+            border-radius: 12px !important;
+            border: 2px solid #e5e7eb !important;
+            background: #fafafa !important;
+            transition: all 0.3s ease !important;
+
+            &:hover {
+              border-color: #d1d5db !important;
+              background: #fff !important;
+            }
+
+            &.v-field--focused {
+              border-color: #667eea !important;
+              background: #fff !important;
+              box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1) !important;
+            }
+          }
+        }
+      }
+
+      .empty-state {
+        text-align: center !important;
+        padding: 3rem 2rem !important;
+
+        i {
+          font-size: 4rem !important;
+          color: #e5e7eb !important;
+          margin-bottom: 1rem !important;
+        }
+
+        h4 {
+          color: #6b7280 !important;
+          margin-bottom: 0.5rem !important;
+        }
+
+        p {
+          color: #9ca3af !important;
+          font-size: 0.9rem !important;
+        }
+      }
+
+      .influencer-list-container {
+        max-height: 400px !important;
+        overflow-y: auto !important;
+
+        .influencer-list-item {
+          display: flex !important;
+          align-items: center !important;
+          padding: 0.75rem !important;
+          border-radius: 12px !important;
+          cursor: pointer !important;
+          transition: all 0.3s ease !important;
+          border: 2px solid #e5e7eb !important;
+          margin-bottom: 0.75rem !important;
+          position: relative !important;
+
+          &:last-child{
+            margin-bottom: 0!important;
+          }
+
+          &:hover {
+            background: #f8fafc !important;
+            border-color: #667eea !important;
+            transform: translateY(-1px) !important;
+            box-shadow: 0 4px 12px rgba(102, 126, 234, 0.1) !important;
+          }
+
+          &.selected {
+            background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%) !important;
+            border-color: #667eea !important;
+            box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2) !important;
+          }
+
+          .item-avatar {
+            min-width: 50px;
+            margin-right: 0.5rem !important;
+            width: 50px !important;
+            height: 50px !important;
+            display: flex !important;
+            align-items: center !important;
+            justify-content: center !important;
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
+            border-radius: 50% !important;
+
+            i {
+              font-size: 1.75rem !important;
+              color: white !important;
+            }
+          }
+
+          .item-info {
+            display: flex;
+            width: 100%;
+            .nickname {
+              color: #374151 !important;
+              font-size: 1rem !important;
+              font-weight: 600 !important;
+            }
+
+            .name {
+              color: #6b7280 !important;
+              font-size: 0.9rem !important;
+            }
+
+            .sns-info {
+              margin-left: auto;
+              display: flex !important;
+              align-items: center !important;
+              gap: 0.5rem !important;
+              color: #9ca3af !important;
+              font-size: 0.85rem !important;
+
+              i {
+                font-size: 1rem !important;
+                color: #667eea !important;
+              }
+            }
+          }
+
+          .item-check {
+            width: 24px !important;
+            height: 24px !important;
+            display: flex !important;
+            align-items: center !important;
+            justify-content: center !important;
+
+            i {
+              font-size: 1.5rem !important;
+              color: #667eea !important;
+            }
+          }
+        }
+
+        &::-webkit-scrollbar {
+          width: 6px !important;
+        }
+
+        &::-webkit-scrollbar-track {
+          background: #f1f5f9 !important;
+          border-radius: 3px !important;
+        }
+
+        &::-webkit-scrollbar-thumb {
+          background: #cbd5e1 !important;
+          border-radius: 3px !important;
+          
+          &:hover {
+            background: #94a3b8 !important;
+          }
+        }
+      }
+    }
+
+    .modal-actions {
+      padding: 1.5rem 2rem !important;
+      border-top: 1px solid #e5e7eb !important;
+      background: #f8fafc !important;
+      display: flex !important;
+      align-items: center !important;
+
+      .action-info {
+        color: #6b7280 !important;
+        font-size: 0.9rem !important;
+
+        strong {
+          color: #374151 !important;
+        }
+      }
+
+      .modal-btn {
+        border-radius: 8px !important;
+        font-weight: 600 !important;
+        padding: 0 1.5rem !important;
+        height: 40px !important;
+
+        &.confirm {
+          background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
+          border: none !important;
+          color: white !important;
+
+          &:hover:not(:disabled) {
+            box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3) !important;
+            transform: translateY(-1px) !important;
+          }
+
+          &:disabled {
+            opacity: 0.5 !important;
+            cursor: not-allowed !important;
+          }
+        }
+
+        &.cancel {
+          margin-right: 0.75rem !important;
+
+          &:hover {
+            background: #f3f4f6 !important;
+          }
+        }
+      }
+    }
+  }
+
+  .influencer-modal-card {
+    max-width: 700px !important;
+  }
+}
 .mt--125rem{
   margin-top: 1.25rem;
 }

+ 1 - 1
assets/scss/style.scss

@@ -668,7 +668,7 @@
 }
 
 .v-application__wrap {
-  min-width: 1920px;
+  min-width: 1680px;
 }
 
 

+ 137 - 132
backend/app/Config/Routes.php

@@ -1,103 +1,108 @@
 <?php
-  
-  use CodeIgniter\Router\RouteCollection;
-  
-  /**
-   * @var RouteCollection $routes
-   */
-  $routes->get('auth/googleLogin', 'Auth::googleLogin');
-  $routes->get('auth/callback', 'Auth::callback');
-  $routes->post('auth/joinmember', 'Auth::join');
-  $routes->post('auth/joinvendor', 'Auth::joinVendor');
-  $routes->post('auth/joinbrand', 'Auth::joinBrand');
-  $routes->post('auth/withdrawal', 'Auth::withdrawal'); //구글 회원탈퇴 , 일반회원 탈퇴
-  $routes->post('auth/kakaowithdrawal', 'Auth::kakaoWithdrawal'); //카카오 회웥탈퇴
-  $routes->get('auth/kakaoLogin', 'Auth::kakaoLogin');
-  $routes->get('auth/kakao', 'Auth::kakao');
-  $routes->get('auth/naverLogin', 'Auth::naverLogin');
-  $routes->get('auth/naver', 'Auth::naver');
-  $routes->get('auth/naverWithdrawal', 'Auth::naverWithdrawal');
-  $routes->post('auth/checkId', 'Auth::checkId'); // 사용 중 체크 아이디
-  
-  $routes->get('/', 'Home::index'); //홈화면 리다이렉트용
-  $routes->post('roulette/login', 'Roulette::login'); //로그인 페이지 토큰 상관없이 호출가능
-  $routes->post('roulette/refreshToken', 'Roulette::refreshToken'); //엑세스 토큰이 있어야만 발급 가능
-  
-  $routes->get('alimtalk/send', 'Alimtalk::send');
-  $routes->post('alimtalk/send', 'Alimtalk::send'); // POST 요청인 경우
-  
-  $routes->post('winner/reg', 'Winner::winnerReg');
-  $routes->post('winner/itemcount', 'Winner::itemCount');
-  $routes->post('winner/winnerchk', 'Winner::winnerChk');
-
-// 관리자 라우트
-  $routes->post('mng/list', 'Mng::mnglist');
-  $routes->post('mng/search', 'Mng::mngSearch');
-  $routes->post('mng/reg', 'Mng::mngRegister');
-  $routes->post('mng/chk', 'Mng::mngIDChk');
-  $routes->post('mng/update', 'Mng::mngUpdate');
-  $routes->get('mng/detail/(:segment)', 'Mng::mngDetail/$1');
-  $routes->post('mng/stupdate/(:segment)', 'Mng::mngStatusUpdate/$1');
-  $routes->post('mng/delete/(:segment)', 'Mng::mngDelete/$1');
+
+use CodeIgniter\Router\RouteCollection;
+
+/**
+ * @var RouteCollection $routes
+ */
+$routes->get('auth/googleLogin', 'Auth::googleLogin');
+$routes->get('auth/callback', 'Auth::callback');
+$routes->post('auth/joinmember', 'Auth::join');
+$routes->post('auth/joinvendor', 'Auth::joinVendor');
+$routes->post('auth/joinbrand', 'Auth::joinBrand');
+$routes->post('auth/withdrawal', 'Auth::withdrawal'); //구글 회원탈퇴 , 일반회원 탈퇴
+$routes->post('auth/kakaowithdrawal', 'Auth::kakaoWithdrawal'); //카카오 회웥탈퇴
+$routes->get('auth/kakaoLogin', 'Auth::kakaoLogin');
+$routes->get('auth/kakao', 'Auth::kakao');
+$routes->get('auth/naverLogin', 'Auth::naverLogin');
+$routes->get('auth/naver', 'Auth::naver');
+$routes->get('auth/naverWithdrawal', 'Auth::naverWithdrawal');
+$routes->post('auth/checkId', 'Auth::checkId'); // 사용 중 체크 아이디
+
+$routes->get('/', 'Home::index'); //홈화면 리다이렉트용
+$routes->post('roulette/login', 'Roulette::login'); //로그인 페이지 토큰 상관없이 호출가능
+$routes->post('roulette/refreshToken', 'Roulette::refreshToken'); //엑세스 토큰이 있어야만 발급 가능
+
+$routes->get('alimtalk/send', 'Alimtalk::send');
+$routes->post('alimtalk/send', 'Alimtalk::send'); // POST 요청인 경우
+
+$routes->post('winner/reg', 'Winner::winnerReg');
+$routes->post('winner/itemcount', 'Winner::itemCount');
+$routes->post('winner/winnerchk', 'Winner::winnerChk');
+
+// 유저 라우트
+$routes->post('user/list', 'User::userlist'); // 공동구매 -> 인플루언서 선택
+$routes->post('user/brandlist', 'User::brandlist'); // 공동구매 -> 브랜드사 선택
+$routes->get('user/getInfName/(:num)', 'User::getInfName/$1');
+$routes->get('user/getBrdName/(:num)', 'User::getBrdName/$1');
+
+//$routes->post('user/search', 'User::userSearch');
+//$routes->post('user/reg', 'User::userRegister');
+//$routes->post('user/chk', 'User::userIDChk');
+//$routes->post('user/update', 'User::userUpdate');
+//$routes->get('user/detail/(:segment)', 'User::userDetail/$1');
+//$routes->post('user/stupdate/(:segment)', 'User::userStatusUpdate/$1');
+//$routes->post('user/delete/(:segment)', 'User::userDelete/$1');
 
 // 아이템 라우트
-  $routes->post('item/list', 'Item::itemlist');
-  $routes->post('item/reg', 'Item::itemRegister');
-  $routes->get('item/detail/(:num)', 'Item::itemDetail/$1');
-  $routes->post('item/update/(:num)', 'Item::itemUpdate/$1');
-  $routes->post('item/delete/(:num)', 'Item::itemDelete/$1');
-  $routes->post('item/search', 'Item::itemSearch');
+$routes->post('item/list', 'Item::itemlist');
+$routes->post('item/close/(:num)', 'Item::itemClose/$1');
+$routes->post('item/reg', 'Item::itemRegister');
+$routes->get('item/detail/(:num)', 'Item::itemDetail/$1');
+$routes->post('item/update/(:num)', 'Item::itemUpdate/$1');
+$routes->post('item/delete/(:num)', 'Item::itemDelete/$1');
+$routes->post('item/search', 'Item::itemSearch');
 // 파일 다운로드
-  $routes->get('item/download/(:segment)', 'Item::file/$1');
+$routes->get('item/download/(:segment)', 'Item::file/$1');
 
 // 제품 주문 라우트
-  $routes->post('deli/search', 'Deli::deliSearch');
-  $routes->post('deli/itemlist', 'Deli::itemlist');
-  $routes->post('deli/list', 'Deli::delilist');
-  $routes->post('deli/reg', 'Deli::deliRegister');
+$routes->post('deli/search', 'Deli::deliSearch');
+$routes->post('deli/itemlist', 'Deli::itemlist');
+$routes->post('deli/list', 'Deli::delilist');
+$routes->post('deli/reg', 'Deli::deliRegister');
 
 // 고객센터 라우트
-  $routes->post('cs/list', 'Cs::csList');
-  $routes->post('cs/search', 'Cs::csSearch');
-  $routes->get('cs/detail/(:num)', 'Cs::csDetail/$1');
-  $routes->post('cs/reg', 'Cs::csRegister');
-  $routes->post('cs/answer', 'Cs::csAnswer');
+$routes->post('cs/list', 'Cs::csList');
+$routes->post('cs/search', 'Cs::csSearch');
+$routes->get('cs/detail/(:num)', 'Cs::csDetail/$1');
+$routes->post('cs/reg', 'Cs::csRegister');
+$routes->post('cs/answer', 'Cs::csAnswer');
 // 파일 다운로드
-  $routes->get('cs/download/(:segment)', 'Cs::file/$1');
+$routes->get('cs/download/(:segment)', 'Cs::file/$1');
 
 // API 라우트 그룹
-  $routes->group('api', ['namespace' => 'App\Controllers'], function($routes) {
-    
+$routes->group('api', ['namespace' => 'App\Controllers'], function($routes) {
+
     // 벤더사 관련 API
     $routes->group('vendor', function($routes) {
-      $routes->post('search', 'InfluencerController::searchVendors'); // 기존 VendorInfluencerController → InfluencerController
-      $routes->post('list', 'VendorController::getList');
-      $routes->post('detail', 'VendorController::getDetail');
-      $routes->post('create', 'VendorController::create');
-      $routes->post('update', 'VendorController::update');
-      $routes->post('delete', 'VendorController::delete');
+        $routes->post('search', 'InfluencerController::searchVendors'); // 기존 VendorInfluencerController → InfluencerController
+        $routes->post('list', 'VendorController::getList');
+        $routes->post('detail', 'VendorController::getDetail');
+        $routes->post('create', 'VendorController::create');
+        $routes->post('update', 'VendorController::update');
+        $routes->post('delete', 'VendorController::delete');
     });
-    
+
     // 벤더사-인플루언서 매핑 관련 API는 Routes2.php에서 관리
     // (기존 파트너십 라우팅은 별도 파일로 분리됨)
-    
+
     // 인증 관련 API
     $routes->group('auth', function($routes) {
-      $routes->post('login', 'AuthController::login');
-      $routes->post('logout', 'AuthController::logout');
-      $routes->post('register', 'AuthController::register');
-      $routes->post('refresh', 'AuthController::refreshToken');
-      $routes->post('verify', 'AuthController::verifyToken');
+        $routes->post('login', 'AuthController::login');
+        $routes->post('logout', 'AuthController::logout');
+        $routes->post('register', 'AuthController::register');
+        $routes->post('refresh', 'AuthController::refreshToken');
+        $routes->post('verify', 'AuthController::verifyToken');
     });
-    
+
     // 사용자 관련 API
     $routes->group('user', function($routes) {
-      $routes->post('profile', 'UserController::getProfile');
-      $routes->post('update-profile', 'UserController::updateProfile');
-      $routes->post('change-password', 'UserController::changePassword');
-      $routes->post('upload-avatar', 'UserController::uploadAvatar');
+        $routes->post('profile', 'UserController::getProfile');
+        $routes->post('update-profile', 'UserController::updateProfile');
+        $routes->post('change-password', 'UserController::changePassword');
+        $routes->post('upload-avatar', 'UserController::uploadAvatar');
     });
-    
+
     // 인플루언서 관련 API (새로 추가)
     $routes->group('influencer', function($routes) {
         $routes->post('search-vendors', 'InfluencerController::searchVendors');
@@ -107,88 +112,88 @@
         $routes->post('terminate', 'InfluencerController::terminatePartnership');
         $routes->post('profile', 'InfluencerController::getProfile');
     });
-    
+
     // 제품 관련 API
     $routes->group('item', function($routes) {
-      $routes->post('list', 'ItemController::getList');
-      $routes->post('detail', 'ItemController::getDetail');
-      $routes->post('create', 'ItemController::create');
-      $routes->post('update', 'ItemController::update');
-      $routes->post('delete', 'ItemController::delete');
-      $routes->post('search', 'ItemController::search');
+        $routes->post('list', 'ItemController::getList');
+        $routes->post('detail', 'ItemController::getDetail');
+        $routes->post('create', 'ItemController::create');
+        $routes->post('update', 'ItemController::update');
+        $routes->post('delete', 'ItemController::delete');
+        $routes->post('search', 'ItemController::search');
     });
-    
+
     // 파일 업로드 관련 API
     $routes->group('upload', function($routes) {
-      $routes->post('image', 'UploadController::uploadImage');
-      $routes->post('file', 'UploadController::uploadFile');
-      $routes->post('multiple', 'UploadController::uploadMultiple');
+        $routes->post('image', 'UploadController::uploadImage');
+        $routes->post('file', 'UploadController::uploadFile');
+        $routes->post('multiple', 'UploadController::uploadMultiple');
     });
-    
+
     // 알림 관련 API
     $routes->group('notification', function($routes) {
-      $routes->post('list', 'NotificationController::getList');
-      $routes->post('mark-read', 'NotificationController::markAsRead');
-      $routes->post('mark-all-read', 'NotificationController::markAllAsRead');
-      $routes->post('delete', 'NotificationController::delete');
+        $routes->post('list', 'NotificationController::getList');
+        $routes->post('mark-read', 'NotificationController::markAsRead');
+        $routes->post('mark-all-read', 'NotificationController::markAllAsRead');
+        $routes->post('delete', 'NotificationController::delete');
     });
-    
+
     // 대시보드 관련 API
     $routes->group('dashboard', function($routes) {
-      $routes->post('stats', 'DashboardController::getStats');
-      $routes->post('recent-activities', 'DashboardController::getRecentActivities');
-      $routes->post('chart-data', 'DashboardController::getChartData');
+        $routes->post('stats', 'DashboardController::getStats');
+        $routes->post('recent-activities', 'DashboardController::getRecentActivities');
+        $routes->post('chart-data', 'DashboardController::getChartData');
     });
-  });
+});
 
 // 인증이 필요한 API 라우트 (필터 적용)
-  $routes->group('api', ['namespace' => 'App\Controllers', 'filter' => 'auth'], function($routes) {
-    
+$routes->group('api', ['namespace' => 'App\Controllers', 'filter' => 'auth'], function($routes) {
+
     // 보호된 벤더사-인플루언서 API (VendorInfluencerController → 새 컨트롤러들로 교체)
     $routes->group('vendor-influencer/protected', function($routes) {
-      $routes->post('my-requests', 'InfluencerController::getMyRequests');
-      $routes->post('my-partnerships', 'InfluencerController::getMyPartnerships');
-      $routes->post('pending-approvals', 'VendorController::getPendingApprovals');
+        $routes->post('my-requests', 'InfluencerController::getMyRequests');
+        $routes->post('my-partnerships', 'InfluencerController::getMyPartnerships');
+        $routes->post('pending-approvals', 'VendorController::getPendingApprovals');
     });
-    
+
     // 관리자 전용 API
     $routes->group('admin', ['filter' => 'admin'], function($routes) {
-      $routes->post('vendor-influencer/all', 'AdminController::getAllMappings');
-      $routes->post('vendor-influencer/expired', 'AdminController::getExpiredRequests');
-      $routes->post('vendor-influencer/process-expired', 'AdminController::processExpiredRequests');
-      $routes->post('system/stats', 'AdminController::getSystemStats');
+        $routes->post('vendor-influencer/all', 'AdminController::getAllMappings');
+        $routes->post('vendor-influencer/expired', 'AdminController::getExpiredRequests');
+        $routes->post('vendor-influencer/process-expired', 'AdminController::processExpiredRequests');
+        $routes->post('system/stats', 'AdminController::getSystemStats');
     });
-  });
+});
 
 // 웹훅 및 외부 API
-  $routes->group('webhook', ['namespace' => 'App\Controllers'], function($routes) {
+$routes->group('webhook', ['namespace' => 'App\Controllers'], function($routes) {
     $routes->post('payment/success', 'WebhookController::paymentSuccess');
     $routes->post('payment/failure', 'WebhookController::paymentFailure');
     $routes->post('notification/send', 'WebhookController::sendNotification');
-  });
+});
 
 // 크론잡 및 스케줄러 API
-  $routes->group('cron', ['namespace' => 'App\Controllers', 'filter' => 'cron'], function($routes) {
+$routes->group('cron', ['namespace' => 'App\Controllers', 'filter' => 'cron'], function($routes) {
     $routes->get('process-expired-requests', 'CronController::processExpiredRequests');
     $routes->get('send-reminder-notifications', 'CronController::sendReminderNotifications');
     $routes->get('cleanup-old-data', 'CronController::cleanupOldData');
-  });
+});
 
 // 개발 및 테스트용 라우트 (개발 환경에서만 사용)
-  if (ENVIRONMENT === 'development') {
+if (ENVIRONMENT === 'development') {
     $routes->group('dev', ['namespace' => 'App\Controllers'], function($routes) {
-      $routes->get('test-db', 'DevController::testDatabase');
-      $routes->get('seed-data', 'DevController::seedTestData');
-      $routes->get('clear-cache', 'DevController::clearCache');
-      $routes->post('test-api', 'DevController::testApi');
+        $routes->get('test-db', 'DevController::testDatabase');
+        $routes->get('seed-data', 'DevController::seedTestData');
+        $routes->get('clear-cache', 'DevController::clearCache');
+        $routes->post('test-api', 'DevController::testApi');
     });
-  }
+}
 
 // 디버깅용 라우트 (임시)
-  $routes->group('debug', ['namespace' => 'App\\Controllers'], function($routes) {
+$routes->group('debug', ['namespace' => 'App\\Controllers'], function($routes) {
     $routes->get('foreign-key', 'DebugController::debugForeignKey');
     $routes->get('simple-update', 'DebugController::testSimpleUpdate');
-  });
+});
 
 // =============================================================================
 // 추가 라우팅 파일 로드
@@ -200,7 +205,7 @@ if (file_exists(APPPATH . 'Config/Routes2.php')) {
 }
 
 // 인플루언서 요청 라우트 (기존 구조와 호환성)
-  $routes->group('influencer-request', function($routes) {
+$routes->group('influencer-request', function($routes) {
     $routes->post('create', 'InfluencerController::createApprovalRequest');
     $routes->post('vendor-approval', 'VendorController::processInfluencerRequest'); // 벤더사의 인플루언서 승인/거절
     $routes->post('search-vendors', 'InfluencerController::searchVendors'); // 인플루언서의 벤더사 검색
@@ -210,13 +215,13 @@ if (file_exists(APPPATH . 'Config/Routes2.php')) {
     $routes->post('vendor-terminate', 'VendorController::terminatePartnership'); // 벤더사의 파트너십 해지
     $routes->post('status-stats', 'VendorController::getStatusStats'); // 벤더사 요청 통계
     $routes->post('reapply-request', 'InfluencerController::createReapplyRequest'); // 인플루언서 재승인 요청
-  });
-  
-  $routes->post('api/influencer/profile', 'InfluencerController::getProfile');
-
-    // 디버깅 라우트 (개발용)
-    $routes->get('debug/mapping/(:num)', 'VendorController::debugMappingStatus/$1');
-    $routes->get('debug/mapping', 'VendorController::debugMappingStatus');
-    $routes->get('debug/sync-mapping', 'VendorController::syncMappingStatus');
-    $routes->post('debug/history-insert', 'VendorController::debugHistoryInsert');
+});
+
+$routes->post('api/influencer/profile', 'InfluencerController::getProfile');
+
+// 디버깅 라우트 (개발용)
+$routes->get('debug/mapping/(:num)', 'VendorController::debugMappingStatus/$1');
+$routes->get('debug/mapping', 'VendorController::debugMappingStatus');
+$routes->get('debug/sync-mapping', 'VendorController::syncMappingStatus');
+$routes->post('debug/history-insert', 'VendorController::debugHistoryInsert');
 

+ 63 - 37
backend/app/Controllers/Item.php

@@ -6,7 +6,7 @@ use CodeIgniter\RESTful\ResourceController;
 
 class Item extends ResourceController
 {
-    //이벤트 리스트
+    //아이템 리스트
     public function itemlist()
     {
         $db = \Config\Database::connect();
@@ -20,10 +20,11 @@ class Item extends ResourceController
         $companyNumber = isset($request['COMPANY_NUMBER']) ? $request['COMPANY_NUMBER'] : null;
         $memberSeq = isset($request['MEMBER_SEQ']) ? $request['MEMBER_SEQ'] : null;
 
-        // 쿼리 빌더 (VENDOR_LIST 조인 추가)
+        // 쿼리 빌더 (VENDOR_LIST, BRAND_LIST 조인 추가)
         $builder = $db->table('ITEM_LIST I')
-            ->select('I.*, V.COMPANY_NAME')
+            ->select('I.*, COALESCE(V.COMPANY_NAME, B.COMPANY_NAME) as COMPANY_NAME')
             ->join('VENDOR_LIST V', 'I.COMPANY_NUMBER = V.COMPANY_NUMBER', 'left')
+            ->join('BRAND_LIST B', 'I.COMPANY_NUMBER = B.COMPANY_NUMBER', 'left')
             ->where('I.DEL_YN', 'N');
 
         // 노출중, 비노출 여부 확인
@@ -31,12 +32,17 @@ class Item extends ResourceController
         $builder->where('I.TYPE', $itemType);
 
         // 사용자 타입별 필터링
-        if ($memberType === 'VENDOR' && !empty($companyNumber)) {
-            // 벤더사의 경우: 자사 제품만 조회
-            $builder->where('I.COMPANY_NUMBER', $companyNumber);
-        } elseif ($memberType === 'INFLUENCER' && !empty($memberSeq)) {
+        if ($memberType === 'INFLUENCER' && !empty($memberSeq)) {
             // 인플루언서의 경우: 공동구매 담당 제품만
             $builder->where('I.CONTACT_INF', $memberSeq);
+        } else {
+            if($memberType === 'VENDOR'){
+                // 벤더사의 경우: 자사 제품만 조회
+                $builder->where('I.COMPANY_NUMBER', $companyNumber);
+            } else {
+                $builder->where('I.COMPANY_NUMBER', $companyNumber)
+                    ->orWhere('I.CONTACT_BRD', $memberSeq);
+            }
         }
 
         // 업데이트 날짜 기준으로 정렬
@@ -141,11 +147,11 @@ class Item extends ResourceController
         // 기본 유효성 검사
         if (
             !$request->getPost('name') ||
-            !$request->getPost('price1') ||
-            !$request->getPost('price2') ||
-            !$request->getPost('deli_fee') ||
-            !$request->getPost('sub_title') ||
-            !$request->getPost('detail') ||
+//            !$request->getPost('price1') ||
+//            !$request->getPost('price2') ||
+//            !$request->getPost('deli_fee') ||
+//            !$request->getPost('sub_title') ||
+//            !$request->getPost('detail') ||
             !$request->getPost('company_number')
         ) {
             return $this->respond([
@@ -172,15 +178,16 @@ class Item extends ResourceController
             // 1. ITEM_LIST에 아이템 정보 등록
             $itemData = [
                 'NAME' => $request->getPost('name'),
-                'PRICE1' => $request->getPost('price1'),
-                'PRICE2' => $request->getPost('price2'),
-                'DELI_FEE' => $request->getPost('deli_fee'),
-                'SUB_TITLE' => $request->getPost('sub_title'),
-                'DETAIL' => $request->getPost('detail'),
-                'STATUS' => $request->getPost('status'),
-                'SHOW_YN' => $request->getPost('show_yn'),
-                'ADD_INFO' => $request->getPost('add_info') ?? 0,
+//                'PRICE1' => $request->getPost('price1'),
+//                'PRICE2' => $request->getPost('price2'),
+//                'DELI_FEE' => $request->getPost('deli_fee'),
+//                'SUB_TITLE' => $request->getPost('sub_title'),
+//                'DETAIL' => $request->getPost('detail'),
+                'STATUS' => 0,
+                'SHOW_YN' => 'Y',
+//                'ADD_INFO' => $request->getPost('add_info') ?? 0,
                 'CONTACT_INF' => $request->getPost('contact_inf') ?? 0,
+                'CONTACT_BRD' => $request->getPost('contact_brd') ?? 0,
                 'ORDER_LINK' => $request->getPost('order_link') ?? 0,
                 'ORDER_START_DATE' => $request->getPost('order_start_date'),
                 'ORDER_END_DATE' => $request->getPost('order_end_date'),
@@ -266,11 +273,11 @@ class Item extends ResourceController
         // 기본 유효성 검사
         if (
             !$request->getPost('name') ||
-            !$request->getPost('price1') ||
-            !$request->getPost('price2') ||
-            !$request->getPost('deli_fee') ||
-            !$request->getPost('sub_title') ||
-            !$request->getPost('detail') ||
+//            !$request->getPost('price1') ||
+//            !$request->getPost('price2') ||
+//            !$request->getPost('deli_fee') ||
+//            !$request->getPost('sub_title') ||
+//            !$request->getPost('detail') ||
             !$request->getPost('company_number')
         ) {
             return $this->respond([
@@ -307,23 +314,23 @@ class Item extends ResourceController
         // 업데이트 데이터 준비
         $itemData = [
             'NAME' => $request->getPost('name'),
-            'PRICE1' => $request->getPost('price1'),
-            'PRICE2' => $request->getPost('price2'),
-            'DELI_FEE' => $request->getPost('deli_fee'),
-            'SUB_TITLE' => $request->getPost('sub_title'),
-            'DETAIL' => $request->getPost('detail'),
-            'STATUS' => $request->getPost('status'),
-            'SHOW_YN' => $request->getPost('show_yn'),
-            'ADD_INFO' => $request->getPost('add_info') ?? 0,
-            'COMPANY_NUMBER' => $request->getPost('company_number'),
+////            'PRICE1' => $request->getPost('price1'),
+////            'PRICE2' => $request->getPost('price2'),
+////            'DELI_FEE' => $request->getPost('deli_fee'),
+////            'SUB_TITLE' => $request->getPost('sub_title'),
+////            'DETAIL' => $request->getPost('detail'),
+//            'STATUS' => $request->getPost('status'),
+//            'SHOW_YN' => $request->getPost('show_yn'),
+//            'ADD_INFO' => $request->getPost('add_info') ?? 0,
+//            'COMPANY_NUMBER' => $request->getPost('company_number'),
             'CONTACT_INF' => $request->getPost('contact_inf') ?? 0,
             'ORDER_LINK' => $request->getPost('order_link') ?? 0,
             'ORDER_START_DATE' => $request->getPost('order_start_date'),
             'ORDER_END_DATE' => $request->getPost('order_end_date'),
             'UDPDATE' => $upddate,
-            'THUMB_FILE' => $thumbFileName,
-            'ZIP_FILE' => $zipFileName,
-            'ZIP_FILE_ORIGIN' => $zipOrigin,
+//            'THUMB_FILE' => $thumbFileName,
+//            'ZIP_FILE' => $zipFileName,
+//            'ZIP_FILE_ORIGIN' => $zipOrigin,
         ];
 
         $db->transBegin();
@@ -344,6 +351,25 @@ class Item extends ResourceController
 
     }
 
+
+    //공동구매 마감
+    public function itemClose($seq)
+    {
+        $db = \Config\Database::connect();
+        $db->transBegin();
+
+        $deleted = $db->table('ITEM_LIST')
+            ->where('SEQ', $seq)
+            ->update(['STATUS' => 1]);
+
+        if ($db->transStatus() === false || !$deleted) {
+            $db->transRollback();
+            return $this->respond(['status' => 'fail', 'message' => '공동구매 마감 중 오류가 발생했습니다.']);
+        }
+        $db->transCommit();
+        return $this->respond(['status' => 'success', 'message' => '공동구매가 마감되었습니다.'], 200);
+    }
+
     //아이템 삭제
     public function itemDelete($seq)
     {

+ 0 - 303
backend/app/Controllers/Mng.php

@@ -1,303 +0,0 @@
-<?php
-
-namespace App\Controllers;
-
-use CodeIgniter\RESTful\ResourceController;
-
-class Mng extends ResourceController
-{
-    //관리자 리스트
-    public function mnglist()
-    {
-        // DB 객체 얻기
-        $db = \Config\Database::connect();
-
-        $request = $this->request->getJSON(true);
-        if (!isset($request['compId'])) {
-          return $this->respond([
-            'status' => 'fail',
-            'message' => 'filter(compId)가 누락되었습니다.'
-          ], 400);
-        }
-
-        // ADM_LIST 테이블 모든 레코드 가져오기
-        $status = isset($request['status']) ? $request['status'] : null;
-        $compId = $request['compId'];
-        $builder = $db->table('ADM_LIST');
-
-        if ($compId !== '0-000000') {
-          $builder->where('COMP_ID', $compId);
-        }
-
-        if ($status === '-1') {
-          // 삭제된 관리자만 조회
-          $builder->where('status', '-1');
-        } else {
-          // 디폴트 :: 사용중(사용중,정지)인 관리자만 조회
-          $builder->whereIn('status', ['0', '1']);
-        }
-
-        $lists = $builder->get()->getResultArray();
-
-        // PASSWORD 필드 제거
-        $filtered = array_map(function($row) {
-            unset($row['PASSWORD']);
-            return $row;
-        }, $lists);
-
-        // 역순으로 정렬
-        $filtered = array_reverse($filtered);
-
-        // JSON 응답
-        return $this->respond($filtered, 200);
-    }
-  public function mngSearch()
-  {
-    $db = \Config\Database::connect();
-
-    // 요청 바디에서 filter와 keyword 추출 (예: {filter: "id", keyword: "admin"})
-    $request = $this->request->getJSON(true);
-
-    // 필수값 체크
-    if (
-      !isset($request['compId']) ||
-      !isset($request['filter']) ||
-      !isset($request['keyword']) ||
-      !in_array($request['filter'], ['id', 'name', 'status'])
-    ) {
-      return $this->respond([
-        'status' => 'fail',
-        'message' => 'filter(id, name, status)와 keyword가 필요합니다.'
-      ], 400);
-    }
-
-    $filterMap = [
-      'id' => 'ID',
-      'name' => 'NAME',
-      'status' => 'STATUS'
-    ];
-    $filterColumn = $filterMap[$request['filter']];
-    $keyword = $request['keyword'];
-    $status = isset($request['status']) ? $request['status'] : null;
-    if (!isset($request['compId'])) {
-      return $this->respond([
-        'status' => 'fail',
-        'message' => 'filter(compId)가 누락되었습니다.'
-      ], 400);
-    }
-    $compId = $request['compId'];
-
-    // 평문 검색 (LIKE 연산 사용)
-    $builder = $db->table('ADM_LIST');
-    if ($compId !== '0-000000') {
-      $builder->where('COMP_ID', $compId);
-    }
-
-    // 사용중 관리자 리스트 검색, 삭제 관리자 리스트 검색 분리
-    if ($status === '-1') {
-      $builder->where('STATUS', '-1');
-    } else {
-      $builder->whereIn('STATUS', ['0', '1']);
-    }
-    $builder->like($filterColumn, $keyword);
-
-    $lists = $builder->get()->getResultArray();
-
-    // PASSWORD 제거
-    $filtered = array_map(function($row) {
-      unset($row['PASSWORD']);
-      return $row;
-    }, $lists);
-
-    // 최신순(역순) 정렬 (ID 기준 또는 원하는 기준으로 변경 가능)
-    $filtered = array_reverse($filtered);
-
-    return $this->respond($filtered, 200);
-  }
-
-  //관리자 등록
-  public function mngRegister()
-  {
-    // DB 객체 얻기
-    $db = \Config\Database::connect();
-    $request = $this->request->getJSON(true);
-
-    if (
-      !isset($request['id']) ||
-      !isset($request['password']) ||
-      !isset($request['name']) ||
-      !isset($request['email']) ||
-      !isset($request['phone'])
-    ) {
-      return $this->respond([
-        'status' => 'fail',
-        'message' => '필수 값이 누락됐습니다.(id, password, name, email, phone)'
-      ], 400);
-    }
-
-    // 비밀번호 해시
-    $hashedPassword = password_hash($request['password'], PASSWORD_DEFAULT);
-
-    $mngData = [
-      'id' => $request['id'],
-      'password' => $hashedPassword,
-      'name' => $request['name'],
-      'email' => $request['email'],
-      'regdate' => date('Y-m-d', strtotime($request['regdate'])),
-      'phone' => $request['phone'],
-      'status' => 0,
-      'comp_name' => $request['comp_name'],
-      'comp_id' => $request['comp_id'],
-    ];
-
-    $builder = $db->table('ADM_LIST');
-
-    if ($builder->insert($mngData)) {
-      return $this->respond(['message' => '관리자 등록 성공'], 201);
-    } else {
-      return $this->respond(['error' => '등록 실패'], 500);
-    }
-  }
-  //아이디 중복체크
-  public function mngIDChk(){
-    $db = \Config\Database::connect();
-    $request = $this->request->getJSON(true);
-
-    if (!isset($request['id']) || trim($request['id']) === '') {
-      return $this->respond([
-        'status' => 'fail',
-        'message' => 'ID가 없습니다.'
-      ], 400);
-    }
-    $id = $request['id'];
-
-    // 영어 소문자와 숫자만 허용 (정규식 체크)
-    if (!preg_match('/^[a-z0-9]+$/', $id)) {
-      return $this->respond([
-        'status' => 'fail',
-        'message' => 'ID는 영어 소문자와 숫자만 사용할 수 있습니다.'
-      ], 400);
-    }
-
-    $builder = $db->table('ADM_LIST');
-    $exists = $builder->where('id', $id)->countAllResults();
-
-    if ($exists > 0) {
-      return $this->respond([
-        'status' => 'fail',
-        'message' => '이미 사용 중인 ID입니다.'
-      ], 409);
-    }
-    return $this->respond([
-      'status' => 'success',
-      'message' => '사용 가능한 ID입니다.'
-    ], 200);
-  }
-  //관리자 수정
-  public function mngUpdate(){
-    $db = \Config\Database::connect();
-    $request = $this->request->getJSON(true);
-
-    if (
-      !isset($request['id']) ||
-      !isset($request['name']) ||
-      !isset($request['phone']) ||
-      !isset($request['email']) ||
-      !isset($request['regdate']) ||
-      !isset($request['status'])
-    ) {
-      return $this->respond([
-        'status' => 'fail',
-        'message' => '필수 값이 누락됐습니다.(id, name, phone, email, regdate, status)'
-      ], 400);
-    }
-    $id = $request['id'];
-
-    $mngData = [
-      'EMAIL' => $request['email'],
-      'REGDATE' => date('Y-m-d', strtotime($request['regdate'])),
-      'PHONE' => $request['phone'],
-      'STATUS' => $request['status'],
-      'COMP_NAME' => $request['comp_name'],
-      'COMP_ID' => $request['comp_id'],
-    ];
-
-    //비밀번호 변경시
-    if (!empty($request['password'])) {
-      $mngData['PASSWORD'] = password_hash($request['password'], PASSWORD_DEFAULT);
-    }
-
-    $updated = $db->table('ADM_LIST')->where('ID', $id)->update($mngData);
-
-    if ($updated) {
-      return $this->respond([
-        'status' => 'success',
-        'message' => '관리자 정보가 수정되었습니다.'
-      ], 200);
-    } else {
-      return $this->respond([
-        'status' => 'fail',
-        'message' => '수정에 실패했습니다.'
-      ], 500);
-    }
-  }
-  //관리자 상세
-  public function mngDetail($id)
-  {
-    // DB 객체 얻기
-    $db = \Config\Database::connect();
-
-    $builder = $db->table('ADM_LIST');
-    $mng = $builder->where('id', $id)->get()->getRowArray();
-
-    if($mng){
-      // 보안상 패스워드는 반환 X
-      unset($mng['password']);
-
-      return $this->respond($mng, 200);
-    } else {
-      return $this->respond([
-        'status' => 'fail',
-        'message' => '해당 ID의 관리자가 존재하지 않습니다.'
-      ], 404);
-    }
-  }
-
-  //관리자 상태 변경(삭제, 복원)
-  public function mngStatusUpdate($id){
-    $db = \Config\Database::connect();
-    $mng = $db->table('ADM_LIST')->select('STATUS')->where('ID', $id)->get()->getRowArray();
-    $currentStatus = (int) $mng['STATUS'];
-    if ($currentStatus == -1 ){
-      // 복원 시 사용중 상태로 변경
-      $nextStatus = 0;
-    } else {
-      // 삭제 시 삭제 상태로 변경
-      $nextStatus = -1;
-    }
-    $updated = $db->table('ADM_LIST')
-      ->where('ID', $id)
-      ->update(['STATUS' => $nextStatus, 'REGDATE' => date('Y-m-d') ]);
-
-    if ($updated) {
-      return $this->respond(['status' => 'success', 'message' => '상태 변경 완료', 'new_status' => $nextStatus], 200);
-    } else {
-      return $this->respond(['status' => 'fail', 'message' => '상태 변경 실패']);
-    }
-  }
-
-  //관리자 삭제
-  public function mngDelete($id)
-  {
-    $db = \Config\Database::connect();
-
-    //관리자 삭제
-    $deleted = $db->table('ADM_LIST')->where('ID', $id)->delete();
-
-    if ($deleted) {
-      return $this->respond(['status' => 'success', 'message' => '관리자 영구 삭제!'], 200);
-    } else {
-      return $this->respond(['status' => 'fail', 'message' => '삭제 실패!'], 500);
-    }
-  }
-}

+ 345 - 0
backend/app/Controllers/User.php

@@ -0,0 +1,345 @@
+<?php
+
+namespace App\Controllers;
+
+use CodeIgniter\RESTful\ResourceController;
+
+class User extends ResourceController
+{
+    //유저 리스트
+    public function userlist()
+    {
+        // DB 객체 얻기
+        $db = \Config\Database::connect();
+
+        $request = $this->request->getJSON(true);
+
+        // USER_LIST 테이블 모든 레코드 가져오기
+        $builder = $db->table('USER_LIST');
+        $lists = $builder->get()->getResultArray();
+
+        // PASSWORD 필드 제거
+        $filtered = array_map(function($row) {
+            unset($row['PASSWORD']);
+            return $row;
+        }, $lists);
+
+        // 역순으로 정렬
+        $filtered = array_reverse($filtered);
+
+        // JSON 응답
+        return $this->respond($filtered, 200);
+    }
+    //브랜드 리스트
+    public function brandlist()
+    {
+        // DB 객체 얻기
+        $db = \Config\Database::connect();
+
+        $request = $this->request->getJSON(true);
+
+        $builder = $db->table('BRAND_LIST');
+        $lists = $builder->get()->getResultArray();
+
+        // PASSWORD 필드 제거
+        $filtered = array_map(function($row) {
+            unset($row['PASSWORD']);
+            return $row;
+        }, $lists);
+
+        // 역순으로 정렬
+        $filtered = array_reverse($filtered);
+
+        // JSON 응답
+        return $this->respond($filtered, 200);
+    }
+    public function userSearch()
+    {
+        $db = \Config\Database::connect();
+
+        // 요청 바디에서 filter와 keyword 추출 (예: {filter: "id", keyword: "admin"})
+        $request = $this->request->getJSON(true);
+
+        // 필수값 체크
+        if (
+            !isset($request['compId']) ||
+            !isset($request['filter']) ||
+            !isset($request['keyword']) ||
+            !in_array($request['filter'], ['id', 'name', 'status'])
+        ) {
+            return $this->respond([
+                'status' => 'fail',
+                'message' => 'filter(id, name, status)와 keyword가 필요합니다.'
+            ], 400);
+        }
+
+        $filterMap = [
+            'id' => 'ID',
+            'name' => 'NAME',
+            'status' => 'STATUS'
+        ];
+        $filterColumn = $filterMap[$request['filter']];
+        $keyword = $request['keyword'];
+        $status = isset($request['status']) ? $request['status'] : null;
+        if (!isset($request['compId'])) {
+            return $this->respond([
+                'status' => 'fail',
+                'message' => 'filter(compId)가 누락되었습니다.'
+            ], 400);
+        }
+        $compId = $request['compId'];
+
+        // 평문 검색 (LIKE 연산 사용)
+        $builder = $db->table('ADM_LIST');
+        if ($compId !== '0-000000') {
+            $builder->where('COMP_ID', $compId);
+        }
+
+        // 사용중 관리자 리스트 검색, 삭제 관리자 리스트 검색 분리
+        if ($status === '-1') {
+            $builder->where('STATUS', '-1');
+        } else {
+            $builder->whereIn('STATUS', ['0', '1']);
+        }
+        $builder->like($filterColumn, $keyword);
+
+        $lists = $builder->get()->getResultArray();
+
+        // PASSWORD 제거
+        $filtered = array_map(function($row) {
+            unset($row['PASSWORD']);
+            return $row;
+        }, $lists);
+
+        // 최신순(역순) 정렬 (ID 기준 또는 원하는 기준으로 변경 가능)
+        $filtered = array_reverse($filtered);
+
+        return $this->respond($filtered, 200);
+    }
+
+    //관리자 등록
+    public function userRegister()
+    {
+        // DB 객체 얻기
+        $db = \Config\Database::connect();
+        $request = $this->request->getJSON(true);
+
+        if (
+            !isset($request['id']) ||
+            !isset($request['password']) ||
+            !isset($request['name']) ||
+            !isset($request['email']) ||
+            !isset($request['phone'])
+        ) {
+            return $this->respond([
+                'status' => 'fail',
+                'message' => '필수 값이 누락됐습니다.(id, password, name, email, phone)'
+            ], 400);
+        }
+
+        // 비밀번호 해시
+        $hashedPassword = password_hash($request['password'], PASSWORD_DEFAULT);
+
+        $userData = [
+            'id' => $request['id'],
+            'password' => $hashedPassword,
+            'name' => $request['name'],
+            'email' => $request['email'],
+            'regdate' => date('Y-m-d', strtotime($request['regdate'])),
+            'phone' => $request['phone'],
+            'status' => 0,
+            'comp_name' => $request['comp_name'],
+            'comp_id' => $request['comp_id'],
+        ];
+
+        $builder = $db->table('ADM_LIST');
+
+        if ($builder->insert($userData)) {
+            return $this->respond(['message' => '관리자 등록 성공'], 201);
+        } else {
+            return $this->respond(['error' => '등록 실패'], 500);
+        }
+    }
+    //아이디 중복체크
+    public function userIDChk(){
+        $db = \Config\Database::connect();
+        $request = $this->request->getJSON(true);
+
+        if (!isset($request['id']) || trim($request['id']) === '') {
+            return $this->respond([
+                'status' => 'fail',
+                'message' => 'ID가 없습니다.'
+            ], 400);
+        }
+        $id = $request['id'];
+
+        // 영어 소문자와 숫자만 허용 (정규식 체크)
+        if (!preg_match('/^[a-z0-9]+$/', $id)) {
+            return $this->respond([
+                'status' => 'fail',
+                'message' => 'ID는 영어 소문자와 숫자만 사용할 수 있습니다.'
+            ], 400);
+        }
+
+        $builder = $db->table('ADM_LIST');
+        $exists = $builder->where('id', $id)->countAllResults();
+
+        if ($exists > 0) {
+            return $this->respond([
+                'status' => 'fail',
+                'message' => '이미 사용 중인 ID입니다.'
+            ], 409);
+        }
+        return $this->respond([
+            'status' => 'success',
+            'message' => '사용 가능한 ID입니다.'
+        ], 200);
+    }
+    //관리자 수정
+    public function userUpdate(){
+        $db = \Config\Database::connect();
+        $request = $this->request->getJSON(true);
+
+        if (
+            !isset($request['id']) ||
+            !isset($request['name']) ||
+            !isset($request['phone']) ||
+            !isset($request['email']) ||
+            !isset($request['regdate']) ||
+            !isset($request['status'])
+        ) {
+            return $this->respond([
+                'status' => 'fail',
+                'message' => '필수 값이 누락됐습니다.(id, name, phone, email, regdate, status)'
+            ], 400);
+        }
+        $id = $request['id'];
+
+        $userData = [
+            'EMAIL' => $request['email'],
+            'REGDATE' => date('Y-m-d', strtotime($request['regdate'])),
+            'PHONE' => $request['phone'],
+            'STATUS' => $request['status'],
+            'COMP_NAME' => $request['comp_name'],
+            'COMP_ID' => $request['comp_id'],
+        ];
+
+        //비밀번호 변경시
+        if (!empty($request['password'])) {
+            $userData['PASSWORD'] = password_hash($request['password'], PASSWORD_DEFAULT);
+        }
+
+        $updated = $db->table('ADM_LIST')->where('ID', $id)->update($userData);
+
+        if ($updated) {
+            return $this->respond([
+                'status' => 'success',
+                'message' => '관리자 정보가 수정되었습니다.'
+            ], 200);
+        } else {
+            return $this->respond([
+                'status' => 'fail',
+                'message' => '수정에 실패했습니다.'
+            ], 500);
+        }
+    }
+    //관리자 상세
+    public function userDetail($id)
+    {
+        // DB 객체 얻기
+        $db = \Config\Database::connect();
+
+        $builder = $db->table('ADM_LIST');
+        $user = $builder->where('id', $id)->get()->getRowArray();
+
+        if($user){
+            // 보안상 패스워드는 반환 X
+            unset($user['password']);
+
+            return $this->respond($user, 200);
+        } else {
+            return $this->respond([
+                'status' => 'fail',
+                'message' => '해당 ID의 관리자가 존재하지 않습니다.'
+            ], 404);
+        }
+    }
+
+    //관리자 상태 변경(삭제, 복원)
+    public function userStatusUpdate($id){
+        $db = \Config\Database::connect();
+        $user = $db->table('ADM_LIST')->select('STATUS')->where('ID', $id)->get()->getRowArray();
+        $currentStatus = (int) $user['STATUS'];
+        if ($currentStatus == -1 ){
+            // 복원 시 사용중 상태로 변경
+            $nextStatus = 0;
+        } else {
+            // 삭제 시 삭제 상태로 변경
+            $nextStatus = -1;
+        }
+        $updated = $db->table('ADM_LIST')
+            ->where('ID', $id)
+            ->update(['STATUS' => $nextStatus, 'REGDATE' => date('Y-m-d') ]);
+
+        if ($updated) {
+            return $this->respond(['status' => 'success', 'message' => '상태 변경 완료', 'new_status' => $nextStatus], 200);
+        } else {
+            return $this->respond(['status' => 'fail', 'message' => '상태 변경 실패']);
+        }
+    }
+
+    // contact_inf로 사용자 정보 조회
+    public function getInfName($seq)
+    {
+        $db = \Config\Database::connect();
+
+        // SEQ로 USER_LIST에서 사용자 정보 조회
+        $builder = $db->table('USER_LIST');
+        $user = $builder->select('SEQ, NAME, NICK_NAME')
+            ->where('SEQ', $seq)
+            ->get()
+            ->getRowArray();
+
+        if ($user) {
+            return $this->respond([
+                'status' => 'success',
+                'data' => [
+                    'SEQ' => $user['SEQ'],
+                    'NAME' => $user['NAME'],
+                    'NICK_NAME' => $user['NICK_NAME']
+                ]
+            ], 200);
+        } else {
+            return $this->respond([
+                'status' => 'fail',
+                'message' => '해당 SEQ의 사용자를 찾을 수 없습니다.'
+            ], 404);
+        }
+    }
+
+    public function getBrdName($seq)
+    {
+        $db = \Config\Database::connect();
+
+        $builder = $db->table('BRAND_LIST');
+        $user = $builder->select('SEQ, COMPANY_NAME')
+            ->where('SEQ', $seq)
+            ->get()
+            ->getRowArray();
+
+        if ($user) {
+            return $this->respond([
+                'status' => 'success',
+                'data' => [
+                    'SEQ' => $user['SEQ'],
+                    'NAME' => $user['COMPANY_NAME'],
+                ]
+            ], 200);
+        } else {
+            return $this->respond([
+                'status' => 'fail',
+                'message' => '해당 SEQ의 사용자를 찾을 수 없습니다.'
+            ], 404);
+        }
+    }
+}

+ 23 - 19
components/common/header.vue

@@ -89,7 +89,6 @@
     const authUser = JSON.parse(localStorage.getItem("authStore"))?.auth;
     const currentUser = snsUser || authUser;
     let memberType = currentUser?.memberType || currentUser?.MEMBER_TYPE;
-
     if (memberType === 'I'){
       userName.value = currentUser?.NICK_NAME || currentUser?.name
     } else {
@@ -119,20 +118,14 @@
     console.log("현재 경로:", route.path);
     console.log("COMPANY_NUMBER:", currentUser?.COMPANY_NUMBER);
 
-    if (memberType === "VENDOR") {
-      // 벤더사 메뉴
-      memberTypeText.value = "벤더사";
+    if (memberType === "I") {
+      // 인플루언서 메뉴
+      memberTypeText.value = "인플루언서";
       info.push(
-        {
-          menuId: "menu00",
-          parentMenuId: "menu00",
-          menuName: "주문 관리",
-          linkType: "/view/vendor/dashboard",
-        },
         {
           menuId: "menu01",
           parentMenuId: "menu01",
-          menuName: "공동구매",
+          menuName: "제품 관리",
           linkType: "/view/common/item",
         },
         // {
@@ -161,8 +154,8 @@
         // {
         //   menuId: "menu03",
         //   parentMenuId: "menu03",
-        //   menuName: "인플루언서 관리",
-        //   linkType: "/view/vendor/dashboard/influencer-requests",
+        //   menuName: "벤더 관리",
+        //   linkType: "/view/influencer/search",
         // },
         // {
         //   menuId: "menu04",
@@ -177,14 +170,25 @@
           linkType: "/view/common/cs",
         }
       );
-    } else {
-      // 인플루언서 메뉴
-      memberTypeText.value = "인플루언서";
+    } else{
+      if(memberType === "VENDOR"){
+        // 벤더사 메뉴
+        memberTypeText.value = "벤더사";
+      } else {
+        // 브랜드사 메뉴
+        memberTypeText.value = "브랜드사";
+      }
       info.push(
+        {
+          menuId: "menu00",
+          parentMenuId: "menu00",
+          menuName: "주문 관리",
+          linkType: "/view/vendor/dashboard",
+        },
         {
           menuId: "menu01",
           parentMenuId: "menu01",
-          menuName: "제품 관리",
+          menuName: "공동구매",
           linkType: "/view/common/item",
         },
         // {
@@ -213,8 +217,8 @@
         // {
         //   menuId: "menu03",
         //   parentMenuId: "menu03",
-        //   menuName: "벤더 관리",
-        //   linkType: "/view/influencer/search",
+        //   menuName: "인플루언서 관리",
+        //   linkType: "/view/vendor/dashboard/influencer-requests",
         // },
         // {
         //   menuId: "menu04",

+ 3 - 1
composables/useLogout.js

@@ -1,6 +1,6 @@
 import { useAuthStore } from '~/stores/auth'
-import { useVendorsStore } from '~/stores/vendors'
 import { useDetailStore } from '~/stores/detail'
+import { useVendorsStore } from '~/stores/vendors'
 
 export const useLogout = () => {
   const authStore = useAuthStore()
@@ -21,6 +21,8 @@ export const useLogout = () => {
         return 'vendor'
       case 'INFLUENCER':
         return 'influence'
+      case 'BRAND':
+        return 'brand'
       default:
         // 3. 기본값은 인플루언서
         return 'influence'

+ 1 - 1
pages/index.vue

@@ -48,7 +48,7 @@
         </div>
         <div class="login-r">
           <div class="tit-login">
-            <strong>로그인</strong>
+            <strong>{{ route.query.type == 'brand' ? '브랜드사' : route.query.type == 'vendor' ? '벤더사' : '' }} 로그인</strong>
           </div>
           <div class="login-input-wrap">
             <div

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 540 - 365
pages/view/common/item/add.vue


+ 479 - 0
pages/view/common/item/detail.vue

@@ -0,0 +1,479 @@
+<template>
+  <div class="modern-item-add">
+    <!-- 메인 컨텐츠 -->
+    <div class="main-content">
+      <div class="form-container">
+        <v-form ref="addForm" class="modern-form">
+          <div class="form-section">
+            <h3 class="section-title">
+              <i class="mdi mdi-package-variant"></i>
+              {{ pageId }}
+            </h3>
+            
+            <!-- 제품명 -->
+            <div class="form-field">
+              <label class="field-label">
+                제품명
+              </label>
+              <div class="field-content">
+                <div class="display-value">
+                  {{ form.formValue1 }}
+                </div>
+              </div>
+            </div>
+            <div class="form-field">
+              <label class="field-label">
+                판매 기간
+              </label>
+              <div class="field-content df--type w--50">
+                <div class="display-value date-range">
+                  <i class="mdi mdi-calendar-range"></i>
+                  {{ form.order_start_date?.slice(0, 10) }} ~ {{ form.order_end_date?.slice(0, 10) }}
+                </div>
+                <v-btn
+                  v-if="form.formValue8 == 0 && memberType !== 'INFLUENCER'"
+                  class="closed-btn"
+                  color="primary"
+                  variant="outlined"
+                  @click="fnCloseEvt"
+                >
+                  <i class="mdi mdi-power"></i>
+                  마감
+                </v-btn>
+              </div>
+            </div>
+
+            <!-- 인플루언서 (공동구매인 경우) -->
+            <div class="form-field-group group--2" v-if="memberType !== 'INFLUENCER'">
+              <div class="form-field">
+                <label class="field-label">인플루언서</label>
+                <div class="field-content">
+                  <div class="display-value date-range">
+                    <i class="mdi mdi-account-circle"></i>
+                    {{ form.contact_inf_display }}
+                  </div>
+                </div>
+              </div>
+              <!-- 브랜드사 (공동구매인 경우) -->
+              <div v-if="memberType !== 'BRAND'" class="form-field">
+                <label class="field-label">브랜드사</label>
+                <div class="field-content">
+                  <div class="display-value date-range">
+                    <i class="mdi mdi-domain"></i>
+                    {{ form.contact_brd_display }}
+                  </div>
+                </div>
+              </div>
+            </div>
+
+
+            <div class="form-field" v-if="form.order_link">
+              <label class="field-label">구매 링크</label>
+              <div class="field-content">
+                <div v-if="pageType == 'D'" class="display-value link-display">
+                  <a 
+                    :href="form.order_link" 
+                    target="_blank" 
+                    rel="noopener noreferrer"
+                    class="external-link"
+                  >
+                    <i class="mdi mdi-link"></i>
+                    {{ form.order_link }}
+                    <i class="mdi mdi-open-in-new"></i>
+                  </a>
+                </div>
+                <v-text-field
+                  v-else
+                  v-model="form.order_link"
+                  class="modern-input"
+                  variant="outlined"
+                  placeholder="공동구매 링크를 입력하세요"
+                  maxlength="200"
+                  hide-details="auto"
+                ></v-text-field>
+              </div>
+            </div>
+          </div>
+        </v-form>
+      </div>
+
+      <!-- 액션 버튼 -->
+      <div class="action-buttons">
+        <div class="button-group left">
+          <v-btn
+            class="action-btn secondary"
+            variant="outlined"
+            @click="listLocated"
+          >
+            <i class="mdi mdi-format-list-bulleted"></i>
+            목록으로
+          </v-btn>
+          <v-btn
+            v-if="memberType !== 'INFLUENCER'"
+            class="action-btn danger"
+            variant="outlined"
+            color="error"
+            @click="fnDelEvt"
+          >
+            <i class="mdi mdi-delete"></i>
+            삭제
+          </v-btn>
+        </div>
+        <div class="button-group right">
+          <v-btn
+            v-if="memberType !== 'INFLUENCER'"
+            class="action-btn primary"
+            color="primary"
+            @click="fnBtnEvt"
+          >
+            <i class="mdi mdi-pencil"></i>
+            수정하기
+          </v-btn>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import useAxios from "@/composables/useAxios";
+import "@vuepic/vue-datepicker/dist/main.css";
+/************************************************************************
+|    레이아웃
+************************************************************************/
+definePageMeta({
+  layout: "default",
+});
+
+/************************************************************************
+|    스토어
+ ************************************************************************/
+const useDtStore = useDetailStore();
+const useAtStore = useAuthStore();
+
+/************************************************************************
+|    전역
+ ************************************************************************/
+const memberType = useAtStore.auth.memberType;
+const { $toast, $log, $dayjs, $eventBus } = useNuxtApp();
+const router = useRouter();
+const pageId = ref("");
+const itemType = useDtStore.boardInfo.itemType;
+const datePickerFormat = "yyyy-MM-dd";
+const sunEditorWrapper = ref(null); //에디터용 전역
+const updatedContent = ref(null); //에디터용 전역
+const editorContentReq = ref(); //에디터용 전역
+const addForm = ref(null);
+const index = ref(null);
+const imageIndex = ref(0);
+const items = ref([]);
+const quillEditor = ref(null);
+const imgTemp = ref("");
+const zipInfo = ref({
+  file_path: "",
+  original_name: ""
+})
+const rowId = ref();
+const form = ref({
+  formValue1: "",
+  formValue2: "",
+  formValue3: "",
+  formValue4: "",
+  formValue5: null,
+  formValue6: "",
+  formValue7: null,
+  formValue8: "0",
+  formValue8Arr: [
+    { title: "판매중", value: "0" },
+    { title: "품절", value: "1" },
+  ],
+  formValue9: "Y",
+  formValue9Arr: [
+    { title: "노출", value: "Y" },
+    { title: "비노출", value: "N" },
+  ],
+  formValue10: "",
+  contact_inf: "", // 실제 전송될 INFLUENCER_SEQ
+  contact_inf_display: "", // 화면에 표시될 이름
+  contact_brd: "", // 실제 전송될 contact_brd
+  contact_brd_display: "", // 화면에 표시될 브랜드명
+  order_link: "",
+  order_start_date: "",
+  order_end_date: "",
+});
+
+// 인플루언서 관련 변수
+const influencerModal = ref(false);
+const influencerList = ref([]);
+const filteredInfluencerList = ref([]);
+const selectedInfluencer = ref(null);
+const influencerSearchQuery = ref("");
+const isSearching = ref(false);
+
+// 브랜드사 관련 변수
+const brandModal = ref(false);
+const brandList = ref([]);
+const filteredBrandList = ref([]);
+const selectedBrand = ref(null);
+const brandSearchQuery = ref("");
+const isBrandSearching = ref(false);
+
+const apiUrl = ref("");
+
+apiUrl.value = import.meta.env.VITE_APP_API_URL;
+const objProc = ref({
+  validErrorMessage: "",
+});
+
+const pageType = ref("");
+
+/************************************************************************
+|    함수(METHODS)
+************************************************************************/
+
+const listLocated = () => {
+  router.push({
+    path: "/view/common/item",
+  });
+  useDtStore.boardInfo.itemType  = itemType;
+};
+
+// 인플루언서 이름 조회
+const getInfName = async (contact_inf) => {
+  try {
+    // contact_inf 값이 있을 때만 API 호출
+    if (!contact_inf) {
+      return null;
+    }
+
+    const response = await useAxios().get(`/user/getInfName/${contact_inf}`);
+    
+    if (response.data?.status === 'success') {
+      return response.data.data;
+    } else {
+      return null;
+    }
+  } catch (error) {
+    return null;
+  }
+};
+
+// 브랜드사 조회
+const getBrdName = async (contact_brd) => {
+  try {
+    if (!contact_brd) {
+      return null;
+    }
+
+    const response = await useAxios().get(`/user/getBrdName/${contact_brd}`);
+    
+    if (response.data?.status === 'success') {
+      return response.data.data;
+    } else {
+      return null;
+    }
+  } catch (error) {
+    return null;
+  }
+};
+
+/*======================================================================
+|    작성 시퀀스
+| 1. 작성 컨펌
+| 2. 버튼 체크
+| 3. 등록시 -> 등록 API 호출
+======================================================================*/
+
+const fnBtnEvt = () => {
+  //await editorContent();
+  router.push({
+      path: "/view/common/item/add",
+    });
+    useDtStore.boardInfo.itemType = itemType;
+    useDtStore.boardInfo.pageType = "U";
+};
+
+const fnDelEvt = () => {
+  let param = {
+    id: pageId,
+    title: pageId,
+    content: "삭제하시겠습니까?",
+    yes: {
+      text: "확인",
+      isProc: true,
+      event: "FN_DELETE",
+      param: "",
+    },
+    no: {
+      text: "취소",
+      isProc: false,
+    },
+  };
+  $eventBus.emit("OPEN_CONFIRM_POP_UP", param);
+};
+
+const fnCloseEvt = () => {
+  let param = {
+    id: pageId,
+    title: pageId,
+    content: "마감하시겠습니까?",
+    yes: {
+      text: "확인",
+      isProc: true,
+      event: "FN_CLOSE",
+      param: "",
+    },
+    no: {
+      text: "취소",
+      isProc: false,
+    },
+  };
+  $eventBus.emit("OPEN_CONFIRM_POP_UP", param);
+};
+
+const fnClose = () => {
+  let req = {
+    seq: useDtStore.boardInfo.seq,
+  };
+
+  useAxios()
+    .post(`/item/close/${req.seq}`)
+    .then((res) => {
+      router.push("/view/common/item");
+    })
+    .catch((error) => {
+    })
+    .finally(() => {
+    });
+};
+
+const fnDelete = () => {
+  let req = {
+    seq: useDtStore.boardInfo.seq,
+  };
+
+  useAxios()
+    .post(`/item/delete/${req.seq}`)
+    .then((res) => {
+      router.push("/view/common/item");
+    })
+    .catch((error) => {
+    })
+    .finally(() => {
+    });
+};
+
+const fnDetail = () => {
+  let req = {
+    seq: useDtStore.boardInfo.seq,
+  };
+  useAxios()
+    .get(`/item/detail/${req.seq}`)
+    .then(async (res) => {
+      form.value.formValue1 = res.data.NAME;
+      form.value.formValue8 = res.data.STATUS;
+      form.value.formValue9 = res.data.SHOW_YN;
+      form.value.formValue10 = res.data.ADD_INFO;
+      form.value.order_link = res.data.ORDER_LINK;
+      form.value.order_start_date = res.data.ORDER_START_DATE;
+      form.value.order_end_date = res.data.ORDER_END_DATE;
+      form.value.contact_inf = res.data.CONTACT_INF;
+      form.value.contact_brd = res.data.CONTACT_BRD;
+      
+      // contact_inf 값이 있으면 인플루언서 이름 조회
+      if (res.data.CONTACT_INF) {
+        const infData = await getInfName(res.data.CONTACT_INF);
+        if (infData) {
+          form.value.contact_inf_display = infData.NICK_NAME 
+            ? `${infData.NICK_NAME} (${infData.NAME})`
+            : infData.NAME;
+        }
+      }
+      if (res.data.CONTACT_BRD) {
+        const brdData = await getBrdName(res.data.CONTACT_BRD);
+        if (brdData) {
+          form.value.contact_brd_display = brdData.NAME;
+        }
+      }
+    })
+    .catch((error) => {
+    })
+    .finally(() => {
+    });
+};
+
+/************************************************************************
+|    팝업 이벤트버스 정의
+************************************************************************/
+
+$eventBus.off("FN_DELETE");
+$eventBus.on("FN_DELETE", () => {
+  fnDelete();
+});
+
+$eventBus.off("FN_CLOSE");
+$eventBus.on("FN_CLOSE", () => {
+  fnClose();
+});
+
+/************************************************************************
+|    라이프사이클
+************************************************************************/
+onMounted(() => {
+  pageType.value = "D";
+  
+  if(pageType.value == "I"){
+    if(itemType == "G"){
+      pageId.value = "공동구매 등록"
+    } else {
+      pageId.value = "제품 등록"
+    }
+  } else if(pageType.value == "U"){
+    if(itemType == "G"){
+      pageId.value = "공동구매 수정"
+    } else {
+      pageId.value = "제품 수정"
+    }
+  } else  {
+    if(itemType == "G"){
+      pageId.value = "공동구매 상세"
+    } else {
+      pageId.value = "제품 상세"
+    }
+  }
+
+  //상세 등록 아니 리스트 클릭시 상세 정보로 접근
+  if (pageType.value !== "I") {
+    fnDetail();
+  }
+});
+
+</script>
+
+<style scoped>
+.cursor-pointer {
+  cursor: pointer;
+}
+
+.cursor-pointer:hover {
+  background-color: #f5f5f5;
+}
+
+.order-link {
+  color: #1976d2;
+  text-decoration: none;
+  display: inline-flex;
+  align-items: center;
+  transition: color 0.2s;
+}
+
+.order-link:hover {
+  color: #1565c0;
+  text-decoration: underline;
+}
+
+.no-link {
+  color: #999;
+  font-style: italic;
+}
+</style>

+ 8 - 25
pages/view/common/item/index.vue

@@ -189,7 +189,7 @@ import dayjs from 'dayjs';
   const { $toast, $log, $dayjs, $eventBus } = useNuxtApp();
   const router = useRouter();
   const pageId = computed(() => {
-    return '공동구매 관리';
+    return '공동구매';
     //return memberType === 'INFLUENCER' ? '제품 관리 (파트너십)' : '제품 관리 (자사)';
   });
   const itemList = ref([]);
@@ -202,22 +202,6 @@ import dayjs from 'dayjs';
   /************************************************************************
 |    함수(METHODS)
 ************************************************************************/
-  const isClosedOrder = (dateStr) => {
-    const today = new Date();
-    const closedOrder = new Date(dateStr);
-    today.setHours(0, 0, 0, 0);
-    closedOrder.setHours(0, 0, 0, 0);
-    // 공동구매 기간이 지났으면 종료
-    return today < closedOrder;
-  }
-
-  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;
@@ -266,12 +250,11 @@ import dayjs from 'dayjs';
 
   const toItemDetail = (__EVENT) => {
     router.push({
-      path: "/view/common/item/add",
+      path: "/view/common/item/detail",
     });
     useDtStore.boardInfo.seq = __EVENT;
     useDtStore.boardInfo.itemType = itemType;
-    //제품 등록한 벤더의 경우 U로, 인플루언서의 경우 D로
-    memberType == 'INFLUENCER' ? useDtStore.boardInfo.pageType = "D" : useDtStore.boardInfo.pageType = "U";
+    useDtStore.boardInfo.pageType = "D";
   };
 
   const itemListGet = async () => {
@@ -284,16 +267,16 @@ import dayjs from 'dayjs';
       MEMBER_SEQ: useAtStore.auth.seq,
     };
 
-    if(memberType === "VENDOR"){
+    if(memberType !== "INFLUENCER"){
       _req.COMPANY_NUMBER = useAtStore.auth.companyNumber || "1";
     }
 
-    console.log(_req);
-
+    
     await useAxios()
-      .post("/item/list", _req)
-      .then((res) => {
+    .post("/item/list", _req)
+    .then((res) => {
         itemList.value = res.data;
+        console.log(res.data);
       });
   };
 

+ 11 - 2
stores/auth.js

@@ -41,8 +41,17 @@ export const useAuthStore = defineStore('authStore', () => {
     console.log('원본 COMPANY_NUMBER:', payload.user.COMPANY_NUMBER);
     console.log('원본 companyNumber:', payload.user.companyNumber);
     
-    // 사용자 타입 설정 (COMPANY_NUMBER가 있으면 벤더사, 없으면 인플루언서)
-    auth.value.memberType = (payload.user.COMPANY_NUMBER || payload.user.companyNumber) ? 'VENDOR' : 'INFLUENCER'
+    // 사용자 타입 설정
+    if (payload.user.MEMBER_TYPE === 'B') {
+      // 브랜드사
+      auth.value.memberType = 'BRAND'
+    } else if (payload.user.COMPANY_NUMBER || payload.user.companyNumber) {
+      // 벤더사
+      auth.value.memberType = 'VENDOR'
+    } else {
+      // 인플루언서
+      auth.value.memberType = 'INFLUENCER'
+    }
     
     console.log('설정된 memberType:', auth.value.memberType);
     console.log('=============================');

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio