Files
calebburke.dev/web/src/use/use-current-user.ts
T
2026-07-17 04:39:18 -07:00

90 lines
2.3 KiB
TypeScript

import { computed, reactive, toRefs } from "vue"
import { DateTime } from "luxon"
import { isNil, isNull, isUndefined } from "lodash"
import currentUserApi, { UserRoles, type UserAsShow } from "@/api/current-user-api"
import { PreferenceKeys, PreferenceValueMap } from "@/api/users/preferences-api"
export { UserRoles, type UserAsShow }
// TODO: consider sending this with every api request?
export const CURRENT_USERS_TIMEZONE = DateTime.local().zoneName
// Global state
const state = reactive<{
currentUser: UserAsShow | null
isLoading: boolean
isErrored: boolean
isCached: boolean
}>({
currentUser: null,
isLoading: false,
isErrored: false,
isCached: false,
})
type State = typeof state
type LoadedState = Omit<State, "currentUser"> & {
currentUser: Exclude<State["currentUser"], null>
}
export function useCurrentUser<IsLoaded extends boolean = false>() {
type StateOrLoadedState = IsLoaded extends true ? LoadedState : State
const isReady = computed(() => state.isCached && !state.isLoading && !state.isErrored)
const isSystemAdmin = computed(() => {
return state.currentUser?.roles.includes(UserRoles.SYSTEM_ADMIN)
})
function getPreference<K extends PreferenceKeys>(key: K): PreferenceValueMap[K] | null {
if (isNull(state.currentUser)) return null
const { preferences } = state.currentUser
if (isUndefined(preferences)) return null
const preference = preferences.find((p) => p.key === key)
if (isNil(preference)) return null
return preference.value as PreferenceValueMap[K]
}
async function fetch(): Promise<UserAsShow> {
state.isLoading = true
try {
const { user } = await currentUserApi.get()
state.isErrored = false
state.currentUser = user
state.isCached = true
return user
} catch (error) {
console.error("Failed to fetch current user:", error)
state.isErrored = true
throw error
} finally {
state.isLoading = false
}
}
// Needs to be called during logout or current user will persist.
function reset() {
state.currentUser = null
state.isLoading = false
state.isErrored = false
state.isCached = false
}
return {
...toRefs(state as StateOrLoadedState),
isReady,
fetch,
refresh: fetch,
reset,
// helpers
isSystemAdmin,
getPreference,
}
}
export default useCurrentUser