208 lines
6 KiB
TypeScript
208 lines
6 KiB
TypeScript
// API Response structure from /api/user/me
|
|
export interface UserProfileResponse {
|
|
id: number;
|
|
username: string;
|
|
email: string;
|
|
updated_at: string;
|
|
created_at: string;
|
|
role: {
|
|
code: string;
|
|
name: {
|
|
en: string;
|
|
th: string;
|
|
};
|
|
};
|
|
profile: {
|
|
prefix: {
|
|
en: string;
|
|
th: string;
|
|
};
|
|
first_name: string;
|
|
last_name: string;
|
|
avatar_url: string | null;
|
|
birth_date: string | null;
|
|
phone: string | null;
|
|
};
|
|
}
|
|
|
|
// Request body for PUT /api/user/me
|
|
export interface UpdateProfileRequest {
|
|
prefix?: {
|
|
en: string;
|
|
th: string;
|
|
};
|
|
first_name: string;
|
|
last_name: string;
|
|
phone?: string | null;
|
|
avatar_url?: string | null;
|
|
birth_date?: string | null;
|
|
}
|
|
|
|
// Mock profile data for development
|
|
const MOCK_PROFILES: Record<string, UserProfileResponse> = {
|
|
'admin@elearning.local': {
|
|
id: 1,
|
|
username: 'admin',
|
|
email: 'admin@elearning.local',
|
|
updated_at: '2024-01-01T00:00:00Z',
|
|
created_at: '2024-01-01T00:00:00Z',
|
|
role: {
|
|
code: 'ADMIN',
|
|
name: { en: 'Administrator', th: 'ผู้ดูแลระบบ' }
|
|
},
|
|
profile: {
|
|
prefix: { en: 'Mr.', th: 'นาย' },
|
|
first_name: 'ผู้ดูแล',
|
|
last_name: 'ระบบ',
|
|
avatar_url: null,
|
|
birth_date: null,
|
|
phone: '081-234-5678'
|
|
}
|
|
},
|
|
'instructor@elearning.local': {
|
|
id: 2,
|
|
username: 'instructor',
|
|
email: 'instructor@elearning.local',
|
|
updated_at: '2024-01-01T00:00:00Z',
|
|
created_at: '2024-01-01T00:00:00Z',
|
|
role: {
|
|
code: 'INSTRUCTOR',
|
|
name: { en: 'Instructor', th: 'ผู้สอน' }
|
|
},
|
|
profile: {
|
|
prefix: { en: 'Mr.', th: 'นาย' },
|
|
first_name: 'อาจารย์',
|
|
last_name: 'ทดสอบ',
|
|
avatar_url: null,
|
|
birth_date: null,
|
|
phone: '081-234-5678'
|
|
}
|
|
}
|
|
};
|
|
|
|
// Helper function to get auth token from cookie
|
|
const getAuthToken = (): string => {
|
|
const tokenCookie = useCookie('token');
|
|
return tokenCookie.value || '';
|
|
};
|
|
|
|
export const userService = {
|
|
async getProfile(): Promise<UserProfileResponse> {
|
|
const config = useRuntimeConfig();
|
|
const useMockData = config.public.useMockData as boolean;
|
|
|
|
if (useMockData) {
|
|
return this.mockGetProfile();
|
|
}
|
|
|
|
return this.apiGetProfile();
|
|
},
|
|
|
|
// Mock get profile
|
|
async mockGetProfile(): Promise<UserProfileResponse> {
|
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
|
|
const userCookie = useCookie('user');
|
|
if (!userCookie.value) throw new Error('User not found');
|
|
|
|
const user = typeof userCookie.value === 'string'
|
|
? JSON.parse(userCookie.value)
|
|
: userCookie.value;
|
|
const mockProfile = MOCK_PROFILES[user.email];
|
|
|
|
if (!mockProfile) {
|
|
throw new Error('Profile not found');
|
|
}
|
|
|
|
return mockProfile;
|
|
},
|
|
|
|
// Real API get profile
|
|
async apiGetProfile(): Promise<UserProfileResponse> {
|
|
const config = useRuntimeConfig();
|
|
const token = getAuthToken();
|
|
|
|
const response = await $fetch<UserProfileResponse>('/api/user/me', {
|
|
baseURL: config.public.apiBaseUrl as string,
|
|
headers: {
|
|
Authorization: `Bearer ${token}`
|
|
}
|
|
});
|
|
|
|
return response;
|
|
},
|
|
|
|
async updateProfile(data: UpdateProfileRequest): Promise<UserProfileResponse> {
|
|
const config = useRuntimeConfig();
|
|
const useMockData = config.public.useMockData as boolean;
|
|
|
|
if (useMockData) {
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
// In mock mode, just return the current profile with updates
|
|
const profile = await this.mockGetProfile();
|
|
return { ...profile, profile: { ...profile.profile, ...data } };
|
|
}
|
|
|
|
const token = getAuthToken();
|
|
const response = await $fetch<UserProfileResponse>('/api/user/me', {
|
|
method: 'PUT',
|
|
baseURL: config.public.apiBaseUrl as string,
|
|
headers: {
|
|
Authorization: `Bearer ${token}`
|
|
},
|
|
body: data
|
|
});
|
|
|
|
return response;
|
|
},
|
|
|
|
async changePassword(oldPassword: string, newPassword: string): Promise<void> {
|
|
const config = useRuntimeConfig();
|
|
const useMockData = config.public.useMockData as boolean;
|
|
|
|
if (useMockData) {
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
// In mock mode, just simulate success
|
|
return;
|
|
}
|
|
|
|
const token = getAuthToken();
|
|
await $fetch('/api/user/change-password', {
|
|
method: 'POST',
|
|
baseURL: config.public.apiBaseUrl as string,
|
|
headers: {
|
|
Authorization: `Bearer ${token}`
|
|
},
|
|
body: {
|
|
oldPassword,
|
|
newPassword
|
|
}
|
|
});
|
|
},
|
|
|
|
async uploadAvatar(file: File): Promise<{ avatar_url: string; id: number }> {
|
|
const config = useRuntimeConfig();
|
|
const useMockData = config.public.useMockData as boolean;
|
|
|
|
if (useMockData) {
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
// Return mock URL
|
|
return { avatar_url: URL.createObjectURL(file), id: 1 };
|
|
}
|
|
|
|
const token = getAuthToken();
|
|
const formData = new FormData();
|
|
formData.append('file', file);
|
|
|
|
const response = await $fetch<{ code: number; message: string; data: { avatar_url: string; id: number } }>('/api/user/upload-avatar', {
|
|
method: 'POST',
|
|
baseURL: config.public.apiBaseUrl as string,
|
|
headers: {
|
|
Authorization: `Bearer ${token}`
|
|
},
|
|
body: formData
|
|
});
|
|
|
|
return response.data;
|
|
}
|
|
};
|