冯诚 2 lat temu
rodzic
commit
838ad4821e

BIN
src/assets/empty.png


+ 23 - 16
src/components/nav-bar/index.vue

@@ -36,10 +36,13 @@
     </div>
     <div v-if="showNavIcons" class="nav-bar-right">
       <div class="user pointer flex-ac" @click="onClickMine">
-        <i class="icon-mine"></i>
-        <span class="user-name">{{
-          state.userInfo ? state.userInfo.name : 'Sign in'
-        }}</span>
+        <template v-if="state.userInfo">
+          <i class="icon-mine"></i>
+          <span class="user-name">{{
+            state.userInfo ? state.userInfo.name : 'Sign in'
+          }}</span>
+        </template>
+        <span v-else class="u-no">LOGIN</span>
       </div>
       <div class="contact">
         <i class="icon-phone"></i>
@@ -116,28 +119,28 @@
           </div>
           <ul class="dropdown-list">
             <template v-if="state.userInfo.orders.length">
-              <li class="dropdown-item">
+              <li class="dropdown-item i1">
                 <router-link to="/repaire/history"
                   >MY REPAIR REQUEST</router-link
                 >
               </li>
-              <li class="dropdown-item">
+              <li class="dropdown-item i2">
                 <router-link to="/order">MY ORDER</router-link>
               </li>
             </template>
-            <li class="dropdown-item">
+            <li class="dropdown-item i3">
               <router-link to="/gift-card">MY DISCOUNT COUPON</router-link>
             </li>
-            <li class="dropdown-item">
+            <li class="dropdown-item i4">
               <router-link to="/invite"
                 >INVITE FRIENDS
                 <span class="ptc-tag">Get a $10 coupon</span></router-link
               >
             </li>
-            <li class="dropdown-item">
+            <li class="dropdown-item i5">
               <router-link to="/account">ACCOUNT INFORMATION</router-link>
             </li>
-            <li class="dropdown-item" @click="signOut">SIGN OUT</li>
+            <li class="dropdown-item i6" @click="signOut">SIGN OUT</li>
           </ul>
         </div>
       </div>
@@ -235,6 +238,10 @@ async function signOut() {
         font-weight: 600;
         color: $primary-color;
       }
