From 83b3e33b1e0c270bbcf1bf3c63589fec8961026c Mon Sep 17 00:00:00 2001 From: Matthieu Date: Tue, 23 Sep 2025 15:06:19 +0200 Subject: [PATCH] feat: Add model feature for piece and component --- app/app.vue | 18 + app/components/PieceModelStructureEditor.vue | 212 +++++++ app/components/model-types/EditModal.vue | 212 +++++++ app/components/model-types/Table.vue | 161 +++++ app/components/model-types/Toolbar.vue | 107 ++++ app/composables/useComponentTypes.js | 111 ++-- app/composables/usePieceTypes.js | 111 ++-- app/pages/machine/[id].vue | 115 +--- app/pages/machines/new.vue | 119 +--- app/pages/model-types.vue | 284 +++++++++ app/pages/models.vue | 585 ------------------- app/pages/models/components.vue | 347 +++++++++++ app/pages/models/index.vue | 25 + app/pages/models/pieces.vue | 349 +++++++++++ app/services/modelTypes.ts | 113 ++++ 15 files changed, 2018 insertions(+), 851 deletions(-) create mode 100644 app/components/PieceModelStructureEditor.vue create mode 100644 app/components/model-types/EditModal.vue create mode 100644 app/components/model-types/Table.vue create mode 100644 app/components/model-types/Toolbar.vue create mode 100644 app/pages/model-types.vue delete mode 100644 app/pages/models.vue create mode 100644 app/pages/models/components.vue create mode 100644 app/pages/models/index.vue create mode 100644 app/pages/models/pieces.vue create mode 100644 app/services/modelTypes.ts diff --git a/app/app.vue b/app/app.vue index 9c4b0e0..09295f1 100644 --- a/app/app.vue +++ b/app/app.vue @@ -53,6 +53,15 @@ Modèles +
  • + + Types de modèles + +
  • +
  • + + Types de modèles + +
  • +
    +
    +
    +

    Champs personnalisés

    + +
    + +

    + Aucun champ personnalisé n'a encore été défini. +

    + +
    +
    +
    +
    +
    + + +
    + +
    + + +
    + + +
    + +
    +
    +
    +
    +
    + + + diff --git a/app/components/model-types/EditModal.vue b/app/components/model-types/EditModal.vue new file mode 100644 index 0000000..3b52ae6 --- /dev/null +++ b/app/components/model-types/EditModal.vue @@ -0,0 +1,212 @@ + + + diff --git a/app/components/model-types/Table.vue b/app/components/model-types/Table.vue new file mode 100644 index 0000000..85517eb --- /dev/null +++ b/app/components/model-types/Table.vue @@ -0,0 +1,161 @@ + + + diff --git a/app/components/model-types/Toolbar.vue b/app/components/model-types/Toolbar.vue new file mode 100644 index 0000000..d1e8e18 --- /dev/null +++ b/app/components/model-types/Toolbar.vue @@ -0,0 +1,107 @@ + + + diff --git a/app/composables/useComponentTypes.js b/app/composables/useComponentTypes.js index 2576166..602a342 100644 --- a/app/composables/useComponentTypes.js +++ b/app/composables/useComponentTypes.js @@ -1,25 +1,43 @@ import { ref } from 'vue' -import { useApi } from './useApi' +import { listModelTypes, createModelType, updateModelType, deleteModelType } from '~/services/modelTypes' import { useToast } from './useToast' const componentTypes = ref([]) const loadingComponentTypes = ref(false) export function useComponentTypes() { - const { get, post, patch, delete: del } = useApi() const { showSuccess, showError } = useToast() + const generateCodeFromName = (name) => { + return (name || '') + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .toLowerCase() + .replace(/[^a-z0-9]+/g, '-') + .replace(/^-+|-+$/g, '') + .replace(/-+/g, '-') || 'type' + } + const loadComponentTypes = async () => { loadingComponentTypes.value = true try { - const result = await get('/types/composants') - if (result.success) { - componentTypes.value = result.data - } - return result + const data = await listModelTypes({ + category: 'COMPONENT', + sort: 'name', + dir: 'asc', + limit: 200, + }) + + componentTypes.value = data.items.map((item) => ({ + ...item, + description: item.description ?? item.notes ?? null, + })) + + return { success: true, data: componentTypes.value } } catch (error) { - showError(`Impossible de charger les types de composant: ${error.message}`) - return { success: false, error: error.message } + const message = error?.message || 'Erreur inconnue' + showError(`Impossible de charger les types de composant: ${message}`) + return { success: false, error: message } } finally { loadingComponentTypes.value = false } @@ -28,15 +46,27 @@ export function useComponentTypes() { const createComponentType = async (payload) => { loadingComponentTypes.value = true try { - const result = await post('/types/composants', payload) - if (result.success) { - componentTypes.value.push(result.data) - showSuccess(`Type de composant "${result.data.name}" créé`) + const data = await createModelType({ + name: payload.name, + code: payload.code || generateCodeFromName(payload.name), + category: 'COMPONENT', + notes: payload.description ?? payload.notes, + description: payload.description ?? null, + }) + + const normalized = { + ...data, + description: data.description ?? data.notes ?? null, } - return result + + componentTypes.value.push(normalized) + showSuccess(`Type de composant "${data.name}" créé`) + + return { success: true, data: normalized } } catch (error) { - showError(`Erreur lors de la création du type de composant: ${error.message}`) - return { success: false, error: error.message } + const message = error?.data?.message || error?.message || 'Erreur inconnue' + showError(`Erreur lors de la création du type de composant: ${message}`) + return { success: false, error: message } } finally { loadingComponentTypes.value = false } @@ -45,18 +75,32 @@ export function useComponentTypes() { const updateComponentType = async (id, payload) => { loadingComponentTypes.value = true try { - const result = await patch(`/types/composants/${id}`, payload) - if (result.success) { - const index = componentTypes.value.findIndex((type) => type.id === id) - if (index !== -1) { - componentTypes.value[index] = result.data - } - showSuccess(`Type de composant "${result.data.name}" mis à jour`) + const data = await updateModelType(id, { + name: payload.name, + description: payload.description, + notes: payload.notes, + code: payload.code, + }) + + const normalized = { + ...data, + description: data.description ?? data.notes ?? null, + } + + const index = componentTypes.value.findIndex((type) => type.id === id) + if (index !== -1) { + componentTypes.value[index] = normalized + } + showSuccess(`Type de composant "${data.name}" mis à jour`) + + return { + success: true, + data: normalized, } - return result } catch (error) { - showError(`Erreur lors de la mise à jour du type de composant: ${error.message}`) - return { success: false, error: error.message } + const message = error?.data?.message || error?.message || 'Erreur inconnue' + showError(`Erreur lors de la mise à jour du type de composant: ${message}`) + return { success: false, error: message } } finally { loadingComponentTypes.value = false } @@ -65,15 +109,14 @@ export function useComponentTypes() { const deleteComponentType = async (id) => { loadingComponentTypes.value = true try { - const result = await del(`/types/composants/${id}`) - if (result.success) { - componentTypes.value = componentTypes.value.filter((type) => type.id !== id) - showSuccess('Type de composant supprimé') - } - return result + await deleteModelType(id) + componentTypes.value = componentTypes.value.filter((type) => type.id !== id) + showSuccess('Type de composant supprimé') + return { success: true } } catch (error) { - showError(`Erreur lors de la suppression du type de composant: ${error.message}`) - return { success: false, error: error.message } + const message = error?.data?.message || error?.message || 'Erreur inconnue' + showError(`Erreur lors de la suppression du type de composant: ${message}`) + return { success: false, error: message } } finally { loadingComponentTypes.value = false } diff --git a/app/composables/usePieceTypes.js b/app/composables/usePieceTypes.js index efdf0c1..c5b61f6 100644 --- a/app/composables/usePieceTypes.js +++ b/app/composables/usePieceTypes.js @@ -1,25 +1,43 @@ import { ref } from 'vue' -import { useApi } from './useApi' +import { listModelTypes, createModelType, updateModelType, deleteModelType } from '~/services/modelTypes' import { useToast } from './useToast' const pieceTypes = ref([]) const loadingPieceTypes = ref(false) export function usePieceTypes() { - const { get, post, patch, delete: del } = useApi() const { showSuccess, showError } = useToast() + const generateCodeFromName = (name) => { + return (name || '') + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .toLowerCase() + .replace(/[^a-z0-9]+/g, '-') + .replace(/^-+|-+$/g, '') + .replace(/-+/g, '-') || 'type' + } + const loadPieceTypes = async () => { loadingPieceTypes.value = true try { - const result = await get('/types/pieces') - if (result.success) { - pieceTypes.value = result.data - } - return result + const data = await listModelTypes({ + category: 'PIECE', + sort: 'name', + dir: 'asc', + limit: 200, + }) + + pieceTypes.value = data.items.map((item) => ({ + ...item, + description: item.description ?? item.notes ?? null, + })) + + return { success: true, data: pieceTypes.value } } catch (error) { - showError(`Impossible de charger les types de pièce: ${error.message}`) - return { success: false, error: error.message } + const message = error?.message || 'Erreur inconnue' + showError(`Impossible de charger les types de pièce: ${message}`) + return { success: false, error: message } } finally { loadingPieceTypes.value = false } @@ -28,15 +46,27 @@ export function usePieceTypes() { const createPieceType = async (payload) => { loadingPieceTypes.value = true try { - const result = await post('/types/pieces', payload) - if (result.success) { - pieceTypes.value.push(result.data) - showSuccess(`Type de pièce "${result.data.name}" créé`) + const data = await createModelType({ + name: payload.name, + code: payload.code || generateCodeFromName(payload.name), + category: 'PIECE', + notes: payload.description ?? payload.notes, + description: payload.description ?? null, + }) + + const normalized = { + ...data, + description: data.description ?? data.notes ?? null, } - return result + + pieceTypes.value.push(normalized) + showSuccess(`Type de pièce "${data.name}" créé`) + + return { success: true, data: normalized } } catch (error) { - showError(`Erreur lors de la création du type de pièce: ${error.message}`) - return { success: false, error: error.message } + const message = error?.data?.message || error?.message || 'Erreur inconnue' + showError(`Erreur lors de la création du type de pièce: ${message}`) + return { success: false, error: message } } finally { loadingPieceTypes.value = false } @@ -45,18 +75,32 @@ export function usePieceTypes() { const updatePieceType = async (id, payload) => { loadingPieceTypes.value = true try { - const result = await patch(`/types/pieces/${id}`, payload) - if (result.success) { - const index = pieceTypes.value.findIndex((type) => type.id === id) - if (index !== -1) { - pieceTypes.value[index] = result.data - } - showSuccess(`Type de pièce "${result.data.name}" mis à jour`) + const data = await updateModelType(id, { + name: payload.name, + description: payload.description, + notes: payload.notes, + code: payload.code, + }) + + const normalized = { + ...data, + description: data.description ?? data.notes ?? null, + } + + const index = pieceTypes.value.findIndex((type) => type.id === id) + if (index !== -1) { + pieceTypes.value[index] = normalized + } + showSuccess(`Type de pièce "${data.name}" mis à jour`) + + return { + success: true, + data: normalized, } - return result } catch (error) { - showError(`Erreur lors de la mise à jour du type de pièce: ${error.message}`) - return { success: false, error: error.message } + const message = error?.data?.message || error?.message || 'Erreur inconnue' + showError(`Erreur lors de la mise à jour du type de pièce: ${message}`) + return { success: false, error: message } } finally { loadingPieceTypes.value = false } @@ -65,15 +109,14 @@ export function usePieceTypes() { const deletePieceType = async (id) => { loadingPieceTypes.value = true try { - const result = await del(`/types/pieces/${id}`) - if (result.success) { - pieceTypes.value = pieceTypes.value.filter((type) => type.id !== id) - showSuccess('Type de pièce supprimé') - } - return result + await deleteModelType(id) + pieceTypes.value = pieceTypes.value.filter((type) => type.id !== id) + showSuccess('Type de pièce supprimé') + return { success: true } } catch (error) { - showError(`Erreur lors de la suppression du type de pièce: ${error.message}`) - return { success: false, error: error.message } + const message = error?.data?.message || error?.message || 'Erreur inconnue' + showError(`Erreur lors de la suppression du type de pièce: ${message}`) + return { success: false, error: message } } finally { loadingPieceTypes.value = false } diff --git a/app/pages/machine/[id].vue b/app/pages/machine/[id].vue index eb19ff4..53cefd7 100644 --- a/app/pages/machine/[id].vue +++ b/app/pages/machine/[id].vue @@ -295,30 +295,8 @@ :key="`${requirement.id}-piece-${entryIndex}`" class="bg-base-200/60 rounded-md p-3 space-y-3" > -
    - - -
    - -
    -
    +
    +
    @@ -343,32 +321,12 @@ > Aucun modèle disponible pour ce type.

    -
    -
    - -
    -
    - - -
    -
    - - +

    + Ancienne pièce : {{ entry.legacyName }} — sélectionner un modèle. +

    @@ -1055,9 +1013,7 @@ const createComponentSelectionEntry = () => ({ }) const createPieceSelectionEntry = () => ({ - mode: 'model', pieceModelId: '', - name: '', }) const resetSkeletonRequirementSelections = () => { @@ -1121,24 +1077,20 @@ const removePieceSelectionEntry = (requirementId, index) => { pieceRequirementSelections[requirementId] = entries.filter((_, i) => i !== index) } -const setPieceSelectionMode = (requirementId, index, mode) => { +const updatePieceSelectionEntry = (requirementId, index, patch) => { const entries = getPieceRequirementEntries(requirementId) pieceRequirementSelections[requirementId] = entries.map((entry, i) => { if (i !== index) return entry - if (mode === 'model') { - return { ...entry, mode: 'model', pieceModelId: entry.pieceModelId || '', name: '' } + const updated = { ...entry, ...patch } + if (Object.prototype.hasOwnProperty.call(patch, 'pieceModelId')) { + if (patch.pieceModelId) { + delete updated.legacyName + } } - return { ...entry, mode: 'manual', pieceModelId: '', name: entry.name || '' } + return updated }) } -const updatePieceSelectionEntry = (requirementId, index, patch) => { - const entries = getPieceRequirementEntries(requirementId) - pieceRequirementSelections[requirementId] = entries.map((entry, i) => - i === index ? { ...entry, ...patch } : entry - ) -} - const collectPiecesForSkeleton = () => { const aggregated = [] machinePieces.value.forEach((piece) => { @@ -1195,9 +1147,12 @@ const initializeSkeletonRequirementSelections = async () => { const entries = existingPieces.map((piece) => { const modelId = piece.pieceModelId || piece.pieceModel?.id || null if (modelId) { - return { mode: 'model', pieceModelId: modelId, name: '' } + return { pieceModelId: modelId } + } + return { + pieceModelId: '', + legacyName: piece.name || piece.reference || '', } - return { mode: 'manual', pieceModelId: '', name: piece.name || '' } }) const min = requirement.minCount ?? (requirement.required ? 1 : 0) while (entries.length < min) { @@ -1287,12 +1242,7 @@ const validateSkeletonSelections = (type) => { for (const requirement of type.pieceRequirements || []) { const entries = getPieceRequirementEntries(requirement.id) - const usableEntries = entries.filter((entry) => { - if (entry.mode === 'model') { - return !!entry.pieceModelId - } - return !!entry.name && entry.name.trim().length > 0 - }) + const usableEntries = entries.filter((entry) => !!entry.pieceModelId) const min = requirement.minCount ?? (requirement.required ? 1 : 0) const max = requirement.maxCount ?? null @@ -1309,26 +1259,11 @@ const validateSkeletonSelections = (type) => { ) } - if (!requirement.allowNewModels && usableEntries.some((entry) => entry.mode === 'manual')) { - errors.push( - `Le groupe "${requirement.label || requirement.typePiece?.name || 'Pièces'}" n'autorise que les modèles existants.` - ) - } - usableEntries.forEach((entry) => { - if (entry.mode === 'model') { - pieceSelectionsPayload.push({ - requirementId: requirement.id, - pieceModelId: entry.pieceModelId, - }) - } else { - pieceSelectionsPayload.push({ - requirementId: requirement.id, - definition: { - name: entry.name.trim(), - }, - }) - } + pieceSelectionsPayload.push({ + requirementId: requirement.id, + pieceModelId: entry.pieceModelId, + }) }) } diff --git a/app/pages/machines/new.vue b/app/pages/machines/new.vue index da10863..a26a7b1 100644 --- a/app/pages/machines/new.vue +++ b/app/pages/machines/new.vue @@ -293,29 +293,7 @@ :key="`${requirement.id}-piece-${entryIndex}`" class="bg-base-200/60 rounded-md p-3 space-y-3" > -
    - - -
    - -
    +
    -
    -
    - - -
    -
    - - -
    -
    -
    - manuel
  • @@ -903,23 +854,12 @@ const machinePreview = computed(() => { const entriesSource = getPieceRequirementEntries(requirement.id) const entriesList = entriesSource ? [...entriesSource] : [] const normalizedEntries = entriesList.map((entry, index) => { - if (entry.mode === 'model') { - const model = resolvePieceModel(requirement, entry.pieceModelId) - return { - key: `${requirement.id}-${index}`, - mode: 'model', - status: model ? 'complete' : 'pending', - title: model ? model.name : 'Sélectionner un modèle', - subtitle: model?.description || null, - } - } - const manualName = (entry.name || '').trim() + const model = resolvePieceModel(requirement, entry.pieceModelId) return { key: `${requirement.id}-${index}`, - mode: 'manual', - status: manualName ? 'complete' : 'pending', - title: manualName || 'Nom à renseigner', - subtitle: manualName ? null : null, + status: model ? 'complete' : 'pending', + title: model ? model.name : 'Sélectionner un modèle', + subtitle: model?.description || null, } }) @@ -936,10 +876,6 @@ const machinePreview = computed(() => { issues.push({ message: `Maximum ${max} dépassé`, kind: 'error', anchor: `piece-group-${requirement.id}` }) } - if (!requirement.allowNewModels && normalizedEntries.some((entry) => entry.mode === 'manual' && entry.status === 'complete')) { - issues.push({ message: "Ce groupe n'autorise que les modèles existants.", kind: 'error', anchor: `piece-group-${requirement.id}` }) - } - if (normalizedEntries.some((entry) => entry.status !== 'complete')) { issues.push({ message: 'Compléter les sélections restantes.', kind: 'warning', anchor: `piece-group-${requirement.id}` }) } @@ -1056,9 +992,7 @@ const createComponentSelectionEntry = () => ({ }) const createPieceSelectionEntry = () => ({ - mode: 'model', pieceModelId: '', - name: '', }) const addComponentSelectionEntry = (requirement) => { @@ -1109,17 +1043,6 @@ const removePieceSelectionEntry = (requirementId, index) => { pieceRequirementSelections[requirementId] = entries.filter((_, i) => i !== index) } -const setPieceSelectionMode = (requirementId, index, mode) => { - const entries = getPieceRequirementEntries(requirementId) - pieceRequirementSelections[requirementId] = entries.map((entry, i) => { - if (i !== index) return entry - if (mode === 'model') { - return { ...entry, mode: 'model', pieceModelId: entry.pieceModelId || '', name: '' } - } - return { ...entry, mode: 'manual', pieceModelId: '', name: entry.name || '' } - }) -} - const updatePieceSelectionEntry = (requirementId, index, patch) => { const entries = getPieceRequirementEntries(requirementId) pieceRequirementSelections[requirementId] = entries.map((entry, i) => @@ -1175,12 +1098,7 @@ const validateRequirementSelections = (type) => { for (const requirement of type.pieceRequirements || []) { const entries = getPieceRequirementEntries(requirement.id) - const usableEntries = entries.filter((entry) => { - if (entry.mode === 'model') { - return !!entry.pieceModelId - } - return !!entry.name && entry.name.trim().length > 0 - }) + const usableEntries = entries.filter((entry) => !!entry.pieceModelId) const min = requirement.minCount ?? (requirement.required ? 1 : 0) const max = requirement.maxCount ?? null @@ -1193,24 +1111,11 @@ const validateRequirementSelections = (type) => { errors.push(`Le groupe "${requirement.label || requirement.typePiece?.name || 'Pièces'}" ne peut dépasser ${max} élément(s).`) } - if (!requirement.allowNewModels && usableEntries.some((entry) => entry.mode === 'manual')) { - errors.push(`Le groupe "${requirement.label || requirement.typePiece?.name || 'Pièces'}" n'autorise que les modèles existants.`) - } - usableEntries.forEach((entry) => { - if (entry.mode === 'model') { - pieceSelectionsPayload.push({ - requirementId: requirement.id, - pieceModelId: entry.pieceModelId, - }) - } else { - pieceSelectionsPayload.push({ - requirementId: requirement.id, - definition: { - name: entry.name.trim(), - }, - }) - } + pieceSelectionsPayload.push({ + requirementId: requirement.id, + pieceModelId: entry.pieceModelId, + }) }) } @@ -1322,10 +1227,9 @@ const submitCreatePieceModel = async () => { if (result.success) { await loadPieceModels(createPieceModelModal.requirement.typePieceId) const entries = getPieceRequirementEntries(createPieceModelModal.requirement.id) - const targetIndex = entries.findIndex((entry) => entry.mode === 'model' && !entry.pieceModelId) + const targetIndex = entries.findIndex((entry) => !entry.pieceModelId) if (targetIndex !== -1) { updatePieceSelectionEntry(createPieceModelModal.requirement.id, targetIndex, { - mode: 'model', pieceModelId: result.data.id, }) } else { @@ -1334,7 +1238,6 @@ const submitCreatePieceModel = async () => { createPieceModelModal.requirement.id, getPieceRequirementEntries(createPieceModelModal.requirement.id).length - 1, { - mode: 'model', pieceModelId: result.data.id, }, ) diff --git a/app/pages/model-types.vue b/app/pages/model-types.vue new file mode 100644 index 0000000..d2a1da7 --- /dev/null +++ b/app/pages/model-types.vue @@ -0,0 +1,284 @@ + + + diff --git a/app/pages/models.vue b/app/pages/models.vue deleted file mode 100644 index d39ef31..0000000 --- a/app/pages/models.vue +++ /dev/null @@ -1,585 +0,0 @@ - - - diff --git a/app/pages/models/components.vue b/app/pages/models/components.vue new file mode 100644 index 0000000..9a4d2ea --- /dev/null +++ b/app/pages/models/components.vue @@ -0,0 +1,347 @@ + + + diff --git a/app/pages/models/index.vue b/app/pages/models/index.vue new file mode 100644 index 0000000..ed13d21 --- /dev/null +++ b/app/pages/models/index.vue @@ -0,0 +1,25 @@ + + + diff --git a/app/pages/models/pieces.vue b/app/pages/models/pieces.vue new file mode 100644 index 0000000..9e41dd4 --- /dev/null +++ b/app/pages/models/pieces.vue @@ -0,0 +1,349 @@ + + + diff --git a/app/services/modelTypes.ts b/app/services/modelTypes.ts new file mode 100644 index 0000000..b08d021 --- /dev/null +++ b/app/services/modelTypes.ts @@ -0,0 +1,113 @@ +import { useRequestFetch } from '#imports'; +import type { FetchOptions } from 'ofetch'; + +export type ModelCategory = 'COMPONENT' | 'PIECE'; + +export interface ModelTypePayload { + name: string; + code: string; + category: ModelCategory; + notes?: string | null; + description?: string | null; +} + +export interface ModelType extends ModelTypePayload { + id: string; + createdAt: string; + updatedAt: string; +} + +export interface ModelTypeListParams { + q?: string; + category?: ModelCategory; + sort?: 'name' | 'code' | 'createdAt'; + dir?: 'asc' | 'desc'; + limit?: number; + offset?: number; +} + +export interface ModelTypeListResponse { + items: ModelType[]; + total: number; + offset: number; + limit: number; +} + +const ENDPOINT = '/api/model-types'; + +function resolveBaseUrl() { + const runtimeConfig = useRuntimeConfig(); + return runtimeConfig.public.apiBaseUrl || ''; +} + +function createOptions(options: FetchOptions = {}) { + return { + baseURL: resolveBaseUrl(), + credentials: 'include' as const, + ...options, + }; +} + +export function listModelTypes(params: ModelTypeListParams = {}, opts: { signal?: AbortSignal } = {}) { + const requestFetch = useRequestFetch(); + const query: Record = {}; + + if (params.q) { + query.q = params.q; + } + if (params.category) { + query.category = params.category; + } + if (params.sort) { + query.sort = params.sort; + } + if (params.dir) { + query.dir = params.dir; + } + if (typeof params.limit === 'number') { + query.limit = params.limit; + } + if (typeof params.offset === 'number') { + query.offset = params.offset; + } + + return requestFetch(ENDPOINT, createOptions({ + method: 'GET', + query, + signal: opts.signal, + })); +} + +export function createModelType(payload: ModelTypePayload, opts: { signal?: AbortSignal } = {}) { + const requestFetch = useRequestFetch(); + return requestFetch(ENDPOINT, createOptions({ + method: 'POST', + body: payload, + signal: opts.signal, + })); +} + +export function updateModelType(id: string, payload: Partial, opts: { signal?: AbortSignal } = {}) { + const requestFetch = useRequestFetch(); + return requestFetch(`${ENDPOINT}/${id}`, createOptions({ + method: 'PATCH', + body: payload, + signal: opts.signal, + })); +} + +export function deleteModelType(id: string, opts: { signal?: AbortSignal } = {}) { + const requestFetch = useRequestFetch(); + return requestFetch(`${ENDPOINT}/${id}`, createOptions({ + method: 'DELETE', + signal: opts.signal, + })); +} + +export function getModelType(id: string, opts: { signal?: AbortSignal } = {}) { + const requestFetch = useRequestFetch(); + return requestFetch(`${ENDPOINT}/${id}`, createOptions({ + method: 'GET', + signal: opts.signal, + })); +}