ClassEventCard.vue 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. <template>
  2. <div
  3. class="class-event-card"
  4. :class="{ 'class-event-card--compact': compact }"
  5. @click.stop="$emit('click', classItem)"
  6. >
  7. <div class="class-event-card__title">{{ classItem.title }}</div>
  8. <div class="class-event-card__row">
  9. <q-icon name="mdi-map-marker-outline" size="14px" />
  10. <span>{{ classItem.room }}</span>
  11. </div>
  12. <div class="class-event-card__row">
  13. <q-icon name="mdi-account-outline" size="14px" />
  14. <span>{{ classItem.instructor }}</span>
  15. </div>
  16. <div class="class-event-card__row">
  17. <q-icon name="mdi-clock-outline" size="14px" />
  18. <span>{{ timeRange }}</span>
  19. </div>
  20. <div class="class-event-card__row">
  21. <q-icon name="mdi-account-group-outline" size="14px" />
  22. <span>{{ enrollment }}</span>
  23. </div>
  24. </div>
  25. </template>
  26. <script setup>
  27. import { computed } from "vue";
  28. import { format, parseISO } from "date-fns";
  29. const props = defineProps({
  30. classItem: { type: Object, required: true },
  31. compact: { type: Boolean, default: false },
  32. });
  33. defineEmits(["click"]);
  34. const timeRange = computed(() => {
  35. const start = format(parseISO(props.classItem.date_time_start), "HH:mm");
  36. const end = format(parseISO(props.classItem.date_time_end), "HH:mm");
  37. return `${start} - ${end}`;
  38. });
  39. const enrollment = computed(() => {
  40. const pad = (n) => String(n ?? 0).padStart(2, "0");
  41. // presentes / total de alunos com contrato ativo no pacote
  42. return `${pad(props.classItem.present_count)}/${pad(props.classItem.students_count)}`;
  43. });
  44. </script>
  45. <style scoped>
  46. .class-event-card {
  47. background: #ffffff;
  48. border-radius: 8px;
  49. padding: 8px 10px;
  50. box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
  51. cursor: pointer;
  52. display: flex;
  53. flex-direction: column;
  54. align-items: center;
  55. gap: 3px;
  56. transition: box-shadow 0.18s ease, transform 0.18s ease;
  57. }
  58. .class-event-card:hover {
  59. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
  60. transform: translateY(-1px);
  61. }
  62. .class-event-card__title {
  63. font-size: 12px;
  64. font-weight: 600;
  65. color: #003e29;
  66. text-align: center;
  67. line-height: 1.15;
  68. margin-bottom: 2px;
  69. }
  70. .class-event-card__row {
  71. display: flex;
  72. align-items: center;
  73. gap: 5px;
  74. font-size: 11px;
  75. color: #505050;
  76. align-self: flex-start;
  77. }
  78. .class-event-card__row .q-icon {
  79. color: #ff8340;
  80. flex-shrink: 0;
  81. }
  82. .class-event-card--compact {
  83. padding: 6px 8px;
  84. }
  85. .class-event-card--compact .class-event-card__title {
  86. font-size: 11px;
  87. }
  88. .class-event-card--compact .class-event-card__row {
  89. font-size: 10px;
  90. }
  91. </style>