Refactor CashTransactionFormModal and EmployeeAdvanceFormModal to utilize useFormDialog for improved form handling. Replace MediaImageUpload with ImageUploadField for photo uploads, enhancing user experience. Update form data handling to accommodate new photo upload logic and streamline code.
This commit is contained in:
parent
10e188807d
commit
e871da4c5f
@ -1,9 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useForm } from '@inertiajs/vue3';
|
import { useForm } from '@inertiajs/vue3';
|
||||||
import { Save } from '@lucide/vue';
|
import { Save } from '@lucide/vue';
|
||||||
import { computed, watch } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { toast } from 'vue-sonner';
|
import { toast } from 'vue-sonner';
|
||||||
import MediaImageUpload from '@/components/media/MediaImageUpload.vue';
|
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
@ -19,12 +18,13 @@ import {
|
|||||||
FieldLabel,
|
FieldLabel,
|
||||||
FieldSet,
|
FieldSet,
|
||||||
} from '@/components/ui/field';
|
} from '@/components/ui/field';
|
||||||
|
import ImageUploadField from '@/components/ui/image-upload-field/ImageUploadField.vue';
|
||||||
import { RupiahInput } from '@/components/ui/rupiah-input';
|
import { RupiahInput } from '@/components/ui/rupiah-input';
|
||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
|
import { useFormDialog } from '@/composables/useFormDialog';
|
||||||
import { formErrors } from '@/lib/form';
|
import { formErrors } from '@/lib/form';
|
||||||
import { parseRupiah } from '@/lib/rupiah';
|
import { parseRupiah } from '@/lib/rupiah';
|
||||||
import type { CashTransactionListItem } from '@/types/cash';
|
import type { CashTransactionListItem } from '@/types/cash';
|
||||||
import { appendRootPhotosToFormData, createMediaUploadState } from '@/types/media';
|
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { default: false });
|
const open = defineModel<boolean>('open', { default: false });
|
||||||
|
|
||||||
@ -34,15 +34,21 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const isEditing = computed(() => props.transaction != null);
|
const isEditing = computed(() => props.transaction != null);
|
||||||
|
|
||||||
|
const existingPhotoId = ref<number | null>(null);
|
||||||
|
|
||||||
|
const currentPhotoUrl = computed(() => props.transaction?.photos?.[0]?.url ?? null);
|
||||||
|
|
||||||
|
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
amount: '',
|
amount: '',
|
||||||
description: '',
|
description: '',
|
||||||
media: createMediaUploadState(),
|
photo: null as File | null,
|
||||||
});
|
});
|
||||||
|
|
||||||
function resetForm() {
|
function resetForm() {
|
||||||
form.reset();
|
form.reset();
|
||||||
form.media = createMediaUploadState();
|
form.photo = null;
|
||||||
|
existingPhotoId.value = null;
|
||||||
form.clearErrors();
|
form.clearErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,22 +61,14 @@ function populateForm(transaction: CashTransactionListItem | null | undefined) {
|
|||||||
|
|
||||||
form.amount = String(transaction.amount);
|
form.amount = String(transaction.amount);
|
||||||
form.description = transaction.description;
|
form.description = transaction.description;
|
||||||
form.media = createMediaUploadState(transaction.photos ?? []);
|
existingPhotoId.value = transaction.photos?.[0]?.id ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
useFormDialog({
|
||||||
() => props.transaction,
|
open,
|
||||||
(transaction) => {
|
source: () => props.transaction,
|
||||||
populateForm(transaction);
|
populate: populateForm,
|
||||||
},
|
reset: resetForm,
|
||||||
);
|
|
||||||
|
|
||||||
watch(open, (isOpen) => {
|
|
||||||
if (isOpen) {
|
|
||||||
populateForm(props.transaction);
|
|
||||||
} else {
|
|
||||||
resetForm();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function buildFormData(forUpdate: boolean): FormData {
|
function buildFormData(forUpdate: boolean): FormData {
|
||||||
@ -82,12 +80,21 @@ function buildFormData(forUpdate: boolean): FormData {
|
|||||||
|
|
||||||
formData.append('amount', parseRupiah(form.amount));
|
formData.append('amount', parseRupiah(form.amount));
|
||||||
formData.append('description', form.description);
|
formData.append('description', form.description);
|
||||||
appendRootPhotosToFormData(formData, form.media);
|
|
||||||
|
if (form.photo) {
|
||||||
|
formData.append('photos[]', form.photo);
|
||||||
|
|
||||||
|
if (existingPhotoId.value) {
|
||||||
|
formData.append('remove_media_ids[]', String(existingPhotoId.value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
function submit() {
|
function submit() {
|
||||||
|
const payload = buildFormData(isEditing.value);
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
forceFormData: true,
|
forceFormData: true,
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
@ -101,13 +108,13 @@ function submit() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const payload = buildFormData(isEditing.value);
|
|
||||||
|
|
||||||
if (isEditing.value && props.transaction) {
|
if (isEditing.value && props.transaction) {
|
||||||
form.transform(() => payload).post(`/admin/finance/cash/transactions/${props.transaction.id}`, options);
|
form.transform(() => payload).put(`/admin/finance/cash/transactions/${props.transaction.id}`, options);
|
||||||
} else {
|
|
||||||
form.transform(() => payload).post('/admin/finance/cash/deposit', options);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form.transform(() => payload).post('/admin/finance/cash/deposit', options);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -132,8 +139,8 @@ function submit() {
|
|||||||
placeholder="Contoh: Setoran kas harian" rows="3" />
|
placeholder="Contoh: Setoran kas harian" rows="3" />
|
||||||
<FieldError :errors="formErrors(form, 'description')" />
|
<FieldError :errors="formErrors(form, 'description')" />
|
||||||
</Field>
|
</Field>
|
||||||
<MediaImageUpload id="cash-photos" v-model="form.media" label="Foto Bukti" required
|
<ImageUploadField id="cash-photos" v-model="form.photo" label="Foto Bukti" required
|
||||||
:errors="formErrors(form, 'photos')" />
|
:current-url="currentPhotoUrl" :errors="formErrors(form, 'photos')" />
|
||||||
</FieldSet>
|
</FieldSet>
|
||||||
</FieldGroup>
|
</FieldGroup>
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useForm } from '@inertiajs/vue3';
|
import { useForm } from '@inertiajs/vue3';
|
||||||
import { Save } from '@lucide/vue';
|
import { Save } from '@lucide/vue';
|
||||||
import { computed, watch } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { toast } from 'vue-sonner';
|
import { toast } from 'vue-sonner';
|
||||||
import MediaImageUpload from '@/components/media/MediaImageUpload.vue';
|
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { DatePicker } from '@/components/ui/date-picker';
|
import { DatePicker } from '@/components/ui/date-picker';
|
||||||
import {
|
import {
|
||||||
@ -20,12 +19,13 @@ import {
|
|||||||
FieldLabel,
|
FieldLabel,
|
||||||
FieldSet,
|
FieldSet,
|
||||||
} from '@/components/ui/field';
|
} from '@/components/ui/field';
|
||||||
|
import ImageUploadField from '@/components/ui/image-upload-field/ImageUploadField.vue';
|
||||||
import { RupiahInput } from '@/components/ui/rupiah-input';
|
import { RupiahInput } from '@/components/ui/rupiah-input';
|
||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
|
import { useFormDialog } from '@/composables/useFormDialog';
|
||||||
import { formErrors } from '@/lib/form';
|
import { formErrors } from '@/lib/form';
|
||||||
import { parseRupiah } from '@/lib/rupiah';
|
import { parseRupiah } from '@/lib/rupiah';
|
||||||
import type { EmployeeAdvanceListItem } from '@/types/employee-advance';
|
import type { EmployeeAdvanceListItem } from '@/types/employee-advance';
|
||||||
import { appendRootPhotosToFormData, createMediaUploadState } from '@/types/media';
|
|
||||||
|
|
||||||
const open = defineModel<boolean>('open', { default: false });
|
const open = defineModel<boolean>('open', { default: false });
|
||||||
|
|
||||||
@ -35,16 +35,21 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const isEditing = computed(() => props.employeeAdvance != null);
|
const isEditing = computed(() => props.employeeAdvance != null);
|
||||||
|
|
||||||
|
const existingPhotoId = ref<number | null>(null);
|
||||||
|
|
||||||
|
const currentPhotoUrl = computed(() => props.employeeAdvance?.photos?.[0]?.url ?? null);
|
||||||
|
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
amount: '',
|
amount: '',
|
||||||
description: '',
|
description: '',
|
||||||
due_date: '',
|
due_date: '',
|
||||||
media: createMediaUploadState(),
|
photo: null as File | null,
|
||||||
});
|
});
|
||||||
|
|
||||||
function resetForm() {
|
function resetForm() {
|
||||||
form.reset();
|
form.reset();
|
||||||
form.media = createMediaUploadState();
|
form.photo = null;
|
||||||
|
existingPhotoId.value = null;
|
||||||
form.clearErrors();
|
form.clearErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,22 +63,14 @@ function populateForm(employeeAdvance: EmployeeAdvanceListItem | null | undefine
|
|||||||
form.amount = String(employeeAdvance.amount);
|
form.amount = String(employeeAdvance.amount);
|
||||||
form.description = employeeAdvance.description;
|
form.description = employeeAdvance.description;
|
||||||
form.due_date = employeeAdvance.due_date_input;
|
form.due_date = employeeAdvance.due_date_input;
|
||||||
form.media = createMediaUploadState(employeeAdvance.photos ?? []);
|
existingPhotoId.value = employeeAdvance.photos?.[0]?.id ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
useFormDialog({
|
||||||
() => props.employeeAdvance,
|
open,
|
||||||
(employeeAdvance) => {
|
source: () => props.employeeAdvance,
|
||||||
populateForm(employeeAdvance);
|
populate: populateForm,
|
||||||
},
|
reset: resetForm,
|
||||||
);
|
|
||||||
|
|
||||||
watch(open, (isOpen) => {
|
|
||||||
if (isOpen) {
|
|
||||||
populateForm(props.employeeAdvance);
|
|
||||||
} else {
|
|
||||||
resetForm();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function buildFormData(forUpdate: boolean): FormData {
|
function buildFormData(forUpdate: boolean): FormData {
|
||||||
@ -86,12 +83,21 @@ function buildFormData(forUpdate: boolean): FormData {
|
|||||||
formData.append('amount', parseRupiah(form.amount));
|
formData.append('amount', parseRupiah(form.amount));
|
||||||
formData.append('description', form.description);
|
formData.append('description', form.description);
|
||||||
formData.append('due_date', form.due_date);
|
formData.append('due_date', form.due_date);
|
||||||
appendRootPhotosToFormData(formData, form.media);
|
|
||||||
|
if (form.photo) {
|
||||||
|
formData.append('photos[]', form.photo);
|
||||||
|
|
||||||
|
if (existingPhotoId.value) {
|
||||||
|
formData.append('remove_media_ids[]', String(existingPhotoId.value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
function submit() {
|
function submit() {
|
||||||
|
const payload = buildFormData(isEditing.value);
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
forceFormData: true,
|
forceFormData: true,
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
@ -103,13 +109,13 @@ function submit() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const payload = buildFormData(isEditing.value);
|
|
||||||
|
|
||||||
if (isEditing.value && props.employeeAdvance) {
|
if (isEditing.value && props.employeeAdvance) {
|
||||||
form.transform(() => payload).post(`/admin/finance/employee-advances/${props.employeeAdvance.id}`, options);
|
form.transform(() => payload).put(`/admin/finance/employee-advances/${props.employeeAdvance.id}`, options);
|
||||||
} else {
|
|
||||||
form.transform(() => payload).post('/admin/finance/employee-advances', options);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form.transform(() => payload).post('/admin/finance/employee-advances', options);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -139,8 +145,8 @@ function submit() {
|
|||||||
<DatePicker id="employee-advance-due-date" v-model="form.due_date" />
|
<DatePicker id="employee-advance-due-date" v-model="form.due_date" />
|
||||||
<FieldError :errors="formErrors(form, 'due_date')" />
|
<FieldError :errors="formErrors(form, 'due_date')" />
|
||||||
</Field>
|
</Field>
|
||||||
<MediaImageUpload id="employee-advance-photos" v-model="form.media" label="Foto Bukti" required
|
<ImageUploadField id="employee-advance-photos" v-model="form.photo" label="Foto Bukti" required
|
||||||
:errors="formErrors(form, 'photos')" />
|
:current-url="currentPhotoUrl" :errors="formErrors(form, 'photos')" />
|
||||||
</FieldSet>
|
</FieldSet>
|
||||||
</FieldGroup>
|
</FieldGroup>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user