FeriadosCard.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. <template>
  2. <q-card flat class="feriados-card card-ring">
  3. <div class="flex justify-between items-center no-wrap q-mb-sm">
  4. <div class="flex items-center q-gutter-x-sm">
  5. <q-icon name="mdi-calendar-star-outline" color="dark" size="sm" />
  6. <span class="text-subtitle1">Feriados do Mês</span>
  7. </div>
  8. <q-btn
  9. icon="mdi-plus"
  10. color="primary"
  11. style="width: 40px; height: 40px"
  12. @click="openDialog"
  13. />
  14. </div>
  15. <q-separator />
  16. <div
  17. v-if="currentMonthHolidays.length === 0"
  18. class="text-caption text-grey-5 text-center q-mt-md"
  19. >
  20. Sem feriados para este mês.
  21. </div>
  22. <q-list v-else class="q-mt-md" dense>
  23. <template v-for="(holiday, index) in currentMonthHolidays" :key="holiday.id">
  24. <q-item class="q-px-none person-item">
  25. <q-item-section avatar style="min-width: 36px">
  26. <div class="day-badge">{{ holiday.day }}</div>
  27. </q-item-section>
  28. <q-item-section>
  29. <q-item-label class="text-body2">{{ holiday.description }}</q-item-label>
  30. <q-item-label caption>{{ typeLabel(holiday.type) }}</q-item-label>
  31. </q-item-section>
  32. </q-item>
  33. <q-separator v-if="index < currentMonthHolidays.length - 1" />
  34. </template>
  35. </q-list>
  36. </q-card>
  37. </template>
  38. <script setup>
  39. import { ref, computed, onMounted } from "vue";
  40. import { useQuasar } from "quasar";
  41. import FeriadosDialog from "src/pages/dashboard/components/FeriadosDialog.vue";
  42. import { getBaseHolidays } from "src/api/holiday";
  43. const $q = useQuasar();
  44. const now = new Date();
  45. const holidays = ref([]);
  46. function toFrontend(h) {
  47. const [year, month, day] = h.holiday_date.split("-").map(Number);
  48. return { id: h.id, day, month, year, description: h.description, type: h.type };
  49. }
  50. async function loadHolidays() {
  51. try {
  52. const items = await getBaseHolidays();
  53. holidays.value = items.map(toFrontend);
  54. } catch {
  55. holidays.value = [];
  56. }
  57. }
  58. onMounted(loadHolidays);
  59. const currentMonthHolidays = computed(() =>
  60. holidays.value
  61. .filter((h) => h.month === now.getMonth() + 1 && h.year === now.getFullYear())
  62. .sort((a, b) => a.day - b.day),
  63. );
  64. function typeLabel(type) {
  65. return type === "facultativo" ? "Ponto Facultativo" : "Feriado";
  66. }
  67. function openDialog() {
  68. $q.dialog({
  69. component: FeriadosDialog,
  70. componentProps: { initialHolidays: holidays.value },
  71. }).onOk((updated) => {
  72. holidays.value = updated;
  73. });
  74. }
  75. </script>
  76. <style scoped>
  77. .feriados-card {
  78. border-radius: 12px;
  79. padding: 20px 24px;
  80. display: flex;
  81. flex-direction: column;
  82. max-height: 370px;
  83. overflow: hidden;
  84. }
  85. .person-item {
  86. padding-top: 6px;
  87. padding-bottom: 6px;
  88. }
  89. .day-badge {
  90. width: 30px;
  91. height: 30px;
  92. border-radius: 50%;
  93. background-color: #e64a19;
  94. color: #fff;
  95. font-size: 12px;
  96. font-weight: 600;
  97. display: flex;
  98. align-items: center;
  99. justify-content: center;
  100. flex-shrink: 0;
  101. }
  102. </style>