Initial commit

This commit is contained in:
sudomarcma
2025-07-07 14:18:30 +08:00
commit 8428d03051
104 changed files with 16528 additions and 0 deletions
+144
View File
@@ -0,0 +1,144 @@
<template>
<div class="flex justify-center items-center min-h-screen bg-gray-100">
<div class="w-full max-w-sm p-8 space-y-6 bg-white rounded-2xl shadow-lg">
<!-- App Logo -->
<div class="flex justify-center">
<ArrowRightOnRectangleIcon class="w-16 h-16 text-blue-600" />
</div>
<!-- Title -->
<h2 class="text-3xl font-extrabold text-center text-gray-900">
{{ t('login') }}
</h2>
<form @submit.prevent="handleLogin" class="space-y-6">
<!-- Username -->
<div>
<label for="username" class="sr-only">{{ t('username') }}</label>
<input type="text" id="username" v-model="username" autocomplete="username"
class="w-full px-4 py-3 text-gray-700 bg-gray-50 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
:placeholder="t('username')"
required />
</div>
<!-- Password -->
<div>
<label for="password" class="sr-only">{{ t('password') }}</label>
<input type="password" id="password" v-model="password" autocomplete="current-password"
class="w-full px-4 py-3 text-gray-700 bg-gray-50 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
:placeholder="t('password')"
required />
</div>
<!-- Remember Me Checkbox -->
<div class="flex items-center justify-between">
<div class="flex items-center">
<input type="checkbox" id="rememberMe" v-model="rememberMe"
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500" />
<label for="rememberMe" class="ml-2 block text-sm text-gray-900">
{{ t('rememberMe') }}
</label>
</div>
</div>
<!-- Submit Button -->
<button type="submit"
class="w-full py-3 text-lg font-semibold text-white bg-blue-600 rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-transform transform hover:scale-105 disabled:opacity-60 disabled:cursor-not-allowed shadow-md"
:disabled="loading">
{{ loading ? t('loggingIn') : t('login') }}
</button>
<!-- Error -->
<p v-if="error" class="text-sm text-center text-red-600 mt-4">
{{ t(error) !== error ? t(error) : error }}
</p>
</form>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { ArrowRightOnRectangleIcon } from '@heroicons/vue/24/outline'
import { authService } from '@/services/authService.js'
import { nativeServicesManager } from '@/services/nativeServicesManager.js'
const { t } = useI18n()
const router = useRouter()
const username = ref('')
const password = ref('')
const rememberMe = ref(false)
const error = ref('')
const loading = ref(false)
const handleLogin = async () => {
loading.value = true
error.value = ''
try {
const loginResult = await authService.login(
username.value,
password.value,
rememberMe.value
)
if (loginResult.success) {
console.log('✅ LOGIN SUCCESS:', loginResult)
sessionStorage.setItem('userId', loginResult.userId.toString())
sessionStorage.setItem('userRole', loginResult.userRole)
sessionStorage.setItem('token', loginResult.token)
console.log('✅ SESSION STORAGE SET:', {
userId: sessionStorage.getItem('userId'),
userRole: sessionStorage.getItem('userRole')
})
if (loginResult.userRole === 'worker') {
console.log('🔄 WORKER LOGIN - Starting native services...')
try {
await nativeServicesManager.onUserLogin()
console.log('✅ NATIVE SERVICES STARTED')
} catch (serviceError) {
console.error('❌ NATIVE SERVICES FAILED:', serviceError)
}
console.log('🔄 NAVIGATING TO WORKER DASHBOARD...')
try {
await router.push('/worker/dashboard')
console.log('✅ NAVIGATION COMPLETED')
} catch (navError) {
console.error('❌ NAVIGATION FAILED:', navError)
}
} else {
console.log('️ NON-WORKER LOGIN - Worker client app only')
error.value = 'This application is designed for workers only.'
await authService.logout()
}
} else {
if (loginResult.error.includes('Device not authorized')) {
error.value = 'deviceNotAuthorized'
} else if (loginResult.error.includes('Invalid credentials')) {
error.value = 'invalidCredentials'
} else if (loginResult.error.includes('Network error')) {
error.value = 'failedConnection'
} else {
error.value = loginResult.error
}
}
} catch (err) {
console.error('Login error:', err)
error.value = 'failedConnection'
} finally {
loading.value = false
}
}
</script>
<style scoped>
/* All styles are now handled by Tailwind CSS classes in the template. */
</style>