NotificacoesAssociadoPage.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <template>
  2. <div>
  3. <DefaultHeaderPage />
  4. <div v-if="loading" class="flex flex-center q-pa-xl">
  5. <q-spinner color="violet-normal" size="50px" />
  6. </div>
  7. <div
  8. v-else-if="notifications.length === 0"
  9. class="flex flex-center q-pa-xl text-grey-6"
  10. >
  11. {{ $t("notification.empty") }}
  12. </div>
  13. <div v-else class="q-gutter-md">
  14. <q-card
  15. v-for="item in notifications"
  16. :key="item.id"
  17. flat
  18. bordered
  19. class="notificacoes-card"
  20. :class="{ 'not-read': !item.read }"
  21. @click="onRead(item)"
  22. >
  23. <q-card-section horizontal>
  24. <!-- IMAGEM -->
  25. <div
  26. v-if="item.notification?.media?.length"
  27. class="notification-image-container"
  28. >
  29. <img
  30. :src="item.notification.media[0].url"
  31. class="notification-image"
  32. />
  33. </div>
  34. <!-- ICONE -->
  35. <q-card-section
  36. v-else
  37. class="flex items-center q-pa-md"
  38. >
  39. <q-icon
  40. name="mdi-bell-outline"
  41. size="28px"
  42. :color="item.read ? 'grey-5' : 'violet-normal'"
  43. />
  44. </q-card-section>
  45. <!-- CONTEUDO -->
  46. <q-card-section class="flex-grow q-pa-md">
  47. <div class="row items-start justify-between">
  48. <div
  49. class="text-weight-bold"
  50. :class="item.read ? 'text-grey-7' : 'text-violet-normal'"
  51. >
  52. {{ item.notification?.title }}
  53. </div>
  54. <q-badge
  55. v-if="!item.read"
  56. color="violet-normal"
  57. rounded
  58. />
  59. </div>
  60. <div class="text-caption text-grey-7 q-mt-xs">
  61. {{ item.notification?.message }}
  62. </div>
  63. <div class="text-caption text-grey-5 q-mt-sm">
  64. {{ item.created_at }}
  65. </div>
  66. </q-card-section>
  67. </q-card-section>
  68. </q-card>
  69. </div>
  70. </div>
  71. </template>
  72. <script setup>
  73. import { ref, onMounted } from "vue";
  74. import {getMyNotifications,markNotificationAsRead} from "src/api/notification";
  75. import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.vue";
  76. const loading = ref(true);
  77. const notifications = ref([]);
  78. const onRead = async (item) => {
  79. if (item.read) return;
  80. try {
  81. await markNotificationAsRead(item.id);
  82. item.read = true;
  83. } catch (e) {
  84. console.error(e);
  85. }
  86. };
  87. onMounted(async () => {
  88. try {
  89. notifications.value = await getMyNotifications();
  90. } catch (e) {
  91. console.error(e);
  92. } finally {
  93. loading.value = false;
  94. }
  95. });
  96. </script>
  97. <style scoped lang="scss">
  98. .notificacoes-card {
  99. border-radius: 12px;
  100. cursor: pointer;
  101. transition: all 0.2s;
  102. overflow: hidden;
  103. &:hover {
  104. background: #f5eef7;
  105. transform: translateY(-1px);
  106. }
  107. &.not-read {
  108. border-left: 4px solid #7b2d97;
  109. }
  110. }
  111. .notification-image-container {
  112. width: 140px;
  113. min-width: 140px;
  114. height: 140px;
  115. overflow: hidden;
  116. background: #f3edf5;
  117. }
  118. .notification-image {
  119. width: 100%;
  120. height: 100%;
  121. object-fit: cover;
  122. }
  123. </style>