feat: lots of updates
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
// import React from 'react';
|
||||
import styled from "styled-components";
|
||||
import { AiOutlineCaretDown, AiOutlineSound } from "react-icons/ai";
|
||||
import { MdOutlineKeyboardVoice } from "react-icons/md";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 16px 12px;
|
||||
width: -webkit-fill-available;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.profile {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 5px;
|
||||
.avatar {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.toggle {
|
||||
}
|
||||
}
|
||||
.settings {
|
||||
gap: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
`;
|
||||
export default function CurrentUser({ collaspe = false }) {
|
||||
const { user } = useSelector((store) => store.authData);
|
||||
if (!user) return null;
|
||||
const { name } = user;
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<div className="profile" title={name}>
|
||||
<img
|
||||
title={name}
|
||||
src={`https://avatars.dicebear.com/api/adventurer-neutral/${name}.svg`}
|
||||
alt="user avatar"
|
||||
className="avatar"
|
||||
/>
|
||||
<AiOutlineCaretDown className="toggle" width={20} color="#C4C4C4" />
|
||||
</div>
|
||||
{!collaspe && (
|
||||
<div className="settings">
|
||||
<AiOutlineSound className="icon" size={15} color="#1C1C1E" />
|
||||
<MdOutlineKeyboardVoice className="icon" size={15} color="#1C1C1E" />
|
||||
</div>
|
||||
)}
|
||||
</StyledWrapper>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// import React from 'react';
|
||||
import styled from "styled-components";
|
||||
import { HiChevronDoubleLeft } from "react-icons/hi";
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
height: 56px;
|
||||
padding: 0 16px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
box-shadow: 0px 1px 0px rgba(0, 0, 0, 0.1);
|
||||
&.collaspe {
|
||||
padding-right: 5px;
|
||||
}
|
||||
.server {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
.logo {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
white-space: nowrap;
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #4b5563;
|
||||
}
|
||||
}
|
||||
.arrow {
|
||||
cursor: pointer;
|
||||
transform-origin: center;
|
||||
transition: transform 0.5s ease-in-out;
|
||||
display: flex;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
.icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
&.collaspe {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
`;
|
||||
export default function ServerDropList({ data, toggle, collaspe = false }) {
|
||||
if (!data) return null;
|
||||
return (
|
||||
<StyledWrapper className={collaspe ? "collaspe" : ""}>
|
||||
<div className="server">
|
||||
<div className="logo">
|
||||
<img src={data.logo} alt="logo" />
|
||||
</div>
|
||||
{!collaspe && <h2 className="title">{data.name}</h2>}
|
||||
</div>
|
||||
<div onClick={toggle} className={`arrow ${collaspe ? "collaspe" : ""}`}>
|
||||
<HiChevronDoubleLeft className="icon" color="#BFBFBF" />
|
||||
</div>
|
||||
</StyledWrapper>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
// import React from 'react';
|
||||
import { RiAddFill } from "react-icons/ri";
|
||||
|
||||
import styled from "styled-components";
|
||||
import { IoLogoGithub } from "react-icons/io5";
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
padding: 0 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 20px;
|
||||
> hr {
|
||||
border: none;
|
||||
width: 40%;
|
||||
height: 1px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
.tools {
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
.tool,
|
||||
.add {
|
||||
cursor: pointer;
|
||||
gap: 9px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #4b5563;
|
||||
}
|
||||
.tool {
|
||||
.logo {
|
||||
border-radius: 5.5px;
|
||||
background: #fff;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.icon {
|
||||
width: 21px;
|
||||
height: 21px;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
white-space: nowrap;
|
||||
}
|
||||
&.add .logo {
|
||||
background: none;
|
||||
.icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export default function Tools({ collaspe = false }) {
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<hr />
|
||||
<ul className="tools">
|
||||
<li className="tool">
|
||||
<div className="logo">
|
||||
<img
|
||||
className="icon"
|
||||
src="https://static.nicegoodthings.com/project/ext/webrowse.logo.png"
|
||||
alt="logo"
|
||||
/>
|
||||
</div>
|
||||
{!collaspe && <h2 className="title">Webrowse</h2>}
|
||||
</li>
|
||||
<li className="tool">
|
||||
<div className="logo">
|
||||
<IoLogoGithub size={40} className="icon" />
|
||||
</div>
|
||||
{!collaspe && <h2 className="title">Github</h2>}
|
||||
</li>
|
||||
<li className="tool add">
|
||||
<div className="logo">
|
||||
<RiAddFill className="icon" size={40} color="#4B5563" />
|
||||
</div>
|
||||
{!collaspe && <h2 className="title">Add new app</h2>}
|
||||
</li>
|
||||
</ul>
|
||||
</StyledWrapper>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// import React from 'react';
|
||||
import { useState } from "react";
|
||||
import StyledWrapper from "./styled";
|
||||
import { Outlet, NavLink } from "react-router-dom";
|
||||
import ServerDropList from "./ServerDropList";
|
||||
import Tools from "./Tools";
|
||||
import usePreload from "./usePreload";
|
||||
|
||||
import CurrentUser from "./CurrentUser";
|
||||
|
||||
import ChatIcon from "../../assets/icons/chat.svg";
|
||||
import ContactIcon from "../../assets/icons/contact.svg";
|
||||
import NotificationHub from "../../common/component/NotificationHub";
|
||||
|
||||
export default function HomePage() {
|
||||
const { data, error, success } = usePreload();
|
||||
const [collaspe, setCollaspe] = useState(false);
|
||||
const toggleCollaspe = () => {
|
||||
setCollaspe((prev) => !prev);
|
||||
};
|
||||
console.log({ data, error, success });
|
||||
return (
|
||||
<>
|
||||
<NotificationHub />
|
||||
<StyledWrapper>
|
||||
<div className={`col left ${collaspe ? "collaspe" : ""}`}>
|
||||
<ServerDropList
|
||||
data={data?.server}
|
||||
collaspe={collaspe}
|
||||
toggle={toggleCollaspe}
|
||||
/>
|
||||
<nav className="nav">
|
||||
<NavLink className="link" to={"/chat"}>
|
||||
<img src={ChatIcon} alt="chat icon" /> {!collaspe && `Chat`}
|
||||
</NavLink>
|
||||
<NavLink className="link" to={"/contacts"}>
|
||||
<img src={ContactIcon} alt="contact icon" />{" "}
|
||||
{!collaspe && `Contacts`}
|
||||
</NavLink>
|
||||
</nav>
|
||||
<Tools collaspe={collaspe} />
|
||||
<CurrentUser collaspe={collaspe} />
|
||||
</div>
|
||||
<div className="col right">
|
||||
<Outlet />
|
||||
</div>
|
||||
</StyledWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import styled from "styled-components";
|
||||
const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: #f5f6f7;
|
||||
> .col {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
&.left {
|
||||
position: relative;
|
||||
/* background: #0891B2; */
|
||||
width: 180px;
|
||||
box-shadow: inset -1px 0px 0px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.5s ease-in;
|
||||
&.collaspe {
|
||||
width: 64px;
|
||||
}
|
||||
}
|
||||
&.right {
|
||||
width: 100%;
|
||||
}
|
||||
> .nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
padding: 24px 8px 10px 8px;
|
||||
.link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
text-decoration: none;
|
||||
padding: 10px 8px;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #4b5563;
|
||||
border-radius: 8px;
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default StyledWrapper;
|
||||
@@ -0,0 +1,39 @@
|
||||
// import React from 'react';
|
||||
import { useGetContactsQuery } from "../../app/services/contact";
|
||||
import { useGetChannelsQuery } from "../../app/services/channel";
|
||||
import { useGetServerQuery } from "../../app/services/server";
|
||||
// pollingInterval: 0,
|
||||
const querySetting = {
|
||||
refetchOnMountOrArgChange: true,
|
||||
};
|
||||
export default function usePreload() {
|
||||
const {
|
||||
isLoading: contactsLoading,
|
||||
isSuccess: contactsSuccess,
|
||||
isError: contactsError,
|
||||
data: contacts,
|
||||
} = useGetContactsQuery(undefined, querySetting);
|
||||
const {
|
||||
isLoading: serverLoading,
|
||||
isSuccess: serverSuccess,
|
||||
isError: serverError,
|
||||
data: server,
|
||||
} = useGetServerQuery(undefined, querySetting);
|
||||
const {
|
||||
isLoading: groupsLoading,
|
||||
isSuccess: groupsSuccess,
|
||||
isError: groupsError,
|
||||
data: groups,
|
||||
} = useGetChannelsQuery(undefined, querySetting);
|
||||
|
||||
return {
|
||||
loading: contactsLoading && groupsLoading && serverLoading,
|
||||
error: contactsError && groupsError && serverError,
|
||||
success: contactsSuccess && groupsSuccess && serverSuccess,
|
||||
data: {
|
||||
contacts,
|
||||
server,
|
||||
groups,
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user