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

@@ -12,14 +12,14 @@
class="w-4 h-4 text-purple-500"
aria-hidden="true"
/>
<input
<input
v-if="isEditMode"
:id="`piece-name-${piece.id}`"
v-model="pieceData.name"
type="text"
v-model="pieceData.name"
type="text"
class="font-semibold text-lg input input-sm input-bordered"
@blur="updatePiece"
/>
>
<div v-else class="font-semibold text-lg input input-sm input-bordered bg-base-200">
{{ pieceData.name }}
</div>
@@ -45,19 +45,19 @@
<div class="space-y-2 text-sm">
<div>
<span class="font-medium">Référence:</span>
<input
<span class="font-medium">Référence:</span>
<input
v-if="isEditMode"
:id="`piece-reference-${piece.id}`"
v-model="pieceData.reference"
type="text"
v-model="pieceData.reference"
type="text"
class="input input-sm input-bordered ml-2"
@blur="updatePiece"
/>
>
<span v-else class="ml-2">{{ pieceData.reference || 'Non définie' }}</span>
</div>
<div>
<span class="font-medium">Constructeur:</span>
<span class="font-medium">Constructeur:</span>
<span v-if="!isEditMode" class="ml-2">
<span class="font-medium">{{ piece.constructeur?.name || 'Non défini' }}</span>
<span v-if="piece.constructeur" class="block text-xs text-gray-500">
@@ -68,20 +68,20 @@
v-else
class="w-full"
:model-value="piece.constructeurId || piece.constructeur?.id || null"
@update:modelValue="handleConstructeurChange"
@update:model-value="handleConstructeurChange"
/>
</div>
<div>
<span class="font-medium">Prix:</span>
<input
<span class="font-medium">Prix:</span>
<input
v-if="isEditMode"
:id="`piece-prix-${piece.id}`"
v-model="pieceData.prix"
type="number"
v-model="pieceData.prix"
type="number"
step="0.01"
class="input input-sm input-bordered ml-2"
@blur="updatePiece"
/>
>
<span v-else class="ml-2">{{ pieceData.prix ? `${pieceData.prix}` : 'Non défini' }}</span>
</div>
</div>
@@ -90,7 +90,7 @@
v-if="isEditMode && piece.typeMachinePieceRequirement"
class="mt-3"
>
<label class="label">
<label class="label">
<span class="label-text text-sm font-medium">Modèle de pièce</span>
<span class="label-text-alt text-xs">
{{ piece.typeMachinePieceRequirement.label || piece.typeMachinePieceRequirement.typePiece?.name || 'Groupe' }}
@@ -101,7 +101,9 @@
class="select select-bordered select-sm w-full"
@change="assignPieceModel($event.target.value)"
>
<option value="">Définir manuellement</option>
<option value="">
Définir manuellement
</option>
<option
v-for="model in pieceModelOptions"
:key="model.id"
@@ -114,10 +116,12 @@
<!-- Champs personnalisés de la pièce -->
<div v-if="piece.customFieldValues && piece.customFieldValues.length > 0" class="mt-4 pt-4 border-t border-gray-200">
<h5 class="text-sm font-medium text-gray-700 mb-3">Champs personnalisés</h5>
<h5 class="text-sm font-medium text-gray-700 mb-3">
Champs personnalisés
</h5>
<div class="space-y-3">
<div
v-for="fieldValue in piece.customFieldValues"
<div
v-for="fieldValue in piece.customFieldValues"
:key="fieldValue.id"
class="form-control"
>
@@ -125,75 +129,77 @@
<span class="label-text text-sm">{{ fieldValue.customField.name }}</span>
<span v-if="fieldValue.customField.required" class="label-text-alt text-error">*</span>
</label>
<!-- Mode édition -->
<template v-if="isEditMode">
<!-- Champ de type TEXT -->
<input
<input
v-if="fieldValue.customField.type === 'text'"
:value="fieldValue.value"
@input="setCustomFieldValue(fieldValue.id, $event.target.value)"
type="text"
class="input input-bordered input-sm"
:required="fieldValue.customField.required"
@input="setCustomFieldValue(fieldValue.id, $event.target.value)"
@blur="updateCustomFieldValue(fieldValue.id)"
/>
>
<!-- Champ de type NUMBER -->
<input
<input
v-else-if="fieldValue.customField.type === 'number'"
:value="fieldValue.value"
@input="setCustomFieldValue(fieldValue.id, $event.target.value)"
type="number"
class="input input-bordered input-sm"
:required="fieldValue.customField.required"
@blur="updateCustomFieldValue(fieldValue.id)"
/>
<!-- Champ de type SELECT -->
<select
v-else-if="fieldValue.customField.type === 'select'"
:value="fieldValue.value"
@change="setCustomFieldValue(fieldValue.id, $event.target.value)"
class="select select-bordered select-sm"
:required="fieldValue.customField.required"
@input="setCustomFieldValue(fieldValue.id, $event.target.value)"
@blur="updateCustomFieldValue(fieldValue.id)"
>
<option value="">Sélectionner...</option>
<option
v-for="option in fieldValue.customField.options"
:key="option"
<!-- Champ de type SELECT -->
<select
v-else-if="fieldValue.customField.type === 'select'"
:value="fieldValue.value"
class="select select-bordered select-sm"
:required="fieldValue.customField.required"
@change="setCustomFieldValue(fieldValue.id, $event.target.value)"
@blur="updateCustomFieldValue(fieldValue.id)"
>
<option value="">
Sélectionner...
</option>
<option
v-for="option in fieldValue.customField.options"
:key="option"
:value="option"
>
{{ option }}
</option>
</select>
<!-- Champ de type BOOLEAN -->
<div v-else-if="fieldValue.customField.type === 'boolean'" class="flex items-center gap-2">
<input
<input
:value="fieldValue.value"
@change="setCustomFieldValue(fieldValue.id, $event.target.checked ? 'true' : 'false')"
type="checkbox"
class="checkbox checkbox-sm"
:checked="fieldValue.value === 'true'"
@change="setCustomFieldValue(fieldValue.id, $event.target.checked ? 'true' : 'false')"
@blur="updateCustomFieldValue(fieldValue.id)"
/>
>
<span class="text-sm">{{ fieldValue.value === 'true' ? 'Oui' : 'Non' }}</span>
</div>
<!-- Champ de type DATE -->
<input
<input
v-else-if="fieldValue.customField.type === 'date'"
:value="fieldValue.value"
@input="setCustomFieldValue(fieldValue.id, $event.target.value)"
type="date"
class="input input-bordered input-sm"
:required="fieldValue.customField.required"
@input="setCustomFieldValue(fieldValue.id, $event.target.value)"
@blur="updateCustomFieldValue(fieldValue.id)"
/>
>
</template>
<!-- Mode lecture seule -->
<template v-else>
<div class="input input-bordered input-sm bg-base-200">
@@ -206,13 +212,17 @@
<div class="mt-4 pt-4 border-t border-gray-200 space-y-3">
<div class="flex items-center justify-between">
<h5 class="text-sm font-medium text-gray-700">Documents</h5>
<h5 class="text-sm font-medium text-gray-700">
Documents
</h5>
<span v-if="isEditMode && selectedFiles.length" class="badge badge-outline">
{{ selectedFiles.length }} fichier{{ selectedFiles.length > 1 ? 's' : '' }} sélectionné{{ selectedFiles.length > 1 ? 's' : '' }}
</span>
</div>
<p v-if="loadingDocuments" class="text-xs text-gray-500">Chargement des documents...</p>
<p v-if="loadingDocuments" class="text-xs text-gray-500">
Chargement des documents...
</p>
<DocumentUpload
v-if="isEditMode"
@@ -237,7 +247,9 @@
/>
</span>
<div>
<div class="font-medium">{{ document.name }}</div>
<div class="font-medium">
{{ document.name }}
</div>
<div class="text-xs text-gray-500">
{{ document.mimeType || 'Inconnu' }} {{ formatSize(document.size) }}
</div>
@@ -268,13 +280,16 @@
</div>
</div>
</div>
<p v-else-if="!loadingDocuments" class="text-xs text-gray-500">Aucun document lié à cette pièce.</p>
<p v-else-if="!loadingDocuments" class="text-xs text-gray-500">
Aucun document lié à cette pièce.
</p>
</div>
</div>
</template>
<script setup>
import { reactive, onMounted, watch, ref, computed } from 'vue'
import ConstructeurSelect from './ConstructeurSelect.vue'
import { useCustomFields } from '~/composables/useCustomFields'
import { useToast } from '~/composables/useToast'
import { useDocuments } from '~/composables/useDocuments'
@@ -282,22 +297,21 @@ import { getFileIcon } from '~/utils/fileIcons'
import { canPreviewDocument } from '~/utils/documentPreview'
import DocumentUpload from '~/components/DocumentUpload.vue'
import DocumentPreviewModal from '~/components/DocumentPreviewModal.vue'
import ConstructeurSelect from './ConstructeurSelect.vue'
import IconLucidePackage from '~icons/lucide/package'
const props = defineProps({
piece: {
type: Object,
required: true,
required: true
},
isEditMode: {
type: Boolean,
default: false,
default: false
},
pieceModelOptions: {
type: Array,
default: () => [],
},
default: () => []
}
})
const emit = defineEmits(['update', 'edit', 'custom-field-update', 'assign-model'])
@@ -314,7 +328,7 @@ const uploadingDocuments = ref(false)
const loadingDocuments = ref(false)
const documentsLoaded = ref(!!(props.piece.documents && props.piece.documents.length))
const pieceDocuments = computed(() => props.piece.documents || [])
const documentIcon = (doc) => getFileIcon({ name: doc.filename || doc.name, mime: doc.mimeType })
const documentIcon = doc => getFileIcon({ name: doc.filename || doc.name, mime: doc.mimeType })
const previewDocument = ref(null)
const previewVisible = ref(false)
const selectedPieceModelId = computed(() => props.piece.pieceModelId || props.piece.pieceModel?.id || '')
@@ -328,7 +342,7 @@ const handleConstructeurChange = (value) => {
const { uploadDocuments, deleteDocument, loadDocumentsByPiece } = useDocuments()
const refreshDocuments = async () => {
if (!props.piece?.id) return
if (!props.piece?.id) { return }
loadingDocuments.value = true
try {
const result = await loadDocumentsByPiece(props.piece.id, { updateStore: false })
@@ -342,7 +356,7 @@ const refreshDocuments = async () => {
}
const handleFilesAdded = async (files) => {
if (!files.length || !props.piece?.id) return
if (!files.length || !props.piece?.id) { return }
uploadingDocuments.value = true
try {
const result = await uploadDocuments(
@@ -365,7 +379,7 @@ const handleFilesAdded = async (files) => {
}
const removeDocument = async (documentId) => {
if (!documentId) return
if (!documentId) { return }
const result = await deleteDocument(documentId, { updateStore: false })
if (result.success) {
props.piece.documents = (props.piece.documents || []).filter(doc => doc.id !== documentId)
@@ -373,7 +387,7 @@ const removeDocument = async (documentId) => {
}
const downloadDocument = (doc) => {
if (!doc?.path) return
if (!doc?.path) { return }
if (doc.path.startsWith('data:')) {
const link = document.createElement('a')
@@ -387,7 +401,7 @@ const downloadDocument = (doc) => {
}
const openPreview = (doc) => {
if (!canPreviewDocument(doc)) return
if (!canPreviewDocument(doc)) { return }
previewDocument.value = doc
previewVisible.value = true
}
@@ -398,8 +412,8 @@ const closePreview = () => {
}
const formatSize = (size) => {
if (size === undefined || size === null) return '—'
if (size === 0) return '0 B'
if (size === undefined || size === null) { return '—' }
if (size === 0) { return '0 B' }
const units = ['B', 'KB', 'MB', 'GB']
const index = Math.min(units.length - 1, Math.floor(Math.log(size) / Math.log(1024)))
const formatted = size / Math.pow(1024, index)
@@ -413,7 +427,6 @@ watch(
}
)
// Méthodes pour gérer les champs personnalisés
const setCustomFieldValue = (fieldValueId, value) => {
const fieldValue = props.piece.customFieldValues?.find(fv => fv.id === fieldValueId)
@@ -428,7 +441,7 @@ const updatePiece = () => {
...props.piece,
...pieceData,
prix: prixValue && prixValue !== '' ? parseFloat(prixValue) : null,
constructeurId: props.piece.constructeurId || null,
constructeurId: props.piece.constructeurId || null
})
}
@@ -443,7 +456,7 @@ const assignPieceModel = (value) => {
pieceId: props.piece.id,
pieceModelId: value || null,
previousModelId,
previousModel,
previousModel
})
}
@@ -452,7 +465,7 @@ const updateCustomFieldValue = async (fieldValueId) => {
if (fieldValue) {
const { updateCustomFieldValue } = useCustomFields()
const { showSuccess, showError } = useToast()
const result = await updateCustomFieldValue(fieldValueId, { value: fieldValue.value })
if (result.success) {
showSuccess(`Champ "${fieldValue.customField.name}" mis à jour avec succès`)
@@ -473,7 +486,7 @@ watch(
pieceData.name = props.piece.name || ''
pieceData.reference = props.piece.reference || ''
pieceData.prix = props.piece.prix || ''
},
}
)
onMounted(() => {
@@ -481,7 +494,7 @@ onMounted(() => {
pieceData.name = props.piece.name || ''
pieceData.reference = props.piece.reference || ''
pieceData.prix = props.piece.prix || ''
// Debug: vérifier si les champs personnalisés sont présents
console.log('PieceItem - piece:', props.piece)
console.log('PieceItem - customFieldValues:', props.piece.customFieldValues)
@@ -490,4 +503,4 @@ onMounted(() => {
refreshDocuments()
}
})
</script>
</script>