mirror of
https://github.com/koel/koel
synced 2024-12-22 10:33:16 +00:00
134 lines
3.1 KiB
Vue
134 lines
3.1 KiB
Vue
<template>
|
|
<div class="invitation-wrapper">
|
|
<form v-if="userProspect" autocomplete="off" @submit.prevent="submit">
|
|
<header>
|
|
Welcome to Koel! To accept the invitation, fill in the form below and click that button.
|
|
</header>
|
|
|
|
<div class="form-row">
|
|
<label>
|
|
Your email
|
|
<input type="text" :value="userProspect.email" disabled>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<label>
|
|
Your name
|
|
<input
|
|
v-model="name"
|
|
v-koel-focus
|
|
data-testid="name"
|
|
placeholder="Erm… Bruce Dickinson?"
|
|
required
|
|
type="text"
|
|
>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<label>
|
|
Password
|
|
<PasswordField v-model="password" data-testid="password" required />
|
|
<small>Min. 10 characters. Should be a mix of characters, numbers, and symbols.</small>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<Btn type="submit" :disabled="loading">Accept & Log In</Btn>
|
|
</div>
|
|
</form>
|
|
|
|
<p v-if="!validToken">Invalid or expired invite.</p>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { onMounted, ref } from 'vue'
|
|
import { invitationService } from '@/services'
|
|
import { useDialogBox, useRouter } from '@/composables'
|
|
|
|
import Btn from '@/components/ui/Btn.vue'
|
|
import PasswordField from '@/components/ui/PasswordField.vue'
|
|
|
|
import { parseValidationError } from '@/utils'
|
|
|
|
const { showErrorDialog } = useDialogBox()
|
|
const { getRouteParam, go } = useRouter()
|
|
|
|
const name = ref('')
|
|
const password = ref('')
|
|
const userProspect = ref<User>()
|
|
const validToken = ref(true)
|
|
const loading = ref(false)
|
|
|
|
const token = String(getRouteParam('token')!)
|
|
|
|
const submit = async () => {
|
|
try {
|
|
loading.value = true
|
|
await invitationService.accept(token, name.value, password.value)
|
|
window.location.href = '/'
|
|
} catch (err: any) {
|
|
const msg = err.response.status === 422 ? parseValidationError(err.response.data)[0] : 'Unknown error.'
|
|
showErrorDialog(msg, 'Error')
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
onMounted(async () => {
|
|
try {
|
|
userProspect.value = await invitationService.getUserProspect(token)
|
|
} catch (err: any) {
|
|
if (err.response?.status === 404) {
|
|
validToken.value = false
|
|
return
|
|
}
|
|
|
|
const msg = err.response?.status === 422 ? parseValidationError(err.response?.data)[0] : 'Unknown error.'
|
|
showErrorDialog(msg, 'Error')
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.invitation-wrapper {
|
|
@include vertical-center();
|
|
|
|
display: flex;
|
|
height: 100vh;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
}
|
|
|
|
header {
|
|
margin-bottom: 1.2rem;
|
|
}
|
|
|
|
small {
|
|
margin-top: .8rem;
|
|
font-size: .9rem;
|
|
display: block;
|
|
line-height: 1.4;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
form {
|
|
width: 320px;
|
|
padding: 1.8rem;
|
|
background: rgba(255, 255, 255, .08);
|
|
border-radius: .6rem;
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
input {
|
|
width: 100%;
|
|
}
|
|
|
|
@media only screen and (max-width: 414px) {
|
|
border: 0;
|
|
background: transparent;
|
|
}
|
|
}
|
|
</style>
|