feat: 筛选会话

2.0/email-builder
Lei OT 11 months ago
parent da74174ebf
commit 7879cf638d

@ -1,26 +1,26 @@
import React, { useState } from 'react';
import { Button, Tag, Radio, Popover, Form } from 'antd';
import React, { useState, useEffect } from 'react';
import { Button, Tag, Radio, Popover, Form, Divider } from 'antd';
import { FilterOutlined, FilterTwoTone } from '@ant-design/icons';
import { isEmpty, objectMapper, stringToColour } from '@/utils/commons';
import { isEmpty, isNotEmpty, objectMapper, stringToColour } from '@/utils/commons';
import useConversationStore from '@/stores/ConversationStore';
import { OrderLabelDefaultOptions, OrderStatusDefaultOptions } from '@/stores/OrderStore';
import { FilterIcon } from '@/components/Icons';
const otypes = [
{ label: 'All', value: '' },
{ label: '重点', value: 'zhongdian' },
{ label: '次重点', value: 'qianli' },
{ label: '成行', value: 'chengxing' },
{ label: '走团中', value: 'zoutuan' },
];
{ label: 'All', value: '', labelValue: '' },
...OrderLabelDefaultOptions.filter((o) =>
[240003, 240002].includes(o.value),
).map((o) => ({ ...o, labelValue: o.value, value: `label@${o.value}` })),
{ value: `state@5`, labelValue: 5, label: '成行', },
{ value: `intour@1`, labelValue: 1, label: '走团中', },
]
const otypesMapped = otypes.reduce((acc, cur) => ({ ...acc, [cur.value]: cur }), {});
const TagColorStyle = (tag, outerStyle = false) => {
const color = stringToColour(tag);
const outerStyleObj = outerStyle ? { borderColor: `${color}66`, backgroundColor: `${color}0D` } : {};
return { color: `${color}`, ...outerStyleObj };
};
const ChatListFilter = ({ ...props }) => {
const handleFilter = async (param) => {};
const ChatListFilter = ({ onFilterChange, ...props }) => {
const [
{ tags: selectedTags, otype: selectedOType, ...filter },
setFilterTags, setFilterOtype, resetFilter
@ -29,6 +29,40 @@ const ChatListFilter = ({ ...props }) => {
state.setFilterTags, state.setFilterOtype, state.resetFilter
]);
const conversationsList = useConversationStore((state) => state.conversationsList);
const closedConversationsList = useConversationStore((state) => state.closedConversationsList);
const handleFilter = async () => {
const [otypeC, v] = selectedOType ? selectedOType.split('@') : [];
const otypeV = v ? parseInt(v) : '';
let filterOTypeFun = () => true;
switch (otypeC) {
case 'label':
filterOTypeFun = (item) => item.order_label_id === otypeV
break
case 'state':
filterOTypeFun = (item) => item.order_state_id === otypeV
break
case 'intour':
filterOTypeFun = (item) => item.intour === otypeV
break
default:
break
}
const filterTagFun = (item) => {
const itemTagKeys = (item.tags || []).map(t => t.key);
return isEmpty(selectedTags) ? true : (selectedTags || []).some(tele => (itemTagKeys).includes(tele));
}
const filterWithOType = conversationsList.filter(filterOTypeFun).filter(filterTagFun);
const filterWithOTypeInClose = closedConversationsList.filter(filterOTypeFun);
if (typeof onFilterChange === 'function') {
onFilterChange(filterWithOType);
}
};
const [tags] = useConversationStore((state) => [state.tags]);
const [form] = Form.useForm();
const handleTagsChange = (tag, checked) => {
@ -37,21 +71,44 @@ const ChatListFilter = ({ ...props }) => {
form.setFieldValue('tags', nextSelectedTags);
};
const onFinish = async (values) => {
const filterParam = objectMapper(values, { tags: {key:'tags', transform: (v) => v ? v.join(',') : ''} });
// const filterParam = objectMapper(values, { tags: {key:'tags', transform: (v) => v ? v.join(',') : ''} });
const filterParam = objectMapper(values, { tags: {key:'tags', } });
filterParam.otype = selectedOType;
console.log('Received values of form[filter_form]: ', values, ' \n', filterParam);
await handleFilter(filterParam);
// await handleFilter(filterParam);
setOpenPopup(false);
};
const onReset = () => {
setFilterOtype('');
resetFilter();
form.resetFields();
if (typeof onFilterChange === 'function') {
onFilterChange(conversationsList);
}
}
useEffect(() => {
handleFilter()
return () => {
}
}, [selectedTags, selectedOType, filter ])
const [openPopup, setOpenPopup] = useState(false);
return (
<>
<div className='my-1 flex justify-between items-center '>
<Radio.Group optionType={'button'} buttonStyle='solid' size='small' options={otypes} value={selectedOType} onChange={(e) => setFilterOtype(e.target.value)} />
<Radio.Group
optionType={'button'}
buttonStyle='solid'
size='small'
options={otypes}
value={selectedOType}
onChange={(e) => {
setFilterOtype(e.target.value)
// handleFilter({ otype: e.target.value })
}}
/>
<Popover
destroyTooltipOnHide
placement='bottom'
@ -69,10 +126,20 @@ const ChatListFilter = ({ ...props }) => {
}
content={
<>
<Form form={form} name='conversation_filter_form' layout='vertical' size='small' initialValues={{}} onFinish={onFinish} className='*:mb-2'>
<Form
form={form}
name='conversation_filter_form'
layout='vertical'
size='small'
initialValues={{}}
onFinish={onFinish}
className='*:mb-2'>
<Form.Item label='订单'>
<Tag key={selectedOType} closeIcon={selectedOType !== ''} onClose={() => setFilterOtype('')}>
{otypesMapped[selectedOType].label}
<Tag
key={selectedOType}
closeIcon={selectedOType !== ''}
onClose={() => setFilterOtype('')}>
{otypesMapped[selectedOType]?.label || 'All'}
</Tag>
</Form.Item>
<Form.Item name={'tags'} label='标签' className='*.div:gap-1'>
@ -82,7 +149,10 @@ const ChatListFilter = ({ ...props }) => {
key={tag.key}
checked={selectedTags.includes(tag.key)}
onChange={(checked) => handleTagsChange(tag, checked)}
style={TagColorStyle(tag.label, selectedTags.includes(tag.key))}>
style={TagColorStyle(
tag.label,
selectedTags.includes(tag.key),
)}>
{tag.label}
</Tag.CheckableTag>
))}
@ -93,19 +163,28 @@ const ChatListFilter = ({ ...props }) => {
<Button onClick={onReset} type='primary' ghost>
重置
</Button>
<Button htmlType='submit' type='primary'>
{/* <Button htmlType='submit' type='primary'>
确定
</Button>
</Button> */}
</Button.Group>
</Form.Item>
</Form>
</>
}>
{/* <Button icon={isEmpty(selectedTags) ? <FilterOutlined /> : <FilterTwoTone />} type='text' size='middle' /> */}
<Button icon={<FilterIcon className={isEmpty(selectedTags) ? 'text-neutral-500' : 'text-blue-500'} />} type='text' size='middle' />
<Button
icon={
<FilterIcon
className={
isEmpty(selectedTags) ? 'text-neutral-500' : 'text-blue-500'
}
/>
}
type='text'
size='middle'
/>
</Popover>
</div>
</>
);
)
};
export default ChatListFilter;

