Parcourir la source

+ 고객센터 디자인 반영
+ 라디오 디자인 초기화
+ 인풋 디자인 초기화
+ 셀렉트 디자인 초기화

송용우 il y a 2 mois
Parent
commit
6a83db0057
4 fichiers modifiés avec 306 ajouts et 243 suppressions
  1. 203 116
      app/assets/scss/sub.scss
  2. 13 4
      app/composables/useApi.ts
  3. 90 108
      app/pages/contact/support.vue
  4. 0 15
      plugins/api.client.ts

+ 203 - 116
app/assets/scss/sub.scss

@@ -145,6 +145,7 @@
   align-items: center;
   justify-content: center;
   padding-top:100px;
+  padding-bottom:120px;
   .out--container{
     max-width:844px;    
 
@@ -172,54 +173,176 @@
       justify-content: center;
       gap:20px;
 
-      .form--contents {
-        margin-bottom: 30px;        
-        &.half--cont{
-          max-width:100%;
+      .contact-form{
+        display: flex;
+        align-items: flex-start;
+        justify-content: space-between;
+        flex-wrap: wrap;        
+
+
+        .btn--wrap{
+          width:100%;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          padding-top:30px;
+          button{
+            display: flex;
+            max-width:160px;
+            width: 100%;
+            height: 48px;
+            border-radius: 24px;            
+            background: #1F2128!important;
+            justify-content: center;
+            align-items: center;
+            gap: 8px;
+            flex-shrink: 0;
+
+            color:#FFF;
+            font-size: 18px;
+            font-style: normal;
+            font-weight: 700;            
+          }
         }
       }
-    }
 
+      .form--contents {
+        margin-bottom: 28px;        
+        width:100%;
+
+
+        input[type="text"],
+        input[type="email"],
+        select,
+        textarea {
+          width: 100%;
+          padding: 10px;
+          border: 1px solid #ddd;      
+          border-radius: 0px;
+          font-size: 14px;
+        }
 
-    .form--contents h3 {
-      font-size: 16px;
-      font-weight: 600;
-      margin-bottom: 10px;
-    }
+        h3 {
+          color:#1F2128;
+          font-size: 16px;
+          font-style: normal;
+          font-weight: 500;          
+          margin-bottom:8px!important;
+          &.privacy--title{
+            color:#1F2128;
+            font-size: 24px;
+            font-style: normal;
+            font-weight: 700;      
+          }
 
-    .form--contents h3 .required {
-      color: #ff0000;
-      margin-left: 4px;
-    }
+          .required {
+            color: #ff0000;
+            margin-left: 4px;
+          }
+        }
+        
+        > div{
+          width:100%;
+        }
+        &.half--cont{
+          width:100%;
+          max-width:calc(50% - 10px);
+        }
 
-    .form--contents input[type="text"],
-    .form--contents input[type="email"],
-    .form--contents select,
-    .form--contents textarea {
-      width: 100%;
-      padding: 10px;
-      border: 1px solid #ddd;
-      border-radius: 4px;
-      font-size: 14px;
+
+        .qna--radio--group{
+          fieldset{
+            background:#EFF1FB;
+            padding:4px;
+            display: flex;
+            gap:0px;
+            >div{
+              display: flex;                            
+              min-width:101px;
+              height:36px;
+              position: relative;
+              >div{
+                &:nth-of-type(1){
+                  position: absolute;
+                  top:0px;
+                  left:0px;
+                  width:100%;
+                  height:100%;
+                  pointer-events: none;
+                  button{
+                    width:100%;
+                    height:100%;
+                    border:0px!important;
+                    box-shadow: none;
+                    &[data-state="checked"]{
+                      background: #fff;
+                    }
+                    >span{
+                      display: none;
+                    }
+                  }
+                }
+                &:nth-of-type(2){                  
+                  margin:0px;  
+                  width:100%; 
+                  height:36px;           
+                  display: flex;
+                  align-items: center;
+                  justify-content: center;
+
+                  label{
+                    position: absolute;
+                    top:0px;
+                    border:0px!important;
+                    left:0px;
+                    width:100%;
+                    height:100%;
+                    margin:0px;
+                    display: flex;
+                    align-items: center;
+                    justify-content: center;
+                    cursor: pointer;
+                    color:#B6BBCC;
+                    font-size: 16px;
+                    font-style: normal;
+                    font-weight: 400;                    
+                    &.actv{
+                      color:#1F2128;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
     }
 
     .tel-group {
       display: flex;
       align-items: center;
       gap: 10px;
+      button{
+        height:40px;
+        width:100%;
+        max-width:calc( (100% / 3) - 20px);
+      }
+      > div{
+        width:100%;
+      }
+      select {
+        width: 100px;      
+      }
+  
+      input {
+        flex: 1;
+      }
+  
+      span {
+        font-weight: 500;
+      }
     }
 
-    .tel-group select {
-      width: 100px;
-    }
-
-    .tel-group input {
-      flex: 1;
-    }
-
-    .tel-group span {
-      font-weight: 500;
-    }
 
     .radio-group {
       display: flex;
@@ -239,92 +362,56 @@
     }
 
     .privacy-box {
-      border: 1px solid #ddd;
-      border-radius: 4px;
-      padding: 20px;
-      background-color: #f9f9f9;
-    }
-
-    .privacy-content {
-      height: 300px;
-      overflow-y: auto;
-      padding: 15px;
-      background-color: #fff;
-      border: 1px solid #e0e0e0;
-      border-radius: 4px;
-      margin-bottom: 20px;
-      line-height: 1.8;
-    }
-
-    .agree-check {
-      padding: 15px;
-      background-color: #fff;
-      border: 1px solid #e0e0e0;
-      border-radius: 4px;
-    }
-
-    .agree-check h4 {
-      font-size: 14px;
-      font-weight: 600;
-      margin-bottom: 10px;
-    }
-
-    .btn--wrap {
-      text-align: center;
-      margin-top: 40px;
-    }
-
-    .btn-submit {
-      padding: 12px 40px;
-      background-color: #00a651;
-      color: #fff;
-      border: none;
-      border-radius: 4px;
-      font-size: 16px;
-      font-weight: 600;
-      cursor: pointer;
-      transition: background-color 0.3s;
-    }
-
-    .btn-submit:hover {
-      background-color: #008840;
-    }
-
-    .btn-submit:disabled {
-      background-color: #ccc;
-      cursor: not-allowed;
-    }
-
-    .map-section {
-      margin-top: 80px;
-      padding-top: 40px;
-      border-top: 1px solid #ddd;
-    }
-
-    .map-section h3 {
-      font-size: 24px;
-      font-weight: 600;
-      margin-bottom: 20px;
+      .privacy-content {
+        height: 300px;
+        overflow-y: auto;
+        padding: 15px;
+        background-color: #fff;     
+        border: 1px solid #ddd;      
+        margin-bottom: 20px;
+        line-height: 1.8;
+      }
+  
+      .agree-check {      
+        background-color: #fff;            
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        > h4 {
+          color: #1F2128;
+          font-size: 16px;
+          font-style: normal;
+          font-weight: 700;
+          line-height: 130%; /* 20.8px */
+        }
+      }            
     }
+  }
+}
 
-    .info-list,
-    .contact-list {
-      list-style: none;
-      padding: 0;
-      margin: 0 0 20px 0;
-    }
 
-    .info-list li,
-    .contact-list li {
-      font-size: 14px;
-      line-height: 1.8;
-    }
 
-    .map-container {
-      height: 450px;
-      border: 1px solid #ddd;
-      border-radius: 4px;
-      overflow: hidden;
+// 라디오 디자인 초기화
+.agree-radio-group{
+  fieldset{
+    gap:32px;
+  }
+  label{
+    color:#1F2128;
+    font-size: 16px;
+    font-style: normal;
+    font-weight: 500;    
+  }
+  button{
+    width:20px;
+    height:20px;
+    border-radius: 20px;
+    > span{
+      background-color:#00A654!important;
+      &:after{
+        width:10px;
+        height:10px;
+      }
     }
   }
 }

+ 13 - 4
composables/useApi.ts → app/composables/useApi.ts

@@ -49,8 +49,8 @@ const getApiClient = () => {
   return apiClient
 }
 
-// 글로벌 API 메서드들
-export const get = async (url, params = {}) => {
+// 글로벌 API 메서드들 (직접 사용 가능)
+export const $get = async (url, params = {}) => {
   try {
     const client = getApiClient()
     const response = await client.get(url, { params })
@@ -60,7 +60,7 @@ export const get = async (url, params = {}) => {
   }
 }
 
-export const post = async (url, data = {}) => {
+export const $post = async (url, data = {}) => {
   try {
     const client = getApiClient()
     const response = await client.post(url, data)
@@ -70,7 +70,7 @@ export const post = async (url, data = {}) => {
   }
 }
 
-export const postForm = async (url, data = {}) => {
+export const $postForm = async (url, data = {}) => {
   try {
     const client = getApiClient()
     const formData = new FormData()
@@ -109,6 +109,15 @@ export const del = async (url, params = {}) => {
   }
 }
 
+// Nuxt 4 composables를 위한 기본 export
+export default () => ({
+  get,
+  post,
+  postForm,
+  put,
+  delete: del
+})
+
 // 기존 useApi 호환성을 위해 유지
 export const useApi = () => ({
   get,

+ 90 - 108
app/pages/contact/support.vue

@@ -7,31 +7,25 @@
         <div class="form--contents--wrap">
           <div class="contact-form">
             <div class="form--contents half--cont">
-              <h3>작성자 (성명) <span class="required">*</span></h3>
-              <div>
-                <UInput 
-                  v-model="formData.name" 
-                  placeholder="성명을 입력해주세요" 
-                />
-              </div>
+              <h3>작성자 (성명) <span class="required">*</span></h3>              
+              <UInput 
+                v-model="formData.name" 
+                placeholder="성명을 입력해주세요" 
+              />              
             </div>
             <div class="form--contents half--cont">
-              <h3>직책</h3>
-              <div>
-                <UInput 
-                  v-model="formData.etc1" 
-                  placeholder="직책을 입력해주세요" 
-                />
-              </div>
+              <h3>직책</h3>              
+              <UInput 
+                v-model="formData.etc1" 
+                placeholder="직책을 입력해주세요" 
+              />              
             </div>
             <div class="form--contents half--cont">
-              <h3>회사명</h3>
-              <div>
-                <UInput 
-                  v-model="formData.etc2" 
-                  placeholder="회사명을 입력해주세요" 
-                />
-              </div>
+              <h3>회사명</h3>              
+              <UInput 
+                v-model="formData.etc2" 
+                placeholder="회사명을 입력해주세요" 
+              />              
             </div>
             <div class="form--contents half--cont">
               <h3>연락처 <span class="required">*</span></h3>
@@ -55,60 +49,29 @@
               </div>
             </div>
             <div class="form--contents half--cont">
-              <h3>이메일 <span class="required">*</span></h3>
-              <div>
-                <UInput 
-                  type="email" 
-                  v-model="formData.email" 
-                  placeholder="이메일을 입력해주세요" 
-                />
-              </div>
+              <h3>이메일 <span class="required">*</span></h3>              
+              <UInput 
+                type="email" 
+                v-model="formData.email" 
+                placeholder="이메일을 입력해주세요" 
+              />              
             </div>
             <div class="form--contents half--cont">
               <h3>문의항목 <span class="required">*</span></h3>
-              <div class="radio-group">
-                <label>
-                  <input 
-                    type="radio" 
-                    v-model="formData.category" 
-                    value="원료" 
-                  />
-                  <span>원료</span>
-                </label>
-                <label>
-                  <input 
-                    type="radio" 
-                    v-model="formData.category" 
-                    value="제품" 
-                  />
-                  <span>제품</span>
-                </label>
-                <label>
-                  <input 
-                    type="radio" 
-                    v-model="formData.category" 
-                    value="기술" 
-                  />
-                  <span>기술</span>
-                </label>
-                <label>
-                  <input 
-                    type="radio" 
-                    v-model="formData.category" 
-                    value="기타" 
-                  />
-                  <span>기타</span>
-                </label>
-              </div>
+              <URadioGroup 
+                v-model="formData.category"
+                :items="categoryOptions"
+                value-key="value"
+                orientation="horizontal"
+                class="qna--radio--group"
+              />
             </div>
             <div class="form--contents">
-              <h3>제목 <span class="required">*</span></h3>
-              <div>
-                <UInput 
-                  v-model="formData.title" 
-                  placeholder="제목을 입력해주세요" 
-                />
-              </div>
+              <h3>제목 <span class="required">*</span></h3>              
+              <UInput 
+                v-model="formData.title" 
+                placeholder="제목을 입력해주세요" 
+              />              
             </div>
             <div class="form--contents">
               <h3>내용 <span class="required">*</span></h3>
@@ -123,14 +86,14 @@
                     <textarea 
                       v-model="formData.contents" 
                       rows="10" 
-                      placeholder="문의 내용 입력해주세요"
+                      placeholder="내용 입력"
                     ></textarea>
                   </template>
                 </client-only>
               </div>
             </div>
             <div class="form--contents">
-              <h3>개인 정보 수집 및 이용 동의</h3>
+              <h3 class="privacy--title">개인 정보 수집 및 이용 동의</h3>
               <div class="privacy-box">
                 <div class="privacy-content">
                   그린웨일 글로벌 주식회사 ('www.greenwhaleglobal.com'이하 '그린웨일 글로벌')은(는) 「개인정보 보호법」 제30조에 따라 정부주체의 개인정보를 보호하고 이와 관련한 고충을 신속하고 원활하게 처리할 수 있도록 하기 위하여 다음과 같이 개인정보 처리방침을 수립·공개합니다.<br/><br/>
@@ -198,41 +161,30 @@
                   3. 대검찰청 : (국번없이) 1301 (www.spo.go.kr)<br/>
                   4. 경찰청 : (국번없이) 182 (cyberbureau.police.go.kr)<br/>
                 </div>
+                
                 <div class="agree-check">
                   <h4>개인정보 수집 및 이용에 동의합니까?</h4>
-                  <div class="radio-group">
-                    <label>
-                      <input 
-                        type="radio" 
-                        v-model="formData.agree" 
-                        value="Y" 
-                      />
-                      <span>동의합니다.</span>
-                    </label>
-                    <label>
-                      <input 
-                        type="radio" 
-                        v-model="formData.agree" 
-                        value="N" 
-                      />
-                      <span>동의하지 않습니다.</span>
-                    </label>
-                  </div>
+                  <URadioGroup 
+                    v-model="formData.agree"
+                    :items="agreeOptions"
+                    value-key="value"
+                    orientation="horizontal"
+                    class="agree-radio-group"
+                  />
                 </div>
               </div>
             </div>
-            <div class="form--contents">
-              <div class="btn--wrap">
-                <UButton 
-                  :loading="isSubmitting"
-                  @click="submitForm"
-                  size="lg"
-                  color="primary"
-                >
-                  {{ isSubmitting ? '전송중...' : '보내기' }}
-                </UButton>
-              </div>
+            
+            <div class="btn--wrap">
+              <UButton 
+                :loading="isSubmitting"
+                @click="submitForm"
+                size="lg"                
+              >
+                {{ isSubmitting ? '전송중...' : '보내기' }}
+              </UButton>
             </div>
+            
           </div>
         </div>
 
@@ -243,7 +195,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref, computed, onMounted } from 'vue'
 import TopVisual from '~/components/topVisual.vue'
 import SummernoteEditor from '~/components/SummernoteEditor.vue'
 
@@ -261,6 +213,36 @@ const phoneOptions = [
   { value: '033', label: '033' }
 ]
 
+// 문의항목 옵션
+const categoryOptions = computed(() => [
+  { 
+    value: '원료', 
+    label: '원료',
+    ui: formData.value.category === '원료' ? { label: 'actv' } : {}
+  },
+  { 
+    value: '제품', 
+    label: '제품',
+    ui: formData.value.category === '제품' ? { label: 'actv' } : {}
+  },
+  { 
+    value: '기술', 
+    label: '기술',
+    ui: formData.value.category === '기술' ? { label: 'actv' } : {}
+  },
+  { 
+    value: '기타', 
+    label: '기타',
+    ui: formData.value.category === '기타' ? { label: 'actv' } : {}
+  }
+])
+
+// 동의 옵션
+const agreeOptions = [
+  { value: 'Y', label: '동의합니다.' },
+  { value: 'N', label: '동의하지 않습니다.' }
+]
+
 // 반응형 데이터
 const isSubmitting = ref(false)
 const formData = ref({
@@ -271,15 +253,15 @@ const formData = ref({
   tel_2: '',
   tel_3: '',
   email: '',
-  category: '',
+  category: '원료',
   title: '',
   contents: '',
-  agree: ''
+  agree: 'Y'
 })
 
 // Summernote 에디터 설정
 const editorHeight = 400
-const editorPlaceholder = '문의 내용 입력해주세요'
+const editorPlaceholder = '내용 입력'
 
 // 페이지 설정
 const className = "contact"
@@ -352,7 +334,7 @@ const submitForm = async () => {
       contents: formData.value.contents
     }
 
-    const response = await $api.postForm('/board_proc', submitData)
+    const response = await $postForm('/board_proc', submitData)
 
     if (response && response.success) {
       alert('문의가 정상적으로 접수되었습니다.')
@@ -384,10 +366,10 @@ const resetForm = () => {
     tel_2: '',
     tel_3: '',
     email: '',
-    category: '',
+    category: '원료',
     title: '',
     contents: '',
-    agree: ''
+    agree: 'Y'
   }
 }
 

+ 0 - 15
plugins/api.client.ts

@@ -1,15 +0,0 @@
-import { get, post, postForm, put, del } from '~/composables/useApi'
-
-export default defineNuxtPlugin(() => {
-  return {
-    provide: {
-      api: {
-        get,
-        post,
-        postForm,
-        put,
-        delete: del
-      }
-    }
-  }
-})