DateTimePicker.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <template>
  2. <v-row>
  3. <v-col cols="12" md="6">
  4. <v-text-field
  5. :model-value="dateModel ? _useDate.format(dateModel, 'fullDateWithWeekday') : undefined"
  6. :label="$t('choose_day')"
  7. prepend-icon="fas fa-calendar"
  8. :rules="rules"
  9. :variant="variant"
  10. :error="error || !!fieldViolations"
  11. :error-messages="
  12. errorMessage || (fieldViolations ? $t(fieldViolations) : '')
  13. "
  14. readonly
  15. >
  16. <v-menu
  17. v-model="showMenuDate"
  18. :close-on-content-click="false"
  19. activator="parent"
  20. min-width="0"
  21. >
  22. <v-date-picker
  23. :model-value="dateModel"
  24. @update:model-value="onUpdateDate($event)"
  25. />
  26. </v-menu>
  27. </v-text-field>
  28. </v-col>
  29. <v-col cols="12" md="6">
  30. <v-text-field
  31. :model-value="time"
  32. :variant="variant"
  33. :label="$t('choose_hour')"
  34. prepend-icon="fas fa-clock"
  35. :rules="rules"
  36. :error="error || !!fieldViolations"
  37. :error-messages="
  38. errorMessage || (fieldViolations ? $t(fieldViolations) : '')
  39. "
  40. readonly
  41. >
  42. <v-menu
  43. v-model="showMenuTime"
  44. :close-on-content-click="false"
  45. activator="parent"
  46. min-width="0"
  47. >
  48. <v-time-picker
  49. :model-value="time"
  50. format="24hr"
  51. @update:model-value="onUpdateTime($event)"
  52. scrollable
  53. />
  54. </v-menu>
  55. </v-text-field>
  56. </v-col>
  57. </v-row>
  58. </template>
  59. <script setup lang="ts">
  60. import { ref, computed, onBeforeUnmount, type PropType } from 'vue'
  61. import { useFieldViolation } from '~/composables/form/useFieldViolation'
  62. import { useDate } from 'vuetify'
  63. import DateUtils from "~/services/utils/dateUtils";
  64. const props = defineProps({
  65. /**
  66. * v-model
  67. */
  68. modelValue: {
  69. type: String as PropType<Date | string | null>,
  70. required: false,
  71. default: null,
  72. },
  73. /**
  74. * Nom de la propriété d'une entité lorsque l'input concerne cette propriété
  75. * - Utilisé par la validation
  76. * - Laisser null si le champ ne s'applique pas à une entité
  77. */
  78. field: {
  79. type: String,
  80. required: false,
  81. default: null,
  82. },
  83. /**
  84. * Label du champ
  85. * Si non défini, c'est le nom de propriété qui est utilisé
  86. */
  87. label: {
  88. type: String,
  89. required: false,
  90. default: null,
  91. },
  92. /**
  93. * Définit si le champ est en lecture seule
  94. */
  95. readonly: {
  96. type: Boolean,
  97. required: false,
  98. },
  99. /**
  100. * Règles de validation
  101. * @see https://vuetify.cn/en/components/forms/#validation-with-submit-clear
  102. */
  103. rules: {
  104. type: Array as PropType<Array<(value: any) => boolean | string>>,
  105. required: false,
  106. default: () => [],
  107. },
  108. /**
  109. * Le champ est-il actuellement en état d'erreur
  110. */
  111. error: {
  112. type: Boolean,
  113. required: false,
  114. },
  115. /**
  116. * Si le champ est en état d'erreur, quel est le message d'erreur?
  117. */
  118. errorMessage: {
  119. type: String,
  120. required: false,
  121. default: null,
  122. },
  123. /**
  124. * @see https://vuetifyjs.com/en/api/v-autocomplete/#props-variant
  125. */
  126. variant: {
  127. type: String as PropType<
  128. | 'filled'
  129. | 'outlined'
  130. | 'plain'
  131. | 'underlined'
  132. | 'solo'
  133. | 'solo-inverted'
  134. | 'solo-filled'
  135. | undefined
  136. >,
  137. required: false,
  138. default: 'outlined',
  139. },
  140. })
  141. const showMenuTime = ref(false)
  142. const showMenuDate = ref(false)
  143. const _useDate = useDate()
  144. const { fieldViolations, updateViolationState } = useFieldViolation(props.field)
  145. const dateModel = computed(()=> props.modelValue ? new Date(props.modelValue) : undefined)
  146. const time = computed(()=> props.modelValue ? _useDate.format(new Date(props.modelValue),'fullTime24h') : undefined)
  147. const emit = defineEmits(['update:model-value'])
  148. const onUpdateDate = (event: Date) => {
  149. updateViolationState()
  150. let date = DateUtils.combineDateAndTime(event, time.value)
  151. emit('update:model-value', date.toISOString().replace('.000Z', '+00:00'))
  152. }
  153. const onUpdateTime = (event: string) => {
  154. updateViolationState()
  155. let date = DateUtils.combineDateAndTime(dateModel.value, event)
  156. emit('update:model-value', date.toISOString().replace('.000Z', '+00:00'))
  157. }
  158. onBeforeUnmount(() => {
  159. updateViolationState()
  160. })
  161. </script>
  162. <style scoped lang="scss">
  163. </style>