import { ref } from 'vue' import { useToast } from './useToast' import { useApi } from './useApi' import { uniqueConstructeurIds } from '~/shared/constructeurUtils' import { useConstructeurs, type Constructeur } from './useConstructeurs' import { extractRelationId, normalizeRelationIds } from '~/shared/apiRelations' import { extractCollection, extractTotal } from '~/shared/utils/apiHelpers' export interface Composant { id: string name: string reference?: string | null description?: string | null typeComposantId?: string | null typeComposant?: { id: string; name?: string } | null productId?: string | null product?: { id: string; name?: string } | null constructeurs?: Constructeur[] constructeurIds?: string[] documents?: unknown[] createdAt?: string | null updatedAt?: string | null [key: string]: unknown } interface ComposantListResult { success: boolean data?: { items: Composant[]; total: number; page: number; itemsPerPage: number } error?: string } interface ComposantSingleResult { success: boolean data?: Composant error?: string } interface LoadComposantsOptions { search?: string page?: number itemsPerPage?: number orderBy?: string orderDir?: 'asc' | 'desc' typeName?: string typeComposantId?: string force?: boolean } const composants = ref([]) const total = ref(0) const loading = ref(false) const loaded = ref(false) export function useComposants() { const { showSuccess } = useToast() const { get, post, patch, delete: del } = useApi() const { ensureConstructeurs } = useConstructeurs() const withResolvedConstructeurs = async (composant: Composant): Promise => { if (!composant || typeof composant !== 'object') { return composant } if (!composant.typeComposantId) { const typeComposantId = extractRelationId(composant.typeComposant) if (typeComposantId) { composant.typeComposantId = typeComposantId } } if (!composant.productId) { const productId = extractRelationId(composant.product) if (productId) { composant.productId = productId } } const ids = uniqueConstructeurIds( composant.constructeurIds, composant.constructeurs, ) const hasResolvedConstructeurs = Array.isArray(composant.constructeurs) && composant.constructeurs.length > 0 && composant.constructeurs.every((item) => item && typeof item === 'object') if (ids.length && !hasResolvedConstructeurs) { const resolved = await ensureConstructeurs(ids) if (resolved.length) { composant.constructeurs = resolved composant.constructeurIds = ids } } return composant } const loadComposants = async (options: LoadComposantsOptions = {}): Promise => { const { search = '', page = 1, itemsPerPage = 30, orderBy = 'name', orderDir = 'asc', typeName, typeComposantId, force = false, } = options if (!force && loaded.value && !search && !typeName && !typeComposantId && page === 1) { return { success: true, data: { items: composants.value, total: total.value, page, itemsPerPage }, } } if (!typeComposantId && loading.value) { return { success: true, data: { items: composants.value, total: total.value, page, itemsPerPage }, } } loading.value = true try { const params = new URLSearchParams() params.set('itemsPerPage', String(itemsPerPage)) params.set('page', String(page)) if (search && search.trim()) { params.set('search', search.trim()) } if (typeName && typeName.trim()) { params.set('typeComposant.name', typeName.trim()) } if (typeComposantId) { params.set('typeComposant', typeComposantId) } params.set(`order[${orderBy}]`, orderDir) const result = await get(`/composants?${params.toString()}`) if (result.success) { const items = extractCollection(result.data) const enrichedItems = await Promise.all(items.map((item) => withResolvedConstructeurs(item))) const resultTotal = extractTotal(result.data, items.length) if (!typeComposantId) { composants.value = enrichedItems total.value = resultTotal loaded.value = true } return { success: true, data: { items: enrichedItems, total: resultTotal, page, itemsPerPage, }, } } return result as ComposantListResult } catch (error) { console.error('Erreur lors du chargement des composants:', error) return { success: false, error: (error as Error).message } } finally { loading.value = false } } const createComposant = async (composantData: Partial): Promise => { loading.value = true try { const { constructeurIds, constructeurs, constructeurId, constructeur, ...cleanPayload } = composantData as any const normalizedPayload = normalizeRelationIds(cleanPayload) const result = await post('/composants', normalizedPayload) if (result.success && result.data) { const enriched = await withResolvedConstructeurs(result.data as Composant) composants.value.unshift(enriched) total.value += 1 const definition = (composantData as Record)?.definition as Record | undefined const displayName = (result.data as Composant)?.name || (definition?.name as string | undefined) || composantData?.name || 'Composant' showSuccess(`Composant "${displayName}" créé avec succès`) return { success: true, data: enriched } } return { success: false, error: result.error } } catch (error) { console.error('Erreur lors de la création du composant:', error) return { success: false, error: (error as Error).message } } finally { loading.value = false } } const updateComposantData = async (id: string, composantData: Partial): Promise => { loading.value = true try { const { constructeurIds, constructeurs, constructeurId, constructeur, ...cleanPayload } = composantData as any const normalizedPayload = normalizeRelationIds(cleanPayload) const result = await patch(`/composants/${id}`, normalizedPayload) if (result.success && result.data) { const updated = await withResolvedConstructeurs(result.data as Composant) const index = composants.value.findIndex((comp) => comp.id === id) if (index !== -1) { composants.value[index] = updated } showSuccess(`Composant "${updated?.name || composantData.name || ''}" mis à jour avec succès`) return { success: true, data: updated } } return { success: false, error: result.error } } catch (error) { console.error('Erreur lors de la mise à jour du composant:', error) return { success: false, error: (error as Error).message } } finally { loading.value = false } } const deleteComposant = async (id: string): Promise => { loading.value = true try { const result = await del(`/composants/${id}`) if (result.success) { const deletedComposant = composants.value.find((comp) => comp.id === id) composants.value = composants.value.filter((comp) => comp.id !== id) total.value = Math.max(0, total.value - 1) showSuccess(`Composant "${deletedComposant?.name || 'inconnu'}" supprimé avec succès`) return { success: true } } return { success: false, error: result.error } } catch (error) { console.error('Erreur lors de la suppression du composant:', error) return { success: false, error: (error as Error).message } } finally { loading.value = false } } const getComposants = () => composants.value const isLoading = () => loading.value const clearComposantsCache = () => { composants.value = [] total.value = 0 loaded.value = false } return { composants, total, loading, loaded, loadComposants, createComposant, updateComposant: updateComposantData, deleteComposant, getComposants, isLoading, clearComposantsCache, } }