MediaTab.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. <template>
  2. <div>
  3. <DefaultTable
  4. v-model:rows="rows"
  5. :columns="columns"
  6. no-api-call
  7. add-item
  8. :show-search-field="false"
  9. hide-no-data-label
  10. @on-add-item="openAddDialog"
  11. >
  12. <template #body-cell-item="{ rowIndex }">
  13. <q-td>{{ rowIndex + 1 }}</q-td>
  14. </template>
  15. <template #body-cell-type="{ row }">
  16. <q-td>
  17. <q-badge
  18. :color="row.type === 'contract' ? 'info' : 'primary'"
  19. :label="row.type === 'contract' ? 'Contrato' : 'Mídia'"
  20. />
  21. </q-td>
  22. </template>
  23. <template #body-cell-name="{ row }">
  24. <q-td>{{ row.name ?? '—' }}</q-td>
  25. </template>
  26. <template #body-cell-actions="{ row }">
  27. <q-btn
  28. flat
  29. round
  30. dense
  31. icon="mdi-eye-outline"
  32. class="q-mr-xs"
  33. :disable="!row.file_url"
  34. @click.stop="openFile(row.file_url)"
  35. />
  36. <q-btn
  37. v-if="row.type !== 'contract'"
  38. flat
  39. round
  40. dense
  41. icon="mdi-file-edit-outline"
  42. class="q-mr-xs"
  43. @click.stop="openEditDialog(row)"
  44. />
  45. <q-btn
  46. flat
  47. round
  48. dense
  49. icon="mdi-trash-can-outline"
  50. @click.stop="confirmDelete(row)"
  51. />
  52. </template>
  53. </DefaultTable>
  54. </div>
  55. </template>
  56. <script setup>
  57. import { ref, onMounted } from "vue";
  58. import { useQuasar } from "quasar";
  59. import DefaultTable from "src/components/defaults/DefaultTable.vue";
  60. import AddStudentMediaDialog from "src/pages/students/components/AddStudentMediaDialog.vue";
  61. import EditStudentMediaDialog from "src/pages/students/components/EditStudentMediaDialog.vue";
  62. import { getStudentMedias, deleteStudentMedia } from "src/api/student_media";
  63. const props = defineProps({
  64. studentId: { type: Number, required: true },
  65. });
  66. const $q = useQuasar();
  67. const rows = ref([]);
  68. const columns = [
  69. { name: "item", label: "Item", field: "id", align: "left" },
  70. { name: "date", label: "Data", field: "created_at", align: "left" },
  71. { name: "type", label: "Tipo", field: "type", align: "left" },
  72. { name: "name", label: "Nome", field: "name", align: "left" },
  73. { name: "actions", label: "Ações", field: null, align: "right" },
  74. ];
  75. async function fetchMedias() {
  76. try {
  77. rows.value = await getStudentMedias(props.studentId);
  78. } catch (e) {
  79. console.error(e);
  80. }
  81. }
  82. function openAddDialog() {
  83. $q.dialog({
  84. component: AddStudentMediaDialog,
  85. componentProps: { studentId: props.studentId },
  86. }).onOk((result) => {
  87. rows.value.unshift(result);
  88. });
  89. }
  90. function openEditDialog(row) {
  91. $q.dialog({
  92. component: EditStudentMediaDialog,
  93. componentProps: { media: row },
  94. }).onOk((updated) => {
  95. const index = rows.value.findIndex((r) => r.id === updated.id);
  96. if (index !== -1) rows.value[index] = updated;
  97. });
  98. }
  99. function openFile(url) {
  100. window.open(url, "_blank");
  101. }
  102. function confirmDelete(row) {
  103. $q.dialog({
  104. title: "Remover mídia",
  105. message: `Deseja remover "${row.name}"?`,
  106. ok: { color: "negative", label: "Remover" },
  107. cancel: { color: "primary", outline: true, label: "Cancelar" },
  108. }).onOk(async () => {
  109. try {
  110. await deleteStudentMedia(row.id);
  111. rows.value = rows.value.filter((r) => r.id !== row.id);
  112. } catch (e) {
  113. console.error(e);
  114. }
  115. });
  116. }
  117. onMounted(fetchMedias);
  118. defineExpose({ refresh: fetchMedias });
  119. </script>