chore: update frontend configuration

This commit is contained in:
Matthieu
2025-09-26 11:29:47 +02:00
parent b7caa4f552
commit a78938a4d1
64 changed files with 5790 additions and 5129 deletions

View File

@@ -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 pièce</h1>
<p class="text-sm text-gray-500">Gérez les modèles disponibles pour chaque groupe de pièces.</p>
<h1 class="text-3xl font-bold text-gray-800">
Catalogue de pièce
</h1>
<p class="text-sm text-gray-500">
Gérez les modèles disponibles pour chaque groupe de pièces.
</p>
</div>
<div class="tabs tabs-boxed">
<NuxtLink to="/component-catalog" class="tab">Composants</NuxtLink>
<NuxtLink to="/pieces-catalog" class="tab tab-active">Pièces</NuxtLink>
<NuxtLink to="/component-catalog" class="tab">
Composants
</NuxtLink>
<NuxtLink to="/pieces-catalog" class="tab tab-active">
Pièces
</NuxtLink>
</div>
</header>
@@ -32,7 +40,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>
@@ -43,7 +51,7 @@
</div>
<div v-if="loadingPieceModels" 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">
@@ -55,10 +63,16 @@
<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 lg:table-cell">Modifié</th>
<th class="text-right">Actions</th>
<th class="hidden lg:table-cell">
Modifié
</th>
<th class="text-right">
Actions
</th>
</tr>
</thead>
<tbody>
@@ -75,9 +89,13 @@
<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.typePiece?.name || 'Non défini' }}</td>
<td class="hidden lg:table-cell text-xs text-gray-500">{{ formatFrenchDate(model.updatedAt || model.createdAt) }}</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
@@ -118,7 +136,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>
@@ -127,7 +145,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 pièce</span></label>
@@ -136,14 +154,18 @@
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 pieceTypes" :key="type.id" :value="type.id">
{{ type.name }}
</option>
</select>
</div>
<div class="divider my-0">Structure</div>
<div class="divider my-0">
Structure
</div>
<PieceModelStructureEditor v-model="form.data.structure" />
<div class="rounded-lg border border-base-200 bg-base-200/60 p-3 text-xs text-gray-500">
@@ -181,7 +203,7 @@ const {
updatePieceModel,
deletePieceModel,
loadingPieceModels,
getPieceModelsForType,
getPieceModelsForType
} = usePieceModels()
const { showError, showSuccess } = useToast()
@@ -206,15 +228,15 @@ const form = reactive({
name: '',
description: '',
typePieceId: '',
structure: defaultStructure(),
},
structure: defaultStructure()
}
})
const ensureTypeSelected = () => {
if (form.data.typePieceId && pieceTypes.value.some((type) => type.id === form.data.typePieceId)) {
if (form.data.typePieceId && pieceTypes.value.some(type => type.id === form.data.typePieceId)) {
return
}
if (selectedType.value !== 'all' && pieceTypes.value.some((type) => type.id === selectedType.value)) {
if (selectedType.value !== 'all' && pieceTypes.value.some(type => type.id === selectedType.value)) {
form.data.typePieceId = selectedType.value
return
}
@@ -228,7 +250,7 @@ const startCreate = () => {
name: '',
description: '',
typePieceId: selectedType.value !== 'all' ? selectedType.value : '',
structure: defaultStructure(),
structure: defaultStructure()
}
ensureTypeSelected()
}
@@ -240,7 +262,7 @@ const startEdit = (model) => {
name: model.name,
description: model.description || '',
typePieceId: model.typePieceId || model.typePiece?.id || '',
structure: cloneStructure(model.structure || defaultStructure()),
structure: cloneStructure(model.structure || defaultStructure())
}
}
@@ -255,9 +277,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.typePiece?.name?.toLowerCase().includes(term)
model.name?.toLowerCase().includes(term) ||
model.description?.toLowerCase().includes(term) ||
model.typePiece?.name?.toLowerCase().includes(term)
)
})
})
@@ -284,7 +306,7 @@ const handleSubmit = async () => {
name: form.data.name.trim(),
description: form.data.description.trim() || undefined,
typePieceId: form.data.typePieceId,
structure,
structure
})
if (!result.success) {
showError(result.error || 'Impossible de créer le modèle')
@@ -296,7 +318,7 @@ const handleSubmit = async () => {
name: form.data.name.trim(),
description: form.data.description.trim() || undefined,
typePieceId: form.data.typePieceId,
structure,
structure
})
if (!result.success) {
showError(result.error || 'Impossible de mettre à jour le modèle')
@@ -314,7 +336,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 deletePieceModel(model.id)
if (!result.success) {
showError(result.error || 'Impossible de supprimer ce modèle')