186 lines
6.1 KiB
Vue
186 lines
6.1 KiB
Vue
<script setup lang="ts">
|
|
import {
|
|
AlertDialog,
|
|
AlertDialogAction,
|
|
AlertDialogCancel,
|
|
AlertDialogContent,
|
|
AlertDialogDescription,
|
|
AlertDialogFooter,
|
|
AlertDialogHeader,
|
|
AlertDialogTitle,
|
|
AlertDialogTrigger,
|
|
} from '@/components/ui/alert-dialog';
|
|
import { useForm } from 'vee-validate';
|
|
import { toTypedSchema } from '@vee-validate/yup';
|
|
import { editUserSchema } from '~/lib/schemas/admin';
|
|
import { editUser } from '~/lib/api/admin/editUser';
|
|
import type { AuthUser } from '~/shared/types/auth';
|
|
|
|
const adminStore = useAdminStore();
|
|
|
|
const isValid = computed(() => Object.keys(form.errors.value).length < 1);
|
|
|
|
// We'll only update this value if there is a user to prevent layout shifts on close
|
|
const user = ref<AuthUser>();
|
|
const editing = ref(false);
|
|
|
|
const isChanged = computed(() => {
|
|
if (user.value == null) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
const values = editUserSchema.validateSync(form.controlledValues.value);
|
|
return (
|
|
values.name !== user.value.name ||
|
|
values.email !== user.value.email ||
|
|
values.password != null ||
|
|
values.admin !== user.value.admin
|
|
);
|
|
} catch {
|
|
return true;
|
|
}
|
|
});
|
|
|
|
function close() {
|
|
adminStore.closeEditUserDialog();
|
|
}
|
|
|
|
const form = useForm({
|
|
validationSchema: toTypedSchema(editUserSchema),
|
|
});
|
|
|
|
adminStore.$subscribe((_mutation, state) => {
|
|
if (state.editUserDialog != null && !editing.value) {
|
|
user.value = state.editUserDialog.user;
|
|
form.setValues(user.value);
|
|
}
|
|
});
|
|
|
|
const onSubmit = form.handleSubmit(async (values) => {
|
|
if (user.value == null || !isChanged.value || editing.value) {
|
|
return;
|
|
}
|
|
|
|
editing.value = true;
|
|
|
|
const result = await editUser({
|
|
id: user.value.id,
|
|
name: values.name,
|
|
email: values.email,
|
|
password: values.password ?? null,
|
|
admin: values.admin,
|
|
});
|
|
|
|
if (result.success) {
|
|
close();
|
|
}
|
|
|
|
editing.value = false;
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<AlertDialog :open="adminStore.editUserDialog != null">
|
|
<AlertDialogTrigger><slot /></AlertDialogTrigger>
|
|
<AlertDialogContent @escape-key-down="close">
|
|
<AlertDialogHeader>
|
|
<AlertDialogTitle>Edit user</AlertDialogTitle>
|
|
<AlertDialogDescription>
|
|
Edit the user's fields, manage permissions or assign warrens
|
|
</AlertDialogDescription>
|
|
</AlertDialogHeader>
|
|
|
|
<form
|
|
id="edit-user-form"
|
|
class="flex flex-col gap-2"
|
|
@submit.prevent="onSubmit"
|
|
>
|
|
<FormField v-slot="{ componentField }" name="name">
|
|
<FormItem>
|
|
<FormLabel>Username</FormLabel>
|
|
<FormControl>
|
|
<Input
|
|
v-bind="componentField"
|
|
id="username"
|
|
type="text"
|
|
placeholder="confused-cat"
|
|
autocomplete="off"
|
|
data-1p-ignore
|
|
data-protonpass-ignore
|
|
data-bwignore
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
|
|
<FormField v-slot="{ componentField }" name="email">
|
|
<FormItem>
|
|
<FormLabel>Email</FormLabel>
|
|
<FormControl>
|
|
<Input
|
|
v-bind="componentField"
|
|
id="email"
|
|
type="email"
|
|
placeholder="confusedcat@example.com"
|
|
autocomplete="off"
|
|
data-1p-ignore
|
|
data-protonpass-ignore
|
|
data-bwignore
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
|
|
<FormField v-slot="{ componentField }" name="password">
|
|
<FormItem>
|
|
<FormLabel>Password</FormLabel>
|
|
<FormControl>
|
|
<Input
|
|
v-bind="componentField"
|
|
id="password"
|
|
type="password"
|
|
autocomplete="off"
|
|
data-1p-ignore
|
|
data-protonpass-ignore
|
|
data-bwignore
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
<FormDescription
|
|
>Leave empty to keep the current
|
|
password</FormDescription
|
|
>
|
|
</FormItem>
|
|
</FormField>
|
|
|
|
<FormField v-slot="{ value, handleChange }" name="admin">
|
|
<FormItem>
|
|
<FormLabel>Admin</FormLabel>
|
|
<FormControl>
|
|
<Switch
|
|
id="admin"
|
|
:model-value="value"
|
|
@update:model-value="handleChange"
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
</form>
|
|
|
|
<AlertDialogFooter class="gap-y-0">
|
|
<AlertDialogCancel @click="close">Cancel</AlertDialogCancel>
|
|
<AlertDialogAction
|
|
type="submit"
|
|
form="edit-user-form"
|
|
:disabled="!isChanged || !isValid"
|
|
>Save</AlertDialogAction
|
|
>
|
|
</AlertDialogFooter>
|
|
</AlertDialogContent>
|
|
</AlertDialog>
|
|
</template>
|