127 lines
4.1 KiB
Vue
127 lines
4.1 KiB
Vue
|
|
<script setup lang="ts">
|
||
|
|
import type { Form } from '@inertiajs/vue3';
|
||
|
|
import InputError from '@/components/InputError.vue';
|
||
|
|
import { Button } from '@/components/ui/button';
|
||
|
|
import { Input } from '@/components/ui/input';
|
||
|
|
import { Label } from '@/components/ui/label';
|
||
|
|
import { Spinner } from '@/components/ui/spinner';
|
||
|
|
|
||
|
|
export type UserFormData = {
|
||
|
|
name: string;
|
||
|
|
email: string;
|
||
|
|
password?: string;
|
||
|
|
password_confirmation?: string;
|
||
|
|
group: string;
|
||
|
|
};
|
||
|
|
|
||
|
|
type Props = {
|
||
|
|
form: Form<UserFormData>;
|
||
|
|
userGroups: Record<string, string>;
|
||
|
|
showPasswordFields?: boolean;
|
||
|
|
passwordRequired?: boolean;
|
||
|
|
submitLabel?: string;
|
||
|
|
};
|
||
|
|
|
||
|
|
withDefaults(defineProps<Props>(), {
|
||
|
|
showPasswordFields: true,
|
||
|
|
passwordRequired: true,
|
||
|
|
submitLabel: 'Save',
|
||
|
|
});
|
||
|
|
|
||
|
|
const emit = defineEmits<{
|
||
|
|
submit: [];
|
||
|
|
}>();
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<template>
|
||
|
|
<form @submit.prevent="emit('submit')" class="flex flex-col space-y-6">
|
||
|
|
<div class="grid gap-2">
|
||
|
|
<Label for="name">Name</Label>
|
||
|
|
<Input
|
||
|
|
id="name"
|
||
|
|
v-model="form.name"
|
||
|
|
type="text"
|
||
|
|
required
|
||
|
|
autocomplete="name"
|
||
|
|
placeholder="Full name"
|
||
|
|
aria-invalid="!!form.errors.name"
|
||
|
|
/>
|
||
|
|
<InputError :message="form.errors.name" />
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="grid gap-2">
|
||
|
|
<Label for="email">Email address</Label>
|
||
|
|
<Input
|
||
|
|
id="email"
|
||
|
|
v-model="form.email"
|
||
|
|
type="email"
|
||
|
|
required
|
||
|
|
autocomplete="email"
|
||
|
|
placeholder="email@example.com"
|
||
|
|
aria-invalid="!!form.errors.email"
|
||
|
|
/>
|
||
|
|
<InputError :message="form.errors.email" />
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div v-if="showPasswordFields" class="grid gap-2">
|
||
|
|
<Label for="password">Password</Label>
|
||
|
|
<Input
|
||
|
|
id="password"
|
||
|
|
v-model="form.password"
|
||
|
|
type="password"
|
||
|
|
:required="passwordRequired"
|
||
|
|
autocomplete="new-password"
|
||
|
|
:placeholder="passwordRequired ? 'Password' : 'Leave blank to keep current'"
|
||
|
|
aria-invalid="!!form.errors.password"
|
||
|
|
/>
|
||
|
|
<InputError :message="form.errors.password" />
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div v-if="showPasswordFields" class="grid gap-2">
|
||
|
|
<Label for="password_confirmation">Confirm password</Label>
|
||
|
|
<Input
|
||
|
|
id="password_confirmation"
|
||
|
|
v-model="form.password_confirmation"
|
||
|
|
type="password"
|
||
|
|
:required="passwordRequired"
|
||
|
|
autocomplete="new-password"
|
||
|
|
placeholder="Confirm password"
|
||
|
|
aria-invalid="!!form.errors.password_confirmation"
|
||
|
|
/>
|
||
|
|
<InputError :message="form.errors.password_confirmation" />
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="grid gap-2">
|
||
|
|
<Label for="group">Group</Label>
|
||
|
|
<select
|
||
|
|
id="group"
|
||
|
|
v-model="form.group"
|
||
|
|
required
|
||
|
|
class="border-input bg-background placeholder:text-muted-foreground focus-visible:ring-ring h-9 w-full rounded-md border px-3 py-1 text-sm shadow-xs outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50"
|
||
|
|
:aria-invalid="!!form.errors.group"
|
||
|
|
>
|
||
|
|
<option value="" disabled>Select a group</option>
|
||
|
|
<option
|
||
|
|
v-for="(label, value) in userGroups"
|
||
|
|
:key="value"
|
||
|
|
:value="value"
|
||
|
|
>
|
||
|
|
{{ label }}
|
||
|
|
</option>
|
||
|
|
</select>
|
||
|
|
<InputError :message="form.errors.group" />
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="flex items-center gap-4">
|
||
|
|
<Button
|
||
|
|
type="submit"
|
||
|
|
:disabled="form.processing"
|
||
|
|
data-test="user-form-submit"
|
||
|
|
>
|
||
|
|
<Spinner v-if="form.processing" />
|
||
|
|
{{ submitLabel }}
|
||
|
|
</Button>
|
||
|
|
</div>
|
||
|
|
</form>
|
||
|
|
</template>
|