From 9455824a2da157178da91b6232f322b29b941e4a Mon Sep 17 00:00:00 2001 From: Steven Date: Sun, 9 Jul 2023 11:36:26 +0800 Subject: [PATCH] feat: add tag filter --- web/src/components/FilterView.tsx | 28 +++++++++++++++++++++++++++ web/src/components/ShortcutView.tsx | 10 ++++++++-- web/src/pages/Home.tsx | 30 +++++++++++++++++++++++++---- web/src/stores/v1/filter.ts | 20 +++++++++++++++++++ 4 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 web/src/components/FilterView.tsx create mode 100644 web/src/stores/v1/filter.ts diff --git a/web/src/components/FilterView.tsx b/web/src/components/FilterView.tsx new file mode 100644 index 0000000..0ef2e5f --- /dev/null +++ b/web/src/components/FilterView.tsx @@ -0,0 +1,28 @@ +import useFilterStore from "../stores/v1/filter"; +import Icon from "./Icon"; + +const FilterView = () => { + const filterStore = useFilterStore(); + const filter = filterStore.filter; + const shouldShowFilters = filter.tag !== undefined; + + if (!shouldShowFilters) { + return <>; + } + + return ( +
+ Filters: + {filter.tag && ( + + )} +
+ ); +}; + +export default FilterView; diff --git a/web/src/components/ShortcutView.tsx b/web/src/components/ShortcutView.tsx index d1184c7..f19ce91 100644 --- a/web/src/components/ShortcutView.tsx +++ b/web/src/components/ShortcutView.tsx @@ -5,6 +5,7 @@ import { useTranslation } from "react-i18next"; import toast from "react-hot-toast"; import { shortcutService } from "../services"; import useFaviconStore from "../stores/v1/favicon"; +import useFilterStore from "../stores/v1/filter"; import useUserStore from "../stores/v1/user"; import { absolutifyLink } from "../helpers/utils"; import { showCommonDialog } from "./Alert"; @@ -22,6 +23,7 @@ const ShortcutView = (props: Props) => { const { shortcut, handleEdit } = props; const { t } = useTranslation(); const currentUser = useUserStore().getCurrentUser(); + const filterStore = useFilterStore(); const faviconStore = useFaviconStore(); const [favicon, setFavicon] = useState(undefined); const [showQRCodeDialog, setShowQRCodeDialog] = useState(false); @@ -116,11 +118,15 @@ const ShortcutView = (props: Props) => { {shortcut.description &&

{shortcut.description}

} {shortcut.tags.length > 0 && ( -
+
{shortcut.tags.map((tag) => { return ( - + filterStore.setFilter({ tag: tag })} + > #{tag} ); diff --git a/web/src/pages/Home.tsx b/web/src/pages/Home.tsx index c00c31f..00d9cde 100644 --- a/web/src/pages/Home.tsx +++ b/web/src/pages/Home.tsx @@ -2,26 +2,45 @@ import { Button, Tab, TabList, Tabs } from "@mui/joy"; import { useEffect, useState } from "react"; import { shortcutService } from "../services"; import { useAppSelector } from "../stores"; +import useFilterStore, { Filter } from "../stores/v1/filter"; import useUserStore from "../stores/v1/user"; import useLoading from "../hooks/useLoading"; import Icon from "../components/Icon"; import ShortcutListView from "../components/ShortcutListView"; import CreateShortcutDialog from "../components/CreateShortcutDialog"; +import FilterView from "../components/FilterView"; interface State { showCreateShortcutDialog: boolean; } +const getFilteredShortcutList = (shortcutList: Shortcut[], filter: Filter, currentUser: User) => { + const { tag, mineOnly } = filter; + const filteredShortcutList = shortcutList.filter((shortcut) => { + if (tag) { + if (!shortcut.tags.includes(tag)) { + return false; + } + } + if (mineOnly) { + if (shortcut.creatorId !== currentUser.id) { + return false; + } + } + return true; + }); + return filteredShortcutList; +}; + const Home: React.FC = () => { const loadingState = useLoading(); const currentUser = useUserStore().getCurrentUser(); + const filterStore = useFilterStore(); const { shortcutList } = useAppSelector((state) => state.shortcut); const [state, setState] = useState({ showCreateShortcutDialog: false, }); - const [selectedFilter, setSelectFilter] = useState<"ALL" | "PRIVATE">("ALL"); - const filteredShortcutList = - selectedFilter === "ALL" ? shortcutList : shortcutList.filter((shortcut) => shortcut.creatorId === currentUser.id); + const filteredShortcutList = getFilteredShortcutList(shortcutList, filterStore.filter, currentUser); useEffect(() => { Promise.all([shortcutService.getMyAllShortcuts()]).finally(() => { @@ -44,7 +63,7 @@ const Home: React.FC = () => {
- setSelectFilter(value as any)}> + filterStore.setFilter({ mineOnly: value !== "ALL" })}> All Mine @@ -57,6 +76,9 @@ const Home: React.FC = () => {
+ + + {loadingState.isLoading ? (
diff --git a/web/src/stores/v1/filter.ts b/web/src/stores/v1/filter.ts new file mode 100644 index 0000000..cc6b967 --- /dev/null +++ b/web/src/stores/v1/filter.ts @@ -0,0 +1,20 @@ +import { create } from "zustand"; + +export interface Filter { + tag?: string; + mineOnly?: boolean; +} + +interface FilterState { + filter: Filter; + setFilter: (filter: Partial) => void; +} + +const useFilterStore = create()((set, get) => ({ + filter: {}, + setFilter: (filter: Partial) => { + set({ filter: { ...get().filter, ...filter } }); + }, +})); + +export default useFilterStore;