KanbanCard.vue 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. <template>
  2. <q-card
  3. class="kanban-card cursor-pointer"
  4. :style="{ borderLeft: `4px solid ${phaseColor}` }"
  5. @click="$emit('edit', card)"
  6. >
  7. <!-- Header: Creator name + Priority badge -->
  8. <div class="row items-center justify-between q-px-md q-pt-md">
  9. <span class="text-body2 text-weight-medium text-grey-8 ellipsis" style="max-width: 60%">
  10. {{ card.created_by_user_name ?? '—' }}
  11. </span>
  12. <q-badge
  13. :color="priorityColor"
  14. :label="priorityLabel"
  15. style="padding: 4px 8px; font-size: 11px"
  16. />
  17. </div>
  18. <!-- Unit name of responsible -->
  19. <div class="q-px-md q-mt-xs text-caption text-grey-6">
  20. {{ card.applicant_unit_name ?? 'Matriz' }}
  21. </div>
  22. <!-- Description truncated -->
  23. <div
  24. v-if="card.description"
  25. class="q-px-md q-mt-sm text-body2 text-grey-7"
  26. style="line-height: 1.4"
  27. >
  28. {{ truncated }}
  29. </div>
  30. <!-- Footer: Sector + Comments count -->
  31. <div class="row items-center justify-between q-px-md q-pb-md q-mt-sm">
  32. <span class="text-caption text-grey-6">{{ card.sector ?? '—' }}</span>
  33. <div class="row items-center" style="gap: 4px">
  34. <q-icon name="mdi-comment-outline" color="grey-5" size="16px" />
  35. <span class="text-caption text-grey-6">{{ card.replies_count ?? 0 }}</span>
  36. </div>
  37. </div>
  38. </q-card>
  39. </template>
  40. <script setup>
  41. import { computed } from "vue";
  42. defineEmits(["edit"]);
  43. const { card } = defineProps({
  44. card: {
  45. type: Object,
  46. required: true,
  47. },
  48. });
  49. const truncated = computed(() => {
  50. const desc = card.description ?? "";
  51. return desc.length > 50 ? desc.slice(0, 50) + "…" : desc;
  52. });
  53. const priorityColor = computed(() => {
  54. const map = { alta: "negative", normal: "warning", baixa: "positive" };
  55. return map[card.priority] ?? "grey";
  56. });
  57. const priorityLabel = computed(() => {
  58. const map = { alta: "Alta", normal: "Normal", baixa: "Baixa" };
  59. return map[card.priority] ?? card.priority;
  60. });
  61. const phaseColor = computed(() => {
  62. const map = {
  63. a_fazer: "#9E9E9E",
  64. em_progresso: "#1976D2",
  65. em_revisao: "#FF9800",
  66. concluido: "#4CAF50",
  67. demandas_especiais: "#FFC107",
  68. };
  69. return map[card.phase] ?? "#9E9E9E";
  70. });
  71. </script>
  72. <style scoped>
  73. .kanban-card {
  74. border-radius: 10px;
  75. transition: box-shadow 0.2s;
  76. }
  77. .kanban-card:hover {
  78. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
  79. }
  80. </style>