243 lines
4.0 KiB
Vue
243 lines
4.0 KiB
Vue
<template>
|
|
<div class="login-container">
|
|
<div v-if="user">
|
|
You are already logged in as {{ user.username }}.
|
|
|
|
<ul>
|
|
<li>
|
|
<a
|
|
:href="`/user/${user.username}`"
|
|
class="link"
|
|
>View my profile</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a
|
|
:href="`/updates`"
|
|
class="link"
|
|
>Check out latest porn updates</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a
|
|
:href="`/actors`"
|
|
class="link"
|
|
>Browse the hottest porn stars</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<form
|
|
v-else
|
|
autocomplete="off"
|
|
class="login-panel"
|
|
@submit.prevent="signup"
|
|
>
|
|
<div
|
|
v-if="errorMsg"
|
|
class="error"
|
|
>{{ errorMsg }}</div>
|
|
|
|
<input
|
|
ref="userInput"
|
|
v-model="username"
|
|
placeholder="Username"
|
|
class="input"
|
|
required
|
|
>
|
|
|
|
<input
|
|
v-model="email"
|
|
type="email"
|
|
placeholder="E-mail"
|
|
class="input"
|
|
required
|
|
>
|
|
|
|
<div class="password-container">
|
|
<input
|
|
v-model="password"
|
|
:type="showPassword ? 'input' : 'password'"
|
|
autocomplete="new-password"
|
|
minlength="3"
|
|
placeholder="Password"
|
|
class="password input"
|
|
required
|
|
>
|
|
|
|
<div
|
|
class="password-show"
|
|
@click="showPassword = !showPassword"
|
|
>
|
|
<Icon
|
|
v-show="!showPassword"
|
|
icon="eye"
|
|
class="password-show"
|
|
/>
|
|
|
|
<Icon
|
|
v-show="showPassword"
|
|
icon="eye-blocked"
|
|
class="password-show"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="password-container">
|
|
<input
|
|
v-model="passwordConfirm"
|
|
:type="showPassword ? 'input' : 'password'"
|
|
autocomplete="new-password"
|
|
minlength="3"
|
|
placeholder="Confirm password"
|
|
class="password input"
|
|
required
|
|
>
|
|
|
|
<div
|
|
class="password-show"
|
|
@click="showPassword = !showPassword"
|
|
>
|
|
<Icon
|
|
v-show="!showPassword"
|
|
icon="eye"
|
|
class="password-show"
|
|
/>
|
|
|
|
<Icon
|
|
v-show="showPassword"
|
|
icon="eye-blocked"
|
|
class="password-show"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<button class="button button-submit">Sign up</button>
|
|
|
|
<a
|
|
href="/login"
|
|
class="link"
|
|
>I already have an account</a>
|
|
</form>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted, inject } from 'vue';
|
|
|
|
import { post } from '#/src/api.js';
|
|
import navigate from '#/src/navigate.js';
|
|
|
|
const pageContext = inject('pageContext');
|
|
const user = pageContext.user;
|
|
|
|
const username = ref('');
|
|
const email = ref('');
|
|
const password = ref('');
|
|
const passwordConfirm = ref('');
|
|
|
|
const errorMsg = ref(null);
|
|
const userInput = ref(null);
|
|
const showPassword = ref(false);
|
|
|
|
async function signup() {
|
|
errorMsg.value = null;
|
|
|
|
if (password.value !== passwordConfirm.value) {
|
|
errorMsg.value = 'Passwords do not match';
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const newUser = await post('/users', {
|
|
username: username.value,
|
|
email: email.value,
|
|
password: password.value,
|
|
redirect: pageContext.urlParsed.search.r,
|
|
});
|
|
|
|
navigate(`/user/${newUser.username}`, null, { redirect: true });
|
|
} catch (error) {
|
|
errorMsg.value = error.message;
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
userInput.value.focus();
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.login-container {
|
|
display: flex;
|
|
flex-grow: 1;
|
|
justify-content: center;
|
|
align-items: center;
|
|
background: var(--background-base-10);
|
|
}
|
|
|
|
.login-panel {
|
|
width: 20rem;
|
|
max-width: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: .5rem;
|
|
padding: 1rem;
|
|
margin: 1rem;
|
|
border-radius: .5rem;
|
|
box-shadow: 0 0 3px var(--shadow-weak-30);
|
|
background: var(--background-base);
|
|
font-size: 1rem;
|
|
|
|
.button {
|
|
justify-content: center;
|
|
}
|
|
|
|
.link {
|
|
margin-top: .5rem;
|
|
text-align: center;
|
|
}
|
|
}
|
|
|
|
.password-container {
|
|
display: flex;
|
|
position: relative;
|
|
}
|
|
|
|
.password {
|
|
flex-grow: 1;
|
|
}
|
|
|
|
.password-show {
|
|
height: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
position: absolute;
|
|
right: 0;
|
|
padding: 0 1rem 0 .5rem;
|
|
|
|
.icon {
|
|
fill: var(--shadow);
|
|
}
|
|
|
|
&:hover {
|
|
cursor: pointer;
|
|
|
|
.icon {
|
|
fill: var(--primary);
|
|
}
|
|
}
|
|
}
|
|
|
|
.error {
|
|
background: var(--error);
|
|
color: var(--text-light);
|
|
padding: .75rem 1rem;
|
|
border-radius: .25rem;
|
|
margin-bottom: .5rem;
|
|
font-size: .9rem;
|
|
font-weight: bold;
|
|
text-align: center;
|
|
}
|
|
</style>
|