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.

376 lines
15 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. <template>
  2. <div :class="['tw-h-full tw-p-[30px] tw-bg-white md:tw-bg-primary-pale']">
  3. <div
  4. 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]">
  5. <div class="tw-hidden xl:tw-block xl:tw-mt-[30px]">
  6. <p class="welcome tw-text-primary-light">{{ $t("Welcome to ShowEasy") }}</p>
  7. <p class="sub tw-text-neutral-400">
  8. {{ $t("Your best guide from trip to show and from show to the world.") }}
  9. </p>
  10. <img class="mt-11 ml-15" :src="require('@/assets/img/UserLoginMain.png')" />
  11. </div>
  12. <div class="md:tw-w-[414px] md:tw-mx-auto">
  13. <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]">
  14. <v-spacer v-if="emailSignUp">
  15. <h1 class="tw-text-[40px] tw-font-bold tw-mb-[20px] md:tw-text-[24px] md:tw-mb-[14px]">{{ $t("Sign Up") }}</h1>
  16. <p class="tw-body-3 tw-text-neutral-400 tw-mb-[16px] md:tw-mb-[12px]">
  17. {{ $t("Welcome to ShowEasy!") }}
  18. </p>
  19. <p class="tw-body-3 tw-mb-[45px] md:tw-mb-[32px]">
  20. {{ $t("Already have an account?") }}
  21. <nuxt-link :to="localePath('/user')" class="primary--text text-decoration-none">{{ $t("Login") }}</nuxt-link>
  22. </p>
  23. <div class="tw-grid tw-grid-cols-1 tw-gap-[10px] md:tw-gap-[12px]">
  24. <!-- <button @click="googleLogin"
  25. class="tw-flex tw-justify-center tw-items-center tw-w-full tw-py-[8px] tw-rounded-[16px] tw-border tw-border-solid tw-text-black tw-border-neutrals-200"><img
  26. width="24px" height="24px" src="~/assets/img/g-normal.png" class="mr-5" />{{ $t("Sign up with Google")
  27. }}</button>
  28. <button @click="facebookLogin"
  29. class="tw-flex tw-justify-center tw-items-center tw-w-full tw-py-[8px] tw-rounded-[16px] tw-border tw-border-solid tw-text-black tw-border-neutrals-200"><img
  30. width="20px" height="20px" src="~/assets/img/f_logo_RGB-Blue_72.png" class="mr-5" />
  31. {{ $t("Sign up with Facebook") }}
  32. </button> -->
  33. <button @click="emailSignUp = !emailSignUp"
  34. class="tw-flex tw-justify-center tw-items-center tw-w-full tw-py-[8px] tw-rounded-[16px] tw-border tw-border-solid tw-text-black tw-border-neutrals-200">
  35. <unicon name="envelope" width="20px" height="20px"
  36. class="tw-flex tw-justify-center tw-items-center tw-mr-[20px]">
  37. </unicon>{{ $t("Sign up with Email") }}
  38. </button>
  39. </div>
  40. </v-spacer>
  41. <v-spacer v-if="!emailSignUp">
  42. <p class="title">{{ $t("Sign up with Email") }}</p>
  43. <p class="neutrals--text text--darken-3 text-size-14">
  44. {{ $t("Welcome to ShowEasy!") }}
  45. </p>
  46. <v-form v-model="valid">
  47. <v-text-field v-model="user.FirstName" background-color="neutrals darken-1"
  48. :label="this.$t('First Name') + '*'" placeholder="" filled rounded dense single-line :rules="[rules.require]">
  49. </v-text-field>
  50. <v-text-field v-model="user.LastName" background-color="neutrals darken-1"
  51. :label="this.$t('Last Name') + '*'" placeholder="" filled rounded dense single-line :rules="[rules.require]">
  52. </v-text-field>
  53. <v-text-field v-model="user.Email" background-color="neutrals darken-1" :label="this.$t('Email') + '*'"
  54. filled rounded dense single-line :rules="[rules.email, rules.require]" validate-on-blur></v-text-field>
  55. <v-text-field v-model="user.Password" background-color="neutrals darken-1"
  56. :label="this.$t('Password') + '*'" :type="showPass ? 'text' : 'password'" placeholder="" filled rounded dense
  57. single-line :rules="[rules.checkPassword, rules.require]" :hint="
  58. this.$t(
  59. 'userProfile.passwordsHint'
  60. )
  61. " persistent-hint :append-icon="showPass ? 'mdi-eye' : 'mdi-eye-off'" @click:append="showPass = !showPass"
  62. validate-on-blur></v-text-field>
  63. <v-text-field v-model="confirmPasswordText" background-color="neutrals darken-1"
  64. :label="this.$t('Confirm Password') + '*'" :type="showConfirmPass ? 'text' : 'password'" placeholder="" filled
  65. rounded dense single-line :rules="[rules.checkConfirmPassword, rules.require]"
  66. :append-icon="showConfirmPass ? 'mdi-eye' : 'mdi-eye-off'" @click:append="showConfirmPass = !showConfirmPass"
  67. validate-on-blur></v-text-field>
  68. </v-form>
  69. <v-checkbox v-model="user.Subscribe" class="mt-n2 ml-1">
  70. <template v-slot:label>
  71. <span class="neutrals--text text--darken-4 text-size-14">
  72. {{ $t("Subscribe to ShowEasy\’s newsletter") }}
  73. </span>
  74. </template>
  75. </v-checkbox>
  76. <div class="md:tw-flex md:tw-justify-center md:tw-items-center">
  77. <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']">
  78. {{ $t("Sign Up") }}
  79. </button>
  80. </div>
  81. <!-- 原註冊流程Modal(信箱連結認證) -->
  82. <v-dialog v-model="dialog" :width="$vuetify.breakpoint.smAndUp ? 423 : 294"
  83. @click:outside="$router.push(localePath('/user'))">
  84. <v-card class="pa-7" :height="$vuetify.breakpoint.smAndUp ? 249 : 290">
  85. <v-spacer class="d-flex align-center text-size-20 neutrals--text text--darken-5">
  86. {{ $t("Verify your email") }}
  87. <v-spacer></v-spacer>
  88. <v-btn @click="$router.push(localePath('/user'))" icon>
  89. <v-icon> mdi-close </v-icon>
  90. </v-btn>
  91. </v-spacer>
  92. <v-spacer class="text-size-16 my-7 neutrals--text text--darken-4">{{ $t("We've sent a verification email to")
  93. }}<br />
  94. <span class="primary--text">{{ user.Email }}</span>{{
  95. $t(". Please click the link within to activate your account.")
  96. }}
  97. </v-spacer>
  98. <v-btn @click="resendVerifyEmail" class="primary no-text-transform" width="153px" rounded
  99. :disabled="countdown > 0">
  100. {{ $t("Resend") }}
  101. <span v-if="countdown > 0">
  102. {{ `(${this.countdown})` }}
  103. </span>
  104. </v-btn>
  105. </v-card>
  106. </v-dialog>
  107. <!-- 帳號已存在Modal -->
  108. <v-dialog v-model="errorDialog" :width="$vuetify.breakpoint.smAndUp ? 423 : 294">
  109. <v-card class="pa-7 border-radius-16" :max-height="$vuetify.breakpoint.smAndUp ? 249 : 290">
  110. <v-spacer class="d-flex align-center text-size-20 neutrals--text text--darken-5">
  111. {{ $t("Error") }}
  112. <v-spacer></v-spacer>
  113. <v-btn @click="errorDialog = !errorDialog" icon>
  114. <v-icon> mdi-close </v-icon>
  115. </v-btn>
  116. </v-spacer>
  117. <v-spacer class="text-size-16 my-7 neutrals--text text--darken-4">
  118. {{ $t("Same email has been created already.") }}
  119. </v-spacer>
  120. <v-spacer class="d-flex justify-center">
  121. <v-btn class="border-radius-16" color="primary" @click="errorDialog = !errorDialog">{{ $t("ok") }}</v-btn>
  122. </v-spacer>
  123. </v-card>
  124. </v-dialog>
  125. <p align="center" class="neutrals--text text--darken-3 text-size-14 mt-7">
  126. {{ $t("By signing up,") }}<br />
  127. {{ $t("you agree to the") }}
  128. <nuxt-link :to="localePath('/termsandconditions')" target="_blank" class="text-decoration-none">
  129. {{ $t("Terms & Conditions") }}</nuxt-link>
  130. {{ $t("and") }}
  131. <nuxt-link :to="localePath('/privacypolicy')" target="_blank" class="text-decoration-none">
  132. {{ $t("Privacy Policy") }}</nuxt-link>
  133. </p>
  134. <p align="center" class="neutrals--text text--darken-5 text-size-14">
  135. {{ $t("Already have an account?") }}
  136. <nuxt-link :to="localePath('/user')" class="primary--text text-decoration-none">{{ $t("Login") }}</nuxt-link>
  137. </p>
  138. </v-spacer>
  139. <loading :isLoading="isPageLoading"></loading>
  140. <VerifyCode @user-verifyCode="userVerifyCode" @resend-mail="resendVerifyEmail" :error="error" :account="user.Account"></VerifyCode>
  141. </div>
  142. </div>
  143. </div>
  144. </div>
  145. </template>
  146. <script>
  147. import loading from "@/components/newComponent/loading/loading.vue";
  148. import VerifyCode from "@/components/newcomponent/modal/VerifyCodeModal.vue";
  149. export default {
  150. name: "SignUp",
  151. layout: "login",
  152. auth: false,
  153. components: {
  154. loading,
  155. VerifyCode
  156. },
  157. data() {
  158. return {
  159. valid: false,
  160. showPass: false,
  161. showConfirmPass: false,
  162. emailSignUp: true,
  163. Subscribe: true,
  164. dialog: false,
  165. errorDialog: false,
  166. btnText: "Sign up",
  167. confirmPasswordText: "",
  168. countdown: 60,
  169. isPageLoading: false,
  170. rules: {
  171. require: (value) => !!value || this.$t("Required."),
  172. email: (v) =>
  173. /^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/.test(
  174. v
  175. ) || this.$t("Invalid email"),
  176. checkPassword: (v) =>
  177. (/(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])/.test(v) &&
  178. v.length >= 8 &&
  179. v.length <= 20) ||
  180. this.$t(
  181. "Passwords must be 8-20 characters with at least 1 number, 1 lower case letter and 1 upper case letter"
  182. ),
  183. checkConfirmPassword: (v) =>
  184. this.confirmPasswordText === this.user.Password ||
  185. this.$t("Your password and confirmation password do not match"),
  186. },
  187. user: {
  188. FirstName: "",
  189. LastName: "",
  190. Account: "",
  191. Password: "",
  192. Email: "",
  193. Subscribe: true,
  194. },
  195. signUp: false,
  196. userInfo: {},
  197. error: false,
  198. userData: {
  199. Account: '',
  200. Password: '',
  201. },
  202. };
  203. },
  204. watch: {
  205. signUp: {
  206. handler: function () {
  207. if (this.signUp == true) {
  208. this.$auth.$storage.removeUniversal("userPassword");
  209. this.$auth.$storage.removeUniversal("userAccount");
  210. }
  211. },
  212. },
  213. },
  214. methods: {
  215. //會員註冊
  216. userRegister() {
  217. const postUserData = { ...this.user };
  218. this.isPageLoading = true;
  219. this.$axios
  220. .post(
  221. `/trending/api/Signup/SignupWithEmail`, postUserData
  222. )
  223. .then((response) => {
  224. //console.log(JSON.stringify(response));
  225. if(response.data.STATUSCODE == "400"){
  226. this.errorDialog = true;
  227. this.isPageLoading = false;
  228. }
  229. if(response && response.data && response.data.DATA && response.data.DATA.rel){
  230. let data = response.data.DATA.rel
  231. if(data){
  232. this.userInfo = data;
  233. this.$modal.show('VerifyCode');
  234. this.signUp = true;
  235. this.isPageLoading = false;
  236. //this.dialog = !this.dialog; //原先的認證流程Modal
  237. }
  238. }
  239. })
  240. .catch((err) => {
  241. console.log(err);
  242. });
  243. },
  244. //重新寄出認證碼
  245. resendVerifyEmail() {
  246. this.countdown = 60;
  247. this.$axios
  248. .post(
  249. `/trending/api/Signup/ReSendVerifyMail?Email=${this.user.Email}`
  250. )
  251. .then((res) => {
  252. })
  253. .catch((err) => {
  254. console.log(err);
  255. });
  256. },
  257. //認證會員
  258. userVerifyCode(value){
  259. this.error = false;
  260. this.$axios
  261. .get(
  262. `/trending/api/Signup/VerifyAccount?OrgID=${this.userInfo.OrgID}&MemberID=${this.userInfo.MemberID}&Code=${value}`
  263. )
  264. .then((response) => {
  265. //console.log(response);
  266. if(response.data.STATUSCODE == 200){
  267. this.$modal.hide('VerifyCode');
  268. this.Login();
  269. }
  270. else{
  271. this.error = true;
  272. }
  273. })
  274. .catch((err) => {
  275. console.log(err);
  276. });
  277. },
  278. //登入
  279. async Login(){
  280. this.userData.Account = this.userInfo.Account;
  281. this.userData.Password = this.user.Password;
  282. const response = await this.$auth.loginWith('local', { data: this.userData });
  283. if(response.data.STATUSCODE == 200){
  284. let data = response.data.DATA;
  285. if(data.authtoken){
  286. const authtoken = data.authtoken;
  287. this.$auth.$storage.removeUniversal('authtoken');
  288. this.$auth.$storage.setUniversal('authtoken', authtoken);
  289. let path = this.$auth.$storage.getUniversal('userBeforePath');
  290. if(path == "/user"){
  291. path = "/";
  292. }
  293. this.$router.push({path: path});
  294. }
  295. }
  296. }
  297. },
  298. computed: {
  299. validFormat() {
  300. if (this.valid && this.user.Password === this.confirmPasswordText) {
  301. return true;
  302. } else {
  303. return false;
  304. }
  305. },
  306. },
  307. beforeUnmount() {
  308. clearInterval(this.timer);
  309. },
  310. };
  311. </script>
  312. <style lang="scss" scoped>
  313. #app {
  314. overflow-y: hidden;
  315. }
  316. .welcome {
  317. color: #f5cda8;
  318. font-family: Damion;
  319. font-size: 48px;
  320. margin-bottom: 0px;
  321. font-weight: 400;
  322. line-height: 66px;
  323. letter-spacing: 0.02em;
  324. }
  325. .sub {
  326. color: #9c9c9c;
  327. font-style: italic;
  328. font-weight: 400;
  329. font-size: 22px;
  330. line-height: 29px;
  331. letter-spacing: 0.02em;
  332. }
  333. :deep(.v-text-field.v-text-field--enclosed .v-text-field__details) {
  334. padding: 0;
  335. margin: 0;
  336. }
  337. :deep(.v-messages__message) {
  338. font-size: 14px;
  339. }
  340. $border-style: 1px solid #e5e5e5;
  341. .title {
  342. font-weight: 700;
  343. font-size: 26px;
  344. line-height: 34px;
  345. letter-spacing: 0.02em;
  346. color: #232323;
  347. }
  348. :deep(.v-text-field.v-text-field--enclosed .v-text-field__details) {
  349. margin-bottom: 0;
  350. padding: 0;
  351. .v-messages {
  352. color: #9c9c9c;
  353. display: none;
  354. }
  355. .v-messages.error--text {
  356. display: block;
  357. margin-top: 4px;
  358. margin-bottom: 16px;
  359. }
  360. }
  361. .btn-border {
  362. border: $border-style;
  363. }
  364. </style>