first commit
This commit is contained in:
80
app/composables/useLogin.ts
Normal file
80
app/composables/useLogin.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import Swal from 'sweetalert2'
|
||||
import { loginSchema, getFirstZodError, getFieldErrors } from '~~/lib/validations/auth'
|
||||
|
||||
export function useLogin () {
|
||||
const { signIn } = useAuth()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const email = ref('')
|
||||
const password = ref('')
|
||||
const turnstileToken = ref<string | null>(null)
|
||||
const turnstileRef = ref<{ reset: () => void } | null>(null)
|
||||
const fieldError = ref<Record<string, string>>({})
|
||||
const loading = ref(false)
|
||||
|
||||
const callbackUrl = computed(() => (route.query.callbackUrl as string) || '/')
|
||||
|
||||
async function onSubmit () {
|
||||
fieldError.value = {}
|
||||
const parsed = loginSchema.safeParse({ email: email.value, password: password.value })
|
||||
if (!parsed.success) {
|
||||
fieldError.value = getFieldErrors(parsed.error)
|
||||
await Swal.fire({ icon: 'error', title: 'Doğrulama hatası', text: getFirstZodError(parsed.error) })
|
||||
return
|
||||
}
|
||||
if (!turnstileToken.value) {
|
||||
await Swal.fire({ icon: 'warning', title: 'Güvenlik doğrulaması', text: 'Lütfen güvenlik kutusunu işaretleyin.' })
|
||||
return
|
||||
}
|
||||
loading.value = true
|
||||
try {
|
||||
const result = await signIn('credentials', {
|
||||
email: email.value,
|
||||
password: password.value,
|
||||
turnstile_token: turnstileToken.value,
|
||||
callbackUrl: callbackUrl.value,
|
||||
})
|
||||
if (result?.error) {
|
||||
const msg = result.error === 'CredentialsSignin' ? 'E-posta veya şifre hatalı.' : String(result.error)
|
||||
await Swal.fire({ icon: 'error', title: 'Giriş başarısız', text: msg })
|
||||
turnstileRef.value?.reset()
|
||||
turnstileToken.value = null
|
||||
return
|
||||
}
|
||||
await Swal.fire({ icon: 'success', title: 'Giriş başarılı', timer: 1500, showConfirmButton: false })
|
||||
if (result?.url) await router.push(result.url)
|
||||
} catch (e: unknown) {
|
||||
const msg = e instanceof Error ? e.message : 'Giriş yapılamadı.'
|
||||
await Swal.fire({ icon: 'error', title: 'Hata', text: msg })
|
||||
turnstileRef.value?.reset()
|
||||
turnstileToken.value = null
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function signInWith (provider: 'github' | 'google') {
|
||||
loading.value = true
|
||||
try {
|
||||
await signIn(provider, { callbackUrl: callbackUrl.value })
|
||||
} catch (e: unknown) {
|
||||
const msg = e instanceof Error ? e.message : 'Giriş yapılamadı.'
|
||||
await Swal.fire({ icon: 'error', title: 'Hata', text: msg })
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
email,
|
||||
password,
|
||||
turnstileToken,
|
||||
turnstileRef,
|
||||
fieldError,
|
||||
loading,
|
||||
callbackUrl,
|
||||
onSubmit,
|
||||
signInWith,
|
||||
}
|
||||
}
|
||||
116
app/composables/useRegister.ts
Normal file
116
app/composables/useRegister.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import Swal from 'sweetalert2'
|
||||
import type { RegisterResponse, RegisterRequestWithTurnstile } from '~~/lib/types/auth'
|
||||
import { registerSchema, getFirstZodError, getFieldErrors } from '~~/lib/validations/auth'
|
||||
|
||||
export function useRegister () {
|
||||
const { signIn } = useAuth()
|
||||
const route = useRoute()
|
||||
|
||||
const email = ref('')
|
||||
const first_name = ref('')
|
||||
const last_name = ref('')
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
const password_confirm = ref('')
|
||||
const turnstileToken = ref<string | null>(null)
|
||||
const turnstileRef = ref<{ reset: () => void } | null>(null)
|
||||
const fieldError = ref<Record<string, string>>({})
|
||||
const success = ref('')
|
||||
const loading = ref(false)
|
||||
const resendLoading = ref(false)
|
||||
const resendSent = ref(false)
|
||||
|
||||
const callbackUrl = computed(() => (route.query.callbackUrl as string) || '/')
|
||||
|
||||
async function onSubmit () {
|
||||
fieldError.value = {}
|
||||
const parsed = registerSchema.safeParse({
|
||||
email: email.value,
|
||||
first_name: first_name.value,
|
||||
last_name: last_name.value,
|
||||
username: username.value,
|
||||
password: password.value,
|
||||
password_confirm: password_confirm.value,
|
||||
})
|
||||
if (!parsed.success) {
|
||||
fieldError.value = getFieldErrors(parsed.error)
|
||||
await Swal.fire({ icon: 'error', title: 'Doğrulama hatası', text: getFirstZodError(parsed.error) })
|
||||
return
|
||||
}
|
||||
if (!turnstileToken.value) {
|
||||
await Swal.fire({ icon: 'warning', title: 'Güvenlik doğrulaması', text: 'Lütfen güvenlik kutusunu işaretleyin.' })
|
||||
return
|
||||
}
|
||||
loading.value = true
|
||||
try {
|
||||
const body: RegisterRequestWithTurnstile = {
|
||||
email: email.value,
|
||||
first_name: first_name.value,
|
||||
last_name: last_name.value,
|
||||
username: username.value,
|
||||
password: password.value,
|
||||
turnstile_token: turnstileToken.value,
|
||||
}
|
||||
const data = await $fetch<RegisterResponse>('/api/auth/register', { method: 'POST', body })
|
||||
success.value = data.message
|
||||
await Swal.fire({ icon: 'success', title: 'Kayıt başarılı', text: data.message })
|
||||
} catch (e: unknown) {
|
||||
const err = e as { data?: { message?: string; detail?: string | string[] }; message?: string }
|
||||
const msg = err?.data?.message ?? err?.data?.detail ?? err?.message ?? 'Kayıt yapılamadı.'
|
||||
const text = Array.isArray(msg) ? msg.join(' ') : String(msg)
|
||||
await Swal.fire({ icon: 'error', title: 'Kayıt hatası', text })
|
||||
turnstileRef.value?.reset()
|
||||
turnstileToken.value = null
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function resendVerification () {
|
||||
resendLoading.value = true
|
||||
try {
|
||||
await $fetch<{ message: string }>('/api/auth/resend-verification', {
|
||||
method: 'POST',
|
||||
body: { email: email.value },
|
||||
})
|
||||
resendSent.value = true
|
||||
await Swal.fire({ icon: 'success', text: 'Doğrulama e-postası gönderildi.', timer: 2000, showConfirmButton: false })
|
||||
} catch {
|
||||
await Swal.fire({ icon: 'error', text: 'E-posta gönderilemedi.' })
|
||||
} finally {
|
||||
resendLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function signInWith (provider: 'github' | 'google') {
|
||||
loading.value = true
|
||||
try {
|
||||
await signIn(provider, { callbackUrl: callbackUrl.value })
|
||||
} catch (e: unknown) {
|
||||
const msg = e instanceof Error ? e.message : 'Giriş yapılamadı.'
|
||||
await Swal.fire({ icon: 'error', title: 'Hata', text: msg })
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
email,
|
||||
first_name,
|
||||
last_name,
|
||||
username,
|
||||
password,
|
||||
password_confirm,
|
||||
turnstileToken,
|
||||
turnstileRef,
|
||||
fieldError,
|
||||
success,
|
||||
loading,
|
||||
resendLoading,
|
||||
resendSent,
|
||||
callbackUrl,
|
||||
onSubmit,
|
||||
resendVerification,
|
||||
signInWith,
|
||||
}
|
||||
}
|
||||
38
app/composables/useTurnstileScale.ts
Normal file
38
app/composables/useTurnstileScale.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { onBeforeUnmount, onMounted, type Ref } from 'vue'
|
||||
|
||||
/** Cloudflare Turnstile varsayılan genişliği (px) */
|
||||
const TURNSTILE_WIDTH = 300
|
||||
|
||||
/**
|
||||
* Turnstile widget'ı sarmalayan elementin genişliğine göre --turnstile-scale CSS değişkenini günceller.
|
||||
* Böylece widget form alanı genişliğinde görünür.
|
||||
*/
|
||||
export function useTurnstileScale(wrapperRef: Ref<HTMLElement | null>) {
|
||||
function updateScale() {
|
||||
const el = wrapperRef.value
|
||||
if (!el) return
|
||||
const w = el.offsetWidth
|
||||
if (w > 0) {
|
||||
const scale = w / TURNSTILE_WIDTH
|
||||
el.style.setProperty('--turnstile-scale', String(scale))
|
||||
}
|
||||
}
|
||||
|
||||
let observer: ResizeObserver | null = null
|
||||
|
||||
onMounted(() => {
|
||||
updateScale()
|
||||
const el = wrapperRef.value
|
||||
if (el && typeof ResizeObserver !== 'undefined') {
|
||||
observer = new ResizeObserver(updateScale)
|
||||
observer.observe(el)
|
||||
}
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (observer && wrapperRef.value) {
|
||||
observer.unobserve(wrapperRef.value)
|
||||
observer = null
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user