ghostguild-org/app/pages/coming-soon.vue
Jennie Robinson Faber 59d6e97787
Some checks failed
Test / vitest (push) Failing after 7m23s
Test / playwright (push) Has been skipped
Test / visual (push) Has been skipped
Test / Notify on failure (push) Successful in 2s
Member/Ecology revamp.
2026-04-14 09:25:09 +01:00

246 lines
5.1 KiB
Vue

<template>
<div class="coming-soon">
<h1 class="coming-soon-title">Ghost Guild</h1>
<p v-if="!isAuthenticated" class="coming-soon-subtitle">Coming Soon</p>
<!-- Logged-in state -->
<div v-if="isAuthenticated" class="coming-soon-auth">
<p>
Welcome, <strong>{{ memberData.name || memberData.email }}</strong>
</p>
<a href="https://wiki.ghostguild.org" class="coming-soon-btn">
Go to Wiki
</a>
<button class="coming-soon-signout" @click="handleLogout">
Sign out
</button>
</div>
<!-- Login form -->
<div v-else class="coming-soon-form">
<!-- Success state -->
<div v-if="loginSuccess" class="coming-soon-success">
<h3>Check your email</h3>
<p>
We've sent a magic link to
<strong>{{ email }}</strong
>. Click the link to sign in.
</p>
</div>
<!-- Form -->
<UForm v-else :state="{ email }" @submit="handleLogin">
<UFormField name="email" required class="mb-4">
<UInput
v-model="email"
type="email"
size="lg"
class="w-full"
placeholder="your.email@example.com"
/>
</UFormField>
<div v-if="loginError" class="coming-soon-error">
<p>{{ loginError }}</p>
</div>
<div class="coming-soon-actions">
<UButton
type="submit"
:loading="isLoggingIn"
:disabled="!isFormValid"
size="lg"
class="uppercase tracking-wide font-semibold whitespace-nowrap"
>
Send Magic Link
</UButton>
</div>
<div class="coming-soon-preregister">
<a href="https://babyghosts.org/ghost-guild/">Pre-Register</a>
</div>
</UForm>
</div>
</div>
</template>
<script setup>
definePageMeta({
layout: "coming-soon",
});
const { isAuthenticated, memberData, checkMemberStatus, logout } = useAuth();
const email = ref("");
const isLoggingIn = ref(false);
const loginSuccess = ref(false);
const loginError = ref("");
const isFormValid = computed(() => email.value && email.value.includes("@"));
const handleLogin = async () => {
if (isLoggingIn.value) return;
isLoggingIn.value = true;
loginError.value = "";
try {
const response = await $fetch("/api/auth/login", {
method: "POST",
body: { email: email.value },
});
if (response.success) {
loginSuccess.value = true;
}
} catch (err) {
if (err.statusCode === 500) {
loginError.value = "Failed to send login email. Please try again later.";
} else {
loginError.value =
err.statusMessage || "Something went wrong. Please try again.";
}
} finally {
isLoggingIn.value = false;
}
};
const handleLogout = async () => {
await logout();
};
</script>
<style scoped>
.coming-soon {
min-height: 100vh;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 16px;
}
.coming-soon-title {
font-family: var(--font-display);
font-size: 3rem;
font-weight: 700;
color: var(--text-bright);
margin-bottom: 8px;
}
.coming-soon-subtitle {
font-size: 10px;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--text-faint);
margin-bottom: 40px;
padding: 16px 0;
}
.coming-soon-auth {
width: 100%;
max-width: 24rem;
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
text-align: center;
margin-top: 32px;
color: var(--text-dim);
}
.coming-soon-auth strong {
color: var(--text-bright);
}
.coming-soon-btn {
display: block;
width: 100%;
padding: 12px 24px;
background: var(--parch);
color: var(--parch-text);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
text-align: center;
transition: background 0.15s;
}
.coming-soon-btn:hover {
background: var(--parch-hover);
text-decoration: none;
}
.coming-soon-signout {
font-size: 12px;
color: var(--candle);
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.05em;
transition: color 0.15s;
cursor: pointer;
}
.coming-soon-signout:hover {
color: var(--candle-dim);
}
.coming-soon-form {
width: 100%;
max-width: 24rem;
}
.coming-soon-success {
text-align: center;
padding: 16px 0;
}
.coming-soon-success h3 {
font-family: var(--font-display);
font-size: 1.125rem;
font-weight: 600;
color: var(--text-bright);
margin-bottom: 8px;
}
.coming-soon-success p {
color: var(--text-dim);
}
.coming-soon-success strong {
color: var(--text-bright);
}
.coming-soon-error {
margin-bottom: 16px;
padding: 12px;
background: var(--ember-bg);
border: 1px dashed var(--ember);
}
.coming-soon-error p {
color: var(--ember);
font-size: 12px;
}
.coming-soon-actions {
display: flex;
justify-content: center;
}
.coming-soon-preregister {
text-align: center;
padding-top: 24px;
border-top: 1px dashed var(--border);
margin-top: 24px;
font-size: 12px;
}
.coming-soon-preregister a {
color: var(--candle);
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.05em;
}
</style>