feat: Implement authentication system with token refresh and initial instructor dashboard with course management.
This commit is contained in:
parent
0eb9b522f6
commit
ab3124628c
11 changed files with 1053 additions and 93 deletions
|
|
@ -70,10 +70,12 @@ export const useAuthStore = defineStore('auth', {
|
|||
userCookie.value = null;
|
||||
},
|
||||
|
||||
checkAuth() {
|
||||
async checkAuth() {
|
||||
const tokenCookie = useCookie('token');
|
||||
const userCookie = useCookie('user');
|
||||
const refreshTokenCookie = useCookie('refreshToken');
|
||||
|
||||
// Case 1: Have token and user - restore auth state
|
||||
if (tokenCookie.value && userCookie.value) {
|
||||
this.token = tokenCookie.value;
|
||||
try {
|
||||
|
|
@ -81,11 +83,45 @@ export const useAuthStore = defineStore('auth', {
|
|||
? JSON.parse(userCookie.value)
|
||||
: userCookie.value;
|
||||
this.isAuthenticated = true;
|
||||
return;
|
||||
} catch (e) {
|
||||
// Invalid user data
|
||||
this.logout();
|
||||
}
|
||||
}
|
||||
|
||||
// Case 2: No token but have refresh token - try to refresh
|
||||
if (!tokenCookie.value && refreshTokenCookie.value && userCookie.value) {
|
||||
// Get cookie refs with options BEFORE await to maintain Nuxt context
|
||||
const tokenCookieWithOptions = useCookie('token', {
|
||||
maxAge: 60 * 60 * 24, // 24 hours
|
||||
sameSite: 'strict'
|
||||
});
|
||||
const refreshTokenCookieWithOptions = useCookie('refreshToken', {
|
||||
maxAge: 60 * 60 * 24 * 7, // 7 days
|
||||
sameSite: 'strict'
|
||||
});
|
||||
const currentRefreshToken = refreshTokenCookie.value;
|
||||
|
||||
try {
|
||||
console.log('Token missing, attempting refresh...');
|
||||
const newTokens = await authService.refreshToken(currentRefreshToken);
|
||||
|
||||
// Update cookies with new tokens
|
||||
tokenCookieWithOptions.value = newTokens.token;
|
||||
refreshTokenCookieWithOptions.value = newTokens.refreshToken;
|
||||
|
||||
this.token = newTokens.token;
|
||||
this.user = typeof userCookie.value === 'string'
|
||||
? JSON.parse(userCookie.value)
|
||||
: userCookie.value;
|
||||
this.isAuthenticated = true;
|
||||
console.log('Token refreshed successfully');
|
||||
} catch (e) {
|
||||
console.error('Token refresh failed');
|
||||
this.logout();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import { defineStore } from 'pinia';
|
||||
import { instructorService } from '~/services/instructor.service';
|
||||
|
||||
interface Course {
|
||||
id: string;
|
||||
id: number;
|
||||
title: string;
|
||||
students: number;
|
||||
lessons: number;
|
||||
icon: string;
|
||||
thumbnail: string | null;
|
||||
}
|
||||
|
||||
interface DashboardStats {
|
||||
|
|
@ -17,27 +19,13 @@ interface DashboardStats {
|
|||
export const useInstructorStore = defineStore('instructor', {
|
||||
state: () => ({
|
||||
stats: {
|
||||
totalCourses: 5,
|
||||
totalStudents: 125,
|
||||
completedStudents: 45
|
||||
totalCourses: 0,
|
||||
totalStudents: 0,
|
||||
completedStudents: 0
|
||||
} as DashboardStats,
|
||||
|
||||
recentCourses: [
|
||||
{
|
||||
id: '1',
|
||||
title: 'Python เบื้องต้น',
|
||||
students: 45,
|
||||
lessons: 8,
|
||||
icon: '📘'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
title: 'JavaScript สำหรับเว็บ',
|
||||
students: 32,
|
||||
lessons: 12,
|
||||
icon: '📗'
|
||||
}
|
||||
] as Course[]
|
||||
recentCourses: [] as Course[],
|
||||
loading: false
|
||||
}),
|
||||
|
||||
getters: {
|
||||
|
|
@ -47,14 +35,31 @@ export const useInstructorStore = defineStore('instructor', {
|
|||
|
||||
actions: {
|
||||
async fetchDashboardData() {
|
||||
// TODO: Replace with real API call
|
||||
// const { $api } = useNuxtApp();
|
||||
// const data = await $api('/instructor/dashboard');
|
||||
// this.stats = data.stats;
|
||||
// this.recentCourses = data.recentCourses;
|
||||
this.loading = true;
|
||||
try {
|
||||
// Fetch real courses from API
|
||||
const courses = await instructorService.getCourses();
|
||||
|
||||
// Using mock data for now
|
||||
console.log('Using mock data for instructor dashboard');
|
||||
// Update stats
|
||||
this.stats.totalCourses = courses.length;
|
||||
// TODO: Get real student counts from API when available
|
||||
this.stats.totalStudents = 0;
|
||||
this.stats.completedStudents = 0;
|
||||
|
||||
// Map to recent courses format (take first 5)
|
||||
this.recentCourses = courses.slice(0, 3).map((course, index) => ({
|
||||
id: course.id,
|
||||
title: course.title.th,
|
||||
students: 0, // TODO: Get from API
|
||||
lessons: 0, // TODO: Get from course detail API
|
||||
icon: ['📘', '📗', '📙', '📕', '📒'][index % 5],
|
||||
thumbnail: course.thumbnail_url || null
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch dashboard data:', error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue