PasswordReset.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { ref } from 'vue'
  4. import { useRouter } from 'vue-router'
  5. import { NotificationTypes } from '#shared/components/CommonNotifications/types.ts'
  6. import { useNotifications } from '#shared/components/CommonNotifications/useNotifications.ts'
  7. import Form from '#shared/components/Form/Form.vue'
  8. import type {
  9. FormSchemaNode,
  10. FormSubmitData,
  11. } from '#shared/components/Form/types.ts'
  12. import { useForm } from '#shared/components/Form/useForm.ts'
  13. import UserError from '#shared/errors/UserError.ts'
  14. import { EnumPublicLinksScreen } from '#shared/graphql/types.ts'
  15. import MutationHandler from '#shared/server/apollo/handler/MutationHandler.ts'
  16. import { useApplicationStore } from '#shared/stores/application.ts'
  17. import CommonButton from '#desktop/components/CommonButton/CommonButton.vue'
  18. import CommonPublicLinks from '#desktop/components/CommonPublicLinks/CommonPublicLinks.vue'
  19. import LayoutPublicPage from '#desktop/components/layout/LayoutPublicPage/LayoutPublicPage.vue'
  20. import { useUserPasswordResetSendMutation } from '../graphql/mutations/userPasswordResetSend.api.ts'
  21. defineOptions({
  22. beforeRouteEnter(to) {
  23. const application = useApplicationStore()
  24. if (!application.config.user_lost_password) {
  25. return to.redirectedFrom ? false : '/'
  26. }
  27. return true
  28. },
  29. })
  30. const router = useRouter()
  31. interface FormValues {
  32. login: string
  33. }
  34. const formSchema: FormSchemaNode[] = [
  35. {
  36. type: 'text',
  37. label: __('Username / Email'),
  38. name: 'login',
  39. required: true,
  40. },
  41. ]
  42. const { form, isDisabled } = useForm()
  43. const showSuccessScreen = ref(false)
  44. const resetHandler = new MutationHandler(useUserPasswordResetSendMutation())
  45. const { notify } = useNotifications()
  46. const resetPassword = async (form: FormSubmitData<FormValues>) => {
  47. try {
  48. const result = await resetHandler.send({ username: form.login })
  49. if (result?.userPasswordResetSend?.success) {
  50. showSuccessScreen.value = true
  51. }
  52. } catch (error) {
  53. if (error instanceof UserError) {
  54. notify({
  55. id: 'password-reset',
  56. type: NotificationTypes.Error,
  57. message: error.generalErrors[0],
  58. })
  59. }
  60. }
  61. }
  62. const resetForm = () => {
  63. showSuccessScreen.value = false
  64. }
  65. const goToLogin = () => {
  66. router.replace('/login')
  67. }
  68. </script>
  69. <template>
  70. <LayoutPublicPage
  71. box-size="small"
  72. :title="
  73. showSuccessScreen
  74. ? __('The password reset request was successful.')
  75. : __('Forgot your password?')
  76. "
  77. >
  78. <Form
  79. v-if="!showSuccessScreen"
  80. id="password-reset"
  81. ref="form"
  82. form-class="mb-2.5"
  83. :schema="formSchema"
  84. @submit="resetPassword($event as FormSubmitData<FormValues>)"
  85. />
  86. <section v-else>
  87. <CommonLabel class="mb-5 text-center">
  88. {{ $t('Password reset instructions were sent to your email address.') }}
  89. </CommonLabel>
  90. <CommonLabel class="text-center">
  91. {{
  92. $t(
  93. "If you don't receive instructions within a minute or two, check your email's spam and junk filters, or try resending your request.",
  94. )
  95. }}
  96. </CommonLabel>
  97. </section>
  98. <template #boxActions>
  99. <CommonButton
  100. variant="secondary"
  101. size="medium"
  102. :disabled="isDisabled"
  103. @click="goToLogin()"
  104. >
  105. {{ $t('Cancel & Go Back') }}
  106. </CommonButton>
  107. <CommonButton
  108. v-if="!showSuccessScreen"
  109. type="submit"
  110. variant="submit"
  111. size="medium"
  112. form="password-reset"
  113. :disabled="isDisabled"
  114. >
  115. {{ $t('Submit') }}
  116. </CommonButton>
  117. <CommonButton v-else variant="submit" size="medium" @click="resetForm">
  118. {{ $t('Try again') }}
  119. </CommonButton>
  120. </template>
  121. <template #bottomContent>
  122. <CommonPublicLinks :screen="EnumPublicLinksScreen.PasswordReset" />
  123. </template>
  124. </LayoutPublicPage>
  125. </template>