first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 22:07:47 +03:00
commit 5285a0dd86
522 changed files with 41738 additions and 0 deletions

177
app/pages/auth/login.vue Normal file
View File

@@ -0,0 +1,177 @@
<template>
<div class="login-area pt-120 pb-120">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-6 col-md-8">
<div class="login-form-wrap shadow-lg p-5 rounded bg-white">
<div class="login-header text-center mb-4">
<h2 class="mb-2">Giriş Yap</h2>
<p>
Hesabınız yok mu?
<NuxtLink to="/auth/register" class="text-primary fw-bold">Kayıt Olun</NuxtLink>
</p>
</div>
<form @submit.prevent="handleLogin">
<div class="mb-3">
<label for="email" class="form-label">E-posta Adresi</label>
<div class="input-group">
<span class="input-group-text"><i class="fas fa-envelope"></i></span>
<input type="email" class="form-control" id="email" v-model="form.email"
placeholder="E-posta adresinizi girin" required>
</div>
<div v-if="errors.email" class="text-danger small mt-1">{{ errors.email }}</div>
</div>
<div class="mb-3">
<label for="password" class="form-label">Şifre</label>
<div class="input-group">
<span class="input-group-text"><i class="fas fa-lock"></i></span>
<input type="password" class="form-control" id="password" v-model="form.password"
placeholder="Şifrenizi girin" required>
</div>
<div v-if="errors.password" class="text-danger small mt-1">{{ errors.password }}</div>
</div>
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="remember-me">
<label class="form-check-label" for="remember-me">Beni Hatırla</label>
</div>
<a href="#" class="text-muted small">Şifremi Unuttum?</a>
</div>
<!-- Turnstile Component -->
<ClientOnly>
<div class="mb-4 d-flex justify-content-center">
<NuxtTurnstile v-model="turnstileToken" />
</div>
</ClientOnly>
<button type="submit" class="btn btn-primary w-100 py-2" :disabled="loading">
<span v-if="loading" class="spinner-border spinner-border-sm me-2" role="status"
aria-hidden="true"></span>
{{ loading ? 'Giriş Yapılıyor...' : 'Giriş Yap' }}
</button>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { loginSchema, type LoginInput } from '~~/utils/validations';
import Swal from 'sweetalert2';
definePageMeta({
middleware: 'guest-only',
auth: { unauthenticatedOnly: true, navigateAuthenticatedTo: '/' }
});
const { signIn } = useAuth();
const router = useRouter();
// Reactive form state
const form = reactive<LoginInput>({
email: '',
password: ''
});
// Validation errors state
const errors = reactive<Partial<Record<keyof LoginInput, string>>>({});
const loading = ref(false);
const turnstileToken = ref('');
const validate = () => {
const result = loginSchema.safeParse(form);
// Clear previous errors
Object.keys(errors).forEach(key => delete errors[key as keyof LoginInput]);
if (!result.success) {
result.error.errors.forEach(err => {
if (err.path[0]) {
errors[err.path[0] as keyof LoginInput] = err.message;
}
});
return false;
}
return true;
};
const handleLogin = async () => {
if (!validate()) return;
if (!turnstileToken.value) {
Swal.fire({
icon: 'warning',
title: 'Güvenlik Kontrolü',
text: 'Lütfen Turnstile güvenlik kontrolünü tamamlayın.',
timer: 3000,
toast: true,
position: 'top-end',
showConfirmButton: false
});
return;
}
loading.value = true;
try {
const result = await signIn('credentials', {
email: form.email,
password: form.password,
redirect: false,
});
if (result?.error) {
Swal.fire({
icon: 'error',
title: 'Giriş Başarısız',
text: 'E-posta veya şifre hatalı.',
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000
});
} else {
Swal.fire({
icon: 'success',
title: 'Giriş Başarılı',
text: 'Yönlendiriliyorsunuz...',
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 1500
});
setTimeout(() => {
router.push('/');
}, 1000);
}
} catch (error) {
console.error(error);
Swal.fire({
icon: 'error',
title: 'Hata',
text: 'Bir şeyler ters gitti, lütfen tekrar deneyin.',
});
} finally {
loading.value = false;
}
};
</script>
<style scoped>
.login-area {
background-color: #f8f9fa;
min-height: 80vh;
display: flex;
align-items: center;
}
.login-form-wrap {
border-top: 5px solid #0d6efd;
}
</style>