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.
 
 
 

169 lines
4.5 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) {
// 401 during session initialization is normal - watch() will retry successfully
if (err.statusCode === 401) {
console.debug('Role status fetch: Session not ready yet, will retry via watch()')
return null
}
// Other errors are real problems
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,
}
}