refactor: favorite error tip

This commit is contained in:
zerosoul
2022-05-07 09:55:18 +08:00
parent 60fab189ad
commit 1902c2f891
9 changed files with 348 additions and 259 deletions
+9 -5
View File
@@ -69,9 +69,9 @@ export default function Commands({
from_uid = 0, from_uid = 0,
toggleEditMessage, toggleEditMessage,
}) { }) {
const { addFavorite, isFavorited } = useFavMessage( const { addFavorite, isFavorited } = useFavMessage({
context == "channel" ? contextId : null cid: context == "channel" ? contextId : null,
); });
const [mids, setMids] = useState([]); const [mids, setMids] = useState([]);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [pinModalVisible, setPinModalVisible] = useState(false); const [pinModalVisible, setPinModalVisible] = useState(false);
@@ -122,8 +122,12 @@ export default function Commands({
toast.success("Favorited!"); toast.success("Favorited!");
return; return;
} }
await addFavorite(mid); const added = await addFavorite(mid);
toast.success("Added Favorites!"); if (added) {
toast.success("Added Favorites!");
} else {
toast.error("Added Favorites Failed!");
}
}; };
useEffect(() => { useEffect(() => {
if (isUnpinSuccess) { if (isUnpinSuccess) {
+1 -1
View File
@@ -14,7 +14,7 @@ const StyledSaved = styled.div`
padding: 8px; padding: 8px;
`; `;
const SavedMessage = ({ cid, id }) => { const SavedMessage = ({ cid, id }) => {
const { favorites } = useFavMessage(cid); const { favorites } = useFavMessage({ cid });
const [fav, setFav] = useState(null); const [fav, setFav] = useState(null);
const [messages, setMessages] = useState(null); const [messages, setMessages] = useState(null);
useEffect(() => { useEffect(() => {
+14 -8
View File
@@ -4,21 +4,20 @@ import {
useLazyRemoveFavoriteQuery, useLazyRemoveFavoriteQuery,
useFavoriteMessageMutation, useFavoriteMessageMutation,
} from "../../app/services/message"; } from "../../app/services/message";
export default function useFavMessage(cid = null) { export default function useFavMessage({ cid = null, uid = null }) {
const [removeFav] = useLazyRemoveFavoriteQuery(); const [removeFav] = useLazyRemoveFavoriteQuery();
const [addFav] = useFavoriteMessageMutation(); const [addFav] = useFavoriteMessageMutation();
const [favorites, setFavorites] = useState([]); const [favorites, setFavorites] = useState([]);
const { favs = [] } = useSelector((store) => { const { favs = [] } = useSelector((store) => {
return { return {
// mids: store.channelMessage.byId[cid],
favs: store.favorites, favs: store.favorites,
// loginUser: store.contacts.byId[store.authData.uid],
}; };
}); });
const addFavorite = async (mid = []) => { const addFavorite = async (mid = []) => {
const mids = Array.isArray(mid) ? mid.map((i) => +i) : [+mid]; const mids = Array.isArray(mid) ? mid.map((i) => +i) : [+mid];
if (mids.length == 0) return; if (mids.length == 0) return;
await addFav(mids); const { error = null } = await addFav(mids);
return !error;
}; };
const removeFavorite = (id) => { const removeFavorite = (id) => {
if (!id) return; if (!id) return;
@@ -36,16 +35,23 @@ export default function useFavMessage(cid = null) {
return mids.findIndex((i) => i == mid) > -1; return mids.findIndex((i) => i == mid) > -1;
}; };
useEffect(() => { useEffect(() => {
const filtereds = cid let filtereds = [];
filtereds = cid
? favs.filter((f) => { ? favs.filter((f) => {
if (!f.messages) return false; if (!f.messages) return false;
return f.messages.every((m) => m.source.gid == cid); return f.messages.every((m) => m.source.gid == cid);
}) })
: favs; : favs;
console.log("filtered", filtereds); filtereds = uid
setFavorites(filtereds); ? filtereds.filter((f) => {
}, [cid, favs]); if (!f.messages) return false;
return f.messages.every((m) => m.source.uid == uid);
})
: filtereds;
setFavorites(filtereds);
}, [cid, uid, favs]);
console.log("filtered", cid, uid, favs);
return { return {
isFavorited, isFavorited,
addFavorite, addFavorite,
+245 -217
View File
@@ -1,231 +1,259 @@
import { useState } from 'react'; import { useState } from "react";
import { useDebounce } from 'rooks'; import { useDebounce } from "rooks";
import { useSelector } from 'react-redux'; import { useSelector } from "react-redux";
import PinList from './PinList'; import PinList from "./PinList";
import FavList from './FavList'; import FavList from "../FavList";
import { useReadMessageMutation } from '../../../app/services/message'; import { useReadMessageMutation } from "../../../app/services/message";
import useChatScroll from '../../../common/hook/useChatScroll'; import useChatScroll from "../../../common/hook/useChatScroll";
import ChannelIcon from '../../../common/component/ChannelIcon'; import ChannelIcon from "../../../common/component/ChannelIcon";
import Tooltip from '../../../common/component/Tooltip'; import Tooltip from "../../../common/component/Tooltip";
import Contact from '../../../common/component/Contact'; import Contact from "../../../common/component/Contact";
import Layout from '../Layout'; import Layout from "../Layout";
import { renderMessageFragment } from '../utils'; import { renderMessageFragment } from "../utils";
import EditIcon from '../../../assets/icons/edit.svg'; import EditIcon from "../../../assets/icons/edit.svg";
// import alertIcon from "../../../assets/icons/alert.svg?url"; // import alertIcon from "../../../assets/icons/alert.svg?url";
import IconFav from '../../../assets/icons/bookmark.svg'; import IconFav from "../../../assets/icons/bookmark.svg";
import IconPeople from '../../../assets/icons/people.svg'; import IconPeople from "../../../assets/icons/people.svg";
import IconPin from '../../../assets/icons/pin.svg'; import IconPin from "../../../assets/icons/pin.svg";
// import searchIcon from "../../../assets/icons/search.svg?url"; // import searchIcon from "../../../assets/icons/search.svg?url";
import IconHeadphone from '../../../assets/icons/headphone.svg'; import IconHeadphone from "../../../assets/icons/headphone.svg";
import boardosIcon from '../../../assets/icons/app.boardos.svg?url'; import boardosIcon from "../../../assets/icons/app.boardos.svg?url";
import webrowseIcon from '../../../assets/icons/app.webrowse.svg?url'; import webrowseIcon from "../../../assets/icons/app.webrowse.svg?url";
import addIcon from '../../../assets/icons/add.svg?url'; import addIcon from "../../../assets/icons/add.svg?url";
import { import {
// StyledNotification, // StyledNotification,
StyledContacts, StyledContacts,
StyledChannelChat, StyledChannelChat,
StyledHeader StyledHeader,
} from './styled'; } from "./styled";
import ChannelInviteModal from '../../../common/component/ChannelInviteModal'; import ChannelInviteModal from "../../../common/component/ChannelInviteModal";
import { NavLink, useLocation } from 'react-router-dom'; import { NavLink, useLocation } from "react-router-dom";
import Tippy from '@tippyjs/react'; import Tippy from "@tippyjs/react";
export default function ChannelChat({ cid = '', dropFiles = [] }) { export default function ChannelChat({ cid = "", dropFiles = [] }) {
const [toolVisible, setToolVisible] = useState(''); const [toolVisible, setToolVisible] = useState("");
const { pathname } = useLocation(); const { pathname } = useLocation();
const [updateReadIndex] = useReadMessageMutation(); const [updateReadIndex] = useReadMessageMutation();
const updateReadDebounced = useDebounce(updateReadIndex, 300); const updateReadDebounced = useDebounce(updateReadIndex, 300);
const [membersVisible, setMembersVisible] = useState(true); const [membersVisible, setMembersVisible] = useState(true);
const [addMemberModalVisible, setAddMemberModalVisible] = useState(false); const [addMemberModalVisible, setAddMemberModalVisible] = useState(false);
// const dispatch = useDispatch(); // const dispatch = useDispatch();
const { selects, msgIds, userIds, data, messageData, loginUid, loginUser, footprint } = const {
useSelector((store) => { selects,
return { msgIds,
selects: store.ui.selectMessages[`channel_${cid}`], userIds,
footprint: store.footprint, data,
loginUser: store.contacts.byId[store.authData.uid], messageData,
loginUid: store.authData.uid, loginUid,
msgIds: store.channelMessage[cid] || [], loginUser,
userIds: store.contacts.ids, footprint,
data: store.channels.byId[cid] || {}, } = useSelector((store) => {
messageData: store.message || {} return {
}; selects: store.ui.selectMessages[`channel_${cid}`],
footprint: store.footprint,
loginUser: store.contacts.byId[store.authData.uid],
loginUid: store.authData.uid,
msgIds: store.channelMessage[cid] || [],
userIds: store.contacts.ids,
data: store.channels.byId[cid] || {},
messageData: store.message || {},
};
}); });
const ref = useChatScroll(msgIds); const ref = useChatScroll(msgIds);
// const handleClearUnreads = () => { // const handleClearUnreads = () => {
// dispatch(readMessage(msgIds)); // dispatch(readMessage(msgIds));
// }; // };
const toggleMembersVisible = () => { const toggleMembersVisible = () => {
setMembersVisible((prev) => !prev); setMembersVisible((prev) => !prev);
}; };
const toggleAddVisible = () => { const toggleAddVisible = () => {
setAddMemberModalVisible((prev) => !prev); setAddMemberModalVisible((prev) => !prev);
}; };
const { name, description, is_public, members = [], owner } = data; const { name, description, is_public, members = [], owner } = data;
const memberIds = is_public ? userIds : members; const memberIds = is_public ? userIds : members;
const addVisible = loginUser?.is_admin || owner == loginUid; const addVisible = loginUser?.is_admin || owner == loginUid;
console.log('channel message list', msgIds); console.log("channel message list", msgIds);
const readIndex = footprint.readChannels[cid]; const readIndex = footprint.readChannels[cid];
const pinCount = data?.pinned_messages?.length || 0; const pinCount = data?.pinned_messages?.length || 0;
return ( return (
<> <>
{addMemberModalVisible && <ChannelInviteModal cid={cid} closeModal={toggleAddVisible} />} {addMemberModalVisible && (
<Layout <ChannelInviteModal cid={cid} closeModal={toggleAddVisible} />
to={cid} )}
context="channel" <Layout
dropFiles={dropFiles} to={cid}
// ref={containerRef} context="channel"
aside={ dropFiles={dropFiles}
<> // ref={containerRef}
<ul className="tools"> aside={
{/* <li className="tool"> <>
<ul className="tools">
{/* <li className="tool">
<Tooltip tip="Search" placement="left"> <Tooltip tip="Search" placement="left">
<img src={searchIcon} alt="opt icon" /> <img src={searchIcon} alt="opt icon" />
</Tooltip> </Tooltip>
</li> */} </li> */}
<li className="tool"> <li className="tool">
<Tooltip tip="Voice/Video Chat" placement="left"> <Tooltip tip="Voice/Video Chat" placement="left">
<IconHeadphone /> <IconHeadphone />
</Tooltip> </Tooltip>
</li> </li>
{/* <li className="tool"> {/* <li className="tool">
<Tooltip tip="Notifications" placement="left"> <Tooltip tip="Notifications" placement="left">
<img src={alertIcon} alt="opt icon" /> <img src={alertIcon} alt="opt icon" />
</Tooltip> </Tooltip>
</li> */} </li> */}
<Tooltip tip="Pin" placement="left" disabled={toolVisible == 'pin'}> <Tooltip
<Tippy tip="Pin"
onShow={() => { placement="left"
setToolVisible('pin'); disabled={toolVisible == "pin"}
}} >
onHide={() => { <Tippy
setToolVisible(''); onShow={() => {
}} setToolVisible("pin");
delay={[0, 0]} }}
duration={0} onHide={() => {
placement="left-start" setToolVisible("");
popperOptions={{ strategy: 'fixed' }} }}
offset={[0, 80]} delay={[0, 0]}
interactive duration={0}
trigger="click" placement="left-start"
content={<PinList id={cid} />} popperOptions={{ strategy: "fixed" }}
> offset={[0, 80]}
<li interactive
className={`tool ${pinCount > 0 ? 'badge' : ''} ${toolVisible == 'pin' ? 'active' : ''} `} trigger="click"
data-count={pinCount} content={<PinList id={cid} />}
> >
<IconPin /> <li
</li> className={`tool ${pinCount > 0 ? "badge" : ""} ${
</Tippy> toolVisible == "pin" ? "active" : ""
</Tooltip> } `}
<Tooltip tip="Favorite" placement="left" disabled={toolVisible == 'favorite'}> data-count={pinCount}
<Tippy >
onShow={() => { <IconPin />
setToolVisible('favorite'); </li>
}} </Tippy>
onHide={() => { </Tooltip>
setToolVisible(''); <Tooltip
}} tip="Favorite"
delay={[0, 0]} placement="left"
duration={0} disabled={toolVisible == "favorite"}
placement="left-start" >
popperOptions={{ strategy: 'fixed' }} <Tippy
offset={[0, 180]} onShow={() => {
interactive setToolVisible("favorite");
trigger="click" }}
content={<FavList cid={cid} />} onHide={() => {
> setToolVisible("");
<li }}
className={`tool fav ${toolVisible == 'favorite' ? 'active' : ''} `} delay={[0, 0]}
data-count={pinCount} duration={0}
> placement="left-start"
<IconFav /> popperOptions={{ strategy: "fixed" }}
</li> offset={[0, 180]}
</Tippy> interactive
</Tooltip> trigger="click"
<li className={`tool ${membersVisible ? 'active' : ''}`} onClick={toggleMembersVisible}> content={<FavList cid={cid} />}
<Tooltip tip="Channel Members" placement="left"> >
<IconPeople /> <li
</Tooltip> className={`tool fav ${
</li> toolVisible == "favorite" ? "active" : ""
</ul> } `}
<hr className="divider" /> data-count={pinCount}
<ul className="apps"> >
<li className="app"> <IconFav />
<Tooltip tip="Webrowse" placement="left"> </li>
<img src={webrowseIcon} alt="app icon" /> </Tippy>
</Tooltip> </Tooltip>
</li> <li
<li className="app"> className={`tool ${membersVisible ? "active" : ""}`}
<Tooltip tip="BoardOS" placement="left"> onClick={toggleMembersVisible}
<img src={boardosIcon} alt="app icon" /> >
</Tooltip> <Tooltip tip="Channel Members" placement="left">
</li> <IconPeople />
</ul> </Tooltip>
</> </li>
} </ul>
header={ <hr className="divider" />
<StyledHeader className="head"> <ul className="apps">
<div className="txt"> <li className="app">
<ChannelIcon personal={!is_public} /> <Tooltip tip="Webrowse" placement="left">
<span className="title">{name}</span> <img src={webrowseIcon} alt="app icon" />
<span className="desc">{description}</span> </Tooltip>
</div> </li>
</StyledHeader> <li className="app">
} <Tooltip tip="BoardOS" placement="left">
contacts={ <img src={boardosIcon} alt="app icon" />
membersVisible ? ( </Tooltip>
<> </li>
<StyledContacts> </ul>
{addVisible && ( </>
<div className="add" onClick={toggleAddVisible}> }
<img className="icon" src={addIcon} /> header={
<div className="txt">Add members</div> <StyledHeader className="head">
</div> <div className="txt">
)} <ChannelIcon personal={!is_public} />
{memberIds.map((uid) => { <span className="title">{name}</span>
return <Contact key={uid} uid={uid} dm popover />; <span className="desc">{description}</span>
})} </div>
</StyledContacts> </StyledHeader>
</> }
) : null contacts={
} membersVisible ? (
> <>
<StyledChannelChat ref={ref}> <StyledContacts>
<div className="info"> {addVisible && (
<h2 className="title">Welcome to #{name} !</h2> <div className="add" onClick={toggleAddVisible}>
<p className="desc">This is the start of the #{name} channel. </p> <img className="icon" src={addIcon} />
<NavLink to={`/setting/channel/${cid}?f=${pathname}`} className="edit"> <div className="txt">Add members</div>
<EditIcon className="icon" /> </div>
Edit Channel )}
</NavLink> {memberIds.map((uid) => {
</div> return <Contact key={uid} uid={uid} dm popover />;
<div className="feed"> })}
{[...msgIds] </StyledContacts>
.sort((a, b) => { </>
return Number(a) - Number(b); ) : null
}) }
.map((mid, idx) => { >
const curr = messageData[mid]; <StyledChannelChat ref={ref}>
if (!curr) return null; <div className="info">
const isFirst = idx == 0; <h2 className="title">Welcome to #{name} !</h2>
const prev = idx == 0 ? null : messageData[msgIds[idx - 1]]; <p className="desc">This is the start of the #{name} channel. </p>
const read = curr?.from_uid == loginUid || mid <= readIndex; <NavLink
return renderMessageFragment({ to={`/setting/channel/${cid}?f=${pathname}`}
selectMode: !!selects, className="edit"
updateReadIndex: updateReadDebounced, >
read, <EditIcon className="icon" />
isFirst, Edit Channel
prev, </NavLink>
curr, </div>
contextId: cid, <div className="feed">
context: 'channel' {[...msgIds]
}); .sort((a, b) => {
})} return Number(a) - Number(b);
</div> })
</StyledChannelChat> .map((mid, idx) => {
{/* {unreads != 0 && ( const curr = messageData[mid];
if (!curr) return null;
const isFirst = idx == 0;
const prev = idx == 0 ? null : messageData[msgIds[idx - 1]];
const read = curr?.from_uid == loginUid || mid <= readIndex;
return renderMessageFragment({
selectMode: !!selects,
updateReadIndex: updateReadDebounced,
read,
isFirst,
prev,
curr,
contextId: cid,
context: "channel",
});
})}
</div>
</StyledChannelChat>
{/* {unreads != 0 && (
<StyledNotification> <StyledNotification>
<div className="content"> <div className="content">
{unreads} new messages {unreads} new messages
@@ -238,7 +266,7 @@ export default function ChannelChat({ cid = '', dropFiles = [] }) {
</button> </button>
</StyledNotification> </StyledNotification>
)} */} )} */}
</Layout> </Layout>
</> </>
); );
} }
+35 -9
View File
@@ -1,10 +1,14 @@
// import { useState, useEffect } from "react"; // import { useState, useEffect } from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { useDebounce } from "rooks"; import { useDebounce } from "rooks";
import Tippy from "@tippyjs/react";
import FavList from "../FavList";
import Tooltip from "../../../common/component/Tooltip"; import Tooltip from "../../../common/component/Tooltip";
import alertIcon from "../../../assets/icons/alert.svg?url"; import FavIcon from "../../../assets/icons/bookmark.svg";
import pinIcon from "../../../assets/icons/pin.svg?url";
// import searchIcon from "../../../assets/icons/search.svg?url"; // import searchIcon from "../../../assets/icons/search.svg?url";
import IconHeadphone from "../../../assets/icons/headphone.svg";
import boardosIcon from "../../../assets/icons/app.boardos.svg?url"; import boardosIcon from "../../../assets/icons/app.boardos.svg?url";
import webrowseIcon from "../../../assets/icons/app.webrowse.svg?url"; import webrowseIcon from "../../../assets/icons/app.webrowse.svg?url";
import useChatScroll from "../../../common/hook/useChatScroll"; import useChatScroll from "../../../common/hook/useChatScroll";
@@ -48,15 +52,37 @@ export default function DMChat({ uid = "", dropFiles = [] }) {
aside={ aside={
<> <>
<ul className="tools"> <ul className="tools">
<li className="tool">
<IconHeadphone />
</li>
{/* <li className="tool"> {/* <li className="tool">
<img src={searchIcon} alt="opt icon" />
</li> */}
<li className="tool">
<img src={alertIcon} alt="opt icon" /> <img src={alertIcon} alt="opt icon" />
</li> </li> */}
<li className="tool"> <Tooltip tip="Favorite" placement="left">
<img src={pinIcon} alt="opt icon" /> <Tippy
</li> // onShow={() => {
// setToolVisible('favorite');
// }}
// onHide={() => {
// setToolVisible('');
// }}
delay={[0, 0]}
duration={0}
placement="left-start"
popperOptions={{ strategy: "fixed" }}
offset={[0, 180]}
interactive
trigger="click"
content={<FavList uid={uid} />}
>
<li className={`tool fav`}>
<FavIcon />
</li>
</Tippy>
</Tooltip>
{/* <li className="tool fav">
<FavIcon />
</li> */}
</ul> </ul>
<hr className="divider" /> <hr className="divider" />
<ul className="apps"> <ul className="apps">
@@ -1,11 +1,11 @@
// import React from "react"; // import React from "react";
// import { useSelector } from "react-redux"; // import { useSelector } from "react-redux";
import styled from "styled-components"; import styled from "styled-components";
import SavedMessage from "../../../common/component/Message/SavedMessage"; import SavedMessage from "../../common/component/Message/SavedMessage";
import IconSurprise from "../../../assets/icons/emoji.suprise.svg"; import IconSurprise from "../../assets/icons/emoji.suprise.svg";
// import IconForward from "../../../assets/icons/forward.svg"; // import IconForward from "../../../assets/icons/forward.svg";
import IconBookmark from "../../../assets/icons/bookmark.svg"; import IconBookmark from "../../assets/icons/bookmark.svg";
import useFavMessage from "../../../common/hook/useFavMessage"; import useFavMessage from "../../common/hook/useFavMessage";
const Styled = styled.div` const Styled = styled.div`
padding: 16px; padding: 16px;
background: #f9fafb; background: #f9fafb;
@@ -82,8 +82,8 @@ const Styled = styled.div`
} }
} }
`; `;
export default function FavList({ cid = null }) { export default function FavList({ cid = null, uid = null }) {
const { favorites, removeFavorite } = useFavMessage(cid); const { favorites, removeFavorite } = useFavMessage({ cid, uid });
const handleRemove = (evt) => { const handleRemove = (evt) => {
const { id } = evt.currentTarget.dataset; const { id } = evt.currentTarget.dataset;
console.log("remove fav", id); console.log("remove fav", id);
+9 -4
View File
@@ -40,7 +40,7 @@ const Styled = styled.div`
export default function Operations({ context, id }) { export default function Operations({ context, id }) {
const [deleteModalVisible, setDeleteModalVisible] = useState(false); const [deleteModalVisible, setDeleteModalVisible] = useState(false);
const { canDelete } = useDeleteMessage(); const { canDelete } = useDeleteMessage();
const { addFavorite } = useFavMessage(id); const { addFavorite } = useFavMessage({});
const mids = useSelector( const mids = useSelector(
(store) => store.ui.selectMessages[`${context}_${id}`] (store) => store.ui.selectMessages[`${context}_${id}`]
); );
@@ -50,9 +50,14 @@ export default function Operations({ context, id }) {
dispatch(updateSelectMessages({ context, id, operation: "reset" })); dispatch(updateSelectMessages({ context, id, operation: "reset" }));
}; };
const handleFav = async () => { const handleFav = async () => {
await addFavorite(mids); const added = await addFavorite(mids);
dispatch(updateSelectMessages({ context, id, operation: "reset" })); if (added) {
toast.success("Messages Saved!"); console.log("added", added);
dispatch(updateSelectMessages({ context, id, operation: "reset" }));
toast.success("Messages Saved!");
} else {
toast.error("Operation Failed!");
}
}; };
const toggleDeleteModal = (isSuccess = false) => { const toggleDeleteModal = (isSuccess = false) => {
setDeleteModalVisible((prev) => !prev); setDeleteModalVisible((prev) => !prev);
+18 -9
View File
@@ -2,17 +2,12 @@
import Styled from "./styled"; import Styled from "./styled";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import SavedMessage from "../../common/component/Message/SavedMessage"; import SavedMessage from "../../common/component/Message/SavedMessage";
// import Masonry from "masonry-layout"; import dayjs from "dayjs";
// import waterfall from "waterfall.js/src/waterfall";
// import { Views } from "../../app/config";
// import View from "./View";
// import Search from "./Search";
// import Filter from "./Filter";
// import FileBox from "../../common/component/FileBox";
function FavsPage() { function FavsPage() {
// const listContainerRef = useRef(null); // const listContainerRef = useRef(null);
// const [filter, setFilter] = useState({}); // const [filter, setFilter] = useState({});
const { favorites } = useSelector((store) => { const { favorites } = useSelector((store) => {
console.log("favs", store.favorites);
return { return {
favorites: store.favorites, favorites: store.favorites,
// channelMessage: store.channelMessage, // channelMessage: store.channelMessage,
@@ -21,8 +16,22 @@ function FavsPage() {
}); });
return ( return (
<Styled> <Styled>
{favorites.map(({ id, created_at }) => { {favorites.map(({ id, created_at, messages }) => {
return <SavedMessage key={id} id={id} />; const [
{
source: { gid, uid },
},
] = messages;
return (
<div className="fav" key={id}>
<h4 className="tip">
{gid ? `gid:${gid}` : `uid:${uid}`}{" "}
{dayjs(created_at).format("YYYY-MM-DD")}
</h4>
<SavedMessage key={id} id={id} />
</div>
);
})} })}
</Styled> </Styled>
); );
+11
View File
@@ -10,6 +10,17 @@ const Styled = styled.div`
margin: 8px 24px 10px 0; margin: 8px 24px 10px 0;
border-radius: 16px; border-radius: 16px;
padding: 16px; padding: 16px;
.fav {
display: flex;
flex-direction: column;
.tip {
font-style: normal;
font-weight: 500;
font-size: 12px;
line-height: 18px;
color: #bfbfbf;
}
}
`; `;
export default Styled; export default Styled;