196 lines
5.4 KiB
Vue
196 lines
5.4 KiB
Vue
<template>
|
||
<div class="space-y-6">
|
||
<!-- Label -->
|
||
<div class="grid grid-cols-4 gap-4">
|
||
<label class="text-sm font-medium leading-8">Label</label>
|
||
<div class="col-span-3">
|
||
<input
|
||
v-model="formData.label"
|
||
type="text"
|
||
placeholder="Display name for this field"
|
||
class="w-full px-3 py-2 border rounded-md text-sm"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- API Name (Read-only if editing existing field) -->
|
||
<div class="grid grid-cols-4 gap-4">
|
||
<label class="text-sm font-medium leading-8">API Name</label>
|
||
<div class="col-span-3">
|
||
<input
|
||
v-model="formData.apiName"
|
||
type="text"
|
||
placeholder="e.g., accountName"
|
||
:disabled="isEditing"
|
||
class="w-full px-3 py-2 border rounded-md text-sm disabled:bg-gray-100 disabled:text-gray-600"
|
||
/>
|
||
<p v-if="isEditing" class="text-xs text-gray-500 mt-1">
|
||
Cannot change API name on existing fields
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Description -->
|
||
<div class="grid grid-cols-4 gap-4">
|
||
<label class="text-sm font-medium leading-8">Description</label>
|
||
<div class="col-span-3">
|
||
<textarea
|
||
v-model="formData.description"
|
||
placeholder="Describe the purpose of this field"
|
||
rows="3"
|
||
class="w-full px-3 py-2 border rounded-md text-sm"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Placeholder -->
|
||
<div class="grid grid-cols-4 gap-4">
|
||
<label class="text-sm font-medium leading-8">Placeholder</label>
|
||
<div class="col-span-3">
|
||
<input
|
||
v-model="formData.placeholder"
|
||
type="text"
|
||
placeholder="e.g., Enter account name"
|
||
class="w-full px-3 py-2 border rounded-md text-sm"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Help Text -->
|
||
<div class="grid grid-cols-4 gap-4">
|
||
<label class="text-sm font-medium leading-8">Help Text</label>
|
||
<div class="col-span-3">
|
||
<textarea
|
||
v-model="formData.helpText"
|
||
placeholder="Additional guidance for users"
|
||
rows="2"
|
||
class="w-full px-3 py-2 border rounded-md text-sm"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Display Order -->
|
||
<div class="grid grid-cols-4 gap-4">
|
||
<label class="text-sm font-medium leading-8">Display Order</label>
|
||
<div class="col-span-3">
|
||
<input
|
||
v-model.number="formData.displayOrder"
|
||
type="number"
|
||
class="w-full px-3 py-2 border rounded-md text-sm"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Required -->
|
||
<div class="grid grid-cols-4 gap-4">
|
||
<label class="text-sm font-medium leading-8">Required</label>
|
||
<div class="col-span-3 flex items-center">
|
||
<input
|
||
v-model="formData.isRequired"
|
||
type="checkbox"
|
||
class="w-4 h-4 border rounded"
|
||
/>
|
||
<span class="ml-2 text-sm text-gray-600">
|
||
{{ formData.isRequired ? 'Yes, this field is required' : 'No, this field is optional' }}
|
||
</span>
|
||
<p v-if="hasData && !wasRequired && formData.isRequired" class="ml-2 text-xs text-red-600">
|
||
⚠️ Existing records may have empty values
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Unique -->
|
||
<div class="grid grid-cols-4 gap-4">
|
||
<label class="text-sm font-medium leading-8">Unique</label>
|
||
<div class="col-span-3 flex items-center">
|
||
<input
|
||
v-model="formData.isUnique"
|
||
type="checkbox"
|
||
class="w-4 h-4 border rounded"
|
||
/>
|
||
<span class="ml-2 text-sm text-gray-600">
|
||
{{ formData.isUnique ? 'Yes, values must be unique' : 'No, duplicate values allowed' }}
|
||
</span>
|
||
<p v-if="hasData && !wasUnique && formData.isUnique" class="ml-2 text-xs text-red-600">
|
||
⚠️ Existing records may have duplicate values
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Default Value -->
|
||
<div class="grid grid-cols-4 gap-4">
|
||
<label class="text-sm font-medium leading-8">Default Value</label>
|
||
<div class="col-span-3">
|
||
<input
|
||
v-model="formData.defaultValue"
|
||
type="text"
|
||
placeholder="Value used when field is not provided"
|
||
class="w-full px-3 py-2 border rounded-md text-sm"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, watch, onMounted } from 'vue'
|
||
|
||
interface Props {
|
||
label?: string
|
||
apiName?: string
|
||
description?: string
|
||
placeholder?: string
|
||
helpText?: string
|
||
displayOrder?: number
|
||
isRequired?: boolean
|
||
isUnique?: boolean
|
||
defaultValue?: string
|
||
isEditing?: boolean
|
||
hasData?: boolean
|
||
}
|
||
|
||
interface Emits {
|
||
(e: 'update', data: any): void
|
||
}
|
||
|
||
const props = withDefaults(defineProps<Props>(), {
|
||
label: '',
|
||
apiName: '',
|
||
description: '',
|
||
placeholder: '',
|
||
helpText: '',
|
||
displayOrder: 0,
|
||
isRequired: false,
|
||
isUnique: false,
|
||
defaultValue: '',
|
||
isEditing: false,
|
||
hasData: false,
|
||
})
|
||
|
||
const emit = defineEmits<Emits>()
|
||
|
||
const formData = ref({
|
||
label: props.label,
|
||
apiName: props.apiName,
|
||
description: props.description,
|
||
placeholder: props.placeholder,
|
||
helpText: props.helpText,
|
||
displayOrder: props.displayOrder,
|
||
isRequired: props.isRequired,
|
||
isUnique: props.isUnique,
|
||
defaultValue: props.defaultValue,
|
||
})
|
||
|
||
const wasRequired = ref(props.isRequired)
|
||
const wasUnique = ref(props.isUnique)
|
||
|
||
onMounted(() => {
|
||
wasRequired.value = props.isRequired
|
||
wasUnique.value = props.isUnique
|
||
})
|
||
|
||
watch(formData, (newVal) => {
|
||
emit('update', newVal)
|
||
}, { deep: true })
|
||
</script>
|