Add team roles and content management updates
This commit is contained in:
@@ -0,0 +1,276 @@
|
||||
import { computed, onMounted, reactive, ref } from 'vue'
|
||||
|
||||
import { ApiRequestError, api } from '../../lib/api'
|
||||
import type { AdminTeamMember, AdminTeamPermission, AdminTeamRole } from '../../types/awards'
|
||||
|
||||
export interface TeamMemberForm {
|
||||
login: string
|
||||
displayName: string
|
||||
role: string
|
||||
isActive: boolean
|
||||
}
|
||||
|
||||
const emptyMemberForm = (): TeamMemberForm => ({
|
||||
login: '',
|
||||
displayName: '',
|
||||
role: 'member',
|
||||
isActive: true,
|
||||
})
|
||||
|
||||
export function useAdminTeamManager() {
|
||||
const loading = ref(true)
|
||||
const saving = ref(false)
|
||||
const errorMessage = ref('')
|
||||
const successMessage = ref('')
|
||||
const generatedPassword = ref('')
|
||||
const generatedPasswordLogin = ref('')
|
||||
const confirmDeleteMemberId = ref<number | null>(null)
|
||||
const members = ref<AdminTeamMember[]>([])
|
||||
const roles = ref<AdminTeamRole[]>([])
|
||||
const permissions = ref<AdminTeamPermission[]>([])
|
||||
const editingMemberId = ref<number | null>(null)
|
||||
const rolePermissionDrafts = ref<Record<string, string[]>>({})
|
||||
const savedRoleSnapshot = ref('')
|
||||
|
||||
const memberForm = reactive<TeamMemberForm>(emptyMemberForm())
|
||||
|
||||
const activeMembers = computed(() => members.value.filter((member) => member.isActive).length)
|
||||
const pendingPasswordChanges = computed(() => members.value.filter((member) => member.mustChangePassword).length)
|
||||
const roleOptions = computed(() => roles.value.map((role) => ({ value: role.key, label: role.label })))
|
||||
const selectedMember = computed(() => members.value.find((member) => member.id === editingMemberId.value) ?? null)
|
||||
const hasRoleChanges = computed(() =>
|
||||
Boolean(savedRoleSnapshot.value) && JSON.stringify(rolePermissionDrafts.value) !== savedRoleSnapshot.value,
|
||||
)
|
||||
|
||||
function resetMessages() {
|
||||
errorMessage.value = ''
|
||||
successMessage.value = ''
|
||||
}
|
||||
|
||||
function applyTeamResponse(response: { members: AdminTeamMember[]; roles: AdminTeamRole[]; permissions: AdminTeamPermission[] }) {
|
||||
members.value = response.members
|
||||
roles.value = response.roles
|
||||
permissions.value = response.permissions
|
||||
rolePermissionDrafts.value = Object.fromEntries(
|
||||
response.roles.map((role) => [role.key, [...role.permissionKeys]]),
|
||||
)
|
||||
savedRoleSnapshot.value = JSON.stringify(rolePermissionDrafts.value)
|
||||
}
|
||||
|
||||
async function loadTeam() {
|
||||
loading.value = true
|
||||
resetMessages()
|
||||
|
||||
try {
|
||||
applyTeamResponse(await api.getAdminTeam())
|
||||
} catch (error) {
|
||||
errorMessage.value = error instanceof ApiRequestError
|
||||
? error.message
|
||||
: 'Team-Daten konnten nicht geladen werden.'
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function startCreateMember() {
|
||||
editingMemberId.value = null
|
||||
Object.assign(memberForm, emptyMemberForm())
|
||||
generatedPassword.value = ''
|
||||
generatedPasswordLogin.value = ''
|
||||
resetMessages()
|
||||
}
|
||||
|
||||
function startEditMember(member: AdminTeamMember) {
|
||||
editingMemberId.value = member.id
|
||||
memberForm.login = member.login
|
||||
memberForm.displayName = member.displayName
|
||||
memberForm.role = member.role
|
||||
memberForm.isActive = member.isActive
|
||||
generatedPassword.value = ''
|
||||
generatedPasswordLogin.value = ''
|
||||
resetMessages()
|
||||
}
|
||||
|
||||
function validateMemberForm() {
|
||||
if (!memberForm.login.trim() && editingMemberId.value === null) {
|
||||
errorMessage.value = 'Bitte gib einen Login an.'
|
||||
return false
|
||||
}
|
||||
|
||||
if (!memberForm.displayName.trim()) {
|
||||
errorMessage.value = 'Bitte gib einen Anzeigenamen an.'
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
async function saveMember() {
|
||||
resetMessages()
|
||||
generatedPassword.value = ''
|
||||
generatedPasswordLogin.value = ''
|
||||
|
||||
if (!validateMemberForm()) return false
|
||||
|
||||
saving.value = true
|
||||
try {
|
||||
if (editingMemberId.value === null) {
|
||||
const result = await api.createAdminTeamMember({
|
||||
login: memberForm.login,
|
||||
displayName: memberForm.displayName,
|
||||
role: memberForm.role,
|
||||
})
|
||||
await loadTeam()
|
||||
generatedPassword.value = result.generatedPassword
|
||||
generatedPasswordLogin.value = memberForm.login
|
||||
successMessage.value = 'Team-Login wurde erstellt. Das temporäre Passwort ist nur jetzt sichtbar.'
|
||||
} else {
|
||||
await api.updateAdminTeamMember(editingMemberId.value, {
|
||||
login: memberForm.login,
|
||||
displayName: memberForm.displayName,
|
||||
role: memberForm.role,
|
||||
isActive: memberForm.isActive,
|
||||
})
|
||||
await loadTeam()
|
||||
successMessage.value = 'Team-Mitglied wurde gespeichert.'
|
||||
}
|
||||
return true
|
||||
} catch (error) {
|
||||
errorMessage.value = error instanceof ApiRequestError
|
||||
? error.message
|
||||
: 'Team-Mitglied konnte nicht gespeichert werden.'
|
||||
return false
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function resetMemberPassword(member: AdminTeamMember) {
|
||||
resetMessages()
|
||||
generatedPassword.value = ''
|
||||
generatedPasswordLogin.value = ''
|
||||
saving.value = true
|
||||
|
||||
try {
|
||||
const result = await api.resetAdminTeamMemberPassword(member.id)
|
||||
await loadTeam()
|
||||
generatedPassword.value = result.generatedPassword
|
||||
generatedPasswordLogin.value = member.login
|
||||
successMessage.value = 'Passwort wurde zurückgesetzt. Das Mitglied muss es beim nächsten Login ändern.'
|
||||
} catch (error) {
|
||||
errorMessage.value = error instanceof ApiRequestError
|
||||
? error.message
|
||||
: 'Passwort konnte nicht zurückgesetzt werden.'
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function requestDeleteMember(member: AdminTeamMember) {
|
||||
confirmDeleteMemberId.value = member.id
|
||||
resetMessages()
|
||||
}
|
||||
|
||||
function cancelDeleteMember() {
|
||||
confirmDeleteMemberId.value = null
|
||||
}
|
||||
|
||||
async function deleteMember(member: AdminTeamMember) {
|
||||
resetMessages()
|
||||
generatedPassword.value = ''
|
||||
generatedPasswordLogin.value = ''
|
||||
saving.value = true
|
||||
|
||||
try {
|
||||
await api.deleteAdminTeamMember(member.id)
|
||||
confirmDeleteMemberId.value = null
|
||||
if (editingMemberId.value === member.id) {
|
||||
startCreateMember()
|
||||
}
|
||||
await loadTeam()
|
||||
successMessage.value = 'Team-Mitglied wurde gelöscht.'
|
||||
} catch (error) {
|
||||
errorMessage.value = error instanceof ApiRequestError
|
||||
? error.message
|
||||
: 'Team-Mitglied konnte nicht gelöscht werden.'
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function roleHasPermission(roleKey: string, permissionKey: string) {
|
||||
return rolePermissionDrafts.value[roleKey]?.includes(permissionKey) ?? false
|
||||
}
|
||||
|
||||
function setRolePermission(roleKey: string, permissionKey: string, checked: boolean) {
|
||||
if (roleKey === 'owner') return
|
||||
|
||||
const current = new Set(rolePermissionDrafts.value[roleKey] ?? [])
|
||||
if (checked) {
|
||||
current.add(permissionKey)
|
||||
} else {
|
||||
current.delete(permissionKey)
|
||||
}
|
||||
|
||||
rolePermissionDrafts.value = {
|
||||
...rolePermissionDrafts.value,
|
||||
[roleKey]: [...current].sort(),
|
||||
}
|
||||
}
|
||||
|
||||
async function saveRolePermissions() {
|
||||
resetMessages()
|
||||
saving.value = true
|
||||
|
||||
try {
|
||||
const result = await api.updateAdminTeamRoles({
|
||||
roles: roles.value.map((role) => ({
|
||||
key: role.key,
|
||||
permissionKeys: rolePermissionDrafts.value[role.key] ?? [],
|
||||
})),
|
||||
})
|
||||
roles.value = result.roles
|
||||
savedRoleSnapshot.value = JSON.stringify(rolePermissionDrafts.value)
|
||||
successMessage.value = 'Rollen und Berechtigungen wurden gespeichert.'
|
||||
} catch (error) {
|
||||
errorMessage.value = error instanceof ApiRequestError
|
||||
? error.message
|
||||
: 'Berechtigungen konnten nicht gespeichert werden.'
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(loadTeam)
|
||||
|
||||
return {
|
||||
loading,
|
||||
saving,
|
||||
errorMessage,
|
||||
successMessage,
|
||||
generatedPassword,
|
||||
generatedPasswordLogin,
|
||||
confirmDeleteMemberId,
|
||||
members,
|
||||
roles,
|
||||
permissions,
|
||||
memberForm,
|
||||
editingMemberId,
|
||||
selectedMember,
|
||||
activeMembers,
|
||||
pendingPasswordChanges,
|
||||
roleOptions,
|
||||
hasRoleChanges,
|
||||
loadTeam,
|
||||
startCreateMember,
|
||||
startEditMember,
|
||||
saveMember,
|
||||
resetMemberPassword,
|
||||
requestDeleteMember,
|
||||
cancelDeleteMember,
|
||||
deleteMember,
|
||||
roleHasPermission,
|
||||
setRolePermission,
|
||||
saveRolePermissions,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user