From bd883431ff466ed2a04e1dece422b19565521ee1 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Wed, 2 Nov 2022 18:39:35 +0100 Subject: [PATCH] added NoSearchResults.tsx to AliasesRoute.tsx --- public/locales/en/translation.json | 4 + src/components/NoSearchResults.tsx | 25 ++++++ src/components/index.ts | 2 + src/hooks/index.ts | 2 + src/hooks/use-is-any-input-focused.ts | 21 +++++ .../AliasesRoute/AliasesDetails.tsx | 82 +++++++++---------- src/routes/AliasesRoute.tsx | 27 +++++- 7 files changed, 118 insertions(+), 45 deletions(-) create mode 100644 src/components/NoSearchResults.tsx create mode 100644 src/hooks/use-is-any-input-focused.ts diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index d5487d3..8ef5520 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -298,6 +298,10 @@ "AliasTypeIndicator": { "random": "This is a randomly generated alias", "custom": "This is a custom-made alias" + }, + "NoSearchResults": { + "title": "Nothing found", + "description": "We couldn't find anything for your search query. Try again with a different query." } }, diff --git a/src/components/NoSearchResults.tsx b/src/components/NoSearchResults.tsx new file mode 100644 index 0000000..12a0ca9 --- /dev/null +++ b/src/components/NoSearchResults.tsx @@ -0,0 +1,25 @@ +import {ReactElement} from "react" +import {useTranslation} from "react-i18next" +import {FaQuestion} from "react-icons/fa" + +import {Grid, Typography} from "@mui/material" + +export default function NoSearchResults(): ReactElement { + const {t} = useTranslation() + + return ( + + + {t("components.NoSearchResults.title")} + + + + + + + {t("components.NoSearchResults.description")} + + + + ) +} diff --git a/src/components/index.ts b/src/components/index.ts index 2eb9270..0de4954 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -34,5 +34,7 @@ export * from "./SimpleOverlayInformation" export {default as SimpleOverlayInformation} from "./SimpleOverlayInformation" export * from "./SimpleInformationContainer" export {default as SimpleInformationContainer} from "./SimpleInformationContainer" +export * from "./NoSearchResults" +export {default as NoSearchResults} from "./NoSearchResults" export * as SimplePageBuilder from "./simple-page-builder" diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 02edbd6..b5d3ebc 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -12,3 +12,5 @@ export * from "./use-navigate-to-next" export {default as useNavigateToNext} from "./use-navigate-to-next" export * from "./use-error-success-snacks" export {default as useErrorSuccessSnacks} from "./use-error-success-snacks" +export * from "./use-is-any-input-focused" +export {default as useIsAnyInputFocused} from "./use-is-any-input-focused" diff --git a/src/hooks/use-is-any-input-focused.ts b/src/hooks/use-is-any-input-focused.ts new file mode 100644 index 0000000..8dbb469 --- /dev/null +++ b/src/hooks/use-is-any-input-focused.ts @@ -0,0 +1,21 @@ +import {useCallback, useState} from "react" +import {useEvent} from "react-use" + +export default function useIsAnyInputFocused(): boolean { + const [isFocused, setIsFocused] = useState(false) + + const focusHandler = useCallback(event => { + const target = event.target as HTMLElement + if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") { + setIsFocused(true) + } + }, []) + const blurHandler = useCallback(() => { + setIsFocused(false) + }, []) + + useEvent("focus", focusHandler, window, {capture: true}) + useEvent("blur", blurHandler, window, {capture: true}) + + return isFocused +} diff --git a/src/route-widgets/AliasesRoute/AliasesDetails.tsx b/src/route-widgets/AliasesRoute/AliasesDetails.tsx index d7cd522..869ae04 100644 --- a/src/route-widgets/AliasesRoute/AliasesDetails.tsx +++ b/src/route-widgets/AliasesRoute/AliasesDetails.tsx @@ -17,10 +17,9 @@ import { import {AliasTypeIndicator} from "~/components" import {AliasList} from "~/server-types" -import {useUIState} from "~/hooks" +import {useIsAnyInputFocused, useUIState} from "~/hooks" import {SUCCESS_SNACKBAR_SHOW_DURATION} from "~/constants/values" import CreateAliasButton from "~/route-widgets/AliasesRoute/CreateAliasButton" -import EmptyStateScreen from "~/route-widgets/AliasesRoute/EmptyStateScreen" export interface AliasesDetailsProps { aliases: AliasList[] @@ -31,54 +30,53 @@ const getAddress = (alias: AliasList): string => `${alias.local}@${alias.domain} export default function AliasesDetails({aliases}: AliasesDetailsProps): ReactElement { const {t} = useTranslation() const {enqueueSnackbar} = useSnackbar() - const [isInCopyAddressMode] = useKeyPress("Control") + const [isPressingControl] = useKeyPress("Control") + const isAnyInputFocused = useIsAnyInputFocused() const [aliasesUIState, setAliasesUIState] = useUIState(aliases) + const isInCopyAddressMode = !isAnyInputFocused && isPressingControl + return ( - {aliasesUIState.length > 0 ? ( - - {aliasesUIState.map(alias => ( - { - if (isInCopyAddressMode) { - event.preventDefault() - event.stopPropagation() + + {aliasesUIState.map(alias => ( + { + if (isInCopyAddressMode) { + event.preventDefault() + event.stopPropagation() - copy(getAddress(alias)) + copy(getAddress(alias)) - enqueueSnackbar( - t( - "relations.alias.mutations.success.addressCopiedToClipboard", - ), - { - variant: "success", - autoHideDuration: SUCCESS_SNACKBAR_SHOW_DURATION, - }, - ) - } - }} - to={`/aliases/${btoa(getAddress(alias))}`} - > - - - - - {isInCopyAddressMode && ( - - - - )} - - ))} - - ) : ( - - )} + enqueueSnackbar( + t( + "relations.alias.mutations.success.addressCopiedToClipboard", + ), + { + variant: "success", + autoHideDuration: SUCCESS_SNACKBAR_SHOW_DURATION, + }, + ) + } + }} + to={`/aliases/${btoa(getAddress(alias))}`} + > + + + + + {isInCopyAddressMode && ( + + + + )} + + ))} + ("") const [queryValue, setQueryValue] = useState("") const [, startTransition] = useTransition() + const [showSearch, setShowSearch] = useState(false) const query = useQuery, AxiosError>( ["get_aliases", queryValue], @@ -25,14 +26,22 @@ export default function AliasesRoute(): ReactElement { getAliases({ query: queryValue, }), + { + onSuccess: ({items}) => { + if (items.length) { + setShowSearch(true) + } + }, + }, ) return ( 0 && ( + showSearch && ( { setSearchValue(event.target.value) @@ -55,7 +64,19 @@ export default function AliasesRoute(): ReactElement { } > , AxiosError> query={query}> - {result => } + {result => + (() => { + if (result.items.length === 0) { + if (searchValue === "") { + return + } else { + return + } + } + + return + })() + } )