冯诚 2 years ago
parent
commit
01707e9002

+ 1 - 1
postcss.config.js

@@ -2,7 +2,7 @@ module.exports = {
   plugins: {
     'postcss-pxtorem': {
       rootValue(input) {
-        return /[\\/]node_modules[\\/]vant/.test(input.file) ? 50 : 100
+        return /[\\/]node_modules[\\/]/.test(input.file) ? 50 : 100
       },
       propList: ['*', '!filter'],
       minPixelValue: 2,

File diff suppressed because it is too large
+ 2 - 0
src/assets/loading2.svg


+ 0 - 9
src/components/infinite-list/index.vue

@@ -90,14 +90,5 @@ watchEffect(onInvalidate => {
       right: -50px;
     }
   }
-
-  @keyframes rotate {
-    0% {
-      transform: rotate(0deg);
-    }
-    100% {
-      transform: rotate(360deg);
-    }
-  }
 }
 </style>

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

@@ -96,11 +96,5 @@ watch(() => props.message, reset)
       animation: rotate 1s linear infinite;
     }
   }
-
-  @keyframes rotate {
-    100% {
-      transform: rotate(360deg);
-    }
-  }
 }
 </style>

+ 5 - 1
src/hooks/useForm.ts

@@ -36,7 +36,11 @@ export default function useForm<Shap extends object>(
     { leading: true, trailing: false }
   )
 
