parent
commit
5cf08bbd61
  1. 11
      FrontEnd/assets/svg/Icon.svg
  2. 161
      FrontEnd/components/newComponent/modal/VerifyCodeModal.vue
  3. 9
      FrontEnd/components/user/userServiceItem.vue
  4. 2
      FrontEnd/locales/zh-tw.json
  5. 1
      FrontEnd/pages/user/myBooking.vue
  6. 148
      FrontEnd/pages/user/redirect.vue
  7. 146
      FrontEnd/pages/user/signUp.vue

11
FrontEnd/assets/svg/Icon.svg

@ -0,0 +1,11 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#70huf6jbya)" stroke="#7997FF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M17.25 3v4.5h-4.5"/>
<path d="M15.367 11.25a6.75 6.75 0 1 1-1.59-7.02L17.25 7.5"/>
</g>
<defs>
<clipPath id="70huf6jbya">
<path fill="#fff" d="M0 0h18v18H0z"/>
</clipPath>
</defs>
</svg>

161
FrontEnd/components/newComponent/modal/VerifyCodeModal.vue

@ -0,0 +1,161 @@
<template>
<modal name="VerifyCode" :clickToClose="false">
<div class="tw-text-base-primary">
<div class="modal-header tw-flex tw-w-full tw-justify-between tw-mb-[30px]">
<div class="tw-font-bold tw-text-[20px]">{{ $t("Verify your email") }}</div>
<button class="close tw-transition tw-btn-md" @click="$modal.hide('VerifyCode')"></button>
</div>
<div class="tw-mb-[30px]">
<div class="modal-content tw-text-[18px] tw-text-hint">
我們已寄送認證碼至您的電子信箱<span class="tw-text-primary-1 tw-text-[18px]">xxx@email.com</span>
</div>
<div>
請至電子信箱確認後在下方輸入驗證碼來啟動您的帳戶
</div>
</div>
<div class="tw-mb-[40px]">
<div>
<input type="text" v-model="user_VerifyCode" placeholder="請輸入認證碼" :class="['tw-w-full tw-text-[18px] tw-p-[10px] tw-border tw-border-solid tw-mb-[10px] tw-rounded-[8px] md:tw-max-w-[360px]', validation ? 'tw-border-error-default' : 'tw-border-[ef5a5a]']" />
</div>
<div class="tw-flex tw-justify-between">
<div :class="['tw-text-[14px] tw-text-error-default', validation ? 'tw-block' : 'tw-hidden']">
認證碼錯誤
</div>
<button class="tw-grid tw-grid-cols-[18px_100px] tw-gap-[10px]">
<img src="~/assets/svg/Icon.svg"/>
<div class="tw-text-[14px] tw-text-complementary-1 tw-w-fit">
重新寄送認證碼
</div>
</button>
</div>
</div>
<div class="tw-grid tw-grid-cols-2 tw-gap-[10px]">
<button @click="$modal.hide('VerifyCode')" class="tw-rounded-[8px] tw-text-primary-1 tw-text-[18px] tw-px-[12px] tw-py-[12px] md:tw-rounded-[16px]">
取消
</button>
<button @click="checkVerifyCode" :class="['tw-rounded-[8px] tw-text-[18px] tw-px-[12px] tw-py-[12px] md:tw-rounded-[16px]', validation ? 'tw-text-base-disable tw-bg-neutral-100 tw-border-neutral-100' : 'tw-text-white tw-bg-primary-default tw-border-primary-default']">
確認
</button>
</div>
</div>
</modal>
</template>
<script>
export default {
name: "VerifyCode",
data() {
return {
user_VerifyCode: "",
checkCode: false,
errorCode: false,
validation: false,
};
},
props: {
error: {
type: Boolean,
}
},
watch: {
error: {
handler: function () {
this.validation = this.error;
console.log("validation: " + this.validation);
},
},
user_VerifyCode: {
handler: function () {
if(this.user_VerifyCode == ""){
this.validation = true;
}else if(this.user_VerifyCode.length > "6"){
this.validation = true;
}else{
this.validation = false;
}
}
}
},
methods: {
checkVerifyCode(){
this.checkCode = true;
this.$emit('user-VerifyCode', this.user_VerifyCode);
}
}
};
</script>
<style lang="scss" scoped>
.close {
position: absolute;
right: 25px;
top: 25px;
background-image: url("~/assets/svg/close.svg");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
width: 14px;
height: 14px;
@media (min-width: 1366px) {
position: relative;
right: initial;
top: initial;
}
}
:deep() {
.v--modal {
background-color: #fefefe !important;
text-align: left;
border-radius: 16px;
box-shadow: 0 20px 60px -2px rgb(27 33 58 / 40%);
padding: 20px;
max-width: 100%;
top: 0 !important;
left: 0 !important;
right: 0 !important;
margin: 0 auto;
height: auto !important;
vertical-align: middle;
@media (min-width: 768px) {
max-width: 360px;
}
}
.v--modal-overlay {
position: fixed;
box-sizing: border-box;
left: 0;
top: 0;
width: 100%;
height: auto;
background: rgba(0, 0, 0, 0.2);
z-index: 999;
opacity: 1;
}
.v--modal-top-right {
display: block;
position: fixed;
right: 0;
top: 0;
}
.v--modal-background-click {
display: flex;
justify-content: center;
align-items: center;
}
.v--modal-box {
margin-left: 60px;
margin-right: 60px;
@media (min-width: 768px) {
margin-left: 161px;
margin-right: 161px;
max-width: 360px;
}
}
}
</style>

