135 lines
4.0 KiB
TypeScript
135 lines
4.0 KiB
TypeScript
import ErrorDisplay from "@/ui/error-display";
|
|
import { useApi } from "@/util/api";
|
|
import {
|
|
Avatar,
|
|
Button,
|
|
Center,
|
|
Container,
|
|
Fieldset,
|
|
Group,
|
|
Loader,
|
|
PasswordInput,
|
|
Stack,
|
|
Text,
|
|
Title,
|
|
} from "@mantine/core";
|
|
import { useForm } from "@mantine/form";
|
|
import { IconFingerprint } from "@tabler/icons-react";
|
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
|
import { AxiosError } from "axios";
|
|
|
|
export default function Me() {
|
|
const client = useApi();
|
|
|
|
const user = useQuery({
|
|
queryKey: ["user"],
|
|
queryFn: async () => await client.get(`users/me`).then((res) => res.data),
|
|
});
|
|
|
|
const updatePassword = useMutation({
|
|
mutationFn: async (values: {
|
|
current_psk: string;
|
|
new_psk: string;
|
|
confirm_new_psk: string;
|
|
}) => {
|
|
await client.put(`/users/me/password`, {
|
|
current_password: values.current_psk,
|
|
new_password: values.new_psk,
|
|
});
|
|
},
|
|
});
|
|
|
|
const updatePskForm = useForm({
|
|
initialValues: {
|
|
current_psk: "",
|
|
new_psk: "",
|
|
confirm_new_psk: "",
|
|
},
|
|
validate: {
|
|
current_psk: (value) =>
|
|
value.length === 0 ? "Please enter your current password" : null,
|
|
new_psk: (value) => {
|
|
if (value.length === 0) return "Please enter a new password";
|
|
if (value.length < 8 || value.length > 16)
|
|
return "Password must be between 8 and 16 characters";
|
|
},
|
|
confirm_new_psk: (value, values) => {
|
|
if (value.length === 0) return "Please confirm your new password";
|
|
if (value.length < 8 || value.length > 16)
|
|
return "Password must be between 8 and 16 characters";
|
|
if (value !== values.new_psk) return "Passwords must match";
|
|
},
|
|
},
|
|
});
|
|
|
|
return (
|
|
<Container>
|
|
{user.isLoading ? (
|
|
<Center h="calc(100vh - 95px)">
|
|
<Loader />
|
|
</Center>
|
|
) : user.isError ? (
|
|
<Center h="calc(100vh - 95px)">
|
|
<ErrorDisplay error="Error Loading User" />
|
|
</Center>
|
|
) : user.data ? (
|
|
<Stack pt="xl">
|
|
<Stack align="center" pb="xl">
|
|
<Avatar size="xl" />
|
|
<Title order={2}>{user.data.username}</Title>
|
|
<Text>
|
|
{user.data.level === 2
|
|
? "Admin"
|
|
: user.data.level === 1
|
|
? "User"
|
|
: "Guest"}
|
|
</Text>{" "}
|
|
</Stack>
|
|
<form
|
|
onSubmit={updatePskForm.onSubmit((values) => {
|
|
updatePassword.mutate(values);
|
|
})}
|
|
>
|
|
<Fieldset legend="Update Password">
|
|
<PasswordInput
|
|
label="Current Password"
|
|
{...updatePskForm.getInputProps("current_psk")}
|
|
/>
|
|
<PasswordInput
|
|
mt="sm"
|
|
label="New Password"
|
|
{...updatePskForm.getInputProps("new_psk")}
|
|
/>
|
|
<PasswordInput
|
|
mt="sm"
|
|
label="Confirm New Password"
|
|
{...updatePskForm.getInputProps("confirm_new_psk")}
|
|
/>
|
|
<Group justify="flex-end" mt="lg">
|
|
{updatePassword.isPending ? (
|
|
<Text>Updating...</Text>
|
|
) : updatePassword.isError ? (
|
|
updatePassword.error &&
|
|
(updatePassword.error as AxiosError).response?.status ===
|
|
403 ? (
|
|
<Text c="red">Incorrect password</Text>
|
|
) : (
|
|
<Text c="red">Failed: {updatePassword.error.message}</Text>
|
|
)
|
|
) : updatePassword.isSuccess ? (
|
|
<Text c="green">Updated</Text>
|
|
) : null}
|
|
<Button type="submit" leftSection={<IconFingerprint />}>
|
|
Update
|
|
</Button>
|
|
</Group>
|
|
</Fieldset>
|
|
</form>
|
|
</Stack>
|
|
) : (
|
|
<Text c="red">Unknown Error</Text>
|
|
)}
|
|
</Container>
|
|
);
|
|
}
|