101 lines
3.0 KiB
Vue
101 lines
3.0 KiB
Vue
<template>
|
||
<div
|
||
class="min-h-screen bg-gray-100 text-gray-900 dark:bg-gray-900 dark:text-gray-100 transition-colors duration-300">
|
||
<header
|
||
class="flex justify-between items-center px-4 py-3 sm:px-8 bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 shadow-sm transition-colors duration-300">
|
||
<h1 class="text-xl sm:text-2xl font-bold">{{ $t('appTitle') }}</h1>
|
||
<div class="flex items-center gap-4">
|
||
|
||
<!-- Language Selector -->
|
||
<select v-model="currentLang" @change="changeLang"
|
||
class="px-2 py-1 rounded-md border border-gray-300 dark:border-gray-600 bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200"
|
||
style="font-size: 0.9em;">
|
||
<option value="en">{{ $t('english') }}</option>
|
||
<option value="ms">{{ $t('malay') }}</option>
|
||
</select>
|
||
|
||
<button v-if="isLoggedIn" @click="logout"
|
||
class="px-4 py-2 bg-gray-200 hover:bg-gray-300 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 rounded-md font-semibold transition-colors duration-200">
|
||
{{ $t('logout') }}
|
||
</button>
|
||
<button @click="toggleTheme"
|
||
class="flex items-center justify-center w-11 h-11 bg-gray-200 hover:bg-gray-300 dark:bg-gray-700 dark:hover:bg-gray-600 text-lg rounded-full transition-colors duration-200"
|
||
title="Toggle Theme">
|
||
<span v-if="isDarkMode">☀️</span>
|
||
<span v-else>🌙</span>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
<main class="p-4 sm:p-8">
|
||
<RouterView />
|
||
</main>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, onMounted, watch } from 'vue'
|
||
import { RouterView, useRouter, useRoute } from 'vue-router'
|
||
import { useI18n } from 'vue-i18n'
|
||
|
||
const { locale } = useI18n()
|
||
|
||
const isDarkMode = ref(false)
|
||
const router = useRouter()
|
||
const route = useRoute()
|
||
|
||
const isLoggedIn = ref(!!sessionStorage.getItem('userId'))
|
||
|
||
// Language switch logic
|
||
const currentLang = ref(locale.value)
|
||
|
||
const changeLang = () => {
|
||
locale.value = currentLang.value
|
||
localStorage.setItem('lang', currentLang.value)
|
||
}
|
||
|
||
watch(
|
||
() => route.path,
|
||
() => {
|
||
isLoggedIn.value = !!sessionStorage.getItem('userId')
|
||
},
|
||
)
|
||
|
||
const logout = () => {
|
||
sessionStorage.removeItem('userId')
|
||
sessionStorage.removeItem('userRole')
|
||
isLoggedIn.value = false
|
||
router.push('/')
|
||
}
|
||
|
||
const toggleTheme = () => {
|
||
isDarkMode.value = !isDarkMode.value
|
||
localStorage.setItem('darkMode', isDarkMode.value)
|
||
updateTheme()
|
||
}
|
||
|
||
const updateTheme = () => {
|
||
if (isDarkMode.value) {
|
||
document.documentElement.classList.add('dark')
|
||
} else {
|
||
document.documentElement.classList.remove('dark')
|
||
}
|
||
}
|
||
|
||
onMounted(() => {
|
||
// Restore theme
|
||
const savedTheme = localStorage.getItem('darkMode')
|
||
isDarkMode.value = savedTheme === 'true'
|
||
updateTheme()
|
||
// Restore language
|
||
const savedLang = localStorage.getItem('lang')
|
||
if (savedLang) {
|
||
currentLang.value = savedLang
|
||
locale.value = savedLang
|
||
}
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* All styles are now handled by Tailwind CSS classes in the template. */
|
||
</style>
|