refactor(machines) : remove TypeMachine skeleton system, simplify machine creation

- Remove TypeEdit*, TypeInfoDisplay, MachineSkeletonSummary, MachineCreatePreview components
- Remove machine-skeleton pages and type pages
- Remove useMachineTypesApi, useMachineSkeletonEditor, useMachineCreateSelections composables
- Add AddEntityToMachineModal for direct entity linking
- Update machine detail/create pages for direct custom fields
- Fix SearchSelect, category display, and ipartial search filters

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matthieu
2026-03-05 17:25:23 +01:00
parent 6f1bac381d
commit 32d03b480d
49 changed files with 1058 additions and 6093 deletions

View File

@@ -49,35 +49,18 @@
</div>
<div class="form-control">
<label class="label">
<span class="label-text">Type de machine</span>
<span class="label-text">Site</span>
</label>
<select v-model="selectedType" class="select select-bordered">
<select v-model="selectedSiteFilter" class="select select-bordered">
<option value="">
Tous les types
Tous les sites
</option>
<option
v-for="type in machineTypes"
:key="type.id"
:value="type.id"
v-for="site in sites"
:key="site.id"
:value="site.id"
>
{{ type.name }}
</option>
</select>
</div>
<div class="form-control">
<label class="label">
<span class="label-text">Catégorie</span>
</label>
<select v-model="selectedCategory" class="select select-bordered">
<option value="">
Toutes les catégories
</option>
<option
v-for="category in categories"
:key="category"
:value="category"
>
{{ category }}
{{ site.name }}
</option>
</select>
</div>
@@ -208,27 +191,9 @@
<h4 class="font-semibold text-sm">
{{ machine.name }}
</h4>
<div
class="badge badge-sm"
:class="
getCategoryBadgeClass(machine.typeMachine?.category)
"
>
{{ machine.typeMachine?.category || "N/A" }}
</div>
</div>
<div class="space-y-1 text-xs text-gray-600">
<div class="flex items-center gap-1">
<IconLucideSettings2
class="w-3 h-3"
aria-hidden="true"
/>
<span>{{
machine.typeMachine?.name || "Type inconnu"
}}</span>
</div>
<div
v-if="machine.reference"
class="flex items-center gap-1"
@@ -373,78 +338,17 @@
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div class="form-control">
<label class="label">
<span class="label-text">Type de machine</span>
</label>
<select
v-model="newMachine.typeMachineId"
class="select select-bordered"
:disabled="!canEdit"
required
>
<option value="">
Sélectionner un type
</option>
<option
v-for="type in machineTypes"
:key="type.id"
:value="type.id"
>
{{ type.name }} ({{ type.category }})
</option>
</select>
</div>
<div class="form-control">
<label class="label">
<span class="label-text">Référence</span>
</label>
<input
v-model="newMachine.reference"
type="text"
placeholder="Ex: PRESS-001"
class="input input-bordered"
:disabled="!canEdit"
>
</div>
</div>
<!-- Type Preview -->
<div
v-if="selectedMachineType"
class="mb-4 p-4 bg-gray-50 rounded-lg"
>
<h4 class="font-semibold text-sm mb-2">
Structure du type sélectionné :
</h4>
<div class="text-xs space-y-1">
<div class="flex items-center gap-2">
<span class="font-medium">Familles de composants :</span>
<span class="badge badge-sm">{{
selectedMachineType.componentRequirements?.length || 0
}}</span>
</div>
<div class="flex items-center gap-2">
<span class="font-medium">Groupes de pièces :</span>
<span class="badge badge-sm">{{
selectedMachineType.pieceRequirements?.length || 0
}}</span>
</div>
<div class="flex items-center gap-2">
<span class="font-medium">Produits requis :</span>
<span class="badge badge-sm">{{
selectedMachineType.productRequirements?.length || 0
}}</span>
</div>
<div class="flex items-center gap-2">
<span class="font-medium">Catégorie :</span>
<span class="badge badge-outline badge-sm">{{
selectedMachineType.category
}}</span>
</div>
</div>
<div class="form-control mb-4">
<label class="label">
<span class="label-text">Référence</span>
</label>
<input
v-model="newMachine.reference"
type="text"
placeholder="Ex: PRESS-001"
class="input input-bordered"
:disabled="!canEdit"
>
</div>
<div class="modal-action">
@@ -469,7 +373,6 @@
import { ref, reactive, onMounted, computed } from 'vue'
import SiteContactFormFields from '~/components/sites/SiteContactFormFields.vue'
import { useSites } from '~/composables/useSites'
import { useMachineTypesApi } from '~/composables/useMachineTypesApi'
import { useMachines } from '~/composables/useMachines'
import { useToast } from '~/composables/useToast'
import { humanizeError } from '~/shared/utils/errorMessages'
@@ -479,22 +382,19 @@ import IconLucideUser from '~icons/lucide/user'
import IconLucidePhone from '~icons/lucide/phone'
import IconLucideMapPinned from '~icons/lucide/map-pinned'
import IconLucideChevronDown from '~icons/lucide/chevron-down'
import IconLucideSettings2 from '~icons/lucide/settings-2'
import IconLucideTag from '~icons/lucide/tag'
import { formatPhone } from '~/utils/formatters/phone'
import { extractRelationId } from '~/shared/apiRelations'
const { canEdit } = usePermissions()
const { sites, loading, loadSites, createSite } = useSites()
const { machineTypes, loadMachineTypes } = useMachineTypesApi()
const { machines, loadMachines, createMachineFromType, deleteMachine } = useMachines()
const { machines, loadMachines, createMachine, deleteMachine } = useMachines()
// Data
const showAddSiteModal = ref(false)
const showAddMachineModal = ref(false)
const searchTerm = ref('')
const selectedType = ref('')
const selectedCategory = ref('')
const selectedSiteFilter = ref('')
const collapsedSites = ref([])
const newSite = reactive({
@@ -509,48 +409,14 @@ const newSite = reactive({
const newMachine = reactive({
name: '',
siteId: '',
typeMachineId: '',
reference: ''
})
// Computed
const selectedMachineType = computed(() => {
if (!newMachine.typeMachineId) { return null }
return machineTypes.value.find(
type => type.id === newMachine.typeMachineId
)
})
const categories = computed(() => {
const cats = new Set()
machineTypes.value.forEach((type) => {
if (type.category) { cats.add(type.category) }
})
return Array.from(cats)
})
const machinesWithType = computed(() => {
return machines.value.map((machine) => {
const resolvedTypeMachineId = machine.typeMachineId || extractRelationId(machine.typeMachine)
const resolvedTypeMachine = resolvedTypeMachineId
? machineTypes.value.find(type => type.id === resolvedTypeMachineId) || null
: null
return {
...machine,
typeMachineId: resolvedTypeMachineId || machine.typeMachineId,
typeMachine:
machine.typeMachine && typeof machine.typeMachine === 'object'
? machine.typeMachine
: resolvedTypeMachine
}
})
})
const machinesBySiteId = computed(() => {
const map = new Map()
machinesWithType.value.forEach((machine) => {
machines.value.forEach((machine) => {
const siteId = machine.siteId || extractRelationId(machine.site)
if (!siteId) { return }
@@ -588,6 +454,11 @@ const formatPhoneDisplay = (value) => {
const filteredSites = computed(() => {
let filtered = sitesWithMachines.value
// Filtrer par site
if (selectedSiteFilter.value) {
filtered = filtered.filter(site => site.id === selectedSiteFilter.value)
}
// Filtrer par terme de recherche
if (searchTerm.value) {
filtered = filtered.filter((site) => {
@@ -616,33 +487,6 @@ const filteredSites = computed(() => {
})
}
// Filtrer par type de machine
if (selectedType.value) {
filtered = filtered
.map(site => ({
...site,
machines:
site.machines?.filter(
machine => machine.typeMachineId === selectedType.value
) || []
}))
.filter(site => site.machines.length > 0)
}
// Filtrer par catégorie
if (selectedCategory.value) {
filtered = filtered
.map(site => ({
...site,
machines:
site.machines?.filter(
machine =>
machine.typeMachine?.category === selectedCategory.value
) || []
}))
.filter(site => site.machines.length > 0)
}
return filtered
})
@@ -670,27 +514,15 @@ const handleCreateSite = async () => {
}
const handleCreateMachine = async () => {
if (!selectedMachineType.value) {
console.error('Aucun type de machine sélectionné')
return
}
const machineData = {
const result = await createMachine({
name: newMachine.name,
siteId: newMachine.siteId,
reference: newMachine.reference
}
const result = await createMachineFromType(
machineData,
selectedMachineType.value
)
})
if (result.success) {
// Reset form
newMachine.name = ''
newMachine.siteId = ''
newMachine.typeMachineId = ''
newMachine.reference = ''
showAddMachineModal.value = false
await loadMachines()
@@ -745,19 +577,8 @@ const addMachineToSite = (site) => {
showAddMachineModal.value = true
}
const getCategoryBadgeClass = (category) => {
const classes = {
Production: 'badge-primary',
Transformation: 'badge-secondary',
Manutention: 'badge-accent',
Traitement: 'badge-info',
Contrôle: 'badge-warning'
}
return classes[category] || 'badge-neutral'
}
// Lifecycle
onMounted(async () => {
await Promise.all([loadSites(), loadMachineTypes(), loadMachines()])
await Promise.all([loadSites(), loadMachines()])
})
</script>