refactor : merge Inventory_frontend submodule into frontend/ directory
Merges the full git history of Inventory_frontend into the monorepo under frontend/. Removes the submodule in favor of a unified repo. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
220
frontend/app/shared/utils/assignmentUtils.ts
Normal file
220
frontend/app/shared/utils/assignmentUtils.ts
Normal file
@@ -0,0 +1,220 @@
|
||||
/**
|
||||
* Entity assignment normalization and display utilities.
|
||||
*
|
||||
* Extracted from pages/machines/new.vue – these pure functions resolve
|
||||
* machine / component / piece assignments from nested API payloads.
|
||||
*/
|
||||
|
||||
type AnyRecord = Record<string, unknown>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Primitive helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const isPlainObject = (value: unknown): value is AnyRecord =>
|
||||
value !== null && typeof value === 'object' && !Array.isArray(value)
|
||||
|
||||
const toTrimmedString = (value: unknown): string | null => {
|
||||
if (typeof value === 'string') {
|
||||
const trimmed = value.trim()
|
||||
return trimmed.length > 0 ? trimmed : null
|
||||
}
|
||||
if (typeof value === 'number' && Number.isFinite(value)) {
|
||||
return String(value)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Dedup
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const dedupeAssignments = (
|
||||
assignments: AnyRecord[],
|
||||
): AnyRecord[] => {
|
||||
const seen = new Set<string>()
|
||||
return assignments.filter((assignment) => {
|
||||
if (!assignment) return false
|
||||
const id = assignment.id != null ? String(assignment.id) : ''
|
||||
const name = assignment.name != null ? String(assignment.name) : ''
|
||||
const key = `${id}::${name}`
|
||||
if (!id && !name) return false
|
||||
if (seen.has(key)) return false
|
||||
seen.add(key)
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Machine assignments
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const normalizeMachineAssignment = (input: unknown): AnyRecord | null => {
|
||||
if (!input) return null
|
||||
if (typeof input === 'string') {
|
||||
const name = toTrimmedString(input)
|
||||
return name ? { id: name, name } : null
|
||||
}
|
||||
if (typeof input === 'number' && Number.isFinite(input)) {
|
||||
const value = String(input)
|
||||
return { id: value, name: value }
|
||||
}
|
||||
|
||||
const container = (input as AnyRecord).machine || (input as AnyRecord).machineData || input
|
||||
if (!isPlainObject(container)) return null
|
||||
|
||||
const id =
|
||||
container.id ?? (input as AnyRecord).machineId ?? (input as AnyRecord).id ?? null
|
||||
const name =
|
||||
container.name ||
|
||||
(input as AnyRecord).machineName ||
|
||||
container.label ||
|
||||
container.title ||
|
||||
(typeof id === 'string' ? id : null) ||
|
||||
(typeof id === 'number' ? String(id) : null)
|
||||
|
||||
if (id == null && name == null) return null
|
||||
|
||||
return {
|
||||
id: id != null ? id : null,
|
||||
name: name != null ? name : null,
|
||||
}
|
||||
}
|
||||
|
||||
export const collectMachineAssignments = (source: unknown): AnyRecord[] => {
|
||||
if (!isPlainObject(source)) return []
|
||||
|
||||
const candidates = [
|
||||
source.machines,
|
||||
source.machineLinks,
|
||||
source.machineAssignments,
|
||||
source.machinesAssignments,
|
||||
source.linkedMachines,
|
||||
]
|
||||
|
||||
const assignments: AnyRecord[] = []
|
||||
|
||||
candidates.forEach((list) => {
|
||||
if (Array.isArray(list)) {
|
||||
list.forEach((item) => {
|
||||
const normalized = normalizeMachineAssignment(item)
|
||||
if (normalized) assignments.push(normalized)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
if (!assignments.length) {
|
||||
const direct = normalizeMachineAssignment(source.machine)
|
||||
if (direct) assignments.push(direct)
|
||||
}
|
||||
|
||||
if (!assignments.length) {
|
||||
const idCandidate = source.machineId ?? source.machineID ?? null
|
||||
const nameCandidate = source.machineName ?? null
|
||||
const normalized = normalizeMachineAssignment(nameCandidate || idCandidate)
|
||||
if (normalized) assignments.push(normalized)
|
||||
}
|
||||
|
||||
return dedupeAssignments(assignments)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Component assignments
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const normalizeComponentAssignment = (input: unknown): AnyRecord | null => {
|
||||
if (!input) return null
|
||||
if (typeof input === 'string') {
|
||||
const value = toTrimmedString(input)
|
||||
return value ? { id: value, name: value } : null
|
||||
}
|
||||
if (typeof input === 'number' && Number.isFinite(input)) {
|
||||
const value = String(input)
|
||||
return { id: value, name: value }
|
||||
}
|
||||
|
||||
const container =
|
||||
(input as AnyRecord).component || (input as AnyRecord).composant || input
|
||||
if (!isPlainObject(container)) return null
|
||||
|
||||
const id =
|
||||
container.id ??
|
||||
(input as AnyRecord).componentId ??
|
||||
(input as AnyRecord).composantId ??
|
||||
(input as AnyRecord).id ??
|
||||
null
|
||||
const name =
|
||||
container.name ||
|
||||
(input as AnyRecord).componentName ||
|
||||
(input as AnyRecord).composantName ||
|
||||
container.label ||
|
||||
(typeof id === 'string' ? id : null) ||
|
||||
(typeof id === 'number' ? String(id) : null)
|
||||
|
||||
if (id == null && name == null) return null
|
||||
|
||||
return {
|
||||
id: id != null ? id : null,
|
||||
name: name != null ? name : null,
|
||||
}
|
||||
}
|
||||
|
||||
export const collectComponentAssignments = (source: unknown): AnyRecord[] => {
|
||||
if (!isPlainObject(source)) return []
|
||||
|
||||
const candidates = [
|
||||
source.components,
|
||||
source.composants,
|
||||
source.componentLinks,
|
||||
source.linkedComponents,
|
||||
]
|
||||
|
||||
const assignments: AnyRecord[] = []
|
||||
|
||||
candidates.forEach((list) => {
|
||||
if (Array.isArray(list)) {
|
||||
list.forEach((item) => {
|
||||
const normalized = normalizeComponentAssignment(item)
|
||||
if (normalized) assignments.push(normalized)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
if (!assignments.length) {
|
||||
const direct = normalizeComponentAssignment(source.component || source.composant)
|
||||
if (direct) assignments.push(direct)
|
||||
}
|
||||
|
||||
if (!assignments.length) {
|
||||
const idCandidate = source.componentId ?? source.composantId ?? null
|
||||
const normalized = normalizeComponentAssignment(idCandidate)
|
||||
if (normalized) assignments.push(normalized)
|
||||
}
|
||||
|
||||
return dedupeAssignments(assignments)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Convenience wrappers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const getComponentMachineAssignments = (component: unknown): AnyRecord[] =>
|
||||
collectMachineAssignments(component || {})
|
||||
|
||||
export const getPieceMachineAssignments = (piece: unknown): AnyRecord[] =>
|
||||
collectMachineAssignments(piece || {})
|
||||
|
||||
export const getPieceComponentAssignments = (piece: unknown): AnyRecord[] =>
|
||||
collectComponentAssignments(piece || {})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Display
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const formatAssignmentList = (assignments: AnyRecord[]): string => {
|
||||
if (!Array.isArray(assignments) || assignments.length === 0) return ''
|
||||
return assignments
|
||||
.map((assignment) => (assignment?.name || assignment?.id) as string)
|
||||
.filter(Boolean)
|
||||
.join(', ')
|
||||
}
|
||||
Reference in New Issue
Block a user