149 lines
3.8 KiB
Vue
149 lines
3.8 KiB
Vue
<script setup lang="ts">
|
|
import { computed, onMounted, ref } from 'vue'
|
|
import { useRouter } from 'vue-router'
|
|
import { useOverlay, useToast } from '@nuxt/ui/composables'
|
|
import AuthShell from '@/components/AuthShell.vue'
|
|
import ConfirmDialog from '@/components/ConfirmDialog.vue'
|
|
import ResultPanel from '@/components/ResultPanel.vue'
|
|
import { ApiError, useApi } from '@/composables/useApi'
|
|
import { registrationCancelledToast } from '@/lib/registrationToasts'
|
|
import { VERIFIED_REDIRECT_DELAY_MS, wait } from '@/lib/verifiedRedirect'
|
|
import { useSessionStore } from '@/stores/session'
|
|
|
|
const router = useRouter()
|
|
const api = useApi()
|
|
const session = useSessionStore()
|
|
const overlay = useOverlay()
|
|
const toast = useToast()
|
|
|
|
const pendingEmail = ref<string | null>(null)
|
|
const loggingOut = ref(false)
|
|
const cancelOutcome = ref<'cancelled' | 'alreadyVerified' | null>(null)
|
|
const verified = ref(false)
|
|
|
|
onMounted(() => {
|
|
pendingEmail.value = sessionStorage.getItem('renewcms:pendingEmail')
|
|
document.title = 'Check your email · RenewCMS'
|
|
})
|
|
|
|
const description = computed(() =>
|
|
pendingEmail.value
|
|
? `We sent a verification link to ${pendingEmail.value}. It expires in 2 hours.`
|
|
: 'We sent a verification link to the email you registered with. It expires in 2 hours.',
|
|
)
|
|
|
|
async function logOut() {
|
|
loggingOut.value = true
|
|
try {
|
|
await api.request('/v1/auth/logout', { method: 'POST' })
|
|
} finally {
|
|
loggingOut.value = false
|
|
}
|
|
session.clear()
|
|
await router.push('/login')
|
|
}
|
|
|
|
async function deleteRegistration() {
|
|
try {
|
|
await api.request('/v1/auth/register', {
|
|
method: 'DELETE',
|
|
onForbidden: 'passthrough',
|
|
})
|
|
cancelOutcome.value = 'cancelled'
|
|
} catch (error) {
|
|
if (error instanceof ApiError && error.status === 403) {
|
|
await session.retry()
|
|
cancelOutcome.value = 'alreadyVerified'
|
|
return
|
|
}
|
|
throw new Error(
|
|
"Couldn't cancel registration, so it's still pending. Try again in a moment.",
|
|
)
|
|
}
|
|
}
|
|
|
|
async function cancelRegistration() {
|
|
cancelOutcome.value = null
|
|
const confirmed = await overlay
|
|
.create(ConfirmDialog, {
|
|
props: {
|
|
title: 'Cancel your registration?',
|
|
description:
|
|
'Your account will be deleted. You can register again with the same or a different email.',
|
|
confirmLabel: 'Cancel registration',
|
|
cancelLabel: 'Keep my account',
|
|
pendingLabel: 'Cancelling…',
|
|
tone: 'danger',
|
|
action: deleteRegistration,
|
|
},
|
|
})
|
|
.open()
|
|
|
|
if (!confirmed) {
|
|
return
|
|
}
|
|
|
|
if (cancelOutcome.value === 'cancelled') {
|
|
await router.push('/register')
|
|
toast.add(registrationCancelledToast)
|
|
return
|
|
}
|
|
|
|
if (cancelOutcome.value === 'alreadyVerified') {
|
|
verified.value = true
|
|
toast.add({
|
|
color: 'info',
|
|
icon: 'i-lucide-info',
|
|
title: 'Your account is already verified',
|
|
description: "There's nothing to cancel.",
|
|
})
|
|
await wait(VERIFIED_REDIRECT_DELAY_MS)
|
|
await router.push('/home')
|
|
}
|
|
}
|
|
|
|
const actions = computed(() => [
|
|
{
|
|
label: 'Log out',
|
|
color: 'neutral' as const,
|
|
variant: 'outline' as const,
|
|
disabled: loggingOut.value,
|
|
onClick: logOut,
|
|
},
|
|
{
|
|
label: 'Cancel registration',
|
|
color: 'neutral' as const,
|
|
variant: 'outline' as const,
|
|
disabled: loggingOut.value,
|
|
onClick: cancelRegistration,
|
|
},
|
|
])
|
|
</script>
|
|
|
|
<template>
|
|
<AuthShell title="">
|
|
<ResultPanel
|
|
v-if="verified"
|
|
tone="success"
|
|
icon="i-lucide-shield-check"
|
|
title="You're verified"
|
|
description="Taking you to your dashboard…"
|
|
:actions="[]"
|
|
/>
|
|
<ResultPanel
|
|
v-else
|
|
tone="success"
|
|
icon="i-lucide-mail-check"
|
|
title="Check your email"
|
|
:description="description"
|
|
:actions="actions"
|
|
>
|
|
<p class="text-sm text-pretty text-muted">
|
|
Opened it on another device? That works too; you'll log in there first. Can't find
|
|
it? Check your spam folder. If the link has expired, cancel your registration and
|
|
start again.
|
|
</p>
|
|
</ResultPanel>
|
|
</AuthShell>
|
|
</template>
|