9
FrontEnd/components/user/userServiceItem.vue

@ -7,7 +7,7 @@
class="tw-grid tw-grid-cols-[16%_82%] lg:tw-grid-cols-[13%_84%] tw-gap-x-2 lg:tw-gap-x-5"
>
<div>
<img class="tw-w-[100px] tw-h-[75px] tw-rounded-[10px ]" :src="info.OnSiteService.Logo"/>
<img class="tw-w-[100px] tw-h-[75px] tw-rounded-[10px]" :src="info.OnSiteService.Logo"/>
<!-- <nuxt-link :to="localePath('/user/booking/' + info.BookingNo)"> -->
<!-- </nuxt-link> -->
</div>
@ -72,6 +72,13 @@
>
{{ $t("Upload Remittance Slip") }}
</button>
<!-- <button
v-if="BookingOrder.BookingStatus == '02' && BookingOrder.PaymentStatus == '02' && BookingOrder.PaymentType == '2' && BookingOrder.Payment.Remittance != null"
@click.prevent="$emit('upload-remittance-slip', info.BookingID)"
class="tw-transition tw-justify-center tw-items-center tw-btn-md tw-text-white tw-bg-primary-1 tw-px-[30px] tw-py-[8.5px] tw-rounded-xl tw-w-fit tw-h-fit"
>
{{ $t("Upload Remittance Slip Again") }}
</button> -->
<!-- <button
v-if="mypaymentStatusMap(info.PaymentStatus) === 'Unpaid'"
class="tw-transition tw-justify-center tw-items-center tw-btn-md tw-text-white tw-bg-primary-1 tw-px-[30px] tw-py-[8.5px] tw-rounded-xl tw-w-fit tw-h-fit"

2
FrontEnd/locales/zh-tw.json

@ -103,7 +103,7 @@
"You might like ...": "你可能會喜歡...",
"Coming Soon in day": "倒數 {days} 天",
"in days": "{days} 天",
"Verify your email": "確認您的信箱",
"Verify your email": "驗證您的電子信箱",
"Thank you for signing up": "感謝您的註冊.",
"Not a member?": "還不是會員嗎?",
"Remember me": "記住我",

1
FrontEnd/pages/user/myBooking.vue

@ -141,7 +141,6 @@ export default {
// },
change(value){
this.searchValue = value;
console.log("shitValue:" + this.searchValue);
}
},

148
FrontEnd/pages/user/redirect.vue

