main
Саске Учиха 2 years ago
parent c86523dcf4
commit 4d7b3dd8cd

@ -10,6 +10,12 @@ Ararat International School - платформа по обучению игры
- Express.js - Express.js
- Mongo DB - Mongo DB
#### V 0.05
- [Messenger] Добавлена заглушка когда чат не выбран
- [Messenger] Чаты теперь открываются по маршруту /messenger/chat/:id
- [Messenger] Создана страница чата
- [Messenger] Убран лишний re-render у Layout по переходу между чатами
#### V 0.04 #### V 0.04
- Пункт Мессенджер теперь ведет по пути /messenger - Пункт Мессенджер теперь ведет по пути /messenger
- [Messenger] Добавлен sidebar - [Messenger] Добавлен sidebar

@ -16,6 +16,7 @@
"@types/uniqid": "^5.3.2", "@types/uniqid": "^5.3.2",
"axios": "^1.4.0", "axios": "^1.4.0",
"body-scroll-lock": "^4.0.0-beta.0", "body-scroll-lock": "^4.0.0-beta.0",
"date-fns": "^2.30.0",
"framer-motion": "^10.13.0", "framer-motion": "^10.13.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
@ -1755,6 +1756,21 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
}, },
"node_modules/date-fns": {
"version": "2.30.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
"dependencies": {
"@babel/runtime": "^7.21.0"
},
"engines": {
"node": ">=0.11"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/date-fns"
}
},
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",

