@bagelink/auth 1.12.3 → 1.12.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/api.d.ts +54 -1
  2. package/dist/index.cjs +154 -1181
  3. package/dist/index.d.ts +0 -9
  4. package/dist/index.mjs +155 -1182
  5. package/dist/routes.d.ts +0 -36
  6. package/dist/types.d.ts +68 -1
  7. package/dist/useAuth.d.ts +17 -1
  8. package/package.json +1 -1
  9. package/src/api.ts +118 -0
  10. package/src/index.ts +0 -13
  11. package/src/routes.ts +0 -96
  12. package/src/types.ts +81 -1
  13. package/src/useAuth.ts +103 -0
  14. package/dist/Callback-BHqVaZZm.cjs +0 -4
  15. package/dist/Callback-C-XghN_z.js +0 -4
  16. package/dist/ForgotPasswordPage-BV9tyhHl.cjs +0 -4
  17. package/dist/ForgotPasswordPage-DvttMGb0.js +0 -4
  18. package/dist/LoginPage-hv1wc54S.cjs +0 -4
  19. package/dist/LoginPage-klj1NV4J.js +0 -4
  20. package/dist/ResetPasswordPage-COPrJmW8.cjs +0 -4
  21. package/dist/ResetPasswordPage-nvQ4uupb.js +0 -4
  22. package/dist/SignupPage-m36w9PLJ.cjs +0 -4
  23. package/dist/SignupPage-oUFYApYW.js +0 -4
  24. package/dist/components/auth/ForgotPasswordForm.vue.d.ts +0 -23
  25. package/dist/components/auth/LoginForm.vue.d.ts +0 -58
  26. package/dist/components/auth/ResetPasswordForm.vue.d.ts +0 -28
  27. package/dist/components/auth/SignupForm.vue.d.ts +0 -34
  28. package/dist/components/index.d.ts +0 -4
  29. package/dist/pages/Callback.vue.d.ts +0 -2
  30. package/dist/pages/ForgotPasswordPage.vue.d.ts +0 -13
  31. package/dist/pages/LoginPage.vue.d.ts +0 -38
  32. package/dist/pages/ResetPasswordPage.vue.d.ts +0 -13
  33. package/dist/pages/SignupPage.vue.d.ts +0 -16
  34. package/src/components/auth/ForgotPasswordForm.vue +0 -97
  35. package/src/components/auth/LoginForm.vue +0 -258
  36. package/src/components/auth/ResetPasswordForm.vue +0 -156
  37. package/src/components/auth/SignupForm.vue +0 -231
  38. package/src/components/index.ts +0 -5
  39. package/src/pages/Callback.vue +0 -196
  40. package/src/pages/ForgotPasswordPage.vue +0 -42
  41. package/src/pages/LoginPage.vue +0 -68
  42. package/src/pages/ResetPasswordPage.vue +0 -47
  43. package/src/pages/SignupPage.vue +0 -46