@ -0,0 +1,148 @@
<template>
<div :class="['tw-h-full tw-p-[30px] tw-bg-white md:tw-bg-primary-pale']">
<div
class="xl:tw-grid xl:tw-grid-cols-[auto_414px] xl:tw-gap-[96px] xl:tw-max-w-[1246px] xl:tw-mx-auto xl:tw-px-[60px]">
<div class="tw-hidden xl:tw-block xl:tw-mt-[30px]">
<p class="welcome tw-text-primary-light">{{ $t("Welcome to ShowEasy") }}</p>
<p class="sub tw-text-neutral-400">
{{
$t(
"Your best guide from trip to show and from show to the world."
)
}}
</p>
<img class="mt-11 ml-15" :src="require('@/assets/img/UserLoginMain.png')" />
</div>
<div class="md:tw-w-[414px] md:tw-mx-auto">
<div class="tw-bg-white md:tw-rounded-[24px] md:tw-mt-[30px] md:tw-pt-[60px] md:tw-pb-[150px] md:tw-px-[30px]">
<div class="tw-font-bold tw-text-black tw-text-[18px] tw-mb-[16px]">
Thank you for signing up.
</div>
<div class="tw-text-black tw-text-[16px] tw-mb-[24px]">
Your email has been verified.
</div>
<button class="tw-bg-primary-1 tw-text-white tw-text-[16px] tw-w-full tw-py-[10px] tw-rounded-[16px] tw-mb-[16px]">
Explore with ShowEasy
</button>
<div class="tw-mx-auto tw-text-primary-1 tw-text-[14px] tw-w-fit">
Go to ShowEasy in {{ `${this.countdown}` }} sec...
</div>
<loading :isLoading="isPageLoading"></loading>
</div>
</div>
</div>
</div>
</template>
<script>
import loading from "@/components/newComponent/loading/loading.vue";
export default {
name: "Redirect",
layout: "login",
auth: false,
components: {
loading,
},
data() {
return {
isPageLoading: false,
countdown: 5,
};
},
watch: {
},
created(){
this.secondCountDown();
},
methods: {
secondCountDown(){
this.timer = setInterval(() => {
if (this.countdown > 0) {
this.countdown--;
}
if (this.countdown === 0) {
clearInterval(this.timer);
}
}, 1000);
if(this.countdown === 0){
console.log("0")
}
}
},
computed: {
},
};
</script>
<style lang="scss" scoped>
#app {
overflow-y: hidden;
}
.welcome {
color: #f5cda8;
font-family: Damion;
font-size: 48px;
margin-bottom: 0px;
font-weight: 400;
line-height: 66px;
letter-spacing: 0.02em;
}
.sub {
color: #9c9c9c;
font-style: italic;
font-weight: 400;
font-size: 22px;
line-height: 29px;
letter-spacing: 0.02em;
}
:deep(.v-text-field.v-text-field--enclosed .v-text-field__details) {
padding: 0;
margin: 0;
}
:deep(.v-messages__message) {
font-size: 14px;
}
$border-style: 1px solid #e5e5e5;
.title {
font-weight: 700;
font-size: 26px;
line-height: 34px;
letter-spacing: 0.02em;
color: #232323;
}
:deep(.v-text-field.v-text-field--enclosed .v-text-field__details) {
margin-bottom: 0;
padding: 0;
.v-messages {
color: #9c9c9c;
display: none;
}
.v-messages.error--text {
display: block;
margin-top: 4px;
margin-bottom: 16px;
}
}
.btn-border {
border: $border-style;
}
</style>

146
FrontEnd/pages/user/signUp.vue

