Initial commit
This commit is contained in:
@@ -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>
|
||||
Reference in New Issue
Block a user