@ -18,6 +18,7 @@
"@types/uniqid": "^5.3.2", "@types/uniqid": "^5.3.2",
"axios": "^1.4.0", "axios": "^1.4.0",
"body-scroll-lock": "^4.0.0-beta.0", "body-scroll-lock": "^4.0.0-beta.0",
"date-fns": "^2.30.0",
"framer-motion": "^10.13.0", "framer-motion": "^10.13.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@ -5,10 +5,11 @@ import IndexPage from "./pages/IndexPage"
import LoginPage from "./pages/LoginPage" import LoginPage from "./pages/LoginPage"
import RegisterPage from "./pages/RegisterPage" import RegisterPage from "./pages/RegisterPage"
import MessengerPage from "./pages/Messenger/MessengerPage" import MessengerPage from "./pages/Messenger/MessengerPage"
import ChatPage from "./pages/Messenger/ChatPage"
import { BrowserRouter, Routes, Route } from 'react-router-dom' import { BrowserRouter, Routes, Route } from 'react-router-dom'
import { checkAuth, userSlice } from "./store/reducers/UserSlice"; import { checkAuth, userSlice } from "./store/reducers/UserSlice";
import { useAppDispatch, useAppSelector } from "./hooks/redux" import { useAppDispatch, useAppSelector } from "./hooks/redux"
import Layout from "./components/Layouts/Messenger"
function App() { function App() {
const {isLoading} = useAppSelector(state => state.UserSlice); const {isLoading} = useAppSelector(state => state.UserSlice);
@ -35,7 +36,8 @@ function App() {
<Route path='/' element={<RequireAuth><IndexPage/></RequireAuth>}/> <Route path='/' element={<RequireAuth><IndexPage/></RequireAuth>}/>
<Route path='/login' element={<OnlyUnauthorized><LoginPage/></OnlyUnauthorized>}/> <Route path='/login' element={<OnlyUnauthorized><LoginPage/></OnlyUnauthorized>}/>
<Route path='/register' element={<OnlyUnauthorized><RegisterPage/></OnlyUnauthorized>}/> <Route path='/register' element={<OnlyUnauthorized><RegisterPage/></OnlyUnauthorized>}/>
<Route path='/messenger' element={<RequireAuth><MessengerPage/></RequireAuth>}/> <Route path='/messenger' element={<RequireAuth><Layout><MessengerPage/></Layout></RequireAuth>}/>
<Route path='/messenger/chat/:userid' element={<RequireAuth><Layout><ChatPage/></Layout></RequireAuth>}/>
</Routes> </Routes>
</BrowserRouter> </BrowserRouter>
) )

@ -0,0 +1,43 @@
import { FC, useRef, useEffect } from 'react'
import TopInfo from './TopInfo';
import Message from './Message';
import EmptyChat from './EmptyChat';
import SendMessage from './SendMessage';
import { useAppSelector } from '../../../hooks/redux';
const Chat: FC = () => {
const messagesEndRef = useRef<HTMLDivElement>(null)
const { user } = useAppSelector(state => state.UserSlice)
const { chat } = useAppSelector(state => state.MessengerSlice)
useEffect(() => {
if(messagesEndRef.current) {
messagesEndRef.current.scrollIntoView()
}
}, [chat.messages])
return (
<div className='w-full bg-gray-300 bg-chat-pattern flex flex-col'>
<TopInfo data={chat.user}/>
<div className="overflow-y-auto flex-grow custom-scroll">
<div className={['w-full flex flex-col mx-auto max-w-[1200px]', chat.messages.length > 0 ? 'mt-10' : 'h-full justify-center'].join(' ')}>
{chat.messages.length > 0
?
<>
{chat.messages.map(message=>
<Message key={message._id} msg={message} user={message.from === user._id ? user : chat.user} isMe={message.from === user._id ? true : false}/>
)}
<div ref={messagesEndRef}></div>
</>
:
<EmptyChat/>
}
</div>
</div>
<SendMessage/>
</div>
)
}
export default Chat;

@ -0,0 +1,13 @@
import {FC} from 'react'
import { IoChatbubblesOutline } from '@react-icons/all-files/io5/IoChatbubblesOutline'
const EmptyChat: FC = () => {
return (
<div className='flex flex-col items-center justify-center w-full text-gray-800'>
<div className="text-9xl mb-5"><IoChatbubblesOutline/></div>
<p className='text-xl font-medium'>Dialog is Empty</p>
</div>
)
}
export default EmptyChat;

@ -0,0 +1,33 @@
import { FC } from 'react'
import { IMessage } from '../../../models/IMessage'
import { User } from '../../../models/User';
import format from 'date-fns/format';
import { BsCheckAll } from '@react-icons/all-files/bs/BsCheckAll'
import Avatar from '../../UI/Avatar';
interface MessageProps {
msg: IMessage;
user?: User;
isMe: boolean;
}
const Message: FC<MessageProps> = ({msg, user, isMe}) => {
return (
<div className={['flex w-1/2 mb-10', isMe ? 'self-end justify-end' : 'self-start justify-start'].join(' ')}>
<Avatar className='-translate-y-[5px] order-2' avatar={user?.avatar}/>
<div className={['shadow-md rounded-md py-2 px-4 relative before:absolute before:border-[10px] before:border-transparent before:border-t-[10px] before:top-0', isMe ? 'bg-apricot order-1 mr-5 before:border-t-apricot before:right-0 before:translate-x-1/2' : 'bg-zinc-400 order-3 ml-5 before:zinc-t-gray-400 before:left-0 before:-translate-x-1/2'].join(' ')}>
<h2 className='font-medium mb-1'>{user?.name} {user?.sname}</h2>
<p className='text-sm'>{msg.msg}</p>
<div className="flex items-center justify-end">
<p className='text-xs'>{format(msg.time, 'H:mm')}</p>
{isMe &&
<span className={['ml-1 text-lg', msg.readed ? 'text-blue-600' : 'text-gray-800'].join(' ')}><BsCheckAll/></span>
}
</div>
</div>
</div>
)
}
export default Message;

@ -0,0 +1,28 @@
import { FC, useState } from 'react'
import Textarea from './Textarea';
import IcoButton from '../../UI/IcoButton';
import { BsMic } from '@react-icons/all-files/bs/BsMic';
import { VscSend } from '@react-icons/all-files/vsc/VscSend';
import {BsEmojiSmile} from '@react-icons/all-files/bs/BsEmojiSmile';
import {ImAttachment} from '@react-icons/all-files/im/ImAttachment';
const SendMessage: FC = () => {
const [msg, setMsg] = useState<string>('');
return (
<div className='bg-gray-800 border-l-2 flex items-center h-auto justify-between border-gray-700 px-12 p-2'>
<div className="flex items-center">
<IcoButton icon={<BsEmojiSmile/>} className='!px-3 !py-2'/>
<IcoButton icon={<ImAttachment/>} className='!px-3 !py-2'/>
</div>
<Textarea msg={msg} setMsg={setMsg}/>
{msg
?
<IcoButton icon={<VscSend/>}/>
:
<IcoButton icon={<BsMic/>}/>
}
</div>
)
}
export default SendMessage;

@ -0,0 +1,25 @@
import { FC, useRef, FormEvent } from 'react'
interface TextareaProps {
msg: string;
setMsg: (msg: string) => void,
}
const Textarea: FC<TextareaProps> = ({msg, setMsg}) => {
const ref = useRef<HTMLTextAreaElement>(null);
const textAreaHandler = (e: FormEvent) => {
const target = e.target as HTMLInputElement;
setMsg(target.value);
if(ref.current) {
ref.current.style.height = "25px";
ref.current.style.height = ref.current.scrollHeight.toString()+"px";
}
}
return (
<textarea ref={ref} value={msg} placeholder='Введите сообщение...' onInput={e=> textAreaHandler(e)} className='px-5 w-full text-sm resize-none custom-scroll focus:outline-none bg-transparent text-white h-[25px] max-h-[80px]'></textarea>
)
}
export default Textarea;

@ -0,0 +1,38 @@
import { FC } from 'react'
import { User } from '../../../models/User';
import Avatar from '../../UI/Avatar';
import IcoButton from '../../UI/IcoButton';
import formatDistanceToNow from 'date-fns/formatDistanceToNow';
import { BsTelephone } from '@react-icons/all-files/bs/BsTelephone';
import { BsCameraVideo } from '@react-icons/all-files/bs/BsCameraVideo';
interface TopInfoProps {
data: User;
}
const TopInfo: FC<TopInfoProps> = ({data}) => {
return (
<div className='bg-gray-800 border-l-2 flex justify-between border-gray-700 px-12 p-2'>
<div className="flex items-center">
<Avatar avatar={data.avatar} className='mr-3'/>
<div className="flex flex-col text-white">
<h2 className='font-semibold'>{data.name} {data.sname}</h2>
<p className='text-sm text-apricot'>
{data.online
?
'online'
:
formatDistanceToNow(data.lastOnline, {addSuffix: true})
}
</p>
</div>
</div>
<div className="flex items-center">
<IcoButton icon={<BsTelephone/>} className='mr-2'/>
<IcoButton icon={<BsCameraVideo/>}/>
</div>
</div>
)
}
export default TopInfo;

@ -1,25 +1,26 @@
import { FC } from 'react' import { FC } from 'react'
import { IChat } from '../../../models/IChat'; import { IChat } from '../../../models/IChat';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
//import { useLocation } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import format from 'date-fns/format';
interface ChatProps { interface ChatProps {
data: IChat data: IChat
} }
const Chat: FC<ChatProps>= ({data}) => { const Chat: FC<ChatProps>= ({data}) => {
// const location = useLocation(); const { userid } = useParams();
return ( return (
<Link to='/messenger' className={['p-5 flex w-full items-center relative hover:bg-gray-700', ''].join(' ')}> <Link to={'/messenger/chat/' + data._id} className={['p-5 flex w-full items-center relative hover:bg-gray-700', userid === data._id ? 'bg-gray-700' : null].join(' ')}>
<div className={['w-12 h-12 min-w-[48px] mr-3 relative', data.isOnline ? 'before:absolute before:w-4 before:h-4 before:bg-green-400 before:rounded-full before:bottom-0 before:right-0 before:border-[3px] before:border-gray-800' : null].join(' ')}> <div className={['w-12 h-12 min-w-[48px] mr-3 relative', data.isOnline ? 'before:absolute before:w-4 before:h-4 before:bg-green-400 before:rounded-full before:bottom-0 before:right-0 before:border-[3px] before:border-gray-800' : null].join(' ')}>
<img className='rounded-full w-[inherit] h-[inherit]' src={data.avatar} alt="avatar"/> <img className='rounded-full w-[inherit] h-[inherit]' src={data.avatar} alt="avatar"/>
</div> </div>
<div className="flex flex-col items-start overflow-hidden"> <div className="flex flex-col items-start overflow-hidden">
<h2 className='text-white font-medium mb-1'>{data.name + ' ' + data.sname}</h2> <h2 className='text-white font-medium mb-1'>{data.name + ' ' + data.sname}</h2>
<p className='text-gray-500 text-sm max-w-[200px] whitespace-nowrap overflow-hidden text-ellipsis'>{data.lastmsg.msg}</p> <p className='text-gray-500 text-sm max-w-[200px] pr-5 whitespace-nowrap overflow-hidden text-ellipsis'>{data.lastmsg.msg}</p>
</div> </div>
<span className="text-sm text-gray-500 absolute right-4 top-4">{data.lastmsg.time}</span> <span className="text-sm text-gray-500 absolute right-4 top-4">{format(data.lastmsg.time, 'H:mm')}</span>
{data.unreaded > 0 && {data.unreaded > 0 &&
<span className='bg-apricot rounded-full text-sm flex items-center justify-center min-w-[20px] text-gray-800 font-semibold h-5 absolute bottom-[22px] right-4'>{data.unreaded}</span> <span className='bg-apricot rounded-full text-sm flex items-center justify-center min-w-[20px] text-gray-800 font-semibold h-5 absolute bottom-[22px] right-4'>{data.unreaded}</span>
} }

@ -12,7 +12,7 @@ const Menu: FC = () => {
return ( return (
<nav className='flex flex-col h-full items-center'> <nav className='flex flex-col h-full items-center'>
<ul className='border-b border-b-gray-600 pb-8 flex flex-col items-center'> <ul className='border-b border-b-gray-600 pb-8 flex flex-col items-center'>
<MenuItem to='/messenger'><BsChatText/></MenuItem> <MenuItem activeOption='/messenger/chat' to='/messenger'><BsChatText/></MenuItem>
<MenuItem className='mb-0' to='/messenger/1'><BsTelephone/></MenuItem> <MenuItem className='mb-0' to='/messenger/1'><BsTelephone/></MenuItem>
</ul> </ul>
<ul className='pt-8 flex flex-col flex-grow items-center'> <ul className='pt-8 flex flex-col flex-grow items-center'>

@ -1,18 +1,19 @@
import { FC, PropsWithChildren } from 'react' import { FC, PropsWithChildren } from 'react'
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useLocation } from 'react-router-dom'; import { useBasePath } from '../../../hooks/useBasePath';
interface MenuItemProps { interface MenuItemProps {
to: string, to: string,
className?: string className?: string
activeOption?: string
} }
const MenuItem: FC<PropsWithChildren<MenuItemProps>> = ({to, className, children}) => { const MenuItem: FC<PropsWithChildren<MenuItemProps>> = ({to, className, activeOption, children}) => {
const location = useLocation(); const path = useBasePath();
return ( return (
<li className={['mb-6', className].join(' ')}><Link to={to} className={['text-white hover:text-apricot transition-all text-xl font-medium', location.pathname === to ? '!text-gray-800 block bg-apricot p-4 rounded-sm' : null].join(' ')}>{children}</Link></li> <li className={['mb-6', className].join(' ')}><Link to={to} className={['text-white hover:text-apricot transition-all text-xl font-medium', (path === to || path === activeOption) ? '!text-gray-800 block bg-apricot p-4 rounded-sm' : null].join(' ')}>{children}</Link></li>
) )
} }

@ -4,6 +4,7 @@ import { Link } from 'react-router-dom';
import Menu from './Menu'; import Menu from './Menu';
const Sidebar: FC = () => { const Sidebar: FC = () => {
return ( return (
<aside className='w-20 bg-gray-900 py-7 px-2 flex flex-col'> <aside className='w-20 bg-gray-900 py-7 px-2 flex flex-col'>
<Link to='/'><img className='w-14 mb-8' src={Logo} alt="logo"/></Link> <Link to='/'><img className='w-14 mb-8' src={Logo} alt="logo"/></Link>

@ -0,0 +1,13 @@
import { FC } from 'react'
import { IoChatbubblesOutline } from '@react-icons/all-files/io5/IoChatbubblesOutline'
const StartMessaging: FC = () => {
return (
<div className='flex flex-col items-center justify-center w-full text-gray-800'>
<div className="text-9xl mb-5"><IoChatbubblesOutline/></div>
<p className='text-xl font-medium'>Select chat to start messaging</p>
</div>
)
}
export default StartMessaging;

@ -0,0 +1,16 @@
import { FC } from 'react'
interface AvatarProps {
avatar?: string;
className?: string;
}
const Avatar: FC<AvatarProps> = ({avatar, className}) => {
return (
<div className={['w-12 h-12 min-w-[48px]', className].join(' ')}>
<img className='w-[inherit] h-[inherit] rounded-full' src={avatar} alt="avatar"/>
</div>
)
}
export default Avatar;

@ -0,0 +1,14 @@
import { FC } from 'react'
interface IcoButton {
icon: React.JSX.Element;
className?: string;
}
const IcoButton: FC<IcoButton> = ({icon, className}) => {
return (
<button className={['hover:bg-gray-700 py-3 px-5 rounded-sm transition-all mr-2 text-white text-xl', className].join(' ')}>{icon}</button>
)
}
export default IcoButton;

@ -0,0 +1,11 @@
import { useLocation, useParams } from 'react-router-dom';
export const useBasePath = () => {
const location = useLocation();
const params = useParams<Record<string, string>>();
return Object.values(params).reduce(
(path: string, param) => path.replace(`/${String(param)}`, ''),
location.pathname,
);
};

@ -1,4 +1,4 @@
import { Message } from "./Message"; import { IMessage } from "./IMessage";
export interface IChat { export interface IChat {
_id: string; _id: string;
@ -6,6 +6,6 @@ export interface IChat {
sname: string; sname: string;
avatar: string; avatar: string;
unreaded: number; unreaded: number;
lastmsg: Message; lastmsg: IMessage;
isOnline: boolean; isOnline: boolean;
} }

@ -0,0 +1,8 @@
export interface IMessage {
_id: string;
msg: string;
time: Date;
to?: string;
from?: string;
readed?: boolean;
}

@ -1,5 +0,0 @@
export interface Message {
_id: string;
msg: string;
time: string;
}

@ -5,4 +5,6 @@ export interface User {
sname: string; sname: string;
avatar?: string; avatar?: string;
role?: string; role?: string;
online?: boolean;
lastOnline: Date;
} }

@ -0,0 +1,14 @@
import { FC } from 'react'
import Chats from '../../components/Messenger/Chats/Chats';
import Chat from '../../components/Messenger/Chat/Chat';
const ChatPage: FC = () => {
return (
<>
<Chats/>
<Chat/>
</>
)
}
export default ChatPage;

@ -1,12 +1,14 @@
import { FC } from 'react' import { FC } from 'react'
import Layout from '../../components/Layouts/Messenger';
import Chats from '../../components/Messenger/Chats/Chats'; import Chats from '../../components/Messenger/Chats/Chats';
import StartMessaging from '../../components/Messenger/StartMessaging';
const MessengerPage: FC = () => { const MessengerPage: FC = () => {
return ( return (
<Layout> <>
<Chats/> <Chats/>
</Layout> <StartMessaging/>
</>
) )
} }

@ -1,28 +1,62 @@
import { createSlice } from "@reduxjs/toolkit" import { createSlice } from "@reduxjs/toolkit"
import { User } from "../../models/User";
import { IChat } from "../../models/IChat"; import { IChat } from "../../models/IChat";
import { faker } from '@faker-js/faker'; import { faker } from '@faker-js/faker';
import { IMessage } from "../../models/IMessage";
export interface MessengerState { export interface MessengerState {
chats: IChat[]; chats: IChat[];
chat: {
user: User,
messages: IMessage[]
}
isLoading: boolean; isLoading: boolean;
} }
const initialState: MessengerState = { const initialState: MessengerState = {
chats: [ chats: [
{_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 1, isOnline: true, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: '23:14'}}, {_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 1, isOnline: true, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime()}},
{_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 4, isOnline: false, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: '22:18'}}, {_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 4, isOnline: false, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime()}},
{_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 0, isOnline: true, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: '12:10'}}, {_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 0, isOnline: true, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime()}},
{_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 0, isOnline: false, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: '16:04'}}, {_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 0, isOnline: false, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime()}},
{_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 0, isOnline: true, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: '18:43'}}, {_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 0, isOnline: true, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime()}},
{_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 1, isOnline: true, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: '23:14'}}, {_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 1, isOnline: true, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime()}},
{_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 4, isOnline: false, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: '22:18'}}, {_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 4, isOnline: false, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime()}},
{_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 0, isOnline: true, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: '12:10'}}, {_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 0, isOnline: true, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime()}},
{_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 0, isOnline: false, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: '16:04'}}, {_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 0, isOnline: false, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime()}},
{_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 0, isOnline: true, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: '18:43'}} {_id: faker.string.uuid(), name: faker.person.firstName(), sname: faker.person.lastName(), avatar: faker.internet.avatar(), unreaded: 0, isOnline: true, lastmsg: {_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime()}}
], ],
chat: {
user: {
_id: faker.string.uuid(),
email: faker.internet.email(),
name: faker.person.firstName(),
sname: faker.person.lastName(),
avatar: faker.internet.avatar(),
online: true,
lastOnline: faker.date.anytime(),
},
messages: [
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: faker.string.uuid(), to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: faker.string.uuid(), to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: faker.string.uuid(), to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: faker.string.uuid(), to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: faker.string.uuid(), to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: faker.string.uuid(), to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: faker.string.uuid(), to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: faker.string.uuid(), to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: faker.string.uuid(), to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: faker.string.uuid(), to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: faker.string.uuid(), to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: faker.string.uuid(), to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: faker.string.uuid(), to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: '64bc6386f0a1f55e83bf04aa', to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: faker.string.uuid(), to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: faker.string.uuid(), to: faker.string.uuid(), readed: true},
{_id: faker.string.uuid(), msg: faker.lorem.sentence(), time: faker.date.anytime(), from: '64bc6386f0a1f55e83bf04aa', to: faker.string.uuid(), readed: false}
]
},
isLoading: true isLoading: true
} }

@ -16,14 +16,8 @@ export interface UserState {
} }
const initialState: UserState = { const initialState: UserState = {
user: { user: {} as User,
_id: '',
email: '',
name: '',
sname: ''
},
isAuth: false, isAuth: false,
isLoading: true isLoading: true
} }

@ -8,6 +8,9 @@ export default {
extend: { extend: {
colors: { colors: {
'apricot': '#fbceb1', 'apricot': '#fbceb1',
},
backgroundImage: {
'chat-pattern': "url('/chat-pattern.webp')",
} }
}, },
}, },

Loading…
Cancel
Save