feat: Composables pour la gestion des données
- useApi.js : Service API générique avec gestion d'erreurs - useSites.js : Gestion des sites industriels - useMachines.js : Gestion des machines et création depuis types - useMachineTypes.js : Gestion des types de machines - useMachineTypesApi.js : API pour les types de machines - useComposants.js : Gestion des composants hiérarchiques - usePieces.js : Gestion des pièces de machines - useCustomFields.js : Gestion des champs personnalisés - useToast.js : Système de notifications toast
This commit is contained in:
75
app/composables/useApi.js
Normal file
75
app/composables/useApi.js
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import { useToast } from './useToast'
|
||||||
|
|
||||||
|
export function useApi() {
|
||||||
|
const { showSuccess, showError, showInfo } = useToast()
|
||||||
|
const API_BASE_URL = process.env.NUXT_PUBLIC_API_BASE_URL || 'http://localhost:3000/api'
|
||||||
|
const API_TIMEOUT = parseInt(process.env.NUXT_PUBLIC_API_TIMEOUT || '30000')
|
||||||
|
|
||||||
|
const apiCall = async (endpoint, options = {}) => {
|
||||||
|
const url = `${API_BASE_URL}${endpoint}`
|
||||||
|
const defaultOptions = {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ajouter un timeout à la requête
|
||||||
|
const controller = new AbortController()
|
||||||
|
const timeoutId = setTimeout(() => controller.abort(), API_TIMEOUT)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, {
|
||||||
|
...defaultOptions,
|
||||||
|
...options,
|
||||||
|
signal: controller.signal
|
||||||
|
})
|
||||||
|
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const data = await response.json()
|
||||||
|
return { success: true, data }
|
||||||
|
} else {
|
||||||
|
const errorData = await response.json().catch(() => ({}))
|
||||||
|
const errorMessage = errorData.message || `Erreur ${response.status}: ${response.statusText}`
|
||||||
|
showError(errorMessage)
|
||||||
|
return { success: false, error: errorMessage, status: response.status }
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
const errorMessage = error.name === 'AbortError' ? 'Timeout de la requête' : error.message || 'Erreur réseau'
|
||||||
|
showError(`Erreur réseau: ${errorMessage}`)
|
||||||
|
return { success: false, error: errorMessage }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const get = async (endpoint) => {
|
||||||
|
return apiCall(endpoint, { method: 'GET' })
|
||||||
|
}
|
||||||
|
|
||||||
|
const post = async (endpoint, data) => {
|
||||||
|
return apiCall(endpoint, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const patch = async (endpoint, data) => {
|
||||||
|
return apiCall(endpoint, {
|
||||||
|
method: 'PATCH',
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const del = async (endpoint) => {
|
||||||
|
return apiCall(endpoint, { method: 'DELETE' })
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
apiCall,
|
||||||
|
get,
|
||||||
|
post,
|
||||||
|
patch,
|
||||||
|
delete: del
|
||||||
|
}
|
||||||
|
}
|
||||||
134
app/composables/useComposants.js
Normal file
134
app/composables/useComposants.js
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import { ref } from 'vue'
|
||||||
|
import { useToast } from './useToast'
|
||||||
|
import { useApi } from './useApi'
|
||||||
|
|
||||||
|
const composants = ref([])
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
export function useComposants() {
|
||||||
|
const { showSuccess, showError, showInfo } = useToast()
|
||||||
|
const { get, post, patch, delete: del } = useApi()
|
||||||
|
|
||||||
|
const loadComposants = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await get('/composants')
|
||||||
|
if (result.success) {
|
||||||
|
composants.value = result.data
|
||||||
|
showInfo(`Chargement de ${composants.value.length} composant(s) réussi`)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors du chargement des composants:', error)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getComposantsByMachine = async (machineId) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await get(`/composants/machine/${machineId}`)
|
||||||
|
if (result.success) {
|
||||||
|
return { success: true, data: result.data }
|
||||||
|
}
|
||||||
|
return { success: false, error: result.error }
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors du chargement des composants:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getComposantHierarchy = async (machineId) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await get(`/composants/hierarchy/${machineId}`)
|
||||||
|
if (result.success) {
|
||||||
|
return { success: true, data: result.data }
|
||||||
|
}
|
||||||
|
return { success: false, error: result.error }
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors du chargement de la hiérarchie:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const createComposant = async (composantData) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await post('/composants', composantData)
|
||||||
|
if (result.success) {
|
||||||
|
composants.value.push(result.data)
|
||||||
|
showSuccess(`Composant "${composantData.name}" créé avec succès`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la création du composant:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateComposantData = async (id, composantData) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await patch(`/composants/${id}`, composantData)
|
||||||
|
if (result.success) {
|
||||||
|
const index = composants.value.findIndex(comp => comp.id === id)
|
||||||
|
if (index !== -1) {
|
||||||
|
composants.value[index] = result.data
|
||||||
|
}
|
||||||
|
showSuccess(`Composant "${composantData.name}" mis à jour avec succès`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la mise à jour du composant:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteComposant = async (id) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await del(`/composants/${id}`)
|
||||||
|
if (result.success) {
|
||||||
|
const deletedComposant = composants.value.find(comp => comp.id === id)
|
||||||
|
composants.value = composants.value.filter(comp => comp.id !== id)
|
||||||
|
showSuccess(`Composant "${deletedComposant?.name || 'inconnu'}" supprimé avec succès`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la suppression du composant:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getComposantById = (id) => {
|
||||||
|
return composants.value.find(comp => comp.id === id)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getComposants = () => composants.value
|
||||||
|
const isLoading = () => loading.value
|
||||||
|
|
||||||
|
return {
|
||||||
|
composants,
|
||||||
|
loading,
|
||||||
|
loadComposants,
|
||||||
|
getComposantsByMachine,
|
||||||
|
getComposantHierarchy,
|
||||||
|
createComposant,
|
||||||
|
updateComposant: updateComposantData,
|
||||||
|
deleteComposant,
|
||||||
|
getComposantById,
|
||||||
|
getComposants,
|
||||||
|
isLoading
|
||||||
|
}
|
||||||
|
}
|
||||||
97
app/composables/useCustomFields.js
Normal file
97
app/composables/useCustomFields.js
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import { ref } from 'vue'
|
||||||
|
import { useApi } from './useApi'
|
||||||
|
|
||||||
|
export function useCustomFields() {
|
||||||
|
const { apiCall } = useApi()
|
||||||
|
const customFieldValues = ref([])
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
// Créer une valeur de champ personnalisé
|
||||||
|
const createCustomFieldValue = async (customFieldValueData) => {
|
||||||
|
try {
|
||||||
|
const result = await apiCall('/custom-fields/values', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(customFieldValueData)
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la création de la valeur de champ personnalisé:', error)
|
||||||
|
return { success: false, error }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtenir les valeurs de champs personnalisés pour une entité
|
||||||
|
const getCustomFieldValuesByEntity = async (entityType, entityId) => {
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
const result = await apiCall(`/custom-fields/values/${entityType}/${entityId}`, {
|
||||||
|
method: 'GET'
|
||||||
|
})
|
||||||
|
if (result.success) {
|
||||||
|
customFieldValues.value = result.data
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la récupération des valeurs de champs personnalisés:', error)
|
||||||
|
return { success: false, error }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mettre à jour une valeur de champ personnalisé
|
||||||
|
const updateCustomFieldValue = async (id, updateData) => {
|
||||||
|
try {
|
||||||
|
const result = await apiCall(`/custom-fields/values/${id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
body: JSON.stringify(updateData)
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la mise à jour de la valeur de champ personnalisé:', error)
|
||||||
|
return { success: false, error }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Créer ou mettre à jour une valeur de champ personnalisé
|
||||||
|
const upsertCustomFieldValue = async (customFieldId, entityType, entityId, value) => {
|
||||||
|
try {
|
||||||
|
const result = await apiCall('/custom-fields/values/upsert', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
customFieldId,
|
||||||
|
entityType,
|
||||||
|
entityId,
|
||||||
|
value
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la création/mise à jour de la valeur de champ personnalisé:', error)
|
||||||
|
return { success: false, error }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Supprimer une valeur de champ personnalisé
|
||||||
|
const deleteCustomFieldValue = async (id) => {
|
||||||
|
try {
|
||||||
|
const result = await apiCall(`/custom-fields/values/${id}`, {
|
||||||
|
method: 'DELETE'
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la suppression de la valeur de champ personnalisé:', error)
|
||||||
|
return { success: false, error }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
customFieldValues,
|
||||||
|
loading,
|
||||||
|
createCustomFieldValue,
|
||||||
|
getCustomFieldValuesByEntity,
|
||||||
|
updateCustomFieldValue,
|
||||||
|
upsertCustomFieldValue,
|
||||||
|
deleteCustomFieldValue
|
||||||
|
}
|
||||||
|
}
|
||||||
654
app/composables/useMachineTypes.js
Normal file
654
app/composables/useMachineTypes.js
Normal file
@@ -0,0 +1,654 @@
|
|||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
// Types de machines prédéfinis avec structure hiérarchique
|
||||||
|
const machineTypes = ref([
|
||||||
|
// Machines de production
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'Presse hydraulique',
|
||||||
|
category: 'Production',
|
||||||
|
description: 'Machine de formage par compression hydraulique',
|
||||||
|
maintenanceFrequency: 'Mensuelle',
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
name: 'Système hydraulique',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Pompe hydraulique',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Rotor' },
|
||||||
|
{ name: 'Stator' },
|
||||||
|
{ name: 'Joint d\'étanchéité' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Cylindre principal',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Piston' },
|
||||||
|
{ name: 'Tige' },
|
||||||
|
{ name: 'Joint de piston' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Soupapes de sécurité',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Soupape de surpression' },
|
||||||
|
{ name: 'Soupape de décharge' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Système mécanique',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Banc de machine',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Poutre supérieure' },
|
||||||
|
{ name: 'Poutre inférieure' },
|
||||||
|
{ name: 'Colonnes' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Système de guidage',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Rails de guidage' },
|
||||||
|
{ name: 'Patins' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
criticalParts: ['Pompe hydraulique', 'Cylindre principal', 'Soupapes de sécurité'],
|
||||||
|
specifications: {
|
||||||
|
force: '100-5000 tonnes',
|
||||||
|
course: '100-800 mm',
|
||||||
|
vitesse: '5-50 mm/s'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'Convoyeur à bande',
|
||||||
|
category: 'Production',
|
||||||
|
description: 'Système de transport continu de matériaux',
|
||||||
|
maintenanceFrequency: 'Hebdomadaire',
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
name: 'Système de transport',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Bande transporteuse',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Carcasse' },
|
||||||
|
{ name: 'Revêtement' },
|
||||||
|
{ name: 'Armature' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Rouleaux',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Rouleaux porteurs' },
|
||||||
|
{ name: 'Rouleaux de retour' },
|
||||||
|
{ name: 'Rouleaux d\'impact' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Système d\'entraînement',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Moteur d\'entraînement',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Rotor' },
|
||||||
|
{ name: 'Stator' },
|
||||||
|
{ name: 'Roulements' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Réducteur',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Engrenages' },
|
||||||
|
{ name: 'Arbre de sortie' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
criticalParts: ['Bande transporteuse', 'Rouleaux', 'Moteur d\'entraînement'],
|
||||||
|
specifications: {
|
||||||
|
longueur: '5-100 m',
|
||||||
|
largeur: '400-2000 mm',
|
||||||
|
vitesse: '0.5-3 m/s'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: 'Robot de soudage',
|
||||||
|
category: 'Production',
|
||||||
|
description: 'Robot industriel pour opérations de soudage automatisé',
|
||||||
|
maintenanceFrequency: 'Trimestrielle',
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
name: 'Bras robotique',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Base rotative',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Moteur de rotation' },
|
||||||
|
{ name: 'Réducteur' },
|
||||||
|
{ name: 'Capteur de position' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bras articulé',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Joint 1' },
|
||||||
|
{ name: 'Joint 2' },
|
||||||
|
{ name: 'Joint 3' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Système de soudage',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Torche de soudage',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Électrode' },
|
||||||
|
{ name: 'Gainage' },
|
||||||
|
{ name: 'Conduit de gaz' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Alimentation électrique',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Transformateur' },
|
||||||
|
{ name: 'Régulateur de courant' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
criticalParts: ['Bras robotique', 'Torche de soudage', 'Contrôleur'],
|
||||||
|
specifications: {
|
||||||
|
portée: '1.5-3 m',
|
||||||
|
charge: '5-200 kg',
|
||||||
|
précision: '±0.1 mm'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Machines de transformation
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: 'Tour CNC',
|
||||||
|
category: 'Transformation',
|
||||||
|
description: 'Machine-outil pour usinage de pièces cylindriques',
|
||||||
|
maintenanceFrequency: 'Mensuelle',
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
name: 'Banc de machine',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Banc principal',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Poutre' },
|
||||||
|
{ name: 'Guidages' },
|
||||||
|
{ name: 'Vis à billes' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Système de broche',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Broche principale',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Arbre de broche' },
|
||||||
|
{ name: 'Roulements' },
|
||||||
|
{ name: 'Moteur de broche' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Contre-pointe',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Pointe' },
|
||||||
|
{ name: 'Cylindre' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
criticalParts: ['Banc de machine', 'Broche', 'Contre-pointe'],
|
||||||
|
specifications: {
|
||||||
|
diamètre: '200-1000 mm',
|
||||||
|
longueur: '500-3000 mm',
|
||||||
|
puissance: '5-50 kW'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: 'Fraiseuse',
|
||||||
|
category: 'Transformation',
|
||||||
|
description: 'Machine-outil pour usinage par enlèvement de copeaux',
|
||||||
|
maintenanceFrequency: 'Mensuelle',
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
name: 'Table de travail',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Table X',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Guidages X' },
|
||||||
|
{ name: 'Vis à billes X' },
|
||||||
|
{ name: 'Moteur X' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Table Y',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Guidages Y' },
|
||||||
|
{ name: 'Vis à billes Y' },
|
||||||
|
{ name: 'Moteur Y' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Système de broche',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Broche verticale',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Arbre de broche' },
|
||||||
|
{ name: 'Roulements' },
|
||||||
|
{ name: 'Moteur de broche' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
criticalParts: ['Table de travail', 'Broche', 'Guidages'],
|
||||||
|
specifications: {
|
||||||
|
courseX: '400-2000 mm',
|
||||||
|
courseY: '300-1500 mm',
|
||||||
|
courseZ: '200-800 mm'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Machines de manutention
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: 'Pont roulant',
|
||||||
|
category: 'Manutention',
|
||||||
|
description: 'Système de levage et transport de charges lourdes',
|
||||||
|
maintenanceFrequency: 'Mensuelle',
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
name: 'Poutre principale',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Poutre de roulement',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Profilé principal' },
|
||||||
|
{ name: 'Rails de roulement' },
|
||||||
|
{ name: 'Renforts' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Système de palans',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Palans',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Moteur de levage' },
|
||||||
|
{ name: 'Treuil' },
|
||||||
|
{ name: 'Crochet' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Système de translation',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Moteur de translation' },
|
||||||
|
{ name: 'Roues de roulement' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
criticalParts: ['Poutre principale', 'Palans', 'Rails de guidage'],
|
||||||
|
specifications: {
|
||||||
|
capacité: '1-500 tonnes',
|
||||||
|
portée: '5-50 m',
|
||||||
|
hauteur: '3-20 m'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
name: 'Chariot élévateur',
|
||||||
|
category: 'Manutention',
|
||||||
|
description: 'Véhicule de manutention pour charges palettisées',
|
||||||
|
maintenanceFrequency: 'Hebdomadaire',
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
name: 'Système de levage',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Mast',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Mât extérieur' },
|
||||||
|
{ name: 'Mât intérieur' },
|
||||||
|
{ name: 'Cylindres de levage' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Fourches',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Fourche gauche' },
|
||||||
|
{ name: 'Fourche droite' },
|
||||||
|
{ name: 'Système de réglage' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Groupe motopropulseur',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Moteur',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Bloc moteur' },
|
||||||
|
{ name: 'Système d\'injection' },
|
||||||
|
{ name: 'Système de refroidissement' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Transmission',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Boîte de vitesses' },
|
||||||
|
{ name: 'Arbre de transmission' },
|
||||||
|
{ name: 'Pont arrière' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
criticalParts: ['Mast', 'Fourches', 'Moteur'],
|
||||||
|
specifications: {
|
||||||
|
capacité: '1-10 tonnes',
|
||||||
|
hauteur: '3-6 m',
|
||||||
|
type: 'Électrique/Diesel/Gaz'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Machines de traitement
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
name: 'Compresseur d\'air',
|
||||||
|
category: 'Traitement',
|
||||||
|
description: 'Générateur d\'air comprimé pour applications industrielles',
|
||||||
|
maintenanceFrequency: 'Hebdomadaire',
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
name: 'Système de compression',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Compresseur',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Pistons' },
|
||||||
|
{ name: 'Cylindres' },
|
||||||
|
{ name: 'Soupapes' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Réservoir',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Cuve' },
|
||||||
|
{ name: 'Soupape de sécurité' },
|
||||||
|
{ name: 'Manomètre' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Système de filtration',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Filtres',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Filtre à air' },
|
||||||
|
{ name: 'Filtre à huile' },
|
||||||
|
{ name: 'Séparateur d\'eau' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
criticalParts: ['Compresseur', 'Réservoir', 'Filtres'],
|
||||||
|
specifications: {
|
||||||
|
débit: '100-10000 L/min',
|
||||||
|
pression: '7-10 bar',
|
||||||
|
puissance: '5-500 kW'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 9,
|
||||||
|
name: 'Pompe hydraulique',
|
||||||
|
category: 'Traitement',
|
||||||
|
description: 'Pompe pour circuits hydrauliques industriels',
|
||||||
|
maintenanceFrequency: 'Mensuelle',
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
name: 'Système de pompage',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Rotor',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Ailettes' },
|
||||||
|
{ name: 'Arbre' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Stator',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Corps' },
|
||||||
|
{ name: 'Chambres' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Système d\'étanchéité',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Joint d\'étanchéité',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Joint radial' },
|
||||||
|
{ name: 'Joint axial' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
criticalParts: ['Rotor', 'Stator', 'Joint d\'étanchéité'],
|
||||||
|
specifications: {
|
||||||
|
débit: '10-500 L/min',
|
||||||
|
pression: '50-350 bar',
|
||||||
|
type: 'Piston/Palette/Engrenage'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Machines de contrôle
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
name: 'Capteur de température',
|
||||||
|
category: 'Contrôle',
|
||||||
|
description: 'Instrument de mesure de température industrielle',
|
||||||
|
maintenanceFrequency: 'Annuelle',
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
name: 'Système de mesure',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Élément sensible',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Fil de platine' },
|
||||||
|
{ name: 'Isolation' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Câblage',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Fils de connexion' },
|
||||||
|
{ name: 'Gaine de protection' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Système de transmission',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Transmetteur',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Circuit électronique' },
|
||||||
|
{ name: 'Affichage' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
criticalParts: ['Élément sensible', 'Câblage', 'Transmetteur'],
|
||||||
|
specifications: {
|
||||||
|
plage: '-50 à +500°C',
|
||||||
|
précision: '±0.5°C',
|
||||||
|
type: 'PT100/PT1000/Thermocouple'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 11,
|
||||||
|
name: 'Manomètre',
|
||||||
|
category: 'Contrôle',
|
||||||
|
description: 'Instrument de mesure de pression',
|
||||||
|
maintenanceFrequency: 'Annuelle',
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
name: 'Système de mesure',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Tube de Bourdon',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Tube' },
|
||||||
|
{ name: 'Extrémité fixe' },
|
||||||
|
{ name: 'Extrémité mobile' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Cadran',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Échelle' },
|
||||||
|
{ name: 'Aiguille' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Système de connexion',
|
||||||
|
subComponents: [
|
||||||
|
{
|
||||||
|
name: 'Joint',
|
||||||
|
subComponents: [
|
||||||
|
{ name: 'Joint d\'étanchéité' },
|
||||||
|
{ name: 'Filetage' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
criticalParts: ['Tube de Bourdon', 'Cadran', 'Joint'],
|
||||||
|
specifications: {
|
||||||
|
plage: '0-600 bar',
|
||||||
|
précision: '±1%',
|
||||||
|
type: 'Analogique/Numérique'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
// Catégories disponibles
|
||||||
|
const categories = ref([
|
||||||
|
'Production',
|
||||||
|
'Transformation',
|
||||||
|
'Manutention',
|
||||||
|
'Traitement',
|
||||||
|
'Contrôle'
|
||||||
|
])
|
||||||
|
|
||||||
|
export function useMachineTypes() {
|
||||||
|
const getTypes = () => machineTypes.value
|
||||||
|
|
||||||
|
const getTypeById = (id) => {
|
||||||
|
return machineTypes.value.find(type => type.id === id)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTypesByCategory = (category) => {
|
||||||
|
return machineTypes.value.filter(type => type.category === category)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCategories = () => categories.value
|
||||||
|
|
||||||
|
const addType = (newType) => {
|
||||||
|
const id = Math.max(...machineTypes.value.map(t => t.id)) + 1
|
||||||
|
machineTypes.value.push({
|
||||||
|
id,
|
||||||
|
...newType
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateType = (id, updatedType) => {
|
||||||
|
const index = machineTypes.value.findIndex(type => type.id === id)
|
||||||
|
if (index !== -1) {
|
||||||
|
machineTypes.value[index] = { ...machineTypes.value[index], ...updatedType }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteType = (id) => {
|
||||||
|
const index = machineTypes.value.findIndex(type => type.id === id)
|
||||||
|
if (index !== -1) {
|
||||||
|
machineTypes.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Méthodes pour la hiérarchie
|
||||||
|
const flattenComponents = (components, level = 0) => {
|
||||||
|
let flat = []
|
||||||
|
components.forEach(comp => {
|
||||||
|
flat.push({ ...comp, level })
|
||||||
|
if (comp.subComponents && comp.subComponents.length > 0) {
|
||||||
|
flat = flat.concat(flattenComponents(comp.subComponents, level + 1))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return flat
|
||||||
|
}
|
||||||
|
|
||||||
|
const getComponentHierarchy = (typeId) => {
|
||||||
|
const type = getTypeById(typeId)
|
||||||
|
if (!type || !type.components) return []
|
||||||
|
return flattenComponents(type.components)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
getTypes,
|
||||||
|
getTypeById,
|
||||||
|
getTypesByCategory,
|
||||||
|
getCategories,
|
||||||
|
addType,
|
||||||
|
updateType,
|
||||||
|
deleteType,
|
||||||
|
flattenComponents,
|
||||||
|
getComponentHierarchy
|
||||||
|
}
|
||||||
|
}
|
||||||
117
app/composables/useMachineTypesApi.js
Normal file
117
app/composables/useMachineTypesApi.js
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import { ref } from 'vue'
|
||||||
|
import { useToast } from './useToast'
|
||||||
|
import { useApi } from './useApi'
|
||||||
|
|
||||||
|
const machineTypes = ref([])
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
export function useMachineTypesApi() {
|
||||||
|
const { showSuccess, showError, showInfo } = useToast()
|
||||||
|
const { get, post, patch, delete: del } = useApi()
|
||||||
|
|
||||||
|
const loadMachineTypes = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await get('/types/machines')
|
||||||
|
if (result.success) {
|
||||||
|
machineTypes.value = result.data
|
||||||
|
showInfo(`Chargement de ${machineTypes.value.length} type(s) de machine réussi`)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors du chargement des types de machines:', error)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const createMachineType = async (typeData) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await post('/types/machines', typeData)
|
||||||
|
if (result.success) {
|
||||||
|
machineTypes.value.push(result.data)
|
||||||
|
showSuccess(`Type de machine "${typeData.name}" créé avec succès`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la création du type de machine:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateMachineType = async (id, typeData) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await patch(`/types/machines/${id}`, typeData)
|
||||||
|
if (result.success) {
|
||||||
|
const index = machineTypes.value.findIndex(type => type.id === id)
|
||||||
|
if (index !== -1) {
|
||||||
|
machineTypes.value[index] = result.data
|
||||||
|
}
|
||||||
|
showSuccess(`Type de machine "${typeData.name}" mis à jour avec succès`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la mise à jour du type de machine:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteMachineType = async (id) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await del(`/types/machines/${id}`)
|
||||||
|
if (result.success) {
|
||||||
|
const deletedType = machineTypes.value.find(type => type.id === id)
|
||||||
|
machineTypes.value = machineTypes.value.filter(type => type.id !== id)
|
||||||
|
showSuccess(`Type de machine "${deletedType?.name || 'inconnu'}" supprimé avec succès`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la suppression du type de machine:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMachineTypeById = async (id) => {
|
||||||
|
// D'abord chercher dans le cache local
|
||||||
|
const localType = machineTypes.value.find(type => type.id === id)
|
||||||
|
if (localType) {
|
||||||
|
return { success: true, data: localType }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si pas trouvé localement, récupérer depuis l'API
|
||||||
|
try {
|
||||||
|
const result = await get(`/types/machines/${id}`)
|
||||||
|
if (result.success) {
|
||||||
|
// Ajouter au cache local
|
||||||
|
machineTypes.value.push(result.data)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la récupération du type de machine:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMachineTypes = () => machineTypes.value
|
||||||
|
const isLoading = () => loading.value
|
||||||
|
|
||||||
|
return {
|
||||||
|
machineTypes,
|
||||||
|
loading,
|
||||||
|
loadMachineTypes,
|
||||||
|
createMachineType,
|
||||||
|
updateMachineType,
|
||||||
|
deleteMachineType,
|
||||||
|
getMachineTypeById,
|
||||||
|
getMachineTypes,
|
||||||
|
isLoading
|
||||||
|
}
|
||||||
|
}
|
||||||
123
app/composables/useMachines.js
Normal file
123
app/composables/useMachines.js
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
import { ref } from 'vue'
|
||||||
|
import { useToast } from './useToast'
|
||||||
|
import { useApi } from './useApi'
|
||||||
|
|
||||||
|
const machines = ref([])
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
export function useMachines() {
|
||||||
|
const { showSuccess, showError, showInfo } = useToast()
|
||||||
|
const { get, post, patch, delete: del } = useApi()
|
||||||
|
|
||||||
|
const loadMachines = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await get('/machines')
|
||||||
|
if (result.success) {
|
||||||
|
machines.value = result.data
|
||||||
|
showInfo(`Chargement de ${machines.value.length} machine(s) réussi`)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors du chargement des machines:', error)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const createMachine = async (machineData) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await post('/machines', machineData)
|
||||||
|
if (result.success) {
|
||||||
|
machines.value.push(result.data)
|
||||||
|
showSuccess(`Machine "${machineData.name}" créée avec succès`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la création de la machine:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const createMachineFromType = async (machineData, typeMachine) => {
|
||||||
|
// Créer la machine avec la structure héritée du type
|
||||||
|
const machineWithStructure = {
|
||||||
|
...machineData,
|
||||||
|
typeMachineId: typeMachine.id,
|
||||||
|
// La structure sera automatiquement héritée du type
|
||||||
|
// Les composants et pièces seront créés automatiquement
|
||||||
|
}
|
||||||
|
|
||||||
|
return await createMachine(machineWithStructure)
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateMachineData = async (id, machineData) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await patch(`/machines/${id}`, machineData)
|
||||||
|
if (result.success) {
|
||||||
|
const index = machines.value.findIndex(machine => machine.id === id)
|
||||||
|
if (index !== -1) {
|
||||||
|
machines.value[index] = result.data
|
||||||
|
}
|
||||||
|
showSuccess(`Machine "${machineData.name}" mise à jour avec succès`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la mise à jour de la machine:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteMachine = async (id) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await del(`/machines/${id}`)
|
||||||
|
if (result.success) {
|
||||||
|
const deletedMachine = machines.value.find(machine => machine.id === id)
|
||||||
|
machines.value = machines.value.filter(machine => machine.id !== id)
|
||||||
|
showSuccess(`Machine "${deletedMachine?.name || 'inconnu'}" supprimée avec succès`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la suppression de la machine:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMachineById = (id) => {
|
||||||
|
return machines.value.find(machine => machine.id === id)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMachinesBySite = (siteId) => {
|
||||||
|
return machines.value.filter(machine => machine.siteId === siteId)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMachinesByType = (typeMachineId) => {
|
||||||
|
return machines.value.filter(machine => machine.typeMachineId === typeMachineId)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMachines = () => machines.value
|
||||||
|
const isLoading = () => loading.value
|
||||||
|
|
||||||
|
return {
|
||||||
|
machines,
|
||||||
|
loading,
|
||||||
|
loadMachines,
|
||||||
|
createMachine,
|
||||||
|
createMachineFromType,
|
||||||
|
updateMachine: updateMachineData,
|
||||||
|
deleteMachine,
|
||||||
|
getMachineById,
|
||||||
|
getMachinesBySite,
|
||||||
|
getMachinesByType,
|
||||||
|
getMachines,
|
||||||
|
isLoading
|
||||||
|
}
|
||||||
|
}
|
||||||
134
app/composables/usePieces.js
Normal file
134
app/composables/usePieces.js
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import { ref } from 'vue'
|
||||||
|
import { useToast } from './useToast'
|
||||||
|
import { useApi } from './useApi'
|
||||||
|
|
||||||
|
const pieces = ref([])
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
export function usePieces() {
|
||||||
|
const { showSuccess, showError, showInfo } = useToast()
|
||||||
|
const { get, post, patch, delete: del } = useApi()
|
||||||
|
|
||||||
|
const loadPieces = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await get('/pieces')
|
||||||
|
if (result.success) {
|
||||||
|
pieces.value = result.data
|
||||||
|
showInfo(`Chargement de ${pieces.value.length} pièce(s) réussi`)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors du chargement des pièces:', error)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPiecesByMachine = async (machineId) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await get(`/pieces/machine/${machineId}`)
|
||||||
|
if (result.success) {
|
||||||
|
return { success: true, data: result.data }
|
||||||
|
}
|
||||||
|
return { success: false, error: result.error }
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors du chargement des pièces:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPiecesByComposant = async (composantId) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await get(`/pieces/composant/${composantId}`)
|
||||||
|
if (result.success) {
|
||||||
|
return { success: true, data: result.data }
|
||||||
|
}
|
||||||
|
return { success: false, error: result.error }
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors du chargement des pièces:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const createPiece = async (pieceData) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await post('/pieces', pieceData)
|
||||||
|
if (result.success) {
|
||||||
|
pieces.value.push(result.data)
|
||||||
|
showSuccess(`Pièce "${pieceData.name}" créée avec succès`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la création de la pièce:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatePieceData = async (id, pieceData) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await patch(`/pieces/${id}`, pieceData)
|
||||||
|
if (result.success) {
|
||||||
|
const index = pieces.value.findIndex(piece => piece.id === id)
|
||||||
|
if (index !== -1) {
|
||||||
|
pieces.value[index] = result.data
|
||||||
|
}
|
||||||
|
showSuccess(`Pièce "${pieceData.name}" mise à jour avec succès`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la mise à jour de la pièce:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deletePiece = async (id) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await del(`/pieces/${id}`)
|
||||||
|
if (result.success) {
|
||||||
|
const deletedPiece = pieces.value.find(piece => piece.id === id)
|
||||||
|
pieces.value = pieces.value.filter(piece => piece.id !== id)
|
||||||
|
showSuccess(`Pièce "${deletedPiece?.name || 'inconnu'}" supprimée avec succès`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la suppression de la pièce:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPieceById = (id) => {
|
||||||
|
return pieces.value.find(piece => piece.id === id)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPieces = () => pieces.value
|
||||||
|
const isLoading = () => loading.value
|
||||||
|
|
||||||
|
return {
|
||||||
|
pieces,
|
||||||
|
loading,
|
||||||
|
loadPieces,
|
||||||
|
getPiecesByMachine,
|
||||||
|
getPiecesByComposant,
|
||||||
|
createPiece,
|
||||||
|
updatePiece: updatePieceData,
|
||||||
|
deletePiece,
|
||||||
|
getPieceById,
|
||||||
|
getPieces,
|
||||||
|
isLoading
|
||||||
|
}
|
||||||
|
}
|
||||||
100
app/composables/useSites.js
Normal file
100
app/composables/useSites.js
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
import { ref } from 'vue'
|
||||||
|
import { useToast } from './useToast'
|
||||||
|
import { useApi } from './useApi'
|
||||||
|
|
||||||
|
const sites = ref([])
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
export function useSites() {
|
||||||
|
const { showSuccess, showInfo } = useToast()
|
||||||
|
const { get, post, patch, delete: del } = useApi()
|
||||||
|
|
||||||
|
const loadSites = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await get('/sites')
|
||||||
|
if (result.success) {
|
||||||
|
sites.value = result.data
|
||||||
|
showInfo(`Chargement de ${sites.value.length} site(s) réussi`)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors du chargement des sites:', error)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const createSite = async (siteData) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await post('/sites', siteData)
|
||||||
|
if (result.success) {
|
||||||
|
sites.value.push(result.data)
|
||||||
|
showSuccess(`Site "${siteData.name}" créé avec succès`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la création du site:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateSite = async (id, siteData) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await patch(`/sites/${id}`, siteData)
|
||||||
|
if (result.success) {
|
||||||
|
const index = sites.value.findIndex(site => site.id === id)
|
||||||
|
if (index !== -1) {
|
||||||
|
sites.value[index] = result.data
|
||||||
|
}
|
||||||
|
showSuccess(`Site "${siteData.name}" mis à jour avec succès`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la mise à jour du site:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteSite = async (id) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const result = await del(`/sites/${id}`)
|
||||||
|
if (result.success) {
|
||||||
|
const deletedSite = sites.value.find(site => site.id === id)
|
||||||
|
sites.value = sites.value.filter(site => site.id !== id)
|
||||||
|
showSuccess(`Site "${deletedSite?.name || 'inconnu'}" supprimé avec succès`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la suppression du site:', error)
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSiteById = (id) => {
|
||||||
|
return sites.value.find(site => site.id === id)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSites = () => sites.value
|
||||||
|
const isLoading = () => loading.value
|
||||||
|
|
||||||
|
return {
|
||||||
|
sites,
|
||||||
|
loading,
|
||||||
|
loadSites,
|
||||||
|
createSite,
|
||||||
|
updateSite,
|
||||||
|
deleteSite,
|
||||||
|
getSiteById,
|
||||||
|
getSites,
|
||||||
|
isLoading
|
||||||
|
}
|
||||||
|
}
|
||||||
66
app/composables/useToast.js
Normal file
66
app/composables/useToast.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const toasts = ref([])
|
||||||
|
let nextId = 1
|
||||||
|
|
||||||
|
export function useToast() {
|
||||||
|
const showToast = (message, type = 'info', duration = 5000) => {
|
||||||
|
const id = nextId++
|
||||||
|
const toast = {
|
||||||
|
id,
|
||||||
|
message,
|
||||||
|
type,
|
||||||
|
visible: true
|
||||||
|
}
|
||||||
|
|
||||||
|
toasts.value.push(toast)
|
||||||
|
|
||||||
|
// Auto-remove after duration
|
||||||
|
setTimeout(() => {
|
||||||
|
removeToast(id)
|
||||||
|
}, duration)
|
||||||
|
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
const showSuccess = (message, duration = 5000) => {
|
||||||
|
return showToast(message, 'success', duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
const showError = (message, duration = 7000) => {
|
||||||
|
return showToast(message, 'error', duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
const showWarning = (message, duration = 6000) => {
|
||||||
|
return showToast(message, 'warning', duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
const showInfo = (message, duration = 5000) => {
|
||||||
|
return showToast(message, 'info', duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeToast = (id) => {
|
||||||
|
const index = toasts.value.findIndex(toast => toast.id === id)
|
||||||
|
if (index !== -1) {
|
||||||
|
toasts.value[index].visible = false
|
||||||
|
setTimeout(() => {
|
||||||
|
toasts.value.splice(index, 1)
|
||||||
|
}, 300) // Animation duration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearAll = () => {
|
||||||
|
toasts.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
toasts,
|
||||||
|
showToast,
|
||||||
|
showSuccess,
|
||||||
|
showError,
|
||||||
|
showWarning,
|
||||||
|
showInfo,
|
||||||
|
removeToast,
|
||||||
|
clearAll
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user