diff --git a/DSL/Resql/feedback-chats-with-negative-feedback.sql b/DSL/Resql/feedback-chats-with-negative-feedback.sql index 5ba167ec..8598050a 100644 --- a/DSL/Resql/feedback-chats-with-negative-feedback.sql +++ b/DSL/Resql/feedback-chats-with-negative-feedback.sql @@ -1,41 +1,62 @@ WITH n_chats AS ( - SELECT + SELECT + base_id, + MAX(created) AS created + FROM chat + WHERE STATUS = 'ENDED' + AND created::date BETWEEN :start::date AND :end::date + AND feedback_rating IS NOT NULL + AND feedback_rating <= 5 +GROUP BY base_id + ), + c_chat AS ( +SELECT base_id, - MAX(created) AS created - FROM chat - WHERE STATUS = 'ENDED' - AND created::date BETWEEN :start::date AND :end::date - AND feedback_rating IS NOT NULL - AND feedback_rating <= 5 - GROUP BY base_id -), -c_chat AS ( - SELECT base_id, MIN(created) AS created, MAX(ended) AS ended - FROM chat - GROUP BY base_id -) -SELECT n_chats.base_id, - c_chat.created, - c_chat.ended, - chat.feedback_rating AS rating, - chat.feedback_text AS feedback, - CEIL(COUNT(*) OVER() / :page_size::DECIMAL) AS total_pages +FROM chat +GROUP BY base_id + ), + deduplicated_users AS ( +SELECT + id_code, + first_name, + last_name +FROM ( + SELECT + id_code, + first_name, + last_name, + ROW_NUMBER() OVER (PARTITION BY id_code ORDER BY first_name, last_name) AS row_num + FROM "user" + ) AS ranked_users +WHERE row_num = 1 + ) +SELECT + n_chats.base_id, + c_chat.created, + c_chat.ended, + chat.feedback_rating AS rating, + chat.feedback_text AS feedback, + deduplicated_users.first_name AS first_name, + deduplicated_users.last_name AS last_name, + CEIL(COUNT(*) OVER() / :page_size::DECIMAL) AS total_pages FROM n_chats -LEFT JOIN chat ON n_chats.base_id = chat.base_id -JOIN c_chat ON c_chat.base_id = chat.base_id AND n_chats.created = chat.created + LEFT JOIN chat ON n_chats.base_id = chat.base_id + LEFT JOIN c_chat ON c_chat.base_id = chat.base_id AND n_chats.created = chat.created + LEFT JOIN deduplicated_users ON chat.customer_support_id = deduplicated_users.id_code WHERE chat.feedback_rating IS NOT NULL -AND chat.ended IS NOT NULL -ORDER BY - CASE WHEN :sorting = 'created desc' THEN n_chats.created END DESC, - CASE WHEN :sorting = 'created asc' THEN n_chats.created END ASC, - CASE WHEN :sorting = 'ended desc' THEN n_chats.created END DESC, - CASE WHEN :sorting = 'ended asc' THEN n_chats.created END ASC, - CASE WHEN :sorting = 'base_id desc' THEN n_chats.base_id END DESC, - CASE WHEN :sorting = 'base_id asc' THEN n_chats.base_id END ASC, - CASE WHEN :sorting = 'feedback desc' THEN feedback_text END DESC, - CASE WHEN :sorting = 'feedback asc' THEN feedback_text END ASC, - CASE WHEN :sorting = 'rating desc' THEN feedback_rating END DESC, - CASE WHEN :sorting = 'rating asc' THEN feedback_rating END ASC -OFFSET ((GREATEST(:page, 1) - 1) * :page_size) LIMIT :page_size; + AND chat.ended IS NOT NULL +ORDER BY + CASE WHEN :sorting = 'created desc' THEN n_chats.created END DESC, + CASE WHEN :sorting = 'created asc' THEN n_chats.created END ASC, + CASE WHEN :sorting = 'ended desc' THEN n_chats.created END DESC, + CASE WHEN :sorting = 'ended asc' THEN n_chats.created END ASC, + CASE WHEN :sorting = 'base_id desc' THEN n_chats.base_id END DESC, + CASE WHEN :sorting = 'base_id asc' THEN n_chats.base_id END ASC, + CASE WHEN :sorting = 'feedback desc' THEN feedback_text END DESC, + CASE WHEN :sorting = 'feedback asc' THEN feedback_text END ASC, + CASE WHEN :sorting = 'rating desc' THEN feedback_rating END DESC, + CASE WHEN :sorting = 'rating asc' THEN feedback_rating END ASC +OFFSET ((GREATEST(:page, 1) - 1) * :page_size) + LIMIT :page_size; diff --git a/GUI/src/components/ChatsTable/index.tsx b/GUI/src/components/ChatsTable/index.tsx index f0a06749..77bbf8f0 100644 --- a/GUI/src/components/ChatsTable/index.tsx +++ b/GUI/src/components/ChatsTable/index.tsx @@ -2,7 +2,7 @@ import {CellContext, createColumnHelper, PaginationState, SortingState} from '@t import React, {useEffect, useMemo, useState} from 'react'; import {useTranslation} from 'react-i18next'; import {MdOutlineRemoveRedEye} from 'react-icons/md'; -import {Chat} from '../../types/chat'; +import {BACKOFFICE_NAME, Chat} from '../../types/chat'; import {formatDate} from '../../util/charts-utils'; import Button from '../Button'; import Card from '../Card'; @@ -28,7 +28,8 @@ type Props = { const ChatsTable = (props: Props) => { const [chats, setChats] = useState([]); const [selectedChat, setSelectedChat] = useState(null); - const columnHelper = createColumnHelper(); + type CombinedRow = Chat & { firstName?: string; lastName?: string }; + const columnHelper = createColumnHelper(); const {t} = useTranslation(); useEffect(() => { @@ -69,6 +70,13 @@ const ChatsTable = (props: Props) => { columnHelper.accessor('baseId', { header: 'ID', }), + columnHelper.accessor( + (row) => row.firstName ?`${row.firstName ?? ''} ${row.lastName ?? ''}` : BACKOFFICE_NAME.DEFAULT, + { + id: `name`, + header: t('chat.history.csaName') ?? '', + } + ), columnHelper.accessor('feedback', { header: t('feedback.comment') ?? '', }), @@ -125,7 +133,8 @@ const ChatsTable = (props: Props) => { + trigger={true} + /> )} diff --git a/GUI/src/types/user.ts b/GUI/src/types/user.ts new file mode 100644 index 00000000..e272582b --- /dev/null +++ b/GUI/src/types/user.ts @@ -0,0 +1,26 @@ +import { ROLES } from 'utils/constants'; + +export interface User { + login?: string; + fullName?: string; + firstName: string; + lastName: string; + idCode: string; + displayName: string; + csaTitle: string; + csaEmail: string; + authorities: ROLES[]; + customerSupportStatus: 'online' | 'idle' | 'offline'; +} + +export interface UserDTO extends Pick { +} + +export interface UserSearchFilters { + search_full_name: string; + search_id_code: string; + search_display_name: string; + search_csa_title: string; + search_csa_email: string; + search_authority: string; +}