mirror of
https://github.com/Myzel394/kleckrelay-website.git
synced 2025-06-20 08:15:26 +02:00
current stand
This commit is contained in:
parent
ff972478be
commit
89dae6ca0e
@ -130,6 +130,14 @@
|
|||||||
"search": {
|
"search": {
|
||||||
"label": "Search",
|
"label": "Search",
|
||||||
"placeholder": "Search for names"
|
"placeholder": "Search for names"
|
||||||
|
},
|
||||||
|
"searchFilter": {
|
||||||
|
"active": "Active",
|
||||||
|
"inactive": "Inactive"
|
||||||
|
},
|
||||||
|
"typeFilter": {
|
||||||
|
"custom": "Custom made",
|
||||||
|
"random": "Randomly generated"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
import {AliasList, GetPageData, PaginationResult} from "~/server-types"
|
import {AliasList, AliasType, GetPageData, PaginationResult} from "~/server-types"
|
||||||
import {client} from "~/constants/axios-client"
|
import {client} from "~/constants/axios-client"
|
||||||
|
|
||||||
export interface GetAliasesData extends GetPageData {
|
export interface GetAliasesData extends GetPageData {
|
||||||
query?: string
|
query?: string
|
||||||
|
active?: boolean
|
||||||
|
type?: AliasType
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function getAliases({
|
export default async function getAliases({
|
||||||
query,
|
query,
|
||||||
size,
|
size,
|
||||||
page,
|
page,
|
||||||
|
active,
|
||||||
|
type,
|
||||||
}: GetAliasesData): Promise<PaginationResult<AliasList>> {
|
}: GetAliasesData): Promise<PaginationResult<AliasList>> {
|
||||||
const {data} = await client.get(`${import.meta.env.VITE_SERVER_BASE_URL}/v1/alias`, {
|
const {data} = await client.get(`${import.meta.env.VITE_SERVER_BASE_URL}/v1/alias`, {
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
@ -16,6 +20,8 @@ export default async function getAliases({
|
|||||||
query,
|
query,
|
||||||
size,
|
size,
|
||||||
page,
|
page,
|
||||||
|
active,
|
||||||
|
aliasType: type,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ export interface AliasTypeIndicatorProps {
|
|||||||
type: AliasType
|
type: AliasType
|
||||||
}
|
}
|
||||||
|
|
||||||
const ALIAS_TYPE_ICON_MAP: Record<AliasType, ReactElement> = {
|
export const ALIAS_TYPE_ICON_MAP: Record<AliasType, ReactElement> = {
|
||||||
[AliasType.RANDOM]: <FaRandom />,
|
[AliasType.RANDOM]: <FaRandom />,
|
||||||
[AliasType.CUSTOM]: <FaHashtag />,
|
[AliasType.CUSTOM]: <FaHashtag />,
|
||||||
}
|
}
|
||||||
|
@ -5,16 +5,45 @@ import {useTranslation} from "react-i18next"
|
|||||||
import {useCopyToClipboard, useKeyPress, useUpdateEffect} from "react-use"
|
import {useCopyToClipboard, useKeyPress, useUpdateEffect} from "react-use"
|
||||||
|
|
||||||
import {useQuery} from "@tanstack/react-query"
|
import {useQuery} from "@tanstack/react-query"
|
||||||
import {Alert, Grid, InputAdornment, List, Snackbar, TextField} from "@mui/material"
|
import {
|
||||||
|
Alert,
|
||||||
|
Chip,
|
||||||
|
Divider,
|
||||||
|
Grid,
|
||||||
|
InputAdornment,
|
||||||
|
List,
|
||||||
|
Snackbar,
|
||||||
|
TextField,
|
||||||
|
ToggleButton,
|
||||||
|
} from "@mui/material"
|
||||||
|
|
||||||
import {AliasList, PaginationResult} from "~/server-types"
|
import {AliasList, AliasType, PaginationResult} from "~/server-types"
|
||||||
import {ErrorSnack, NoSearchResults, QueryResult, SimplePage, SuccessSnack} from "~/components"
|
import {
|
||||||
|
ALIAS_TYPE_ICON_MAP,
|
||||||
|
ErrorSnack,
|
||||||
|
NoSearchResults,
|
||||||
|
QueryResult,
|
||||||
|
SimplePage,
|
||||||
|
SuccessSnack,
|
||||||
|
} from "~/components"
|
||||||
import {useIsAnyInputFocused} from "~/hooks"
|
import {useIsAnyInputFocused} from "~/hooks"
|
||||||
import {CreateAliasButton} from "~/route-widgets/AliasesRoute/CreateAliasButton"
|
import {CreateAliasButton} from "~/route-widgets/AliasesRoute/CreateAliasButton"
|
||||||
import AliasesListItem from "~/route-widgets/AliasesRoute/AliasesListItem"
|
import AliasesListItem from "~/route-widgets/AliasesRoute/AliasesListItem"
|
||||||
import EmptyStateScreen from "~/route-widgets/AliasesRoute/EmptyStateScreen"
|
import EmptyStateScreen from "~/route-widgets/AliasesRoute/EmptyStateScreen"
|
||||||
import getAliases from "~/apis/get-aliases"
|
import getAliases from "~/apis/get-aliases"
|
||||||
|
|
||||||
|
enum SearchFilter {
|
||||||
|
All = "all",
|
||||||
|
Active = "active",
|
||||||
|
Inactive = "inactive",
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TypeFilter {
|
||||||
|
All = "all",
|
||||||
|
Custom = "custom",
|
||||||
|
Random = "random",
|
||||||
|
}
|
||||||
|
|
||||||
export default function AliasesRoute(): ReactElement {
|
export default function AliasesRoute(): ReactElement {
|
||||||
const {t} = useTranslation()
|
const {t} = useTranslation()
|
||||||
|
|
||||||
@ -22,6 +51,8 @@ export default function AliasesRoute(): ReactElement {
|
|||||||
const [queryValue, setQueryValue] = useState<string>("")
|
const [queryValue, setQueryValue] = useState<string>("")
|
||||||
const [, startTransition] = useTransition()
|
const [, startTransition] = useTransition()
|
||||||
const [showSearch, setShowSearch] = useState<boolean>(false)
|
const [showSearch, setShowSearch] = useState<boolean>(false)
|
||||||
|
const [searchFilter, setSearchFilter] = useState<SearchFilter>(SearchFilter.All)
|
||||||
|
const [typeFilter, setTypeFilter] = useState<TypeFilter>(TypeFilter.All)
|
||||||
|
|
||||||
const [{value, error}, copyToClipboard] = useCopyToClipboard()
|
const [{value, error}, copyToClipboard] = useCopyToClipboard()
|
||||||
const [isPressingControl] = useKeyPress("Shift")
|
const [isPressingControl] = useKeyPress("Shift")
|
||||||
@ -30,15 +61,37 @@ export default function AliasesRoute(): ReactElement {
|
|||||||
const isInCopyAddressMode = !isAnyInputFocused && !lockDisabledCopyMode && isPressingControl
|
const isInCopyAddressMode = !isAnyInputFocused && !lockDisabledCopyMode && isPressingControl
|
||||||
|
|
||||||
const query = useQuery<PaginationResult<AliasList>, AxiosError>(
|
const query = useQuery<PaginationResult<AliasList>, AxiosError>(
|
||||||
["get_aliases", queryValue],
|
["get_aliases", queryValue, searchFilter, typeFilter],
|
||||||
() =>
|
() =>
|
||||||
getAliases({
|
getAliases({
|
||||||
query: queryValue,
|
query: queryValue,
|
||||||
|
active: (() => {
|
||||||
|
switch (searchFilter) {
|
||||||
|
case SearchFilter.All:
|
||||||
|
return undefined
|
||||||
|
case SearchFilter.Active:
|
||||||
|
return true
|
||||||
|
case SearchFilter.Inactive:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})(),
|
||||||
|
type: (() => {
|
||||||
|
switch (typeFilter) {
|
||||||
|
case TypeFilter.All:
|
||||||
|
return undefined
|
||||||
|
case TypeFilter.Custom:
|
||||||
|
return AliasType.CUSTOM
|
||||||
|
case TypeFilter.Random:
|
||||||
|
return AliasType.RANDOM
|
||||||
|
}
|
||||||
|
})(),
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
onSuccess: ({items}) => {
|
onSuccess: ({items}) => {
|
||||||
if (items.length) {
|
if (items.length) {
|
||||||
setShowSearch(true)
|
setShowSearch(true)
|
||||||
|
setSearchFilter(SearchFilter.All)
|
||||||
|
setTypeFilter(TypeFilter.All)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -55,26 +108,131 @@ export default function AliasesRoute(): ReactElement {
|
|||||||
title={t("routes.AliasesRoute.title")}
|
title={t("routes.AliasesRoute.title")}
|
||||||
pageOptionsActions={
|
pageOptionsActions={
|
||||||
showSearch && (
|
showSearch && (
|
||||||
<TextField
|
<Grid container spacing={2} direction="column">
|
||||||
key="search"
|
<Grid item>
|
||||||
value={searchValue}
|
<TextField
|
||||||
onChange={event => {
|
key="search"
|
||||||
setSearchValue(event.target.value)
|
fullWidth
|
||||||
startTransition(() => {
|
value={searchValue}
|
||||||
setQueryValue(event.target.value)
|
onChange={event => {
|
||||||
})
|
setSearchValue(event.target.value)
|
||||||
}}
|
startTransition(() => {
|
||||||
label={t("routes.AliasesRoute.pageActions.search.label")}
|
setQueryValue(event.target.value)
|
||||||
placeholder={t("routes.AliasesRoute.pageActions.search.placeholder")}
|
})
|
||||||
id="search"
|
}}
|
||||||
InputProps={{
|
label={t("routes.AliasesRoute.pageActions.search.label")}
|
||||||
startAdornment: (
|
placeholder={t(
|
||||||
<InputAdornment position="start">
|
"routes.AliasesRoute.pageActions.search.placeholder",
|
||||||
<MdSearch />
|
)}
|
||||||
</InputAdornment>
|
id="search"
|
||||||
),
|
InputProps={{
|
||||||
}}
|
startAdornment: (
|
||||||
/>
|
<InputAdornment position="start">
|
||||||
|
<MdSearch />
|
||||||
|
</InputAdornment>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Grid container justifyContent="space-between">
|
||||||
|
<Grid item>
|
||||||
|
<Grid container spacing={1}>
|
||||||
|
<Grid item>
|
||||||
|
<Chip
|
||||||
|
label={t(
|
||||||
|
"routes.AliasesRoute.pageActions.searchFilter.active",
|
||||||
|
)}
|
||||||
|
variant={
|
||||||
|
searchFilter === SearchFilter.Active
|
||||||
|
? "filled"
|
||||||
|
: "outlined"
|
||||||
|
}
|
||||||
|
onClick={() =>
|
||||||
|
setSearchFilter(value => {
|
||||||
|
if (value === SearchFilter.Active) {
|
||||||
|
return SearchFilter.All
|
||||||
|
}
|
||||||
|
|
||||||
|
return SearchFilter.Active
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Chip
|
||||||
|
label={t(
|
||||||
|
"routes.AliasesRoute.pageActions.searchFilter.inactive",
|
||||||
|
)}
|
||||||
|
variant={
|
||||||
|
searchFilter === SearchFilter.Inactive
|
||||||
|
? "filled"
|
||||||
|
: "outlined"
|
||||||
|
}
|
||||||
|
onClick={() =>
|
||||||
|
setSearchFilter(value => {
|
||||||
|
if (value === SearchFilter.Inactive) {
|
||||||
|
return SearchFilter.All
|
||||||
|
}
|
||||||
|
|
||||||
|
return SearchFilter.Inactive
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Grid container spacing={1}>
|
||||||
|
<Grid item>
|
||||||
|
<Chip
|
||||||
|
icon={ALIAS_TYPE_ICON_MAP[AliasType.CUSTOM]}
|
||||||
|
label={t(
|
||||||
|
"routes.AliasesRoute.pageActions.typeFilter.custom",
|
||||||
|
)}
|
||||||
|
variant={
|
||||||
|
typeFilter === TypeFilter.Custom
|
||||||
|
? "filled"
|
||||||
|
: "outlined"
|
||||||
|
}
|
||||||
|
onClick={() =>
|
||||||
|
setTypeFilter(value => {
|
||||||
|
if (value === TypeFilter.Custom) {
|
||||||
|
return TypeFilter.All
|
||||||
|
}
|
||||||
|
|
||||||
|
return TypeFilter.Custom
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Chip
|
||||||
|
icon={ALIAS_TYPE_ICON_MAP[AliasType.RANDOM]}
|
||||||
|
label={t(
|
||||||
|
"routes.AliasesRoute.pageActions.typeFilter.random",
|
||||||
|
)}
|
||||||
|
variant={
|
||||||
|
typeFilter === TypeFilter.Random
|
||||||
|
? "filled"
|
||||||
|
: "outlined"
|
||||||
|
}
|
||||||
|
onClick={() =>
|
||||||
|
setTypeFilter(value => {
|
||||||
|
if (value === TypeFilter.Random) {
|
||||||
|
return TypeFilter.All
|
||||||
|
}
|
||||||
|
|
||||||
|
return TypeFilter.Random
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@ -85,7 +243,11 @@ export default function AliasesRoute(): ReactElement {
|
|||||||
<Grid item>
|
<Grid item>
|
||||||
{(() => {
|
{(() => {
|
||||||
if (aliases.length === 0) {
|
if (aliases.length === 0) {
|
||||||
if (searchValue === "") {
|
if (
|
||||||
|
searchValue === "" &&
|
||||||
|
searchFilter === SearchFilter.All &&
|
||||||
|
typeFilter === TypeFilter.All
|
||||||
|
) {
|
||||||
return <EmptyStateScreen />
|
return <EmptyStateScreen />
|
||||||
} else {
|
} else {
|
||||||
return <NoSearchResults />
|
return <NoSearchResults />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user