@ -5,11 +5,7 @@
<div class="tw-hidden xl:tw-block xl:tw-mt-[30px]">
<p class="welcome tw-text-primary-light">{{ $t("Welcome to ShowEasy") }}</p>
<p class="sub tw-text-neutral-400">
{{
$t(
"Your best guide from trip to show and from show to the world."
)
}}
{{ $t("Your best guide from trip to show and from show to the world.") }}
</p>
<img class="mt-11 ml-15" :src="require('@/assets/img/UserLoginMain.png')" />
</div>
@ -20,7 +16,6 @@
<p class="tw-body-3 tw-text-neutral-400 tw-mb-[16px] md:tw-mb-[12px]">
{{ $t("Welcome to ShowEasy!") }}
</p>
<p class="tw-body-3 tw-mb-[45px] md:tw-mb-[32px]">
{{ $t("Already have an account?") }}
<nuxt-link :to="localePath('/user')" class="primary--text text-decoration-none">{{ $t("Login") }}</nuxt-link>
@ -49,15 +44,15 @@
{{ $t("Welcome to ShowEasy!") }}
</p>
<v-form v-model="valid">
<v-text-field v-model="userData.FirstName" background-color="neutrals darken-1"
<v-text-field v-model="user.FirstName" background-color="neutrals darken-1"
:label="this.$t('First Name') + '*'" placeholder="" filled rounded dense single-line :rules="[rules.require]">
</v-text-field>
<v-text-field v-model="userData.LastName" background-color="neutrals darken-1"
<v-text-field v-model="user.LastName" background-color="neutrals darken-1"
:label="this.$t('Last Name') + '*'" placeholder="" filled rounded dense single-line :rules="[rules.require]">
</v-text-field>
<v-text-field v-model="userData.Email" background-color="neutrals darken-1" :label="this.$t('Email') + '*'"
<v-text-field v-model="user.Email" background-color="neutrals darken-1" :label="this.$t('Email') + '*'"
filled rounded dense single-line :rules="[rules.email, rules.require]" validate-on-blur></v-text-field>
<v-text-field v-model="userData.Password" background-color="neutrals darken-1"
<v-text-field v-model="user.Password" background-color="neutrals darken-1"
:label="this.$t('Password') + '*'" :type="showPass ? 'text' : 'password'" placeholder="" filled rounded dense
single-line :rules="[rules.checkPassword, rules.require]" :hint="
this.$t(
@ -71,15 +66,19 @@
:append-icon="showConfirmPass ? 'mdi-eye' : 'mdi-eye-off'" @click:append="showConfirmPass = !showConfirmPass"
validate-on-blur></v-text-field>
</v-form>
<v-checkbox v-model="userData.Subscribe" class="mt-n2 ml-1"><template v-slot:label><span
class="neutrals--text text--darken-4 text-size-14">{{
$t("Subscribe to ShowEasy\’s newsletter")
}}</span></template></v-checkbox>
<div class="md:tw-flex md:tw-justify-center md:tw-items-center"> <button @click="userRegister"
:disabled="!validFormat"
:class="['tw-block tw-w-full tw-py-[10px] tw-rounded-[16px] tw-border tw-border-solid tw-body-3 tw-font-normal tw-transition-all tw-duration-200 tw-ease-in-out',valid?'tw-text-white tw-bg-primary-default tw-border-primary-default':'tw-text-base-disable tw-bg-neutral-100 tw-border-neutral-100']">
<v-checkbox v-model="user.Subscribe" class="mt-n2 ml-1">
<template v-slot:label>
<span class="neutrals--text text--darken-4 text-size-14">
{{ $t("Subscribe to ShowEasy\’s newsletter") }}
</span>
</template>
</v-checkbox>
<div class="md:tw-flex md:tw-justify-center md:tw-items-center">
<button @click="userRegister" :disabled="!validFormat" :class="['tw-block tw-w-full tw-py-[10px] tw-rounded-[16px] tw-border tw-border-solid tw-body-3 tw-font-normal tw-transition-all tw-duration-200 tw-ease-in-out',valid?'tw-text-white tw-bg-primary-default tw-border-primary-default':'tw-text-base-disable tw-bg-neutral-100 tw-border-neutral-100']">
{{ $t("Sign Up") }}
</button></div>
</button>
</div>
<!-- 原註冊流程Modal(信箱連結認證) -->
<v-dialog v-model="dialog" :width="$vuetify.breakpoint.smAndUp ? 423 : 294"
@click:outside="$router.push(localePath('/user'))">
<v-card class="pa-7" :height="$vuetify.breakpoint.smAndUp ? 249 : 290">
@ -92,7 +91,7 @@
</v-spacer>
<v-spacer class="text-size-16 my-7 neutrals--text text--darken-4">{{ $t("We've sent a verification email to")
}}<br />
<span class="primary--text">{{ userData.Email }}</span>{{
<span class="primary--text">{{ user.Email }}</span>{{
$t(". Please click the link within to activate your account.")
}}
</v-spacer>
@ -105,6 +104,7 @@
</v-btn>
</v-card>
</v-dialog>
<!-- 帳號已存在Modal -->
<v-dialog v-model="errorDialog" :width="$vuetify.breakpoint.smAndUp ? 423 : 294">
<v-card class="pa-7 border-radius-16" :max-height="$vuetify.breakpoint.smAndUp ? 249 : 290">
<v-spacer class="d-flex align-center text-size-20 neutrals--text text--darken-5">
@ -137,21 +137,22 @@
</p>
</v-spacer>
<loading :isLoading="isPageLoading"></loading>
<VerifyCode @user-VerifyCode="userVerifyCode" :error="error"></VerifyCode>
</div>
</div>
</div>
</div>
</template>
<script>
import loading from "@/components/newComponent/loading/loading.vue";
import VerifyCode from "@/components/newcomponent/modal/VerifyCodeModal.vue";
export default {
name: "SignUp",
layout: "login",
auth: false,
components: {
loading,
VerifyCode
},
data() {
return {
@ -180,10 +181,10 @@ export default {
"Passwords must be 8-20 characters with at least 1 number, 1 lower case letter and 1 upper case letter"
),
checkConfirmPassword: (v) =>
this.confirmPasswordText === this.userData.Password ||
this.confirmPasswordText === this.user.Password ||
this.$t("Your password and confirmation password do not match"),
},
userData: {
user: {
FirstName: "",
LastName: "",
Account: "",
@ -192,6 +193,12 @@ export default {
Subscribe: true,
},
signUp: false,
userInfo: {},
error: false,
userData: {
Account: '',
Password: '',
},
};
},
watch: {
@ -205,16 +212,16 @@ export default {
},
},
methods: {
//
userRegister() {
const postUserData = { ...this.userData };
const postUserData = { ...this.user };
this.isPageLoading = true;
this.$axios
.post(
`/trending/api/Signup/SignupWithEmail`, postUserData
)
.then((response) => {
//console.log(JSON.stringify(response));
console.log(JSON.stringify(response));
if(response.data.STATUSCODE == "400"){
this.errorDialog = true;
this.isPageLoading = false;
@ -222,31 +229,33 @@ export default {
if(response && response.data && response.data.DATA && response.data.DATA.rel){
let data = response.data.DATA.rel
if(data){
this.userInfo = data;
this.$modal.show('VerifyCode');
this.signUp = true;
this.timer = setInterval(() => {
if (this.countdown > 0) {
this.countdown--;
}
if (this.countdown === 0) {
clearInterval(this.timer);
}
}, 1000);
// this.timer = setInterval(() => {
// if (this.countdown > 0) {
// this.countdown--;
// }
// if (this.countdown === 0) {
// clearInterval(this.timer);
// }
// }, 1000);
this.isPageLoading = false;
this.dialog = !this.dialog;
//this.dialog = !this.dialog; //Modal
}
}
})
.catch((err) => {
console.log(err);
});
});
},
//
resendVerifyEmail() {
this.countdown = 60;
this.$axios
.post(
`/trending/api/Signup/ReSendVerifyMail?Email=${this.userData.Email}`
`/trending/api/Signup/ReSendVerifyMail?Email=${this.user.Email}`
)
.then((res) => {
//console.log(JSON.stringify(res));
@ -261,31 +270,54 @@ export default {
}, 1000);
})
.catch((err) => {
console.log(err);
});
});
},
async facebookLogin() {
try {
await this.$auth.loginWith("facebook");
} catch (err) {
console.log(err);
}
//
userVerifyCode(value){
this.$axios
.get(
`/trending/api/Signup/VerifyAccount?OrgID=${this.userInfo.OrgID}&MemberID=${this.userInfo.MemberID}&Code=${value}`
)
.then((response) => {
console.log(response);
if(response.data.STATUSCODE == 200){
this.$modal.hide('VerifyCode');
this.Login();
//this.$router.push(this.localePath("/user/redirect"));
}
else{
this.error = true;
}
})
.catch((err) => {
console.log(err);
});
},
async googleLogin() {
try {
await this.$auth.loginWith("google");
} catch (err) {
console.log(err);
//
async Login(){
this.userData.Account = this.userInfo.Account;
this.userData.Password = this.user.Password;
const response = await this.$auth.loginWith('local', { data: this.userData });
if(response.data.STATUSCODE == 200){
let data = response.data.DATA;
if(data.authtoken){
const authtoken = data.authtoken;
this.$auth.$storage.removeUniversal('authtoken');
this.$auth.$storage.setUniversal('authtoken', authtoken);
let path = this.$auth.$storage.getUniversal('userBeforePath');
if(path == "/user"){
path = "/";
}
this.$router.push({path: path});
}
}
},
}
},
computed: {
validFormat() {
if (this.valid && this.userData.Password === this.confirmPasswordText) {
if (this.valid && this.user.Password === this.confirmPasswordText) {
return true;
} else {
return false;

|||||||
100:0
Loading…
Cancel
Save