diff --git a/management-ui/src/customcompometns/AdminUserDropdonw.vue b/management-ui/src/customcompometns/AdminUserDropdonw.vue index 9b8d85b..faa189f 100644 --- a/management-ui/src/customcompometns/AdminUserDropdonw.vue +++ b/management-ui/src/customcompometns/AdminUserDropdonw.vue @@ -14,11 +14,13 @@ const props = defineProps<{ row: Users }>() // ← accept full row const emit = defineEmits<{ (e: 'deleted', id: string): void (e: 'error', err: unknown): void + (e: 'updated', payload: { id: string; username: string; role: 'admin' | 'user' }): void }>() const isEditOpen = ref(false) const isDeleteOpen = ref(false) const deleting = ref(false) +const updating = ref(false) async function onDeleteConfirmed() { try { @@ -34,8 +36,50 @@ async function onDeleteConfirmed() { } } -function onEditConfirm() { - isEditOpen.value = false +async function onEditConfirm(payload: { username: string; password?: string; role: 'admin' | 'user' }) { + try { + updating.value = true + + // Build UpdateUserDto payload + const body: { + username?: string + password?: string + role?: 'admin' | 'user' + } = {} + + // Only include fields that really changed / are provided + if (payload.username && payload.username !== props.row.username) { + body.username = payload.username + } + if (payload.password) { + body.password = payload.password + } + if (payload.role && payload.role !== props.row.role) { + body.role = payload.role + } + + // If nothing changed, skip request + if (Object.keys(body).length === 0) { + return + } + + await api.put( + `/users/${encodeURIComponent(String(props.row.id))}`, + body + ) + + emit('updated', { + id: String(props.row.id), + username: payload.username || props.row.username, + role: payload.role || (props.row.role as 'admin' | 'user'), + }) + } catch (err) { + console.error(err) + emit('error', err) + } finally { + updating.value = false + // dialog is already closed in EditUserDialog via v-model update + } } @@ -55,6 +99,6 @@ function onEditConfirm() { - + diff --git a/management-ui/src/customcompometns/EditUserDialog.vue b/management-ui/src/customcompometns/EditUserDialog.vue index 84f2f7a..9130178 100644 --- a/management-ui/src/customcompometns/EditUserDialog.vue +++ b/management-ui/src/customcompometns/EditUserDialog.vue @@ -11,8 +11,9 @@ import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Switch } from '@/components/ui/switch' -import { defineProps, defineEmits } from 'vue' +import { defineProps, defineEmits, reactive, watch } from 'vue' import type { PropType } from 'vue' +import type { Users } from '@/lib/interfaces' // 1) runtime props so Vue + TS agree const props = defineProps({ @@ -20,26 +21,58 @@ const props = defineProps({ type: Boolean as PropType, required: true, }, + user: { + type: Object as PropType, + required: true, + }, }) // 2) two emits: v-model and confirm const emit = defineEmits<{ + ( + e: 'confirm', + payload: { username: string; password?: string; role: 'admin' | 'user' } + ): void (e: 'update:modelValue', v: boolean): void - (e: 'confirm'): void }>() +const form = reactive({ + username: '', + password: '', + isAdmin: false, +}) + +// when dialog opens or user changes – sync form with props.user +watch( + () => [props.modelValue, props.user], + () => { + if (props.modelValue && props.user) { + form.username = props.user.username + form.password = '' + form.isAdmin = props.user.role === 'admin' + } + }, + { immediate: true } +) + function onSave() { - emit('confirm') - // close the dialog + const payload: { username: string; password?: string; role: 'admin' | 'user' } = { + username: form.username, + role: form.isAdmin ? 'admin' : 'user', + } + + // only send password if user entered something + if (form.password.trim() !== '') { + payload.password = form.password.trim() + } + + emit('confirm', payload) emit('update:modelValue', false) }