feat: Add course detail page, authentication composable, and course browsing page.

This commit is contained in:
supalerk-ar66 2026-01-21 10:02:37 +07:00
parent 1e06041769
commit 327f6ec7b5
3 changed files with 230 additions and 115 deletions

View file

@ -69,26 +69,22 @@ export const useAuth = () => {
// Login
const login = async (credentials: { email: string; password: string }) => {
try {
const { data, error } = await useFetch<loginResponse>(`${API_BASE_URL}/auth/login`, {
const data = await $fetch<loginResponse>(`${API_BASE_URL}/auth/login`, {
method: 'POST',
body: credentials
})
if (error.value) {
throw error.value
}
if (data.value) {
if (data) {
// Validation: Only allow STUDENT role to login
if (data.value.user.role.code !== 'STUDENT') {
if (data.user.role.code !== 'STUDENT') {
return { success: false, error: 'Email ไม่ถูกต้อง' }
}
token.value = data.value.token
refreshToken.value = data.value.refreshToken // Save refresh token
token.value = data.token
refreshToken.value = data.refreshToken // Save refresh token
// The API returns the profile nested inside the user object
user.value = data.value.user
user.value = data.user
return { success: true }
}
@ -105,16 +101,12 @@ export const useAuth = () => {
// Register
const register = async (payload: RegisterPayload) => {
try {
const { data, error } = await useFetch(`${API_BASE_URL}/auth/register`, {
const data = await $fetch(`${API_BASE_URL}/auth/register`, {
method: 'POST',
body: payload
})
if (error.value) {
throw error.value
}
return { success: true, data: data.value }
return { success: true, data }
} catch (err: any) {
console.error('Register failed:', err)
@ -130,42 +122,41 @@ export const useAuth = () => {
if (!token.value) return
try {
const { data, error } = await useFetch<User>(`${API_BASE_URL}/user/me`, {
const data = await $fetch<User>(`${API_BASE_URL}/user/me`, {
headers: {
Authorization: `Bearer ${token.value}`
}
})
if (error.value) {
if (error.value.statusCode === 401) {
// Try to refresh token
const refreshed = await refreshAccessToken()
if (refreshed) {
// Retry fetch with new token
const { data: retryData, error: retryError } = await useFetch<User>(`${API_BASE_URL}/user/me`, {
if (data) {
user.value = data
}
} catch (error: any) {
if (error.statusCode === 401) {
// Try to refresh token
const refreshed = await refreshAccessToken()
if (refreshed) {
// Retry fetch with new token
try {
const retryData = await $fetch<User>(`${API_BASE_URL}/user/me`, {
headers: {
Authorization: `Bearer ${token.value}`
}
})
if (retryData.value) {
user.value = retryData.value
if (retryData) {
user.value = retryData
return
}
if (retryError.value) throw retryError.value
} else {
logout()
}
}
throw error.value
} catch (retryErr) {
console.error('Failed to fetch user profile after refresh:', retryErr)
}
} else {
logout()
}
} else {
console.error('Failed to fetch user profile:', error)
}
if (data.value) {
user.value = data.value
}
} catch (err) {
console.error('Failed to fetch user profile:', err)
}
}
@ -179,7 +170,7 @@ export const useAuth = () => {
if (!token.value) return
try {
const { error } = await useFetch(`${API_BASE_URL}/user/me`, {
await $fetch(`${API_BASE_URL}/user/me`, {
method: 'PUT',
headers: {
Authorization: `Bearer ${token.value}`
@ -187,8 +178,6 @@ export const useAuth = () => {
body: payload
})
if (error.value) throw error.value
// If successful, refresh the local user data
await fetchUserProfile()
@ -202,12 +191,11 @@ export const useAuth = () => {
// Request Password Reset
const requestPasswordReset = async (email: string) => {
try {
const { error } = await useFetch(`${API_BASE_URL}/auth/reset-request`, {
await $fetch(`${API_BASE_URL}/auth/reset-request`, {
method: 'POST',
body: { email }
})
if (error.value) throw error.value
return { success: true }
} catch (err: any) {
return { success: false, error: err.data?.message || 'ส่งคำขอไม่สำเร็จ' }
@ -217,12 +205,11 @@ export const useAuth = () => {
// Confirm Reset Password
const confirmResetPassword = async (payload: { token: string; password: string }) => {
try {
const { error } = await useFetch(`${API_BASE_URL}/auth/reset-password`, {
await $fetch(`${API_BASE_URL}/auth/reset-password`, {
method: 'POST',
body: payload
})
if (error.value) throw error.value
return { success: true }
} catch (err: any) {
return { success: false, error: err.data?.message || 'รีเซ็ตรหัสผ่านไม่สำเร็จ' }
@ -234,7 +221,7 @@ export const useAuth = () => {
if (!token.value) return { success: false, error: 'ไม่พบ Token การใช้งาน' }
try {
const { data, error } = await useFetch(`${API_BASE_URL}/user/change-password`, {
await $fetch(`${API_BASE_URL}/user/change-password`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token.value}`
@ -242,7 +229,6 @@ export const useAuth = () => {
body: payload
})
if (error.value) throw error.value
return { success: true }
} catch (err: any) {
return { success: false, error: err.data?.message || 'เปลี่ยนรหัสผ่านไม่สำเร็จ' }
@ -254,16 +240,14 @@ export const useAuth = () => {
if (!refreshToken.value) return false
try {
const { data, error } = await useFetch<{ token: string; refreshToken: string }>(`${API_BASE_URL}/auth/refresh`, {
const data = await $fetch<{ token: string; refreshToken: string }>(`${API_BASE_URL}/auth/refresh`, {
method: 'POST',
body: { refreshToken: refreshToken.value }
})
if (error.value) throw error.value
if (data.value) {
token.value = data.value.token
refreshToken.value = data.value.refreshToken
if (data) {
token.value = data.token
refreshToken.value = data.refreshToken
return true
}
} catch (err) {