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"; import { createStructuredSelector } from "reselect"; import { setSelectedConversation } from "../../redux/messaging/messaging.actions"; import { selectSelectedConversation } from "../../redux/messaging/messaging.selectors"; 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"; import { phone } from "phone"; import { useTranslation } from "react-i18next"; import { selectBodyshop } from "../../redux/user/user.selectors"; const mapStateToProps = createStructuredSelector({ selectedConversation: selectSelectedConversation, bodyshop: selectBodyshop }); const mapDispatchToProps = (dispatch) => ({ setSelectedConversation: (conversationId) => dispatch(setSelectedConversation(conversationId)) }); function ChatConversationListComponent({ conversationList, selectedConversation, setSelectedConversation, bodyshop }) { const { t } = useTranslation(); const [, forceUpdate] = useState(false); const phoneNumbers = conversationList.map((item) => phone(item.phone_num, "CA").phoneNumber.replace(/^\+1/, "")); const { data: optOutData } = useQuery(GET_PHONE_NUMBER_OPT_OUTS, { variables: { bodyshopid: bodyshop.id, phone_numbers: phoneNumbers }, skip: !conversationList.length, fetchPolicy: "cache-and-network" }); const optOutMap = useMemo(() => { const map = new Map(); optOutData?.phone_number_opt_out?.forEach((optOut) => { map.set(optOut.phone_number, true); }); return map; }, [optOutData?.phone_number_opt_out]); useEffect(() => { const interval = setInterval(() => { forceUpdate((prev) => !prev); }, 60000); return () => clearInterval(interval); }, []); const sortedConversationList = useMemo(() => { return _.orderBy(conversationList, ["updated_at"], ["desc"]); }, [conversationList]); const renderConversation = (index, t) => { const item = sortedConversationList[index]; const normalizedPhone = phone(item.phone_num, "CA").phoneNumber.replace(/^\+1/, ""); const hasOptOutEntry = optOutMap.has(normalizedPhone); const cardContentRight = {item.updated_at}; const cardContentLeft = item.job_conversations.length > 0 ? item.job_conversations.map((j, idx) => {j.job.ro_number}) : null; const names = <>{_.uniq(item.job_conversations.map((j) => OwnerNameDisplayFunction(j.job)))}; const cardTitle = ( <> {item.label && {item.label}} {item.job_conversations.length > 0 ? ( {names} ) : ( {item.phone_num} )} ); const cardExtra = ( <> {hasOptOutEntry && ( }> {t("messaging.labels.no_consent")} )} ); const getCardStyle = () => item.id === selectedConversation ? { backgroundColor: "var(--card-selected-bg)" } : { backgroundColor: index % 2 === 0 ? "var(--card-stripe-even-bg)" : "var(--card-stripe-odd-bg)" }; return ( setSelectedConversation(item.id)} className={`chat-list-item ${item.id === selectedConversation ? "chat-list-selected-conversation" : ""}`} >
{cardContentLeft}
{cardContentRight}
); }; return (
renderConversation(index, t)} style={{ height: "100%", width: "100%" }} />
); } export default connect(mapStateToProps, mapDispatchToProps)(ChatConversationListComponent);