Files
Nilai_Clock/src/App.vue
T
2025-07-02 10:19:06 +08:00

101 lines
3.0 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>