-  return { values, handleSubmit }
+  const reset = () => {
+    Object.keys(values).forEach(key => delete (values as any)[key])
+  }
+
+  return { values, handleSubmit, reset }
 }
 
 setLocale({

+ 50 - 6
src/pages/invite/index.vue

@@ -35,23 +35,24 @@
           <div class="method">
             <p class="method-title">Email invitation</p>
             <textarea
+              v-model="emails"
               placeholder="Enter email addresses, multiple mailboxes are separated by“ ,”"
             ></textarea>
           </div>
-          <button class="ptc-button">Send invitation</button>
+          <button class="ptc-button" @click="invite">Send invitation</button>
         </div>
       </div>
     </div>
 
     <div class="p-bottom">
-      <h3 class="ptc-title">My Reward $90</h3>
+      <h3 class="ptc-title">My Reward ${{ totalAmount }}</h3>
       <div class="block records">
         <div class="ptc-inner-md">
           <ul>
-            <li v-for="n of 5" :key="n" class="record">
-              <span class="left">John</span>
-              <span class="center">2021/09/02</span>
-              <span class="right">$10</span>
+            <li v-for="(award, index) of awards" :key="index" class="record">
+              <span class="left">{{ award.title }}</span>
+              <span class="center">{{ award.created_at }}</span>
+              <span class="right">${{ award.gift_card_amount }}</span>
             </li>
           </ul>
         </div>
@@ -77,6 +78,49 @@
   </div>
 </template>
 
+<script lang="ts">
+import { defineComponent } from 'vue'
+import { string } from 'yup'
+import { inviteFriends, getInviteRewards } from '@/service/user'
+import Toast from '@/components/toast'
+
+export default defineComponent({
+  name: 'InviteFriends',
+  async beforeRouteEnter(to, from, next) {
+    const { results } = await getInviteRewards()
+    next((vm: any) => (vm.awards = results))
+  },
+  data() {
+    return {
+      emails: '',
+      awards: [] as any[],
+    }
+  },
+  computed: {
+    totalAmount() {
+      // @ts-ignore
+      return this.awards.reduce((sum, award) => sum + award.gift_card_amount, 0)
+    },
+  },
+  methods: {
+    async invite() {
+      if (!this.emails) return Toast('Please enter email addresses')
+      try {
+        this.emails
+          .split(',')
+          .forEach(email =>
+            string().email('Please check email addresses').validateSync(email)
+          )
+        await inviteFriends(this.emails)
+        Toast('done')
+      } catch (err) {
+        Toast(err.message)
+      }
+    },
+  },
+})
+</script>
+
 <style lang="scss">
 .p-invite {
   .p-top {

+ 3 - 2
src/pages/password/index.vue

@@ -104,6 +104,7 @@ import {
 import { string } from 'yup'
 import { debounce } from 'lodash-es'
 import useForm from '@/hooks/useForm'
+import Toast from '@/components/toast'
 
 const props = defineProps<{ action: 'change' | 'reset' }>()
 
@@ -145,7 +146,7 @@ async function sendEmail() {
     await sendPasswordEmail(resetForm.email)
     next()
   } catch (err) {
-    console.error(err.message)
+    Toast(err.message)
   }
 }
 
@@ -156,7 +157,7 @@ async function applyReset() {
     await resetPassword(resetForm)
     next()
   } catch (err) {
-    console.error(err.message)
+    Toast(err.message)
   }
 }
 </script>

+ 7 - 1
src/pages/register/index.vue

@@ -45,10 +45,14 @@
 
 <script setup lang="ts">
 import { string } from 'yup'
+import { useRouter } from 'vue-router'
 import useForm from '@/hooks/useForm'
 import { register } from '@/service/user'
+import Toast from '@/components/toast'
 
-const { values, handleSubmit } = useForm<ApiUser.Register.Request>({
+const router = useRouter()
+
+const { values, handleSubmit, reset } = useForm<ApiUser.Register.Request>({
   schema: {
     email: string().email().required(),
     password: string().required(),
@@ -59,5 +63,7 @@ async function onSubmit() {
   values.name = values.email
   values.password_confirmation = values.password
   await register(values as any)
+  Toast('register success')
+  setTimeout(() => router.push('/login'), 500)
 }
 </script>

+ 1 - 0
src/pages/repaire/steps/StepFive.vue

@@ -64,4 +64,5 @@
 
 <script setup lang="ts">
 import { state } from '../store'
+import { cancelRepair } from '@/service/repair'
 </script>

+ 20 - 2
src/pages/repaire/steps/StepThree.vue

@@ -50,7 +50,9 @@
     </div>
     <div class="ptc-button-group">
       <div class="ptc-inner">
-        <button class="ptc-button" @click="state.step++">SUBMIT</button>
+        <button class="ptc-button ptc-button--loading" @click="submit">
+          SUBMIT
+        </button>
       </div>
     </div>
   </div>
@@ -59,11 +61,27 @@
 <script setup lang="ts">
 import { onMounted } from 'vue'
 import { state } from '../store'
-import { getRepairPhone } from '@/service/repair'
+import { getRepairPhone, applyRepair, rescheduleRepair } from '@/service/repair'
+import Toast from '@/components/toast'
 
 onMounted(async () => {
   if (state.repairId) {
     state.phoneNumber = (await getRepairPhone()).results
   }
 })
+
+async function submit() {
+  if (!state.phoneNumber) return Toast('Please enter a phone number')
+  const commonParams = {
+    igeektek_id: state.shop.igeektek_id,
+    pickup_time: state.date + ' ' + state.period,
+    phone_number: state.phoneNumber,
+    remark: state.remark || '',
+  }
+  const request = state.repairId
+    ? rescheduleRepair({ id: +state.repairId, ...commonParams })
+    : applyRepair({ ...commonParams })
+  await request
+  state.step++
+}
 </script>

+ 2 - 0
src/router.ts

@@ -2,6 +2,8 @@ import { createRouter, createWebHistory } from 'vue-router'
 // @ts-ignore
 import NProgress from 'nprogress'
 
+NProgress.configure({ showSpinner: false })
+
 const router = createRouter({
   history: createWebHistory(import.meta.env.BASE_URL),
   scrollBehavior() {

+ 8 - 0
src/service/user.ts

@@ -31,3 +31,11 @@ export function updateUserInfo(data: ApiUser.Update.Request) {
 export function getUserInfo() {
   return request.get<ApiUser.Info.Response>('/user/info')
 }
+
+export function inviteFriends(emails: string) {
+  return request.post('/user/invite', { emails })
+}
+
+export function getInviteRewards() {
+  return request.get('/user/invite/rewards')
+}

+ 5 - 0
src/style/animate.scss

@@ -13,4 +13,9 @@
   100% {
     opacity: 0;
   }
+}
+@keyframes rotate {
+  100% {
+    transform: rotate(360deg);
+  }
 }

+ 16 - 1
src/style/components.scss

@@ -59,7 +59,9 @@
 }
 
 .ptc-button {
-  display: block;
+  display: flex;
+  justify-content: center;
+  align-items: center;
   width: 100%;
   height: 92px;
   background: $primary-color;
@@ -79,6 +81,19 @@
       background: #f2f5fb;
     }
   }
+
+  &--loading {
+    pointer-events: none;
+    opacity: 0.75;
+    position: relative;
+    &::before {
+      content: '';
+      margin-right: 8px;
+      margin-top: -4px;
+      animation: rotate 2s linear infinite;
+      @include icon('@img/loading2.svg', 48px);
+    }
+  }
 }
 
 .ptc-form {