added remainder of details

This commit is contained in:
Roland Osborne 2022-08-20 21:17:25 -07:00
parent a0bb8d5c6c
commit 1317c6f6d7
12 changed files with 237 additions and 50 deletions

BIN
net/web/src/images/team.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,10 +1,14 @@
import avatar from 'images/avatar.png';
import appstore from 'images/appstore.png';
import solution from 'images/solution.png';
import team from 'images/team.png';
export function Logo({ url, width, height, radius, img }) {
return (
<div style={{ borderRadius: radius, overflow: 'hidden' }}>
{ img === 'team' && (
<img src={team} alt="direct logo" width={width} height={height} />
)}
{ img === 'appstore' && (
<img src={appstore} alt="group logo" width={width} height={height} />
)}

View File

@ -4,7 +4,7 @@ import { CardSelectWrapper } from './CardSelect.styled';
import { SelectItem } from './selectItem/SelectItem';
import { useCardSelect } from './useCardSelect.hook';
export function CardSelect({ filter, unknown, select, selected }) {
export function CardSelect({ filter, unknown, select, selected, markup }) {
const { state, actions } = useCardSelect(filter);
@ -12,7 +12,7 @@ export function CardSelect({ filter, unknown, select, selected }) {
<CardSelectWrapper>
<List local={{ emptyText: '' }} itemLayout="horizontal" dataSource={state.cards} gutter="0"
renderItem={item => (
<SelectItem item={item} select={select} selected={selected} />
<SelectItem item={item} select={select} selected={selected} markup={markup} />
)}
/>
</CardSelectWrapper>

View File

@ -1,11 +1,11 @@
import { Switch } from 'antd';
import { SelectItemWrapper } from './SelectItem.styled';
import { Switch, Tooltip } from 'antd';
import { SelectItemWrapper, Markup } from './SelectItem.styled';
import { useSelectItem } from './useSelectItem.hook';
import { Logo } from 'logo/Logo';
export function SelectItem({ item, select, selected }) {
export function SelectItem({ item, select, selected, markup }) {
const { state, actions } = useSelectItem(item, selected);
const { state, actions } = useSelectItem(item, selected, markup);
const profile = item?.data?.cardProfile;
const detail = item?.data?.cardDetail;
@ -16,18 +16,31 @@ export function SelectItem({ item, select, selected }) {
return profile?.handle;
}
const onSelect = () => {
if (select) {
select(item.id);
}
}
return (
<SelectItemWrapper onClick={() => select(item.id)}>
<Logo url={state.logo} width={32} height={32} radius={8} />
<div class="details">
<div class="name">{ profile?.name }</div>
<div class="handle">{ handle() }</div>
</div>
{ select && (
<div class="switch">
<Switch checked={state.selected} onChange={() => select(item.id)} size="small" />
<SelectItemWrapper onClick={onSelect}>
<div class={ state.className }>
<Logo url={state.logo} width={32} height={32} radius={8} />
<div class="details">
<div class="name">{ profile?.name }</div>
<div class="handle">{ handle() }</div>
</div>
)}
{ select && (
<div class="switch">
<Switch checked={state.selected} onChange={onSelect} size="small" />
</div>
)}
{ state.markup && (
<Tooltip placement="left" title="channel host">
<Markup />
</Tooltip>
)}
</div>
</SelectItemWrapper>
);
}

View File

@ -2,16 +2,27 @@ import styled from 'styled-components';
import Colors from 'constants/Colors';
export const SelectItemWrapper = styled.div`
height: 48px;
width: 100%;
display: flex;
align-items: center;
padding-left: 8px;
padding-right: 8px;
cursor: pointer;
.active {
cursor: pointer;
height: 48px;
width: 100%;
padding-left: 8px;
padding-right: 8px;
display: flex;
align-items: center;
&:hover {
background-color: ${Colors.selectHover};
&:hover {
background-color: ${Colors.selectHover};
}
}
.passive {
height: 48px;
width: 100%;
padding-left: 8px;
padding-right: 8px;
display: flex;
align-items: center;
}
.details {
@ -41,3 +52,12 @@ export const SelectItemWrapper = styled.div`
flex-shrink: 0;
}
`
export const Markup = styled.div`
background-color: ${Colors.connected};
border-radius: 8px;
width: 8px;
height: 8px;
margin-right: 8px;
`;

View File

@ -1,12 +1,14 @@
import { useContext, useState, useEffect } from 'react';
import { CardContext } from 'context/CardContext';
export function useSelectItem(item, selected) {
export function useSelectItem(item, selected, markup) {
const [state, setState] = useState({
logo: null,
selected: false,
busy: false,
className: 'passive',
markup: false,
});
const card = useContext(CardContext);
@ -16,7 +18,12 @@ export function useSelectItem(item, selected) {
}
useEffect(() => {
updateState({ selected: selected.has(item.id) });
if (selected) {
updateState({ className: 'active', selected: selected.has(item.id) });
}
else {
updateState({ className: 'passive', markup: item.id === markup });
}
}, [selected]);
useEffect(() => {

View File

@ -17,7 +17,7 @@ export function useCardSelect(filter) {
let contacts = Array.from(card.state.cards.values());
let filtered = contacts.filter(filter);
updateState({ cards: filtered });
}, [card]);
}, [card, filter]);
const actions = {
};

View File

@ -1,4 +1,5 @@
import { ChannelItemWrapper } from './ChannelItem.styled';
import { Tooltip } from 'antd';
import { ChannelItemWrapper, Markup } from './ChannelItem.styled';
import { Logo } from 'logo/Logo';
import { AppstoreFilled, SolutionOutlined } from '@ant-design/icons';
@ -39,7 +40,9 @@ export function ChannelItem({ item, openChannel }) {
<div class="message">{ item.message }</div>
</div>
{ item.updated && (
<div class="markup"></div>
<Tooltip placement="right" title="new message">
<Markup />
</Tooltip>
)}
</div>
)}

View File

@ -55,15 +55,15 @@ export const ChannelItemWrapper = styled.div`
color: ${Colors.disabled};
}
}
.markup {
position: absolute;
right: 0;
border-radius: 8px;
background-color: ${Colors.background};
width: 8px;
height: 8px;
margin-right: 16px;
}
}
`
export const Markup = styled.div`
position: absolute;
right: 0;
border-radius: 8px;
background-color: ${Colors.background};
width: 8px;
height: 8px;
margin-right: 16px;
`;

View File

@ -1,12 +1,17 @@
import { Space } from 'antd';
import { DetailsWrapper } from './Details.styled';
import { DoubleRightOutlined } from '@ant-design/icons';
import { useDetails } from './useDetails.hook';
import { Logo } from 'logo/Logo';
import { EditOutlined } from '@ant-design/icons';
import { CardSelect } from '../cardSelect/CardSelect';
export function Details({ cardId, channelId, closeDetails, closeConversation, openContact }) {
const { state, actions } = useDetails(cardId, channelId);
console.log(state.contacts);
return (
<DetailsWrapper>
<div class="header">
@ -16,8 +21,51 @@ export function Details({ cardId, channelId, closeDetails, closeConversation, op
</div>
</div>
<div class="content" onClick={closeDetails}>
<div class="details">
<Logo url={state.logo} width={48} height={48} radius={4} img={state.img} />
<div class="description">
<div class="logo">
<Logo width={72} height={72} radius={4} img={state.img} />
</div>
<div class="stats">
{ state.host && (
<div class="subject edit">
<Space>
<div>{ state.subject }</div>
<EditOutlined />
</Space>
</div>
)}
{ !state.host && (
<div class="subject">{ state.subject }</div>
)}
{ state.host && (
<div class="host">host</div>
)}
{ !state.host && (
<div class="host">guest</div>
)}
<div class="created">{ state.started }</div>
</div>
</div>
{ state.host && (
<div class="button">Delete Channel</div>
)}
{ state.host && (
<div class="button">Edit Membership</div>
)}
{ !state.host && (
<div class="button">Leave Channel</div>
)}
<div class="label">Members</div>
<div class="members">
<CardSelect filter={(item) => {
console.log("CHECK: ", item.id, state.contacts);
if(state.contacts.includes(item.id)) {
console.log("YES");
return true;
}
return false;
}} unknown={0}
markup={cardId} />
</div>
</div>
</DetailsWrapper>

View File

@ -38,9 +38,77 @@ export const DetailsWrapper = styled.div`
overflow: scroll;
display: flex;
flex-direction: column;
justify-content: center;
padding-top: 32px;
align-items: center;
flex-grow: 1;
position: relative;
.label {
padding-top: 16px;
width: 100%;
border-bottom: 1px solid ${Colors.divider};
padding-left: 16px;
}
.members {
width: 100%;
min-height: 0;
overflow: scroll;
padding-left: 16px;
}
.button {
width: 144px;
padding: 4px;
border-radius: 4px;
color: ${Colors.white};
background-color: ${Colors.primary};
cursor: pointer;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: center;
}
.description {
display: flex;
flex-direction: row;
margin-bottom: 32px;
width: 100%;
.logo {
flex-shrink: 0;
width: 40%;
display: flex;
flex-direction: row;
justify-content: flex-end;
}
.stats {
display: flex;
flex-direction: column;
padding-left: 16px;
.edit {
display: flex;
flex-direction: row;
align-items: center;
cursor: pointer;
}
.subject {
font-size: 18px;
font-weight: bold;
padding-right: 8px;
}
.host {
font-size: 16px;
}
.created {
font-size: 14px;
}
}
}
`

View File

@ -7,6 +7,12 @@ export function useDetails(cardId, channelId) {
const [state, setState] = useState({
logo: null,
img: null,
subject: null,
server: null,
startedDate: null,
startedTime: null,
host: null,
contacts: [],
});
const card = useContext(CardContext);
@ -17,7 +23,7 @@ export function useDetails(cardId, channelId) {
}
useEffect(() => {
let logo, img;
let img, subject, host, started;
let chan;
if (cardId) {
const cardChan = card.state.cards.get(cardId);
@ -28,23 +34,41 @@ export function useDetails(cardId, channelId) {
else {
chan = channel.state.channels.get(channelId);
}
console.log(chan);
if (chan) {
if (chan.contacts?.length == 0) {
img = 'solution';
logo = null;
subject = 'Private';
}
else if (chan.contacts?.length > 1) {
img = 'appstore'
logo = null;
subject = 'Group';
}
else {
img = null;
logo = card.actions.getImageUrl(chan.contacts[0]?.id);
img = 'team';
subject = 'Direct'
}
const parsed = JSON.parse(chan.data.channelDetail.data);
if (parsed.subject) {
subject = parsed.subject;
}
const date = new Date(chan.data.channelDetail.created * 1000);
const now = new Date();
if(now.getTime() - date.getTime() < 86400000) {
started = date.toLocaleTimeString([], {hour: 'numeric', minute:'2-digit'});
}
else {
started = date.toLocaleDateString("en-US");
}
if (chan.cardId) {
host = false;
}
else {
host = true;
}
}
updateState({ logo, img });
updateState({ img, subject, host, started,
contacts: chan.contacts.map((contact) => contact?.id) });
}, [cardId, channelId, card, channel]);
const actions = {