feature/IO-3182-Phone-Number-Consent - Checkpoint
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Badge, Card, List, Space, Tag } from "antd";
|
||||
import { Badge, Card, List, Space, Tag, Tooltip } from "antd";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Virtuoso } from "react-virtuoso";
|
||||
@@ -9,6 +9,7 @@ import { TimeAgoFormatter } from "../../utils/DateFormatter";
|
||||
import PhoneFormatter from "../../utils/PhoneFormatter";
|
||||
import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
|
||||
import _ from "lodash";
|
||||
import { ExclamationCircleOutlined } from "@ant-design/icons";
|
||||
import "./chat-conversation-list.styles.scss";
|
||||
import { useQuery } from "@apollo/client";
|
||||
import { GET_PHONE_NUMBER_OPT_OUTS } from "../../graphql/phone-number-opt-out.queries.js";
|
||||
@@ -88,7 +89,13 @@ function ChatConversationListComponent({ conversationList, selectedConversation,
|
||||
const cardExtra = (
|
||||
<>
|
||||
<Badge count={item.messages_aggregate.aggregate.count} />
|
||||
{hasOptOutEntry && <Tag color="red">{t("messaging.labels.no_consent")}</Tag>}
|
||||
{hasOptOutEntry && (
|
||||
<Tooltip title={t("consent.text_body")}>
|
||||
<Tag color="red" icon={<ExclamationCircleOutlined />}>
|
||||
{t("messaging.labels.no_consent")}
|
||||
</Tag>
|
||||
</Tooltip>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ function ChatConversationContainer({ bodyshop, selectedConversation }) {
|
||||
userid
|
||||
created_at
|
||||
read
|
||||
is_system
|
||||
}
|
||||
`,
|
||||
data: message
|
||||
|
||||
@@ -4,13 +4,16 @@
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.archive-button {
|
||||
height: 20px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.chat-title {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.messages {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -37,11 +40,13 @@
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
.chat-send-message-button{
|
||||
|
||||
.chat-send-message-button {
|
||||
margin: 0.3rem;
|
||||
padding-left: 0.5rem;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.message-icon {
|
||||
position: absolute;
|
||||
bottom: 0.1rem;
|
||||
@@ -125,6 +130,37 @@
|
||||
}
|
||||
}
|
||||
|
||||
.system {
|
||||
align-items: center;
|
||||
margin: 0.5rem 10%;
|
||||
|
||||
.message {
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 10px;
|
||||
padding: 0.5rem 1rem;
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
color: #555;
|
||||
width: fit-content;
|
||||
max-width: 80%;
|
||||
}
|
||||
|
||||
.system-label {
|
||||
font-size: 0.75rem;
|
||||
color: #888;
|
||||
margin-bottom: 0.2rem;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.system-date {
|
||||
font-size: 0.75rem;
|
||||
color: #888;
|
||||
margin-top: 0.2rem;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.virtuoso-container {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
|
||||
@@ -7,12 +7,24 @@ import { DateTimeFormatter } from "../../utils/DateFormatter";
|
||||
|
||||
export const renderMessage = (messages, index) => {
|
||||
const message = messages[index];
|
||||
const isSystem = message.is_system;
|
||||
|
||||
// Determine message class
|
||||
const messageClass = isSystem ? "system messages" : message.isoutbound ? "mine messages" : "yours messages";
|
||||
|
||||
// Tooltip content based on message type
|
||||
const tooltipTitle = isSystem ? (
|
||||
i18n.t("consent.text_body")
|
||||
) : (
|
||||
<DateTimeFormatter>{message.created_at}</DateTimeFormatter>
|
||||
);
|
||||
|
||||
return (
|
||||
<div key={index} className={`${message.isoutbound ? "mine messages" : "yours messages"}`}>
|
||||
<div key={index} className={messageClass}>
|
||||
<div className="message msgmargin">
|
||||
<Tooltip title={DateTimeFormatter({ children: message.created_at })}>
|
||||
<Tooltip title={tooltipTitle}>
|
||||
<div>
|
||||
{isSystem && <span className="system-label">System</span>}
|
||||
{/* Render images if available */}
|
||||
{message.image && message.image_path?.length > 0 && (
|
||||
<div className="message-images">
|
||||
@@ -26,23 +38,31 @@ export const renderMessage = (messages, index) => {
|
||||
</div>
|
||||
)}
|
||||
{/* Render text if available */}
|
||||
{message.text && <div>{message.text}</div>}
|
||||
{message.text && <div className="message-text">{message.text}</div>}
|
||||
{/* Render date for system messages */}
|
||||
{isSystem && (
|
||||
<div className="system-date">
|
||||
<DateTimeFormatter>{message.created_at}</DateTimeFormatter>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
{/* Message status icons */}
|
||||
{message.status &&
|
||||
{/* Message status icons for non-system messages */}
|
||||
{!isSystem &&
|
||||
message.status &&
|
||||
(message.status === "sent" || message.status === "delivered" || message.status === "failed") && (
|
||||
<div className="message-status">
|
||||
<Icon
|
||||
component={message.status === "sent" ? MdDone : message.status === "delivered" ? MdDoneAll : MdClose}
|
||||
className="message-icon"
|
||||
style={message.status === "failed" ? { color: "#ff0000" } : undefined}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{/* Outbound message metadata */}
|
||||
{message.isoutbound && (
|
||||
{/* Outbound message metadata for non-system messages */}
|
||||
{!isSystem && message.isoutbound && (
|
||||
<div style={{ fontSize: 10 }}>
|
||||
{i18n.t("messaging.labels.sentby", {
|
||||
by: message.userid,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { LoadingOutlined, SendOutlined } from "@ant-design/icons";
|
||||
import { Alert, Input, Space, Spin } from "antd";
|
||||
import { ExclamationCircleOutlined, LoadingOutlined, SendOutlined } from "@ant-design/icons";
|
||||
import { Alert, Input, Space, Spin, Tooltip } from "antd";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
@@ -69,7 +69,16 @@ function ChatSendMessageComponent({ conversation, bodyshop, sendMessage, isSendi
|
||||
|
||||
return (
|
||||
<Space direction="vertical" style={{ width: "100%" }} size="middle">
|
||||
{isOptedOut && <Alert message={t("messaging.errors.no_consent")} type="error" />}
|
||||
{isOptedOut && (
|
||||
<Tooltip title={t("consent.text_body")}>
|
||||
<Alert
|
||||
showIcon={true}
|
||||
icon={<ExclamationCircleOutlined />}
|
||||
message={t("messaging.errors.no_consent")}
|
||||
type="error"
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
<div className="imex-flex-row" style={{ width: "100%" }}>
|
||||
{!isOptedOut && (
|
||||
<>
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
import { useQuery } from "@apollo/client";
|
||||
import { Input, Space, Table, Typography } from "antd";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Input, Table, Typography } from "antd";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
|
||||
import { GET_PHONE_NUMBER_OPT_OUTS, SEARCH_OWNERS_BY_PHONE_NUMBERS } from "../../graphql/phone-number-opt-out.queries";
|
||||
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
|
||||
import { GET_PHONE_NUMBER_OPT_OUTS } from "../../graphql/phone-number-opt-out.queries";
|
||||
import { TimeAgoFormatter } from "../../utils/DateFormatter";
|
||||
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useState } from "react";
|
||||
|
||||
const { Paragraph } = Typography; // Destructure Paragraph from Typography
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
// Commented out Associated Owners section for now
|
||||
//import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||
//import { Link } from "react-router-dom";
|
||||
//import { useMemo, useState } from "react";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -30,7 +33,8 @@ function PhoneNumberConsentList({ bodyshop, currentUser }) {
|
||||
fetchPolicy: "network-only"
|
||||
});
|
||||
|
||||
// Prepare phone numbers for owner query
|
||||
// Commented out Associated Owners section for now
|
||||
/*// Prepare phone numbers for owner query
|
||||
const phoneNumbers = useMemo(() => {
|
||||
return optOutData?.phone_number_opt_out?.map((item) => item.phone_number) || [];
|
||||
}, [optOutData?.phone_number_opt_out]);
|
||||
@@ -74,16 +78,17 @@ function PhoneNumberConsentList({ bodyshop, currentUser }) {
|
||||
: t("consent.phone_2")
|
||||
: null
|
||||
}));
|
||||
};
|
||||
};*/
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: t("consent.phone_number"),
|
||||
dataIndex: "phone_number",
|
||||
render: (text) => <PhoneNumberFormatter>{text}</PhoneNumberFormatter>,
|
||||
render: (text) => <ChatOpenButton phone={text} />,
|
||||
sorter: (a, b) => a.phone_number.localeCompare(b.phone_number)
|
||||
},
|
||||
{
|
||||
// Commented out Associated Owners section for now
|
||||
/*{
|
||||
title: t("consent.associated_owners"),
|
||||
dataIndex: "phone_number",
|
||||
render: (phoneNumber) => {
|
||||
@@ -109,7 +114,7 @@ function PhoneNumberConsentList({ bodyshop, currentUser }) {
|
||||
const bName = bOwners[0] ? `${bOwners[0].ownr_fn} ${bOwners[0].ownr_ln}` : "";
|
||||
return aName.localeCompare(bName);
|
||||
}
|
||||
},
|
||||
},*/
|
||||
{
|
||||
title: t("consent.created_at"),
|
||||
dataIndex: "created_at",
|
||||
@@ -130,7 +135,7 @@ function PhoneNumberConsentList({ bodyshop, currentUser }) {
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={optOutData?.phone_number_opt_out}
|
||||
loading={optOutLoading || ownersLoading}
|
||||
loading={optOutLoading /* || ownersLoading*/}
|
||||
rowKey="id"
|
||||
style={{ marginTop: 16 }}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user