@@ -1,156 +0,0 @@
1
- <script lang="ts" setup>
2
- import { useAuth } from '@bagelink/auth'
3
- import { Btn, Icon, PasswordInput } from '@bagelink/vue'
4
- import { computed, ref } from 'vue'
5
-
6
- export interface ResetPasswordTexts {
7
- title?: string
8
- invalidLinkTitle?: string
9
- invalidLinkMessage?: string
10
- newPasswordLabel?: string
11
- confirmPasswordLabel?: string
12
- submitButton?: string
13
- backToLogin?: string
14
- passwordMismatchError?: string
15
- invalidTokenError?: string
16
- successTitle?: string
17
- successMessage?: string
18
- goToLogin?: string
19
- }
20
-
21
- interface Props {
22
- token?: string
23
- showSuccess?: boolean
24
- useHebrewDefaults?: boolean
25
- texts?: Partial<ResetPasswordTexts>
26
- }
27
-
28
- const props = withDefaults(defineProps<Props>(), {
29
- useHebrewDefaults: false
30
- })
31
- defineEmits<{
32
- switchForm: [form: string]
33
- }>()
34
-
35
- const { resetPassword } = useAuth()
36
-
37
- const error = ref<string>('')
38
- const internalSuccess = ref<boolean>(false)
39
- const newPassword = ref<string>('')
40
- const confirmPassword = ref<string>('')
41
-
42
- const isValidToken = computed(() => !!props.token)
43
- const isSuccess = computed(() => props.showSuccess || internalSuccess.value)
44
-
45
- // Text configuration with conditional defaults
46
- const texts = computed(() => {
47
- const hebrewDefaults = {
48
- title: 'איפוס סיסמה',
49
- invalidLinkTitle: 'קישור לא תקין',
50
- invalidLinkMessage: 'קישור איפוס הסיסמה לא תקין או פג תוקף',
51
- newPasswordLabel: 'סיסמה חדשה',
52
- confirmPasswordLabel: 'אימות סיסמה',
53
- submitButton: 'איפוס סיסמה',
54
- backToLogin: 'חזרה להתחברות',
55
- passwordMismatchError: 'הסיסמאות לא תואמות',
56
- invalidTokenError: 'אסימון לא תקין',
57
- successTitle: 'הסיסמה אופסה בהצלחה!',
58
- successMessage: 'הסיסמה שלכם אופסה. כעת תוכלו להתחברות עם הסיסמה החדשה.',
59
- goToLogin: 'מעבר להתחברות'
60
- }
61
-
62
- const englishDefaults = {
63
- title: 'Reset Password',
64
- invalidLinkTitle: 'Invalid Link',
65
- invalidLinkMessage: 'This reset link is invalid or has expired',
66
- newPasswordLabel: 'New Password',
67
- confirmPasswordLabel: 'Confirm Password',
68
- submitButton: 'Reset Password',
69
- backToLogin: 'Back to Login',
70
- passwordMismatchError: 'Passwords do not match',
71
- invalidTokenError: 'Invalid token',
72
- successTitle: 'Password Reset Successfully!',
73
- successMessage: 'Your password has been reset. You can now log in with your new password.',
74
- goToLogin: 'Go to Login'
75
- }
76
-
77
- const defaults = props.useHebrewDefaults ? hebrewDefaults : englishDefaults
78
-
79
- return {
80
- title: props.texts?.title ?? defaults.title,
81
- invalidLinkTitle: props.texts?.invalidLinkTitle ?? defaults.invalidLinkTitle,
82
- invalidLinkMessage: props.texts?.invalidLinkMessage ?? defaults.invalidLinkMessage,
83
- newPasswordLabel: props.texts?.newPasswordLabel ?? defaults.newPasswordLabel,
84
- confirmPasswordLabel: props.texts?.confirmPasswordLabel ?? defaults.confirmPasswordLabel,
85
- submitButton: props.texts?.submitButton ?? defaults.submitButton,
86
- backToLogin: props.texts?.backToLogin ?? defaults.backToLogin,
87
- passwordMismatchError: props.texts?.passwordMismatchError ?? defaults.passwordMismatchError,
88
- invalidTokenError: props.texts?.invalidTokenError ?? defaults.invalidTokenError,
89
- successTitle: props.texts?.successTitle ?? defaults.successTitle,
90
- successMessage: props.texts?.successMessage ?? defaults.successMessage,
91
- goToLogin: props.texts?.goToLogin ?? defaults.goToLogin
92
- }
93
- })
94
-
95
- const textDirection = computed(() => ({ 'auth-rtl': props.useHebrewDefaults }))
96
-
97
- async function handleResetPassword() {
98
- if (newPassword.value !== confirmPassword.value) {
99
- error.value = texts.value.passwordMismatchError
100
- return
101
- }
102
- if (!props.token) {
103
- error.value = texts.value.invalidTokenError
104
- return
105
- }
106
- try {
107
- await resetPassword(props.token, newPassword.value)
108
- internalSuccess.value = true
109
- error.value = ''
110
- } catch (err: unknown) {
111
- error.value = err instanceof Error ? err.message : 'Reset failed'
112
- }
113
- }
114
- </script>
115
-
116
- <template>
117
- <div v-if="!isValidToken" class="txt-center" :class="textDirection">
118
- <h1 class="txt20 bold mb-1">
119
- {{ texts.invalidLinkTitle }}
120
- </h1>
121
- <p class="opacity-7 mb-2">
122
- {{ texts.invalidLinkMessage }}
123
- </p>
124
- <Btn :value="texts.backToLogin" @click="$emit('switchForm', 'login')" />
125
- </div>
126
- <div v-else-if="isSuccess" class="txt-center" :class="textDirection">
127
- <Icon name="check_circle" size="4" class="txt-green mb-1" />
128
- <h1 class="txt20 bold mb-1">
129
- {{ texts.successTitle }}
130
- </h1>
131
- <p class="opacity-7 mb-2">
132
- {{ texts.successMessage }}
133
- </p>
134
- <Btn :value="texts.goToLogin" @click="$emit('switchForm', 'login')" />
135
- </div>
136
- <form v-else :class="textDirection" @submit.prevent="handleResetPassword">
137
- <h1 class="txt20 bold txt-center mb-1">
138
- {{ texts.title }}
139
- </h1>
140
- <PasswordInput
141
- v-model="newPassword" class="mb-05" :label="texts.newPasswordLabel"
142
- autocomplete="new-password"
143
- />
144
- <PasswordInput v-model="confirmPassword" :label="texts.confirmPasswordLabel" autocomplete="new-password" />
145
- <Btn type="submit" class="w-100 mt-2" :value="texts.submitButton" />
146
- <Btn
147
- thin flat class="txt-12 mt-075 underline block" :value="texts.backToLogin"
148
- @click="$emit('switchForm', 'login')"
149
- />
150
- <div class="h-20px pt-075">
151
- <p v-if="error" class="txt-center color-red txt-12">
152
- {{ error }}
153
- </p>
154
- </div>
155
- </form>
156
- </template>
@@ -1,231 +0,0 @@
1
- <script lang="ts" setup>
2
- import { useAuth } from '@bagelink/auth'
3
- import { Btn, PasswordInput, TextInput } from '@bagelink/vue'
4
- import { computed, ref } from 'vue'
5
-
6
- export interface SignupTexts {
7
- title?: string
8
- firstNameLabel?: string
9
- lastNameLabel?: string
10
- emailLabel?: string
11
- passwordLabel?: string
12
- confirmPasswordLabel?: string
13
- signupButton?: string
14
- alreadyHaveAccount?: string
15
- // Validation errors
16
- emailRequiredError?: string
17
- emailInvalidError?: string
18
- passwordRequiredError?: string
19
- passwordTooShortError?: string
20
- passwordMismatchError?: string
21
- firstNameRequiredError?: string
22
- lastNameRequiredError?: string
23
- }
24
-
25
- interface Props {
26
- showNames?: boolean
27
- useHebrewDefaults?: boolean
28
- errorState?: 'normal' | 'email-required' | 'email-invalid' | 'password-short' | 'password-mismatch' | 'name-required' | 'server-error'
29
- texts?: Partial<SignupTexts>
30
- }
31
-
32
- const props = withDefaults(defineProps<Props>(), {
33
- showNames: true,
34
- useHebrewDefaults: false,
35
- errorState: 'normal',
36
- texts: () => ({})
37
- })
38
-
39
- defineEmits<{
40
- switchForm: [form: string]
41
- }>()
42
-
43
- const { signup, login } = useAuth()
44
-
45
- // Internal error for actual validation
46
- const internalError = ref<string>('')
47
-
48
- // Use computed for error that reacts to errorState changes
49
- const error = computed(() => {
50
- if (props.errorState !== 'normal') {
51
- return getDevError()
52
- }
53
- return internalError.value
54
- })
55
-
56
- const form = ref({
57
- email: '',
58
- password: '',
59
- confirmPassword: '',
60
- first_name: '',
61
- last_name: '',
62
- })
63
-
64
- // Text configuration with conditional defaults
65
- const texts = computed(() => {
66
- const hebrewDefaults = {
67
- title: 'יצירת חשבון',
68
- firstNameLabel: 'שם פרטי',
69
- lastNameLabel: 'שם משפחה',
70
- emailLabel: 'איימיל',
71
- passwordLabel: 'סיסמה',
72
- confirmPasswordLabel: 'אימות סיסמה',
73
- signupButton: 'יצירת חשבון',
74
- alreadyHaveAccount: 'יש לך כבר חשבון?',
75
- // Validation errors
76
- emailRequiredError: 'איימיל נדרש',
77
- emailInvalidError: 'יש להזין כתובת איימיל תקינה',
78
- passwordRequiredError: 'סיסמה נדרשת',
79
- passwordTooShortError: 'הסיסמה חייבת להיות לפחות 8 תווים',
80
- passwordMismatchError: 'הסיסמאות לא תואמות',
81
- firstNameRequiredError: 'שם פרטי נדרש',
82
- lastNameRequiredError: 'שם משפחה נדרש'
83
- }
84
-
85
- const englishDefaults = {
86
- title: 'Create Account',
87
- firstNameLabel: 'First Name',
88
- lastNameLabel: 'Last Name',
89
- emailLabel: 'Email',
90
- passwordLabel: 'Password',
91
- confirmPasswordLabel: 'Confirm Password',
92
- signupButton: 'Create Account',
93
- alreadyHaveAccount: 'Already have an account?',
94
- // Validation errors
95
- emailRequiredError: 'Email is required',
96
- emailInvalidError: 'Please enter a valid email address',
97
- passwordRequiredError: 'Password is required',
98
- passwordTooShortError: 'Password must be at least 8 characters',
99
- passwordMismatchError: 'Passwords do not match',
100
- firstNameRequiredError: 'First name is required',
101
- lastNameRequiredError: 'Last name is required'
102
- }
103
-
104
- const defaults = props.useHebrewDefaults ? hebrewDefaults : englishDefaults
105
-
106
- return {
107
- title: props.texts.title || defaults.title,
108
- firstNameLabel: props.texts.firstNameLabel || defaults.firstNameLabel,
109
- lastNameLabel: props.texts.lastNameLabel || defaults.lastNameLabel,
110
- emailLabel: props.texts.emailLabel || defaults.emailLabel,
111
- passwordLabel: props.texts.passwordLabel || defaults.passwordLabel,
112
- confirmPasswordLabel: props.texts.confirmPasswordLabel || defaults.confirmPasswordLabel,
113
- signupButton: props.texts.signupButton || defaults.signupButton,
114
- alreadyHaveAccount: props.texts.alreadyHaveAccount || defaults.alreadyHaveAccount,
115
- // Validation errors
116
- emailRequiredError: props.texts.emailRequiredError || defaults.emailRequiredError,
117
- emailInvalidError: props.texts.emailInvalidError || defaults.emailInvalidError,
118
- passwordRequiredError: props.texts.passwordRequiredError || defaults.passwordRequiredError,
119
- passwordTooShortError: props.texts.passwordTooShortError || defaults.passwordTooShortError,
120
- passwordMismatchError: props.texts.passwordMismatchError || defaults.passwordMismatchError,
121
- firstNameRequiredError: props.texts.firstNameRequiredError || defaults.firstNameRequiredError,
122
- lastNameRequiredError: props.texts.lastNameRequiredError || defaults.lastNameRequiredError
123
- }
124
- })
125
-
126
- const textDirection = computed(() => ({ 'auth-rtl': props.useHebrewDefaults }))
127
-
128
- function getDevError() {
129
- switch (props.errorState) {
130
- case 'email-required': return texts.value.emailRequiredError
131
- case 'email-invalid': return texts.value.emailInvalidError
132
- case 'password-short': return texts.value.passwordTooShortError
133
- case 'password-mismatch': return texts.value.passwordMismatchError
134
- case 'name-required': return props.showNames ? texts.value.firstNameRequiredError : null
135
- case 'server-error': return props.useHebrewDefaults ? 'כתובת האימייל כבר קיימת או שגיאת שרת' : 'Email already exists or server error'
136
- default: return null
137
- }
138
- }
139
-
140
- function validateForm() {
141
- // Email validation
142
- if (!form.value.email.trim()) {
143
- return texts.value.emailRequiredError
144
- }
145
- const emailRegex = /^[^\s@]+@[^\s@][^\s.@]*\.[^\s@]+$/
146
- if (!emailRegex.test(form.value.email)) {
147
- return texts.value.emailInvalidError
148
- }
149
-
150
- // Password validation
151
- if (!form.value.password) {
152
- return texts.value.passwordRequiredError
153
- }
154
- if (form.value.password.length < 8) {
155
- return texts.value.passwordTooShortError
156
- }
157
- if (form.value.password !== form.value.confirmPassword) {
158
- return texts.value.passwordMismatchError
159
- }
160
-
161
- // Name validation (only if names are shown)
162
- if (props.showNames) {
163
- if (!form.value.first_name.trim()) {
164
- return texts.value.firstNameRequiredError
165
- }
166
- if (!form.value.last_name.trim()) {
167
- return texts.value.lastNameRequiredError
168
- }
169
- }
170
-
171
- return null
172
- }
173
-
174
- async function handleSignup() {
175
- // Don't process if we're showing a development error
176
- if (props.errorState !== 'normal') {
177
- return
178
- }
179
-
180
- // Clear previous errors
181
- internalError.value = ''
182
-
183
- // Validate form first
184
- const validationError = validateForm()
185
- if (validationError) {
186
- internalError.value = validationError
187
- return
188
- }
189
- const { message, success } = await signup(form.value).catch((error) => {
190
- console.error(error)
191
- // Handle specific server errors
192
- const errorMessage = error.response?.data?.detail as string
193
- if (errorMessage?.toLowerCase().includes('email')) {
194
- return { success: false, message: 'Email already exists or invalid' }
195
- }
196
- if (errorMessage?.toLowerCase().includes('password')) {
197
- return { success: false, message: 'Password does not meet requirements' }
198
- }
199
- return { success: false, message: errorMessage || 'Registration failed. Please try again.' }
200
- })
201
- if (!success) {
202
- internalError.value = message as string
203
- return
204
- }
205
- await login({ email: form.value.email, password: form.value.password })
206
- }
207
- </script>
208
-
209
- <template>
210
- <form :class="textDirection" @submit.prevent="handleSignup">
211
- <h1 class="txt20 bold txt-center mb-1">
212
- {{ texts.title }}
213
- </h1>
214
-
215
- <TextInput v-if="props.showNames" v-model="form.first_name" :label="texts.firstNameLabel" />
216
- <TextInput v-if="props.showNames" v-model="form.last_name" :label="texts.lastNameLabel" />
217
- <TextInput v-model="form.email" type="email" :label="texts.emailLabel" autocomplete="username" />
218
- <PasswordInput v-model="form.password" class="mb-05" :label="texts.passwordLabel" />
219
- <PasswordInput v-model="form.confirmPassword" :label="texts.confirmPasswordLabel" />
220
- <Btn class="w-100 mt-2" :value="texts.signupButton" type="submit" />
221
- <Btn
222
- thin flat class="txt-12 mt-075 underline block" :value="texts.alreadyHaveAccount"
223
- @click="$emit('switchForm', 'login')"
224
- />
225
- <div class="h-20px pt-075">
226
- <p v-if="error" class="txt-center color-red txt-12">
227
- {{ error }}
228
- </p>
229
- </div>
230
- </form>
231
- </template>
@@ -1,5 +0,0 @@
1
- // Export form components
2
- export { default as ForgotPasswordForm } from './auth/ForgotPasswordForm.vue'
3
- export { default as LoginForm } from './auth/LoginForm.vue'
4
- export { default as ResetPasswordForm } from './auth/ResetPasswordForm.vue'
5
- export { default as SignupForm } from './auth/SignupForm.vue'
@@ -1,196 +0,0 @@
1
- <script setup lang="ts">
2
- import type { AuthenticationResponse, SSOProvider } from '@bagelink/auth'
3
- import { useAuth } from '@bagelink/auth'
4
- import { Btn, Card, Icon, Loading } from '@bagelink/vue'
5
- import { computed, onMounted, ref } from 'vue'
6
- import { useRoute, useRouter } from 'vue-router'
7
-
8
- import { providers } from '../constants'
9
-
10
- const isLoading = ref(true)
11
- const error = ref<string | null>(null)
12
- const success = ref(false)
13
- const isLinking = ref(false)
14
- const provider = ref<SSOProvider | null>(null)
15
- const authResponse = ref<AuthenticationResponse | null>(null)
16
-
17
- const { sso, user, accountInfo } = useAuth()
18
- const route = useRoute()
19
- const router = useRouter()
20
- const timeout = 4000
21
- // Get provider info for better UI
22
- const providerInfo = computed(() => {
23
- if (provider.value === null) return null
24
- return providers[provider.value]
25
- })
26
-
27
- async function linkCallback() {
28
- isLinking.value = true
29
- const { redirect } = route.query
30
- try {
31
- await sso.handleLinkCallback()
32
- success.value = true
33
- setTimeout(() => {
34
- const redirectPath = typeof redirect === 'string' ? redirect : '/'
35
- router.push(redirectPath)
36
- }, timeout)
37
- } catch (err: unknown) {
38
- const errorMessage = err instanceof Error ? err.message : 'Failed to link account'
39
- error.value = errorMessage
40
- } finally {
41
- isLoading.value = false
42
- }
43
- }
44
-
45
- async function handleCallback() {
46
- const { state, redirect } = route.query
47
- provider.value = sessionStorage.getItem(`oauth_provider:${state}`) as SSOProvider
48
- console.log('[Callback] Query params:', { state, redirect })
49
- console.log('[Callback] Full route query:', route.query)
50
-
51
- try {
52
- const response = await sso.handleCallback()
53
- if (response === null) {
54
- error.value = `Failed to authenticate with ${providerInfo.value?.name ?? 'provider'}`
55
- } else {
56
- authResponse.value = response
57
- success.value = true
58
- console.log('[Callback] Login successful, redirect param:', redirect)
59
- // Auto-redirect will handle navigation, but fallback to manual redirect
60
- // if auto-redirect is disabled or router not connected
61
- setTimeout(() => {
62
- const redirectPath = typeof redirect === 'string' ? redirect : '/'
63
- console.log('[Callback] Manual fallback redirecting to:', redirectPath)
64
- router.push(redirectPath)
65
- }, timeout)
66
- }
67
- } catch (err: unknown) {
68
- const errorMessage = err instanceof Error ? err.message : 'Authentication failed'
69
- error.value = errorMessage
70
- } finally {
71
- isLoading.value = false
72
- }
73
- }
74
-
75
- onMounted(async () => {
76
- if (user.value) {
77
- await linkCallback()
78
- } else {
79
- await handleCallback()
80
- }
81
- })
82
- </script>
83
-
84
- <template>
85
- <div class="flex justify-content-center align-items-center vh-100 px-1">
86
- <Card class="p-2 txt-center w450px shadow">
87
- <!-- Loading State -->
88
- <div v-if="isLoading" class="flex column align-items-center gap-1">
89
- <Loading />
90
- <div class="mt-1">
91
- <h2 class="mb-05 pb-0 mt-0 txt24 m_txt20">
92
- {{ isLinking ? 'Linking Account' : 'Authenticating' }}
93
- </h2>
94
- <p class="opacity-7 txt-14">
95
- Please wait while we {{ isLinking ? 'link your' : 'complete the' }} {{ providerInfo?.name
96
- || 'OAuth' }} {{ isLinking ? 'account' : 'authentication' }}.
97
- </p>
98
- </div>
99
- </div>
100
-
101
- <!-- Success State -->
102
- <div v-else-if="success && !error" class="flex column align-items-center gap-1">
103
- <div class="flex justify-content-center align-items-center mb-1">
104
- <div class="relative">
105
- <Icon name="check_circle" size="5" class="txt-green line-height-1" />
106
- <div
107
- v-if="providerInfo"
108
- class="absolute flex justify-content-center align-items-center bg-white rounded"
109
- style="bottom: -8px; right: -8px; width: 40px; height: 40px; border: 3px solid white;"
110
- >
111
- <Icon :name="providerInfo.icon" size="1.5" :style="{ color: providerInfo.color }" />
112
- </div>
113
- </div>
114
- </div>
115
-
116
- <div>
117
- <h2 class="mb-05 pb-0 mt-0 txt24 m_txt20">
118
- {{ isLinking ? 'Account Linked!' : 'Welcome Back!' }}
119
- </h2>
120
- <p class="opacity-7 txt-14 mb-1">
121
- {{ isLinking
122
- ? `Successfully linked your ${providerInfo?.name || 'account'}.`
123
- : `You've successfully signed in with ${providerInfo?.name || 'your account'}.`
124
- }}
125
- </p>
126
-
127
- <!-- Show user info if available -->
128
- <div v-if="user || accountInfo" class="bg-gray-light rounded p-1 mt-1">
129
- <div class="flex column gap-05">
130
- <div v-if="user?.name" class="flex align-items-center gap-05 justify-content-center">
131
- <Icon name="person" size="1.2" class="opacity-7" />
132
- <span class="txt-14 bold">{{ user.name }}</span>
133
- </div>
134
- <div v-if="user?.email" class="flex align-items-center gap-05 justify-content-center">
135
- <Icon name="email" size="1.2" class="opacity-7" />
136
- <span class="txt-14 opacity-7">{{ user.email }}</span>
137
- </div>
138
- <div
139
- v-if="accountInfo?.authentication_methods"
140
- class="flex gap-05 justify-content-center mt-05"
141
- >
142
- <Icon
143
- v-for="method in accountInfo.authentication_methods" :key="method.id"
144
- :name="method.type === 'sso' ? (method.provider || 'link') : 'password'" size="1.2"
145
- class="opacity-5"
146
- />
147
- </div>
148
- </div>
149
- </div>
150
-
151
- <p class="txt-12 opacity-5 mt-1">
152
- Redirecting you to home...
153
- </p>
154
- </div>
155
- </div>
156
-
157
- <!-- Error State -->
158
- <div v-else-if="error" class="flex column align-items-center gap-1">
159
- <Icon name="error" size="5" class="txt-red mb-1 line-height-1" />
160
- <div>
161
- <h2 class="mb-05 pb-0 mt-0 txt24 m_txt20">
162
- Authentication Failed
163
- </h2>
164
- <p class="opacity-7 txt-14 mb-1">
165
- {{ error }}
166
- </p>
167
-
168
- <div class="bg-red-light rounded p-1 mt-1 mb-1">
169
- <p class="txt-12 opacity-7">
170
- This could happen if:
171
- </p>
172
- <ul class="txt-12 opacity-7 txt-start mt-05" style="list-style: none; padding-left: 0;">
173
- <li class="mb-025">
174
- • The authorization was cancelled
175
- </li>
176
- <li class="mb-025">
177
- • The state parameter was invalid
178
- </li>
179
- <li class="mb-025">
180
- • The OAuth provider denied access
181
- </li>
182
- <li class="mb-025">
183
- • Network connectivity issues
184
- </li>
185
- </ul>
186
- </div>
187
-
188
- <div class="flex gap-05 justify-content-center">
189
- <Btn outline value="Try Again" to="/login" />
190
- <Btn value="Go Home" to="/" />
191
- </div>
192
- </div>
193
- </div>
194
- </Card>
195
- </div>
196
- </template>
@@ -1,42 +0,0 @@
1
- <script setup lang="ts">
2
- import type { ForgotPasswordTexts } from '../components/auth/ForgotPasswordForm.vue'
3
- import { Card } from '@bagelink/vue'
4
- import { useRouter } from 'vue-router'
5
- import ForgotPasswordForm from '../components/auth/ForgotPasswordForm.vue'
6
-
7
- interface Props {
8
- /** Custom texts for the forgot password form */
9
- texts?: Partial<ForgotPasswordTexts>
10
- /** Card styling */
11
- cardWidth?: string
12
- cardShadow?: boolean
13
- }
14
-
15
- const props = withDefaults(defineProps<Props>(), {
16
- cardWidth: '450px',
17
- cardShadow: true
18
- })
19
-
20
- const router = useRouter()
21
-
22
- function switchForm(form: string) {
23
- if (form === 'login') {
24
- router.push('/login')
25
- }
26
- }
27
- </script>
28
-
29
- <template>
30
- <div class="flex justify-content-center align-items-center min-vh-100 px-1 py-2">
31
- <Card
32
- :class="{ shadow: cardShadow }"
33
- :style="{ width: cardWidth, maxWidth: '100%' }"
34
- class="p-2"
35
- >
36
- <ForgotPasswordForm
37
- :texts="texts"
38
- @switch-form="switchForm"
39
- />
40
- </Card>
41
- </div>
42
- </template>