39 lines
2.1 KiB
Vue
39 lines
2.1 KiB
Vue
<script setup lang="ts">
|
|
const route = useRoute()
|
|
const { session, restore } = useDngAuth()
|
|
const { api } = useDngApi()
|
|
const state = ref<'joining' | 'signin' | 'error'>('joining')
|
|
const message = ref('')
|
|
|
|
onMounted(async () => {
|
|
const token = String(route.params.token ?? '')
|
|
await restore()
|
|
if (!session.value) {
|
|
localStorage.setItem('dng-post-auth-redirect', route.fullPath)
|
|
state.value = 'signin'
|
|
return
|
|
}
|
|
try {
|
|
const result = await api<{ campaignId: string }>('/api/v1/invites/join', { method: 'POST', body: { token } })
|
|
await navigateTo(`/campaign/${result.campaignId}`, { replace: true })
|
|
} catch (cause) {
|
|
const error = cause as { data?: { statusMessage?: string }; message?: string }
|
|
message.value = error.data?.statusMessage ?? error.message ?? 'This invite is invalid or expired.'
|
|
state.value = 'error'
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="join noise">
|
|
<AppMark />
|
|
<div v-if="state === 'joining'" class="card"><small>PARTY INVITE</small><h1>JOINING CAMPAIGN…</h1><p>Verifying your seat at the table.</p></div>
|
|
<div v-else-if="state === 'signin'" class="card"><small>PARTY INVITE</small><h1>ENTER THE ALPHA FIRST</h1><p>Your invite is saved. Guest access needs no email; after entering, this campaign will open automatically.</p><NuxtLink to="/">ENTER THE ALPHA →</NuxtLink></div>
|
|
<div v-else class="card"><small>INVITE ERROR</small><h1>THE DOOR STAYED SHUT</h1><p>{{ message }}</p><NuxtLink to="/dashboard">BACK TO DASHBOARD</NuxtLink></div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.join{min-height:100vh;display:grid;place-content:center;justify-items:center;gap:30px;padding:24px}.card{width:min(560px,calc(100vw - 40px));padding:42px;border:1px solid var(--line);background:#0d0d0c}.card small{font:600 8px var(--mono);letter-spacing:.16em;color:var(--acid)}.card h1{font:600 clamp(26px,5vw,45px)/1.05 var(--display);letter-spacing:-.05em}.card p{color:var(--muted);line-height:1.7}.card a{display:inline-flex;margin-top:20px;padding:15px 18px;background:var(--acid);color:#080808;text-decoration:none;font:600 9px var(--mono)}
|
|
</style>
|