Files
Inventory/app/pages/generator.vue
2025-09-17 11:13:57 +02:00

222 lines
7.4 KiB
Vue

<template>
<main class="container mx-auto px-6 py-8 space-y-8">
<div class="hero min-h-[30vh] bg-gradient-to-r from-primary to-secondary">
<div class="hero-content text-center text-neutral-content">
<div class="max-w-md">
<h1 class="mb-5 text-4xl font-bold">Générateur de Types</h1>
<p class="mb-5">
Créez rapidement un nouveau type de machine avec sa structure complète.
</p>
</div>
</div>
</div>
<div class="card bg-base-100 shadow-xl">
<div class="card-body space-y-6">
<div class="flex items-center gap-3">
<span class="inline-flex h-10 w-10 items-center justify-center rounded-full bg-primary/10 text-primary">
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
</span>
<div>
<h2 class="card-title text-2xl">Nouveau type de machine</h2>
<p class="text-sm text-gray-500">
Complétez les informations puis enregistrez pour générer le nouveau type.
</p>
</div>
</div>
<form @submit.prevent="handleSubmit">
<TypeEditForm
:key="formKey"
v-model="draftType"
:saving="creating"
:resettable="false"
submit-label="Créer le type"
submit-loading-label="Création..."
/>
</form>
</div>
</div>
<section class="space-y-4">
<div v-if="initialLoading" class="text-center py-12 text-sm text-gray-500">
Chargement des types existants...
</div>
<template v-else>
<div v-if="recentTypes.length" class="space-y-4">
<h3 class="text-xl font-semibold">Types générés récemment</h3>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
<article
v-for="type in recentTypes"
:key="type.id"
class="card bg-base-100 shadow-md border border-base-200"
>
<div class="card-body space-y-2">
<div class="flex items-center justify-between">
<h4 class="card-title text-base">{{ type.name }}</h4>
<span v-if="type.category" class="badge badge-outline badge-sm">{{ type.category }}</span>
</div>
<p class="text-sm text-gray-600 line-clamp-3">{{ type.description || 'Aucune description' }}</p>
<div class="text-xs text-gray-500 flex items-center gap-2">
<span class="inline-flex items-center gap-1">
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-3-3v6m-7 5h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
{{ type.components?.length || 0 }} composant(s)
</span>
<span class="inline-flex items-center gap-1">
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M4 14h16M4 18h16" />
</svg>
{{ type.machinePieces?.length || 0 }} pièce(s) machine
</span>
</div>
</div>
</article>
</div>
</div>
<div v-else class="text-center py-12 text-sm text-gray-500">
Aucun type généré récemment.
</div>
</template>
</section>
</main>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import { useMachineTypesApi } from '~/composables/useMachineTypesApi'
import { useToast } from '~/composables/useToast'
const { machineTypes, loadMachineTypes, createMachineType } = useMachineTypesApi()
const { showError } = useToast()
const formKey = ref(0)
const creating = ref(false)
const initialLoading = ref(true)
const createEmptyType = () => ({
name: '',
description: '',
category: '',
maintenanceFrequency: '',
customFields: [],
machinePieces: [],
components: []
})
const draftType = ref(createEmptyType())
const recentTypes = computed(() => machineTypes.value.slice(-3).reverse())
onMounted(async () => {
if (!machineTypes.value.length) {
try {
initialLoading.value = true
await loadMachineTypes()
} finally {
initialLoading.value = false
}
} else {
initialLoading.value = false
}
})
const parseOptions = (field = {}) => {
if (field.type !== 'select') return []
if (field.optionsText && typeof field.optionsText === 'string') {
return field.optionsText
.split('\n')
.map(option => option.trim())
.filter(Boolean)
}
if (Array.isArray(field.options)) {
return field.options
.map(option => String(option).trim())
.filter(Boolean)
}
return []
}
const normalizeCustomFields = (fields = []) =>
fields
.filter(field => field?.name && field.name.trim() !== '')
.map(field => ({
name: field.name,
type: field.type || '',
required: !!field.required,
defaultValue: field.defaultValue || '',
options: parseOptions(field)
}))
const normalizePrice = (value) => {
if (value === undefined || value === null || value === '') return null
const num = Number(value)
return Number.isFinite(num) ? num : null
}
const normalizePieces = (pieces = []) =>
pieces
.filter(piece => piece?.name && piece.name.trim() !== '')
.map(piece => ({
name: piece.name,
reference: piece.reference || '',
constructeur: piece.constructeur || '',
emplacement: piece.emplacement || '',
prix: normalizePrice(piece.prix),
customFields: normalizeCustomFields(piece.customFields || [])
}))
const normalizeComponents = (components = []) =>
components
.filter(component => component?.name && component.name.trim() !== '')
.map(component => ({
name: component.name,
reference: component.reference || '',
constructeur: component.constructeur || '',
emplacement: component.emplacement || '',
prix: normalizePrice(component.prix),
customFields: normalizeCustomFields(component.customFields || []),
pieces: normalizePieces(component.pieces || []),
subComponents: normalizeComponents(component.subComponents || [])
}))
const buildPayload = (typeData) => ({
name: typeData.name,
description: typeData.description,
category: typeData.category,
maintenanceFrequency: typeData.maintenanceFrequency,
customFields: normalizeCustomFields(typeData.customFields),
machinePieces: normalizePieces(typeData.machinePieces),
components: normalizeComponents(typeData.components)
})
const resetForm = () => {
draftType.value = createEmptyType()
formKey.value += 1
}
const handleSubmit = async () => {
if (!draftType.value.name?.trim()) {
showError('Le nom du type est requis.')
return
}
const payload = buildPayload(draftType.value)
creating.value = true
const result = await createMachineType(payload)
creating.value = false
if (result?.success) {
resetForm()
} else if (result?.error) {
showError(result.error)
} else {
showError("Impossible de créer le type.")
}
}
</script>