diff --git a/src/route-widgets/AliasesRoute/AliasListItem.tsx b/src/route-widgets/AliasesRoute/AliasListItem.tsx deleted file mode 100644 index 19b0c78..0000000 --- a/src/route-widgets/AliasesRoute/AliasListItem.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import {ReactElement} from "react" -import {FaHashtag, FaRandom} from "react-icons/fa" - -import {ListItemButton, ListItemIcon, ListItemText} from "@mui/material" - -import {AliasList, AliasType} from "~/server-types" -import AliasTypeIndicator from "~/components/AliasTypeIndicator" - -export interface AliasListItemProps { - alias: AliasList -} - -const ALIAS_TYPE_ICON_MAP: Record = { - [AliasType.RANDOM]: , - [AliasType.CUSTOM]: , -} - -export default function AliasListItem({ - alias, -}: AliasListItemProps): ReactElement { - const address = `${alias.local}@${alias.domain}` - - return ( - - - - - - - ) -} diff --git a/src/route-widgets/AliasesRoute/AliasesDetails.tsx b/src/route-widgets/AliasesRoute/AliasesDetails.tsx new file mode 100644 index 0000000..23411ef --- /dev/null +++ b/src/route-widgets/AliasesRoute/AliasesDetails.tsx @@ -0,0 +1,59 @@ +import {ReactElement} from "react" + +import { + Grid, + List, + ListItemButton, + ListItemIcon, + ListItemText, +} from "@mui/material" + +import {AliasTypeIndicator} from "~/components" +import {AliasList} from "~/server-types" +import {useUIState} from "~/hooks" +import CreateAliasButton from "~/route-widgets/AliasesRoute/CreateAliasButton" + +export interface AliasesDetailsProps { + aliases: AliasList[] +} + +const getAddress = (alias: AliasList): string => + `${alias.local}@${alias.domain}` + +export default function AliasesDetails({ + aliases, +}: AliasesDetailsProps): ReactElement { + const [aliasesUIState, setAliasesUIState] = useUIState(aliases) + + return ( + <> + + + + {aliasesUIState.map(alias => ( + + + + + + + ))} + + + + + setAliasesUIState(currentAliases => [ + alias, + ...currentAliases, + ]) + } + /> + + + + ) +} diff --git a/src/route-widgets/AliasesRoute/CreateAliasButton.tsx b/src/route-widgets/AliasesRoute/CreateAliasButton.tsx index 73f26fc..d321fe9 100644 --- a/src/route-widgets/AliasesRoute/CreateAliasButton.tsx +++ b/src/route-widgets/AliasesRoute/CreateAliasButton.tsx @@ -15,27 +15,32 @@ import { } from "@mui/material" import {useMutation} from "@tanstack/react-query" -import {createAlias} from "~/apis" +import {CreateAliasData, createAlias} from "~/apis" import {Alias, AliasType} from "~/server-types" +import {parseFastAPIError} from "~/utils" +import {ErrorSnack, SuccessSnack} from "~/components" +import CustomAliasDialog from "~/route-widgets/AliasesRoute/CustomAliasDialog" export interface CreateAliasButtonProps { - onRandomCreated: (alias: Alias) => void - onCustomCreated: () => void + onCreated: (alias: Alias) => void } export default function CreateAliasButton({ - onRandomCreated, - onCustomCreated, + onCreated, }: CreateAliasButtonProps): ReactElement { - const {mutate, isLoading} = useMutation( - () => - createAlias({ - type: AliasType.RANDOM, - }), - { - onSuccess: onRandomCreated, - }, - ) + const [errorMessage, setErrorMessage] = useState("") + const {mutateAsync, isLoading, isSuccess} = useMutation< + Alias, + AxiosError, + CreateAliasData + >(values => createAlias(values), { + onSuccess: onCreated, + onError: error => + setErrorMessage(parseFastAPIError(error).detail as string), + }) + + const [showCustomCreateDialog, setShowCustomCreateDialog] = + useState(false) const [anchorElement, setAnchorElement] = useState(null) const open = Boolean(anchorElement) @@ -46,7 +51,11 @@ export default function CreateAliasButton({ @@ -64,9 +73,10 @@ export default function CreateAliasButton({ > { + setShowCustomCreateDialog(true) setAnchorElement(null) - onCustomCreated() }} > @@ -76,6 +86,19 @@ export default function CreateAliasButton({ + { + await mutateAsync(values) + setShowCustomCreateDialog(false) + }} + onClose={() => setShowCustomCreateDialog(false)} + /> + + ) } diff --git a/src/route-widgets/AliasesRoute/CustomAliasDialog.tsx b/src/route-widgets/AliasesRoute/CustomAliasDialog.tsx index a9b23b0..ee932fb 100644 --- a/src/route-widgets/AliasesRoute/CustomAliasDialog.tsx +++ b/src/route-widgets/AliasesRoute/CustomAliasDialog.tsx @@ -18,17 +18,16 @@ import { TextField, Typography, } from "@mui/material" -import {useMutation} from "@tanstack/react-query" -import {Alias, AliasType, ServerSettings} from "~/server-types" -import {CreateAliasData, createAlias} from "~/apis" +import {AliasType, ServerSettings} from "~/server-types" +import {CreateAliasData} from "~/apis" import {parseFastAPIError} from "~/utils" import {LOCAL_REGEX} from "~/constants/values" -import {ErrorSnack, SuccessSnack} from "~/components" export interface CustomAliasDialogProps { visible: boolean - onCreated: () => void + onCreate: (values: CreateAliasData) => void + isLoading: boolean onClose: () => void } @@ -40,7 +39,8 @@ interface Form { export default function CustomAliasDialog({ visible, - onCreated, + isLoading, + onCreate, onClose, }: CustomAliasDialogProps): ReactElement { const serverSettings = useLoaderData() as ServerSettings @@ -54,25 +54,6 @@ export default function CustomAliasDialog({ .max(64 - serverSettings.customAliasSuffixLength - 1), }) - const {mutateAsync, isLoading, isSuccess, reset} = useMutation< - Alias, - AxiosError, - Omit - >( - values => - // @ts-ignore - createAlias({ - type: AliasType.CUSTOM, - ...values, - }), - { - onSuccess: () => { - reset() - onCreated() - }, - }, - ) - const formik = useFormik
({ validationSchema: schema, initialValues: { @@ -80,9 +61,11 @@ export default function CustomAliasDialog({ }, onSubmit: async (values, {setErrors}) => { try { - await mutateAsync({ + await onCreate({ local: values.local, + type: AliasType.CUSTOM, }) + formik.resetForm() } catch (error) { setErrors(parseFastAPIError(error as AxiosError)) } @@ -90,75 +73,68 @@ export default function CustomAliasDialog({ }) return ( - <> - - - Create Custom Alias - - - You can define your own custom alias. Note that a - random suffix will be added at the end to avoid - duplicates. - - - - - - {Array( - serverSettings.customAliasSuffixLength, - ) - .fill("#") - .join("")} - - - @{serverSettings.mailDomain} - - - - ), - }} - /> - - - - - - - -
- - - + +
+ Create Custom Alias + + + You can define your own custom alias. Note that a random + suffix will be added at the end to avoid duplicates. + + + + + + {Array( + serverSettings.customAliasSuffixLength, + ) + .fill("#") + .join("")} + + + @{serverSettings.mailDomain} + + + + ), + }} + /> + + + + + + +
+
) } diff --git a/src/routes/AliasesRoute.tsx b/src/routes/AliasesRoute.tsx index 05c06c3..dec15df 100644 --- a/src/routes/AliasesRoute.tsx +++ b/src/routes/AliasesRoute.tsx @@ -1,13 +1,10 @@ import {ReactElement, useState} from "react" import {AxiosError} from "axios" -import {List} from "@mui/material" import {useQuery} from "@tanstack/react-query" import {AliasList, PaginationResult} from "~/server-types" -import AliasListItem from "~/route-widgets/AliasesRoute/AliasListItem" -import CreateAliasButton from "~/route-widgets/AliasesRoute/CreateAliasButton" -import CustomAliasDialog from "~/route-widgets/AliasesRoute/CustomAliasDialog" +import AliasesDetails from "~/route-widgets/AliasesRoute/AliasesDetails" import QueryResult from "~/components/QueryResult" import SimplePage from "~/components/SimplePage" import getAliases from "~/apis/get-aliases" @@ -22,34 +19,10 @@ export default function AliasesRoute(): ReactElement { useState(false) return ( - <> - query.refetch()} - onCustomCreated={() => setShowCustomCreateDialog(true)} - /> - } - > - > query={query}> - {result => ( - - {result.items.map(alias => ( - - ))} - - )} - - - { - setShowCustomCreateDialog(false) - query.refetch() - }} - onClose={() => setShowCustomCreateDialog(false)} - /> - + + > query={query}> + {result => } + + ) }