refactor(custom-fields) : unify 3 parallel implementations into 1 module
Replace ~2900 lines across 9 files with ~400 lines in 2 files: - shared/utils/customFields.ts (types + pure helpers) - composables/useCustomFieldInputs.ts (reactive composable) Migrated all consumers: - Backend: add defaultValue to API Platform serialization groups - Standalone pages: component edit/create, piece edit/create, product edit/create/detail - Machine page: MachineCustomFieldsCard, MachineInfoCard, useMachineDetailCustomFields - Hierarchy: ComponentItem, PieceItem - Shared: CustomFieldDisplay, CustomFieldInputGrid - Category editor: componentStructure.ts Deleted: - entityCustomFieldLogic.ts (335 lines) - customFieldUtils.ts (440 lines) - customFieldFormUtils.ts (404 lines) - useEntityCustomFields.ts (181 lines) - customFieldFormUtils.test.ts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,15 +17,9 @@ import { useProductTypes } from '~/composables/useProductTypes'
|
||||
import { useApi } from '~/composables/useApi'
|
||||
import { useToast } from '~/composables/useToast'
|
||||
import { humanizeError } from '~/shared/utils/errorMessages'
|
||||
import { useCustomFields } from '~/composables/useCustomFields'
|
||||
import { useDocuments } from '~/composables/useDocuments'
|
||||
import { formatStructurePreview, normalizeStructureForEditor } from '~/shared/modelUtils'
|
||||
import {
|
||||
type CustomFieldInput,
|
||||
normalizeCustomFieldInputs,
|
||||
requiredCustomFieldsFilled as _requiredCustomFieldsFilled,
|
||||
saveCustomFieldValues as _saveCustomFieldValues,
|
||||
} from '~/shared/utils/customFieldFormUtils'
|
||||
import { useCustomFieldInputs, type CustomFieldInput } from '~/composables/useCustomFieldInputs'
|
||||
import { useConstructeurLinks } from '~/composables/useConstructeurLinks'
|
||||
import { uniqueConstructeurIds, constructeurIdsFromLinks } from '~/shared/constructeurUtils'
|
||||
import type { ConstructeurLinkEntry } from '~/shared/constructeurUtils'
|
||||
@@ -77,7 +71,6 @@ export function useComponentCreate() {
|
||||
loading: productsLoading,
|
||||
} = useProducts()
|
||||
const toast = useToast()
|
||||
const { upsertCustomFieldValue, updateCustomFieldValue } = useCustomFields()
|
||||
const { uploadDocuments } = useDocuments()
|
||||
const { syncLinks } = useConstructeurLinks()
|
||||
const { canEdit } = usePermissions()
|
||||
@@ -98,7 +91,20 @@ export function useComponentCreate() {
|
||||
const constructeurLinks = ref<ConstructeurLinkEntry[]>([])
|
||||
const constructeurIdsFromForm = computed(() => constructeurIdsFromLinks(constructeurLinks.value))
|
||||
const lastSuggestedName = ref('')
|
||||
const customFieldInputs = ref<CustomFieldInput[]>([])
|
||||
const createdComponentId = ref<string | null>(null)
|
||||
|
||||
const {
|
||||
fields: customFieldInputs,
|
||||
requiredFilled: requiredCustomFieldsFilled,
|
||||
saveAll: saveAllCustomFields,
|
||||
refresh: refreshCustomFieldInputs,
|
||||
} = useCustomFieldInputs({
|
||||
definitions: computed(() => selectedTypeStructure.value?.customFields ?? []),
|
||||
values: computed(() => []),
|
||||
entityType: 'composant',
|
||||
entityId: createdComponentId,
|
||||
})
|
||||
|
||||
const structureAssignments = ref<StructureAssignmentNode | null>(null)
|
||||
const selectedDocuments = ref<File[]>([])
|
||||
const uploadingDocuments = ref(false)
|
||||
@@ -165,10 +171,6 @@ export function useComponentCreate() {
|
||||
return isAssignmentNodeComplete(structureAssignments.value, true)
|
||||
})
|
||||
|
||||
const requiredCustomFieldsFilled = computed(() =>
|
||||
_requiredCustomFieldsFilled(customFieldInputs.value),
|
||||
)
|
||||
|
||||
const canSubmit = computed(() => Boolean(
|
||||
canEdit.value
|
||||
&& selectedType.value
|
||||
@@ -225,7 +227,6 @@ export function useComponentCreate() {
|
||||
watch(selectedType, (type) => {
|
||||
if (!type) {
|
||||
clearCreationForm()
|
||||
customFieldInputs.value = []
|
||||
structureAssignments.value = null
|
||||
return
|
||||
}
|
||||
@@ -233,7 +234,8 @@ export function useComponentCreate() {
|
||||
creationForm.name = type.name
|
||||
}
|
||||
lastSuggestedName.value = creationForm.name
|
||||
customFieldInputs.value = normalizeCustomFieldInputs(selectedTypeStructure.value)
|
||||
// useCustomFieldInputs auto-refreshes via its watcher on definitions
|
||||
refreshCustomFieldInputs()
|
||||
structureAssignments.value = initializeStructureAssignments(selectedTypeStructure.value)
|
||||
})
|
||||
|
||||
@@ -323,12 +325,11 @@ export function useComponentCreate() {
|
||||
const result = await createComposant(payload)
|
||||
if (result.success) {
|
||||
const createdComponent = result.data as Record<string, any>
|
||||
await _saveCustomFieldValues(
|
||||
'composant',
|
||||
createdComponent.id,
|
||||
[createdComponent?.typeComposant?.structure?.customFields],
|
||||
{ customFieldInputs, upsertCustomFieldValue, updateCustomFieldValue, toast },
|
||||
)
|
||||
createdComponentId.value = createdComponent.id
|
||||
const failedFields = await saveAllCustomFields()
|
||||
if (failedFields.length) {
|
||||
toast.showError(`Erreur sur les champs : ${failedFields.join(', ')}`)
|
||||
}
|
||||
if (selectedDocuments.value.length && result.data?.id) {
|
||||
uploadingDocuments.value = true
|
||||
const uploadResult = await uploadDocuments(
|
||||
|
||||
Reference in New Issue
Block a user