mirror of
https://github.com/Myzel394/kleckrelay-website.git
synced 2025-06-19 07:55:25 +02:00
added NoSearchResults.tsx to AliasesRoute.tsx
This commit is contained in:
parent
dcde72e4d2
commit
bd883431ff
@ -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."
|
||||
}
|
||||
},
|
||||
|
||||
|
25
src/components/NoSearchResults.tsx
Normal file
25
src/components/NoSearchResults.tsx
Normal 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>
|
||||
)
|
||||
}
|
@ -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"
|
||||
|
@ -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"
|
||||
|
21
src/hooks/use-is-any-input-focused.ts
Normal file
21
src/hooks/use-is-any-input-focused.ts
Normal 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
|
||||
}
|
@ -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
|
||||
|
@ -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>
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user