ilk
This commit is contained in:
306
ui/src/pages/MainPage.vue
Normal file
306
ui/src/pages/MainPage.vue
Normal file
@@ -0,0 +1,306 @@
|
||||
<template>
|
||||
<q-page class="flex flex-center login-bg">
|
||||
|
||||
<q-card class="q-pa-lg shadow-4 login-card">
|
||||
<!-- HEADER -->
|
||||
<q-card-section class="text-center">
|
||||
<q-avatar size="80px" class="bg-white text-secondary shadow-2">
|
||||
<q-icon name="lock" size="40px" />
|
||||
</q-avatar>
|
||||
<div class="login-title q-mt-sm">Kullanıcı Girişi</div>
|
||||
</q-card-section>
|
||||
|
||||
<!-- FORM -->
|
||||
<q-card-section>
|
||||
<q-input
|
||||
v-model="username"
|
||||
label="Kullanıcı Adı"
|
||||
dense
|
||||
standout="bg-white"
|
||||
class="q-mb-md custom-input"
|
||||
autocomplete="username"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
v-model="password"
|
||||
type="password"
|
||||
label="Şifre"
|
||||
dense
|
||||
standout="bg-white"
|
||||
class="custom-input"
|
||||
autocomplete="current-password"
|
||||
/>
|
||||
|
||||
<div class="q-mt-md row items-center justify-between">
|
||||
<div>
|
||||
<q-checkbox
|
||||
v-model="rememberUser"
|
||||
label="Kullanıcıyı hatırla"
|
||||
color="secondary"
|
||||
dense
|
||||
/>
|
||||
<q-checkbox
|
||||
v-model="rememberPass"
|
||||
label="Parolayı kaydet"
|
||||
color="secondary"
|
||||
dense
|
||||
/>
|
||||
</div>
|
||||
|
||||
<q-btn
|
||||
flat
|
||||
dense
|
||||
color="primary"
|
||||
label="Şifremi Unuttum"
|
||||
@click="forgotOpen = true"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<!-- ACTION -->
|
||||
<q-card-actions align="center">
|
||||
<q-btn
|
||||
label="Giriş Yap"
|
||||
color="primary"
|
||||
glossy
|
||||
unelevated
|
||||
icon="login"
|
||||
class="full-width"
|
||||
:loading="loading"
|
||||
@click="login"
|
||||
/>
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
|
||||
<!-- 🔐 FORGOT PASSWORD -->
|
||||
<q-dialog v-model="forgotOpen" persistent>
|
||||
<q-card style="width:420px; max-width:90vw">
|
||||
<q-card-section class="text-h6">
|
||||
Parola Sıfırlama
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section>
|
||||
<div class="text-caption text-grey-7 q-mb-sm">
|
||||
Kullanıcı adınızı girin.
|
||||
</div>
|
||||
|
||||
<q-input
|
||||
v-model="forgotUsername"
|
||||
label="Kullanıcı Adı"
|
||||
dense
|
||||
outlined
|
||||
:disable="forgotLoading"
|
||||
/>
|
||||
|
||||
<q-banner
|
||||
v-if="forgotMessage"
|
||||
class="q-mt-md"
|
||||
:class="forgotSuccess ? 'bg-green-1 text-green' : 'bg-red-1 text-red'"
|
||||
rounded
|
||||
>
|
||||
{{ forgotMessage }}
|
||||
</q-banner>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions align="right">
|
||||
<q-btn flat label="Vazgeç" v-close-popup />
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="Gönder"
|
||||
:loading="forgotLoading"
|
||||
@click="sendResetMail"
|
||||
/>
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
</q-page>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useAuthStore } from 'stores/authStore'
|
||||
import { useQuasar } from 'quasar'
|
||||
import api from 'src/services/api'
|
||||
import { usePermission } from 'src/composables/usePermission'
|
||||
|
||||
const { canRead, canWrite, canUpdate } = usePermission()
|
||||
|
||||
const canReadOrder = canRead('order')
|
||||
const canWriteOrder = canWrite('order')
|
||||
const canUpdateOrder = canUpdate('order')
|
||||
|
||||
const router = useRouter()
|
||||
const auth = useAuthStore()
|
||||
const $q = useQuasar()
|
||||
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
const rememberUser = ref(false)
|
||||
const rememberPass = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
/* 🔐 Forgot password */
|
||||
const forgotOpen = ref(false)
|
||||
const forgotUsername = ref('')
|
||||
const forgotLoading = ref(false)
|
||||
const forgotMessage = ref('')
|
||||
const forgotSuccess = ref(false)
|
||||
|
||||
onMounted(() => {
|
||||
if (localStorage.getItem('remember_user') === 'true') {
|
||||
username.value = localStorage.getItem('username') || ''
|
||||
rememberUser.value = true
|
||||
}
|
||||
if (localStorage.getItem('remember_pass') === 'true') {
|
||||
password.value = localStorage.getItem('password') || ''
|
||||
rememberPass.value = true
|
||||
}
|
||||
})
|
||||
|
||||
/* =========================================================
|
||||
🔐 LOGIN
|
||||
========================================================= */
|
||||
async function login () {
|
||||
loading.value = true
|
||||
|
||||
try {
|
||||
await auth.login(username.value, password.value)
|
||||
|
||||
// remember checks
|
||||
rememberUser.value
|
||||
? localStorage.setItem('username', username.value)
|
||||
: localStorage.removeItem('username')
|
||||
|
||||
rememberPass.value
|
||||
? localStorage.setItem('password', password.value)
|
||||
: localStorage.removeItem('password')
|
||||
|
||||
localStorage.setItem('remember_user', rememberUser.value ? 'true' : 'false')
|
||||
localStorage.setItem('remember_pass', rememberPass.value ? 'true' : 'false')
|
||||
|
||||
// 🔥 YÖNLENDİRME
|
||||
if (auth.mustChangePassword) {
|
||||
router.replace('/first-password-change')
|
||||
} else {
|
||||
router.replace('/app')
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('❌ Login error:', err)
|
||||
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: 'Kullanıcı adı veya şifre hatalı',
|
||||
position: 'top-right'
|
||||
})
|
||||
|
||||
auth.clearSession()
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
🔐 FORGOT PASSWORD
|
||||
========================================================= */
|
||||
async function sendResetMail () {
|
||||
if (!forgotUsername.value) return
|
||||
|
||||
forgotLoading.value = true
|
||||
forgotMessage.value = ''
|
||||
|
||||
try {
|
||||
await api.post('/password/forgot', {
|
||||
email: forgotUsername.value
|
||||
})
|
||||
|
||||
forgotSuccess.value = true
|
||||
forgotMessage.value =
|
||||
'Eğer hesabınız aktif ise parola sıfırlama bağlantısı e-posta adresinize gönderilmiştir.'
|
||||
} catch {
|
||||
// 👈 bilgi sızdırmamak için bilinçli olarak aynı mesaj
|
||||
forgotSuccess.value = true
|
||||
forgotMessage.value =
|
||||
'Eğer hesabınız aktif ise parola sıfırlama bağlantısı e-posta adresinize gönderilmiştir.'
|
||||
} finally {
|
||||
forgotLoading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.login-bg {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
}
|
||||
.login-bg::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: url("/images/Baggi-Fabrika-resmi.jpg") no-repeat center;
|
||||
background-size: cover;
|
||||
opacity: 0.3;
|
||||
}
|
||||
.login-bg > * {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.login-card {
|
||||
width: 400px;
|
||||
max-width: 90%;
|
||||
border-radius: 16px;
|
||||
background: var(--q-secondary);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
color: var(--q-primary);
|
||||
}
|
||||
|
||||
.custom-input {
|
||||
background: #fdfcfc;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
/* ===============================
|
||||
LOGIN INPUT TEXT COLOR (GOLD)
|
||||
=============================== */
|
||||
|
||||
/* Input içindeki yazı */
|
||||
.login-card :deep(.q-field__native),
|
||||
.login-card :deep(.q-field__input) {
|
||||
color: var(--q-primary) !important; /* gold */
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Placeholder rengi */
|
||||
.login-card :deep(.q-field__native::placeholder) {
|
||||
color: rgba(149, 113, 22, 0.6); /* gold soft */
|
||||
}
|
||||
|
||||
/* Label rengi */
|
||||
.login-card :deep(.q-field__label) {
|
||||
color: var(--q-primary);
|
||||
}
|
||||
|
||||
/* Focus olunca */
|
||||
.login-card :deep(.q-field--focused .q-field__native) {
|
||||
color: var(--q-primary);
|
||||
}
|
||||
|
||||
/* Autofill (Chrome sarı arkaplanı bastırmak için) */
|
||||
.login-card :deep(input:-webkit-autofill) {
|
||||
-webkit-text-fill-color: var(--q-primary) !important;
|
||||
transition: background-color 9999s ease-in-out 0s;
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user