add / edit / delete user warrens

This commit is contained in:
2025-07-21 19:27:41 +02:00
parent 50e066f794
commit 2c26002507
86 changed files with 2197 additions and 300 deletions

View File

@@ -1,4 +1,5 @@
<script setup lang="ts">
import { Accordion } from '@/components/ui/accordion';
import {
AlertDialog,
AlertDialogAction,
@@ -14,14 +15,14 @@ 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';
import type { AuthUserWithWarrens } from '~/shared/types/admin';
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 user = ref<AuthUserWithWarrens>();
const editing = ref(false);
const isChanged = computed(() => {
@@ -52,8 +53,13 @@ const form = useForm({
adminStore.$subscribe((_mutation, state) => {
if (state.editUserDialog != null && !editing.value) {
user.value = state.editUserDialog.user;
form.setValues(user.value);
user.value = state.resources.users.find(
(u) => u.id === state.editUserDialog?.user.id
);
if (user.value != null) {
form.setValues(user.value);
}
}
});
@@ -73,7 +79,14 @@ const onSubmit = form.handleSubmit(async (values) => {
});
if (result.success) {
close();
const newUser: AuthUserWithWarrens = {
id: result.user.id,
name: result.user.name,
email: result.user.email,
admin: result.user.admin,
warrens: user.value.warrens,
};
adminStore.setEditUserDialog(newUser);
}
editing.value = false;
@@ -83,102 +96,141 @@ const onSubmit = form.handleSubmit(async (values) => {
<template>
<AlertDialog :open="adminStore.editUserDialog != null">
<AlertDialogTrigger><slot /></AlertDialogTrigger>
<AlertDialogContent @escape-key-down="close">
<AlertDialogHeader>
<AlertDialogContent
v-if="user != null"
class="flex max-h-[95vh] flex-col"
@escape-key-down="close"
>
<AlertDialogHeader class="shrink">
<AlertDialogTitle>Edit user</AlertDialogTitle>
<AlertDialogDescription>
Edit the user's fields, manage permissions or assign warrens
Modify 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"
<ScrollArea
class="flex h-full grow flex-col justify-start overflow-hidden"
>
<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>
<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="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
<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>
<AlertDialogAction
type="submit"
form="edit-user-form"
:disabled="!isChanged || !isValid"
>Save</AlertDialogAction
>
</form>
<Separator orientation="horizontal" class="my-4" />
<div class="flex w-full flex-col gap-2">
<AdminAddUserWarrenDialog :user>
<Button variant="outline" size="icon">
<Icon name="lucide:folder-plus" />
</Button>
</AdminAddUserWarrenDialog>
<Accordion
v-if="user.warrens.length > 0"
class="flex w-full flex-col gap-2"
collapsible
type="single"
>
<AdminUserWarrenListing
v-for="warren in user.warrens"
:key="warren.warrenId"
:user-warren="warren"
/>
</Accordion>
<div v-else class="flex flex-col gap-4">
<span class="text-muted-foreground"
>This user is not assigned to any warrens</span
>
</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>
</div>
</div>
<Separator orientation="horizontal" class="mt-4" />
</ScrollArea>
<AlertDialogFooter class="gap-y-0">
<AlertDialogCancel @click="close">Cancel</AlertDialogCancel>
<AlertDialogAction
type="submit"
form="edit-user-form"
:disabled="!isChanged || !isValid"
>Save</AlertDialogAction
>
<AlertDialogCancel @click="close">Close</AlertDialogCancel>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>