225 lines
6.9 KiB
JavaScript
225 lines
6.9 KiB
JavaScript
import { ref } from 'vue'
|
|
import { useToast } from './useToast'
|
|
import { useApi } from './useApi'
|
|
import { buildConstructeurRequestPayload, uniqueConstructeurIds } from '~/shared/constructeurUtils'
|
|
import { useConstructeurs } from './useConstructeurs'
|
|
import { extractRelationId, normalizeRelationIds } from '~/shared/apiRelations'
|
|
|
|
const pieces = ref([])
|
|
const total = ref(0)
|
|
const loading = ref(false)
|
|
|
|
const extractCollection = (payload) => {
|
|
if (Array.isArray(payload)) {
|
|
return payload
|
|
}
|
|
if (Array.isArray(payload?.member)) {
|
|
return payload.member
|
|
}
|
|
if (Array.isArray(payload?.['hydra:member'])) {
|
|
return payload['hydra:member']
|
|
}
|
|
if (Array.isArray(payload?.data)) {
|
|
return payload.data
|
|
}
|
|
return []
|
|
}
|
|
|
|
const extractTotal = (payload, fallbackLength) => {
|
|
if (typeof payload?.totalItems === 'number') {
|
|
return payload.totalItems
|
|
}
|
|
if (typeof payload?.['hydra:totalItems'] === 'number') {
|
|
return payload['hydra:totalItems']
|
|
}
|
|
return fallbackLength
|
|
}
|
|
|
|
export function usePieces () {
|
|
const { showSuccess, showError, showInfo } = useToast()
|
|
const { get, post, patch, delete: del } = useApi()
|
|
const { ensureConstructeurs } = useConstructeurs()
|
|
|
|
const withResolvedConstructeurs = async (piece) => {
|
|
if (!piece || typeof piece !== 'object') {
|
|
return piece
|
|
}
|
|
if (!piece.typePieceId) {
|
|
const typePieceId = extractRelationId(piece.typePiece)
|
|
if (typePieceId) {
|
|
piece.typePieceId = typePieceId
|
|
}
|
|
}
|
|
if (!piece.productId) {
|
|
const productId = extractRelationId(piece.product)
|
|
if (productId) {
|
|
piece.productId = productId
|
|
}
|
|
}
|
|
const productIds = Array.isArray(piece.productIds) ? piece.productIds.filter(Boolean) : []
|
|
if (productIds.length === 0 && piece.productId) {
|
|
piece.productIds = [piece.productId]
|
|
} else if (productIds.length > 0) {
|
|
piece.productIds = productIds.map((id) => String(id))
|
|
if (!piece.productId) {
|
|
piece.productId = piece.productIds[0] || null
|
|
}
|
|
}
|
|
const ids = uniqueConstructeurIds(
|
|
piece.constructeurIds,
|
|
piece.constructeurs,
|
|
piece.constructeur,
|
|
)
|
|
const hasResolvedConstructeurs =
|
|
Array.isArray(piece.constructeurs)
|
|
&& piece.constructeurs.length > 0
|
|
&& piece.constructeurs.every((item) => item && typeof item === 'object')
|
|
|
|
if (ids.length && !hasResolvedConstructeurs) {
|
|
const resolved = await ensureConstructeurs(ids)
|
|
if (resolved.length) {
|
|
piece.constructeurs = resolved
|
|
piece.constructeurIds = ids
|
|
}
|
|
}
|
|
return piece
|
|
}
|
|
|
|
/**
|
|
* Load pieces with pagination and search support
|
|
* @param {Object} options - Query options
|
|
* @param {string} [options.search] - Search term for name/reference
|
|
* @param {number} [options.page=1] - Current page (1-based)
|
|
* @param {number} [options.itemsPerPage=30] - Items per page
|
|
* @param {string} [options.orderBy='name'] - Field to order by
|
|
* @param {string} [options.orderDir='asc'] - Order direction (asc/desc)
|
|
*/
|
|
const loadPieces = async (options = {}) => {
|
|
loading.value = true
|
|
try {
|
|
const {
|
|
search = '',
|
|
page = 1,
|
|
itemsPerPage = 30,
|
|
orderBy = 'name',
|
|
orderDir = 'asc'
|
|
} = options
|
|
|
|
const params = new URLSearchParams()
|
|
params.set('itemsPerPage', String(itemsPerPage))
|
|
params.set('page', String(page))
|
|
|
|
if (search && search.trim()) {
|
|
// API Platform uses property filters
|
|
params.set('name', search.trim())
|
|
}
|
|
|
|
// API Platform OrderFilter syntax: order[field]=direction
|
|
params.set(`order[${orderBy}]`, orderDir)
|
|
|
|
const result = await get(`/pieces?${params.toString()}`)
|
|
if (result.success) {
|
|
const items = extractCollection(result.data)
|
|
const enrichedItems = await Promise.all(items.map((item) => withResolvedConstructeurs(item)))
|
|
pieces.value = enrichedItems
|
|
total.value = extractTotal(result.data, items.length)
|
|
return {
|
|
success: true,
|
|
data: {
|
|
items: enrichedItems,
|
|
total: total.value,
|
|
page,
|
|
itemsPerPage
|
|
}
|
|
}
|
|
}
|
|
return result
|
|
} catch (error) {
|
|
console.error('Erreur lors du chargement des pièces:', error)
|
|
return { success: false, error: error.message }
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const createPiece = async (pieceData) => {
|
|
loading.value = true
|
|
try {
|
|
const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(pieceData))
|
|
const result = await post('/pieces', normalizedPayload)
|
|
if (result.success) {
|
|
const enriched = await withResolvedConstructeurs(result.data)
|
|
pieces.value.unshift(enriched)
|
|
total.value += 1
|
|
const displayName = result.data?.name
|
|
|| pieceData?.definition?.name
|
|
|| pieceData?.name
|
|
|| 'Pièce'
|
|
showSuccess(`Pièce "${displayName}" créée avec succès`)
|
|
}
|
|
return result
|
|
} catch (error) {
|
|
console.error('Erreur lors de la création de la pièce:', error)
|
|
return { success: false, error: error.message }
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const updatePieceData = async (id, pieceData) => {
|
|
loading.value = true
|
|
try {
|
|
const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(pieceData))
|
|
const result = await patch(`/pieces/${id}`, normalizedPayload)
|
|
if (result.success) {
|
|
const updated = await withResolvedConstructeurs(result.data)
|
|
const index = pieces.value.findIndex(piece => piece.id === id)
|
|
if (index !== -1) {
|
|
pieces.value[index] = updated
|
|
}
|
|
showSuccess(`Pièce "${updated?.name || pieceData.name || ''}" mise à jour avec succès`)
|
|
}
|
|
return result
|
|
} catch (error) {
|
|
console.error('Erreur lors de la mise à jour de la pièce:', error)
|
|
return { success: false, error: error.message }
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const deletePiece = async (id) => {
|
|
loading.value = true
|
|
try {
|
|
const result = await del(`/pieces/${id}`)
|
|
if (result.success) {
|
|
const deletedPiece = pieces.value.find(piece => piece.id === id)
|
|
pieces.value = pieces.value.filter(piece => piece.id !== id)
|
|
total.value = Math.max(0, total.value - 1)
|
|
showSuccess(`Pièce "${deletedPiece?.name || 'inconnu'}" supprimée avec succès`)
|
|
}
|
|
return result
|
|
} catch (error) {
|
|
console.error('Erreur lors de la suppression de la pièce:', error)
|
|
return { success: false, error: error.message }
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const getPieces = () => pieces.value
|
|
const isLoading = () => loading.value
|
|
|
|
return {
|
|
pieces,
|
|
total,
|
|
loading,
|
|
loadPieces,
|
|
createPiece,
|
|
updatePiece: updatePieceData,
|
|
deletePiece,
|
|
getPieces,
|
|
isLoading
|
|
}
|
|
}
|