DatePicker.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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 DateUtils from "~/services/utils/dateUtils";
  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 } = useNuxtApp()
  96. const { data, range } = props
  97. const {fieldViolations, updateViolationState} = useFieldViolation(props.field)
  98. const datesParsed: Ref<Array<string>|string|null> = range ? ref(Array<string>()) : ref(null)
  99. const fieldLabel = props.label ?? props.field
  100. const dateOpen: Ref<boolean> = ref(false)
  101. const onInputFocused = (event: any) => {
  102. dateOpen.value = true
  103. }
  104. const onInputBlured = (event: any) => {
  105. dateOpen.value = false
  106. }
  107. if (Array.isArray(datesParsed.value)) {
  108. for (const date of data as Array<string>) {
  109. if (date) {
  110. datesParsed.value.push(DateUtils.format(date, 'YYYY-MM-DD'))
  111. }
  112. }
  113. } else {
  114. datesParsed.value = data ? DateUtils.format(data, 'YYYY-MM-DD') : null
  115. }
  116. const datesFormatted: ComputedRef<string|null> = computed(() => {
  117. if (props.range && datesParsed.value && datesParsed.value.length < 2) {
  118. return null
  119. }
  120. return datesParsed.value ? DateUtils.formatAndConcat(datesParsed.value, props.format) : null
  121. })
  122. const unwatch: WatchStopHandle = watch(datesParsed, (newValue, oldValue) => {
  123. if (newValue === oldValue) { return }
  124. if (props.range && newValue && newValue.length < 2) { return }
  125. updateViolationState(Array.isArray(newValue) ? DateUtils.sort(newValue) : newValue)
  126. })
  127. onUnmounted(() => {
  128. unwatch()
  129. })
  130. </script>
  131. <style scoped>
  132. </style>