chore: update frontend configuration
This commit is contained in:
@@ -2,12 +2,20 @@
|
||||
<main class="container mx-auto px-6 py-8 space-y-8">
|
||||
<header class="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<div class="space-y-1">
|
||||
<h1 class="text-3xl font-bold text-gray-800">Catalogue de composant</h1>
|
||||
<p class="text-sm text-gray-500">Gérez les modèles disponibles pour chaque famille de composant.</p>
|
||||
<h1 class="text-3xl font-bold text-gray-800">
|
||||
Catalogue de composant
|
||||
</h1>
|
||||
<p class="text-sm text-gray-500">
|
||||
Gérez les modèles disponibles pour chaque famille de composant.
|
||||
</p>
|
||||
</div>
|
||||
<div class="tabs tabs-boxed">
|
||||
<NuxtLink to="/component-catalog" class="tab tab-active">Composants</NuxtLink>
|
||||
<NuxtLink to="/pieces-catalog" class="tab">Pièces</NuxtLink>
|
||||
<NuxtLink to="/component-catalog" class="tab tab-active">
|
||||
Composants
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/pieces-catalog" class="tab">
|
||||
Pièces
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -36,7 +44,7 @@
|
||||
type="search"
|
||||
placeholder="Rechercher un modèle..."
|
||||
class="input input-bordered input-sm"
|
||||
/>
|
||||
>
|
||||
</label>
|
||||
<span class="text-xs text-gray-500">{{ filteredModels.length }} modèle(s)</span>
|
||||
</div>
|
||||
@@ -47,7 +55,7 @@
|
||||
</div>
|
||||
|
||||
<div v-if="loadingComponentModels" class="flex justify-center py-16">
|
||||
<span class="loading loading-spinner loading-lg"></span>
|
||||
<span class="loading loading-spinner loading-lg" />
|
||||
</div>
|
||||
|
||||
<div v-else-if="filteredModels.length === 0" class="py-16 text-center text-sm text-gray-500">
|
||||
@@ -59,11 +67,19 @@
|
||||
<thead>
|
||||
<tr class="text-sm text-gray-500">
|
||||
<th>Nom</th>
|
||||
<th class="hidden md:table-cell">Description</th>
|
||||
<th class="hidden md:table-cell">
|
||||
Description
|
||||
</th>
|
||||
<th>Type</th>
|
||||
<th class="hidden xl:table-cell">Structure</th>
|
||||
<th class="hidden lg:table-cell">Modifié</th>
|
||||
<th class="text-right">Actions</th>
|
||||
<th class="hidden xl:table-cell">
|
||||
Structure
|
||||
</th>
|
||||
<th class="hidden lg:table-cell">
|
||||
Modifié
|
||||
</th>
|
||||
<th class="text-right">
|
||||
Actions
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -80,10 +96,16 @@
|
||||
<span class="font-medium">{{ model.name }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="hidden md:table-cell">{{ model.description || '—' }}</td>
|
||||
<td class="hidden md:table-cell">
|
||||
{{ model.description || '—' }}
|
||||
</td>
|
||||
<td>{{ model.typeComposant?.name || 'Non défini' }}</td>
|
||||
<td class="hidden xl:table-cell text-xs text-gray-500">{{ formatStructurePreview(model.structure) }}</td>
|
||||
<td class="hidden lg:table-cell text-xs text-gray-500">{{ formatFrenchDate(model.updatedAt || model.createdAt) }}</td>
|
||||
<td class="hidden xl:table-cell text-xs text-gray-500">
|
||||
{{ formatStructurePreview(model.structure) }}
|
||||
</td>
|
||||
<td class="hidden lg:table-cell text-xs text-gray-500">
|
||||
{{ formatFrenchDate(model.updatedAt || model.createdAt) }}
|
||||
</td>
|
||||
<td class="text-right space-x-2">
|
||||
<button type="button" class="btn btn-sm btn-outline" @click="startEdit(model)">
|
||||
Éditer
|
||||
@@ -124,7 +146,7 @@
|
||||
class="input input-bordered input-sm"
|
||||
placeholder="Nom du modèle"
|
||||
required
|
||||
/>
|
||||
>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label"><span class="label-text">Description</span></label>
|
||||
@@ -133,7 +155,7 @@
|
||||
class="textarea textarea-bordered textarea-sm"
|
||||
rows="3"
|
||||
placeholder="Notes optionnelles"
|
||||
></textarea>
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label"><span class="label-text">Type de composant</span></label>
|
||||
@@ -142,7 +164,9 @@
|
||||
class="select select-bordered select-sm"
|
||||
required
|
||||
>
|
||||
<option value="" disabled>Sélectionner un type</option>
|
||||
<option value="" disabled>
|
||||
Sélectionner un type
|
||||
</option>
|
||||
<option
|
||||
v-for="type in componentTypes"
|
||||
:key="type.id"
|
||||
@@ -153,7 +177,9 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="divider my-0">Structure</div>
|
||||
<div class="divider my-0">
|
||||
Structure
|
||||
</div>
|
||||
<ComponentModelStructureEditor v-model="form.data.structure" />
|
||||
<div class="rounded-lg border border-base-200 bg-base-200/60 p-3 text-xs text-gray-500">
|
||||
Aperçu : {{ formatStructurePreview(form.data.structure) }}
|
||||
@@ -190,7 +216,7 @@ const {
|
||||
updateComponentModel,
|
||||
deleteComponentModel,
|
||||
loadingComponentModels,
|
||||
getComponentModelsForType,
|
||||
getComponentModelsForType
|
||||
} = useComponentModels()
|
||||
const { showError, showSuccess } = useToast()
|
||||
|
||||
@@ -205,15 +231,15 @@ const form = reactive({
|
||||
name: '',
|
||||
description: '',
|
||||
typeComposantId: '',
|
||||
structure: {},
|
||||
},
|
||||
structure: {}
|
||||
}
|
||||
})
|
||||
|
||||
const ensureTypeSelected = () => {
|
||||
if (form.data.typeComposantId && componentTypes.value.some((type) => type.id === form.data.typeComposantId)) {
|
||||
if (form.data.typeComposantId && componentTypes.value.some(type => type.id === form.data.typeComposantId)) {
|
||||
return
|
||||
}
|
||||
if (selectedType.value !== 'all' && componentTypes.value.some((type) => type.id === selectedType.value)) {
|
||||
if (selectedType.value !== 'all' && componentTypes.value.some(type => type.id === selectedType.value)) {
|
||||
form.data.typeComposantId = selectedType.value
|
||||
return
|
||||
}
|
||||
@@ -227,7 +253,7 @@ const startCreate = () => {
|
||||
name: '',
|
||||
description: '',
|
||||
typeComposantId: selectedType.value !== 'all' ? selectedType.value : '',
|
||||
structure: {},
|
||||
structure: {}
|
||||
}
|
||||
ensureTypeSelected()
|
||||
}
|
||||
@@ -239,7 +265,7 @@ const startEdit = (model) => {
|
||||
name: model.name,
|
||||
description: model.description || '',
|
||||
typeComposantId: model.typeComposantId || model.typeComposant?.id || '',
|
||||
structure: model.structure || {},
|
||||
structure: model.structure || {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,9 +280,9 @@ const filteredModels = computed(() => {
|
||||
const term = searchQuery.value.toLowerCase()
|
||||
return list.filter((model) => {
|
||||
return (
|
||||
model.name?.toLowerCase().includes(term)
|
||||
|| model.description?.toLowerCase().includes(term)
|
||||
|| model.typeComposant?.name?.toLowerCase().includes(term)
|
||||
model.name?.toLowerCase().includes(term) ||
|
||||
model.description?.toLowerCase().includes(term) ||
|
||||
model.typeComposant?.name?.toLowerCase().includes(term)
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -282,7 +308,7 @@ const handleSubmit = async () => {
|
||||
name: form.data.name.trim(),
|
||||
description: form.data.description.trim() || undefined,
|
||||
typeComposantId: form.data.typeComposantId,
|
||||
structure: form.data.structure || {},
|
||||
structure: form.data.structure || {}
|
||||
})
|
||||
if (!result.success) {
|
||||
showError(result.error || 'Impossible de créer le modèle')
|
||||
@@ -294,7 +320,7 @@ const handleSubmit = async () => {
|
||||
name: form.data.name.trim(),
|
||||
description: form.data.description.trim() || undefined,
|
||||
typeComposantId: form.data.typeComposantId,
|
||||
structure: form.data.structure || {},
|
||||
structure: form.data.structure || {}
|
||||
})
|
||||
if (!result.success) {
|
||||
showError(result.error || 'Impossible de mettre à jour le modèle')
|
||||
@@ -312,7 +338,7 @@ const handleSubmit = async () => {
|
||||
|
||||
const confirmDelete = async (model) => {
|
||||
const ok = confirm(`Supprimer le modèle "${model.name}" ?`)
|
||||
if (!ok) return
|
||||
if (!ok) { return }
|
||||
const result = await deleteComponentModel(model.id)
|
||||
if (!result.success) {
|
||||
showError(result.error || 'Impossible de supprimer ce modèle')
|
||||
|
||||
Reference in New Issue
Block a user