You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
495 lines
18 KiB
495 lines
18 KiB
<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 tw-mt-[30px] md:tw-rounded-[24px] md:tw-pt-[60px] md:tw-pb-[150px] md:tw-px-[30px]">
|
|
<h1 class="tw-text-[40px] tw-font-bold tw-mb-[20px] md:tw-text-[24px]">{{ $t('Login') }}</h1>
|
|
<p class="tw-body-3 tw-text-neutral-400 tw-mb-[16px] md:tw-mb-[12px]">
|
|
{{ $t('Welcome back! Please enter your details') }}
|
|
</p>
|
|
<p class="tw-body-3 tw-mb-[24px] md:tw-mb-[32px]">{{ $t('Not a member?') }} <nuxt-link
|
|
:to="localePath('/user/signup')" class="primary--text text-decoration-none">{{ $t('Sign up') }}</nuxt-link>
|
|
</p>
|
|
<!-- <div class="tw-grid tw-grid-cols-1 tw-gap-[10px] tw-mb-[30px] md:tw-gap-[12px] md:tw-mb-[12px]">
|
|
<button @click="googleLogin"
|
|
class="tw-block tw-w-full tw-py-[8px] tw-rounded-[16px] tw-border tw-border-solid tw-text-black tw-border-neutrals-200"><img
|
|
width="20px" height="20px" src="~/assets/img/g-normal.png" class="mr-5" />{{ $t('Login with Google')
|
|
}}</button>
|
|
<button @click="facebookLogin"
|
|
class="tw-block tw-w-full tw-py-[8px] tw-rounded-[16px] tw-border tw-border-solid tw-text-black tw-border-neutrals-200"><img
|
|
width="20px" height="20px" src="~/assets/img/f_logo_RGB-Blue_72.png" class="mr-5" />
|
|
{{ $t("Login with Facebook")
|
|
}}</button>
|
|
</div>
|
|
<div class="tw-grid tw-grid-cols-[auto_16px_auto] tw-gap-[28px] tw-mb-[6px]">
|
|
<div class="tw-flex tw-justify-center tw-items-center">
|
|
<div class="tw-w-full tw-h-[1px] tw-bg-neutral-200"></div>
|
|
</div>
|
|
<div class="tw-text-neutral-400 tw-body-3 tw-font-normal">{{ $t("or") }}</div>
|
|
<div class="tw-flex tw-justify-center tw-items-center">
|
|
<div class="tw-w-full tw-h-[1px] tw-bg-neutral-200"></div>
|
|
</div>
|
|
</div> -->
|
|
<div v-if="serviceExceptionActive" class="warning--text text-size-14 ps-1 mb-3">
|
|
{{ $t('Service exception') }}
|
|
</div>
|
|
<div v-if="wrongMessageActive" class="warning--text text-size-14 ps-1 mb-3">
|
|
{{ $t('The username or password entered is incorrect') }}
|
|
</div>
|
|
<v-form ref="loginFormRef" lazy-validation>
|
|
<!-- <div v-if="$auth.$storage.getUniversal('userAccount') && $auth.$storage.getUniversal('userPassword')"></div>
|
|
<div v-else></div> -->
|
|
<v-text-field
|
|
v-model="userData.Account" background-color="neutrals darken-1" :label="this.$t('Email')"
|
|
:placeholder="this.$t('Email')" height="40px" filled rounded dense single-line persistent-placeholder
|
|
:rules="[rules.email,rules.require]" v-on:input="updateValid"
|
|
/>
|
|
<v-text-field
|
|
v-model="userData.Password" background-color="neutrals darken-1" :label="this.$t('Password')"
|
|
:type=" showPass ? 'text' : 'password'" :placeholder="this.$t('Password')" filled rounded dense single-line
|
|
persistent-placeholder :append-icon=" showPass ? 'mdi-eye' : 'mdi-eye-off'" @click:append="showPass = !showPass"
|
|
:rules="[rules.checkPassword,rules.require]" v-on:input="updateValid" @keyup.enter="userLogin"
|
|
/>
|
|
</v-form>
|
|
<div class="tw-flex tw-justify-between tw-items-center tw-mb-[28px] md:tw-mb-[32px]">
|
|
<div class="tw-flex tw-items-center">
|
|
<div class="tw-flex tw-items-center">
|
|
<div class="tw-flex tw-flex-col">
|
|
<label class="tw-body-4 container-checkbox" for="remember">
|
|
{{ $t('Remember me')
|
|
}}
|
|
<input id="remember" type="checkbox" value="remember" v-model="remember" />
|
|
<span class="checkmark"></span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="tw-flex tw-items-center">
|
|
<nuxt-link class="complementary--text text-decoration-none text-size-14" :to="localePath('/user/forgot')">{{
|
|
$t('Forgot Password?') }}</nuxt-link>
|
|
</div>
|
|
</div>
|
|
<div class="md:tw-flex md:tw-justify-center md:tw-items-center"> <button @click="userLogin" :disabled="!valid"
|
|
: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("Login")
|
|
}}</button></div>
|
|
<v-dialog v-model="dialog" :width="$vuetify.breakpoint.smAndUp ? 423 : 294"
|
|
@click:outside="colseDialog()">
|
|
<v-card class="tw-p-[30px]" :height="$vuetify.breakpoint.smAndUp ? 289 : 290">
|
|
<v-spacer class="d-flex align-center tw-justify-between tw-mb-[30px]">
|
|
<div class="tw-text-[20px] tw-font-bold tw-text-black">
|
|
{{ $t("Verify your email") }}
|
|
</div>
|
|
<v-btn @click="colseDialog()" icon>
|
|
<v-icon> mdi-close </v-icon>
|
|
</v-btn>
|
|
</v-spacer>
|
|
<v-spacer class="tw-mb-[40px]">
|
|
<div class="tw-text-[16px] tw-text-neutrals-800">
|
|
{{ $t("Oops! Seems like you haven't verified your email,please click the button below to resend a verification email.")}}
|
|
</div>
|
|
</v-spacer>
|
|
<button @click="resendVerifyEmail()" :class="['tw-text-white tw-bg-primary-1 hover:tw-bg-primary-light tw-text-[18px] tw-rounded-[16px] tw-px-[77px] tw-py-[13px]']">
|
|
{{ $t("Resend verification email") }}
|
|
</button>
|
|
<!-- <v-btn @click="resendVerifyEmail" class="tw-bg-primary-1 hover:tw-bg-primary-light tw-text-white tw-text-[18px] tw-rounded-[16px] tw-px-[77px] tw-py-[13px]"
|
|
:disabled="countdown > 0">
|
|
{{ $t("Resend verification email") }}
|
|
<span v-if="countdown > 0">
|
|
{{ `(${this.countdown})` }}
|
|
</span>
|
|
</v-btn> -->
|
|
</v-card>
|
|
</v-dialog>
|
|
<v-dialog v-model="deleteDialog" :width="$vuetify.breakpoint.smAndUp ? 423 : 294"
|
|
@click:outside="colseDialog()">
|
|
<v-card class="tw-p-[30px]" :height="$vuetify.breakpoint.smAndUp ? 289 : 290">
|
|
<v-spacer class="d-flex tw-justify-between align-center tw-mb-[30px]">
|
|
<div class="tw-text-[20px] tw-text-black tw-font-bold">
|
|
{{ $t("Reactivate your account") }}
|
|
</div>
|
|
<v-btn @click="colseDialog()" icon>
|
|
<v-icon> mdi-close </v-icon>
|
|
</v-btn>
|
|
</v-spacer>
|
|
<v-spacer class="tw-mb-[40px]">
|
|
<div class="tw-text-[16px] tw-text-neutrals-800 tw-font-bold">
|
|
{{ $t("Welcome back!")}}
|
|
</div>
|
|
<div class="tw-text-[16px] tw-text-neutrals-800">
|
|
{{ $t("Looks like your account has been deactivated.")}}
|
|
<br />
|
|
{{ $t("Would you like to reactivate this account?")}}
|
|
</div>
|
|
</v-spacer>
|
|
<button @click="ReactivateAccount()" class="tw-bg-primary-1 tw-text-white hover:tw-bg-primary-light tw-text-[18px] tw-rounded-[16px] tw-px-[86px] tw-py-[13px]">
|
|
{{ $t("Reactivate my account") }}
|
|
</button>
|
|
<!-- <v-btn class="primary tw-w-auto" rounded
|
|
:disabled="countdown > 0">
|
|
<span v-if="countdown > 0">
|
|
{{ `(${this.countdown})` }}
|
|
</span>
|
|
</v-btn> -->
|
|
</v-card>
|
|
</v-dialog>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { getCurrentTime } from "~/utils/assist";
|
|
export default {
|
|
name: "login",
|
|
layout: "login",
|
|
auth: false,
|
|
data() {
|
|
return {
|
|
timer: null,
|
|
showPass: false,
|
|
resendDialog: false,
|
|
wrongMessageActive: false,
|
|
verifyEmailSent: false,
|
|
serviceExceptionActive: false,
|
|
valid: false,
|
|
remember: false,
|
|
countdown: 60,
|
|
userData: {
|
|
Account: '',
|
|
Password: '',
|
|
},
|
|
rules: {
|
|
require: value => !!value || this.$t('Required.'),
|
|
email: v => /^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/.test(v) || this.$t('Invalid email'),
|
|
// checkPassword: v => (/(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])/.test(v) && v.length >= 8 && v.length <= 20) || '請輸入密碼',
|
|
checkPassword: v => v.length >= 1 || '請輸入密碼',
|
|
},
|
|
deleteDialog: false,
|
|
dialog: false,
|
|
expireTime: new Date(),
|
|
}
|
|
},
|
|
watch: {
|
|
remember: {
|
|
handler: function () {
|
|
if (this.remember == true) {
|
|
this.$auth.$storage.setUniversal("userPassword", this.userData.Password);
|
|
this.$auth.$storage.setUniversal("userAccount", this.userData.Account);
|
|
}else{
|
|
this.$auth.$storage.removeUniversal("userPassword");
|
|
this.$auth.$storage.removeUniversal("userAccount", this.userData.Account);
|
|
}
|
|
},
|
|
},
|
|
},
|
|
created(){
|
|
if(this.$auth.$storage.getUniversal('userAccount') && this.$auth.$storage.getUniversal('userPassword')){
|
|
this.checkExpireTime();
|
|
|
|
}
|
|
},
|
|
mounted(){
|
|
if(this.$auth.$storage.getUniversal('userAccount') && this.$auth.$storage.getUniversal('userPassword')){
|
|
this.remember = true;
|
|
|
|
}else{
|
|
this.remember = false;
|
|
|
|
}
|
|
|
|
var userAccount = this.$auth.$storage.getUniversal('userAccount');
|
|
var userPassword = this.$auth.$storage.getUniversal('userPassword');
|
|
|
|
this.userData.Account = userAccount ? userAccount : '';
|
|
this.userData.Password = userPassword ? userPassword : '';
|
|
|
|
if(this.userData.Account !=='' && this.userData.Password !==''){
|
|
this.valid = true;
|
|
}else{
|
|
this.valid = false;
|
|
}
|
|
|
|
},
|
|
methods: {
|
|
colseDialog(){
|
|
this.dialog = false;
|
|
this.deleteDialog = false;
|
|
|
|
},
|
|
async userLogin() {
|
|
let that = this;
|
|
if (!that.$refs.loginFormRef.validate()) return;
|
|
try {
|
|
const response =await that.$auth.loginWith('local', { data: that.userData });
|
|
that.serviceExceptionActive = false;
|
|
if(response.data.STATUSCODE==200){
|
|
let data = response.data.DATA;
|
|
if(data.authtoken){
|
|
const authtoken = data.authtoken;
|
|
that.$auth.$storage.removeUniversal('authtoken');
|
|
that.$auth.$storage.setUniversal('authtoken', authtoken);
|
|
let path = that.$auth.$storage.getUniversal('userBeforePath');
|
|
if(path == "/user"){
|
|
path = "/";
|
|
}
|
|
that.$router.push({path: path});
|
|
}
|
|
}else if(response.data.STATUSCODE==500){
|
|
that.$auth.redirect('login');
|
|
}else if(response.data.STATUSCODE==401){
|
|
if(response.data.MSG == "0"){
|
|
that.dialog = true;
|
|
}else if(response.data.MSG == "2"){
|
|
that.deleteDialog = true;
|
|
}else if(response.data.MSG == "帳號或密碼不正確"){
|
|
that.wrongMessageActive = true;
|
|
}
|
|
}else{
|
|
// that.resendDialog = !that.resendDialog;
|
|
that.wrongMessageActive = true;
|
|
}
|
|
} catch(err) {
|
|
console.log(err);
|
|
that.serviceExceptionActive = true;
|
|
// if(err && err.response && err.response.status){
|
|
// err.response.status === 403 ? that.resendDialog = !that.resendDialog : err.response.status === 401 ? that.wrongMessageActive = true : that.resendDialog;
|
|
// }
|
|
}
|
|
},
|
|
resendVerifyEmail() {
|
|
this.$axios
|
|
.post(
|
|
`/trending/api/Signup/ReSendVerifyMail?Email=${this.userData.Account}`
|
|
)
|
|
.then((response) => {
|
|
//console.log(JSON.stringify(response))
|
|
if(response && response.data){
|
|
this.dialog = false;
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
console.log(error);
|
|
});
|
|
|
|
},
|
|
ReactivateAccount(){
|
|
this.$axios
|
|
.post(
|
|
`/trending/api/Members/ReactivateAccountByAcc?Account=${this.userData.Account}`
|
|
)
|
|
.then((response) => {
|
|
//console.log(JSON.stringify(response))
|
|
if(response && response.data && response.data.DATA && response.data.DATA.rel){
|
|
let data = response.data.DATA.rel
|
|
if(data){
|
|
this.deleteDialog = false;
|
|
|
|
}
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
console.log(error);
|
|
});
|
|
},
|
|
updateValid(){
|
|
if(this.userData.Account !=='' && this.userData.Password !==''){
|
|
this.valid = true;
|
|
}else{
|
|
this.valid = false;
|
|
}
|
|
},
|
|
checkExpireTime(){
|
|
console.log("給我時間");
|
|
console.log("帳號:" + this.$auth.$storage.getUniversal('userAccount'));
|
|
this.$axios
|
|
.get(`/trending/api/System/RememberMe?Account=${this.$auth.$storage.getUniversal('userAccount')}`)
|
|
.then((response) => {
|
|
//console.log(response);
|
|
const data = response.data.DATA.authtoken;
|
|
this.expireTime = new Date(data.ExpireTime);
|
|
const now = new Date(Date.now());
|
|
|
|
const saveTime = this.expireTime - now;
|
|
if(saveTime >= 0){
|
|
const hour = saveTime / (60 * 60 * 1000);
|
|
|
|
if(hour == 0){
|
|
this.$auth.$storage.removeUniversal('userPassword');
|
|
this.$auth.$storage.removeUniversal('userAccount');
|
|
}
|
|
}else{
|
|
this.$auth.$storage.removeUniversal('userPassword');
|
|
this.$auth.$storage.removeUniversal('userAccount');
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
console.log(error);
|
|
});
|
|
|
|
}
|
|
},
|
|
beforeUnmount() {
|
|
if(this.timer!=null){
|
|
clearInterval(this.timer);
|
|
}
|
|
},
|
|
beforeRouteEnter(to, from, next) {
|
|
next(vm => {
|
|
if (from.name) {
|
|
if (!from.path.includes('user')) {
|
|
vm.$auth.$storage.setUniversal("userBeforePath", from.fullPath, true)
|
|
}
|
|
}
|
|
if (vm.$auth.loggedIn) {
|
|
vm.$router.push({path: vm.$auth.$storage.getUniversal('userBeforePath') || '/'})
|
|
}
|
|
else {
|
|
next()
|
|
}
|
|
})
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
$border-style: 1px solid #E5E5E5;
|
|
#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;
|
|
}
|
|
|
|
.title {
|
|
font-weight: 700;
|
|
font-size: 26px;
|
|
line-height: 34px;
|
|
letter-spacing: 0.02em;
|
|
color: #232323;
|
|
}
|
|
|
|
.btn-border {
|
|
border: $border-style;
|
|
}
|
|
|
|
.seperator {
|
|
border-bottom: $border-style;
|
|
text-align: center;
|
|
height: 12px;
|
|
margin: 20px 0 30px;
|
|
}
|
|
|
|
:deep(.v-text-field.v-text-field--enclosed .v-text-field__details) {
|
|
margin-bottom: 0;
|
|
padding: 0;
|
|
|
|
.v-messages {
|
|
display: none;
|
|
}
|
|
|
|
.v-messages.error--text {
|
|
display: block;
|
|
margin-top: 4px;
|
|
margin-bottom: 16px;
|
|
}
|
|
}
|
|
|
|
/* The container */
|
|
.container-checkbox {
|
|
display: block;
|
|
position: relative;
|
|
padding-left: 28px;
|
|
cursor: pointer;
|
|
-webkit-user-select: none;
|
|
-moz-user-select: none;
|
|
-ms-user-select: none;
|
|
user-select: none;
|
|
}
|
|
|
|
/* Hide the browser's default checkbox */
|
|
.container-checkbox input {
|
|
position: absolute;
|
|
opacity: 0;
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* Create a custom checkbox */
|
|
.container-checkbox .checkmark {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
height: 18px;
|
|
width: 18px;
|
|
background-color: transparent;
|
|
border: 1px solid #f48800;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
/* On mouse-over, add a grey background color */
|
|
.container-checkbox:hover input~.checkmark {
|
|
border-color: #f48800;
|
|
}
|
|
|
|
/* When the checkbox is checked, add a blue background */
|
|
.container-checkbox input:checked~.checkmark {
|
|
background-color: #f48800;
|
|
border-color: #f48800;
|
|
}
|
|
|
|
/* Create the checkmark/indicator (hidden when not checked) */
|
|
.container-checkbox .checkmark:after {
|
|
content: "";
|
|
position: absolute;
|
|
display: none;
|
|
}
|
|
|
|
/* Show the checkmark when checked */
|
|
.container-checkbox input:checked~.checkmark:after {
|
|
display: block;
|
|
}
|
|
|
|
/* Style the checkmark/indicator */
|
|
.container-checkbox .checkmark:after {
|
|
left: 5px;
|
|
top: 2px;
|
|
width: 5px;
|
|
height: 10px;
|
|
border: solid #ffffff;
|
|
border-width: 0 2px 2px 0;
|
|
-webkit-transform: rotate(45deg);
|
|
-ms-transform: rotate(45deg);
|
|
transform: rotate(45deg);
|
|
}
|
|
</style>
|
|
|
|
|