DefaultInputDatePicker.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. <template>
  2. <div v-bind="$attrs">
  3. <q-input
  4. ref="inputRef"
  5. v-model="treatedDate"
  6. :mask="inputMask"
  7. :label="label"
  8. :rules="rules"
  9. :dense="dense"
  10. clearable
  11. >
  12. <template #append>
  13. <q-icon
  14. :name="time ? 'mdi-calendar-clock' : 'mdi-calendar'"
  15. class="cursor-pointer"
  16. >
  17. <q-popup-proxy cover transition-show="scale" transition-hide="scale">
  18. <template v-if="!time">
  19. <q-date v-model="date" mask="YYYY-MM-DD">
  20. <div class="row items-center justify-end">
  21. <q-btn v-close-popup label="Close" color="primary" flat />
  22. </div>
  23. </q-date>
  24. </template>
  25. <template v-else>
  26. <q-tab-panels
  27. v-model="activePanel"
  28. animated
  29. transition-prev="slide-right"
  30. transition-next="slide-left"
  31. class="bg-white"
  32. >
  33. <q-tab-panel name="date" class="q-pa-none">
  34. <q-date
  35. v-model="date"
  36. mask="YYYY-MM-DD HH:mm"
  37. @update:model-value="handleDateSelection"
  38. />
  39. </q-tab-panel>
  40. <q-tab-panel name="time" class="q-pa-none">
  41. <q-time v-model="date" mask="YYYY-MM-DD HH:mm" format24h />
  42. </q-tab-panel>
  43. </q-tab-panels>
  44. </template>
  45. </q-popup-proxy>
  46. </q-icon>
  47. </template>
  48. </q-input>
  49. </div>
  50. </template>
  51. <script setup>
  52. import { watch, ref, computed, useTemplateRef } from "vue";
  53. import { useI18n } from "vue-i18n";
  54. import masks from "src/helpers/masks";
  55. const { label, rules, time, dense } = defineProps({
  56. label: {
  57. type: String,
  58. default: () => useI18n().t("common.terms.date"),
  59. },
  60. rules: {
  61. type: Array,
  62. default: () => [],
  63. },
  64. dense: {
  65. type: Boolean,
  66. default: false,
  67. },
  68. time: {
  69. type: Boolean,
  70. default: false,
  71. },
  72. });
  73. const qInputRef = useTemplateRef("inputRef");
  74. const treatedDate = defineModel();
  75. const untreatedDate = defineModel("untreatedDate");
  76. const activePanel = ref("date");
  77. const date = ref();
  78. const handleDateSelection = () => {
  79. if (time) {
  80. activePanel.value = "time";
  81. }
  82. };
  83. const formatDate = (value) => {
  84. if (!value) return null;
  85. const [datePart, timePart] = value.split(" ");
  86. const formattedDate = datePart.split("-").reverse().join("/");
  87. return time && timePart ? `${formattedDate} ${timePart}` : formattedDate;
  88. };
  89. const unformatDate = (value) => {
  90. if (!value) return null;
  91. const [datePart, timePart] = value.split(" ");
  92. const formattedDate = datePart.split("/").reverse().join("-");
  93. return time && timePart ? `${formattedDate} ${timePart}` : formattedDate;
  94. };
  95. const inputMask = computed(() => {
  96. if (!qInputRef.value) return "";
  97. if (time) {
  98. return masks.Brasil.datetime;
  99. }
  100. return masks.Brasil.date;
  101. });
  102. watch(date, (value) => {
  103. if (!value) return;
  104. untreatedDate.value = value;
  105. treatedDate.value = formatDate(value);
  106. });
  107. watch(treatedDate, (value) => {
  108. if (!value) {
  109. date.value = null;
  110. untreatedDate.value = null;
  111. treatedDate.value = null;
  112. activePanel.value = "date";
  113. return;
  114. }
  115. date.value = unformatDate(value);
  116. });
  117. watch(
  118. untreatedDate,
  119. (value) => {
  120. if (!value) {
  121. date.value = null;
  122. untreatedDate.value = null;
  123. treatedDate.value = null;
  124. activePanel.value = "date";
  125. return;
  126. }
  127. date.value = value;
  128. treatedDate.value = formatDate(value);
  129. },
  130. { immediate: true },
  131. );
  132. </script>