174 lines
6.1 KiB
Vue
174 lines
6.1 KiB
Vue
<template>
|
|
<div class="authentication bg-gray">
|
|
<v-container class="pa-3 auth-login">
|
|
<v-row class="h-100vh d-flex justify-center align-center">
|
|
<v-col cols="12" class="text-center mt-6">
|
|
</v-col>
|
|
<v-col cols="12" class="d-flex align-center">
|
|
<v-card rounded="md" elevation="10" class="mx-auto">
|
|
<div class="pa-3">
|
|
<v-row>
|
|
<v-col cols="12" md="6" class="border-e px-md-12 px-6 py-md-12 py-6 bg-primary rounded-s-md">
|
|
<div class="login-container d-flex flex-column justify-space-between h-100 w-100">
|
|
|
|
<!-- TOP AREA -->
|
|
<div>
|
|
<!-- Logo and Title -->
|
|
<div class="mb-8">
|
|
<div class="d-flex align-center mb-2">
|
|
<v-icon size="40" color="white">mdi-hospital-building</v-icon>
|
|
<div class="ml-3">
|
|
<h2 class="text-h5 font-weight-bold">Antrean Operasi</h2>
|
|
<p class="text-caption">
|
|
RSUD Dr. Saiful Anwar Provinsi Jawa Timur
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sign In Section -->
|
|
<div class="mb-8 pa-4">
|
|
<h1 class="text-h3 font-weight-bold mb-6">Login</h1>
|
|
|
|
<!-- Error Message -->
|
|
<v-alert
|
|
v-if="errorMessage"
|
|
type="error"
|
|
closable
|
|
class="mb-4"
|
|
@click:close="errorMessage = ''"
|
|
>
|
|
{{ errorMessage }}
|
|
</v-alert>
|
|
|
|
<!-- Success Message -->
|
|
<v-alert
|
|
v-if="successMessage"
|
|
type="success"
|
|
class="mb-4"
|
|
>
|
|
{{ successMessage }}
|
|
</v-alert>
|
|
|
|
<v-btn
|
|
color="default"
|
|
size="x-large"
|
|
block
|
|
class="text-none mb-4 text-primary"
|
|
elevation="0"
|
|
:loading="isLoading"
|
|
:disabled="isLoading"
|
|
@click="handleLogin"
|
|
>
|
|
<v-icon left class="mr-3">mdi-account-circle</v-icon>
|
|
Log In with Keycloak
|
|
</v-btn>
|
|
</div>
|
|
|
|
<!-- BOTTOM AREA -->
|
|
<div class="d-flex align-center text-white">
|
|
<v-icon size="small" class="mr-2">mdi-lock-outline</v-icon>
|
|
<span class="text-caption">Not Authenticated</span>
|
|
</div>
|
|
|
|
</div>
|
|
</v-col>
|
|
<v-col cols="12" md="6" class="d-md-flex d-none">
|
|
<div class="d-flex flex-column justify-center px-md-12 px-6 h-100 align-center">
|
|
<div class="mt-16">
|
|
<img src="@/assets/images/backgrounds/undraw_wait-in-line_login.svg" alt="matdash-img"
|
|
width="300" />
|
|
</div>
|
|
<v-carousel :continuous="false" :show-arrows="false" cycle height="200" hide-delimiter-background
|
|
class="text-center mt-4">
|
|
<v-carousel-item v-for="item in AuthCuroselData" :key="item.title">
|
|
<h3 class="text-h3 mb-4">{{ item.title }}</h3>
|
|
<p class="textSecondary">
|
|
{{ item.subtitle }}
|
|
</p>
|
|
</v-carousel-item>
|
|
</v-carousel>
|
|
|
|
</div>
|
|
</v-col>
|
|
</v-row>
|
|
</div>
|
|
</v-card>
|
|
</v-col>
|
|
<v-col cols="12" class="text-center mt-6">
|
|
<p class="text-caption textSecondary">© 2026 RSUD Dr. Saiful Anwar Provinsi Jawa Timur. All rights reserved.</p>
|
|
</v-col>
|
|
</v-row>
|
|
</v-container>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, onMounted } from 'vue';
|
|
import type { LoginResponse } from '~/types/auth';
|
|
|
|
const route = useRoute();
|
|
|
|
const AuthCuroselData = [
|
|
{
|
|
title: 'Sistem Antrean Operasi',
|
|
subtitle: 'Kelola antrean operasi dengan efisien menggunakan sistem antrean.'
|
|
}
|
|
];
|
|
|
|
const isLoading = ref(false);
|
|
const errorMessage = ref('');
|
|
const successMessage = ref('');
|
|
|
|
// Check for error in URL query parameters
|
|
onMounted(() => {
|
|
const errorParam = route.query.error as string;
|
|
if (errorParam) {
|
|
errorMessage.value = decodeURIComponent(errorParam);
|
|
}
|
|
});
|
|
|
|
const handleLogin = async (): Promise<void> => {
|
|
isLoading.value = true;
|
|
errorMessage.value = '';
|
|
successMessage.value = '';
|
|
|
|
try {
|
|
console.log('Starting login process...');
|
|
|
|
// Call API route to initiate Keycloak login process
|
|
const response = await $fetch<LoginResponse>('/api/auth/keycloak-login', {
|
|
method: 'POST'
|
|
});
|
|
|
|
if (response?.success && response?.data?.authUrl) {
|
|
console.log('Redirecting to Keycloak...');
|
|
successMessage.value = 'Redirecting to Keycloak...';
|
|
|
|
// Redirect the user to the Keycloak authorization URL
|
|
setTimeout(() => {
|
|
window.location.href = response.data!.authUrl;
|
|
}, 500);
|
|
} else {
|
|
throw new Error('Failed to get authorization URL');
|
|
}
|
|
} catch (error: any) {
|
|
console.error('Login error:', error);
|
|
// Display the error message
|
|
errorMessage.value = `Login failed: ${error.message || 'Please try again.'}`;
|
|
} finally {
|
|
// Only set isLoading back to false if no redirect is happening
|
|
if (!successMessage.value.includes('Redirecting')) {
|
|
isLoading.value = false;
|
|
}
|
|
}
|
|
};
|
|
|
|
/*-For Set Blank Layout-*/
|
|
definePageMeta({
|
|
layout: "blank",
|
|
middleware: "guest"
|
|
});
|
|
</script>
|