Files
RenewCMS/web/src/composables/useUsers.ts
T

97 lines
2.0 KiB
TypeScript

import { useApi } from '@/composables/useApi'
import type { LinkableUser } from '@/lib/directoryTypes'
export type UserListItem =
| {
kind: 'user'
id: number
username: string
display_name: string
email: string
role: 'owner' | 'admin'
status: 'accepted'
created_at: string
}
| {
kind: 'invite'
id: number
email: string
display_name?: string
status: 'pending' | 'expired'
created_at: string
}
export const USER_SKELETON_ROWS = 5
export function userRowKey(kind: UserListItem['kind'], id: number) {
return `${kind}-${id}`
}
export function userDisplayName(item: UserListItem) {
return item.display_name ?? ''
}
export function userRole(item: UserListItem): 'owner' | 'admin' {
return item.kind === 'user' ? item.role : 'admin'
}
export interface CreatedInvite {
id: number
kind: 'invite'
email: string
status: 'pending'
created_at: string
expires_at: string
}
export function useUsers() {
const { request } = useApi()
function listUsers(): Promise<UserListItem[]> {
return request<UserListItem[]>('/v1/user/')
}
async function listLinkableUsers(
takenUserIds: ReadonlySet<number | null>,
): Promise<LinkableUser[]> {
const users = await listUsers()
return users.flatMap((user) =>
user.kind === 'user' && !takenUserIds.has(user.id)
? [
{
id: user.id,
label: user.display_name || user.username,
email: user.email,
},
]
: [],
)
}
function inviteUser(email: string): Promise<CreatedInvite> {
return request<CreatedInvite>('/v1/user/invite', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email }),
})
}
function cancelInvite(id: number): Promise<void> {
return request<void>(`/v1/user/invite/${id}`, { method: 'DELETE' })
}
function renewInvite(id: number): Promise<CreatedInvite> {
return request<CreatedInvite>(`/v1/user/invite/${id}/renew`, {
method: 'POST',
})
}
return {
listUsers,
listLinkableUsers,
inviteUser,
cancelInvite,
renewInvite,
}
}