Files
Homarr/src/pages/manage/users/create.tsx

214 lines
6.3 KiB
TypeScript
Raw Normal View History

2023-08-01 01:13:21 +02:00
import { Alert, Button, Card, Flex, Group, Stepper, Table, Text, Title } from '@mantine/core';
2023-07-29 17:29:57 +02:00
import { useForm, zodResolver } from '@mantine/form';
import {
IconArrowLeft,
2023-07-29 17:29:57 +02:00
IconCheck,
IconInfoCircle,
IconKey,
IconMail,
2023-07-29 17:29:57 +02:00
IconMailCheck,
IconUser,
IconUserPlus,
2023-07-29 17:29:57 +02:00
} from '@tabler/icons-react';
2023-07-29 16:17:34 +02:00
import Head from 'next/head';
2023-07-29 17:29:57 +02:00
import Link from 'next/link';
2023-07-29 16:17:34 +02:00
import { useState } from 'react';
2023-07-29 17:29:57 +02:00
import { z } from 'zod';
import {
CreateAccountStep,
createAccountStepValidationSchema,
} from '~/components/Admin/CreateNewUser/create-account-step';
import {
CreateAccountSecurityStep,
createAccountSecurityStepValidationSchema,
} from '~/components/Admin/CreateNewUser/security-step';
2023-08-01 01:13:21 +02:00
import { ManageLayout } from '~/components/layout/Templates/ManageLayout';
2023-07-29 17:29:57 +02:00
import { api } from '~/utils/api';
2023-07-29 16:17:34 +02:00
const CreateNewUserPage = () => {
2023-07-29 17:29:57 +02:00
const [active, setActive] = useState(0);
2023-07-29 16:17:34 +02:00
const nextStep = () => setActive((current) => (current < 3 ? current + 1 : current));
const prevStep = () => setActive((current) => (current > 0 ? current - 1 : current));
2023-07-29 17:29:57 +02:00
const form = useForm({
initialValues: {
account: {
username: '',
eMail: '',
},
security: {
password: '',
},
},
validate: zodResolver(
z.object({
account: createAccountStepValidationSchema,
security: createAccountSecurityStepValidationSchema,
})
),
});
2023-07-29 20:12:49 +02:00
const context = api.useContext();
const { mutateAsync, isLoading } = api.user.createUser.useMutation({
2023-07-29 20:12:49 +02:00
onSettled: () => {
void context.user.getAll.invalidate();
},
onSuccess: () => {
nextStep();
},
2023-07-29 20:12:49 +02:00
});
2023-07-29 17:29:57 +02:00
2023-07-29 16:17:34 +02:00
return (
2023-08-01 01:13:21 +02:00
<ManageLayout>
2023-07-29 16:17:34 +02:00
<Head>
<title>Create user Homarr</title>
</Head>
2023-07-29 17:29:57 +02:00
<Stepper active={active} onStepClick={setActive} breakpoint="sm" mih="100%">
2023-07-29 16:17:34 +02:00
<Stepper.Step
allowStepClick={false}
allowStepSelect={false}
icon={<IconUser />}
label="First step"
2023-07-29 17:29:57 +02:00
description="Create account"
2023-07-29 16:17:34 +02:00
>
2023-07-29 17:29:57 +02:00
<CreateAccountStep
nextStep={(value) => {
form.setFieldValue('account', value);
nextStep();
}}
/>
2023-07-29 16:17:34 +02:00
</Stepper.Step>
<Stepper.Step
allowStepClick={false}
allowStepSelect={false}
icon={<IconKey />}
2023-07-29 16:17:34 +02:00
label="Second step"
2023-07-29 17:29:57 +02:00
description="Password"
2023-07-29 16:17:34 +02:00
>
2023-07-29 17:29:57 +02:00
<CreateAccountSecurityStep
nextStep={(value) => {
form.setFieldValue('security', value);
nextStep();
}}
prevStep={prevStep}
/>
2023-07-29 16:17:34 +02:00
</Stepper.Step>
<Stepper.Step
allowStepClick={false}
allowStepSelect={false}
2023-07-29 17:29:57 +02:00
icon={<IconMailCheck />}
2023-07-29 16:17:34 +02:00
label="Final step"
2023-07-29 17:29:57 +02:00
description="Save to database"
2023-07-29 16:17:34 +02:00
>
2023-07-29 17:29:57 +02:00
<Card mih={400}>
<Title order={5}>Review your inputs</Title>
<Text mb="xl">
After you submit your data to the database, the user will be able to log in. Are you
sure that you want to store this user in the database and activate the login?
2023-07-29 17:29:57 +02:00
</Text>
<Table mb="lg" withBorder highlightOnHover>
<thead>
<tr>
<th>Property</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<Group spacing="xs">
<IconUser size="1rem" />
<Text>Username</Text>
</Group>
</td>
<td>{form.values.account.username}</td>
</tr>
<tr>
<td>
<Group spacing="xs">
<IconMail size="1rem" />
<Text>E-Mail</Text>
</Group>
</td>
<td>
{form.values.account.eMail ? (
<Text>{form.values.account.eMail}</Text>
) : (
<Group spacing="xs">
<IconInfoCircle size="1rem" color="orange" />
<Text color="orange">Not set</Text>
</Group>
)}
</td>
</tr>
<tr>
<td>
<Group spacing="xs">
<IconKey size="1rem" />
<Text>Password</Text>
</Group>
</td>
<td>
<Group spacing="xs">
<IconCheck size="1rem" color="green" />
<Text color="green">Valid</Text>
</Group>
</td>
</tr>
</tbody>
</Table>
2023-07-29 17:29:57 +02:00
<Flex justify="end" wrap="nowrap">
<Button
onClick={async () => {
await mutateAsync({
username: form.values.account.username,
password: form.values.security.password,
email: form.values.account.eMail === '' ? undefined : form.values.account.eMail,
});
}}
loading={isLoading}
2023-07-29 17:29:57 +02:00
rightIcon={<IconCheck size="1rem" />}
variant="light"
px="xl"
>
Confirm
2023-07-29 17:29:57 +02:00
</Button>
</Flex>
</Card>
2023-07-29 16:17:34 +02:00
</Stepper.Step>
<Stepper.Completed>
<Alert title="User was created" color="green" mb="md">
User has been created in the database. They can now log in.
</Alert>
<Group>
<Button
onClick={() => {
form.reset();
setActive(0);
}}
leftIcon={<IconUserPlus size="1rem" />}
variant="default"
>
Create another
</Button>
<Button
component={Link}
leftIcon={<IconArrowLeft size="1rem" />}
variant="default"
href="/manage/users"
>
Go back to users
</Button>
</Group>
</Stepper.Completed>
2023-07-29 16:17:34 +02:00
</Stepper>
2023-08-01 01:13:21 +02:00
</ManageLayout>
2023-07-29 16:17:34 +02:00
);
};
export default CreateNewUserPage;