diff --git a/app/app.vue b/app/app.vue
index 329f5ac..e0dea99 100644
--- a/app/app.vue
+++ b/app/app.vue
@@ -30,7 +30,7 @@
: 'text-base-content hover:bg-primary/10 hover:text-primary'
"
>
- Vue d'ensemble
+ Vue d'ensemblee
diff --git a/app/composables/useApi.js b/app/composables/useApi.js
index b2945e7..b1a4233 100644
--- a/app/composables/useApi.js
+++ b/app/composables/useApi.js
@@ -10,6 +10,7 @@ export function useApi () {
const apiCall = async (endpoint, options = {}) => {
const url = `${API_BASE_URL}${endpoint}`
const defaultOptions = {
+ credentials: 'include',
headers: {
'Content-Type': 'application/json'
}
@@ -32,7 +33,7 @@ export function useApi () {
let data = null
if (response.status !== 204) {
const contentType = response.headers.get('content-type') || ''
- if (contentType.includes('application/json')) {
+ if (contentType.includes('application/json') || contentType.includes('application/ld+json') || contentType.includes('+json')) {
const text = await response.text()
data = text ? JSON.parse(text) : null
} else {
diff --git a/app/composables/useComposants.js b/app/composables/useComposants.js
index 5599ede..5bdf629 100644
--- a/app/composables/useComposants.js
+++ b/app/composables/useComposants.js
@@ -3,10 +3,27 @@ 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 composants = ref([])
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 []
+}
+
export function useComposants () {
const { showSuccess, showError, showInfo } = useToast()
const { get, post, patch, delete: del } = useApi()
@@ -16,6 +33,18 @@ export function useComposants () {
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,
@@ -34,27 +63,28 @@ export function useComposants () {
return composant
}
-const loadComposants = async () => {
- loading.value = true
- try {
- const result = await get('/composants')
- if (result.success) {
- const items = Array.isArray(result.data) ? result.data : []
- const enrichedItems = await Promise.all(items.map((item) => withResolvedConstructeurs(item)))
- composants.value = enrichedItems
- showInfo(`Chargement de ${composants.value.length} composant(s) réussi`)
+ const loadComposants = async () => {
+ loading.value = true
+ try {
+ const result = await get('/composants')
+ if (result.success) {
+ const items = extractCollection(result.data)
+ const enrichedItems = await Promise.all(items.map((item) => withResolvedConstructeurs(item)))
+ composants.value = enrichedItems
+ showInfo(`Chargement de ${composants.value.length} composant(s) réussi`)
+ }
+ } catch (error) {
+ console.error('Erreur lors du chargement des composants:', error)
+ } finally {
+ loading.value = false
}
- } catch (error) {
- console.error('Erreur lors du chargement des composants:', error)
- } finally {
- loading.value = false
}
-}
const createComposant = async (composantData) => {
loading.value = true
try {
- const result = await post('/composants', buildConstructeurRequestPayload(composantData))
+ const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(composantData))
+ const result = await post('/composants', normalizedPayload)
if (result.success) {
const enriched = await withResolvedConstructeurs(result.data)
composants.value.push(enriched)
@@ -76,7 +106,8 @@ const loadComposants = async () => {
const updateComposantData = async (id, composantData) => {
loading.value = true
try {
- const result = await patch(`/composants/${id}`, buildConstructeurRequestPayload(composantData))
+ const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(composantData))
+ const result = await patch(`/composants/${id}`, normalizedPayload)
if (result.success) {
const updated = await withResolvedConstructeurs(result.data)
const index = composants.value.findIndex(comp => comp.id === id)
diff --git a/app/composables/useConstructeurs.js b/app/composables/useConstructeurs.js
index 025e5ed..67a2996 100644
--- a/app/composables/useConstructeurs.js
+++ b/app/composables/useConstructeurs.js
@@ -39,6 +39,22 @@ const upsertConstructeurs = (items = []) => {
const getIndexedConstructeur = (id) =>
constructeurs.value.find((item) => item && item.id === id) || null
+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 pendingFetches = new Map()
export function useConstructeurs () {
@@ -51,7 +67,7 @@ export function useConstructeurs () {
const query = search ? `?search=${encodeURIComponent(search)}` : ''
const result = await get(`/constructeurs${query}`)
if (result.success) {
- const items = Array.isArray(result.data) ? result.data : []
+ const items = extractCollection(result.data)
constructeurs.value = uniqueConstructeurs(items)
}
return result
diff --git a/app/composables/useDocuments.js b/app/composables/useDocuments.js
index 5b89cd6..8177fe2 100644
--- a/app/composables/useDocuments.js
+++ b/app/composables/useDocuments.js
@@ -1,10 +1,27 @@
import { ref } from 'vue'
import { useApi } from './useApi'
import { useToast } from './useToast'
+import { normalizeRelationIds } from '~/shared/apiRelations'
const documents = ref([])
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 fileToBase64 = file =>
new Promise((resolve, reject) => {
const reader = new FileReader()
@@ -22,7 +39,7 @@ export function useDocuments () {
try {
const result = await get(endpoint)
if (result.success) {
- const data = result.data || []
+ const data = extractCollection(result.data)
if (updateStore) {
documents.value = data
}
@@ -80,14 +97,14 @@ export function useDocuments () {
for (const file of files) {
const dataUrl = await fileToBase64(file)
- const payload = {
+ const payload = normalizeRelationIds({
name: file.name,
filename: file.name,
mimeType: file.type || 'application/octet-stream',
size: file.size,
path: dataUrl,
...context
- }
+ })
const result = await post('/documents', payload)
if (result.success) {
diff --git a/app/composables/useMachineTypesApi.js b/app/composables/useMachineTypesApi.js
index 2f38673..83f47fa 100644
--- a/app/composables/useMachineTypesApi.js
+++ b/app/composables/useMachineTypesApi.js
@@ -1,11 +1,30 @@
import { ref } from 'vue'
import { useToast } from './useToast'
import { useApi } from './useApi'
+import { extractRelationId } from '~/shared/apiRelations'
const machineTypes = ref([])
const loading = ref(false)
-const normalizeRequirementList = (value) => (Array.isArray(value) ? value : [])
+const normalizeRequirementList = (value, relationKey) => {
+ if (!Array.isArray(value)) {
+ return []
+ }
+ return value.map((entry) => {
+ if (!entry || typeof entry !== 'object') {
+ return entry
+ }
+ const normalized = { ...entry }
+ if (relationKey && !normalized[relationKey]) {
+ const relationValue = normalized[relationKey.replace('Id', '')]
+ const relationId = extractRelationId(relationValue)
+ if (relationId) {
+ normalized[relationKey] = relationId
+ }
+ }
+ return normalized
+ })
+}
const normalizeMachineType = (type) => {
if (!type || typeof type !== 'object') {
@@ -13,12 +32,28 @@ const normalizeMachineType = (type) => {
}
return {
...type,
- componentRequirements: normalizeRequirementList(type.componentRequirements),
- pieceRequirements: normalizeRequirementList(type.pieceRequirements),
- productRequirements: normalizeRequirementList(type.productRequirements),
+ componentRequirements: normalizeRequirementList(type.componentRequirements, 'typeComposantId'),
+ pieceRequirements: normalizeRequirementList(type.pieceRequirements, 'typePieceId'),
+ productRequirements: normalizeRequirementList(type.productRequirements, 'typeProductId'),
}
}
+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 []
+}
+
export function useMachineTypesApi () {
const { showSuccess, showError, showInfo } = useToast()
const { get, post, patch, delete: del } = useApi()
@@ -26,11 +61,10 @@ export function useMachineTypesApi () {
const loadMachineTypes = async () => {
loading.value = true
try {
- const result = await get('/types/machines')
+ const result = await get('/type_machines')
if (result.success) {
- machineTypes.value = Array.isArray(result.data)
- ? result.data.map(normalizeMachineType)
- : []
+ const items = extractCollection(result.data)
+ machineTypes.value = items.map(normalizeMachineType)
showInfo(`Chargement de ${machineTypes.value.length} type(s) de machine réussi`)
}
} catch (error) {
@@ -43,7 +77,7 @@ export function useMachineTypesApi () {
const createMachineType = async (typeData) => {
loading.value = true
try {
- const result = await post('/types/machines', typeData)
+ const result = await post('/type_machines', typeData)
if (result.success) {
machineTypes.value.push(normalizeMachineType(result.data))
showSuccess(`Type de machine "${typeData.name}" créé avec succès`)
@@ -60,7 +94,7 @@ export function useMachineTypesApi () {
const updateMachineType = async (id, typeData) => {
loading.value = true
try {
- const result = await patch(`/types/machines/${id}`, typeData)
+ const result = await patch(`/type_machines/${id}`, typeData)
if (result.success) {
const normalized = normalizeMachineType(result.data)
const index = machineTypes.value.findIndex(type => type.id === id)
@@ -81,7 +115,7 @@ export function useMachineTypesApi () {
const deleteMachineType = async (id) => {
loading.value = true
try {
- const result = await del(`/types/machines/${id}`)
+ const result = await del(`/type_machines/${id}`)
if (result.success) {
const deletedType = machineTypes.value.find(type => type.id === id)
machineTypes.value = machineTypes.value.filter(type => type.id !== id)
@@ -105,7 +139,7 @@ export function useMachineTypesApi () {
// Si pas trouvé localement, récupérer depuis l'API
try {
- const result = await get(`/types/machines/${id}`)
+ const result = await get(`/type_machines/${id}`)
if (result.success) {
// Ajouter au cache local
machineTypes.value.push(normalizeMachineType(result.data))
diff --git a/app/composables/useMachines.js b/app/composables/useMachines.js
index 9e4a0c6..35141df 100644
--- a/app/composables/useMachines.js
+++ b/app/composables/useMachines.js
@@ -2,6 +2,7 @@ import { ref } from 'vue'
import { useToast } from './useToast'
import { useApi } from './useApi'
import { buildConstructeurRequestPayload } from '~/shared/constructeurUtils'
+import { extractRelationId, normalizeRelationIds } from '~/shared/apiRelations'
const machines = ref([])
const loading = ref(false)
@@ -32,6 +33,20 @@ const normalizeMachineResponse = (payload) => {
const normalized = { ...container }
+ if (!normalized.siteId) {
+ const siteId = extractRelationId(container.site)
+ if (siteId) {
+ normalized.siteId = siteId
+ }
+ }
+
+ if (!normalized.typeMachineId) {
+ const typeMachineId = extractRelationId(container.typeMachine)
+ if (typeMachineId) {
+ normalized.typeMachineId = typeMachineId
+ }
+ }
+
const componentLinks = resolveLinkCollection(payload, ['componentLinks', 'machineComponentLinks']) ??
resolveLinkCollection(container, ['componentLinks', 'machineComponentLinks']) ??
[]
@@ -56,11 +71,15 @@ export function useMachines () {
if (result.success) {
const machineList = Array.isArray(result.data)
? result.data
- : Array.isArray(result.data?.machines)
- ? result.data.machines
- : Array.isArray(result.data?.data)
- ? result.data.data
- : []
+ : Array.isArray(result.data?.member)
+ ? result.data.member
+ : Array.isArray(result.data?.['hydra:member'])
+ ? result.data['hydra:member']
+ : Array.isArray(result.data?.machines)
+ ? result.data.machines
+ : Array.isArray(result.data?.data)
+ ? result.data.data
+ : []
const normalized = machineList
.map((item) => normalizeMachineResponse(item))
.filter(Boolean)
@@ -77,7 +96,8 @@ export function useMachines () {
const createMachine = async (machineData) => {
loading.value = true
try {
- const result = await post('/machines', buildConstructeurRequestPayload(machineData))
+ const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(machineData))
+ const result = await post('/machines', normalizedPayload)
if (result.success) {
const createdMachine = normalizeMachineResponse(result.data) ||
normalizeMachineResponse(result.data?.machine) ||
@@ -106,13 +126,14 @@ export function useMachines () {
// Les composants et pièces seront créés automatiquement
}
- return await createMachine(buildConstructeurRequestPayload(machineWithStructure))
+ return await createMachine(machineWithStructure)
}
const updateMachineData = async (id, machineData) => {
loading.value = true
try {
- const result = await patch(`/machines/${id}`, buildConstructeurRequestPayload(machineData))
+ const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(machineData))
+ const result = await patch(`/machines/${id}`, normalizedPayload)
if (result.success) {
const updatedMachine = normalizeMachineResponse(result.data) ||
normalizeMachineResponse(result.data?.machine) ||
diff --git a/app/composables/usePieces.js b/app/composables/usePieces.js
index aa0112e..b27964e 100644
--- a/app/composables/usePieces.js
+++ b/app/composables/usePieces.js
@@ -3,10 +3,27 @@ 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 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 []
+}
+
export function usePieces () {
const { showSuccess, showError, showInfo } = useToast()
const { get, post, patch, delete: del } = useApi()
@@ -16,6 +33,18 @@ export function usePieces () {
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 ids = uniqueConstructeurIds(
piece.constructeurIds,
piece.constructeurs,
@@ -39,7 +68,7 @@ export function usePieces () {
try {
const result = await get('/pieces')
if (result.success) {
- const items = Array.isArray(result.data) ? result.data : []
+ const items = extractCollection(result.data)
const enrichedItems = await Promise.all(items.map((item) => withResolvedConstructeurs(item)))
pieces.value = enrichedItems
showInfo(`Chargement de ${pieces.value.length} pièce(s) réussi`)
@@ -54,7 +83,8 @@ export function usePieces () {
const createPiece = async (pieceData) => {
loading.value = true
try {
- const result = await post('/pieces', buildConstructeurRequestPayload(pieceData))
+ const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(pieceData))
+ const result = await post('/pieces', normalizedPayload)
if (result.success) {
const enriched = await withResolvedConstructeurs(result.data)
pieces.value.push(enriched)
@@ -76,7 +106,8 @@ export function usePieces () {
const updatePieceData = async (id, pieceData) => {
loading.value = true
try {
- const result = await patch(`/pieces/${id}`, buildConstructeurRequestPayload(pieceData))
+ 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)
diff --git a/app/composables/useProducts.js b/app/composables/useProducts.js
index 9a90ed7..9b8b204 100644
--- a/app/composables/useProducts.js
+++ b/app/composables/useProducts.js
@@ -3,6 +3,7 @@ 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 products = ref([])
const total = ref(0)
@@ -25,6 +26,22 @@ const replaceInCache = (item) => {
return 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 []
+}
+
export function useProducts () {
const { showError } = useToast()
const { get, post, patch, delete: del } = useApi()
@@ -34,6 +51,12 @@ export function useProducts () {
if (!product || typeof product !== 'object') {
return product
}
+ if (!product.typeProductId) {
+ const typeProductId = extractRelationId(product.typeProduct)
+ if (typeProductId) {
+ product.typeProductId = typeProductId
+ }
+ }
const ids = uniqueConstructeurIds(
product.constructeurIds,
product.constructeurs,
@@ -69,12 +92,14 @@ export function useProducts () {
loading.value = true
error.value = null
try {
- const result = await get('/products?limit=100')
+ const result = await get('/products?itemsPerPage=100')
if (result.success) {
- const items = Array.isArray(result.data?.items) ? result.data.items : []
+ const items = extractCollection(result.data)
const enrichedItems = await Promise.all(items.map((item) => withResolvedConstructeurs(item)))
products.value = enrichedItems
- total.value = typeof result.data?.total === 'number' ? result.data.total : items.length
+ total.value = typeof result.data?.totalItems === 'number'
+ ? result.data.totalItems
+ : items.length
loaded.value = true
} else if (result.error) {
error.value = result.error
@@ -93,7 +118,7 @@ export function useProducts () {
}
const createProduct = async (payload) => {
- const normalizedPayload = buildConstructeurRequestPayload(payload)
+ const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(payload))
loading.value = true
error.value = null
try {
@@ -121,7 +146,7 @@ export function useProducts () {
}
const updateProduct = async (id, payload) => {
- const normalizedPayload = buildConstructeurRequestPayload(payload)
+ const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(payload))
loading.value = true
error.value = null
try {
diff --git a/app/composables/useProfileSession.js b/app/composables/useProfileSession.js
index 0a09fd1..83be2f2 100644
--- a/app/composables/useProfileSession.js
+++ b/app/composables/useProfileSession.js
@@ -2,7 +2,10 @@ import { useState, useRequestHeaders, useRuntimeConfig } from '#imports'
const buildUrl = (path) => {
const config = useRuntimeConfig()
- const base = config.public.apiBaseUrl?.replace(/\/$/, '') || ''
+ const baseUrl = process.server
+ ? (config.apiBaseUrl || config.public.apiBaseUrl || '')
+ : (config.public.apiBaseUrl || '')
+ const base = baseUrl.replace(/\/$/, '')
return `${base}${path}`
}
diff --git a/app/composables/useProfiles.js b/app/composables/useProfiles.js
index a6e0e40..ad1c80d 100644
--- a/app/composables/useProfiles.js
+++ b/app/composables/useProfiles.js
@@ -20,7 +20,7 @@ export function useProfiles () {
const fetchProfiles = async () => {
loadingProfiles.value = true
try {
- profiles.value = await $fetch(buildUrl('/profiles'), {
+ profiles.value = await $fetch(buildUrl('/session/profiles'), {
method: 'GET',
credentials: 'include',
headers: getSessionHeaders()
@@ -37,7 +37,7 @@ export function useProfiles () {
}
const createProfile = async ({ firstName, lastName }) => {
- const profile = await $fetch(buildUrl('/profiles'), {
+ const profile = await $fetch(buildUrl('/session/profiles'), {
method: 'POST',
credentials: 'include',
body: { firstName, lastName },
@@ -48,7 +48,7 @@ export function useProfiles () {
}
const deleteProfile = async (profileId) => {
- await $fetch(buildUrl(`/profiles/${profileId}`), {
+ await $fetch(buildUrl(`/session/profiles/${profileId}`), {
method: 'DELETE',
credentials: 'include',
headers: getSessionHeaders()
diff --git a/app/composables/useSites.js b/app/composables/useSites.js
index 9d1eecd..1c76e51 100644
--- a/app/composables/useSites.js
+++ b/app/composables/useSites.js
@@ -13,9 +13,20 @@ export function useSites () {
loading.value = true
try {
const result = await get('/sites')
+ console.log('sites api result', result)
+
if (result.success) {
- sites.value = result.data
- showInfo(`Chargement de ${sites.value.length} site(s) réussi`)
+ const collection = Array.isArray(result.data)
+ ? result.data
+ : Array.isArray(result.data?.member)
+ ? result.data.member
+ : Array.isArray(result.data?.['hydra:member'])
+ ? result.data['hydra:member']
+ : Array.isArray(result.data?.data)
+ ? result.data.data
+ : []
+ sites.value = collection
+ showInfo(`Chargement de ${collection.length} site(s) réussi`)
}
} catch (error) {
console.error('Erreur lors du chargement des sites:', error)
diff --git a/app/services/modelTypes.ts b/app/services/modelTypes.ts
index 2c54e6f..18f46c2 100644
--- a/app/services/modelTypes.ts
+++ b/app/services/modelTypes.ts
@@ -65,7 +65,7 @@ export interface ModelTypeListResponse {
limit: number;
}
-const ENDPOINT = '/api/model-types';
+const ENDPOINT = '/model_types';
function resolveBaseUrl() {
const runtimeConfig = useRuntimeConfig();
@@ -80,7 +80,7 @@ function createOptions(options: FetchOptions = {}) {
};
}
-export function listModelTypes(params: ModelTypeListParams = {}, opts: { signal?: AbortSignal } = {}) {
+export async function listModelTypes(params: ModelTypeListParams = {}, opts: { signal?: AbortSignal } = {}) {
const requestFetch = useRequestFetch();
const query: Record = {};
@@ -97,17 +97,37 @@ export function listModelTypes(params: ModelTypeListParams = {}, opts: { signal?
query.dir = params.dir;
}
if (typeof params.limit === 'number') {
- query.limit = params.limit;
+ query.itemsPerPage = params.limit;
}
if (typeof params.offset === 'number') {
query.offset = params.offset;
}
- return requestFetch(ENDPOINT, createOptions({
+ const payload = await requestFetch>(ENDPOINT, createOptions({
method: 'GET',
query,
signal: opts.signal,
}));
+
+ const items = Array.isArray(payload?.member)
+ ? payload.member
+ : Array.isArray(payload?.['hydra:member'])
+ ? payload['hydra:member']
+ : Array.isArray(payload?.items)
+ ? payload.items
+ : [];
+ const total = typeof payload?.totalItems === 'number'
+ ? payload.totalItems
+ : Array.isArray(payload?.items)
+ ? payload.items.length
+ : items.length;
+
+ return {
+ items,
+ total,
+ offset: params.offset ?? 0,
+ limit: typeof params.limit === 'number' ? params.limit : items.length,
+ } satisfies ModelTypeListResponse;
}
export function createModelType(payload: ModelTypePayload, opts: { signal?: AbortSignal } = {}) {
diff --git a/app/shared/apiRelations.ts b/app/shared/apiRelations.ts
new file mode 100644
index 0000000..3a1b1ac
--- /dev/null
+++ b/app/shared/apiRelations.ts
@@ -0,0 +1,57 @@
+export const RELATION_ID_MAP: Record = {
+ siteId: { key: 'site', path: 'sites' },
+ machineId: { key: 'machine', path: 'machines' },
+ composantId: { key: 'composant', path: 'composants' },
+ pieceId: { key: 'piece', path: 'pieces' },
+ productId: { key: 'product', path: 'products' },
+ typeMachineId: { key: 'typeMachine', path: 'type_machines' },
+ typeComposantId: { key: 'typeComposant', path: 'model_types' },
+ typePieceId: { key: 'typePiece', path: 'model_types' },
+ typeProductId: { key: 'typeProduct', path: 'model_types' },
+};
+
+export const toIri = (path: string, id: string): string => `/api/${path}/${id}`;
+
+export const extractRelationId = (value: unknown): string | null => {
+ if (!value) {
+ return null;
+ }
+ if (typeof value === 'string') {
+ const trimmed = value.trim();
+ if (!trimmed) {
+ return null;
+ }
+ if (trimmed.includes('/')) {
+ const parts = trimmed.split('/').filter(Boolean);
+ return parts.length ? parts[parts.length - 1] : null;
+ }
+ return trimmed;
+ }
+ if (typeof value === 'object' && 'id' in (value as Record)) {
+ const id = (value as Record).id;
+ return typeof id === 'string' ? id : null;
+ }
+ return null;
+};
+
+export const normalizeRelationIds = >(payload: T): T => {
+ if (!payload || typeof payload !== 'object') {
+ return payload;
+ }
+
+ const next: Record = { ...payload };
+ Object.entries(RELATION_ID_MAP).forEach(([sourceKey, config]) => {
+ const raw = next[sourceKey];
+ if (typeof raw !== 'string') {
+ return;
+ }
+ const trimmed = raw.trim();
+ if (!trimmed) {
+ return;
+ }
+ next[config.key] = toIri(config.path, trimmed);
+ delete next[sourceKey];
+ });
+
+ return next as T;
+};
diff --git a/app/shared/constructeurUtils.ts b/app/shared/constructeurUtils.ts
index 02649ed..31030d7 100644
--- a/app/shared/constructeurUtils.ts
+++ b/app/shared/constructeurUtils.ts
@@ -15,7 +15,14 @@ const toStringId = (value: unknown): string | null => {
return null;
}
const trimmed = value.trim();
- return trimmed.length > 0 ? trimmed : null;
+ if (!trimmed) {
+ return null;
+ }
+ if (trimmed.includes('/')) {
+ const parts = trimmed.split('/').filter(Boolean);
+ return parts.length ? parts[parts.length - 1] : null;
+ }
+ return trimmed;
};
export const uniqueConstructeurIds = (...sources: unknown[]): string[] => {
@@ -107,7 +114,7 @@ export const formatConstructeurContact = (
export const buildConstructeurRequestPayload = >(
payload: T,
-): T & { constructeurIds: string[] } => {
+): T & { constructeurs?: string[] } => {
const ids = uniqueConstructeurIds(
payload?.constructeurIds,
payload?.constructeurId,
@@ -116,10 +123,13 @@ export const buildConstructeurRequestPayload = >(
);
const next = { ...payload } as Record;
- next.constructeurIds = ids;
+ if (ids.length) {
+ next.constructeurs = ids.map((id) => `/api/constructeurs/${id}`);
+ }
delete next.constructeurId;
delete next.constructeur;
delete next.constructeurs;
+ delete next.constructeurIds;
- return next as T & { constructeurIds: string[] };
+ return next as T & { constructeurs?: string[] };
};
diff --git a/nuxt.config.ts b/nuxt.config.ts
index 6c85c85..964c43d 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -18,8 +18,11 @@ export default defineNuxtConfig({
]
],
runtimeConfig: {
+ apiBaseUrl: process.env.NUXT_API_BASE_URL
+ || process.env.NUXT_PUBLIC_API_BASE_URL
+ || 'http://localhost/api',
public: {
- apiBaseUrl: process.env.NUXT_PUBLIC_API_BASE_URL || 'http://localhost:3000',
+ apiBaseUrl: process.env.NUXT_PUBLIC_API_BASE_URL || 'http://localhost:8081/api',
appUrl: process.env.NUXT_PUBLIC_APP_URL || 'http://localhost:3001',
appName: process.env.NUXT_PUBLIC_APP_NAME || 'Inventory Management System',
appVersion: process.env.NUXT_PUBLIC_APP_VERSION || '0.1.0',
diff --git a/package-lock.json b/package-lock.json
index 78d6e80..fffcc3e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3754,7 +3754,6 @@
"integrity": "sha512-UG8hdElzuBDzIbjG1QDwnYH0MQ73YLXDFHgZzB4Zh/YJfnw8XNsloVtytqzx0I2Qky9THSdpTmi8Vjn/pf/Lew==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.0",
"@typescript-eslint/types": "^8.44.0",
@@ -11673,7 +11672,6 @@
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.2.tgz",
"integrity": "sha512-I25/2QgoROE1vYV+NQ1En9T9UFB9Cmfm2CJ83zZOlaDpvz29wGQSZXWKw7MiNXau7wYgB/T9fVIdIuEQ+KbiiA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@types/estree": "1.0.8"
},
@@ -12483,6 +12481,7 @@
"resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz",
"integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==",
"license": "BSD-2-Clause",
+ "peer": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.15.0",