munch-ease-frontend/src/components/LoginPage.vue
2025-11-02 21:57:57 +11:00

161 lines
3.4 KiB
Vue

<template>
<div class="login">
<h1>Login</h1>
<!-- Multitenant: Email/Password login -->
<div v-if="isMultitenant">
<form @submit.prevent="onSubmitLogin">
<div class="form-group">
<label for="email">Email</label>
<input
id="email"
v-model="email"
type="email"
required
>
</div>
<div class="form-group">
<label for="password">Password</label>
<input
id="password"
v-model="password"
type="password"
required
>
</div>
<button
type="submit"
class="btn btn-primary"
>
Sign in
</button>
<button
type="button"
class="btn btn-secondary"
@click="onGoogleLogin"
>
Sign in with Google
</button>
<router-link
class="btn btn-link"
:to="{ name: 'create-account' }"
>
Create account
</router-link>
</form>
</div>
<div v-else>
<p>This environment is configured without multi-tenancy enabled.</p>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { loginWithPassword, handleGoogleLogin } from '@/api/auth'
import { useAuth } from '@/composables/useAuth'
const props = defineProps({
redirect: { type: String, default: '/' },
})
const router = useRouter()
const route = useRoute()
const email = ref('')
const password = ref('')
const isMultitenant = computed(() => true)
const { user } = useAuth()
onMounted(async () => {})
function afterLoginNavigate() {
const q = route.query?.redirect
const redirectPath = (typeof q === 'string' ? q : undefined) || props.redirect
router.push(redirectPath || '/')
}
async function onSubmitLogin() {
try {
await loginWithPassword(email.value.trim(), password.value)
if (user.value?.id !== undefined) {
afterLoginNavigate()
return
}
alert('Login failed')
} catch (e) {
alert(e instanceof Error ? e.message : 'Login error')
}
}
async function onGoogleLogin() {
try {
const url = await handleGoogleLogin()
if (typeof window !== 'undefined') {
window.location.href = url
}
} catch (e) {
alert(e instanceof Error ? e.message : 'Google login not available')
}
}
</script>
<style scoped>
/* Remove the default list styling */
ul {
list-style-type: none;
padding: 0;
}
/* Center the buttons in the middle of the page, and let them wrap */
.button-group {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
/* Display each button as a large round circle */
button {
width: 100px;
height: 100px;
border-radius: 50%;
margin: 10px;
font-size: 1.5em;
/* Center the text in the middle of the button */
display: flex;
justify-content: center;
align-items: center;
/* Add a shadow to make the buttons look like they are floating */
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
/* Some nice flat nuetral shades for the user buttons */
li:nth-child(1) > button {
background-color: #3939ff;
color: white;
}
li:nth-child(2) > button {
background-color: #156a14;
color: white;
}
li:nth-child(3) > button {
background-color: #325293;
color: white;
}
li:nth-child(4) > button {
background-color: #9a1f1f;
color: white;
}
.form-group {
margin-bottom: 12px;
}
</style>