feat(user): add CreateUser button&page
This commit is contained in:
parent
9c7c6e9a58
commit
b515ae3e67
6 changed files with 136 additions and 1 deletions
1
src/app/users/new/page.tsx
Normal file
1
src/app/users/new/page.tsx
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export {NewUserPage as default, generateMetadata} from "@/plain-pages/new-user";
|
1
src/plain-pages/new-user/index.ts
Normal file
1
src/plain-pages/new-user/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export {NewUserPage, generateMetadata} from "./page";
|
19
src/plain-pages/new-user/page.tsx
Normal file
19
src/plain-pages/new-user/page.tsx
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
"use server";
|
||||||
|
|
||||||
|
import {ClientPage} from "./ui";
|
||||||
|
import {Metadata} from "next";
|
||||||
|
|
||||||
|
const generateMetadata = async (): Promise<Metadata> => {
|
||||||
|
return {
|
||||||
|
title: 'Добавить пользователя',
|
||||||
|
description: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const Page = async () => {
|
||||||
|
return (
|
||||||
|
<ClientPage/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {Page as NewUserPage, generateMetadata};
|
85
src/plain-pages/new-user/ui.tsx
Normal file
85
src/plain-pages/new-user/ui.tsx
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import {AppShell, AppShellHeader, AppShellMain, Button, PasswordInput, Stack, TextInput, Title} from "@mantine/core";
|
||||||
|
import {Header} from "@/components/header";
|
||||||
|
import React from "react";
|
||||||
|
import {useForm} from "@mantine/form";
|
||||||
|
import {useRouter} from "next/navigation";
|
||||||
|
import {useMutation} from "@tanstack/react-query";
|
||||||
|
import {CreateUser, Credentials} from "@/shared/api";
|
||||||
|
import {CreateUserResponse} from "../../../proto/user/v1/api";
|
||||||
|
|
||||||
|
const Page = () => {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const form = useForm({
|
||||||
|
initialValues: {
|
||||||
|
username: "",
|
||||||
|
password: ""
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const mutation = useMutation({
|
||||||
|
mutationFn: async (credentials: Credentials) => {
|
||||||
|
return await CreateUser(credentials)
|
||||||
|
},
|
||||||
|
onSuccess: async (data: CreateUserResponse) => {
|
||||||
|
await router.push(`/users/${data.id}`)
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
form.clearErrors();
|
||||||
|
|
||||||
|
form.setFieldError("username", "Что-то пошло не так. Попробуйте позже.")
|
||||||
|
},
|
||||||
|
retry: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
mutation.mutate(form.getValues())
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppShell header={{height: 70}}>
|
||||||
|
<AppShellHeader>
|
||||||
|
<Header/>
|
||||||
|
</AppShellHeader>
|
||||||
|
<AppShellMain>
|
||||||
|
<form
|
||||||
|
onSubmit={onSubmit}
|
||||||
|
>
|
||||||
|
<Stack
|
||||||
|
align="center"
|
||||||
|
justify="center"
|
||||||
|
w="fit-content"
|
||||||
|
m="auto"
|
||||||
|
mt="5%"
|
||||||
|
p="md"
|
||||||
|
style={{color: "var(--mantine-color-bright)"}}
|
||||||
|
>
|
||||||
|
<Title>Добавить пользователя</Title>
|
||||||
|
<Stack w="100%" gap="0" align="center">
|
||||||
|
<TextInput
|
||||||
|
label="Username"
|
||||||
|
placeholder="Username"
|
||||||
|
key={form.key('username')}
|
||||||
|
w="250"
|
||||||
|
{...form.getInputProps('username')}
|
||||||
|
/>
|
||||||
|
<PasswordInput
|
||||||
|
label="Пароль"
|
||||||
|
placeholder="Пароль"
|
||||||
|
w="250"
|
||||||
|
key={form.key('password')}
|
||||||
|
{...form.getInputProps('password')}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
<Button type="submit" loading={mutation.isPending}>Добавить</Button>
|
||||||
|
</Stack>
|
||||||
|
</form>
|
||||||
|
</AppShellMain>
|
||||||
|
</AppShell>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export {Page as ClientPage};
|
|
@ -6,6 +6,7 @@ import {
|
||||||
AppShellAside,
|
AppShellAside,
|
||||||
AppShellHeader,
|
AppShellHeader,
|
||||||
AppShellMain,
|
AppShellMain,
|
||||||
|
Button,
|
||||||
Pagination,
|
Pagination,
|
||||||
Stack,
|
Stack,
|
||||||
Table,
|
Table,
|
||||||
|
@ -99,6 +100,9 @@ const ClientPage = (props: Props) => {
|
||||||
<AppShellAside withBorder={false} px="16">
|
<AppShellAside withBorder={false} px="16">
|
||||||
<Stack pt="16">
|
<Stack pt="16">
|
||||||
<TextInput placeholder="Поиск"/>
|
<TextInput placeholder="Поиск"/>
|
||||||
|
<Button component={Link} href="/users/new">
|
||||||
|
Добавить пользователя
|
||||||
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
</AppShellAside>
|
</AppShellAside>
|
||||||
</AppShell>
|
</AppShell>
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {decode} from "jsonwebtoken";
|
||||||
import {cookies} from "next/headers";
|
import {cookies} from "next/headers";
|
||||||
import {authApi} from "./config";
|
import {authApi} from "./config";
|
||||||
|
|
||||||
type Credentials = {
|
export type Credentials = {
|
||||||
username: string,
|
username: string,
|
||||||
password: string
|
password: string
|
||||||
}
|
}
|
||||||
|
@ -163,6 +163,7 @@ export const GetMe = async () => {
|
||||||
|
|
||||||
if (session === undefined) {
|
if (session === undefined) {
|
||||||
throw new Error("Session id not found");
|
throw new Error("Session id not found");
|
||||||
|
// redirect("/login");
|
||||||
}
|
}
|
||||||
|
|
||||||
const options: AxiosRequestConfig = {
|
const options: AxiosRequestConfig = {
|
||||||
|
@ -173,6 +174,10 @@ export const GetMe = async () => {
|
||||||
|
|
||||||
const token = new JWTWithPermissions(decode(session.value) as JWT);
|
const token = new JWTWithPermissions(decode(session.value) as JWT);
|
||||||
|
|
||||||
|
// if (token.exp < Date.now() / 1000) {
|
||||||
|
// redirect("/login");
|
||||||
|
// }
|
||||||
|
|
||||||
const response = await authApi.getUser(token.user_id, options);
|
const response = await authApi.getUser(token.user_id, options);
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
|
@ -197,3 +202,23 @@ export const GetUsers = async (page: number, pageSize: number) => {
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const CreateUser = async (credentials: Credentials) => {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
|
||||||
|
const session = cookieStore.get(CookieName);
|
||||||
|
|
||||||
|
if (session === undefined) {
|
||||||
|
throw new Error("Session id not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
const options: AxiosRequestConfig = {
|
||||||
|
headers: {
|
||||||
|
'Authorization': "Bearer " + session.value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await authApi.createUser(credentials, options);
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue