Files
Inventory_frontend/app/components/SkeletonComponentNodeSelector.vue

202 lines
6.6 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div :class="['space-y-4', depth > 0 ? 'border-l border-base-200 pl-4 ml-2' : '']">
<div class="bg-base-100 border border-base-200 rounded-lg p-4 space-y-4">
<div class="flex flex-col gap-2">
<div class="flex items-start justify-between gap-3">
<div class="space-y-1">
<h4 class="font-semibold text-sm">
{{ node.name || node.typeComposantLabel || 'Composant' }}
</h4>
<p class="text-xs text-gray-500">
{{
node.typeComposantLabel
? `Famille : ${node.typeComposantLabel}`
: node.typeComposantId
? `Famille : ${node.typeComposantId}`
: 'Famille non définie'
}}
</p>
</div>
<div v-if="!showSelfSelector && selectedComponentModelLabel" class="badge badge-outline badge-sm">
Modèle : {{ selectedComponentModelLabel }}
</div>
</div>
<div v-if="showSelfSelector" class="form-control max-w-xs">
<label class="label">
<span class="label-text text-xs">Modèle de composant</span>
</label>
<select
class="select select-bordered select-xs"
:value="selectedComponentModelId"
@change="onComponentModelSelect($event.target.value)"
>
<option value="">Sélectionner un modèle</option>
<option v-for="model in componentModels" :key="model.id" :value="model.id">
{{ model.name }}
</option>
</select>
<p v-if="loadingComponentModels" class="text-[10px] text-gray-500 mt-1">
Chargement des modèles
</p>
<p v-else-if="!componentModels.length" class="text-[10px] text-gray-500 mt-1">
Aucun modèle disponible pour cette famille.
</p>
</div>
</div>
<div v-if="hasPieces" class="space-y-2">
<h5 class="text-[11px] font-semibold uppercase text-gray-500">Pièces associées</h5>
<div
v-for="(piece, pieceIndex) in node.pieces"
:key="pieceIndex"
class="bg-base-200/60 border border-base-200 rounded-md p-3 space-y-2"
>
<div class="space-y-1">
<span class="font-medium text-sm">{{ piece.name || piece.typePieceLabel || 'Pièce' }}</span>
<p class="text-[11px] text-gray-500">
{{
piece.typePieceLabel
? `Famille : ${piece.typePieceLabel}`
: piece.typePieceId
? `Famille : ${piece.typePieceId}`
: 'Famille non définie'
}}
</p>
</div>
<div class="form-control max-w-xs">
<label class="label">
<span class="label-text text-xs">Modèle de pièce</span>
</label>
<select
class="select select-bordered select-xs"
:value="piece.__pieceModelId || ''"
@change="onPieceModelSelect(piece, $event.target.value)"
>
<option value="">Sélectionner un modèle</option>
<option v-for="model in getPieceModels(piece.typePieceId)" :key="model.id" :value="model.id">
{{ model.name }}
</option>
</select>
<p v-if="loadingPieceModels" class="text-[10px] text-gray-500 mt-1">
Chargement des modèles
</p>
<p
v-else-if="getPieceModels(piece.typePieceId).length === 0"
class="text-[10px] text-gray-500 mt-1"
>
Aucun modèle disponible pour cette famille.
</p>
</div>
</div>
</div>
<div v-if="hasSubComponents" class="space-y-3">
<h5 class="text-[11px] font-semibold uppercase text-gray-500">Sous-composants</h5>
<SkeletonComponentNodeSelector
v-for="(subComponent, index) in node.subComponents"
:key="index"
:node="subComponent"
:depth="depth + 1"
:get-component-models-for-type="getComponentModelsForType"
:get-piece-models-for-type="getPieceModelsForType"
:loading-component-models="loadingComponentModels"
:loading-piece-models="loadingPieceModels"
@component-model-change="forwardComponentModelChange"
@piece-model-change="forwardPieceModelChange"
/>
</div>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue'
defineOptions({ name: 'SkeletonComponentNodeSelector' })
const props = withDefaults(defineProps({
node: {
type: Object,
required: true,
},
depth: {
type: Number,
default: 0,
},
getComponentModelsForType: {
type: Function,
required: true,
},
getPieceModelsForType: {
type: Function,
required: true,
},
loadingComponentModels: {
type: Boolean,
default: false,
},
loadingPieceModels: {
type: Boolean,
default: false,
},
showSelfSelector: {
type: Boolean,
default: true,
},
}), {
depth: 0,
loadingComponentModels: false,
loadingPieceModels: false,
showSelfSelector: true,
})
const emit = defineEmits(['component-model-change', 'piece-model-change'])
const componentModels = computed(() => {
if (!props.node?.typeComposantId) {
return []
}
const models = props.getComponentModelsForType(props.node.typeComposantId)
return Array.isArray(models) ? models : []
})
const selectedComponentModelId = computed(() => props.node?.__componentModelId || '')
const selectedComponentModelLabel = computed(() => {
if (!selectedComponentModelId.value) {
return ''
}
const match = componentModels.value.find((model) => model.id === selectedComponentModelId.value)
return match?.name || ''
})
const hasPieces = computed(() => Array.isArray(props.node?.pieces) && props.node.pieces.length > 0)
const hasSubComponents = computed(() => Array.isArray(props.node?.subComponents) && props.node.subComponents.length > 0)
const getPieceModels = (typePieceId) => {
if (!typePieceId) {
return []
}
const models = props.getPieceModelsForType(typePieceId)
return Array.isArray(models) ? models : []
}
const onComponentModelSelect = (value) => {
emit('component-model-change', props.node, props.node?.typeComposantId || '', value || '')
}
const onPieceModelSelect = (piece, value) => {
emit('piece-model-change', piece, piece?.typePieceId || '', value || '')
}
const forwardComponentModelChange = (...args) => {
emit('component-model-change', ...args)
}
const forwardPieceModelChange = (...args) => {
emit('piece-model-change', ...args)
}
</script>