Files
Inventory/app/composables/useConstructeurs.ts

231 lines
6.8 KiB
TypeScript

import { ref } from 'vue'
import { useApi } from './useApi'
import { useToast } from './useToast'
export interface Constructeur {
id: string
name: string
email?: string | null
phone?: string | null
}
interface ConstructeurResult {
success: boolean
data?: Constructeur | Constructeur[]
error?: string
}
const constructeurs = ref<Constructeur[]>([])
const loading = ref(false)
const uniqueConstructeurs = (items: Constructeur[] = []): Constructeur[] => {
const map = new Map<string, Constructeur>()
items.forEach((item) => {
if (item && typeof item === 'object' && typeof item.id === 'string') {
map.set(item.id, item)
}
})
return Array.from(map.values())
}
const normalizeIds = (ids: unknown[] = []): string[] => {
if (!Array.isArray(ids)) {
return []
}
return Array.from(
new Set(
ids
.map((value) => (typeof value === 'string' ? value.trim() : ''))
.filter((value) => value.length > 0),
),
)
}
const upsertConstructeurs = (items: Constructeur[] = []) => {
if (!Array.isArray(items) || !items.length) {
return
}
const merged = uniqueConstructeurs([...constructeurs.value, ...items])
constructeurs.value = merged
}
const getIndexedConstructeur = (id: string): Constructeur | null =>
constructeurs.value.find((item) => item && item.id === id) || null
const extractCollection = (payload: unknown): Constructeur[] => {
if (Array.isArray(payload)) {
return payload as Constructeur[]
}
const p = payload as Record<string, unknown> | null
if (Array.isArray(p?.member)) {
return p.member as Constructeur[]
}
if (Array.isArray(p?.['hydra:member'])) {
return p['hydra:member'] as Constructeur[]
}
if (Array.isArray(p?.data)) {
return p.data as Constructeur[]
}
return []
}
const pendingFetches = new Map<string, Promise<Constructeur | null>>()
export function useConstructeurs() {
const { get, post, patch, delete: del } = useApi()
const { showSuccess, showError } = useToast()
const loadConstructeurs = async (search = ''): Promise<ConstructeurResult> => {
loading.value = true
try {
const query = search ? `?search=${encodeURIComponent(search)}` : ''
const result = await get(`/constructeurs${query}`)
if (result.success) {
const items = extractCollection(result.data)
constructeurs.value = uniqueConstructeurs(items)
}
return result as ConstructeurResult
} catch (error) {
const err = error as Error
console.error('Erreur lors du chargement des fournisseurs:', error)
return { success: false, error: err.message }
} finally {
loading.value = false
}
}
const searchConstructeurs = async (search = ''): Promise<ConstructeurResult> => {
return loadConstructeurs(search)
}
const createConstructeur = async (data: Partial<Constructeur>): Promise<ConstructeurResult> => {
loading.value = true
try {
const result = await post('/constructeurs', data)
if (result.success) {
upsertConstructeurs([result.data as Constructeur])
showSuccess(`Fournisseur "${(result.data as Constructeur).name}" créé`)
} else if (result.error) {
showError(result.error)
}
return result as ConstructeurResult
} catch (error) {
const err = error as Error
console.error('Erreur lors de la création du fournisseur:', error)
showError('Impossible de créer le fournisseur')
return { success: false, error: err.message }
} finally {
loading.value = false
}
}
const ensureConstructeurs = async (ids: unknown[] = []): Promise<Constructeur[]> => {
const normalizedIds = normalizeIds(ids)
if (!normalizedIds.length) {
return []
}
const collected: Constructeur[] = []
const missing: string[] = []
normalizedIds.forEach((id) => {
const existing = getIndexedConstructeur(id)
if (existing) {
collected.push(existing)
} else {
missing.push(id)
}
})
if (missing.length) {
const fetchTasks = missing.map((id) => {
const cached = pendingFetches.get(id)
if (cached) {
return cached
}
const task = get(`/constructeurs/${id}`)
.then((result) => {
if (result.success && result.data) {
return result.data as Constructeur
}
return null
})
.catch((error) => {
console.error('Erreur lors du chargement du fournisseur:', error)
return null
})
.finally(() => {
pendingFetches.delete(id)
})
pendingFetches.set(id, task)
return task
})
const fetched = await Promise.all(fetchTasks)
const validFetched = fetched.filter((item): item is Constructeur => item !== null && item.id !== undefined)
if (validFetched.length) {
upsertConstructeurs(validFetched)
}
}
return normalizedIds
.map((id) => getIndexedConstructeur(id))
.filter((item): item is Constructeur => item !== null)
}
const updateConstructeur = async (id: string, data: Partial<Constructeur>): Promise<ConstructeurResult> => {
loading.value = true
try {
const result = await patch(`/constructeurs/${id}`, data)
if (result.success) {
upsertConstructeurs([result.data as Constructeur])
showSuccess(`Fournisseur "${(result.data as Constructeur).name}" mis à jour`)
} else if (result.error) {
showError(result.error)
}
return result as ConstructeurResult
} catch (error) {
const err = error as Error
console.error('Erreur lors de la mise à jour du fournisseur:', error)
showError('Impossible de mettre à jour le fournisseur')
return { success: false, error: err.message }
} finally {
loading.value = false
}
}
const deleteConstructeur = async (id: string): Promise<ConstructeurResult> => {
loading.value = true
try {
const result = await del(`/constructeurs/${id}`)
if (result.success) {
constructeurs.value = constructeurs.value.filter((item) => item.id !== id)
showSuccess('Fournisseur supprimé')
} else if (result.error) {
showError(result.error)
}
return result as ConstructeurResult
} catch (error) {
const err = error as Error
console.error('Erreur lors de la suppression du fournisseur:', error)
showError('Impossible de supprimer le fournisseur')
return { success: false, error: err.message }
} finally {
loading.value = false
}
}
const getConstructeurById = (id: string) => getIndexedConstructeur(id)
return {
constructeurs,
loading,
loadConstructeurs,
searchConstructeurs,
createConstructeur,
updateConstructeur,
deleteConstructeur,
getConstructeurById,
ensureConstructeurs,
}
}