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.

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