DatePicker.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. <!--
  2. Sélecteur de dates
  3. @see https://vuetifyjs.com/en/components/date-pickers/
  4. -->
  5. <template>
  6. <main>
  7. <v-text-field
  8. ref="input"
  9. v-model="datesFormatted"
  10. autocomplete="off"
  11. :label="$t(fieldLabel)"
  12. prepend-icon="mdi:mdi-calendar"
  13. :disabled="readonly"
  14. :density="dense ? 'compact' : 'default'"
  15. :single-line="singleLine"
  16. :error="error || !!fieldViolations"
  17. :error-messages="errorMessage || fieldViolations ? $t(fieldViolations) : ''"
  18. @update:focused=""
  19. @focus="onInputFocused($event); $emit('focus', $event)"
  20. @blur="onInputBlured($event); $emit('blur', $event)"
  21. />
  22. <v-menu
  23. activator="input"
  24. :model-value="dateOpen"
  25. :close-on-content-click="false"
  26. :nudge-right="40"
  27. transition="scale-transition"
  28. offset-y
  29. min-width="auto"
  30. >
  31. <!-- TODO: terminer une fois v-date-picker implémenté dans vuetify 3 -->
  32. <v-date-picker
  33. v-model="datesParsed"
  34. :range="range"
  35. color="ot-green lighten-1"
  36. @input="dateOpen = range && datesParsed.length < 2"
  37. />
  38. </v-menu>
  39. </main>
  40. </template>
  41. <script setup lang="ts">
  42. import {useNuxtApp} from "#app";
  43. import {useFieldViolation} from "~/composables/form/useFieldViolation";
  44. import {computed, ComputedRef, Ref} from "@vue/reactivity";
  45. import {useDateUtils} from "~/composables/utils/useDateUtils";
  46. import {onUnmounted, watch, WatchStopHandle} from "@vue/runtime-core";
  47. const props = defineProps({
  48. field: {
  49. type: String,
  50. required: false,
  51. default: null
  52. },
  53. label: {
  54. type: String,
  55. required: false,
  56. default: null
  57. },
  58. data: {
  59. type: [String, Array],
  60. required: false,
  61. default: null
  62. },
  63. readonly: {
  64. type: Boolean,
  65. required: false
  66. },
  67. range: {
  68. type: Boolean,
  69. required: false
  70. },
  71. dense: {
  72. type: Boolean,
  73. required: false
  74. },
  75. singleLine: {
  76. type: Boolean,
  77. required: false
  78. },
  79. format: {
  80. type: String,
  81. required: false,
  82. default: 'DD/MM/YYYY'
  83. },
  84. error: {
  85. type: Boolean,
  86. required: false
  87. },
  88. errorMessage: {
  89. type: String,
  90. required: false,
  91. default: null
  92. }
  93. })
  94. const input = ref(null)
  95. const { emit, $moment } = useNuxtApp()
  96. const { data, range } = props
  97. const {fieldViolations, updateViolationState} = useFieldViolation(props.field)
  98. const dateUtils = useDateUtils()
  99. const datesParsed: Ref<Array<string>|string|null> = range ? ref(Array<string>()) : ref(null)
  100. const fieldLabel = props.label ?? props.field
  101. const dateOpen: Ref<boolean> = ref(false)
  102. const onInputFocused = (event: any) => {
  103. dateOpen.value = true
  104. }
  105. const onInputBlured = (event: any) => {
  106. dateOpen.value = false
  107. }
  108. if (Array.isArray(datesParsed.value)) {
  109. for (const date of data as Array<string>) {
  110. if (date) {
  111. datesParsed.value.push($moment(date).format('YYYY-MM-DD'))
  112. }
  113. }
  114. } else {
  115. datesParsed.value = data ? $moment(data as string).format('YYYY-MM-DD') : null
  116. }
  117. const datesFormatted: ComputedRef<string|null> = computed(() => {
  118. if (props.range && datesParsed.value && datesParsed.value.length < 2) {
  119. return null
  120. }
  121. return datesParsed.value ? dateUtils.formatDatesAndConcat(datesParsed.value, props.format) : null
  122. })
  123. const unwatch: WatchStopHandle = watch(datesParsed, (newValue, oldValue) => {
  124. if (newValue === oldValue) { return }
  125. if (props.range && newValue && newValue.length < 2) { return }
  126. updateViolationState(Array.isArray(newValue) ? dateUtils.sortDate(newValue) : newValue)
  127. })
  128. onUnmounted(() => {
  129. unwatch()
  130. })
  131. </script>
  132. <style scoped>
  133. </style>