export interface LoginRequest { email: string; password: string; } // API Response structure (from backend) - new format: only token/refreshToken export interface ApiLoginResponse { token: string; refreshToken: string; } // JWT Payload structure (decoded from token) export interface JwtPayload { id: number; username: string; email: string; roleCode: string; iat: number; exp: number; } // Frontend User structure export interface LoginResponse { token: string; refreshToken: string; user: { id: string; email: string; firstName: string; lastName: string; role: string; avatarUrl?: string | null; }; message?: string; } export interface ApiResponse { code: number; message: string; data: T; } /** * Decode JWT payload without verification (read-only) * Verification is handled by the backend on each request */ function decodeJwtPayload(token: string): JwtPayload { const base64Url = token.split('.')[1]; const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); const jsonPayload = decodeURIComponent( atob(base64).split('').map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2) ).join('') ); return JSON.parse(jsonPayload); } export const authService = { async login(email: string, password: string): Promise { const config = useRuntimeConfig(); try { const response = await $fetch>('/api/auth/login', { method: 'POST', baseURL: config.public.apiBaseUrl as string, body: { email, password } }); const loginData = response.data; // Decode JWT to get user info const payload = decodeJwtPayload(loginData.token); // Check if user role is STUDENT - block login if (payload.roleCode === 'STUDENT') { throw new Error('ไม่สามารถเข้าสู่ระบบได้ ระบบนี้สำหรับผู้สอนและผู้ดูแลระบบเท่านั้น'); } // Return basic user info from JWT payload // Full profile will be fetched via fetchUserProfile() in the auth store return { token: loginData.token, refreshToken: loginData.refreshToken, user: { id: payload.id.toString(), email: payload.email, firstName: '', lastName: '', role: payload.roleCode, avatarUrl: null }, message: response.message || 'เข้าสู่ระบบสำเร็จ' }; } catch (error: any) { // Re-throw custom errors (like STUDENT role block) if (error.message && !error.response) { throw error; } // Handle API errors const apiError = error.data?.error || error.data; const errorMessage = apiError?.message || error.message; if (errorMessage) { throw new Error(errorMessage); } if (error.response?.status === 401) { throw new Error('อีเมลหรือรหัสผ่านไม่ถูกต้อง'); } throw new Error('เกิดข้อผิดพลาดในการเข้าสู่ระบบ'); } }, async logout(): Promise { // Clear cookies const tokenCookie = useCookie('token'); const refreshTokenCookie = useCookie('refreshToken'); const userCookie = useCookie('user'); tokenCookie.value = null; refreshTokenCookie.value = null; userCookie.value = null; }, async forgotPassword(email: string): Promise> { const config = useRuntimeConfig(); const response = await $fetch>('/api/auth/reset-request', { method: 'POST', baseURL: config.public.apiBaseUrl as string, body: { email } }); return response; }, async resetPassword(token: string, password: string): Promise { const config = useRuntimeConfig(); await $fetch('/api/auth/reset-password', { method: 'POST', baseURL: config.public.apiBaseUrl as string, body: { token, password } }); }, async registerInstructor(data: RegisterInstructorRequest): Promise { const config = useRuntimeConfig(); await $fetch('/api/auth/register-instructor', { method: 'POST', baseURL: config.public.apiBaseUrl as string, body: data }); }, async refreshToken(currentRefreshToken: string): Promise<{ token: string; refreshToken: string }> { const config = useRuntimeConfig(); if (!currentRefreshToken) { throw new Error('No refresh token available'); } const response = await $fetch<{ token: string; refreshToken: string }>('/api/auth/refresh', { method: 'POST', baseURL: config.public.apiBaseUrl as string, body: { refreshToken: currentRefreshToken } }); return response; }, async sendVerifyEmail(): Promise> { const config = useRuntimeConfig(); const token = useCookie('token').value; const response = await $fetch>('/api/user/send-verify-email', { method: 'POST', baseURL: config.public.apiBaseUrl as string, headers: { Authorization: `Bearer ${token}` } }); return response; }, async verifyEmail(verificationToken: string): Promise> { const config = useRuntimeConfig(); const token = useCookie('token').value; const response = await $fetch>('/api/user/verify-email', { method: 'POST', baseURL: config.public.apiBaseUrl as string, headers: { Authorization: `Bearer ${token}` }, body: { token: verificationToken } }); return response; } }; // Register Instructor Request export interface RegisterInstructorRequest { username: string; email: string; password: string; first_name: string; last_name: string; prefix: { en: string; th: string; }; phone: string; }