104 lines
3.0 KiB
Vue
104 lines
3.0 KiB
Vue
<script setup lang="ts">
|
||
import {
|
||
Dialog,
|
||
DialogContent,
|
||
DialogHeader,
|
||
DialogTitle,
|
||
DialogDescription,
|
||
DialogFooter,
|
||
} from '@/components/ui/dialog'
|
||
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, 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({
|
||
modelValue: {
|
||
type: Boolean as PropType<boolean>,
|
||
required: true,
|
||
},
|
||
user: {
|
||
type: Object as PropType<Users>,
|
||
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
|
||
}>()
|
||
|
||
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() {
|
||
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)
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<Dialog :open="props.modelValue" @update:open="(v: boolean) => emit('update:modelValue', v)">
|
||
<DialogContent class="sm:max-w-[425px]">
|
||
<DialogHeader>
|
||
<DialogTitle>Edit profile</DialogTitle>
|
||
<DialogDescription>
|
||
Make changes to user credentials below.
|
||
</DialogDescription>
|
||
</DialogHeader>
|
||
|
||
<div class="grid gap-4 py-4">
|
||
<div class="grid grid-cols-4 items-center gap-4">
|
||
<Label for="username" class="text-right">Username</Label>
|
||
<Input id="username" class="col-span-3" v-model="form.username"/>
|
||
</div>
|
||
<div class="grid grid-cols-4 items-center gap-4">
|
||
<Label for="password" class="text-right">Password</Label>
|
||
<Input id="password" class="col-span-3" type="password" v-model="form.password"/>
|
||
</div>
|
||
<div class="grid grid-cols-4 items-center gap-4">
|
||
<Label for="isAdmin" class="text-right">Make admin</Label>
|
||
<Switch id="isAdmin" :default-value="form.isAdmin" v-model:checked="form.isAdmin"/>
|
||
</div>
|
||
</div>
|
||
|
||
<DialogFooter>
|
||
<Button @click="onSave">Save changes</Button>
|
||
</DialogFooter>
|
||
</DialogContent>
|
||
</Dialog>
|
||
</template> |