| 1 |
<template> |
| 2 |
<div class="ivyforms-field-date" :class="{ 'ivyforms-field-date--readonly': readOnly }"> |
| 3 |
<!-- Date Picker Type --> |
| 4 |
<template v-if="isPickerType"> |
| 5 |
<IvyFormItem |
| 6 |
:label="hideLabel ? '' : label" |
| 7 |
:required="required" |
| 8 |
:label-position="labelPosition" |
| 9 |
> |
| 10 |
<IvyTextInput |
| 11 |
:id="'date_' + index" |
| 12 |
:aria-label="label" |
| 13 |
:placeholder="placeholder" |
| 14 |
:model-value="datePickerValue" |
| 15 |
type="text" |
| 16 |
readonly="" |
| 17 |
/> |
| 18 |
<div |
| 19 |
v-if="description" |
| 20 |
class="ivyforms-field-date__description regular-14 ivyforms-width-100 ivyforms-mt-6" |
| 21 |
> |
| 22 |
{{ description }} |
| 23 |
</div> |
| 24 |
</IvyFormItem> |
| 25 |
</template> |
| 26 |
|
| 27 |
<!-- Input Type (manual entry) --> |
| 28 |
<template v-else-if="isInputType"> |
| 29 |
<IvyFormItem |
| 30 |
:label="hideLabel ? '' : label" |
| 31 |
:required="required" |
| 32 |
:label-position="labelPosition" |
| 33 |
> |
| 34 |
<IvyTextInput |
| 35 |
:id="'date_' + index" |
| 36 |
:aria-label="label" |
| 37 |
readonly |
| 38 |
:placeholder="placeholder" |
| 39 |
:model-value="datePickerValue" |
| 40 |
type="text" |
| 41 |
/> |
| 42 |
<div |
| 43 |
v-if="description" |
| 44 |
class="ivyforms-field-date__description regular-14 ivyforms-width-100 ivyforms-mt-6" |
| 45 |
> |
| 46 |
{{ description }} |
| 47 |
</div> |
| 48 |
</IvyFormItem> |
| 49 |
</template> |
| 50 |
|
| 51 |
<!-- Dropdown Type --> |
| 52 |
<template v-else-if="isDropdownType"> |
| 53 |
<IvyFormItem |
| 54 |
:label="hideLabel ? '' : label" |
| 55 |
:required="required" |
| 56 |
:label-position="labelPosition" |
| 57 |
> |
| 58 |
<div class="ivyforms-flex ivyforms-width-100 ivyforms-gap-12"> |
| 59 |
<div class="ivyforms-flex ivyforms-flex-1 ivyforms-flex-direction-column"> |
| 60 |
<div class="medium-14 ivyforms-mb-6 ivyforms-field-date__sublabel"> |
| 61 |
{{ getDayLabel }} |
| 62 |
</div> |
| 63 |
<IvySelectInput |
| 64 |
:model-value="dropdownDayValue" |
| 65 |
placeholder="--" |
| 66 |
readonly |
| 67 |
@mousedown.prevent |
| 68 |
@click.prevent |
| 69 |
/> |
| 70 |
</div> |
| 71 |
<div class="ivyforms-flex ivyforms-flex-1 ivyforms-flex-direction-column"> |
| 72 |
<div class="medium-14 ivyforms-mb-6 ivyforms-field-date__sublabel"> |
| 73 |
{{ getMonthLabel }} |
| 74 |
</div> |
| 75 |
<IvySelectInput |
| 76 |
:model-value="dropdownMonthValue" |
| 77 |
placeholder="--" |
| 78 |
readonly |
| 79 |
@mousedown.prevent |
| 80 |
@click.prevent |
| 81 |
/> |
| 82 |
</div> |
| 83 |
<div class="ivyforms-flex ivyforms-flex-1 ivyforms-flex-direction-column"> |
| 84 |
<div class="medium-14 ivyforms-mb-6 ivyforms-field-date__sublabel"> |
| 85 |
{{ getYearLabel }} |
| 86 |
</div> |
| 87 |
<IvySelectInput |
| 88 |
:model-value="dropdownYearValue" |
| 89 |
placeholder="--" |
| 90 |
readonly |
| 91 |
@mousedown.prevent |
| 92 |
@click.prevent |
| 93 |
/> |
| 94 |
</div> |
| 95 |
</div> |
| 96 |
<div |
| 97 |
v-if="description" |
| 98 |
class="ivyforms-field-date__description regular-14 ivyforms-width-100 ivyforms-mt-6" |
| 99 |
> |
| 100 |
{{ description }} |
| 101 |
</div> |
| 102 |
</IvyFormItem> |
| 103 |
</template> |
| 104 |
</div> |
| 105 |
</template> |
| 106 |
|
| 107 |
<script setup lang="ts"> |
| 108 |
import { computed } from 'vue' |
| 109 |
import { useFormBuilder } from '@/stores/useFormBuilder' |
| 110 |
import { useLabels } from '@/composables/useLabels' |
| 111 |
import { useDateField } from '@/composables/useDateField' |
| 112 |
import IvySelectInput from '@/views/_components/input/IvySelectInput.vue' |
| 113 |
import IvyTextInput from '@/views/_components/input/IvyTextInput.vue' |
| 114 |
import IvyFormItem from '@/views/_components/form/IvyFormItem.vue' |
| 115 |
|
| 116 |
const { getLabel } = useLabels() |
| 117 |
const props = defineProps<{ fieldIndex: number }>() |
| 118 |
const formBuilderStore = useFormBuilder() |
| 119 |
const field = computed(() => formBuilderStore.fields.find((f) => f.fieldIndex === props.fieldIndex)) |
| 120 |
const label = computed(() => field.value?.label || '') |
| 121 |
const placeholder = computed(() => field.value?.placeholder || '') |
| 122 |
const required = computed(() => field.value?.required || false) |
| 123 |
const hideLabel = computed(() => field.value?.hideLabel || false) |
| 124 |
const readOnly = computed(() => field.value?.readOnly || false) |
| 125 |
const description = computed(() => field.value?.description || '') |
| 126 |
const index = computed(() => field.value?.fieldIndex ?? props.fieldIndex) |
| 127 |
const modelValue = computed(() => field.value?.defaultValue || '') |
| 128 |
|
| 129 |
const dateFieldType = computed(() => field.value?.dateFieldType || 'picker') |
| 130 |
const dateFormat = computed(() => field.value?.dateFormat || 'MM/DD/YYYY') |
| 131 |
const labelPosition = computed(() => |
| 132 |
field.value?.labelPosition === 'default' ? 'top' : field.value?.labelPosition || 'top', |
| 133 |
) |
| 134 |
|
| 135 |
const isPickerType = computed(() => dateFieldType.value === 'picker') |
| 136 |
const isInputType = computed(() => dateFieldType.value === 'input') |
| 137 |
const isDropdownType = computed(() => dateFieldType.value === 'dropdown') |
| 138 |
|
| 139 |
const { parseDateString } = useDateField() |
| 140 |
|
| 141 |
// Parse default value |
| 142 |
const parsedDate = computed(() => |
| 143 |
parseDateString(String(modelValue.value || ''), String(dateFormat.value as unknown as string)), |
| 144 |
) |
| 145 |
|
| 146 |
// For date picker and input mode - both use the same formatted value |
| 147 |
const datePickerValue = computed(() => modelValue.value || '') |
| 148 |
|
| 149 |
// For dropdown mode |
| 150 |
const dropdownDayValue = computed(() => parsedDate.value.day) |
| 151 |
const dropdownMonthValue = computed(() => parsedDate.value.month) |
| 152 |
const dropdownYearValue = computed(() => parsedDate.value.year) |
| 153 |
|
| 154 |
// Labels based on format |
| 155 |
const getDayLabel = computed(() => getLabel('day')) |
| 156 |
const getMonthLabel = computed(() => getLabel('month')) |
| 157 |
const getYearLabel = computed(() => getLabel('year')) |
| 158 |
</script> |
| 159 |
|
| 160 |
<style lang="scss" scoped> |
| 161 |
.ivyforms-field-date { |
| 162 |
cursor: default; |
| 163 |
|
| 164 |
&--readonly { |
| 165 |
opacity: 0.6; |
| 166 |
} |
| 167 |
|
| 168 |
&__sublabel { |
| 169 |
color: var(--map-base-text-0); |
| 170 |
} |
| 171 |
|
| 172 |
&__description { |
| 173 |
color: var(--map-base-text-0); |
| 174 |
display: block; |
| 175 |
white-space: normal; |
| 176 |
overflow-wrap: anywhere; |
| 177 |
word-break: break-word; |
| 178 |
} |
| 179 |
|
| 180 |
:deep(.el-input__inner), |
| 181 |
:deep(.el-input__wrapper) { |
| 182 |
cursor: default; |
| 183 |
} |
| 184 |
|
| 185 |
:deep(.ivyforms-input.el-input .el-input__wrapper), |
| 186 |
:deep(.ivyforms-input.el-input .el-input__wrapper:hover), |
| 187 |
:deep(.ivyforms-input.el-input .el-input__wrapper.is-hovering), |
| 188 |
:deep(.ivyforms-input.el-input .el-input__wrapper:focus), |
| 189 |
:deep(.ivyforms-input.el-input .el-input__wrapper.is-focused), |
| 190 |
:deep(.ivyforms-input.el-input .el-input__wrapper:active), |
| 191 |
:deep(.ivyforms-input.el-input .el-input__wrapper.is-active) { |
| 192 |
border: 1px solid var(--map-base-dusk-stroke--2); |
| 193 |
} |
| 194 |
} |
| 195 |
</style> |
| 196 |
|