freekake_webapp/pages/content/contents/[id].vue
2025-07-01 09:29:50 +07:00

191 lines
8.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<ul class="flex space-x-2 rtl:space-x-reverse">
<li>
<a href="javascript:;" class="text-primary hover:underline">Konten</a>
</li>
<li class="before:mr-2 before:content-['/'] rtl:before:ml-2">
<NuxtLink to="/content/topics/list" class="text-primary hover:underline">Daftar Topik Konten</NuxtLink>
</li>
<li class="before:mr-2 before:content-['/'] rtl:before:ml-2">
<span>Edit Topik Konten</span>
</li>
</ul>
<div class="grid grid-cols-1 gap-6 pt-5">
<div class="panel">
<div class="mb-5 flex items-center justify-between">
<h5 class="text-lg font-semibold dark:text-white-light">Edit Topik Konten</h5>
<NuxtLink to="/content/topics/list" class="dark:text-white-light btn btn-dark !py-1">
<icon-arrow-backward class="me-1" />
Daftar
</NuxtLink>
</div>
<div class="mb-5">
<form class="space-y-5" @submit.prevent="submitForm()">
<div class="grid grid-cols-1 gap-4 md:grid-cols-4 gap-2">
<div :class="{ 'has-error': $validate.form.theme.$error, 'has-success': isSubmitted && !$validate.form.topic.$error }">
<label for="topic">Topik</label>
<input id="topic" type="text" class="form-input" v-model="form.topic" />
<template v-if="isSubmitted && $validate.form.topic.$error">
<p class="text-danger mt-1">Topik konten harus diisi</p>
</template>
</div>
<div :class="{ 'has-error': $validate.form.theme.$error, 'has-success': isSubmitted && !$validate.form.theme.$error }">
<label for="theme">Tema</label>
<multiselect id="province"
v-model="form.theme"
:options="themes?.results"
class="custom-multiselect"
:searchable="true"
placeholder="Pilih tema konten"
selected-label=""
select-label=""
deselect-label=""
label="theme"
track-by="id"
></multiselect>
<template v-if="isSubmitted && $validate.form.theme.$error">
<p class="text-danger mt-1">Tema konten harus diisi</p>
</template>
</div>
</div>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 gap-2">
<div class="md:col-span-2" :class="{ 'has-error': $validate.form.description.$error, 'has-success': isSubmitted && !$validate.form.description.$error }">
<label for="description">Deskripsi/Keterangan</label>
<textarea id="description" rows="3" class="form-textarea" v-model="form.description"></textarea>
<template v-if="isSubmitted && $validate.form.description.$error">
<p class="text-danger mt-1">Deskripsi/ketarangan tema konten harus diisi</p>
</template>
</div>
</div>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 gap-2 ">
<div class="custom-file-container" data-upload-id="featuredImage"
:class="{ 'has-error': $validate.form.featured_image.$error, 'has-success': isSubmitted && !$validate.form.featured_image.$error }">
<div class="label-container">
<label for="featured_image">Gambar </label> <a href="javascript:;" class="custom-file-container__image-clear" title="Clear Image">×</a>
</div>
<label class="custom-file-container__custom-file" >
<input id="featured_image" type="file" class="custom-file-container__custom-file__custom-file-input"
accept="image/png" @change="handleImageChange" />
<input type="hidden" name="MAX_FILE_SIZE" value="10485760" />
<span class="custom-file-container__custom-file__custom-file-control ltr:pr-20 rtl:pl-20"></span>
</label>
<template v-if="isSubmitted && $validate.form.featured_image.$error">
<p class="text-danger mt-1">Gambar tema konten harus diisi</p>
</template>
<div class="custom-file-container__image-preview"></div>
</div>
</div>
<div class="flex items-center ltr:ml-auto mt-8">
<button type="submit" class="btn btn-success !py-1"><icon-save class="me-1" /> Simpan</button>
<button type="reset" class="btn btn-dark !py-1 ml-1"><icon-restore class="me-1" />Reset</button>
</div>
</form>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { useVuelidate } from '@vuelidate/core';
import { required } from '@vuelidate/validators';
import Multiselect from '@suadelabs/vue3-multiselect';
import '@suadelabs/vue3-multiselect/dist/vue3-multiselect.css';
import '@/assets/css/file-upload-preview.css';
useHead({ title: 'Daftar Topik Konten' });
const isSubmitted = ref(false);
const rules = {
form: {
theme: { required },
description: { required },
featured_image: { required },
}
};
const router = useRouter();
const route = useRoute();
const config = useRuntimeConfig();
const { data: form } = await useAsyncData('provinces',
() => $fetch(`${config.public.apiBase}content/topics/${route.params.id}`, {}), {}
);
const $validate = useVuelidate(rules, { form });
const params = reactive({
current_page: 1,
pagesize: 10,
sort_column: 'id',
sort_direction: 'asc',
});
const { data: themes } = await useAsyncData('themes',
() => $fetch(`${config.public.apiBase}content/themes/`, {
params: {
page: params.current_page,
page_size: 50
}
}), {
watch: [params]
}
);
onMounted(async () => {
const fileupload = await import('file-upload-with-preview');
let FileUploadWithPreview = fileupload.default;
// single image upload
new FileUploadWithPreview('featuredImage', {
images: {
baseImage: form.value.featured_image ? form.value.featured_image : '/assets/images/file-preview.svg',
backgroundImage: '',
},
});
});
const submitForm = async () => {
isSubmitted.value = true;
$validate.value.form.$touch();
if ($validate.value.form.$invalid) {
return false;
}
const formData = new FormData();
formData.append('topic', form.value.topic);
formData.append('theme', form.value.theme.id);
formData.append('description', form.value.description);
if (form.value.featured_image) {
formData.append('featured_image', form.value.featured_image);
}
await $fetch(`${config.public.apiBase}content/topics/${route.params.id}/`, {
method: 'PUT',
body: formData
}).then(() => {
//redirect
router.push({ path: "/content/topics/list" });
})
.catch((error) => {
//assign response error data to state "errors"
console.log(error);
});
}
function handleImageChange(event: { target: { files: any[]; }; }) {
const file = event.target.files[0]
if (!file) return
const allowed = ['image/png']
if (!allowed.includes(file.type)) {
alert('Hanya PNG yang diizinkan')
return
}
form.value.featured_image = file
}
</script>