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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user