wip: dynamic search for component create
This commit is contained in:
@@ -17,12 +17,13 @@
|
|||||||
<SearchSelect
|
<SearchSelect
|
||||||
:model-value="assignment.selectedComponentId || ''"
|
:model-value="assignment.selectedComponentId || ''"
|
||||||
:options="componentOptions"
|
:options="componentOptions"
|
||||||
:loading="componentsLoading"
|
:loading="componentsLoading || componentLoadingByPath[assignment.path]"
|
||||||
size="sm"
|
size="sm"
|
||||||
placeholder="Rechercher un composant..."
|
placeholder="Rechercher un composant..."
|
||||||
:empty-text="componentOptions.length ? 'Aucun résultat' : 'Aucun composant disponible'"
|
:empty-text="componentOptions.length ? 'Aucun résultat' : 'Aucun composant disponible'"
|
||||||
:option-label="componentOptionLabel"
|
:option-label="componentOptionLabel"
|
||||||
:option-description="componentOptionDescription"
|
:option-description="componentOptionDescription"
|
||||||
|
@search="fetchComponentOptions"
|
||||||
@update:modelValue="(value) => { assignment.selectedComponentId = normalizeSelectionValue(value); }"
|
@update:modelValue="(value) => { assignment.selectedComponentId = normalizeSelectionValue(value); }"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -45,22 +46,23 @@
|
|||||||
>
|
>
|
||||||
<div class="space-y-1">
|
<div class="space-y-1">
|
||||||
<p class="text-xs font-medium text-base-content">
|
<p class="text-xs font-medium text-base-content">
|
||||||
{{ describePieceRequirement(pieceAssignment.definition) }}
|
{{ describePieceRequirement(pieceAssignment) }}
|
||||||
</p>
|
</p>
|
||||||
<p v-if="!getPieceOptions(pieceAssignment.definition).length" class="text-[11px] text-error">
|
<p v-if="!getPieceOptions(pieceAssignment).length" class="text-[11px] text-error">
|
||||||
Aucune pièce disponible pour cette famille.
|
Aucune pièce disponible pour cette famille.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SearchSelect
|
<SearchSelect
|
||||||
:model-value="pieceAssignment.selectedPieceId || ''"
|
:model-value="pieceAssignment.selectedPieceId || ''"
|
||||||
:options="getPieceOptions(pieceAssignment.definition)"
|
:options="getPieceOptions(pieceAssignment)"
|
||||||
:loading="piecesLoading"
|
:loading="piecesLoading || pieceLoadingByPath[pieceAssignment.path]"
|
||||||
size="xs"
|
size="xs"
|
||||||
placeholder="Rechercher une pièce..."
|
placeholder="Rechercher une pièce..."
|
||||||
:empty-text="getPieceOptions(pieceAssignment.definition).length ? 'Aucun résultat' : 'Aucune pièce disponible'"
|
:empty-text="getPieceOptions(pieceAssignment).length ? 'Aucun résultat' : 'Aucune pièce disponible'"
|
||||||
:option-label="pieceOptionLabel"
|
:option-label="pieceOptionLabel"
|
||||||
:option-description="pieceOptionDescription"
|
:option-description="pieceOptionDescription"
|
||||||
|
@search="(term) => fetchPieceOptions(pieceAssignment, term)"
|
||||||
@update:modelValue="(value) => { pieceAssignment.selectedPieceId = normalizeSelectionValue(value); }"
|
@update:modelValue="(value) => { pieceAssignment.selectedPieceId = normalizeSelectionValue(value); }"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -83,22 +85,23 @@
|
|||||||
>
|
>
|
||||||
<div class="space-y-1">
|
<div class="space-y-1">
|
||||||
<p class="text-xs font-medium text-base-content">
|
<p class="text-xs font-medium text-base-content">
|
||||||
{{ describeProductRequirement(productAssignment.definition) }}
|
{{ describeProductRequirement(productAssignment) }}
|
||||||
</p>
|
</p>
|
||||||
<p v-if="!getProductOptions(productAssignment.definition).length" class="text-[11px] text-error">
|
<p v-if="!getProductOptions(productAssignment).length" class="text-[11px] text-error">
|
||||||
Aucun produit disponible pour cette catégorie.
|
Aucun produit disponible pour cette catégorie.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SearchSelect
|
<SearchSelect
|
||||||
:model-value="productAssignment.selectedProductId || ''"
|
:model-value="productAssignment.selectedProductId || ''"
|
||||||
:options="getProductOptions(productAssignment.definition)"
|
:options="getProductOptions(productAssignment)"
|
||||||
:loading="productsLoading"
|
:loading="productsLoading || productLoadingByPath[productAssignment.path]"
|
||||||
size="xs"
|
size="xs"
|
||||||
placeholder="Rechercher un produit..."
|
placeholder="Rechercher un produit..."
|
||||||
:empty-text="getProductOptions(productAssignment.definition).length ? 'Aucun résultat' : 'Aucun produit disponible'"
|
:empty-text="getProductOptions(productAssignment).length ? 'Aucun résultat' : 'Aucun produit disponible'"
|
||||||
:option-label="productOptionLabel"
|
:option-label="productOptionLabel"
|
||||||
:option-description="productOptionDescription"
|
:option-description="productOptionDescription"
|
||||||
|
@search="(term) => fetchProductOptions(productAssignment, term)"
|
||||||
@update:modelValue="(value) => { productAssignment.selectedProductId = normalizeSelectionValue(value); }"
|
@update:modelValue="(value) => { productAssignment.selectedProductId = normalizeSelectionValue(value); }"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -131,8 +134,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import SearchSelect from '~/components/common/SearchSelect.vue';
|
import SearchSelect from '~/components/common/SearchSelect.vue';
|
||||||
|
import { useApi } from '~/composables/useApi';
|
||||||
import type {
|
import type {
|
||||||
ComponentModelPiece,
|
ComponentModelPiece,
|
||||||
ComponentModelProduct,
|
ComponentModelProduct,
|
||||||
@@ -206,6 +210,9 @@ const props = withDefaults(
|
|||||||
componentsLoading?: boolean;
|
componentsLoading?: boolean;
|
||||||
piecesLoading?: boolean;
|
piecesLoading?: boolean;
|
||||||
productsLoading?: boolean;
|
productsLoading?: boolean;
|
||||||
|
pieceTypeLabelMap?: Record<string, string>;
|
||||||
|
productTypeLabelMap?: Record<string, string>;
|
||||||
|
componentTypeLabelMap?: Record<string, string>;
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
depth: 0,
|
depth: 0,
|
||||||
@@ -215,6 +222,9 @@ const props = withDefaults(
|
|||||||
componentsLoading: false,
|
componentsLoading: false,
|
||||||
piecesLoading: false,
|
piecesLoading: false,
|
||||||
productsLoading: false,
|
productsLoading: false,
|
||||||
|
pieceTypeLabelMap: () => ({}),
|
||||||
|
productTypeLabelMap: () => ({}),
|
||||||
|
componentTypeLabelMap: () => ({}),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -225,10 +235,42 @@ const wrapperClass = computed(() =>
|
|||||||
depth.value === 0 ? 'space-y-6' : 'space-y-6 border-l border-base-300 pl-4',
|
depth.value === 0 ? 'space-y-6' : 'space-y-6 border-l border-base-300 pl-4',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { get } = useApi();
|
||||||
|
const pieceOptionsByPath = ref<Record<string, PieceOption[]>>({});
|
||||||
|
const productOptionsByPath = ref<Record<string, ProductOption[]>>({});
|
||||||
|
const componentOptionsByPath = ref<Record<string, ComponentOption[]>>({});
|
||||||
|
const pieceLoadingByPath = ref<Record<string, boolean>>({});
|
||||||
|
const productLoadingByPath = ref<Record<string, boolean>>({});
|
||||||
|
const componentLoadingByPath = ref<Record<string, boolean>>({});
|
||||||
|
|
||||||
|
const extractCollection = (payload: any): any[] => {
|
||||||
|
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 setLoading = (target: Record<string, boolean>, key: string, value: boolean) => {
|
||||||
|
target[key] = value;
|
||||||
|
};
|
||||||
|
|
||||||
const componentOptions = computed(() => {
|
const componentOptions = computed(() => {
|
||||||
if (isRoot.value) {
|
if (isRoot.value) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
const cached = componentOptionsByPath.value[props.assignment.path];
|
||||||
|
if (cached) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
const definition = props.assignment.definition || {};
|
const definition = props.assignment.definition || {};
|
||||||
const requiredTypeId =
|
const requiredTypeId =
|
||||||
definition.typeComposantId || definition.modelId || null;
|
definition.typeComposantId || definition.modelId || null;
|
||||||
@@ -274,6 +316,104 @@ const componentOptionDescription = (component?: ComponentOption | null) => {
|
|||||||
return parts.join(' • ');
|
return parts.join(' • ');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const typeIri = (id: string) => `/api/model_types/${id}`;
|
||||||
|
const primedPiecePaths = new Set<string>();
|
||||||
|
const primedProductPaths = new Set<string>();
|
||||||
|
const primedComponentPaths = new Set<string>();
|
||||||
|
|
||||||
|
const fetchComponentOptions = async (term = '') => {
|
||||||
|
if (isRoot.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const key = props.assignment.path;
|
||||||
|
if (componentLoadingByPath.value[key]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const definition = props.assignment.definition || {};
|
||||||
|
const requiredTypeId =
|
||||||
|
definition.typeComposantId || definition.modelId || definition.typeComposant?.id || null;
|
||||||
|
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.set('itemsPerPage', '50');
|
||||||
|
if (term.trim()) {
|
||||||
|
params.set('name', term.trim());
|
||||||
|
}
|
||||||
|
if (requiredTypeId) {
|
||||||
|
params.set('typeComposant', typeIri(requiredTypeId));
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(componentLoadingByPath.value, key, true);
|
||||||
|
try {
|
||||||
|
const result = await get(`/composants?${params.toString()}`);
|
||||||
|
if (result.success) {
|
||||||
|
componentOptionsByPath.value[key] = extractCollection(result.data);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setLoading(componentLoadingByPath.value, key, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchPieceOptions = async (assignment: StructurePieceAssignment, term = '') => {
|
||||||
|
const key = assignment.path;
|
||||||
|
if (pieceLoadingByPath.value[key]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const definition = assignment.definition || {};
|
||||||
|
const requiredTypeId =
|
||||||
|
definition.typePieceId || (definition as any).typePiece?.id || null;
|
||||||
|
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.set('itemsPerPage', '50');
|
||||||
|
if (term.trim()) {
|
||||||
|
params.set('name', term.trim());
|
||||||
|
}
|
||||||
|
if (requiredTypeId) {
|
||||||
|
params.set('typePiece', typeIri(requiredTypeId));
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(pieceLoadingByPath.value, key, true);
|
||||||
|
try {
|
||||||
|
const result = await get(`/pieces?${params.toString()}`);
|
||||||
|
if (result.success) {
|
||||||
|
pieceOptionsByPath.value[key] = extractCollection(result.data);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setLoading(pieceLoadingByPath.value, key, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchProductOptions = async (assignment: StructureProductAssignment, term = '') => {
|
||||||
|
const key = assignment.path;
|
||||||
|
if (productLoadingByPath.value[key]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const definition = assignment.definition || {};
|
||||||
|
const requiredTypeId =
|
||||||
|
definition.typeProductId || (definition as any).typeProduct?.id || null;
|
||||||
|
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.set('itemsPerPage', '50');
|
||||||
|
if (term.trim()) {
|
||||||
|
params.set('name', term.trim());
|
||||||
|
}
|
||||||
|
if (requiredTypeId) {
|
||||||
|
params.set('typeProduct', typeIri(requiredTypeId));
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(productLoadingByPath.value, key, true);
|
||||||
|
try {
|
||||||
|
const result = await get(`/products?${params.toString()}`);
|
||||||
|
if (result.success) {
|
||||||
|
productOptionsByPath.value[key] = extractCollection(result.data);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setLoading(productLoadingByPath.value, key, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
componentOptions,
|
componentOptions,
|
||||||
(options) => {
|
(options) => {
|
||||||
@@ -290,7 +430,8 @@ watch(
|
|||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
const describePieceRequirement = (definition: ComponentModelPiece) => {
|
const describePieceRequirement = (assignment: StructurePieceAssignment) => {
|
||||||
|
const definition = assignment.definition;
|
||||||
const parts: string[] = [];
|
const parts: string[] = [];
|
||||||
const addPart = (value?: string | null) => {
|
const addPart = (value?: string | null) => {
|
||||||
const trimmed = typeof value === 'string' ? value.trim() : '';
|
const trimmed = typeof value === 'string' ? value.trim() : '';
|
||||||
@@ -299,16 +440,17 @@ const describePieceRequirement = (definition: ComponentModelPiece) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const options = getPieceOptions(definition);
|
const options = getPieceOptions(assignment);
|
||||||
const fallbackPiece = options[0] || null;
|
const fallbackPiece = options[0] || null;
|
||||||
const fallbackType = fallbackPiece?.typePiece || null;
|
const fallbackType = fallbackPiece?.typePiece || null;
|
||||||
|
|
||||||
addPart(definition.role);
|
addPart(definition.role);
|
||||||
addPart(
|
const explicitLabel =
|
||||||
definition.typePieceLabel ||
|
definition.typePieceLabel ||
|
||||||
(definition as any).typePiece?.name ||
|
(definition as any).typePiece?.name ||
|
||||||
fallbackType?.name,
|
(definition.typePieceId ? props.pieceTypeLabelMap[definition.typePieceId] : null) ||
|
||||||
);
|
fallbackType?.name;
|
||||||
|
addPart(explicitLabel);
|
||||||
|
|
||||||
const family =
|
const family =
|
||||||
definition.familyCode ||
|
definition.familyCode ||
|
||||||
@@ -333,7 +475,12 @@ const describePieceRequirement = (definition: ComponentModelPiece) => {
|
|||||||
return parts.length ? parts.join(' • ') : 'Pièce du squelette';
|
return parts.length ? parts.join(' • ') : 'Pièce du squelette';
|
||||||
};
|
};
|
||||||
|
|
||||||
const getProductOptions = (definition: ComponentModelProduct) => {
|
const getProductOptions = (assignment: StructureProductAssignment) => {
|
||||||
|
const cached = productOptionsByPath.value[assignment.path];
|
||||||
|
if (cached) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
const definition = assignment.definition;
|
||||||
const requiredTypeId =
|
const requiredTypeId =
|
||||||
definition.typeProductId ||
|
definition.typeProductId ||
|
||||||
(definition as any).typeProduct?.id ||
|
(definition as any).typeProduct?.id ||
|
||||||
@@ -386,7 +533,8 @@ const productOptionDescription = (product?: ProductOption | null) => {
|
|||||||
return parts.join(' • ');
|
return parts.join(' • ');
|
||||||
};
|
};
|
||||||
|
|
||||||
const describeProductRequirement = (definition: ComponentModelProduct) => {
|
const describeProductRequirement = (assignment: StructureProductAssignment) => {
|
||||||
|
const definition = assignment.definition;
|
||||||
const parts: string[] = [];
|
const parts: string[] = [];
|
||||||
const addPart = (value?: string | null) => {
|
const addPart = (value?: string | null) => {
|
||||||
const trimmed = typeof value === 'string' ? value.trim() : '';
|
const trimmed = typeof value === 'string' ? value.trim() : '';
|
||||||
@@ -395,16 +543,17 @@ const describeProductRequirement = (definition: ComponentModelProduct) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const options = getProductOptions(definition);
|
const options = getProductOptions(assignment);
|
||||||
const fallbackProduct = options[0] || null;
|
const fallbackProduct = options[0] || null;
|
||||||
const fallbackType = fallbackProduct?.typeProduct || null;
|
const fallbackType = fallbackProduct?.typeProduct || null;
|
||||||
|
|
||||||
addPart(definition.role);
|
addPart(definition.role);
|
||||||
addPart(
|
const explicitLabel =
|
||||||
definition.typeProductLabel ||
|
definition.typeProductLabel ||
|
||||||
(definition as any).typeProduct?.name ||
|
(definition as any).typeProduct?.name ||
|
||||||
fallbackType?.name,
|
(definition.typeProductId ? props.productTypeLabelMap[definition.typeProductId] : null) ||
|
||||||
);
|
fallbackType?.name;
|
||||||
|
addPart(explicitLabel);
|
||||||
|
|
||||||
const family =
|
const family =
|
||||||
definition.familyCode ||
|
definition.familyCode ||
|
||||||
@@ -435,6 +584,9 @@ const requirementLabel = computed(() => {
|
|||||||
if (alias) {
|
if (alias) {
|
||||||
return alias;
|
return alias;
|
||||||
}
|
}
|
||||||
|
if (definition.typeComposantId && props.componentTypeLabelMap[definition.typeComposantId]) {
|
||||||
|
return props.componentTypeLabelMap[definition.typeComposantId];
|
||||||
|
}
|
||||||
if (definition.typeComposant?.name) {
|
if (definition.typeComposant?.name) {
|
||||||
return definition.typeComposant.name;
|
return definition.typeComposant.name;
|
||||||
}
|
}
|
||||||
@@ -448,6 +600,7 @@ const requirementDescription = computed(() => {
|
|||||||
const definition = props.assignment.definition || {};
|
const definition = props.assignment.definition || {};
|
||||||
const family =
|
const family =
|
||||||
definition.typeComposantLabel ||
|
definition.typeComposantLabel ||
|
||||||
|
(definition.typeComposantId ? props.componentTypeLabelMap[definition.typeComposantId] : null) ||
|
||||||
definition.typeComposant?.name ||
|
definition.typeComposant?.name ||
|
||||||
definition.familyCode;
|
definition.familyCode;
|
||||||
if (family) {
|
if (family) {
|
||||||
@@ -456,7 +609,12 @@ const requirementDescription = computed(() => {
|
|||||||
return 'Sélectionnez un composant enfant conforme à cette position.';
|
return 'Sélectionnez un composant enfant conforme à cette position.';
|
||||||
});
|
});
|
||||||
|
|
||||||
const getPieceOptions = (definition: ComponentModelPiece) => {
|
const getPieceOptions = (assignment: StructurePieceAssignment) => {
|
||||||
|
const cached = pieceOptionsByPath.value[assignment.path];
|
||||||
|
if (cached) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
const definition = assignment.definition;
|
||||||
const requiredTypeId =
|
const requiredTypeId =
|
||||||
definition.typePieceId ||
|
definition.typePieceId ||
|
||||||
(definition as any).typePiece?.id ||
|
(definition as any).typePiece?.id ||
|
||||||
@@ -526,13 +684,17 @@ watch(
|
|||||||
() => [props.pieces, props.assignment.pieces],
|
() => [props.pieces, props.assignment.pieces],
|
||||||
() => {
|
() => {
|
||||||
for (const pieceAssignment of props.assignment.pieces) {
|
for (const pieceAssignment of props.assignment.pieces) {
|
||||||
const options = getPieceOptions(pieceAssignment.definition);
|
const options = getPieceOptions(pieceAssignment);
|
||||||
if (
|
if (
|
||||||
pieceAssignment.selectedPieceId &&
|
pieceAssignment.selectedPieceId &&
|
||||||
!options.some((piece) => piece.id === pieceAssignment.selectedPieceId)
|
!options.some((piece) => piece.id === pieceAssignment.selectedPieceId)
|
||||||
) {
|
) {
|
||||||
pieceAssignment.selectedPieceId = '';
|
pieceAssignment.selectedPieceId = '';
|
||||||
}
|
}
|
||||||
|
if (!primedPiecePaths.has(pieceAssignment.path) && !pieceOptionsByPath.value[pieceAssignment.path]) {
|
||||||
|
primedPiecePaths.add(pieceAssignment.path);
|
||||||
|
fetchPieceOptions(pieceAssignment).catch(() => {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ deep: true, immediate: true },
|
{ deep: true, immediate: true },
|
||||||
@@ -542,15 +704,34 @@ watch(
|
|||||||
() => [props.products, props.assignment.products],
|
() => [props.products, props.assignment.products],
|
||||||
() => {
|
() => {
|
||||||
for (const productAssignment of props.assignment.products) {
|
for (const productAssignment of props.assignment.products) {
|
||||||
const options = getProductOptions(productAssignment.definition);
|
const options = getProductOptions(productAssignment);
|
||||||
if (
|
if (
|
||||||
productAssignment.selectedProductId &&
|
productAssignment.selectedProductId &&
|
||||||
!options.some((product) => product.id === productAssignment.selectedProductId)
|
!options.some((product) => product.id === productAssignment.selectedProductId)
|
||||||
) {
|
) {
|
||||||
productAssignment.selectedProductId = '';
|
productAssignment.selectedProductId = '';
|
||||||
}
|
}
|
||||||
|
if (!primedProductPaths.has(productAssignment.path) && !productOptionsByPath.value[productAssignment.path]) {
|
||||||
|
primedProductPaths.add(productAssignment.path);
|
||||||
|
fetchProductOptions(productAssignment).catch(() => {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ deep: true, immediate: true },
|
{ deep: true, immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.assignment.definition,
|
||||||
|
() => {
|
||||||
|
if (isRoot.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const key = props.assignment.path;
|
||||||
|
if (!primedComponentPaths.has(key) && !componentOptionsByPath.value[key]) {
|
||||||
|
primedComponentPaths.add(key);
|
||||||
|
fetchComponentOptions().catch(() => {});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const emit = defineEmits(['update:modelValue', 'search'])
|
||||||
|
|
||||||
const searchTerm = ref('')
|
const searchTerm = ref('')
|
||||||
const openDropdown = ref(false)
|
const openDropdown = ref(false)
|
||||||
@@ -267,6 +267,7 @@ function handleInput () {
|
|||||||
if (!openDropdown.value) {
|
if (!openDropdown.value) {
|
||||||
openDropdown.value = true
|
openDropdown.value = true
|
||||||
}
|
}
|
||||||
|
emit('search', searchTerm.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeDropdown () {
|
function closeDropdown () {
|
||||||
|
|||||||
@@ -212,6 +212,9 @@
|
|||||||
:pieces-loading="piecesLoading"
|
:pieces-loading="piecesLoading"
|
||||||
:products-loading="productsLoading"
|
:products-loading="productsLoading"
|
||||||
:components-loading="componentsLoading"
|
:components-loading="componentsLoading"
|
||||||
|
:piece-type-label-map="pieceTypeLabelMap"
|
||||||
|
:product-type-label-map="productTypeLabelMap"
|
||||||
|
:component-type-label-map="componentTypeLabelMap"
|
||||||
/>
|
/>
|
||||||
<p v-else class="text-xs text-error">
|
<p v-else class="text-xs text-error">
|
||||||
Impossible de générer les emplacements définis par le squelette.
|
Impossible de générer les emplacements définis par le squelette.
|
||||||
@@ -349,7 +352,9 @@ import SearchSelect from '~/components/common/SearchSelect.vue'
|
|||||||
import { useComponentTypes } from '~/composables/useComponentTypes'
|
import { useComponentTypes } from '~/composables/useComponentTypes'
|
||||||
import { useComposants } from '~/composables/useComposants'
|
import { useComposants } from '~/composables/useComposants'
|
||||||
import { usePieces } from '~/composables/usePieces'
|
import { usePieces } from '~/composables/usePieces'
|
||||||
|
import { usePieceTypes } from '~/composables/usePieceTypes'
|
||||||
import { useProducts } from '~/composables/useProducts'
|
import { useProducts } from '~/composables/useProducts'
|
||||||
|
import { useProductTypes } from '~/composables/useProductTypes'
|
||||||
import { useToast } from '~/composables/useToast'
|
import { useToast } from '~/composables/useToast'
|
||||||
import { useCustomFields } from '~/composables/useCustomFields'
|
import { useCustomFields } from '~/composables/useCustomFields'
|
||||||
import { useDocuments } from '~/composables/useDocuments'
|
import { useDocuments } from '~/composables/useDocuments'
|
||||||
@@ -372,20 +377,19 @@ const route = useRoute()
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const { componentTypes, loadComponentTypes, loadingComponentTypes } = useComponentTypes()
|
const { componentTypes, loadComponentTypes, loadingComponentTypes } = useComponentTypes()
|
||||||
|
const { pieceTypes, loadPieceTypes } = usePieceTypes()
|
||||||
|
const { productTypes, loadProductTypes } = useProductTypes()
|
||||||
const {
|
const {
|
||||||
createComposant,
|
createComposant,
|
||||||
composants: componentCatalogRef,
|
composants: componentCatalogRef,
|
||||||
loadComposants,
|
|
||||||
loading: componentsLoading,
|
loading: componentsLoading,
|
||||||
} = useComposants()
|
} = useComposants()
|
||||||
const {
|
const {
|
||||||
pieces: pieceCatalogRef,
|
pieces: pieceCatalogRef,
|
||||||
loadPieces,
|
|
||||||
loading: piecesLoading,
|
loading: piecesLoading,
|
||||||
} = usePieces()
|
} = usePieces()
|
||||||
const {
|
const {
|
||||||
products: productCatalogRef,
|
products: productCatalogRef,
|
||||||
loadProducts,
|
|
||||||
loading: productsLoading,
|
loading: productsLoading,
|
||||||
} = useProducts()
|
} = useProducts()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
@@ -414,6 +418,28 @@ const structureDataLoading = computed(
|
|||||||
() => piecesLoading.value || componentsLoading.value || productsLoading.value,
|
() => piecesLoading.value || componentsLoading.value || productsLoading.value,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const pieceTypeLabelMap = computed(() =>
|
||||||
|
Object.fromEntries(
|
||||||
|
(pieceTypes.value || [])
|
||||||
|
.filter((type: any) => type?.id)
|
||||||
|
.map((type: any) => [type.id, type.name || type.code || '']),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
const productTypeLabelMap = computed(() =>
|
||||||
|
Object.fromEntries(
|
||||||
|
(productTypes.value || [])
|
||||||
|
.filter((type: any) => type?.id)
|
||||||
|
.map((type: any) => [type.id, type.name || type.code || '']),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
const componentTypeLabelMap = computed(() =>
|
||||||
|
Object.fromEntries(
|
||||||
|
(componentTypes.value || [])
|
||||||
|
.filter((type: any) => type?.id)
|
||||||
|
.map((type: any) => [type.id, type.name || type.code || '']),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => route.query.typeId,
|
() => route.query.typeId,
|
||||||
(value) => {
|
(value) => {
|
||||||
@@ -934,9 +960,8 @@ const submitCreation = async () => {
|
|||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await Promise.allSettled([
|
await Promise.allSettled([
|
||||||
loadComponentTypes(),
|
loadComponentTypes(),
|
||||||
loadPieces(),
|
loadPieceTypes(),
|
||||||
loadComposants(),
|
loadProductTypes(),
|
||||||
loadProducts(),
|
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user