+      .u-no {
+        font-size: 32px;
+        color: #193059;
+      }
       .contact {
         position: relative;
         display: none;
@@ -621,22 +628,22 @@ async function signOut() {
     &:active {
       background-color: #f2f5fb;
     }
-    &:nth-child(1) {
+    &.i1 {
       background-image: url(@img/m-repair.png);
     }
-    &:nth-child(2) {
+    &.i2 {
       background-image: url(@img/m-order.png);
     }
-    &:nth-child(3) {
+    &.i3 {
       background-image: url(@img/m-coupon.png);
     }
-    &:nth-child(4) {
+    &.i4 {
       background-image: url(@img/m-friend.png);
     }
-    &:nth-child(5) {
+    &.i5 {
       background-image: url(@img/m-info.png);
     }
-    &:nth-child(6) {
+    &.i6 {
       background-image: url(@img/m-exit.png);
     }
 

+ 2 - 0
src/components/toast/Toast.vue

@@ -84,8 +84,10 @@ watch(() => props.message, reset)
   @include media-breakpoint-up(md) {
     top: 15%;
     transform: translate(-50%, 0);
+    max-width: 800px;
     background-color: #dbe8ff;
     color: $primary-color;
+    box-shadow: $toast-shadow;
   }
 
   &--loading {

+ 4 - 3
src/pages/fill-order/StepThree.vue

@@ -50,6 +50,7 @@
 <script setup lang="ts">
 import { string } from 'yup'
 import { state, getters } from './store'
+import { state as rootState } from '@/store'
 import { checkoutOrder } from '@/service/order'
 import Toast from '@/components/toast'
 
@@ -59,9 +60,9 @@ defineEmits<{
 
 async function submit() {
   try {
-    await string()
-      .email('Please enter a valid email address')
-      .validate(state.form.email)
+    const schema = string().email('Please enter a valid email address')
+    if (!rootState.userInfo) schema.required('Email is required')
+    await schema.validate(state.form.email)
     const { results } = await checkoutOrder(state.form)
     location.href = results
   } catch (err) {

+ 2 - 2
src/pages/fill-order/index.vue

@@ -29,8 +29,8 @@ const step = ref(0)
 const Component = computed(() => [StepOne, StepTwo, StepThree][step.value])
 const { from, invitee } = useRoute().query as any
 
-state.form.from = from
-state.form.invitor = invitee
+state.form.from = from || ''
+state.form.invitor = invitee || ''
 
 // 此处不直接传入resetState是有必要的,否则resetState在整个应用生命周期只会执行一次
 onUnmounted(() => resetState())

+ 5 - 1
src/pages/gift-card/index.vue

@@ -18,7 +18,11 @@
       </div>
     </div>
     <div class="card-list-wrap">
-      <div class="card-list">
+      <div v-if="!list.length" class="ptc-empty">
+        <i class="ptc-empty-img"></i>
+        <p class="ptc-empty-txt">No gift card yet</p>
+      </div>
+      <div v-else class="card-list">
         <div
           v-for="(item, index) of list"
           :key="index"

+ 4 - 0
src/pages/my-order/index.vue

@@ -1,6 +1,10 @@
 <template>
   <div class="p-my-order">
     <h3 class="ptc-title">My Order</h3>
+    <div v-if="!list.length" class="ptc-empty">
+      <i class="ptc-empty-img"></i>
+      <p class="ptc-empty-txt">No order yet</p>
+    </div>
     <div
       v-for="item of list"
       :key="item.id"

+ 10 - 15
src/pages/password/index.vue

@@ -66,7 +66,7 @@
       </div>
       <!-- <div class="ptc-form">
         <div class="ptc-form-item">
-          <button class="ptc-button" @click="next">GO</button>
+          <button class="ptc-button">GO</button>
         </div>
       </div> -->
     </div>
@@ -101,7 +101,7 @@
 </template>
 
 <script setup lang="ts">
-import { reactive } from 'vue'
+import { reactive, ref, watch } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
 import { state } from '@/store'
 import {
@@ -119,16 +119,16 @@ const props = defineProps<{ action: 'change' | 'reset' }>()
 const router = useRouter()
 const { query } = useRoute() as any
 const fromPath = history.state.back
-const step = query.step ? +(query.step as string) : 0
+const step = ref(query.token ? 2 : 0)
 const { values, handleSubmit } = useForm<ApiUser.PasswordChange.Request>({
   schema: {
-    old_password: string().required(),
-    new_password: string().required(),
-    new_password_confirmation: string().required(),
+    old_password: string().required('Please enter old password'),
+    new_password: string().required('Please enter new password'),
+    new_password_confirmation: string().required('Please repeat new password'),
   },
 })
 const resetForm = reactive<ApiUser.PasswordReset.Request>({
-  email: step === 2 ? query.email : '',
+  email: step.value === 2 ? query.email : '',
   token: query.token || '',
   password: '',
   password_confirmation: '',
@@ -136,12 +136,7 @@ const resetForm = reactive<ApiUser.PasswordReset.Request>({
 
 state.bgWhite = true
 
-function next() {
-  router.push({
-    path: '',
-    query: { step: step + 1 },
-  })
-}
+watch(step, () => window.scrollTo(0, 0))
 
 async function applyChange() {
   const { message } = await changePassword(values as any)
@@ -157,7 +152,7 @@ async function sendEmail() {
       .required('email is required')
       .validate(resetForm.email)
     await sendPasswordEmail(resetForm.email)
-    next()
+    step.value++
   } catch (err) {
     Toast(err.message)
   }
@@ -168,7 +163,7 @@ async function applyReset() {
     await string().required('password is required').validate(resetForm.password)
     resetForm.password_confirmation = resetForm.password
     await resetPassword(resetForm)
-    next()
+    step.value++
   } catch (err) {
     Toast(err.message)
   }

+ 4 - 0
src/pages/repaire/history.vue

@@ -1,6 +1,10 @@
 <template>
   <div class="p-repaire">
     <h3 class="ptc-title">Confirm appointment</h3>
+    <div v-if="!list.length" class="ptc-empty">
+      <i class="ptc-empty-img"></i>
+      <p class="ptc-empty-txt">No appointment yet</p>
+    </div>
     <div v-for="item of list" :key="item.id" class="ptc-block wrapper">
       <div class="inner">
         <div class="block-title">

+ 4 - 2
src/pages/repaire/index.scss

@@ -21,6 +21,8 @@
   }
 
   .search-suggestions {
+    max-height: 464px * 2;
+    overflow: auto;
     @include media-breakpoint-down(md) {
       + .shop-wrap {
         display: none !important;
@@ -32,10 +34,10 @@
       top: 116px;
       padding: 0 64px 32px;
       width: 962px;
-      max-height: 464px * 2;
+      // max-height: 464px * 2;
       background: #FFFFFF;
       box-shadow: 0px 0px 28px 0px rgba(0, 0, 0, 0.08);
-      overflow: auto;
+      // overflow: auto;
       z-index: 2;
     }
   }

+ 5 - 5
src/pages/repaire/steps/StepOne.vue

@@ -27,7 +27,7 @@
         </div>
       </div>
       <div class="shop-wrap">
-        <div class="tip">Nearby shops</div>
+        <div v-show="!postCode" class="tip">Nearby shops</div>
         <InfiniteList
           class="shop-list-wrap"
           :loading="loading"
@@ -78,10 +78,10 @@ const hasMore = ref(true)
 const list = ref<any[]>()
 const suggestions = ref<any[]>([])
 const code = ref('')
+const postCode = ref('')
 
 let pageNo = 1
 let coords: GeolocationCoordinates | undefined
-let postCode = ''
 
 async function fetchData() {
   loading.value = true
@@ -96,7 +96,7 @@ async function fetchData() {
       size: 10,
       lat: coords?.latitude,
       lng: coords?.longitude,
-      post_code: postCode,
+      post_code: postCode.value,
     })
     list.value.push(...results.items)
     pageNo++
@@ -121,8 +121,8 @@ const autocomplete = debounce(async () => {
 
 function handleSearch() {
   const value = code.value.trim()
-  if (value === postCode) return
-  postCode = value
+  if (value === postCode.value) return
+  postCode.value = value
   pageNo = 1
   list.value = []
   suggestions.value = []

+ 2 - 0
src/style/_variables.scss

@@ -4,6 +4,8 @@ $danger-color: #EB3735;
 $border-color: #D9D9D9;
 $placeholder-color: #bebebe;
 
+$toast-shadow: 0 4Px 10Px rgba(204, 217, 239, 40%);
+
 $nav-bar-height: 116px;
 $nav-bar-height-md: 168px;
 

+ 18 - 25
src/style/components.scss

@@ -142,31 +142,6 @@
   border-radius: 30px 4px 30px 4px;
 }
 
-.ptc-select {
-  position: relative;
-  padding: 0 114px 0 34px;
-  line-height: 84px;
-  border-radius: 8px;
-  border: 2px solid #D9D9D9;
-  font-size: 32px;
-  color: #1a1a1a;
-
-  &__placeholder {
-    color: $placeholder-color;
-  }
-
-  &::after {
-    content: '';
-    position: absolute;
-    top: 50%;
-    right: 34px;
-    transform: translateY(-50%);
-    width: 44px;
-    height: 44px;
-    background: #eee;
-  }
-}
-
 .ptc-comboinput {
   display: flex;
   .ptc-input {
@@ -182,3 +157,21 @@
     font-size: 28px;
   }
 }
+
+.ptc-empty {
+  height: 900px;
+  text-align: center;
+  background: #fff;
+  overflow: hidden;
+  &-img {
+    @include icon('@img/empty.png', 160px, 206px);
+    display: inline-block;
+    vertical-align: top;
+    margin-top: 200px;
+  }
+  &-txt {
+    margin-top: 48px;
+    font-size: 32px;
+    color: #999;
+  }
+}