95 lines
3.7 KiB
Vue
95 lines
3.7 KiB
Vue
<script setup>
|
|
import { router, useForm } from '@inertiajs/vue3';
|
|
|
|
const props = defineProps({
|
|
item: { type: Object, default: null },
|
|
action: { type: String, required: true },
|
|
destroyUrl: { type: String, default: null },
|
|
allowImage: { type: Boolean, default: false },
|
|
labels: { type: Object, required: true },
|
|
initial: { type: Object, default: () => ({}) },
|
|
});
|
|
|
|
const form = useForm({
|
|
title: props.item?.title ?? props.initial.title ?? '',
|
|
sort_order: props.item?.sort_order ?? props.initial.sort_order ?? 0,
|
|
is_published: props.item?.is_published ?? props.initial.is_published ?? true,
|
|
body: props.item?.body ?? props.initial.body ?? '',
|
|
...(props.allowImage ? { image: null } : {}),
|
|
});
|
|
|
|
function submit() {
|
|
const hasImage = props.allowImage && Boolean(form.image);
|
|
const options = {
|
|
preserveScroll: true,
|
|
forceFormData: hasImage,
|
|
errorBag: props.item ? `news-edit-${props.item.id}` : 'news-create',
|
|
onSuccess: () => {
|
|
if (!props.item) form.reset();
|
|
},
|
|
};
|
|
|
|
form.transform((data) => data);
|
|
|
|
if (props.item && hasImage) {
|
|
form.transform((data) => ({ ...data, _method: 'patch' })).post(props.action, options);
|
|
} else if (props.item) {
|
|
form.patch(props.action, options);
|
|
} else {
|
|
form.post(props.action, options);
|
|
}
|
|
}
|
|
|
|
function destroyItem() {
|
|
if (props.destroyUrl && window.confirm(props.labels.deleteConfirm)) {
|
|
router.delete(props.destroyUrl, { preserveScroll: true });
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<form class="admin-form" @submit.prevent="submit">
|
|
<div class="admin-form-grid">
|
|
<label class="admin-field admin-field--wide">
|
|
<span>{{ labels.title }}</span>
|
|
<input v-model="form.title" maxlength="120" required />
|
|
<small v-if="form.errors.title">{{ form.errors.title }}</small>
|
|
</label>
|
|
<label class="admin-field">
|
|
<span>Порядок вывода</span>
|
|
<input v-model="form.sort_order" type="number" min="0" max="9999" required />
|
|
<small v-if="form.errors.sort_order">{{ form.errors.sort_order }}</small>
|
|
</label>
|
|
</div>
|
|
|
|
<label class="admin-check">
|
|
<input v-model="form.is_published" type="checkbox" />
|
|
<span class="admin-check__box"></span>
|
|
<span>{{ labels.published }}</span>
|
|
</label>
|
|
|
|
<label class="admin-field">
|
|
<span>{{ labels.body }}</span>
|
|
<textarea v-model="form.body" rows="10" required></textarea>
|
|
<em v-if="labels.bodyHint">{{ labels.bodyHint }}</em>
|
|
<small v-if="form.errors.body">{{ form.errors.body }}</small>
|
|
</label>
|
|
|
|
<label v-if="allowImage" class="admin-field admin-upload">
|
|
<span>{{ item ? 'Заменить картинку' : 'Картинка' }}</span>
|
|
<input type="file" accept="image/*" @input="form.image = $event.target.files[0]" />
|
|
<em>{{ item ? 'Оставь пустым, чтобы сохранить текущую. Максимум 10 МБ.' : 'Максимум 10 МБ. Необязательно.' }}</em>
|
|
<small v-if="form.errors.image">{{ form.errors.image }}</small>
|
|
</label>
|
|
|
|
<div class="admin-form-actions">
|
|
<button class="btn btn-primary admin-submit" type="submit" :disabled="form.processing">
|
|
{{ form.processing ? 'Сохраняем…' : labels.submit }}
|
|
</button>
|
|
<button v-if="destroyUrl" class="btn btn-ghost admin-danger-button" type="button" @click="destroyItem">
|
|
{{ labels.delete }}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</template>
|