@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { Dropdown, Input, Button, Tag, Popover, Form } from 'antd';
import { CloseCircleOutlined } from '@ant-design/icons';
import { CloseCircleOutlined, MinusCircleOutlined } from '@ant-design/icons';
import { fetchConversationItemClose, fetchConversationsSearch, fetchConversationItemUnread, fetchConversationItemTop, postConversationTags, deleteConversationTags } from '@/actions/ConversationActions';
import { ChatItem } from 'react-chat-elements';
// import ConversationsNewItem from './ConversationsNewItem';
@ -182,7 +182,7 @@ const ChatListItem = (({item, refreshConversationList,setListUpdateFlag,onSwitch
key: `tag_${t.key}`,
style: { color: stringToColour(t.label) },
// icon: itemTagsKeys.includes(t.key) ? <CloseCircleOutlined className='text-red-500' /> : false,
extra: itemTagsKeys.includes(t.key) ? <CloseCircleOutlined className='text-red-500' /> : false,
extra: itemTagsKeys.includes(t.key) ? <MinusCircleOutlined className='text-red-500' /> : false,
})),
{
label: (
@ -261,7 +261,12 @@ const ChatListItem = (({item, refreshConversationList,setListUpdateFlag,onSwitch
id={item.sn}
letterItem={{ id: item.whatsapp_name || item.whatsapp_phone_number, letter: (item.whatsapp_name || item.whatsapp_phone_number).slice(0, 5) }}
alt={item.whatsapp_name}
title={(item.top_state === 1 ? '🔝' : '') + (item.conversation_memo || item.whatsapp_name || item.whatsapp_phone_number)}
title={(item.top_state === 1 ? '🔝' : '')
// + (item.order_label_id === 240003 ? '🔴' : '')
// + (item.order_label_id === 240002 ? '🟠' : '')
// + (item.order_state_id === 4 ? '🌹' : '')
// + (item.intour === 0 ? '🧳' : '')
+ (item.conversation_memo || item.whatsapp_name || item.whatsapp_phone_number)}
// subtitle={item.coli_id}
subtitle={
<div>
@ -270,8 +275,8 @@ const ChatListItem = (({item, refreshConversationList,setListUpdateFlag,onSwitch
{/* <SentIcon /> */}
{/* todo: last message ⤴⤵↗️↖️↘✔️ */}
{/* <span>{item.coli_id}</span> */}
<span><ReadIcon />最后一条消息</span>
{/* <span>最后一条消息</span> */}
{/* <span><ReadIcon />最后一条消息</span> */}
<span>{item?.last_message?.text?.body || ''}</span>
<div className='text-sm'>
{(item?.tags || [])?.map((tag) => (
<Tag key={tag.label} style={{ ...TagColorStyle(tag.label) }} className='text-xs px-0.5 me-0.5'>

@ -222,18 +222,6 @@ const Conversations = () => {
</Select>
);
const [newTagOpen, setNewTagOpen] = useState(false);
const [contextMenuOpen, setContextMenuOpen] = useState(false);
const handleContextMenuOpenChange = (nextOpen, info, ...x) => {
console.log(info);
console.log(nextOpen);
console.log(x);
if (info.source === 'trigger' || nextOpen) {
setContextMenuOpen(nextOpen);
}
};
return (
<div className='flex flex-col h-inherit'>
<div className='flex gap-1 items-center'>
@ -306,7 +294,7 @@ const Conversations = () => {
/>
)}
</div>
<ChatListFilter />
<ChatListFilter onFilterChange={(list) => setDataSource(list)} />
<div className='flex-1 overflow-x-hidden overflow-y-auto relative'>
{conversationsListLoading && dataSource.length === 0 ? (
<div className='text-center py-2'>

Loading…
Cancel
Save