Login.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <script setup lang="ts">
  2. import { defineAsyncComponent, ref } from "vue";
  3. import Toast from "toasters";
  4. import { storeToRefs } from "pinia";
  5. import { useConfigStore } from "@/stores/config";
  6. import { useUserAuthStore } from "@/stores/userAuth";
  7. import { useModalsStore } from "@/stores/modals";
  8. const Modal = defineAsyncComponent(() => import("@/components/Modal.vue"));
  9. const email = ref("");
  10. const password = ref({
  11. value: "",
  12. visible: false
  13. });
  14. const passwordElement = ref();
  15. const configStore = useConfigStore();
  16. const { registrationDisabled } = storeToRefs(configStore);
  17. const { login } = useUserAuthStore();
  18. const { openModal, closeCurrentModal } = useModalsStore();
  19. const submitModal = () => {
  20. if (!email.value || !password.value.value) return;
  21. login({
  22. email: email.value,
  23. password: password.value.value
  24. })
  25. .then((res: any) => {
  26. if (res.status === "success") window.location.reload();
  27. })
  28. .catch(err => new Toast(err.message));
  29. };
  30. const checkForAutofill = (type, event) => {
  31. if (
  32. event.target.value !== "" &&
  33. event.inputType === undefined &&
  34. event.data === undefined &&
  35. event.dataTransfer === undefined &&
  36. event.isComposing === undefined
  37. )
  38. submitModal();
  39. };
  40. const togglePasswordVisibility = () => {
  41. if (passwordElement.value.type === "password") {
  42. passwordElement.value.type = "text";
  43. password.value.visible = true;
  44. } else {
  45. passwordElement.value.type = "password";
  46. password.value.visible = false;
  47. }
  48. };
  49. const changeToRegisterModal = () => {
  50. closeCurrentModal();
  51. openModal("register");
  52. };
  53. </script>
  54. <template>
  55. <div>
  56. <modal
  57. title="Login"
  58. class="login-modal"
  59. :size="'slim'"
  60. @closed="closeCurrentModal()"
  61. >
  62. <template #body>
  63. <form>
  64. <!-- email address -->
  65. <p class="control">
  66. <label class="label">Username/Email</label>
  67. <input
  68. v-model="email"
  69. class="input"
  70. type="email"
  71. autocomplete="username"
  72. placeholder="Username/Email..."
  73. @input="checkForAutofill('email', $event)"
  74. @keyup.enter="submitModal()"
  75. />
  76. </p>
  77. <!-- password -->
  78. <p class="control">
  79. <label class="label">Password</label>
  80. </p>
  81. <div id="password-visibility-container">
  82. <input
  83. v-model="password.value"
  84. class="input"
  85. type="password"
  86. autocomplete="current-password"
  87. ref="passwordElement"
  88. placeholder="Password..."
  89. @input="checkForAutofill('password', $event)"
  90. @keyup.enter="submitModal()"
  91. />
  92. <a @click="togglePasswordVisibility()">
  93. <i class="material-icons">
  94. {{
  95. !password.visible
  96. ? "visibility"
  97. : "visibility_off"
  98. }}
  99. </i>
  100. </a>
  101. </div>
  102. <p
  103. v-if="configStore.mailEnabled"
  104. class="content-box-optional-helper"
  105. >
  106. <router-link
  107. id="forgot-password"
  108. to="/reset_password"
  109. @click="closeCurrentModal()"
  110. >
  111. Forgot password?
  112. </router-link>
  113. </p>
  114. <br />
  115. <p>
  116. By logging in you agree to our
  117. <router-link to="/terms" @click="closeCurrentModal()">
  118. Terms of Service
  119. </router-link>
  120. and
  121. <router-link to="/privacy" @click="closeCurrentModal()">
  122. Privacy Policy</router-link
  123. >.
  124. </p>
  125. </form>
  126. </template>
  127. <template #footer>
  128. <div id="actions">
  129. <button class="button is-primary" @click="submitModal()">
  130. Login
  131. </button>
  132. </div>
  133. <p
  134. v-if="!registrationDisabled"
  135. class="content-box-optional-helper"
  136. >
  137. <a @click="changeToRegisterModal()">
  138. Don't have an account?
  139. </a>
  140. </p>
  141. </template>
  142. </modal>
  143. </div>
  144. </template>
  145. <style lang="less" scoped>
  146. .night-mode {
  147. .modal-card,
  148. .modal-card-head,
  149. .modal-card-body,
  150. .modal-card-foot {
  151. background-color: var(--dark-grey-3);
  152. }
  153. .label,
  154. p:not(.help) {
  155. color: var(--light-grey-2);
  156. }
  157. }
  158. .modal-card-foot {
  159. display: flex;
  160. justify-content: space-between;
  161. flex-wrap: wrap;
  162. .content-box-optional-helper {
  163. margin-top: 0;
  164. }
  165. }
  166. .is-primary:focus {
  167. background-color: var(--primary-color) !important;
  168. }
  169. .invert {
  170. filter: brightness(5);
  171. }
  172. </style>