Skip to content
This repository has been archived by the owner on Jul 25, 2023. It is now read-only.

Commit

Permalink
Merge pull request #5 from OnrampLab/issue-4-conversations
Browse files Browse the repository at this point in the history
Issue 4 conversations
  • Loading branch information
kenpingshu authored Nov 13, 2019
2 parents 019f12c + f3c247e commit 39512c8
Show file tree
Hide file tree
Showing 14 changed files with 482 additions and 15 deletions.
3 changes: 3 additions & 0 deletions pages/conversations/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ConversationsMainPage } from '@onr/conversations';

export default ConversationsMainPage;
21 changes: 6 additions & 15 deletions src/app/configs/menuItems.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { ReactElement } from 'react';

import { Home, MessageCircle, PhoneCall } from 'react-feather';
import { Home, PhoneCall, MessageSquare } from 'react-feather';

interface MenuItem {
name: string;
Expand All @@ -15,20 +15,11 @@ export const menuItems: MenuItem[] = [
name: 'Home',
icon: <Home strokeWidth={1} size={16} />,
},
// {
// name: 'Demo',
// icon: <MessageCircle strokeWidth={1} size={16} />,
// children: [
// {
// path: '/demo/planet',
// name: 'Daily Planet',
// },
// {
// path: '/demo/mars',
// name: 'Mars Photos',
// },
// ],
// },
{
path: '/conversations',
name: 'Conversations',
icon: <MessageSquare strokeWidth={1} size={16} />,
},
{
name: 'IVR',
icon: <PhoneCall strokeWidth={1} size={16} />,
Expand Down
206 changes: 206 additions & 0 deletions src/modules/conversations/components/ChatRoom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import React from 'react';
import { Anchor, Image, MessageCircle, Mic, Search as SearchIcon, Settings } from 'react-feather';
import { Button, Input, Layout, Menu, Row } from 'antd';
import { LeadAvatar } from '@onr/conversations';
import format from 'date-fns/format';
import styled from 'styled-components';
import { useSelector } from 'react-redux';

const { Header } = Layout;
const { TextArea } = Input;
const ChatStyled = styled.div`
flex: 1;
overflow-y: auto;
position: relative;
padding: 5rem 2rem;
background-color: #f9f9f9;
.weakColor & {
-webkit-filter: invert(100%);
filter: invert(100%);
}
p {
margin-bottom: 0;
}
.conversation {
box-sizing: border-box;
width: 100%;
margin-bottom: 1rem;
display: flex;
}
.conversation-sent {
justify-content: flex-end;
}
.body {
position: relative;
padding: 0.625rem 1rem;
background-color: white;
border-radius: 0.8rem;
min-width: 100px;
}
.body-sent {
position: relative;
background-color: #e2f8ff;
float: right;
order: 1;
}
.date {
display: block;
font-size: 11px;
padding-top: 2px;
font-weight: 600;
color: ${props => props.theme.textColorSecondary};
text-align: right;
}
.date-Sent {
text-align: right;
}
input {
flex: 1 1 0%;
box-sizing: border-box;
}
`;
interface ChatRoomProps {
conversation: any;
}

export const ChatRoom: React.FC<ChatRoomProps> = ({ conversation }: ChatRoomProps) => {
const isMobile = useSelector((store: any) => store.wrapper.mobile);
return (
<Layout className="fill-workspace rounded shadow-sm overflow-hidden">
<Header
css={`
display: flex;
align-items: center;
padding: 0.3rem 2rem;
z-index: 1;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.02), 0 1px 0 rgba(0, 0, 0, 0.02);
height: auto;
line-height: auto;
`}
>
{isMobile && (
<Button shape="circle" size="large" onClick={() => setContacts(true)} className="mr-3">
<MessageCircle size={20} strokeWidth={1} />
</Button>
)}
<Row type="flex" align="middle">
<LeadAvatar name={conversation.lead.phone} />
{!isMobile && (
<span
className="ml-3"
css={`
line-height: 1;
`}
>
<span
css={`
display: block;
`}
>
{conversation.lead.phone}
</span>
<small className="text-muted">
<span>Online</span>
</small>
</span>
)}
</Row>
<span className="mr-auto" />
<Menu mode="horizontal" className="border-0">
<Menu.Item>
<SearchIcon size={20} strokeWidth={1} />
</Menu.Item>
<Menu.Item>
<Settings size={20} strokeWidth={1} />
</Menu.Item>
</Menu>
</Header>
<Layout>
<Layout>
<div
css={`
display: flex;
flex: 1;
flex-direction: column;
height: 100%;
overflow: hidden;
`}
>
<ChatStyled>
<>
{conversation.messages.map((chat, index) => (
<div
key={index}
className={`conversation
${chat.type === 'sent' ? 'conversation-sent' : 'conversation-received'}
`}
>
<div
className={`
body shadow-sm
${
chat.type === 'sent'
? 'body-sent'
: 'body-received text-body'
}
`}
>
<p color="inherit">{chat.content}</p>
<p
variant="caption"
className={`
date
${chat.type === 'sent' ? 'date-sent' : 'date-received'}
`}
>
{format(chat.created_at, 'hh:mm')}
</p>
</div>
</div>
))}
</>
</ChatStyled>
<div
className="px-3 py-2"
css={`
background: #f9f9f9;
`}
>
<div
css={`
display: flex;
align-items: center;
`}
>
<Menu
mode="horizontal"
className="border-bottom-0 bg-transparent"
>
<Menu.Item key="read">
<a href="javascript:;">
<Image size={20} strokeWidth={1} />
</a>
</Menu.Item>
<Menu.Item key="favorite">
<a href="javascript:;">
<Anchor size={20} strokeWidth={1} />
</a>
</Menu.Item>
<Menu.Item key="star">
<a href="javascript:;">
<Mic size={20} strokeWidth={1} />
</a>
</Menu.Item>
</Menu>

<TextArea placeholder="Type a message" autosize />
</div>
</div>
</div>
</Layout>
</Layout>
</Layout>
);
};
107 changes: 107 additions & 0 deletions src/modules/conversations/components/ConversationsSidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import React, { useState } from 'react';
import { Drawer, Layout, List, Menu } from 'antd';
import { useSelector } from 'react-redux';
import { CheckCircle, Heart, RefreshCcw, Star } from 'react-feather';
import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
import { LeadAvatar } from '@onr/conversations';

const { Sider } = Layout;

interface ConversationsSidebarProps {
conversationsData: any;
onConversationSelected: any;
}

export const ConversationsSidebar: React.FC<ConversationsSidebarProps> = ({
conversationsData,
onConversationSelected,
}: ConversationsSidebarProps) => {
const isMobile = useSelector((store: any) => store.wrapper.mobile);
const [messages, setMessages] = useState(false);
const [selectedIndex, setSelectedIndex] = useState(0);
const changeIndex = (index: number) => {
setSelectedIndex(index);
onConversationSelected(index);
};
const conversations = (
<div
css={`
display: flex;
flex: 1;
flex-direction: column;
height: 100%;
overflow: hidden;
border-right: 1px solid rgba(0, 0, 0, 0.05);
`}
>
<Menu mode="horizontal" className="border-0 m-auto">
<Menu.Item key="read">
<a href="javascript:;">
<CheckCircle size={20} strokeWidth={1} />
</a>
</Menu.Item>
<Menu.Item key="favorite">
<a href="javascript:;">
<Heart size={20} strokeWidth={1} />
</a>
</Menu.Item>
<Menu.Item key="star">
<a href="javascript:;">
<Star size={20} strokeWidth={1} />
</a>
</Menu.Item>
<Menu.Item key="refresh">
<a href="javascript:;">
<RefreshCcw size={20} strokeWidth={1} />
</a>
</Menu.Item>
</Menu>
<List
className="scroll-y flex-1 bg-transparent px-3 py-1"
dataSource={conversationsData}
itemLayout="horizontal"
renderItem={(item, index) => (
<List.Item
onClick={changeIndex.bind(null, index)}
style={{
backgroundColor: selectedIndex === index ? '#e6f7ff' : '',
}}
className={`${selectedIndex === index ? '' : 'border-0'} rounded border-0 p-3`}
>
<List.Item.Meta
avatar={<LeadAvatar name={item.lead.phone} />}
title={
<small
css={`
display: flex;
width: 100%;
`}
>
<span>{item.lead.phone}</span>
<span className="mr-auto" />
<span>{item.latest_message && distanceInWordsToNow(new Date(item.latest_message.created_at))}</span>
</small>
}
description={item.latest_message && item.latest_message.content}
/>
</List.Item>
)}
/>
</div>
);
return (
<>
{!isMobile && <Sider width={350}>{conversations}</Sider>}
<Drawer
closable={false}
width={350}
placement="left"
onClose={() => setMessages(false)}
visible={messages}
className="chat-drawer"
>
{conversations}
</Drawer>
</>
);
};
Loading

0 comments on commit 39512c8

Please sign in to comment.