mirror of
https://github.com/balzack/databag.git
synced 2025-02-11 19:19:16 +00:00
cleanup webapp cards component
This commit is contained in:
parent
8c343a7f60
commit
d21473e76b
@ -10,53 +10,54 @@ export function Cards({ closeCards, openContact, openListing }) {
|
||||
|
||||
return (
|
||||
<CardsWrapper>
|
||||
<div class="search">
|
||||
<div className="search">
|
||||
{ !state.sorted && (
|
||||
<div class="unsorted" onClick={() => actions.setSort(true)}>
|
||||
<div className="unsorted" onClick={() => actions.setSort(true)}>
|
||||
<SortAscendingOutlined />
|
||||
</div>
|
||||
)}
|
||||
{ state.sorted && (
|
||||
<div class="sorted" onClick={() => actions.setSort(false)}>
|
||||
<div className="sorted" onClick={() => actions.setSort(false)}>
|
||||
<SortAscendingOutlined />
|
||||
</div>
|
||||
)}
|
||||
<div class="filter">
|
||||
<div className="filter">
|
||||
<Input bordered={false} allowClear={true} placeholder="Contacts" prefix={<SearchOutlined />}
|
||||
spellCheck="false" onChange={(e) => actions.onFilter(e.target.value)} />
|
||||
</div>
|
||||
{ state.display === 'small' && (
|
||||
<div class="inline">
|
||||
<div class="add" onClick={openListing}>
|
||||
<div className="inline">
|
||||
<div className="add" onClick={openListing}>
|
||||
<UserOutlined />
|
||||
<div class="label">New</div>
|
||||
<div className="label">New</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{ state.display !== 'small' && (
|
||||
<div class="inline">
|
||||
<div class="dismiss" onClick={closeCards} >
|
||||
<div className="inline">
|
||||
<div className="dismiss" onClick={closeCards} >
|
||||
<DoubleRightOutlined />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div class="view">
|
||||
<div className="view">
|
||||
{ state.cards.length > 0 && (
|
||||
<List local={{ emptyText: '' }} itemLayout="horizontal" dataSource={state.cards} gutter="0"
|
||||
renderItem={item => (
|
||||
<CardItem item={item} open={openContact} />
|
||||
<CardItem item={item} tooltip={state.tooltip} resync={() => actions.resync(item.cardId)}
|
||||
open={() => openContact(item.guid)} />
|
||||
)} />
|
||||
)}
|
||||
{ state.cards.length === 0 && (
|
||||
<div class="empty">No Contacts</div>
|
||||
<div className="empty">No Contacts</div>
|
||||
)}
|
||||
</div>
|
||||
{ state.display !== 'small' && (
|
||||
<div class="bar">
|
||||
<div class="add" onClick={openListing}>
|
||||
<div className="bar">
|
||||
<div className="add" onClick={openListing}>
|
||||
<UpOutlined />
|
||||
<div class="label">Find New Contact</div>
|
||||
<div className="label">Find New Contact</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
@ -2,70 +2,58 @@ import { CardItemWrapper, StatusError,
|
||||
StatusConnected, StatusConnecting,
|
||||
StatusRequested, StatusPending,
|
||||
StatusConfirmed} from './CardItem.styled';
|
||||
import { useCardItem } from './useCardItem.hook';
|
||||
import { Logo } from 'logo/Logo';
|
||||
import { Tooltip } from 'antd';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons';
|
||||
|
||||
export function CardItem({ item, open }) {
|
||||
export function CardItem({ item, tooltip, resync, open }) {
|
||||
|
||||
const { state, actions } = useCardItem(item);
|
||||
const profile = item?.data?.cardProfile;
|
||||
const detail = item?.data?.cardDetail;
|
||||
|
||||
const handle = () => {
|
||||
if (profile?.node) {
|
||||
return profile.handle + '@' + profile.node;
|
||||
}
|
||||
return profile?.handle;
|
||||
}
|
||||
|
||||
const resync = (e) => {
|
||||
const onResync = (e) => {
|
||||
e.stopPropagation();
|
||||
actions.resync();
|
||||
resync();
|
||||
};
|
||||
|
||||
return (
|
||||
<CardItemWrapper onClick={() => open(profile.guid)}>
|
||||
<Logo url={state.logo} width={32} height={32} radius={8} />
|
||||
<div class="details">
|
||||
<div class="name">{ profile?.name }</div>
|
||||
<div class="handle">{ handle() }</div>
|
||||
<CardItemWrapper onClick={open}>
|
||||
<Logo url={item.logo} width={32} height={32} radius={8} />
|
||||
<div className="details">
|
||||
<div className="name">{ item.name }</div>
|
||||
<div className="handle">{ item.handle }</div>
|
||||
</div>
|
||||
<div class="markup">
|
||||
{ !state.resync && item.error && state.display === 'small' && (
|
||||
<StatusError onClick={resync}>
|
||||
<div className="markup">
|
||||
{ item.offsync && !item.tooltip && (
|
||||
<StatusError onClick={onResync}>
|
||||
<ExclamationCircleOutlined />
|
||||
</StatusError>
|
||||
)}
|
||||
{ !state.resync && item.error && state.display !== 'small' && (
|
||||
{ item.offsync && item.tooltip && (
|
||||
<Tooltip placement="left" title="sync error">
|
||||
<StatusError onClick={resync}>
|
||||
<StatusError onClick={onResync}>
|
||||
<ExclamationCircleOutlined />
|
||||
</StatusError>
|
||||
</Tooltip>
|
||||
)}
|
||||
{ detail?.status === 'connected' && (
|
||||
{ item.status === 'connected' && (
|
||||
<Tooltip placement="left" title="connected contact">
|
||||
<StatusConnected />
|
||||
</Tooltip>
|
||||
)}
|
||||
{ detail?.status === 'requested' && (
|
||||
{ item.status === 'requested' && (
|
||||
<Tooltip placement="left" title="connection requested by contact">
|
||||
<StatusRequested />
|
||||
</Tooltip>
|
||||
)}
|
||||
{ detail?.status === 'connecting' && (
|
||||
{ item.status === 'connecting' && (
|
||||
<Tooltip placement="left" title="requested contact connection">
|
||||
<StatusConnecting />
|
||||
</Tooltip>
|
||||
)}
|
||||
{ detail?.status === 'pending' && (
|
||||
{ item.status === 'pending' && (
|
||||
<Tooltip placement="left" title="unknwon contact connection request">
|
||||
<StatusPending />
|
||||
</Tooltip>
|
||||
)}
|
||||
{ detail?.status === 'confirmed' && (
|
||||
{ item.status === 'confirmed' && (
|
||||
<Tooltip placement="left" title="disconnected contact">
|
||||
<StatusConfirmed />
|
||||
</Tooltip>
|
||||
|
@ -1,39 +0,0 @@
|
||||
import { useContext, useState, useEffect } from 'react';
|
||||
import { CardContext } from 'context/CardContext';
|
||||
import { ViewportContext } from 'context/ViewportContext';
|
||||
|
||||
export function useCardItem(item) {
|
||||
|
||||
const [state, setState] = useState({
|
||||
logo: null,
|
||||
resync: false,
|
||||
});
|
||||
|
||||
const card = useContext(CardContext);
|
||||
const viewport = useContext(ViewportContext);
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }));
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
updateState({ logo: card.actions.getCardImageUrl(item.id) });
|
||||
}, [card, item]);
|
||||
|
||||
useEffect(() => {
|
||||
updateState({ display: viewport.state.display });
|
||||
}, [viewport]);
|
||||
|
||||
const actions = {
|
||||
resync: async () => {
|
||||
if (!state.resync) {
|
||||
updateState({ resync: true });
|
||||
await card.actions.resync(item.id);
|
||||
updateState({ resync: false });
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
}
|
||||
|
@ -8,10 +8,10 @@ export function useCards() {
|
||||
const [filter, setFilter] = useState(null);
|
||||
|
||||
const [state, setState] = useState({
|
||||
tooltip: false,
|
||||
sorted: false,
|
||||
display: null,
|
||||
cards: [],
|
||||
busy: false
|
||||
});
|
||||
|
||||
const card = useContext(CardContext);
|
||||
@ -22,44 +22,45 @@ export function useCards() {
|
||||
setState((s) => ({ ...s, ...value }));
|
||||
}
|
||||
|
||||
const actions = {
|
||||
onFilter: (value) => {
|
||||
setFilter(value.toUpperCase());
|
||||
},
|
||||
setSort: (value) => {
|
||||
updateState({ sorted: value });
|
||||
},
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let updated = 0;
|
||||
const contacts = Array.from(card.state.cards.values());
|
||||
|
||||
const contacts = Array.from(card.state.cards.values()).map(item => {
|
||||
const profile = item?.data?.cardProfile;
|
||||
const detail = item?.data?.cardDetail;
|
||||
|
||||
const cardId = item.id;
|
||||
const updated = detail?.statusUpdated;
|
||||
const status = detail?.status;
|
||||
const offsync = item.offsync;
|
||||
const guid = profile?.guid;
|
||||
const name = profile?.name;
|
||||
const handle = profile?.node ? `${profile.handle}@${profile.node}` : profile.handle;
|
||||
const logo = profile?.imageSet ? card.actions.getCardImageUrl(item.id) : null;
|
||||
return { cardId, guid, updated, offsync, status, name, handle, logo };
|
||||
});
|
||||
|
||||
let latest = 0;
|
||||
contacts.forEach(contact => {
|
||||
if (!updated || updated < contact?.data?.cardDetail?.statusUpdated) {
|
||||
updated = contact?.data?.cardDetail?.statusUpdated;
|
||||
if (latest < contact.updated) {
|
||||
latest = contact.updated;
|
||||
}
|
||||
});
|
||||
store.actions.setValue('cards:updated', updated);
|
||||
// eslint-disable-next-line
|
||||
}, [card]);
|
||||
|
||||
useEffect(() => {
|
||||
const contacts = Array.from(card.state.cards.values());
|
||||
|
||||
let filtered = contacts.filter((contact) => {
|
||||
store.actions.setValue('cards:updated', latest);
|
||||
|
||||
let filtered = contacts.filter(contact => {
|
||||
if (!filter) {
|
||||
return true;
|
||||
}
|
||||
if (!contact?.data?.cardProfile?.name) {
|
||||
if (!contact.name) {
|
||||
return false;
|
||||
}
|
||||
return contact.data.cardProfile.name.toUpperCase().includes(filter);
|
||||
return contact.name.toUpperCase().includes(filter);
|
||||
});
|
||||
|
||||
if (state.sorted) {
|
||||
filtered.sort((a, b) => {
|
||||
let aName = a?.data?.cardProfile?.name;
|
||||
let bName = b?.data?.cardProfile?.name;
|
||||
let aName = a?.name;
|
||||
let bName = b?.name;
|
||||
if (aName === bName) {
|
||||
return 0;
|
||||
}
|
||||
@ -71,8 +72,8 @@ export function useCards() {
|
||||
}
|
||||
else {
|
||||
filtered.sort((a, b) => {
|
||||
const aUpdated = a?.data?.cardDetail?.statusUpdated;
|
||||
const bUpdated = b?.data?.cardDetail?.statusUpdated;
|
||||
const aUpdated = a?.updated;
|
||||
const bUpdated = b?.updated;
|
||||
if (aUpdated === bUpdated) {
|
||||
return 0;
|
||||
}
|
||||
@ -85,11 +86,29 @@ export function useCards() {
|
||||
|
||||
updateState({ cards: filtered });
|
||||
|
||||
}, [card, filter, state.sorted]);
|
||||
// eslint-disable-next-line
|
||||
}, [card.state, state.sorted, filter]);
|
||||
|
||||
useEffect(() => {
|
||||
updateState({ display: viewport.state.display });
|
||||
}, [viewport]);
|
||||
if (viewport.state.display === 'small') {
|
||||
updateState({ tooltip: false });
|
||||
}
|
||||
else {
|
||||
updateState({ tooltip: true });
|
||||
}
|
||||
}, [viewport.state]);
|
||||
|
||||
const actions = {
|
||||
onFilter: (value) => {
|
||||
setFilter(value.toUpperCase());
|
||||
},
|
||||
setSort: (value) => {
|
||||
updateState({ sorted: value });
|
||||
},
|
||||
resync: async (cardId) => {
|
||||
await card.actions.resync(cardId);
|
||||
},
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user