giao dien moi

This commit is contained in:
2021-05-22 09:54:28 +07:00
parent ab2830f449
commit 4770ce26d2
25 changed files with 23237 additions and 416 deletions

View File

@@ -1,30 +1,30 @@
import React, {createRef, useState, Fragment, FC} from 'react';
import {Layout, Col, Row, Button, Image} from 'antd';
import { EditOutlined, CloseOutlined } from '@ant-design/icons';
import React, { createRef, useState, Fragment, FC } from 'react';
import { Layout, Col, Row, Button, Image } from 'antd';
import { EditOutlined, CloseOutlined, AppstoreOutlined } from '@ant-design/icons';
import ConversationList from "@/components/ConversationList";
import Chatbox from "@/components/Chatbox";
import CustomerInfo from "@/components/CustomerInfo";
import ActionTabs from "@/components/ActionTabs";
import {HelpSideBar} from "@/components/Help";
import { HelpSideBar } from "@/components/Help";
import HeaderComponent from "@/components/HeaderComponent";
import {useDispatch, useSelector} from "react-redux";
import {AppState} from "@/store/typing";
import {UserInfo} from "@/typings/user";
import {actions} from "@/store/actions";
import { useDispatch, useSelector } from "react-redux";
import { AppState } from "@/store/typing";
import { UserInfo } from "@/typings/user";
import { actions } from "@/store/actions";
import GlobalModal from '@/components/GlobalModal';
import GlobalDrawer from "@/components/GlobalDrawer";
import BadgeStatus from "@/components/BadgeStatus";
import NetworkError from "@/components/Error/NetworkError";
import {ClientSettings} from "@/typings";
import { ClientSettings } from "@/typings";
import TYPING_ANIMATION_IMAGE from "@/assets/typing-animation.gif";
import DashBoard from "@/components/DashBoard";
import {user_list} from "@/test/test_state";
import { user_list } from "@/test/test_state";
import { DEFAULT_AVATAR } from "@/config";
import '@/styles/app.css';
@@ -33,11 +33,11 @@ const { Header, Content, Sider } = Layout;
const WINDOW_HEIGHT = global.window.innerHeight;
const UserNameForm = ({user}: {user: UserInfo | null}) => {
const UserNameForm = ({ user }: { user: UserInfo | null }) => {
const [openForm, setFormOpen] = useState<boolean>(false);
const dispatch = useDispatch();
if( ! user ) {
if (!user) {
return null;
}
@@ -50,17 +50,24 @@ const UserNameForm = ({user}: {user: UserInfo | null}) => {
}));
setFormOpen(false);
}
if(!openForm) {
const avatar = user.avatar || DEFAULT_AVATAR;
if (!openForm) {
return (
<Fragment>
<BadgeStatus online={user.online || false}>
{user.name}
{
user.typing && <Image preview={false} style={{height:20}} src={TYPING_ANIMATION_IMAGE} />
}
</BadgeStatus> ( <EditOutlined onClick={() => setFormOpen(true)} title={'Thay đổi tên'} /> )
</Fragment>
<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>
)
}
@@ -72,86 +79,118 @@ const UserNameForm = ({user}: {user: UserInfo | null}) => {
}
function getUserById(user_list: UserInfo[], user_id: string) : UserInfo | null {
function getUserById(user_list: UserInfo[], user_id: string): UserInfo | null {
let filtered_list = user_list.filter(user => user.id === user_id);
return filtered_list.length > 0 ? filtered_list[0] : null;
}
const ShowUserSpace = () => {
const ShowUserSpace = ({openHelp}: {openHelp: () => any}) => {
// TODO:
const chatting_with_user = useSelector((state: AppState) => state.chatting_with_user );
const chatting_with_user = useSelector((state: AppState) => state.chatting_with_user);
const dispatch = useDispatch();
let chatting_user_info = getUserById(user_list, chatting_with_user);
if( ! chatting_user_info && user_list.length > 0) {
if (!chatting_user_info && user_list.length > 0) {
// auto show the first user in the list if there
dispatch(actions.chatWithUser(user_list[0].id));
}
// else show the dashboard
if( ! chatting_user_info ) {
if (!chatting_user_info) {
return <DashBoard />
}
return (
<Fragment>
<div>
<UserNameForm user={chatting_user_info} />
<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" />
</div>
</div>
<div className="contentCenterCt">
<Row>
<Col span={12}>
<Col className="contentCenterCtColLeft" span={12}>
{/* 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>
<Col span={12} className="scrollable" style={{height: 600, overflow: 'auto'}}>
<h3 style={{fontSize:16, fontWeight:'bold'}}>Lựa chọn</h3>
<Col span={12} className="contentCenterCtColRight">
<div className="contentCenterCtColRightItem">
<h3 className="contentCenterCtColRightTitle" style={{ fontSize: 16, fontWeight: 'bold' }}>Lựa chọn</h3>
<ActionTabs customer_id={chatting_user_info.id} />
<h3 style={{fontSize:16, fontWeight:'bold'}}>Thông tin khách hàng</h3>
<CustomerInfo user_info={chatting_user_info} />
<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>
<CustomerInfo user_info={chatting_user_info} />
</div>
</Col>
</Row>
</Fragment>
</div>
</Fragment>
)
}
const App: FC<{client_setting: ClientSettings}> = ({client_setting}) => {
const App: FC<{ client_setting: ClientSettings }> = ({ client_setting }) => {
const HEADER_HEIGHT = 70;
const [closeHelp, setHelpClose] = useState<boolean>(false);
const LAYOUT_CLOSED = closeHelp ? {width:1200, marginLeft:'auto', marginRight: 'auto'} : {marginTop: HEADER_HEIGHT, height: WINDOW_HEIGHT - HEADER_HEIGHT, overflow: 'auto'};
const LAYOUT_CLOSED = closeHelp ? { width: 1200, marginLeft: 'auto', marginRight: 'auto' } : { marginTop: HEADER_HEIGHT, height: WINDOW_HEIGHT - HEADER_HEIGHT, overflow: 'auto' };
const windowWidth = window.innerWidth;
return (
<Layout>
<Header style={{ position: 'fixed', zIndex: 1, width: '100%' }}>
<Layout className={'box-chatboard'}>
<Header style={{ width: '100%' }}>
<HeaderComponent />
</Header>
<Layout style={LAYOUT_CLOSED}>
<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>
}
<Sider width={250} className="scrollable">
<ConversationList />
</Sider>
<Content>
<ShowUserSpace />
</Content>
{
!closeHelp &&
<Sider width={400} >
<h2>Trợ giúp <CloseOutlined onClick={() => setHelpClose(true)} title={'Đóng'} /> </h2>
<HelpSideBar />
</Sider>
}
{
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>
</Layout>
<NetworkError />