diff --git a/app/javascript/dashboard/api/liveReports.js b/app/javascript/dashboard/api/liveReports.js new file mode 100644 index 000000000..1435da258 --- /dev/null +++ b/app/javascript/dashboard/api/liveReports.js @@ -0,0 +1,20 @@ +/* global axios */ +import ApiClient from './ApiClient'; + +class LiveReportsAPI extends ApiClient { + constructor() { + super('live_reports', { accountScoped: true, apiVersion: 'v2' }); + } + + getConversationMetric(params = {}) { + return axios.get(`${this.url}/conversation_metrics`, { params }); + } + + getGroupedConversations({ groupBy } = { groupBy: 'assignee_id' }) { + return axios.get(`${this.url}/grouped_conversation_metrics`, { + params: { group_by: groupBy }, + }); + } +} + +export default new LiveReportsAPI(); diff --git a/app/javascript/dashboard/components-next/dropdown-menu/DropdownMenu.vue b/app/javascript/dashboard/components-next/dropdown-menu/DropdownMenu.vue index 95b368dae..4e3b96259 100644 --- a/app/javascript/dashboard/components-next/dropdown-menu/DropdownMenu.vue +++ b/app/javascript/dashboard/components-next/dropdown-menu/DropdownMenu.vue @@ -29,6 +29,10 @@ const props = defineProps({ type: Boolean, default: false, }, + labelClass: { + type: String, + default: '', + }, }); const emit = defineEmits(['action']); @@ -97,9 +101,13 @@ onMounted(() => { {{ item.emoji }} - {{ - item.label - }} + + {{ item.label }} +
-import { mapGetters } from 'vuex'; -import AgentTable from './components/overview/AgentTable.vue'; -import MetricCard from './components/overview/MetricCard.vue'; -import { OVERVIEW_METRICS } from './constants'; - -import endOfDay from 'date-fns/endOfDay'; -import getUnixTime from 'date-fns/getUnixTime'; + diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/components/AgentLiveReportContainer.vue b/app/javascript/dashboard/routes/dashboard/settings/reports/components/AgentLiveReportContainer.vue new file mode 100644 index 000000000..e274e4fe2 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/reports/components/AgentLiveReportContainer.vue @@ -0,0 +1,36 @@ + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/components/StatsLiveReportsContainer.vue b/app/javascript/dashboard/routes/dashboard/settings/reports/components/StatsLiveReportsContainer.vue new file mode 100644 index 000000000..8a3ee5ecd --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/reports/components/StatsLiveReportsContainer.vue @@ -0,0 +1,142 @@ + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/components/TeamLiveReportContainer.vue b/app/javascript/dashboard/routes/dashboard/settings/reports/components/TeamLiveReportContainer.vue new file mode 100644 index 000000000..c72d0dd96 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/reports/components/TeamLiveReportContainer.vue @@ -0,0 +1,36 @@ + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/components/overview/AgentTable.vue b/app/javascript/dashboard/routes/dashboard/settings/reports/components/overview/AgentTable.vue index fb470d8fc..42ca08582 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/reports/components/overview/AgentTable.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/reports/components/overview/AgentTable.vue @@ -4,6 +4,7 @@ import { useVueTable, createColumnHelper, getCoreRowModel, + getPaginationRowModel, } from '@tanstack/vue-table'; import { useI18n } from 'vue-i18n'; @@ -13,7 +14,7 @@ import Table from 'dashboard/components/table/Table.vue'; import Pagination from 'dashboard/components/table/Pagination.vue'; import AgentCell from './AgentCell.vue'; -const { agents, agentMetrics, pageIndex } = defineProps({ +const { agents, agentMetrics } = defineProps({ agents: { type: Array, default: () => [], @@ -26,42 +27,45 @@ const { agents, agentMetrics, pageIndex } = defineProps({ type: Boolean, default: false, }, - pageIndex: { - type: Number, - default: 1, - }, }); -const emit = defineEmits(['pageChange']); const { t } = useI18n(); -function getAgentInformation(id) { - return agents?.find(agent => agent.id === Number(id)); -} +const getAgentMetrics = id => + agentMetrics.find(metrics => metrics.assignee_id === Number(id)) || {}; -const totalCount = computed(() => agents.length); - -const tableData = computed(() => { - return agentMetrics - .filter(agentMetric => getAgentInformation(agentMetric.id)) +const tableData = computed(() => + agents .map(agent => { - const agentInformation = getAgentInformation(agent.id); + const metric = getAgentMetrics(agent.id); return { - agent: agentInformation.name || agentInformation.available_name, - email: agentInformation.email, - thumbnail: agentInformation.thumbnail, - open: agent.metric.open ?? 0, - unattended: agent.metric.unattended ?? 0, - status: agentInformation.availability_status, + agent: agent.available_name || agent.name, + email: agent.email, + thumbnail: agent.thumbnail, + open: metric.open || 0, + unattended: metric.unattended || 0, + status: agent.availability_status, }; - }); -}); + }) + .sort((a, b) => { + // First sort by open tickets (descending) + const openDiff = b.open - a.open; + // If open tickets are equal, sort by name (ascending) + if (openDiff === 0) { + return a.agent.localeCompare(b.agent); + } + return openDiff; + }) +); const defaulSpanRender = cellProps => h( 'span', + { - class: cellProps.getValue() ? '' : 'text-slate-300 dark:text-slate-700', + class: cellProps.getValue() + ? 'capitalize text-n-slate-12' + : 'capitalize text-n-slate-11', }, cellProps.getValue() ? cellProps.getValue() : '---' ); @@ -86,100 +90,33 @@ const columns = [ }), ]; -const paginationParams = computed(() => { - return { - pageIndex: pageIndex, - pageSize: 25, - }; -}); - const table = useVueTable({ get data() { return tableData.value; }, columns, - manualPagination: true, enableSorting: false, getCoreRowModel: getCoreRowModel(), - get rowCount() { - return totalCount.value; - }, - state: { - get pagination() { - return paginationParams.value; - }, - }, - onPaginationChange: updater => { - const newPagintaion = updater(paginationParams.value); - emit('pageChange', newPagintaion.pageIndex); - }, + getPaginationRowModel: getPaginationRowModel(), }); - - diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/components/overview/MetricCard.vue b/app/javascript/dashboard/routes/dashboard/settings/reports/components/overview/MetricCard.vue index 8c83d56af..02ada6ccf 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/reports/components/overview/MetricCard.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/reports/components/overview/MetricCard.vue @@ -19,7 +19,7 @@ defineProps({