diff --git a/site/src/components/CreateUserForm/CreateUserForm.stories.tsx b/site/src/components/CreateUserForm/CreateUserForm.stories.tsx new file mode 100644 index 0000000000..4d9b27980f --- /dev/null +++ b/site/src/components/CreateUserForm/CreateUserForm.stories.tsx @@ -0,0 +1,22 @@ +import { Story } from "@storybook/react" +import React from "react" +import { CreateUserForm, CreateUserFormProps } from "./CreateUserForm" + +export default { + title: "components/CreateUserForm", + component: CreateUserForm, + argTypes: { + isLoading: "boolean", + authErrorMessage: "string", + onSubmit: { action: "Submit" }, + }, +} + +const Template: Story = (args: CreateUserFormProps) => + +export const Example = Template.bind({}) +Example.args = { + onSubmit: () => { + return Promise.resolve() + }, +} diff --git a/site/src/components/CreateUserForm/CreateUserForm.tsx b/site/src/components/CreateUserForm/CreateUserForm.tsx new file mode 100644 index 0000000000..9be5e2087b --- /dev/null +++ b/site/src/components/CreateUserForm/CreateUserForm.tsx @@ -0,0 +1,80 @@ +import Button from "@material-ui/core/Button" +import TextField from "@material-ui/core/TextField" +import { FormikContextType, useFormik } from "formik" +import React from "react" +import * as Yup from "yup" +import { CreateUserRequest } from "../../api/typesGenerated" +import { getFormHelpers, onChangeTrimmed } from "../../util/formUtils" +import { LoadingButton } from "../LoadingButton/LoadingButton" + +const Language = { + emailLabel: "Email", + passwordLabel: "Password", + usernameLabel: "Username", + emailInvalid: "Please enter a valid email address.", + emailRequired: "Please enter an email address.", + passwordRequired: "Please enter a password.", + usernameRequired: "Please enter a username.", + createUser: "Create", + cancel: "Cancel", +} + +export interface CreateUserFormProps { + onSubmit: (user: CreateUserRequest) => void +} + +const validationSchema = Yup.object({ + email: Yup.string().trim().email(Language.emailInvalid).required(Language.emailRequired), + password: Yup.string().required(), + username: Yup.string().required(), +}) + +export const CreateUserForm: React.FC = ({ onSubmit }) => { + const form: FormikContextType = useFormik({ + initialValues: { + email: "", + password: "", + username: "", + }, + validationSchema, + onSubmit, + }) + + return ( +
+ (form, "username")} + onChange={onChangeTrimmed(form)} + autoFocus + autoComplete="username" + fullWidth + label={Language.usernameLabel} + variant="outlined" + /> + (form, "email")} + onChange={onChangeTrimmed(form)} + autoFocus + autoComplete="email" + fullWidth + label={Language.emailLabel} + variant="outlined" + /> + (form, "password")} + autoComplete="current-password" + fullWidth + id="password" + label={Language.passwordLabel} + type="password" + variant="outlined" + /> +
+ + {Language.createUser} + + +
+ + ) +} diff --git a/site/src/pages/UsersPage/CreateUserPage/CreateUserPage.tsx b/site/src/pages/UsersPage/CreateUserPage/CreateUserPage.tsx index f21789b603..4d558706ac 100644 --- a/site/src/pages/UsersPage/CreateUserPage/CreateUserPage.tsx +++ b/site/src/pages/UsersPage/CreateUserPage/CreateUserPage.tsx @@ -1,5 +1,12 @@ -import React from "react" +import { useActor } from "@xstate/react" +import React, { useContext } from "react" +import { CreateUserRequest } from "../../../api/typesGenerated" +import { CreateUserForm } from "../../../components/CreateUserForm/CreateUserForm" +import { XServiceContext } from "../../../xServices/StateContext" export const CreateUserPage = () => { - return
"Coming soon!"
+ const xServices = useContext(XServiceContext) + const [_, usersSend] = useActor(xServices.usersXService) + + return usersSend({ type: "CREATE", user })} /> }