112 lines
3.5 KiB
Vue
112 lines
3.5 KiB
Vue
<template>
|
|
<section class="space-y-3">
|
|
<h3 class="text-sm font-semibold">
|
|
Définitions des champs personnalisés
|
|
</h3>
|
|
|
|
<p v-if="!fields.length" class="text-xs text-gray-500">
|
|
Aucun champ personnalisé défini. Cliquez sur « Ajouter » pour en créer un.
|
|
</p>
|
|
|
|
<ul v-else class="space-y-2" role="list">
|
|
<li
|
|
v-for="(field, index) in fields"
|
|
:key="field.uid"
|
|
class="border border-base-200 rounded-md p-3 space-y-2 bg-base-100 transition-colors"
|
|
:class="reorderClass(index)"
|
|
draggable="true"
|
|
@dragstart="onDragStart(index, $event)"
|
|
@dragenter="onDragEnter(index)"
|
|
@dragover.prevent="onDragEnter(index)"
|
|
@drop.prevent="onDrop(index)"
|
|
@dragend="onDragEnd"
|
|
>
|
|
<div class="flex items-start gap-3">
|
|
<button
|
|
type="button"
|
|
class="btn btn-ghost btn-xs btn-square cursor-grab active:cursor-grabbing mt-1"
|
|
title="Réordonner"
|
|
draggable="false"
|
|
>
|
|
<IconLucideGripVertical class="w-4 h-4" aria-hidden="true" />
|
|
</button>
|
|
|
|
<div class="flex-1 space-y-2">
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-2">
|
|
<CustomFieldNameInput
|
|
v-model="field.name"
|
|
placeholder="Nom du champ"
|
|
size="sm"
|
|
/>
|
|
<select v-model="field.type" class="select select-bordered select-sm">
|
|
<option value="text">
|
|
Texte
|
|
</option>
|
|
<option value="number">
|
|
Nombre
|
|
</option>
|
|
<option value="select">
|
|
Liste
|
|
</option>
|
|
<option value="boolean">
|
|
Oui/Non
|
|
</option>
|
|
<option value="date">
|
|
Date
|
|
</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="flex items-center gap-2 text-xs">
|
|
<input v-model="field.required" type="checkbox" class="checkbox checkbox-xs">
|
|
Obligatoire
|
|
</div>
|
|
|
|
<textarea
|
|
v-if="field.type === 'select'"
|
|
v-model="field.optionsText"
|
|
class="textarea textarea-bordered textarea-sm h-20"
|
|
placeholder="Option 1 Option 2"
|
|
/>
|
|
</div>
|
|
|
|
<button
|
|
type="button"
|
|
class="btn btn-ghost btn-xs btn-square text-error"
|
|
@click="$emit('remove-field', index)"
|
|
>
|
|
<IconLucideTrash class="w-4 h-4" aria-hidden="true" />
|
|
</button>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
|
|
<button type="button" class="btn btn-outline btn-sm" @click="$emit('add-field')">
|
|
<IconLucidePlus class="w-3 h-3 mr-2" aria-hidden="true" />
|
|
Ajouter un champ
|
|
</button>
|
|
</section>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { MachineCustomFieldEditorField } from '~/composables/useMachineCustomFieldDefs'
|
|
import IconLucideGripVertical from '~icons/lucide/grip-vertical'
|
|
import IconLucidePlus from '~icons/lucide/plus'
|
|
import IconLucideTrash from '~icons/lucide/trash'
|
|
|
|
defineProps<{
|
|
fields: MachineCustomFieldEditorField[]
|
|
saving: boolean
|
|
reorderClass: (index: number) => string
|
|
onDragStart: (index: number, event: DragEvent) => void
|
|
onDragEnter: (index: number) => void
|
|
onDrop: (index: number) => void
|
|
onDragEnd: () => void
|
|
}>()
|
|
|
|
defineEmits<{
|
|
'add-field': []
|
|
'remove-field': [index: number]
|
|
}>()
|
|
</script>
|