diff --git a/src/App.tsx b/src/App.tsx
index 62d9b06..67e8221 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -13,7 +13,9 @@ import AliasesRoute from "~/routes/AliasesRoute"
import AuthenticateRoute from "~/routes/AuthenticateRoute"
import AuthenticatedRoute from "~/routes/AuthenticatedRoute"
import CompleteAccountRoute from "~/routes/CompleteAccountRoute"
+import CreateReservedAliasRoute from "~/routes/CreateReservedAliasRoute"
import EnterDecryptionPassword from "~/routes/EnterDecryptionPassword"
+import I18nHandler from "./I18nHandler"
import LoginRoute from "~/routes/LoginRoute"
import LogoutRoute from "~/routes/LogoutRoute"
import OverviewRoute from "~/routes/OverviewRoute"
@@ -23,9 +25,6 @@ import RootRoute from "~/routes/Root"
import SettingsRoute from "~/routes/SettingsRoute"
import SignupRoute from "~/routes/SignupRoute"
import VerifyEmailRoute from "~/routes/VerifyEmailRoute"
-
-import AdminRoute from "~/routes/AdminRoute"
-import I18nHandler from "./I18nHandler"
import "./init-i18n"
const router = createBrowserRouter([
@@ -101,9 +100,9 @@ const router = createBrowserRouter([
element: ,
},
{
- path: "/admin",
+ path: "/admin/reserved-aliases/create",
loader: getServerSettings,
- element: ,
+ element: ,
},
],
},
diff --git a/src/route-widgets/AdminPage/AliasExplanation.tsx b/src/route-widgets/CreateReservedAliasRoute/AliasExplanation.tsx
similarity index 100%
rename from src/route-widgets/AdminPage/AliasExplanation.tsx
rename to src/route-widgets/CreateReservedAliasRoute/AliasExplanation.tsx
diff --git a/src/route-widgets/CreateReservedAliasRoute/UsersSelectField.tsx b/src/route-widgets/CreateReservedAliasRoute/UsersSelectField.tsx
new file mode 100644
index 0000000..feff4b2
--- /dev/null
+++ b/src/route-widgets/CreateReservedAliasRoute/UsersSelectField.tsx
@@ -0,0 +1,132 @@
+import {ReactElement} from "react"
+import {HiUsers} from "react-icons/hi"
+import {useTranslation} from "react-i18next"
+import {AxiosError} from "axios"
+
+import {useQuery} from "@tanstack/react-query"
+import {
+ Box,
+ Checkbox,
+ Chip,
+ FormControl,
+ FormHelperText,
+ InputAdornment,
+ InputLabel,
+ ListItemText,
+ MenuItem,
+ Select,
+ SelectProps,
+} from "@mui/material"
+
+import {GetAdminUsersResponse, getAdminUsers} from "~/apis"
+import {useUser} from "~/hooks"
+
+export interface UsersSelectFieldProps extends Omit {
+ onChange: SelectProps["onChange"]
+ value: GetAdminUsersResponse["users"]
+
+ helperText?: string | string[]
+ error?: boolean
+}
+
+export default function UsersSelectField({
+ value,
+ onChange,
+ helperText,
+ error,
+ ...props
+}: UsersSelectFieldProps): ReactElement {
+ const {t} = useTranslation()
+ const meUser = useUser()
+ const {data: {users} = {}} = useQuery(
+ ["getAdminUsers"],
+ getAdminUsers,
+ )
+ const findUser = (id: string) => users?.find(user => user.id === id)
+ const userIds = value?.map(user => user.id) || []
+
+ return (
+
+
+ {t("routes.AdminRoute.forms.reservedAliases.fields.users.label")}
+
+
+ {helperText ? {helperText} : null}
+
+ )
+}
diff --git a/src/route-widgets/AdminPage/ReservedAliasesForm.tsx b/src/routes/CreateReservedAliasRoute.tsx
similarity index 54%
rename from src/route-widgets/AdminPage/ReservedAliasesForm.tsx
rename to src/routes/CreateReservedAliasRoute.tsx
index e8309ed..f61df89 100644
--- a/src/route-widgets/AdminPage/ReservedAliasesForm.tsx
+++ b/src/routes/CreateReservedAliasRoute.tsx
@@ -3,44 +3,32 @@ import {ReactElement} from "react"
import {AxiosError} from "axios"
import {useTranslation} from "react-i18next"
import {useFormik} from "formik"
-
-import {useMutation, useQuery} from "@tanstack/react-query"
-
-import {
- CreateReservedAliasData,
- GetAdminUsersResponse,
- createReservedAlias,
- getAdminUsers,
-} from "~/apis"
-import {Grid, InputAdornment, MenuItem, TextField} from "@mui/material"
import {BiText} from "react-icons/bi"
-import {HiUsers} from "react-icons/hi"
-import {useErrorSuccessSnacks, useNavigateToNext, useUser} from "~/hooks"
-import {ReservedAlias, ServerUser} from "~/server-types"
+
+import {useMutation} from "@tanstack/react-query"
+import {Grid, InputAdornment, TextField} from "@mui/material"
+
+import {CreateReservedAliasData, GetAdminUsersResponse, createReservedAlias} from "~/apis"
+import {useErrorSuccessSnacks, useNavigateToNext} from "~/hooks"
+import {ReservedAlias} from "~/server-types"
import {parseFastAPIError} from "~/utils"
import {SimpleForm} from "~/components"
-import AliasExplanation from "~/route-widgets/AdminPage/AliasExplanation"
+import AliasExplanation from "~/route-widgets/CreateReservedAliasRoute/AliasExplanation"
+import UsersSelectField from "~/route-widgets/CreateReservedAliasRoute/UsersSelectField"
interface Form {
local: string
- users: string[]
+ users: GetAdminUsersResponse["users"]
isActive?: boolean
- nonFieldError?: string
+ detail?: string
}
-export interface ReservedAliasesFormProps {}
-
-export default function ReservedAliasesForm({}: ReservedAliasesFormProps): ReactElement {
+export default function CreateReservedAliasRoute(): ReactElement {
const {t} = useTranslation()
- const meUser = useUser()
- const {showError, showSuccess} = useErrorSuccessSnacks()
+ const {showSuccess} = useErrorSuccessSnacks()
const navigateToNext = useNavigateToNext("/admin/reserved-aliases")
- const {data: {users} = {}} = useQuery(
- ["getAdminUsers"],
- getAdminUsers,
- )
const {mutateAsync: createAlias} = useMutation<
ReservedAlias,
AxiosError,
@@ -63,7 +51,15 @@ export default function ReservedAliasesForm({}: ReservedAliasesFormProps): React
// Only store IDs of users, as they provide a reference to the user
users: yup
.array()
- .of(yup.string())
+ .of(
+ yup.object().shape({
+ id: yup.string(),
+ email: yup.object().shape({
+ id: yup.string(),
+ address: yup.string(),
+ }),
+ }),
+ )
.label(t("routes.AdminRoute.forms.reservedAliases.fields.users.label")),
})
const formik = useFormik
- getUser(userId).email.address)}
- />
+
)