Skip to content

Commit

Permalink
Merge pull request #228 from weni-ai/feature/add-tooltips-human-dashb…
Browse files Browse the repository at this point in the history
…oard

[ENGAGE-2558] add tooltips human dashboard
  • Loading branch information
MarcusviniciusLsantos authored Jan 24, 2025
2 parents 0f64c54 + 5b52bf1 commit f1910a9
Show file tree
Hide file tree
Showing 6 changed files with 230 additions and 70 deletions.
152 changes: 85 additions & 67 deletions src/components/insights/cards/CardDashboard.vue
Original file line number Diff line number Diff line change
@@ -1,78 +1,86 @@
<template>
<CardBase
class="card-dashboard"
:class="{
loading: isLoading,
'not-configured': !configured,
clickable,
}"
<UnnnicToolTip
:data-testid="`card-${id}-tooltip`"
:text="hoverTooltip"
side="right"
maxWidth="200px"
:enabled="!!hoverTooltip"
>
<section class="card__content">
<template v-if="showMetricError">
<CardTitleError />
<p class="content__error">
{{ $t('widgets.card.error_description') }}
</p>
</template>

<section
v-else
class="content-metric"
>
<section class="content-metric__container">
<CardBase
class="card-dashboard"
:class="{
loading: isLoading,
'not-configured': !configured,
clickable,
}"
>
<section class="card__content">
<template v-if="showMetricError">
<CardTitleError />
<p class="content__error">
{{ $t('widgets.card.error_description') }}
</p>
</template>

<section
v-else
class="content-metric"
>
<section class="content-metric__container">
<p
v-if="friendlyEmoji"
class="content-metric__friendly-id"
data-testid="card-dashboard-friendly-id"
>
{{ friendlyEmoji }}
</p>
<IconLoading v-if="isLoading" />
<h1
v-else
class="content-metric__value"
:title="configured ? metric : '0'"
data-testid="card-dashboard-metric-value"
>
{{ configured ? metric : '0' }}
</h1>
</section>
<UnnnicButton
v-if="configurable || !configured"
class="card-dashboard__button-config"
data-testid="card-dashboard-button-config"
type="tertiary"
iconCenter="tune"
@click.stop="$emit('open-config')"
/>
</section>
<section class="content-description">
<p
v-if="friendlyEmoji"
class="content-metric__friendly-id"
data-testid="card-dashboard-friendly-id"
v-if="!showMetricError"
class="content-description__text"
data-testid="card-dashboard-content-description"
:title="
configured ? $t(description) : $t('widgets.card.metric_empty')
"
>
{{ friendlyEmoji }}
{{ configured ? $t(description) : $t('widgets.card.metric_empty') }}
</p>
<IconLoading v-if="isLoading" />
<h1
v-else
class="content-metric__value"
:title="configured ? metric : '0'"
data-testid="card-dashboard-metric-value"
<UnnnicToolTip
v-if="tooltip"
enabled
:text="tooltip"
side="right"
class="content-description__tooltip"
data-testid="content-desciption-tooltip"
>
{{ configured ? metric : '0' }}
</h1>
<UnnnicIcon
icon="info"
size="avatar-nano"
/>
</UnnnicToolTip>
</section>
<UnnnicButton
v-if="configurable || !configured"
class="card-dashboard__button-config"
data-testid="card-dashboard-button-config"
type="tertiary"
iconCenter="tune"
@click.stop="$emit('open-config')"
/>
</section>
<section class="content-description">
<p
v-if="!showMetricError"
class="content-description__text"
data-testid="card-dashboard-content-description"
:title="
configured ? $t(description) : $t('widgets.card.metric_empty')
"
>
{{ configured ? $t(description) : $t('widgets.card.metric_empty') }}
</p>
<UnnnicToolTip
v-if="tooltip"
enabled
:text="tooltip"
side="right"
class="content-description__tooltip"
data-testid="content-desciption-tooltip"
>
<UnnnicIcon
icon="info"
size="avatar-nano"
/>
</UnnnicToolTip>
</section>
</section>
</CardBase>
</CardBase>
</UnnnicToolTip>
</template>

<script>
Expand Down Expand Up @@ -109,6 +117,14 @@ export default {
configured: Boolean,
configurable: Boolean,
isLoading: Boolean,
id: {
type: String,
default: '',
},
hoverTooltip: {
type: String,
default: '',
},
tooltip: {
type: String,
default: '',
Expand All @@ -133,6 +149,8 @@ export default {
<style scoped lang="scss">
.card-dashboard {
padding: $unnnic-spacing-md;
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
Expand Down
32 changes: 32 additions & 0 deletions src/components/insights/widgets/DynamicWidget.vue
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ export default {
configurable: is_configurable,
friendlyId: config?.friendly_id,
tooltip: config?.tooltip ? this.$t(config.tooltip) : '',
hoverTooltip: this.getHoverTooltipData(this.widget),
id: this.widget.uuid,
},
table_dynamic_by_filter: {
headerTitle: tableDynamicFilterConfig?.name_overwrite || name,
Expand Down Expand Up @@ -364,6 +366,36 @@ export default {
}
return (data?.value || 0).toLocaleString(this.$i18n.locale || 'en-US');
},
getHoverTooltipData(widget) {
const isHumanServiceDashboard =
this.currentDashboard.name === 'human_service_dashboard.title';
if (isHumanServiceDashboard && widget.type === 'card') {
const defaultTranslations = (key) => `human_service_dashboard.${key}`;
const getTooltipTranslations = {
in_progress: this.$t('human_service_dashboard.tooltips.in_progress'),
[defaultTranslations('response_time')]: this.$t(
'human_service_dashboard.tooltips.response_time',
),
[defaultTranslations('interaction_time')]: this.$t(
'human_service_dashboard.tooltips.interaction_time',
),
[defaultTranslations('waiting_time')]: this.$t(
'human_service_dashboard.tooltips.waiting_time',
),
[defaultTranslations('awaiting_service')]: this.$t(
'human_service_dashboard.tooltips.awaiting_service',
),
closeds: this.$t('human_service_dashboard.tooltips.closeds'),
};
return getTooltipTranslations[widget.name] || '';
}
return '';
},
},
};
</script>
86 changes: 86 additions & 0 deletions src/components/insights/widgets/__tests__/DynamicWidget.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -605,4 +605,90 @@ describe('DynamicWidget', () => {
});
});
});

