adding profile page

This commit is contained in:
Roland Osborne 2022-08-16 12:13:17 -07:00
parent f59b4ba8d2
commit 979288d1fc
18 changed files with 434 additions and 65 deletions

View File

@ -7,18 +7,29 @@ const Colors = {
grey: '#888888',
white: '#ffffff',
divider: '#dddddd',
mask: '#dddddd',
encircle: '#cccccc',
alert: '#ff8888',
enabled: '#444444',
disabled: '#aaaaaa',
text: '#444444',
link: '#0077CC',
itemDivider: '#eeeeee',
connected: '#44cc44',
connecting: '#dd88ff',
requested: '#4488ff',
pending: '#22aaaa',
confirmed: '#aaaaaa',
error: '#ff4444',
profileForm: '#e8e8e8',
profileDivider: '#aaaaaa',
statsForm: '#ededed',
statsDivider: '#afafaf',
channel: '#f2f2f2',
card: '#eeeeee',
};
export default Colors;

View File

@ -12,7 +12,7 @@ import { Channels } from './channels/Channels';
import { Cards } from './cards/Cards';
import { Contact } from './contact/Contact';
import { Profile } from './profile/Profile';
import { Stats } from './stats/Stats';
import { Account } from './account/Account';
import { Welcome } from './welcome/Welcome';
import { BottomNav } from './bottomNav/BottomNav';
@ -31,8 +31,13 @@ export function Session() {
}
}, [app, navigate]);
const openProfile = () => {
actions.openProfile();
const closeAccount = () => {
actions.closeProfile();
actions.closeAccount();
}
const openAccount = () => {
actions.openAccount();
actions.closeCards();
actions.closeContact();
}
@ -40,15 +45,17 @@ export function Session() {
const openCards = () => {
actions.openCards();
actions.closeProfile();
actions.closeStats();
actions.closeAccount();
}
console.log("STATE", state);
return (
<SessionWrapper>
{ (viewport.state.display === 'xlarge') && (
<div class="desktop-layout noselect">
<div class="left">
<Identity openProfile={openProfile} openCards={openCards} cardUpdated={state.cardUpdated} />
<Identity openAccount={openAccount} openCards={openCards} cardUpdated={state.cardUpdated} />
<div class="bottom">
<Channels />
</div>
@ -66,7 +73,7 @@ export function Session() {
)}
{ state.profile && (
<div class="reframe">
<Profile />
<Profile closeProfile={actions.closeProfile} />
</div>
)}
</div>
@ -82,9 +89,9 @@ export function Session() {
<Cards close={actions.closeCards} />
</div>
)}
{ state.profile && (
{ (state.profile || state.account) && (
<div class="reframe">
<Stats />
<Account closeAccount={closeAccount} openProfile={actions.openProfile} />
</div>
)}
</div>
@ -93,7 +100,7 @@ export function Session() {
{ (viewport.state.display === 'large' || viewport.state.display === 'medium') && (
<div class="tablet-layout noselect">
<div class="left">
<Identity openProfile={actions.openProfile} openCards={actions.openCards} cardUpdated={state.cardUpdated} />
<Identity openAccount={actions.openProfile} openCards={actions.openCards} cardUpdated={state.cardUpdated} />
<div class="bottom">
<Channels />
</div>
@ -120,15 +127,10 @@ export function Session() {
)}
</Drawer>
</Drawer>
<Drawer width={'33%'} closable={false} onClose={actions.closeProfile} visible={state.profile} zIndex={40}>
{ state.profile && (
<Profile />
<Drawer bodyStyle={{ padding: 0 }} width={'33%'} closable={false} onClose={closeAccount} visible={state.profile || state.account} zIndex={40}>
{ (state.profile || state.account) && (
<Profile closeProfile={closeAccount}/>
)}
<Drawer bodyStyle={{ padding: 0 }} width={'33%'} closable={false} onClose={actions.closeStats} visible={state.stats} zIndex={50}>
{ state.stats && (
<Stats />
)}
</Drawer>
</Drawer>
</div>
</div>
@ -159,16 +161,11 @@ export function Session() {
<Contact guid={state.contactGuid} />
</div>
)}
{ state.profile && (
{ (state.profile || state.account) && (
<div class="reframe">
<Profile />
</div>
)}
{ state.stats && (
<div class="reframe">
<Stats />
</div>
)}
</div>
<div class="bottom">
<BottomNav state={state} actions={actions} />

View File

@ -28,7 +28,7 @@ export const SessionWrapper = styled.div`
min-height: 0;
.bottom {
height: calc(100% - 64px);
height: calc(100% - 48px);
}
}
.center {
@ -65,7 +65,7 @@ export const SessionWrapper = styled.div`
min-height: 0;
.bottom {
height: calc(100% - 64px);
height: calc(100% - 48px);
}
}
.right {

View File

@ -0,0 +1,30 @@
import { AccountWrapper } from './Account.styled';
import { DoubleRightOutlined } from '@ant-design/icons';
import { Checkbox } from 'antd';
import { SettingOutlined, LockOutlined } from '@ant-design/icons';
export function Account({ closeAccount, openProfile }) {
return (
<AccountWrapper>
<div class="header">
<div class="label">Account</div>
<div class="dismiss" onClick={closeAccount}>
<DoubleRightOutlined />
</div>
</div>
<div class="content">
<Checkbox>Visible in Registry</Checkbox>
<div class="link" onClick={openProfile}>
<SettingOutlined />
<div class="label">Update Profile</div>
</div>
<div class="link">
<LockOutlined />
<div class="label">Change Login</div>
</div>
</div>
</AccountWrapper>
);
}

View File

@ -0,0 +1,59 @@
import styled from 'styled-components';
import Colors from 'constants/Colors';
export const AccountWrapper = styled.div`
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
background-color: ${Colors.statsForm};
.header {
width: 100%;
height: 48px;
border-bottom: 1px solid ${Colors.statsDivider};
display: flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
font-size: 18px;
padding: 16px;
.label {
flex-grow: 1;
display: flex;
justify-content: center;
}
.dismiss {
font-size: 18px;
color: ${Colors.text};
cursor: pointer;
}
}
.content {
min-height: 0;
width: 100%;
overflow: scroll;
display: flex;
flex-direction: column;
justify-content: center;
padding-top: 32px;
align-items: center;
.link {
color: ${Colors.primary};
padding-top: 16px;
display: flex;
flex-direction: row;
align-items: center;
cursor: pointer;
.label {
padding-left: 8px;
}
}
}
`

View File

@ -18,7 +18,7 @@ export function BottomNav({ state, actions }) {
actions.closeCards();
actions.closeContact();
actions.closeProfile();
actions.closeStats();
actions.closeAccount();
actions.closeConversation();
}
@ -27,7 +27,6 @@ export function BottomNav({ state, actions }) {
actions.closeCards();
actions.closeContact();
actions.openProfile();
actions.closeStats();
actions.closeConversation();
}
@ -36,7 +35,7 @@ export function BottomNav({ state, actions }) {
actions.openCards();
actions.closeContact();
actions.closeProfile();
actions.closeStats();
actions.closeAccount();
actions.closeConversation();
}

View File

@ -23,7 +23,7 @@ export function Cards({ close }) {
)}
<div class="filter">
<Input bordered={false} allowClear={true} placeholder="Contacts" prefix={<SearchOutlined />}
size="large" spellCheck="false" onChange={(e) => actions.onFilter(e.target.value)} />
spellCheck="false" onChange={(e) => actions.onFilter(e.target.value)} />
</div>
{ state.display === 'small' && (
<div class="inline">

View File

@ -6,7 +6,7 @@ export const CardsWrapper = styled.div`
width: 100%;
display: flex;
flex-direction: column;
background-color: ${Colors.formFocus};
background-color: ${Colors.card};
.view {
min-height: 0;
@ -15,10 +15,14 @@ export const CardsWrapper = styled.div`
}
.search {
padding: 12px;
border-bottom: 1px solid ${Colors.divider};
display: flex;
flex-direction: row;
height: 48px;
padding-left: 16px;
padding-right: 16px;
padding-top: 8px;
padding-bottom: 8px;
.sorted {
color: ${Colors.enabled};
@ -65,7 +69,7 @@ export const CardsWrapper = styled.div`
}
.bar {
height: 64px;
height: 48px;
width: 100%;
display: flex;
flex-shrink: 0;
@ -73,9 +77,9 @@ export const CardsWrapper = styled.div`
align-items: center;
justify-content: center;
background-color: ${Colors.formBackground};
border-top: 2px solid ${Colors.divider};
padding-bottom: 16px;
padding-top: 16px;
border-top: 1px solid ${Colors.divider};
padding-bottom: 12px;
padding-top: 12px;
position: relative;
}

View File

@ -13,7 +13,7 @@ export function Channels() {
<div class="search">
<div class="filter">
<Input bordered={false} allowClear={true} placeholder="Channels" prefix={<SearchOutlined />}
size="large" spellCheck="false" onChange={(e) => actions.onFilter(e.target.value)} />
spellCheck="false" onChange={(e) => actions.onFilter(e.target.value)} />
</div>
{ state.display === 'small' && (
<div class="inline">

View File

@ -15,7 +15,7 @@ export const ChannelsWrapper = styled.div`
}
.search {
padding: 12px;
padding: 8px;
border-bottom: 1px solid ${Colors.divider};
display: flex;
flex-direction: row;
@ -40,7 +40,7 @@ export const ChannelsWrapper = styled.div`
}
.bar {
height: 64px;
height: 48px;
width: 100%;
display: flex;
flex-shrink: 0;
@ -48,9 +48,9 @@ export const ChannelsWrapper = styled.div`
align-items: center;
justify-content: center;
background-color: ${Colors.formBackground};
border-top: 2px solid ${Colors.divider};
padding-bottom: 16px;
padding-top: 16px;
border-top: 1px solid ${Colors.divider};
padding-bottom: 12px;
padding-top: 12px;
position: relative;
}

View File

@ -6,9 +6,10 @@ export const ChannelItemWrapper = styled.div`
width: 100%;
display: flex;
align-items: center;
border-bottom: 1px solid ${Colors.divider};
border-bottom: 1px solid ${Colors.itemDivider};
padding-left: 16px;
padding-right: 16px;
line-height: 16px;
&:hover {
background-color: ${Colors.formHover};

View File

@ -4,14 +4,14 @@ import { IdentityWrapper, ErrorNotice, InfoNotice } from './Identity.styled';
import { useIdentity } from './useIdentity.hook';
import { InfoCircleOutlined, ExclamationCircleOutlined, DownOutlined } from '@ant-design/icons';
export function Identity({ openProfile, openCards, cardUpdated }) {
export function Identity({ openAccount, openCards, cardUpdated }) {
const { state, actions } = useIdentity();
const menu = (
<Menu>
<Menu.Item key="0">
<div onClick={openProfile}>Profile</div>
<div onClick={openAccount}>Account</div>
</Menu.Item>
<Menu.Item key="1">
<div onClick={openCards}>Contacts</div>
@ -26,7 +26,7 @@ export function Identity({ openProfile, openCards, cardUpdated }) {
<Dropdown overlay={menu} overlayStyle={{ minWidth: 0 }} trigger={['click']} placement="bottomRight">
<IdentityWrapper>
{ state.init && (
<Logo url={state.url} width={48} height={48} radius={4} />
<Logo url={state.url} width={40} height={40} radius={4} />
)}
<div class="label">
<div class="name">{state.name}</div>

View File

@ -3,13 +3,13 @@ import Colors from 'constants/Colors';
export const IdentityWrapper = styled.div`
width: 100%;
height: 64px;
height: 48px;
display: flex;
flex-direction: row;
align-items: center;
padding-left: 16px;
padding-right: 16px;
border-bottom: 2px solid ${Colors.divider};
border-bottom: 1px solid ${Colors.divider};
background-color: ${Colors.formBackground};
flex-shrink: 0;
@ -37,10 +37,11 @@ export const IdentityWrapper = styled.div`
justify-content: center;
.name {
font-size: 1.2em;
font-size: 14px;
}
.handle {
font-size: 12px;
display: flex;
flex-direction: row;
justify-content: center;

View File

@ -1,18 +1,78 @@
import { useContext } from 'react';
import { Button } from 'antd';
import { Button, Checkbox } from 'antd';
import { AppContext } from 'context/AppContext';
import { ViewportContext } from 'context/ViewportContext';
import { ProfileWrapper } from './Profile.styled';
import { useProfile } from './useProfile.hook';
import { Logo } from 'logo/Logo';
import { LockOutlined, RightOutlined, EditOutlined, BookOutlined, EnvironmentOutlined } from '@ant-design/icons';
export function Profile() {
export function Profile({ closeProfile }) {
const app = useContext(AppContext);
const viewport = useContext(ViewportContext);
const { state, actions } = useProfile();
const Image = (
<div class="logo">
<Logo url={state.url} width={'100%'} radius={8} />
<div class="edit">
<EditOutlined />
</div>
</div>
);
const Details = (
<div class="details">
<div class="name">
<div class="data">{ state.name }</div>
<EditOutlined />
</div>
<div class="location">
<EnvironmentOutlined />
<div class="data">{ state.location }</div>
</div>
<div class="description">
<BookOutlined />
<div class="data">{ state.description }</div>
</div>
</div>
);
return (
<div>
<Button type="primary" onClick={() => app.actions.logout()}>LOGOUT</Button>
<div>{ JSON.stringify(viewport.state) }</div>
</div>
<ProfileWrapper>
{ state.init && state.display === 'xlarge' && (
<>
<div class="header">
<div class="handle">{ state.handle }</div>
<div class="close" onClick={closeProfile}>
<RightOutlined />
</div>
</div>
<div class="content">
{ Image }
{ Details }
</div>
</>
)}
{ state.init && state.display !== 'xlarge' && (
<div class="view">
<div class="title">{ state.handle }</div>
<div class="section">Profile Settings</div>
<div class="controls">
{ Image }
{ Details }
</div>
<div class="section">Account Settings</div>
<div class="controls">
<Checkbox>Visible in Registry</Checkbox>
<div class="link">
<LockOutlined />
<div class="label">Change Login</div>
</div>
</div>
</div>
)}
</ProfileWrapper>
);
}

View File

@ -0,0 +1,173 @@
import styled from 'styled-components';
import Colors from 'constants/Colors';
export const ProfileWrapper = styled.div`
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
background-color: ${Colors.profileForm};
.header {
margin-left: 16px;
margin-right: 16px;
height: 48px;
border-bottom: 1px solid ${Colors.profileDivider};
display: flex;
flex-direction: row;
align-items: center;
flex-shrink: 0;
.handle {
font-size: 20px;
font-weight: bold;
flex-grow: 1;
padding-left: 16px;
}
.close {
font-size: 16px;
color: ${Colors.primary};
cursor: pointer;
padding-right: 16px;
}
}
.content {
min-height: 0;
width: 100%;
overflow: scroll;
display: flex;
flex-direction: row;
justify-content: center;
padding-top: 32px;
.logo {
position: relative;
width: 20vw;
margin-right: 32px;
.edit {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
width: 24px;
height: 24px;
bottom: 0;
right: 0;
color: ${Colors.link};
background-color: ${Colors.mask};
cursor: pointer;
}
}
}
.view {
width: 100%;
height: 100%;
overflow: scroll;
display: flex;
flex-direction: column;
align-items: center;
.title {
font-size: 18px;
font-weight: bold;
}
.logo {
position: relative;
width: 80%;
margin-bottom: 16px;
.edit {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
width: 24px;
height: 24px;
bottom: 0;
right: 0;
color: ${Colors.link};
background-color: ${Colors.mask};
cursor: pointer;
}
}
.section {
width: 100%;
color: ${Colors.grey};
padding-top: 16px;
font-size: 12px;
display: flex;
justify-content: center;
}
.controls {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: 1px solid ${Colors.divider};
border-radius: 4px;
padding: 8px;
width: 75%;
}
.link {
display: flex;
flex-direction: row;
align-items: center;
cursor: pointer;
color: ${Colors.primary};
padding-top: 8px;
.label {
padding-left: 8px;
}
}
}
.details {
display: flex;
flex-direction: column;
.name {
display: flex;
flex-direction: row;
align-items: center;
.data {
padding-right: 8px;
font-size: 24px;
font-weight: bold;
}
}
.location {
display: flex;
flex-direction: row;
align-items: center;
padding-bottom: 8px;
.data {
padding-left: 8px;
}
}
.description {
display: flex;
flex-direction: row;
align-items: center;
padding-bottom: 8px;
.data {
padding-left: 8px;
}
}
}
`

View File

@ -0,0 +1,38 @@
import { useState, useEffect, useContext } from 'react';
import { ProfileContext } from 'context/ProfileContext';
import { AppContext } from 'context/AppContext';
import { ViewportContext } from 'context/ViewportContext';
export function useProfile() {
const [state, setState] = useState({
init: false,
});
const app = useContext(AppContext);
const viewport = useContext(ViewportContext);
const profile = useContext(ProfileContext);
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
}
useEffect(() => {
if (profile.state.init) {
const { name, handle, location, description, image } = profile.state.profile;
let url = !image ? null : profile.actions.profileImageUrl();
updateState({ init: true, name, handle, url, location, description });
}
}, [profile]);
useEffect(() => {
updateState({ display: viewport.state.display });
}, [viewport]);
const actions = {
logout: app.actions.logout,
};
return { state, actions };
}

View File

@ -1,4 +0,0 @@
export function Stats() {
return <div>STATS</div>
}

View File

@ -11,7 +11,7 @@ export function useSession() {
cards: false,
contact: false,
profile: false,
stats: false,
account: false,
});
const card = useContext(CardContext);
@ -67,11 +67,11 @@ export function useSession() {
closeProfile: () => {
updateState({ profile: false });
},
openStats: () => {
updateState({ stats: true });
openAccount: () => {
updateState({ account: true });
},
closeStats: () => {
updateState({ stats: false });
closeAccount: () => {
updateState({ account: false });
},
closeConversation: () => {
updateState({ conversation: false });