You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
4.2 KiB
162 lines
4.2 KiB
/**
|
|
* useActiveRole Composable
|
|
*
|
|
* Client-side state management for user's active role (RoleSwitcher)
|
|
*
|
|
* Features:
|
|
* - Reactive active role state
|
|
* - List of all roles with approval status
|
|
* - Switch role function with server validation
|
|
* - Admin change notification flag
|
|
*
|
|
* Usage:
|
|
* ```vue
|
|
* const { activeRole, roles, roleChangedByAdmin, switchRole, fetchRoleStatus } = useActiveRole()
|
|
*
|
|
* // Fetch current status (validates server-side)
|
|
* await fetchRoleStatus()
|
|
*
|
|
* // Switch role
|
|
* await switchRole('educator')
|
|
* ```
|
|
*/
|
|
|
|
export interface RoleWithStatus {
|
|
code: string
|
|
displayName: string
|
|
description: string
|
|
hasRole: boolean
|
|
requiresApproval: boolean
|
|
}
|
|
|
|
export function useActiveRole() {
|
|
// Use useState for shared state across the app
|
|
const activeRole = useState<string>('activeRole', () => 'private')
|
|
const roles = useState<RoleWithStatus[]>('roles', () => [])
|
|
const roleChangedByAdmin = useState<boolean>('roleChangedByAdmin', () => false)
|
|
const loading = useState<boolean>('roleLoading', () => false)
|
|
const error = useState<string | null>('roleError', () => null)
|
|
|
|
/**
|
|
* Fetch current role status from server
|
|
* - Validates active role (TTL-based)
|
|
* - Fetches all roles with approval status
|
|
* - Detects if admin changed user's roles
|
|
*/
|
|
async function fetchRoleStatus() {
|
|
loading.value = true
|
|
error.value = null
|
|
|
|
try {
|
|
const data = await $fetch('/api/user/role-status')
|
|
|
|
activeRole.value = data.activeRoleCode
|
|
roles.value = data.roles
|
|
roleChangedByAdmin.value = data.roleChangedByAdmin
|
|
|
|
return data
|
|
} catch (err: any) {
|
|
console.error('Failed to fetch role status:', err)
|
|
error.value = 'Fehler beim Laden der Rollen'
|
|
throw err
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Switch to a different role
|
|
* - Validates server-side that user has the role
|
|
* - Updates session + database
|
|
* - Refreshes products list if on products page
|
|
*
|
|
* @param roleCode - Role to switch to ('private', 'educator', 'company')
|
|
* @throws Error if user doesn't have the role or if switch fails
|
|
*/
|
|
async function switchRole(roleCode: string) {
|
|
loading.value = true
|
|
error.value = null
|
|
|
|
try {
|
|
await $fetch('/api/user/active-role', {
|
|
method: 'PATCH',
|
|
body: { roleCode },
|
|
})
|
|
|
|
// Update local state
|
|
activeRole.value = roleCode
|
|
roleChangedByAdmin.value = false
|
|
|
|
// Refresh all product list pages (role-based visibility)
|
|
// Note: Product detail pages will handle visibility via API 404 check
|
|
await Promise.all([
|
|
refreshNuxtData('products-list'), // Main products page
|
|
refreshNuxtData('educator-products'), // Educator products page
|
|
refreshNuxtData('experimenta-products'), // Experimenta products page
|
|
])
|
|
|
|
return true
|
|
} catch (err: any) {
|
|
console.error('Failed to switch role:', err)
|
|
error.value = err.data?.message || 'Fehler beim Wechseln der Rolle'
|
|
throw err
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reset all role state (called on logout)
|
|
*/
|
|
function resetRoles() {
|
|
activeRole.value = 'private'
|
|
roles.value = []
|
|
roleChangedByAdmin.value = false
|
|
loading.value = false
|
|
error.value = null
|
|
}
|
|
|
|
/**
|
|
* Get roles that user actually has (approved only)
|
|
*/
|
|
const approvedRoles = computed(() => roles.value.filter((r) => r.hasRole))
|
|
|
|
/**
|
|
* Check if user has multiple roles
|
|
*/
|
|
const hasMultipleRoles = computed(() => approvedRoles.value.length > 1)
|
|
|
|
/**
|
|
* Auto-fetch roles when user logs in
|
|
* This ensures the role button shows the correct role immediately after login
|
|
*/
|
|
const { loggedIn } = useUserSession()
|
|
|
|
// Initial fetch if already logged in
|
|
if (loggedIn.value) {
|
|
callOnce('init-roles', () => fetchRoleStatus())
|
|
}
|
|
|
|
// Watch for login changes - fetch roles when user logs in
|
|
watch(loggedIn, (newLoggedIn) => {
|
|
if (newLoggedIn) {
|
|
fetchRoleStatus()
|
|
}
|
|
})
|
|
|
|
return {
|
|
// State (useState already returns writable refs)
|
|
activeRole,
|
|
roles,
|
|
approvedRoles,
|
|
hasMultipleRoles,
|
|
roleChangedByAdmin,
|
|
loading,
|
|
error,
|
|
|
|
// Actions
|
|
fetchRoleStatus,
|
|
switchRole,
|
|
resetRoles,
|
|
}
|
|
}
|
|
|