added NoSearchResults.tsx to AliasesRoute.tsx

This commit is contained in:
Myzel394 2022-11-02 18:39:35 +01:00
parent dcde72e4d2
commit bd883431ff
7 changed files with 118 additions and 45 deletions

View File

@ -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."
}
},

View File

@ -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 (
<Grid container spacing={4} direction="column" alignItems="center">
<Grid item>
<Typography variant="h6">{t("components.NoSearchResults.title")}</Typography>
</Grid>
<Grid item>
<FaQuestion size={40} />
</Grid>
<Grid item>
<Typography variant="body1">
{t("components.NoSearchResults.description")}
</Typography>
</Grid>
</Grid>
)
}

View File

@ -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"

View File

@ -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"

View File

@ -0,0 +1,21 @@
import {useCallback, useState} from "react"
import {useEvent} from "react-use"
export default function useIsAnyInputFocused(): boolean {
const [isFocused, setIsFocused] = useState<boolean>(false)
const focusHandler = useCallback<EventListener>(event => {
const target = event.target as HTMLElement
if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") {
setIsFocused(true)
}
}, [])
const blurHandler = useCallback<EventListener>(() => {
setIsFocused(false)
}, [])
useEvent("focus", focusHandler, window, {capture: true})
useEvent("blur", blurHandler, window, {capture: true})
return isFocused
}

View File

@ -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<AliasList[]>(aliases)
const isInCopyAddressMode = !isAnyInputFocused && isPressingControl
return (
<Grid container spacing={4} direction="column">
<Grid item>
{aliasesUIState.length > 0 ? (
<List>
{aliasesUIState.map(alias => (
<ListItemButton
component={RouterLink}
key={alias.id}
onClick={event => {
if (isInCopyAddressMode) {
event.preventDefault()
event.stopPropagation()
<List>
{aliasesUIState.map(alias => (
<ListItemButton
component={RouterLink}
key={alias.id}
onClick={event => {
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))}`}
>
<ListItemIcon>
<AliasTypeIndicator type={alias.type} />
</ListItemIcon>
<ListItemText primary={getAddress(alias)} />
{isInCopyAddressMode && (
<ListItemSecondaryAction>
<MdContentCopy />
</ListItemSecondaryAction>
)}
</ListItemButton>
))}
</List>
) : (
<EmptyStateScreen />
)}
enqueueSnackbar(
t(
"relations.alias.mutations.success.addressCopiedToClipboard",
),
{
variant: "success",
autoHideDuration: SUCCESS_SNACKBAR_SHOW_DURATION,
},
)
}
}}
to={`/aliases/${btoa(getAddress(alias))}`}
>
<ListItemIcon>
<AliasTypeIndicator type={alias.type} />
</ListItemIcon>
<ListItemText primary={getAddress(alias)} />
{isInCopyAddressMode && (
<ListItemSecondaryAction>
<MdContentCopy />
</ListItemSecondaryAction>
)}
</ListItemButton>
))}
</List>
</Grid>
<Grid item>
<CreateAliasButton

View File

@ -7,7 +7,7 @@ import {useQuery} from "@tanstack/react-query"
import {InputAdornment, TextField} from "@mui/material"
import {AliasList, PaginationResult} from "~/server-types"
import {QueryResult, SimplePage} from "~/components"
import {NoSearchResults, QueryResult, SimplePage} from "~/components"
import AliasesDetails from "~/route-widgets/AliasesRoute/AliasesDetails"
import EmptyStateScreen from "~/route-widgets/AliasesRoute/EmptyStateScreen"
import getAliases from "~/apis/get-aliases"
@ -18,6 +18,7 @@ export default function AliasesRoute(): ReactElement {
const [searchValue, setSearchValue] = useState<string>("")
const [queryValue, setQueryValue] = useState<string>("")
const [, startTransition] = useTransition()
const [showSearch, setShowSearch] = useState<boolean>(false)
const query = useQuery<PaginationResult<AliasList>, AxiosError>(
["get_aliases", queryValue],
@ -25,14 +26,22 @@ export default function AliasesRoute(): ReactElement {
getAliases({
query: queryValue,
}),
{
onSuccess: ({items}) => {
if (items.length) {
setShowSearch(true)
}
},
},
)
return (
<SimplePage
title={t("routes.AliasesRoute.title")}
pageOptionsActions={
(query.data?.items?.length || 0) > 0 && (
showSearch && (
<TextField
key="search"
value={searchValue}
onChange={event => {
setSearchValue(event.target.value)
@ -55,7 +64,19 @@ export default function AliasesRoute(): ReactElement {
}
>
<QueryResult<PaginationResult<AliasList>, AxiosError> query={query}>
{result => <AliasesDetails aliases={result.items} />}
{result =>
(() => {
if (result.items.length === 0) {
if (searchValue === "") {
return <EmptyStateScreen />
} else {
return <NoSearchResults />
}
}
return <AliasesDetails aliases={result.items} />
})()
}
</QueryResult>
</SimplePage>
)