feat: implement user authentication, profile management, and email verification with i18n support

This commit is contained in:
supalerk-ar66 2026-02-03 11:01:33 +07:00
parent 06db182c46
commit b2365a4c6a
6 changed files with 271 additions and 17 deletions

View file

@ -4,6 +4,7 @@ interface User {
id: number
username: string
email: string
email_verified_at?: string | null
created_at?: string
updated_at?: string
role: {
@ -19,6 +20,8 @@ interface User {
}
}
// Interface สำหรับข้อมูลตอบกลับตอน Login
interface loginResponse {
token: string
@ -367,8 +370,13 @@ export const useAuth = () => {
const sendVerifyEmail = async () => {
if (!token.value) return { success: false, error: 'Token missing' }
interface VerifyEmailResponse {
code: number
message: string
}
const doSend = async () => {
return await $fetch<{code: number, message: string}>(`${API_BASE_URL}/user/send-verify-email`, {
return await $fetch<VerifyEmailResponse>(`${API_BASE_URL}/user/send-verify-email`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token.value}`
@ -378,7 +386,7 @@ export const useAuth = () => {
try {
const res = await doSend()
return { success: true, message: res.message }
return { success: true, message: res.message, code: res.code }
} catch (err: any) {
if (err.statusCode === 400) {
return { success: false, error: 'Email already verified', code: 400 }
@ -388,7 +396,7 @@ export const useAuth = () => {
if (refreshed) {
try {
const res = await doSend()
return { success: true, message: res.message }
return { success: true, message: res.message, code: res.code }
} catch (retryErr: any) {
return { success: false, error: retryErr.data?.message || 'Failed to send verification email' }
}
@ -401,6 +409,43 @@ export const useAuth = () => {
}
}
// ฟังก์ชันยืนยันอีเมลด้วย Token
const verifyEmail = async (token: string) => {
try {
interface VerifyResponse {
code: number
message: string
}
const res = await $fetch<VerifyResponse>(`${API_BASE_URL}/user/verify-email`, {
method: 'POST',
body: { token }
})
// Handle HTTP 200 but logical error if API behaves that way (defensive)
if (res && typeof res.code === 'number' && res.code !== 200) {
return {
success: false,
message: res.message,
code: res.code,
error: res.message
}
}
return { success: true, message: res.message, code: res.code }
} catch (err: any) {
// Prioritize backend 'code' field, then HTTP status
const status = err.data?.code || err.statusCode || err.response?.status || err.status
return {
success: false,
error: err.data?.message || err.message || 'Verification failed',
code: status
}
}
}
// ฟังก์ชันออกจากระบบ (Logout)
const logout = () => {
token.value = null
@ -427,6 +472,7 @@ export const useAuth = () => {
firstName,
lastName,
email: user.value.email,
emailVerifiedAt: user.value.email_verified_at,
phone: user.value.profile?.phone || '',
photoURL: user.value.profile?.avatar_url || '',
role: user.value.role,
@ -443,6 +489,7 @@ export const useAuth = () => {
uploadAvatar,
refreshAccessToken,
logout,
sendVerifyEmail
sendVerifyEmail,
verifyEmail
}
}