60 lines
1.4 KiB
Vue
60 lines
1.4 KiB
Vue
<template>
|
|
<IonPage>
|
|
<IonContent class="ion-padding ion-text-center">
|
|
<div class="callback-state">
|
|
<IonSpinner v-if="!errorMessage" name="crescent" class="callback-spinner" />
|
|
<IonIcon v-else :icon="alertCircleOutline" class="callback-error-icon" color="danger" />
|
|
<p>{{ errorMessage || 'Signing you in...' }}</p>
|
|
</div>
|
|
</IonContent>
|
|
</IonPage>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { IonPage, IonContent, IonSpinner, IonIcon } from '@ionic/vue'
|
|
import { alertCircleOutline } from 'ionicons/icons'
|
|
|
|
definePageMeta({ layout: false })
|
|
|
|
const supabase = useSupabaseClient()
|
|
const user = useSupabaseUser()
|
|
const route = useRoute()
|
|
const errorMessage = ref('')
|
|
|
|
onMounted(async () => {
|
|
const code = route.query.code as string | undefined
|
|
if (code) {
|
|
const { error } = await supabase.auth.exchangeCodeForSession(code)
|
|
if (error) {
|
|
errorMessage.value = 'Sign-in failed. Please try again.'
|
|
return
|
|
}
|
|
}
|
|
})
|
|
|
|
// Navigate home once session is established (handles both hash-based and PKCE flows)
|
|
watch(user, (value) => {
|
|
if (value) navigateTo('/')
|
|
}, { immediate: true })
|
|
</script>
|
|
|
|
<style scoped>
|
|
.callback-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 100%;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.callback-spinner {
|
|
width: 2.5rem;
|
|
height: 2.5rem;
|
|
}
|
|
|
|
.callback-error-icon {
|
|
font-size: 2.5rem;
|
|
}
|
|
</style>
|