iachat/app/javascript/dashboard/routes/dashboard/settings/reports/Index.vue
2022-03-14 18:15:27 +05:30

204 lines
6.0 KiB
Vue

<template>
<div class="column content-box">
<woot-button
color-scheme="success"
class-names="button--fixed-right-top"
icon="arrow-download"
@click="downloadAgentReports"
>
{{ $t('REPORT.DOWNLOAD_AGENT_REPORTS') }}
</woot-button>
<report-filter-selector
group-by-filter
:selected-group-by-filter="selectedGroupByFilter"
:filter-items-list="filterItemsList"
@date-range-change="onDateRangeChange"
@filter-change="onFilterChange"
/>
<div class="row">
<woot-report-stats-card
v-for="(metric, index) in metrics"
:key="metric.NAME"
:desc="metric.DESC"
:heading="metric.NAME"
:index="index"
:on-click="changeSelection"
:point="displayMetric(metric.KEY)"
:trend="calculateTrend(metric.KEY)"
:selected="index === currentSelection"
/>
</div>
<div class="report-bar">
<woot-loading-state
v-if="accountReport.isFetching"
:message="$t('REPORT.LOADING_CHART')"
/>
<div v-else class="chart-container">
<woot-bar v-if="accountReport.data.length" :collection="collection" />
<span v-else class="empty-state">
{{ $t('REPORT.NO_ENOUGH_DATA') }}
</span>
</div>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import fromUnixTime from 'date-fns/fromUnixTime';
import format from 'date-fns/format';
import ReportFilterSelector from './components/FilterSelector';
import { GROUP_BY_FILTER } from './constants';
import reportMixin from '../../../../mixins/reportMixin';
const REPORTS_KEYS = {
CONVERSATIONS: 'conversations_count',
INCOMING_MESSAGES: 'incoming_messages_count',
OUTGOING_MESSAGES: 'outgoing_messages_count',
FIRST_RESPONSE_TIME: 'avg_first_response_time',
RESOLUTION_TIME: 'avg_resolution_time',
RESOLUTION_COUNT: 'resolutions_count',
};
export default {
components: {
ReportFilterSelector,
},
mixins: [reportMixin],
data() {
return {
from: 0,
to: 0,
currentSelection: 0,
groupBy: GROUP_BY_FILTER[1],
filterItemsList: this.$t('REPORT.GROUP_BY_DAY_OPTIONS'),
selectedGroupByFilter: {},
};
},
computed: {
...mapGetters({
accountSummary: 'getAccountSummary',
accountReport: 'getAccountReports',
}),
collection() {
if (this.accountReport.isFetching) {
return {};
}
if (!this.accountReport.data.length) return {};
const labels = this.accountReport.data.map(element => {
if (this.groupBy.period === GROUP_BY_FILTER[2].period) {
let week_date = new Date(fromUnixTime(element.timestamp));
const first_day = week_date.getDate() - week_date.getDay();
const last_day = first_day + 6;
const week_first_date = new Date(week_date.setDate(first_day));
const week_last_date = new Date(week_date.setDate(last_day));
return `${format(week_first_date, 'dd/MM/yy')} - ${format(
week_last_date,
'dd/MM/yy'
)}`;
}
if (this.groupBy.period === GROUP_BY_FILTER[3].period) {
return format(fromUnixTime(element.timestamp), 'MMM-yyyy');
}
if (this.groupBy.period === GROUP_BY_FILTER[4].period) {
return format(fromUnixTime(element.timestamp), 'yyyy');
}
return format(fromUnixTime(element.timestamp), 'dd-MMM-yyyy');
});
const data = this.accountReport.data.map(element => element.value);
return {
labels,
datasets: [
{
label: this.metrics[this.currentSelection].NAME,
backgroundColor: '#1f93ff',
data,
},
],
};
},
metrics() {
const reportKeys = [
'CONVERSATIONS',
'INCOMING_MESSAGES',
'OUTGOING_MESSAGES',
'FIRST_RESPONSE_TIME',
'RESOLUTION_TIME',
'RESOLUTION_COUNT',
];
return reportKeys.map(key => ({
NAME: this.$t(`REPORT.METRICS.${key}.NAME`),
KEY: REPORTS_KEYS[key],
DESC: this.$t(`REPORT.METRICS.${key}.DESC`),
}));
},
},
methods: {
fetchAllData() {
const { from, to, groupBy } = this;
this.$store.dispatch('fetchAccountSummary', {
from,
to,
groupBy: groupBy.period,
});
this.fetchChartData();
},
fetchChartData() {
const { from, to, groupBy } = this;
this.$store.dispatch('fetchAccountReport', {
metric: this.metrics[this.currentSelection].KEY,
from,
to,
groupBy: groupBy.period,
});
},
downloadAgentReports() {
const { from, to } = this;
const fileName = `agent-report-${format(
fromUnixTime(to),
'dd-MM-yyyy'
)}.csv`;
this.$store.dispatch('downloadAgentReports', { from, to, fileName });
},
changeSelection(index) {
this.currentSelection = index;
this.fetchChartData();
},
onDateRangeChange({ from, to, groupBy }) {
this.from = from;
this.to = to;
this.filterItemsList = this.fetchFilterItems(groupBy);
const filterItems = this.filterItemsList.filter(
item => item.id === this.groupBy.id
);
if (filterItems.length > 0) {
this.selectedGroupByFilter = filterItems[0];
} else {
this.selectedGroupByFilter = this.filterItemsList[0];
this.groupBy = GROUP_BY_FILTER[this.selectedGroupByFilter.id];
}
this.fetchAllData();
},
onFilterChange(payload) {
this.groupBy = GROUP_BY_FILTER[payload.id];
this.fetchAllData();
},
fetchFilterItems(group_by) {
switch (group_by) {
case GROUP_BY_FILTER[2].period:
return this.$t('REPORT.GROUP_BY_WEEK_OPTIONS');
case GROUP_BY_FILTER[3].period:
return this.$t('REPORT.GROUP_BY_MONTH_OPTIONS');
case GROUP_BY_FILTER[4].period:
return this.$t('REPORT.GROUP_BY_YEAR_OPTIONS');
default:
return this.$t('REPORT.GROUP_BY_DAY_OPTIONS');
}
},
},
};
</script>