From 24b944f1058bbd849953385e714f093021b406aa Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 21 Jan 2021 19:44:47 +0800 Subject: feat: Add search page. --- FrontEnd/src/app/views/search/index.tsx | 117 ++++++++++++++++++++++++++++++ FrontEnd/src/app/views/search/search.sass | 13 ++++ 2 files changed, 130 insertions(+) create mode 100644 FrontEnd/src/app/views/search/index.tsx create mode 100644 FrontEnd/src/app/views/search/search.sass (limited to 'FrontEnd/src/app/views') diff --git a/FrontEnd/src/app/views/search/index.tsx b/FrontEnd/src/app/views/search/index.tsx new file mode 100644 index 00000000..d7b1ac53 --- /dev/null +++ b/FrontEnd/src/app/views/search/index.tsx @@ -0,0 +1,117 @@ +import { TimelineInfo } from "@/services/timeline"; +import React from "react"; +import { Container, Row } from "react-bootstrap"; +import { useHistory, useLocation } from "react-router"; +import { Link } from "react-router-dom"; + +import { getHttpSearchClient } from "@/http/search"; + +import SearchInput from "../common/SearchInput"; +import { HttpNetworkError } from "@/http/common"; +import { useAvatar } from "@/services/user"; +import BlobImage from "../common/BlobImage"; + +const TimelineSearchResultItemView: React.FC<{ timeline: TimelineInfo }> = ({ + timeline, +}) => { + const link = timeline.name.startsWith("@") + ? `users/${timeline.owner.username}` + : `timelines/${timeline.name}`; + + const avatar = useAvatar(timeline.owner.username); + + return ( +
+

+ + {timeline.title} + {timeline.name} + +

+
+ + {timeline.owner.nickname} + + @{timeline.owner.username} + +
+
+ ); +}; + +const SearchPage: React.FC = () => { + const history = useHistory(); + const location = useLocation(); + const searchParams = new URLSearchParams(location.search); + const queryParam = searchParams.get("q"); + + const [searchText, setSearchText] = React.useState(""); + const [state, setState] = React.useState< + TimelineInfo[] | "init" | "loading" | "network-error" | "error" + >("init"); + + React.useEffect(() => { + if (queryParam != null && queryParam.length > 0) { + setSearchText(queryParam); + setState("loading"); + void getHttpSearchClient() + .searchTimelines(queryParam) + .then( + (ts) => { + setState(ts); + }, + (e) => { + if (e instanceof HttpNetworkError) { + setState("network-error"); + } else { + setState("error"); + } + } + ); + } + }, [queryParam]); + + return ( + + + { + if (searchText.length > 0) { + history.push(`/search?q=${searchText}`); + } + }} + /> + + {(() => { + switch (state) { + case "init": { + return "Input something and search!"; + } + case "loading": { + return "Loading!"; + } + case "network-error": { + return "Network error!"; + } + case "error": { + return "Unknown error!"; + } + default: { + return state.map((t) => ( + + )); + } + } + })()} + + ); +}; + +export default SearchPage; diff --git a/FrontEnd/src/app/views/search/search.sass b/FrontEnd/src/app/views/search/search.sass new file mode 100644 index 00000000..83f297fe --- /dev/null +++ b/FrontEnd/src/app/views/search/search.sass @@ -0,0 +1,13 @@ +.timeline-search-result-item + @extend .rounded + border: 1px solid + border-color: $gray-200 + background: $gray-100 + transition: all 0.3s + &:hover + border-color: $primary + +.timeline-search-result-item-avatar + width: 2em + height: 2em + border-radius: 50% -- cgit v1.2.3