feat(frontend): replace inline icons with lucide components
This commit is contained in:
@@ -17,9 +17,7 @@
|
||||
:aria-expanded="!isCollapsed"
|
||||
:title="isCollapsed ? 'Déplier les détails du composant' : 'Replier les détails du composant'"
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
<IconLucideChevronRight class="w-5 h-5 transition-transform" aria-hidden="true" />
|
||||
<span class="sr-only">{{ isCollapsed ? 'Déplier' : 'Replier' }} le composant</span>
|
||||
</button>
|
||||
<div class="flex-1">
|
||||
@@ -195,7 +193,11 @@
|
||||
>
|
||||
<div class="flex items-center gap-3 text-sm">
|
||||
<span class="text-xl" :class="documentIcon(document).colorClass">
|
||||
{{ documentIcon(document).icon }}
|
||||
<component
|
||||
:is="documentIcon(document).component"
|
||||
class="h-6 w-6"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</span>
|
||||
<div>
|
||||
<div class="font-medium">{{ document.name }}</div>
|
||||
@@ -277,6 +279,7 @@ import { useDocuments } from '~/composables/useDocuments'
|
||||
import { getFileIcon } from '~/utils/fileIcons'
|
||||
import { canPreviewDocument } from '~/utils/documentPreview'
|
||||
import DocumentPreviewModal from '~/components/DocumentPreviewModal.vue'
|
||||
import IconLucideChevronRight from '~icons/lucide/chevron-right'
|
||||
|
||||
const props = defineProps({
|
||||
component: {
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
class="absolute right-2 top-1/2 -translate-y-1/2 btn btn-ghost btn-xs"
|
||||
@click="ensureOptionsLoaded(true)"
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16l4-4 4 4m0-8l-4 4-4-4" />
|
||||
</svg>
|
||||
<IconLucideChevronsUpDown class="w-4 h-4" aria-hidden="true" />
|
||||
</button>
|
||||
<div
|
||||
v-if="openDropdown"
|
||||
@@ -90,6 +88,7 @@
|
||||
<script setup>
|
||||
import { ref, watch, computed, onMounted, onBeforeUnmount } from 'vue'
|
||||
import { useConstructeurs } from '~/composables/useConstructeurs'
|
||||
import IconLucideChevronsUpDown from '~icons/lucide/chevrons-up-down'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
@drop.prevent="onDrop"
|
||||
>
|
||||
<div class="flex flex-col items-center gap-3 text-center">
|
||||
<svg class="w-10 h-10 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 00-.88 7.912L6 24h12a4 4 0 00.88-7.912L18 16H7zm5-14a4 4 0 014 4v4h1.586a1 1 0 01.707 1.707l-5.586 5.586a1 1 0 01-1.414 0L7.707 11.707A1 1 0 018.414 10H10V6a4 4 0 014-4z" />
|
||||
</svg>
|
||||
<IconLucideCloudUpload class="w-10 h-10 text-primary" aria-hidden="true" />
|
||||
|
||||
<div>
|
||||
<h3 class="font-semibold">{{ title }}</h3>
|
||||
@@ -35,7 +33,12 @@
|
||||
<ul v-if="selectedFiles.length" class="mt-4 w-full space-y-2 text-left">
|
||||
<li v-for="file in selectedFiles" :key="file.name" class="flex items-center justify-between text-sm">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="text-xl" :class="getIcon(file).colorClass">{{ getIcon(file).icon }}</span>
|
||||
<component
|
||||
:is="getIcon(file).component"
|
||||
class="h-6 w-6"
|
||||
:class="getIcon(file).colorClass"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<div class="flex flex-col">
|
||||
<span class="font-medium">{{ file.name }}</span>
|
||||
<span class="text-xs text-gray-500">{{ formatSize(file.size) }} • {{ file.type || 'Type inconnu' }}</span>
|
||||
@@ -54,6 +57,7 @@
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useToast } from '~/composables/useToast'
|
||||
import { getFileIcon } from '~/utils/fileIcons'
|
||||
import IconLucideCloudUpload from '~icons/lucide/cloud-upload'
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
|
||||
@@ -8,9 +8,10 @@
|
||||
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<div class="flex items-center gap-2">
|
||||
<svg class="w-4 h-4 text-purple-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"></path>
|
||||
</svg>
|
||||
<IconLucidePackage
|
||||
class="w-4 h-4 text-purple-500"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<input
|
||||
v-if="isEditMode"
|
||||
:id="`piece-name-${piece.id}`"
|
||||
@@ -201,7 +202,11 @@
|
||||
>
|
||||
<div class="flex items-center gap-3 text-sm">
|
||||
<span class="text-xl" :class="documentIcon(document).colorClass">
|
||||
{{ documentIcon(document).icon }}
|
||||
<component
|
||||
:is="documentIcon(document).component"
|
||||
class="h-6 w-6"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</span>
|
||||
<div>
|
||||
<div class="font-medium">{{ document.name }}</div>
|
||||
@@ -250,6 +255,7 @@ 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: {
|
||||
|
||||
@@ -17,18 +17,26 @@
|
||||
<div class="flex items-center gap-2">
|
||||
<!-- Icon -->
|
||||
<div class="flex-shrink-0">
|
||||
<svg v-if="toast.type === 'success'" class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
|
||||
</svg>
|
||||
<svg v-else-if="toast.type === 'error'" class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
||||
</svg>
|
||||
<svg v-else-if="toast.type === 'warning'" class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"></path>
|
||||
</svg>
|
||||
<svg v-else class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
<IconLucideCheck
|
||||
v-if="toast.type === 'success'"
|
||||
class="w-5 h-5"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<IconLucideX
|
||||
v-else-if="toast.type === 'error'"
|
||||
class="w-5 h-5"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<IconLucideAlertTriangle
|
||||
v-else-if="toast.type === 'warning'"
|
||||
class="w-5 h-5"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<IconLucideInfo
|
||||
v-else
|
||||
class="w-5 h-5"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Message -->
|
||||
@@ -41,9 +49,7 @@
|
||||
@click="removeToast(toast.id)"
|
||||
class="btn btn-ghost btn-xs"
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
||||
</svg>
|
||||
<IconLucideX class="w-4 h-4" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -54,6 +60,10 @@
|
||||
|
||||
<script setup>
|
||||
import { useToast } from '~/composables/useToast'
|
||||
import IconLucideCheck from '~icons/lucide/check'
|
||||
import IconLucideX from '~icons/lucide/x'
|
||||
import IconLucideAlertTriangle from '~icons/lucide/alert-triangle'
|
||||
import IconLucideInfo from '~icons/lucide/info'
|
||||
|
||||
const { toasts, removeToast } = useToast()
|
||||
|
||||
@@ -92,4 +102,4 @@ const getToastClasses = (type) => {
|
||||
.toast-move {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -8,19 +8,13 @@
|
||||
@click="toggleComponent"
|
||||
title="Plier / déplier le composant"
|
||||
>
|
||||
<svg
|
||||
class="w-4 h-4 transition-transform duration-200"
|
||||
<IconLucideChevronRight
|
||||
class="w-4 h-4 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': expanded }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
<svg class="w-5 h-5 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path>
|
||||
</svg>
|
||||
<IconLucideCpu class="w-5 h-5 text-blue-500" aria-hidden="true" />
|
||||
<h4 class="text-lg font-medium">{{ component.name }}</h4>
|
||||
<span v-if="!expanded && component.reference" class="text-xs text-gray-500">(Ref: {{ component.reference }})</span>
|
||||
</div>
|
||||
@@ -50,15 +44,11 @@
|
||||
class="btn btn-ghost btn-xs p-1"
|
||||
@click="toggleSection('customFields')"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
<IconLucideChevronRight
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': expandedSections.customFields }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="expandedSections.customFields" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2">
|
||||
@@ -79,15 +69,11 @@
|
||||
class="btn btn-ghost btn-xs p-1"
|
||||
@click="toggleSection('pieces')"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
<IconLucideChevronRight
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': expandedSections.pieces }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="expandedSections.pieces" class="space-y-2">
|
||||
@@ -103,19 +89,13 @@
|
||||
class="btn btn-ghost btn-xs p-1"
|
||||
@click="togglePieceDetails(pieceIndex)"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
<IconLucideChevronRight
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': isPieceExpanded(pieceIndex) }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
<svg class="w-4 h-4 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"></path>
|
||||
</svg>
|
||||
<IconLucidePackage class="w-4 h-4 text-red-500" aria-hidden="true" />
|
||||
<span class="font-medium">{{ piece.name }}</span>
|
||||
<span v-if="!isPieceExpanded(pieceIndex) && piece.reference" class="text-xs text-gray-500">(Ref: {{ piece.reference }})</span>
|
||||
</div>
|
||||
@@ -142,18 +122,14 @@
|
||||
<span class="text-xs font-medium text-gray-600">Champs personnalisés</span>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-ghost btn-xs p-1"
|
||||
class="btn btn-ghost btn-xs p-1"
|
||||
@click="togglePieceCustomFields(pieceIndex)"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
<IconLucideChevronRight
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': isPieceCustomFieldSectionExpanded(pieceIndex) }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="isPieceCustomFieldSectionExpanded(pieceIndex)" class="grid grid-cols-1 md:grid-cols-2 gap-1">
|
||||
@@ -178,15 +154,11 @@
|
||||
class="btn btn-ghost btn-xs p-1"
|
||||
@click="toggleSection('subComponents')"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
<IconLucideChevronRight
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': expandedSections.subComponents }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="expandedSections.subComponents" class="space-y-3">
|
||||
@@ -196,25 +168,19 @@
|
||||
class="border border-gray-200 rounded p-3 bg-gray-50"
|
||||
>
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-ghost btn-xs p-1"
|
||||
@click="toggleSubComponentDetails(subIndex)"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': isSubComponentExpanded(subIndex) }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<svg class="w-4 h-4 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
<div class="flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-ghost btn-xs p-1"
|
||||
@click="toggleSubComponentDetails(subIndex)"
|
||||
>
|
||||
<IconLucideChevronRight
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': isSubComponentExpanded(subIndex) }"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
<IconLucideCheckCircle2 class="w-4 h-4 text-green-500" aria-hidden="true" />
|
||||
<span class="font-medium">{{ subComponent.name }}</span>
|
||||
<span v-if="!isSubComponentExpanded(subIndex) && subComponent.reference" class="text-xs text-gray-500">(Ref: {{ subComponent.reference }})</span>
|
||||
</div>
|
||||
@@ -244,15 +210,11 @@
|
||||
class="btn btn-ghost btn-xs p-1"
|
||||
@click="toggleSubComponentCustomFieldSection(subIndex)"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
<IconLucideChevronRight
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': isSubComponentCustomFieldSectionExpanded(subIndex) }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="isSubComponentCustomFieldSectionExpanded(subIndex)" class="grid grid-cols-1 md:grid-cols-2 gap-1">
|
||||
@@ -273,15 +235,11 @@
|
||||
class="btn btn-ghost btn-xs p-1"
|
||||
@click="toggleSubComponentPieceSection(subIndex)"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
<IconLucideChevronRight
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': isSubComponentPieceSectionExpanded(subIndex) }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="isSubComponentPieceSectionExpanded(subIndex)" class="space-y-1">
|
||||
@@ -297,19 +255,13 @@
|
||||
class="btn btn-ghost btn-xs p-1"
|
||||
@click="toggleSubPieceDetails(subIndex, pieceIndex)"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
<IconLucideChevronRight
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': isSubPieceExpanded(subIndex, pieceIndex) }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
<svg class="w-3 h-3 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"></path>
|
||||
</svg>
|
||||
<IconLucidePackage class="w-3 h-3 text-red-500" aria-hidden="true" />
|
||||
<span class="text-xs font-medium">{{ piece.name }}</span>
|
||||
<span v-if="!isSubPieceExpanded(subIndex, pieceIndex) && piece.reference" class="text-[10px] text-gray-500">(Ref: {{ piece.reference }})</span>
|
||||
</div>
|
||||
@@ -339,15 +291,11 @@
|
||||
class="btn btn-ghost btn-xs p-1"
|
||||
@click="toggleSubPieceCustomFields(subIndex, pieceIndex)"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
<IconLucideChevronRight
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': isSubPieceCustomFieldSectionExpanded(subIndex, pieceIndex) }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="isSubPieceCustomFieldSectionExpanded(subIndex, pieceIndex)" class="grid grid-cols-1 md:grid-cols-2 gap-1">
|
||||
@@ -373,6 +321,10 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, watch, onMounted } from 'vue'
|
||||
import IconLucideChevronRight from '~icons/lucide/chevron-right'
|
||||
import IconLucideCpu from '~icons/lucide/cpu'
|
||||
import IconLucidePackage from '~icons/lucide/package'
|
||||
import IconLucideCheckCircle2 from '~icons/lucide/check-circle-2'
|
||||
|
||||
const props = defineProps({
|
||||
component: {
|
||||
|
||||
@@ -6,18 +6,12 @@
|
||||
Réinitialiser
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary" :disabled="saving">
|
||||
<svg
|
||||
<IconLucideRefreshCw
|
||||
v-if="saving"
|
||||
class="w-5 h-5 mr-2 animate-spin"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
|
||||
</svg>
|
||||
<svg v-else class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<IconLucideCheck v-else class="w-5 h-5 mr-2" aria-hidden="true" />
|
||||
{{ saving ? 'Sauvegarde...' : 'Sauvegarder les modifications' }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -26,6 +20,9 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import IconLucideRefreshCw from '~icons/lucide/refresh-cw'
|
||||
import IconLucideCheck from '~icons/lucide/check'
|
||||
|
||||
defineProps({
|
||||
saving: {
|
||||
type: Boolean,
|
||||
|
||||
@@ -8,15 +8,11 @@
|
||||
class="btn btn-ghost btn-sm p-1"
|
||||
@click="toggleSection"
|
||||
>
|
||||
<svg
|
||||
<IconLucideChevronRight
|
||||
class="w-4 h-4 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': expanded }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
<h3 class="card-title text-lg">Composants</h3>
|
||||
<span class="badge badge-accent">{{ components.length }}</span>
|
||||
@@ -37,19 +33,13 @@
|
||||
@click="toggleComponent(index)"
|
||||
title="Plier / déplier le composant"
|
||||
>
|
||||
<svg
|
||||
<IconLucideChevronRight
|
||||
class="w-4 h-4 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': isComponentExpanded(index) }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
<svg class="w-4 h-4 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z"></path>
|
||||
</svg>
|
||||
<IconLucideSettings2 class="w-4 h-4 text-green-500" aria-hidden="true" />
|
||||
<h5 class="text-sm font-medium">Composant {{ index + 1 }}</h5>
|
||||
<span v-if="!isComponentExpanded(index)" class="text-xs text-gray-500 truncate max-w-[160px]">
|
||||
{{ component.name || 'Sans nom' }}
|
||||
@@ -61,9 +51,7 @@
|
||||
class="btn btn-square btn-error btn-sm"
|
||||
title="Supprimer ce composant"
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
||||
</svg>
|
||||
<IconLucideX class="w-4 h-4" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -140,18 +128,14 @@
|
||||
|
||||
<div class="flex justify-end">
|
||||
<button type="button" @click="addComponent" class="btn btn-primary btn-sm">
|
||||
<svg class="w-4 h-4 mr-2" 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"></path>
|
||||
</svg>
|
||||
<IconLucidePlus class="w-4 h-4 mr-2" aria-hidden="true" />
|
||||
Ajouter un composant
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="flex justify-end">
|
||||
<button type="button" @click="addComponent" class="btn btn-primary btn-sm">
|
||||
<svg class="w-4 h-4 mr-2" 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"></path>
|
||||
</svg>
|
||||
<IconLucidePlus class="w-4 h-4 mr-2" aria-hidden="true" />
|
||||
Ajouter un composant
|
||||
</button>
|
||||
</div>
|
||||
@@ -165,6 +149,10 @@ import TypeEditCustomFieldsSection from '~/components/TypeEditCustomFieldsSectio
|
||||
import TypeMachinePieceForm from '~/components/TypeMachinePieceForm.vue'
|
||||
import ConstructeurSelect from '~/components/ConstructeurSelect.vue'
|
||||
import { useConstructeurs } from '~/composables/useConstructeurs'
|
||||
import IconLucideChevronRight from '~icons/lucide/chevron-right'
|
||||
import IconLucideSettings2 from '~icons/lucide/settings-2'
|
||||
import IconLucideX from '~icons/lucide/x'
|
||||
import IconLucidePlus from '~icons/lucide/plus'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
|
||||
@@ -8,15 +8,11 @@
|
||||
class="btn btn-ghost btn-sm p-1"
|
||||
@click="toggleSection"
|
||||
>
|
||||
<svg
|
||||
<IconLucideChevronRight
|
||||
class="w-4 h-4 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': expanded }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
<h3 class="card-title text-lg">Champs personnalisés du type</h3>
|
||||
<span class="badge badge-primary">{{ fields.length }}</span>
|
||||
@@ -37,19 +33,13 @@
|
||||
@click="toggleField(fieldIndex)"
|
||||
title="Plier / déplier le champ"
|
||||
>
|
||||
<svg
|
||||
<IconLucideChevronRight
|
||||
class="w-4 h-4 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': isFieldExpanded(fieldIndex) }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
<svg class="w-4 h-4 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"></path>
|
||||
</svg>
|
||||
<IconLucideListChecks class="w-4 h-4 text-blue-500" aria-hidden="true" />
|
||||
<h5 class="text-sm font-medium">Champ personnalisé {{ fieldIndex + 1 }}</h5>
|
||||
<span v-if="!isFieldExpanded(fieldIndex)" class="text-xs text-gray-500 truncate max-w-[160px]">
|
||||
{{ field.name || 'Sans nom' }}
|
||||
@@ -61,9 +51,7 @@
|
||||
class="btn btn-square btn-error btn-sm"
|
||||
title="Supprimer ce champ"
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
||||
</svg>
|
||||
<IconLucideX class="w-4 h-4" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -148,18 +136,14 @@
|
||||
|
||||
<div class="flex justify-end">
|
||||
<button type="button" @click="addField" class="btn btn-primary btn-sm">
|
||||
<svg class="w-4 h-4 mr-2" 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"></path>
|
||||
</svg>
|
||||
<IconLucidePlus class="w-4 h-4 mr-2" aria-hidden="true" />
|
||||
Ajouter un champ
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="flex justify-end">
|
||||
<button type="button" @click="addField" class="btn btn-primary btn-sm">
|
||||
<svg class="w-4 h-4 mr-2" 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"></path>
|
||||
</svg>
|
||||
<IconLucidePlus class="w-4 h-4 mr-2" aria-hidden="true" />
|
||||
Ajouter un champ
|
||||
</button>
|
||||
</div>
|
||||
@@ -169,6 +153,10 @@
|
||||
|
||||
<script setup>
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import IconLucideChevronRight from '~icons/lucide/chevron-right'
|
||||
import IconLucideListChecks from '~icons/lucide/list-checks'
|
||||
import IconLucideX from '~icons/lucide/x'
|
||||
import IconLucidePlus from '~icons/lucide/plus'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
|
||||
@@ -8,15 +8,11 @@
|
||||
class="btn btn-ghost btn-sm p-1"
|
||||
@click="toggleSection"
|
||||
>
|
||||
<svg
|
||||
<IconLucideChevronRight
|
||||
class="w-4 h-4 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': expanded }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
<h3 class="card-title text-lg">Pièces principales</h3>
|
||||
<span class="badge badge-secondary">{{ pieces.length }}</span>
|
||||
@@ -37,6 +33,7 @@
|
||||
<script setup>
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import TypeMachinePieceForm from '~/components/TypeMachinePieceForm.vue'
|
||||
import IconLucideChevronRight from '~icons/lucide/chevron-right'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
|
||||
@@ -8,19 +8,13 @@
|
||||
@click="toggleDetails"
|
||||
title="Plier / déplier la pièce"
|
||||
>
|
||||
<svg
|
||||
class="w-4 h-4 transition-transform duration-200"
|
||||
<IconLucideChevronRight
|
||||
class="w-4 h-4 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': expanded }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
<svg class="w-5 h-5 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"></path>
|
||||
</svg>
|
||||
<IconLucidePackage class="w-5 h-5 text-red-500" aria-hidden="true" />
|
||||
<h4 class="font-medium">{{ piece.name }}</h4>
|
||||
<span v-if="!expanded && piece.reference" class="text-xs text-gray-500">(Ref: {{ piece.reference }})</span>
|
||||
</div>
|
||||
@@ -62,6 +56,8 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import IconLucideChevronRight from '~icons/lucide/chevron-right'
|
||||
import IconLucidePackage from '~icons/lucide/package'
|
||||
|
||||
const props = defineProps({
|
||||
piece: {
|
||||
|
||||
@@ -1,166 +1,150 @@
|
||||
<template>
|
||||
<div class="space-y-4">
|
||||
<div class="flex justify-end">
|
||||
<button
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline btn-sm"
|
||||
@click="toggleAllPieces"
|
||||
>
|
||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
v-if="allExpanded"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M18 12H6"
|
||||
></path>
|
||||
<path
|
||||
v-else
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 6v12m6-6H6"
|
||||
></path>
|
||||
</svg>
|
||||
{{ allExpanded ? 'Tout plier' : 'Tout déplier' }}
|
||||
<IconLucideChevronRight
|
||||
class="w-4 h-4 mr-2 transform transition-transform"
|
||||
:class="allExpanded ? 'rotate-90' : ''"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span>{{ allExpanded ? 'Tout plier' : 'Tout déplier' }}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-for="(piece, index) in pieces" :key="index" class="border border-gray-200 rounded-lg p-4 bg-gray-50">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<div class="flex items-center gap-2">
|
||||
<button
|
||||
<div
|
||||
v-for="(piece, index) in pieces"
|
||||
:key="piece.id ?? index"
|
||||
class="border border-base-200 rounded-lg bg-base-100 p-4 space-y-3"
|
||||
>
|
||||
<div class="flex items-start justify-between">
|
||||
<div class="flex items-start gap-2">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-ghost btn-xs p-1"
|
||||
@click="togglePieceDetails(index)"
|
||||
title="Plier / déplier la pièce"
|
||||
>
|
||||
<svg
|
||||
class="w-4 h-4 transition-transform duration-200"
|
||||
<IconLucideChevronRight
|
||||
class="w-4 h-4 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': isPieceExpanded(index) }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
<h5 class="text-sm font-medium">Nouvelle pièce {{ index + 1 }}</h5>
|
||||
<span v-if="!isPieceExpanded(index)" class="text-xs text-gray-500 truncate max-w-[160px]">
|
||||
{{ piece.name || 'Sans nom' }}
|
||||
</span>
|
||||
<div>
|
||||
<h5 class="text-sm font-medium">Pièce {{ index + 1 }}</h5>
|
||||
<span
|
||||
v-if="!isPieceExpanded(index)"
|
||||
class="text-xs text-gray-500 block max-w-[200px] truncate"
|
||||
>
|
||||
{{ piece.name || 'Sans nom' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
@click="removePiece(index)"
|
||||
class="btn btn-square btn-error btn-sm"
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-square btn-error btn-xs"
|
||||
@click="removePiece(index)"
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
||||
</svg>
|
||||
<IconLucideX class="w-3 h-3" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="isPieceExpanded(index)" class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">Nom de la pièce</span>
|
||||
</label>
|
||||
<input
|
||||
v-model="piece.name"
|
||||
type="text"
|
||||
placeholder="Nom de la pièce"
|
||||
class="input input-bordered input-sm"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">Référence</span>
|
||||
</label>
|
||||
<input
|
||||
v-model="piece.reference"
|
||||
type="text"
|
||||
placeholder="Référence"
|
||||
class="input input-bordered input-sm"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">Constructeur</span>
|
||||
</label>
|
||||
<ConstructeurSelect
|
||||
:model-value="piece.constructeurId || piece.constructeur?.id || null"
|
||||
placeholder="Rechercher un constructeur..."
|
||||
@update:modelValue="(value) => setPieceConstructeur(index, value)"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">Emplacement</span>
|
||||
</label>
|
||||
<input
|
||||
v-model="piece.emplacement"
|
||||
type="text"
|
||||
placeholder="Emplacement"
|
||||
class="input input-bordered input-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Champs personnalisés de cette pièce -->
|
||||
<div v-if="isPieceExpanded(index) && piece.customFields && piece.customFields.length > 0" class="mt-4">
|
||||
<h6 class="text-xs font-medium text-gray-600 mb-2">Champs personnalisés de cette pièce :</h6>
|
||||
<div class="space-y-2">
|
||||
<div
|
||||
v-for="(field, fieldIndex) in piece.customFields"
|
||||
:key="fieldIndex"
|
||||
class="border border-gray-200 rounded p-2 bg-white"
|
||||
<div v-if="isPieceExpanded(index)" class="space-y-4">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="form-control">
|
||||
<label class="label"><span class="label-text">Nom</span></label>
|
||||
<input
|
||||
v-model="piece.name"
|
||||
type="text"
|
||||
class="input input-bordered input-sm"
|
||||
placeholder="Nom de la pièce"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label"><span class="label-text">Référence</span></label>
|
||||
<input
|
||||
v-model="piece.reference"
|
||||
type="text"
|
||||
class="input input-bordered input-sm"
|
||||
placeholder="Référence"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label"><span class="label-text">Constructeur</span></label>
|
||||
<ConstructeurSelect
|
||||
:model-value="piece.constructeurId || piece.constructeur?.id || null"
|
||||
placeholder="Sélectionner un constructeur"
|
||||
@update:modelValue="value => setPieceConstructeur(index, value)"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label"><span class="label-text">Emplacement</span></label>
|
||||
<input
|
||||
v-model="piece.emplacement"
|
||||
type="text"
|
||||
class="input input-bordered input-sm"
|
||||
placeholder="Emplacement"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label"><span class="label-text">Prix</span></label>
|
||||
<input
|
||||
v-model="piece.prix"
|
||||
type="number"
|
||||
step="0.01"
|
||||
class="input input-bordered input-sm"
|
||||
placeholder="Prix (optionnel)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-3">
|
||||
<div
|
||||
v-for="(field, fieldIndex) in piece.customFields || []"
|
||||
:key="field.id || `${index}-${fieldIndex}`"
|
||||
class="border border-base-200 rounded-lg bg-base-200/60 p-3 space-y-2"
|
||||
>
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<button
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-ghost btn-xs p-1"
|
||||
@click="togglePieceCustomFieldDetails(index, fieldIndex)"
|
||||
title="Plier / déplier le champ"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
<IconLucideChevronRight
|
||||
class="w-3 h-3 transition-transform duration-200"
|
||||
:class="{ 'rotate-90': isPieceCustomFieldExpanded(index, fieldIndex) }"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
<span class="text-xs font-medium">Champ {{ fieldIndex + 1 }}</span>
|
||||
<span v-if="!isPieceCustomFieldExpanded(index, fieldIndex)" class="text-[10px] text-gray-500 truncate max-w-[120px]">
|
||||
<span
|
||||
v-if="!isPieceCustomFieldExpanded(index, fieldIndex)"
|
||||
class="text-[10px] text-gray-500 max-w-[160px] truncate"
|
||||
>
|
||||
{{ field.name || 'Sans nom' }}
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
@click="removeCustomField(index, fieldIndex)"
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-square btn-error btn-xs"
|
||||
@click="removeCustomField(index, fieldIndex)"
|
||||
>
|
||||
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
||||
</svg>
|
||||
<IconLucideX class="w-3 h-3" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="isPieceCustomFieldExpanded(index, fieldIndex)" class="grid grid-cols-1 md:grid-cols-2 gap-2">
|
||||
<div>
|
||||
<input
|
||||
v-model="field.name"
|
||||
type="text"
|
||||
placeholder="Nom du champ"
|
||||
class="input input-bordered input-xs w-full"
|
||||
|
||||
<div v-if="isPieceCustomFieldExpanded(index, fieldIndex)" class="space-y-3">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-2">
|
||||
<input
|
||||
v-model="field.name"
|
||||
type="text"
|
||||
class="input input-bordered input-xs w-full"
|
||||
placeholder="Nom du champ"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<select v-model="field.type" class="select select-bordered select-xs w-full">
|
||||
<option value="">Type</option>
|
||||
<option value="text">Texte</option>
|
||||
@@ -170,63 +154,49 @@
|
||||
<option value="date">Date</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="isPieceCustomFieldExpanded(index, fieldIndex)" class="grid grid-cols-1 md:grid-cols-2 gap-2 mt-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<input
|
||||
v-model="field.required"
|
||||
type="checkbox"
|
||||
class="checkbox checkbox-xs"
|
||||
/>
|
||||
<span class="text-xs">Obligatoire</span>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
v-model="field.defaultValue"
|
||||
type="text"
|
||||
placeholder="Valeur par défaut"
|
||||
class="input input-bordered input-xs w-full"
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-2">
|
||||
<label class="flex items-center gap-2 text-xs">
|
||||
<input v-model="field.required" type="checkbox" class="checkbox checkbox-xs" />
|
||||
Obligatoire
|
||||
</label>
|
||||
<input
|
||||
v-model="field.defaultValue"
|
||||
type="text"
|
||||
class="input input-bordered input-xs w-full"
|
||||
placeholder="Valeur par défaut"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Options pour les champs de type SELECT -->
|
||||
<div v-if="isPieceCustomFieldExpanded(index, fieldIndex) && field.type === 'select'" class="mt-2">
|
||||
<textarea
|
||||
v-model="field.optionsText"
|
||||
placeholder="Option 1 Option 2 Option 3"
|
||||
class="textarea textarea-bordered textarea-xs w-full h-16"
|
||||
@input="updateFieldOptions(index, fieldIndex)"
|
||||
></textarea>
|
||||
|
||||
<div v-if="field.type === 'select'">
|
||||
<textarea
|
||||
v-model="field.optionsText"
|
||||
class="textarea textarea-bordered textarea-xs w-full h-16"
|
||||
placeholder="Option 1 Option 2 Option 3"
|
||||
@input="updateFieldOptions(index, fieldIndex)"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline btn-sm"
|
||||
@click="addCustomField(index)"
|
||||
>
|
||||
<IconLucidePlus class="w-4 h-4 mr-2" aria-hidden="true" />
|
||||
Ajouter un champ personnalisé
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bouton pour ajouter des champs personnalisés -->
|
||||
<div v-if="isPieceExpanded(index)" class="mt-3">
|
||||
<button
|
||||
type="button"
|
||||
@click="addCustomField(index)"
|
||||
class="btn btn-outline btn-sm"
|
||||
>
|
||||
<svg class="w-4 h-4 mr-2" 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"></path>
|
||||
</svg>
|
||||
Ajouter champs personnalisés
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
@click="addPiece"
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline btn-sm"
|
||||
@click="addPiece"
|
||||
>
|
||||
<svg class="w-4 h-4 mr-2" 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"></path>
|
||||
</svg>
|
||||
<IconLucidePlus class="w-4 h-4 mr-2" aria-hidden="true" />
|
||||
Ajouter une pièce de machine
|
||||
</button>
|
||||
</div>
|
||||
@@ -236,6 +206,9 @@
|
||||
import { ref, reactive, onMounted, watch } from 'vue'
|
||||
import ConstructeurSelect from '~/components/ConstructeurSelect.vue'
|
||||
import { useConstructeurs } from '~/composables/useConstructeurs'
|
||||
import IconLucideChevronRight from '~icons/lucide/chevron-right'
|
||||
import IconLucideX from '~icons/lucide/x'
|
||||
import IconLucidePlus from '~icons/lucide/plus'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
|
||||
Reference in New Issue
Block a user