SupportRequestsPage.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. <template>
  2. <div>
  3. <DefaultHeaderPage />
  4. <div>
  5. <div class="row q-px-sm q-mb-sm">
  6. <q-select
  7. v-model="statusFilter"
  8. :options="statusOptions"
  9. :label="$t('support_request.fields.status')"
  10. emit-value
  11. map-options
  12. dense
  13. outlined
  14. clearable
  15. style="min-width: 220px"
  16. />
  17. </div>
  18. <DefaultTableServerSide
  19. :key="statusFilter ?? 'all'"
  20. ref="tableRef"
  21. :columns="columns"
  22. :api-call="apiCall"
  23. :add-item="false"
  24. :rows-per-page="10"
  25. open-item
  26. @on-row-click="onRowClick"
  27. >
  28. <template #body-cell-status="slotProps">
  29. <q-td :props="slotProps">
  30. <q-badge :color="statusColor(slotProps.row.status)" :label="statusLabel(slotProps.row.status)" />
  31. </q-td>
  32. </template>
  33. </DefaultTableServerSide>
  34. </div>
  35. </div>
  36. </template>
  37. <script setup>
  38. import { defineAsyncComponent, useTemplateRef, computed, ref } from "vue";
  39. import { useQuasar } from "quasar";
  40. import { useI18n } from "vue-i18n";
  41. import { getSupportRequests } from "src/api/supportRequest";
  42. import DefaultTableServerSide from "src/components/defaults/DefaultTableServerSide.vue";
  43. import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.vue";
  44. const SupportRequestDetailDialog = defineAsyncComponent(() =>
  45. import("src/pages/supportRequest/components/SupportRequestDetailDialog.vue")
  46. );
  47. const $q = useQuasar();
  48. const tableRef = useTemplateRef("tableRef");
  49. const { t } = useI18n();
  50. const statusFilter = ref(null);
  51. const apiCall = (params) => getSupportRequests({ ...params, status: statusFilter.value });
  52. const statusOptions = computed(() => [
  53. { label: t("support_request.status.pending"), value: "pending" },
  54. { label: t("support_request.status.in_progress"), value: "in_progress" },
  55. { label: t("support_request.status.resolved"), value: "resolved" },
  56. ]);
  57. const categoryLabel = (category) => t(`support_request.categories.${category}`, category);
  58. const statusLabel = (status) => t(`support_request.status.${status}`, status);
  59. const userTypeLabel = (type) =>
  60. type ? t(`support_request.user_types.${type.toLowerCase()}`, type) : "—";
  61. const statusColor = (status) =>
  62. ({ pending: "orange", in_progress: "blue", resolved: "green" }[status] || "grey");
  63. const columns = computed(() => [
  64. {
  65. name: "title",
  66. label: t("support_request.fields.title"),
  67. field: "title",
  68. align: "left",
  69. sortable: false,
  70. },
  71. {
  72. name: "category",
  73. label: t("support_request.fields.category"),
  74. field: (row) => categoryLabel(row.category),
  75. align: "left",
  76. sortable: false,
  77. },
  78. {
  79. name: "name",
  80. label: t("support_request.fields.name"),
  81. field: "name",
  82. align: "left",
  83. sortable: false,
  84. },
  85. {
  86. name: "user_type",
  87. label: t("support_request.fields.user_type"),
  88. field: (row) => userTypeLabel(row.user_type),
  89. align: "left",
  90. sortable: false,
  91. },
  92. {
  93. name: "status",
  94. label: t("support_request.fields.status"),
  95. field: (row) => statusLabel(row.status),
  96. align: "left",
  97. sortable: false,
  98. },
  99. {
  100. name: "created_at",
  101. label: t("common.terms.created_at"),
  102. field: "created_at",
  103. align: "left",
  104. sortable: false,
  105. },
  106. ]);
  107. const onRowClick = ({ row }) => {
  108. $q.dialog({
  109. component: SupportRequestDetailDialog,
  110. componentProps: {
  111. supportRequest: row,
  112. },
  113. }).onOk(async (updated) => {
  114. if (updated) {
  115. tableRef.value.refresh();
  116. }
  117. });
  118. };
  119. </script>