store/resources/js/composables/useVariantList.ts

92 lines
2.2 KiB
TypeScript

import { ref } from 'vue';
import type { Ref } from 'vue';
import { formErrors } from '@/lib/form';
import type { FormWithErrors } from '@/lib/form';
export interface VariantItem {
client_id: string;
id?: number;
media: unknown;
[key: string]: unknown;
}
export function useVariantList<T extends VariantItem>(
prefix: string,
createEmpty: () => T,
buildInitial: () => T[],
) {
const items: Ref<T[]> = ref(buildInitial()) as Ref<T[]>;
function addItem() {
items.value = [...items.value, createEmpty()];
}
function removeItem(clientId: string) {
if (items.value.length <= 1) {
return;
}
items.value = items.value.filter((item) => item.client_id !== clientId);
}
function setField(clientId: string, key: string, value: unknown) {
items.value = items.value.map((item) =>
item.client_id === clientId ? { ...item, [key]: value } : item,
);
}
function indexOf(clientId: string): number {
return items.value.findIndex((item) => item.client_id === clientId);
}
function appendToFormData(
formData: FormData,
appendItem: (formData: FormData, index: number, item: T) => void,
method?: 'post' | 'put',
) {
if (method === 'put') {
formData.append('_method', 'PUT');
}
items.value.forEach((item, index) => {
if (item.id) {
formData.append(`${prefix}[${index}][id]`, String(item.id));
}
appendItem(formData, index, item);
});
}
function itemErrors(
form: FormWithErrors,
clientId: string,
field: string,
): string[] {
const index = indexOf(clientId);
if (index === -1) {
return [];
}
return formErrors(form, `${prefix}.${index}.${field}`);
}
function allItemErrors(
form: FormWithErrors,
field: string,
): string[] {
return items.value.flatMap((item) => itemErrors(form, item.client_id, field));
}
return {
items,
addItem,
removeItem,
setField,
indexOf,
appendToFormData,
itemErrors,
allItemErrors,
};
}