feat: user search

This commit is contained in:
Tristan Yang
2022-12-05 19:31:55 +08:00
parent a512a2a97b
commit 0f3e01a922
4 changed files with 25 additions and 20 deletions
+2 -2
View File
@@ -61,7 +61,7 @@ const User: FC<Props> = ({
<Avatar url={curr.avatar} name={curr.name} alt="avatar" /> <Avatar url={curr.avatar} name={curr.name} alt="avatar" />
<div className={`status ${online ? "online" : "offline"}`}></div> <div className={`status ${online ? "online" : "offline"}`}></div>
</div> </div>
{!compact && <span className="name">{curr?.name}</span>} {!compact && <span className="name" title={curr?.name}>{curr?.name}</span>}
{owner && <IconOwner />} {owner && <IconOwner />}
</StyledWrapper> </StyledWrapper>
</ContextMenu> </ContextMenu>
@@ -91,7 +91,7 @@ const User: FC<Props> = ({
<Avatar url={curr.avatar} name={curr.name} alt="avatar" /> <Avatar url={curr.avatar} name={curr.name} alt="avatar" />
<div className={`status ${online ? "online" : "offline"}`}></div> <div className={`status ${online ? "online" : "offline"}`}></div>
</div> </div>
{!compact && <span className="name">{curr?.name}</span>} {!compact && <span className="name" title={curr?.name}>{curr?.name}</span>}
{owner && <IconOwner />} {owner && <IconOwner />}
</StyledWrapper> </StyledWrapper>
</Tippy> </Tippy>
+3
View File
@@ -50,6 +50,9 @@ const StyledWrapper = styled.div`
font-size: 14px; font-size: 14px;
line-height: 20px; line-height: 20px;
color: #52525b; color: #52525b;
max-width: 190px;
overflow: hidden;
text-overflow: ellipsis;
} }
/* session nav */ /* session nav */
&.compact { &.compact {
@@ -2,9 +2,9 @@ import styled from "styled-components";
import Tippy from "@tippyjs/react"; import Tippy from "@tippyjs/react";
import searchIcon from "../../assets/icons/search.svg?url"; import searchIcon from "../../assets/icons/search.svg?url";
import addIcon from "../../assets/icons/add.svg?url"; import addIcon from "../../assets/icons/add.svg?url";
import AddEntriesMenu from "./AddEntriesMenu"; import AddEntriesMenu from "../../common/component/AddEntriesMenu";
import Tooltip from "./Tooltip"; import Tooltip from "../../common/component/Tooltip";
import { FC } from "react"; import { FC, ChangeEvent } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
const StyledWrapper = styled.div` const StyledWrapper = styled.div`
@@ -30,22 +30,25 @@ const StyledWrapper = styled.div`
line-height: 20px; line-height: 20px;
} }
} }
.add {
cursor: pointer;
}
`; `;
type Props = {}; type Props = {
const Search: FC<Props> = () => { input: string,
updateInput: (input: string) => void
};
const Search: FC<Props> = ({ input, updateInput }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const handleInput = (evt: ChangeEvent<HTMLInputElement>) => {
updateInput(evt.target.value);
};
return ( return (
<StyledWrapper> <StyledWrapper>
<div className="search"> <div className="search">
<img src={searchIcon} alt="search icon" /> <img src={searchIcon} alt="search icon" />
<input placeholder={`${t("action.search")}...`} className="input" /> <input value={input} placeholder={`${t("action.search")}...`} className="input" onChange={handleInput} />
</div> </div>
<Tooltip tip={t("more")} placement="bottom"> <Tooltip tip={t("more")} placement="bottom">
<Tippy interactive placement="bottom-end" trigger="click" content={<AddEntriesMenu />}> <Tippy interactive placement="bottom-end" trigger="click" content={<AddEntriesMenu />}>
<img src={addIcon} alt="add icon" className="add" /> <img src={addIcon} alt="add icon" className="cursor-pointer" />
</Tippy> </Tippy>
</Tooltip> </Tooltip>
</StyledWrapper> </StyledWrapper>
+7 -8
View File
@@ -1,22 +1,21 @@
import { memo, useEffect } from "react"; import { memo, useEffect } from "react";
import { NavLink, useParams, useLocation } from "react-router-dom"; import { NavLink, useParams, useLocation } from "react-router-dom";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import _ from "lodash";
import { updateRememberedNavs } from "../../app/slices/ui"; import { updateRememberedNavs } from "../../app/slices/ui";
import Search from "../../common/component/Search"; import Search from "./Search";
import User from "../../common/component/User"; import User from "../../common/component/User";
import Profile from "../../common/component/Profile"; import Profile from "../../common/component/Profile";
import StyledWrapper from "./styled"; import StyledWrapper from "./styled";
import BlankPlaceholder from "../../common/component/BlankPlaceholder"; import BlankPlaceholder from "../../common/component/BlankPlaceholder";
import { useAppSelector } from "../../app/store"; import useFilteredUsers from "../../common/hook/useFilteredUsers";
function UsersPage() { function UsersPage() {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { pathname } = useLocation(); const { pathname } = useLocation();
const { input, updateInput, users } = useFilteredUsers();
const { user_id } = useParams(); const { user_id } = useParams();
const userIds = useAppSelector((store) => store.users.ids, _.isEqual); // 记住路由
useEffect(() => { useEffect(() => {
dispatch(updateRememberedNavs({ key: "user" })); dispatch(updateRememberedNavs({ key: "user" }));
return () => { return () => {
@@ -24,14 +23,14 @@ function UsersPage() {
}; };
}, [pathname]); }, [pathname]);
if (!userIds) return null; if (!users) return null;
return ( return (
<StyledWrapper> <StyledWrapper>
<div className="left"> <div className="left">
<Search /> <Search input={input} updateInput={updateInput} />
<div className="list"> <div className="list">
<nav className="nav"> <nav className="nav">
{userIds.map((uid: number) => { {users.map(({ uid }) => {
return ( return (
<NavLink key={uid} className="session" to={`/users/${uid}`}> <NavLink key={uid} className="session" to={`/users/${uid}`}>
<User uid={uid} enableContextMenu={true} /> <User uid={uid} enableContextMenu={true} />