describe('getHoverTooltipData method', () => {
beforeEach(() => {
wrapper = createWrapper({
widget: {
type: 'card',
uuid: 'test-uuid',
name: 'in_progress',
},
});

vi.spyOn(wrapper.vm, 'currentDashboard', 'get').mockReturnValue({
name: 'human_service_dashboard.title',
});

wrapper.vm.$t = vi.fn((key) => {
const translations = {
'human_service_dashboard.tooltips.in_progress': 'In Progress Tooltip',
'human_service_dashboard.tooltips.response_time':
'Response Time Tooltip',
'human_service_dashboard.tooltips.interaction_time':
'Interaction Time Tooltip',
'human_service_dashboard.tooltips.waiting_time':
'Waiting Time Tooltip',
'human_service_dashboard.tooltips.awaiting_service':
'Awaiting Service Tooltip',
'human_service_dashboard.tooltips.closeds': 'Closed Tooltip',
};
return translations[key] || key;
});
});

it('should return tooltip for human service dashboard card', () => {
const result = wrapper.vm.getHoverTooltipData(wrapper.vm.widget);

expect(result).toBe('In Progress Tooltip');
});

it('should return empty string for non-human service dashboard', () => {
vi.spyOn(wrapper.vm, 'currentDashboard', 'get').mockReturnValue({
name: 'other_dashboard',
});

const result = wrapper.vm.getHoverTooltipData(wrapper.vm.widget);

expect(result).toBe('');
});

it('should return empty string for non-card widget types', () => {
wrapper.vm.currentDashboard = { name: 'human_service_dashboard.title' };
wrapper.vm.widget.type = 'graph';

const result = wrapper.vm.getHoverTooltipData(wrapper.vm.widget);

expect(result).toBe('');
});

it('should return tooltip for other human service dashboard card names', () => {
wrapper.vm.currentDashboard = { name: 'human_service_dashboard.title' };
const testCases = [
{
name: 'human_service_dashboard.response_time',
expected: 'Response Time Tooltip',
},
{
name: 'human_service_dashboard.interaction_time',
expected: 'Interaction Time Tooltip',
},
{
name: 'human_service_dashboard.waiting_time',
expected: 'Waiting Time Tooltip',
},
{
name: 'human_service_dashboard.awaiting_service',
expected: 'Awaiting Service Tooltip',
},
{ name: 'closeds', expected: 'Closed Tooltip' },
];

testCases.forEach(({ name, expected }) => {
wrapper.vm.widget.name = name;
const result = wrapper.vm.getHoverTooltipData(wrapper.vm.widget);
expect(result).toBe(expected);
});
});
});
});
10 changes: 9 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@
"response_time": "Response time",
"waiting_time": "Waiting time",
"awaiting_service": "Waiting for service",
"interaction_time": "Interaction time"
"interaction_time": "Interaction time",
"tooltips": {
"in_progress": "Total number of chats currently being handled.",
"response_time": "Average time the contact waits to receive a reply to each message.",
"interaction_time": "Average duration of completed chats. ",
"waiting_time": "The average time contacts spend waiting for their chats to be initiated.",
"awaiting_service": "The number of contacts waiting for an agent to initiate the chat.",
"closeds": "Total number of chats that have been completed."
}
},
"table_dynamic_by_filter": {
"status": "Status",
Expand Down
10 changes: 9 additions & 1 deletion src/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@
"response_time": "Tiempo de respuesta",
"waiting_time": "Tiempo de espera",
"awaiting_service": "Esperando atención",
"interaction_time": "Tiempo de interacción"
"interaction_time": "Tiempo de interacción",
"tooltips": {
"in_progress": "Número total de chats que se están respondiendo actualmente.",
"response_time": "Tiempo medio que espera el contacto para recibir una respuesta a cada mensaje.",
"interaction_time": "Duración media total de las llamadas.",
"waiting_time": "Tiempo medio que los contactos esperan a que se inicie el servicio.",
"awaiting_service": "Número de contactos que esperan a que se inicie el servicio.",
"closeds": "Número total de chats que ya han finalizado."
}
},
"table_dynamic_by_filter": {
"status": "Status",
Expand Down
10 changes: 9 additions & 1 deletion src/locales/pt_br.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@
"response_time": "Tempo de resposta",
"waiting_time": "Tempo de espera",
"awaiting_service": "Aguardando atendimento",
"interaction_time": "Tempo de interação"
"interaction_time": "Tempo de interação",
"tooltips": {
"in_progress": "Total de chats sendo atendidos no momento.",
"response_time": "Média de tempo que o contato espera para receber uma resposta para cada mensagem.",
"interaction_time": "Tempo médio de duração total dos atendimentos. ",
"waiting_time": "Média de tempo que contatos aguardam até o início do atendimento.",
"awaiting_service": "Número de contatos aguardando início do atendimento.",
"closeds": "Total de chats que já foram finalizados."
}
},
"table_dynamic_by_filter": {
"status": "Status",
Expand Down

0 comments on commit f1910a9

Please sign in to comment.