121 lines
3.5 KiB
TypeScript
121 lines
3.5 KiB
TypeScript
import { defineStore } from 'pinia'
|
|
import { ref, computed } from 'vue'
|
|
import { post, get } from '../api/client'
|
|
import type { User, LoginRequest, LoginResponse, UserProfileResponse } from '../types'
|
|
import router from '../router'
|
|
|
|
export function getDefaultRouteForRole(role: string): string {
|
|
switch (role) {
|
|
case 'INTAKE_CLERK':
|
|
return '/intake'
|
|
case 'DATA_ENTRY_CLERK':
|
|
return '/entry'
|
|
case 'VERIFIER':
|
|
case 'CLINICAL_APPROVER':
|
|
return '/verification'
|
|
case 'ADMINISTRATOR':
|
|
return '/dashboard'
|
|
default:
|
|
return '/login'
|
|
}
|
|
}
|
|
|
|
export const useAuthStore = defineStore('auth', () => {
|
|
const token = ref<string | null>(localStorage.getItem('vigilcare_token'))
|
|
const refreshToken = ref<string | null>(localStorage.getItem('vigilcare_refresh_token'))
|
|
const user = ref<User | null>(
|
|
JSON.parse(localStorage.getItem('vigilcare_user') || 'null')
|
|
)
|
|
|
|
const isAuthenticated = computed(() => !!token.value)
|
|
const userRole = computed(() => user.value?.role ?? '')
|
|
const userId = computed(() => user.value?.id ?? '')
|
|
const userFullName = computed(() => user.value?.fullName ?? '')
|
|
|
|
// Role-based view access
|
|
const canIntake = computed(() =>
|
|
['INTAKE_CLERK', 'ADMINISTRATOR'].includes(userRole.value)
|
|
)
|
|
const canEntry = computed(() =>
|
|
['DATA_ENTRY_CLERK', 'ADMINISTRATOR'].includes(userRole.value)
|
|
)
|
|
const canVerify = computed(() =>
|
|
['VERIFIER', 'CLINICAL_APPROVER', 'ADMINISTRATOR'].includes(userRole.value)
|
|
)
|
|
const canSupervise = computed(() =>
|
|
['ADMINISTRATOR'].includes(userRole.value)
|
|
)
|
|
|
|
async function login(credentials: LoginRequest): Promise<void> {
|
|
const response = await post<LoginResponse>('auth/login', credentials)
|
|
|
|
if (!response.success || !response.data) {
|
|
throw new Error(response.error?.message ?? 'Login failed')
|
|
}
|
|
|
|
const loginData = response.data
|
|
|
|
token.value = loginData.token
|
|
refreshToken.value = loginData.refreshToken
|
|
user.value = {
|
|
id: loginData.userId,
|
|
username: loginData.username,
|
|
fullName: loginData.fullName,
|
|
role: loginData.role,
|
|
}
|
|
|
|
localStorage.setItem('vigilcare_token', loginData.token)
|
|
localStorage.setItem('vigilcare_refresh_token', loginData.refreshToken)
|
|
localStorage.setItem('vigilcare_user', JSON.stringify(user.value))
|
|
|
|
router.push(getDefaultRouteForRole(loginData.role))
|
|
}
|
|
|
|
async function fetchCurrentUser(): Promise<void> {
|
|
const response = await get<UserProfileResponse>('auth/me')
|
|
if (response.success && response.data) {
|
|
user.value = {
|
|
id: response.data.id,
|
|
username: response.data.username,
|
|
fullName: response.data.fullName,
|
|
role: response.data.role,
|
|
}
|
|
localStorage.setItem('vigilcare_user', JSON.stringify(user.value))
|
|
}
|
|
}
|
|
|
|
async function logout(): Promise<void> {
|
|
if (refreshToken.value) {
|
|
try {
|
|
await post<void>('auth/logout', { refreshToken: refreshToken.value })
|
|
} catch {
|
|
// Still clear local session if server revoke fails
|
|
}
|
|
}
|
|
|
|
token.value = null
|
|
refreshToken.value = null
|
|
user.value = null
|
|
localStorage.removeItem('vigilcare_token')
|
|
localStorage.removeItem('vigilcare_refresh_token')
|
|
localStorage.removeItem('vigilcare_user')
|
|
router.push('/login')
|
|
}
|
|
|
|
return {
|
|
token,
|
|
refreshToken,
|
|
user,
|
|
isAuthenticated,
|
|
userRole,
|
|
userId,
|
|
userFullName,
|
|
canIntake,
|
|
canEntry,
|
|
canVerify,
|
|
canSupervise,
|
|
login,
|
|
fetchCurrentUser,
|
|
logout,
|
|
}
|
|
}) |