2025-02-16 13:10:19 +01:00
|
|
|
<template>
|
|
|
|
|
<v-app full-height>
|
|
|
|
|
<v-main class="container">
|
|
|
|
|
<v-container class="fill-height" fluid>
|
|
|
|
|
<v-row align="center" justify="center" class="fill-height">
|
2025-06-12 16:36:32 +02:00
|
|
|
<v-col cols="12" class="d-flex flex-column align-center">
|
2025-06-15 17:37:14 +02:00
|
|
|
<v-card class="pa-8" rounded max-width="450" elevation="3">
|
2025-06-14 14:09:56 +02:00
|
|
|
<v-row no-gutters>
|
2025-06-15 17:37:14 +02:00
|
|
|
<v-col cols="12" class="text-center mb-6">
|
|
|
|
|
<v-img src="/Port_Nimara_Logo_2_Colour_New_Transparent.png" width="200" class="mx-auto mb-4" />
|
|
|
|
|
<h1 class="text-h5 font-weight-medium mb-2">Welcome to Port Nimara</h1>
|
|
|
|
|
<p class="text-body-2 text-grey-darken-1">Client Portal Access</p>
|
|
|
|
|
</v-col>
|
|
|
|
|
|
|
|
|
|
<!-- Error Alert -->
|
|
|
|
|
<v-col cols="12" v-if="errorMessage" class="mb-4">
|
|
|
|
|
<v-alert
|
|
|
|
|
:text="errorMessage"
|
|
|
|
|
color="error"
|
|
|
|
|
variant="tonal"
|
|
|
|
|
closable
|
|
|
|
|
@click:close="errorMessage = ''"
|
|
|
|
|
/>
|
2025-06-14 14:09:56 +02:00
|
|
|
</v-col>
|
|
|
|
|
|
2025-06-14 15:26:26 +02:00
|
|
|
<!-- Keycloak SSO Login -->
|
|
|
|
|
<v-col cols="12" class="mb-4">
|
|
|
|
|
<v-btn
|
|
|
|
|
color="primary"
|
|
|
|
|
size="large"
|
|
|
|
|
block
|
|
|
|
|
@click="loginWithKeycloak"
|
|
|
|
|
prepend-icon="mdi-shield-account"
|
|
|
|
|
:loading="keycloakLoading"
|
2025-06-15 17:37:14 +02:00
|
|
|
:disabled="keycloakLoading"
|
2025-06-14 15:26:26 +02:00
|
|
|
>
|
2025-06-15 17:37:14 +02:00
|
|
|
{{ keycloakLoading ? 'Connecting...' : 'Login with Single Sign-On' }}
|
2025-06-14 15:26:26 +02:00
|
|
|
</v-btn>
|
2025-06-15 17:37:14 +02:00
|
|
|
<p class="text-caption text-center text-grey-darken-1 mt-3">
|
|
|
|
|
Secure authentication through Keycloak SSO
|
|
|
|
|
</p>
|
2025-06-14 14:09:56 +02:00
|
|
|
</v-col>
|
|
|
|
|
</v-row>
|
2025-06-12 16:36:32 +02:00
|
|
|
</v-card>
|
|
|
|
|
|
|
|
|
|
<!-- PWA Install Banner -->
|
|
|
|
|
<PWAInstallBanner />
|
|
|
|
|
</v-col>
|
2025-02-16 13:10:19 +01:00
|
|
|
</v-row>
|
|
|
|
|
</v-container>
|
|
|
|
|
</v-main>
|
|
|
|
|
</v-app>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2025-06-14 14:09:56 +02:00
|
|
|
// Define page meta for public access
|
|
|
|
|
definePageMeta({
|
|
|
|
|
auth: false
|
|
|
|
|
});
|
|
|
|
|
|
2025-06-15 15:36:48 +02:00
|
|
|
// Custom Keycloak auth
|
|
|
|
|
const { login: keycloakLogin } = useCustomAuth();
|
2025-06-14 15:26:26 +02:00
|
|
|
|
|
|
|
|
const keycloakLoading = ref(false);
|
2025-06-15 17:37:14 +02:00
|
|
|
const errorMessage = ref('');
|
2025-02-16 13:10:19 +01:00
|
|
|
|
2025-06-15 17:37:14 +02:00
|
|
|
// Check for error in query params
|
|
|
|
|
const route = useRoute();
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
if (route.query.error === 'auth_failed') {
|
|
|
|
|
errorMessage.value = 'Authentication failed. Please try again.';
|
|
|
|
|
}
|
|
|
|
|
});
|
2025-02-16 13:10:19 +01:00
|
|
|
|
2025-06-15 15:36:48 +02:00
|
|
|
// SSO login function using custom Keycloak auth
|
2025-06-14 15:26:26 +02:00
|
|
|
const loginWithKeycloak = async () => {
|
|
|
|
|
try {
|
2025-06-15 17:37:14 +02:00
|
|
|
errorMessage.value = ''; // Clear any previous errors
|
2025-06-14 15:26:26 +02:00
|
|
|
keycloakLoading.value = true;
|
2025-06-15 17:37:14 +02:00
|
|
|
console.log('[LOGIN] Starting SSO authentication via Keycloak...');
|
2025-06-14 15:26:26 +02:00
|
|
|
|
2025-06-15 15:36:48 +02:00
|
|
|
// Use our custom Keycloak authentication
|
|
|
|
|
keycloakLogin();
|
2025-06-14 15:26:26 +02:00
|
|
|
|
|
|
|
|
} catch (error) {
|
2025-06-14 15:58:03 +02:00
|
|
|
console.error('[LOGIN] SSO login error:', error);
|
2025-06-15 17:37:14 +02:00
|
|
|
errorMessage.value = 'SSO login failed. Please try again.';
|
2025-06-14 15:26:26 +02:00
|
|
|
} finally {
|
|
|
|
|
keycloakLoading.value = false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-02-16 13:10:19 +01:00
|
|
|
useHead({
|
2025-06-15 17:37:14 +02:00
|
|
|
title: "Port Nimara - Login",
|
2025-02-16 13:10:19 +01:00
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
.container {
|
|
|
|
|
background: url(/background.jpg);
|
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
|
background-size: cover;
|
|
|
|
|
}
|
|
|
|
|
</style>
|