DefaultInputDatePicker.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. <template>
  2. <div v-bind="$attrs">
  3. <q-input
  4. ref="inputRef"
  5. v-model="treatedDate"
  6. :mask="inputMask"
  7. :label
  8. :rules
  9. :dense
  10. :error
  11. :error-message
  12. clearable
  13. >
  14. <template #append>
  15. <q-icon
  16. :name="time ? 'mdi-calendar-clock' : 'mdi-calendar'"
  17. class="cursor-pointer"
  18. >
  19. <q-popup-proxy cover transition-show="scale" transition-hide="scale">
  20. <template v-if="!time">
  21. <q-date v-model="date" mask="YYYY-MM-DD" color="primary" class="bg-surface text-text calendar-custom">
  22. <div class="row items-center justify-end">
  23. <q-btn v-close-popup label="Close" color="primary" flat />
  24. </div>
  25. </q-date>
  26. </template>
  27. <template v-else>
  28. <q-tab-panels
  29. v-model="activePanel"
  30. animated
  31. transition-prev="slide-right"
  32. transition-next="slide-left"
  33. class="bg-white"
  34. >
  35. <q-tab-panel name="date" class="q-pa-none">
  36. <q-date
  37. v-model="date"
  38. mask="YYYY-MM-DD HH:mm"
  39. @update:model-value="handleDateSelection"
  40. />
  41. </q-tab-panel>
  42. <q-tab-panel name="time" class="q-pa-none">
  43. <q-time v-model="date" mask="YYYY-MM-DD HH:mm" format24h />
  44. </q-tab-panel>
  45. </q-tab-panels>
  46. </template>
  47. </q-popup-proxy>
  48. </q-icon>
  49. </template>
  50. </q-input>
  51. </div>
  52. </template>
  53. <script setup>
  54. import { watch, ref, computed, useTemplateRef } from "vue";
  55. import { useI18n } from "vue-i18n";
  56. import masks from "src/helpers/masks";
  57. const { label, rules, time, dense } = defineProps({
  58. label: {
  59. type: String,
  60. default: () => useI18n().t("common.terms.date"),
  61. },
  62. rules: {
  63. type: Array,
  64. default: () => [],
  65. },
  66. dense: {
  67. type: Boolean,
  68. default: false,
  69. },
  70. time: {
  71. type: Boolean,
  72. default: false,
  73. },
  74. error: {
  75. type: Boolean,
  76. default: false,
  77. },
  78. errorMessage: {
  79. type: String,
  80. default: "",
  81. },
  82. });
  83. const qInputRef = useTemplateRef("inputRef");
  84. const treatedDate = defineModel();
  85. const untreatedDate = defineModel("untreatedDate");
  86. const activePanel = ref("date");
  87. const date = ref();
  88. const handleDateSelection = () => {
  89. if (time) {
  90. activePanel.value = "time";
  91. }
  92. };
  93. const formatDate = (value) => {
  94. if (!value) return null;
  95. const [datePart, timePart] = value.split(" ");
  96. const formattedDate = datePart.split("-").reverse().join("/");
  97. return time && timePart ? `${formattedDate} ${timePart}` : formattedDate;
  98. };
  99. const unformatDate = (value) => {
  100. if (!value) return null;
  101. const [datePart, timePart] = value.split(" ");
  102. const formattedDate = datePart.split("/").reverse().join("-");
  103. return time && timePart ? `${formattedDate} ${timePart}` : formattedDate;
  104. };
  105. const inputMask = computed(() => {
  106. if (!qInputRef.value) return "";
  107. if (time) {
  108. return masks.Brasil.datetime;
  109. }
  110. return masks.Brasil.date;
  111. });
  112. watch(date, (value) => {
  113. if (!value) return;
  114. untreatedDate.value = value;
  115. treatedDate.value = formatDate(value);
  116. });
  117. watch(treatedDate, (value) => {
  118. if (!value) {
  119. date.value = null;
  120. untreatedDate.value = null;
  121. treatedDate.value = null;
  122. activePanel.value = "date";
  123. return;
  124. }
  125. date.value = unformatDate(value);
  126. });
  127. watch(
  128. untreatedDate,
  129. (value) => {
  130. if (!value) {
  131. date.value = null;
  132. untreatedDate.value = null;
  133. treatedDate.value = null;
  134. activePanel.value = "date";
  135. return;
  136. }
  137. date.value = value;
  138. treatedDate.value = formatDate(value);
  139. },
  140. { immediate: true },
  141. );
  142. </script>
  143. <style scoped lang="scss">
  144. .calendar-custom {
  145. border-radius: 20px;
  146. background-color: white !important;
  147. :deep(.q-date__main) {
  148. background-color: white !important;
  149. }
  150. :deep(.q-date__content) {
  151. background-color: white !important;
  152. }
  153. :deep(.q-date__calendar) {
  154. background-color: white !important;
  155. }
  156. :deep(.q-date__calendar-item--out) {
  157. .q-btn__content {
  158. color: #CBD5E1 !important;
  159. }
  160. }
  161. :deep(.q-date__calendar-days .q-btn__content) {
  162. font-family: 'Inter', sans-serif;
  163. font-weight: 500;
  164. color: #1E293B;
  165. }
  166. :deep(.q-date__calendar-weekdays > div) {
  167. color: #6366F1;
  168. font-weight: 700;
  169. opacity: 0.8;
  170. }
  171. :deep(.q-date__navigation) {
  172. .q-btn {
  173. color: #1E293B !important;
  174. }
  175. .q-btn__content {
  176. color: #1E293B !important;
  177. }
  178. }
  179. :deep(.q-date__nav-btn-month),
  180. :deep(.q-date__nav-btn-year) {
  181. color: #6366F1 !important;
  182. font-weight: 700;
  183. }
  184. :deep(.q-date__event) {
  185. bottom: 4px;
  186. height: 6px;
  187. width: 6px;
  188. border-radius: 50%;
  189. }
  190. :deep(.q-date__today) {
  191. .q-btn__content {
  192. color: #7c4dff !important;
  193. background: #7c4dff15;
  194. border-radius: 50%;
  195. }
  196. }
  197. :deep(.q-date__selected) {
  198. .q-btn__content {
  199. background: #6366F1 !important;
  200. color: white !important;
  201. border-radius: 50%;
  202. box-shadow: 0 4px 10px rgba(99, 102, 241, 0.4);
  203. }
  204. }
  205. :deep(.q-date__view--months),
  206. :deep(.q-date__view--years) {
  207. .q-btn {
  208. color: #1E293B !important;
  209. }
  210. }
  211. }
  212. </style>