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:
@@ -225,7 +225,6 @@ import { usePieceTypes } from '~/composables/usePieceTypes'
|
||||
import { usePieces } from '~/composables/usePieces'
|
||||
import { useToast } from '~/composables/useToast'
|
||||
import { humanizeError } from '~/shared/utils/errorMessages'
|
||||
import { useCustomFields } from '~/composables/useCustomFields'
|
||||
import { useDocuments } from '~/composables/useDocuments'
|
||||
import { useConstructeurLinks } from '~/composables/useConstructeurLinks'
|
||||
import { useConstructeurs } from '~/composables/useConstructeurs'
|
||||
@@ -243,12 +242,7 @@ import {
|
||||
applyProductSelection,
|
||||
collectNormalizedProductIds,
|
||||
} from '~/shared/utils/pieceProductSelectionUtils'
|
||||
import {
|
||||
type CustomFieldInput,
|
||||
normalizeCustomFieldInputs,
|
||||
requiredCustomFieldsFilled as _requiredCustomFieldsFilled,
|
||||
saveCustomFieldValues as _saveCustomFieldValues,
|
||||
} from '~/shared/utils/customFieldFormUtils'
|
||||
import { useCustomFieldInputs, type CustomFieldEntityType } from '~/composables/useCustomFieldInputs'
|
||||
|
||||
interface PieceCatalogType extends ModelType {
|
||||
structure: PieceModelStructure | null
|
||||
@@ -261,7 +255,6 @@ const router = useRouter()
|
||||
const { pieceTypes, loadPieceTypes, loadingPieceTypes: loadingTypes } = usePieceTypes()
|
||||
const { createPiece } = usePieces()
|
||||
const toast = useToast()
|
||||
const { upsertCustomFieldValue, updateCustomFieldValue } = useCustomFields()
|
||||
const { uploadDocuments } = useDocuments()
|
||||
const { syncLinks } = useConstructeurLinks()
|
||||
const { getConstructeurById } = useConstructeurs()
|
||||
@@ -281,7 +274,14 @@ const constructeurLinks = ref<ConstructeurLinkEntry[]>([])
|
||||
const productSelections = ref<(string | null)[]>([])
|
||||
|
||||
const lastSuggestedName = ref('')
|
||||
const customFieldInputs = ref<CustomFieldInput[]>([])
|
||||
const cfDefinitions = ref<any[]>([])
|
||||
const createdEntityId = ref<string | null>(null)
|
||||
const { fields: customFieldInputs, requiredFilled: requiredCustomFieldsFilled, saveAll: saveAllCustomFields } = useCustomFieldInputs({
|
||||
definitions: cfDefinitions,
|
||||
values: [] as any[],
|
||||
entityType: 'piece' as CustomFieldEntityType,
|
||||
entityId: createdEntityId,
|
||||
})
|
||||
const selectedDocuments = ref<File[]>([])
|
||||
const uploadingDocuments = ref(false)
|
||||
|
||||
@@ -360,21 +360,17 @@ watch(structureProducts, (products) => {
|
||||
watch(selectedType, (type) => {
|
||||
if (!type) {
|
||||
clearCreationForm()
|
||||
customFieldInputs.value = []
|
||||
cfDefinitions.value = []
|
||||
return
|
||||
}
|
||||
if (!creationForm.name || creationForm.name === lastSuggestedName.value) {
|
||||
creationForm.name = type.name
|
||||
}
|
||||
lastSuggestedName.value = creationForm.name
|
||||
customFieldInputs.value = normalizeCustomFieldInputs(type.structure)
|
||||
cfDefinitions.value = type.structure?.customFields ?? []
|
||||
productSelections.value = Array.from({ length: structureProducts.value.length }, () => null)
|
||||
})
|
||||
|
||||
const requiredCustomFieldsFilled = computed(() =>
|
||||
_requiredCustomFieldsFilled(customFieldInputs.value),
|
||||
)
|
||||
|
||||
const canSubmit = computed(() =>
|
||||
Boolean(
|
||||
canEdit.value &&
|
||||
@@ -450,14 +446,11 @@ const submitCreation = async () => {
|
||||
const result = await createPiece(payload)
|
||||
if (result.success && result.data) {
|
||||
const createdPiece = result.data as Record<string, any>
|
||||
await _saveCustomFieldValues(
|
||||
'piece',
|
||||
createdPiece.id,
|
||||
[
|
||||
createdPiece?.typePiece?.structure?.customFields,
|
||||
],
|
||||
{ customFieldInputs, upsertCustomFieldValue, updateCustomFieldValue, toast },
|
||||
)
|
||||
createdEntityId.value = createdPiece.id
|
||||
const failedFields = await saveAllCustomFields()
|
||||
if (failedFields.length) {
|
||||
toast.showError(`Pièce créée, mais impossible d'enregistrer ${failedFields.length} champ(s): ${failedFields.join(', ')}`)
|
||||
}
|
||||
// Sync constructeur links after creation
|
||||
if (constructeurLinks.value.length) {
|
||||
await syncLinks('piece', createdPiece.id, [], constructeurLinks.value)
|
||||
|
||||
Reference in New Issue
Block a user