2021-05-22 09:54:28 +07:00
|
|
|
import React, { createRef, useState, Fragment, FC } from 'react';
|
|
|
|
|
import { Layout, Col, Row, Button, Image } from 'antd';
|
|
|
|
|
import { EditOutlined, CloseOutlined, AppstoreOutlined } from '@ant-design/icons';
|
2021-05-19 11:57:16 +07:00
|
|
|
import ConversationList from "@/components/ConversationList";
|
|
|
|
|
import Chatbox from "@/components/Chatbox";
|
|
|
|
|
import CustomerInfo from "@/components/CustomerInfo";
|
|
|
|
|
import ActionTabs from "@/components/ActionTabs";
|
2021-05-22 09:54:28 +07:00
|
|
|
import { HelpSideBar } from "@/components/Help";
|
2021-05-19 11:57:16 +07:00
|
|
|
import HeaderComponent from "@/components/HeaderComponent";
|
|
|
|
|
|
2021-05-22 09:54:28 +07:00
|
|
|
import { useDispatch, useSelector } from "react-redux";
|
|
|
|
|
import { AppState } from "@/store/typing";
|
|
|
|
|
import { UserInfo } from "@/typings/user";
|
|
|
|
|
import { actions } from "@/store/actions";
|
2021-05-19 11:57:16 +07:00
|
|
|
|
|
|
|
|
import GlobalModal from '@/components/GlobalModal';
|
|
|
|
|
import GlobalDrawer from "@/components/GlobalDrawer";
|
|
|
|
|
import BadgeStatus from "@/components/BadgeStatus";
|
|
|
|
|
import NetworkError from "@/components/Error/NetworkError";
|
|
|
|
|
|
2021-05-22 09:54:28 +07:00
|
|
|
import { ClientSettings } from "@/typings";
|
2021-05-19 11:57:16 +07:00
|
|
|
|
|
|
|
|
import TYPING_ANIMATION_IMAGE from "@/assets/typing-animation.gif";
|
|
|
|
|
import DashBoard from "@/components/DashBoard";
|
|
|
|
|
|
2021-05-22 09:54:28 +07:00
|
|
|
import { user_list } from "@/test/test_state";
|
|
|
|
|
import { DEFAULT_AVATAR } from "@/config";
|
2021-05-19 11:57:16 +07:00
|
|
|
import '@/styles/app.css';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { Header, Content, Sider } = Layout;
|
|
|
|
|
|
|
|
|
|
const WINDOW_HEIGHT = global.window.innerHeight;
|
|
|
|
|
|
|
|
|
|
|
2021-05-22 09:54:28 +07:00
|
|
|
const UserNameForm = ({ user }: { user: UserInfo | null }) => {
|
2021-05-19 11:57:16 +07:00
|
|
|
const [openForm, setFormOpen] = useState<boolean>(false);
|
|
|
|
|
const dispatch = useDispatch();
|
|
|
|
|
|
2021-05-22 09:54:28 +07:00
|
|
|
if (!user) {
|
2021-05-19 11:57:16 +07:00
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const userInputRef = createRef<HTMLInputElement>();
|
|
|
|
|
const updateName = () => {
|
|
|
|
|
let new_name = userInputRef.current?.value;
|
|
|
|
|
dispatch(actions.updateUserInfo({
|
|
|
|
|
id: user.id,
|
|
|
|
|
name: new_name,
|
|
|
|
|
}));
|
|
|
|
|
setFormOpen(false);
|
|
|
|
|
}
|
2021-05-22 09:54:28 +07:00
|
|
|
const avatar = user.avatar || DEFAULT_AVATAR;
|
|
|
|
|
if (!openForm) {
|
2021-05-19 11:57:16 +07:00
|
|
|
return (
|
2021-05-22 09:54:28 +07:00
|
|
|
<div className="cuscontentCenterHeader">
|
|
|
|
|
<div className="avatar-cus">
|
|
|
|
|
<img className="conversation-photo" src={avatar} alt="conversation" />
|
|
|
|
|
<BadgeStatus online={user.online || false}>
|
|
|
|
|
</BadgeStatus>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="info-cus">
|
|
|
|
|
<div className="name">{user.name}</div>
|
|
|
|
|
<div className="address">{user.location}</div>
|
|
|
|
|
</div>
|
|
|
|
|
{
|
|
|
|
|
user.typing && <Image preview={false} style={{ height: 20 }} src={TYPING_ANIMATION_IMAGE} />
|
|
|
|
|
}<div className="cuscontentCenterHeaderEdit">( <EditOutlined onClick={() => setFormOpen(true)} title={'Thay đổi tên'} /> )</div>
|
|
|
|
|
</div>
|
2021-05-19 11:57:16 +07:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Fragment>
|
|
|
|
|
<input type={'text'} size={30} ref={userInputRef} defaultValue={user.name} /> <Button onClick={updateName}>OK</Button>
|
|
|
|
|
</Fragment>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-05-22 09:54:28 +07:00
|
|
|
function getUserById(user_list: UserInfo[], user_id: string): UserInfo | null {
|
2021-05-19 11:57:16 +07:00
|
|
|
let filtered_list = user_list.filter(user => user.id === user_id);
|
|
|
|
|
return filtered_list.length > 0 ? filtered_list[0] : null;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-22 09:54:28 +07:00
|
|
|
const ShowUserSpace = ({openHelp}: {openHelp: () => any}) => {
|
2021-05-19 11:57:16 +07:00
|
|
|
// TODO:
|
|
|
|
|
|
2021-05-22 09:54:28 +07:00
|
|
|
const chatting_with_user = useSelector((state: AppState) => state.chatting_with_user);
|
2021-05-19 11:57:16 +07:00
|
|
|
const dispatch = useDispatch();
|
|
|
|
|
|
|
|
|
|
let chatting_user_info = getUserById(user_list, chatting_with_user);
|
2021-05-22 09:54:28 +07:00
|
|
|
if (!chatting_user_info && user_list.length > 0) {
|
2021-05-19 11:57:16 +07:00
|
|
|
// auto show the first user in the list if there
|
|
|
|
|
dispatch(actions.chatWithUser(user_list[0].id));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// else show the dashboard
|
2021-05-22 09:54:28 +07:00
|
|
|
if (!chatting_user_info) {
|
2021-05-19 11:57:16 +07:00
|
|
|
return <DashBoard />
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
2021-05-22 09:54:28 +07:00
|
|
|
<Fragment>
|
|
|
|
|
<div className="contentCenterHeader">
|
|
|
|
|
<UserNameForm user={chatting_user_info} />
|
|
|
|
|
<div onClick={openHelp} className="contentCenterHeaderAdmin">
|
|
|
|
|
<span className="h-title">Trợ giúp admin</span>
|
|
|
|
|
<AppstoreOutlined className="h-icon" />
|
2021-05-19 11:57:16 +07:00
|
|
|
</div>
|
2021-05-22 09:54:28 +07:00
|
|
|
</div>
|
2021-05-19 11:57:16 +07:00
|
|
|
|
2021-05-22 09:54:28 +07:00
|
|
|
<div className="contentCenterCt">
|
2021-05-19 11:57:16 +07:00
|
|
|
<Row>
|
2021-05-22 09:54:28 +07:00
|
|
|
<Col className="contentCenterCtColLeft" span={12}>
|
2021-05-19 11:57:16 +07:00
|
|
|
{/* add key to force to component to remount when user id change to simplify the component's code*/}
|
|
|
|
|
<Chatbox key={chatting_user_info.id} user_info={chatting_user_info} />
|
|
|
|
|
</Col>
|
|
|
|
|
|
2021-05-22 09:54:28 +07:00
|
|
|
<Col span={12} className="contentCenterCtColRight">
|
|
|
|
|
<div className="contentCenterCtColRightItem">
|
|
|
|
|
<h3 className="contentCenterCtColRightTitle" style={{ fontSize: 16, fontWeight: 'bold' }}>Lựa chọn</h3>
|
2021-05-19 11:57:16 +07:00
|
|
|
|
2021-05-22 09:54:28 +07:00
|
|
|
<ActionTabs customer_id={chatting_user_info.id} />
|
|
|
|
|
</div>
|
|
|
|
|
<div className="contentCenterCtColRightItem">
|
|
|
|
|
<h3 className="contentCenterCtColRightTitle" style={{ fontSize: 16, fontWeight: 'bold' }}>Thông tin khách hàng</h3>
|
2021-05-19 11:57:16 +07:00
|
|
|
|
2021-05-22 09:54:28 +07:00
|
|
|
<CustomerInfo user_info={chatting_user_info} />
|
|
|
|
|
</div>
|
2021-05-19 11:57:16 +07:00
|
|
|
</Col>
|
|
|
|
|
</Row>
|
2021-05-22 09:54:28 +07:00
|
|
|
</div>
|
|
|
|
|
</Fragment>
|
2021-05-19 11:57:16 +07:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-05-22 09:54:28 +07:00
|
|
|
const App: FC<{ client_setting: ClientSettings }> = ({ client_setting }) => {
|
2021-05-19 11:57:16 +07:00
|
|
|
|
|
|
|
|
const HEADER_HEIGHT = 70;
|
|
|
|
|
const [closeHelp, setHelpClose] = useState<boolean>(false);
|
2021-05-22 09:54:28 +07:00
|
|
|
const LAYOUT_CLOSED = closeHelp ? { width: 1200, marginLeft: 'auto', marginRight: 'auto' } : { marginTop: HEADER_HEIGHT, height: WINDOW_HEIGHT - HEADER_HEIGHT, overflow: 'auto' };
|
|
|
|
|
const windowWidth = window.innerWidth;
|
2021-05-19 11:57:16 +07:00
|
|
|
|
|
|
|
|
return (
|
2021-05-22 09:54:28 +07:00
|
|
|
<Layout className={'box-chatboard'}>
|
|
|
|
|
<Header style={{ width: '100%' }}>
|
2021-05-19 11:57:16 +07:00
|
|
|
<HeaderComponent />
|
|
|
|
|
</Header>
|
2021-05-22 09:54:28 +07:00
|
|
|
<Layout className={'content-chatboard'}>
|
|
|
|
|
<Row className={'content-chatboard-row'}>
|
|
|
|
|
<Col className={'content-chatboard-col'} span={4}>
|
|
|
|
|
<div className="contentLeft">
|
|
|
|
|
<ConversationList />
|
|
|
|
|
</div>
|
|
|
|
|
</Col>
|
|
|
|
|
{
|
|
|
|
|
windowWidth <= 1366 ?
|
|
|
|
|
<Col className={'content-chatboard-col'} span={20}>
|
|
|
|
|
<Content className="contentCenter">
|
|
|
|
|
<ShowUserSpace openHelp={() => setHelpClose(true)} />
|
|
|
|
|
</Content>
|
|
|
|
|
</Col>
|
|
|
|
|
:
|
|
|
|
|
<Col className={'content-chatboard-col content-chatboard-col-big'} span={14}>
|
|
|
|
|
<Content className="contentCenter">
|
|
|
|
|
<ShowUserSpace openHelp={() => setHelpClose(true)} />
|
|
|
|
|
</Content>
|
|
|
|
|
</Col>
|
|
|
|
|
}
|
2021-05-19 11:57:16 +07:00
|
|
|
|
2021-05-22 09:54:28 +07:00
|
|
|
{
|
|
|
|
|
windowWidth <= 1366 ?
|
|
|
|
|
(
|
|
|
|
|
closeHelp &&
|
|
|
|
|
<div className="fix-ab-ct-right" id="fix-ab-ct-right">
|
|
|
|
|
<div className="contentRight" >
|
|
|
|
|
<h2 className="contentRightHeader">Trợ giúp Admin <CloseOutlined onClick={() => setHelpClose(false)} title={'Đóng'} /> </h2>
|
|
|
|
|
<HelpSideBar />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
:
|
|
|
|
|
<Col className={'content-chatboard-col'} span={6}>
|
|
|
|
|
<div className="contentRight" >
|
|
|
|
|
<h2 className="contentRightHeader">Trợ giúp Admin <CloseOutlined onClick={() => setHelpClose(false)} title={'Đóng'} /> </h2>
|
|
|
|
|
<HelpSideBar />
|
|
|
|
|
</div>
|
|
|
|
|
</Col>
|
|
|
|
|
}
|
|
|
|
|
</Row>
|
2021-05-19 11:57:16 +07:00
|
|
|
</Layout>
|
|
|
|
|
|
|
|
|
|
<NetworkError />
|
|
|
|
|
<GlobalModal />
|
|
|
|
|
<GlobalDrawer />
|
|
|
|
|
|
|
|
|
|
</Layout>
|
|
|
|
|
)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default App;
|