rendering card updated status

This commit is contained in:
Roland Osborne 2022-08-13 11:24:49 -07:00
parent 35a4a51094
commit cedd337ab0
9 changed files with 133 additions and 25 deletions

View File

@ -35,7 +35,7 @@ export function Session() {
{ (viewport.state.display === 'xlarge') && (
<div class="desktop-layout noselect">
<div class="left">
<Identity openCards={actions.openCards} />
<Identity openCards={actions.openCards} cardUpdated={state.cardUpdated} />
<div class="bottom">
<Channels />
</div>
@ -75,7 +75,7 @@ export function Session() {
{ (viewport.state.display === 'large' || viewport.state.display === 'medium') && (
<div class="tablet-layout noselect">
<div class="left">
<Identity openCards={actions.openCards} />
<Identity openCards={actions.openCards} cardUpdated={state.cardUpdated} />
<div class="bottom">
<Channels />
</div>

View File

@ -1,6 +1,6 @@
import { Input, List } from 'antd';
import { CardsWrapper } from './Cards.styled';
import { RightOutlined, UserOutlined, SearchOutlined } from '@ant-design/icons';
import { SortAscendingOutlined, RightOutlined, UserOutlined, SearchOutlined } from '@ant-design/icons';
import { useCards } from './useCards.hook';
import { CardItem } from './cardItem/CardItem';
@ -12,6 +12,16 @@ export function Cards({ close }) {
<CardsWrapper>
<div class="view">
<div class="search">
{ !state.sorted && (
<div class="unsorted" onClick={() => actions.setSort(true)}>
<SortAscendingOutlined />
</div>
)}
{ state.sorted && (
<div class="sorted" onClick={() => actions.setSort(false)}>
<SortAscendingOutlined />
</div>
)}
<div class="filter">
<Input bordered={false} allowClear={true} placeholder="Contacts" prefix={<SearchOutlined />}
size="large" spellCheck="false" onChange={(e) => actions.onFilter(e.target.value)} />

View File

@ -19,6 +19,25 @@ export const CardsWrapper = styled.div`
display: flex;
flex-direction: row;
.sorted {
color: ${Colors.enabled};
font-size: 18px;
padding-right: 8px;
display: flex;
align-items: center;
cursor: pointer;
}
.unsorted {
color: ${Colors.disabled};
font-size: 18px;
padding-right: 8px;
display: flex;
align-items: center;
cursor: pointer;
}
.filter {
border: 1px solid ${Colors.divider};
background-color: ${Colors.white};
@ -70,7 +89,7 @@ export const CardsWrapper = styled.div`
padding-left: 16px;
padding-right: 16px;
border-radius: 4px;
font-size: 18px;
font-size: 14px;
cursor: pointer;
height: 100%;

View File

@ -1,3 +1,3 @@
export function CardItem() {
return <div>CARD ITEM</div>
export function CardItem({ item }) {
return <div>{ item?.data?.cardProfile?.name }</div>
}

View File

@ -7,6 +7,7 @@ export function useCards() {
const [filter, setFilter] = useState(null);
const [state, setState] = useState({
sorted: false,
display: null,
cards: [],
busy: false }
@ -23,10 +24,44 @@ export function useCards() {
onFilter: (value) => {
setFilter(value.toUpperCase());
},
setSort: (value) => {
updateState({ sorted: value });
},
};
useEffect(() => {
}, [card]);
const contacts = Array.from(card.state.cards.values());
let filtered = contacts.filter((contact) => {
if (!filter) {
return true;
}
if (!contact?.data?.cardProfile?.name) {
return false;
}
return contact.data.cardProfile.name.toUpperCase().includes(filter);
});
if (state.sorted) {
filtered.sort((a, b) => {
if (a?.data?.cardProfile?.name > b?.data?.cardProfile?.name) {
return -1;
}
return 1;
});
}
else {
filtered.sort((a, b) => {
if (a?.data?.cardDetails?.statusUpdated > b?.data?.cardDetails?.statusUpdated) {
return -1;
}
return 1;
});
}
updateState({ cards: filtered });
}, [card, filter, state.sorted]);
useEffect(() => {
updateState({ display: viewport.state.display });

View File

@ -64,7 +64,7 @@ export const ChannelsWrapper = styled.div`
padding-left: 16px;
padding-right: 16px;
border-radius: 4px;
font-size: 18px;
font-size: 14px;
cursor: pointer;
height: 100%;

View File

@ -1,10 +1,10 @@
import { Dropdown, Menu, Tooltip } from 'antd';
import { Logo } from 'logo/Logo';
import { IdentityWrapper } from './Identity.styled';
import { IdentityWrapper, ErrorNotice, InfoNotice } from './Identity.styled';
import { useIdentity } from './useIdentity.hook';
import { ExclamationCircleOutlined, DownOutlined } from '@ant-design/icons';
import { InfoCircleOutlined, ExclamationCircleOutlined, DownOutlined } from '@ant-design/icons';
export function Identity({ openCards }) {
export function Identity({ openCards, cardUpdated }) {
const { state, actions } = useIdentity();
@ -31,15 +31,25 @@ export function Identity({ openCards }) {
<div class="label">
<div class="name">{state.name}</div>
<div class="handle">
<div class="alert">
<div class="notice">
{ state.disconnected && (
<Tooltip placement="right" title="disconnected from server">
<ErrorNotice>
<ExclamationCircleOutlined />
</ErrorNotice>
</Tooltip>
)}
</div>
<div>{state.handle}</div>
<div class="alert"></div>
<div class="notice">
{ cardUpdated && (
<Tooltip placement="right" title="contacts have updated">
<InfoNotice>
<InfoCircleOutlined />
</InfoNotice>
</Tooltip>
)}
</div>
</div>
</div>
<div class="drop">

View File

@ -47,11 +47,21 @@ export const IdentityWrapper = styled.div`
align-items: center;
font-weight: bold;
.alert {
width: 24px;
color: ${Colors.alert};
.notice {
width: 32px;
display: flex;
flex-direction: row;
justify-content: center;
}
}
}
`;
export const ErrorNotice = styled.div`
color: ${Colors.alert};
`
export const InfoNotice = styled.div`
color: ${Colors.primary};
`

View File

@ -1,8 +1,11 @@
import { useState, useEffect } from 'react';
import { useContext, useState, useEffect, useRef } from 'react';
import { CardContext } from 'context/CardContext';
import { StoreContext } from 'context/StoreContext';
export function useSession() {
const [state, setState] = useState({
cardUpdated: false,
conversation: false,
details: false,
cards: false,
@ -10,18 +13,39 @@ export function useSession() {
profile: false,
});
const card = useContext(CardContext);
const store = useContext(StoreContext);
const storeStatus = useRef(null);
const cardStatus = useRef(null);
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
}
useEffect(() => {
setTimeout(() => {
updateState({ cards: true });
}, 1000);
setTimeout(() => {
updateState({ contact: true });
}, 2000);
}, []);
const contacts = Array.from(card.state.cards.values());
let updated;
contacts.forEach(contact => {
if (!updated || updated < contact?.data?.cardDetail?.statusUpdated) {
updated = contact?.data?.cardDetail?.statusUpdated;
}
});
if (state.cards) {
cardStatus.current = updated;
storeStatus.current = updated;
store.actions.setValue('cards:updated', updated);
}
updateState({ cardUpdated: cardStatus.current > storeStatus.current });
}, [card]);
useEffect(() => {
storeStatus.current = store.actions.getValue('cards:updated');
updateState({ cardUpdated: cardStatus.current > storeStatus.current });
}, [store]);
const actions = {
closeDetails: () => {