feat: invite code
This commit is contained in:
@@ -200,6 +200,7 @@ export type { FinishPauseByShiftIdResponse } from './models/FinishPauseByShiftId
|
|||||||
export type { FinishPauseByUserIdResponse } from './models/FinishPauseByUserIdResponse';
|
export type { FinishPauseByUserIdResponse } from './models/FinishPauseByUserIdResponse';
|
||||||
export type { FinishShiftByIdResponse } from './models/FinishShiftByIdResponse';
|
export type { FinishShiftByIdResponse } from './models/FinishShiftByIdResponse';
|
||||||
export type { FinishShiftResponse } from './models/FinishShiftResponse';
|
export type { FinishShiftResponse } from './models/FinishShiftResponse';
|
||||||
|
export type { GenerateInviteCodeRequest } from './models/GenerateInviteCodeRequest';
|
||||||
export type { GenerateInviteCodeResponse } from './models/GenerateInviteCodeResponse';
|
export type { GenerateInviteCodeResponse } from './models/GenerateInviteCodeResponse';
|
||||||
export type { GetAllBarcodeTemplateAttributesResponse } from './models/GetAllBarcodeTemplateAttributesResponse';
|
export type { GetAllBarcodeTemplateAttributesResponse } from './models/GetAllBarcodeTemplateAttributesResponse';
|
||||||
export type { GetAllBarcodeTemplateSizesResponse } from './models/GetAllBarcodeTemplateSizesResponse';
|
export type { GetAllBarcodeTemplateSizesResponse } from './models/GetAllBarcodeTemplateSizesResponse';
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
import type { Body_upload_passport_image } from '../models/Body_upload_passport_image';
|
import type { Body_upload_passport_image } from '../models/Body_upload_passport_image';
|
||||||
import type { CreateUserRequest } from '../models/CreateUserRequest';
|
import type { CreateUserRequest } from '../models/CreateUserRequest';
|
||||||
import type { CreateUserResponse } from '../models/CreateUserResponse';
|
import type { CreateUserResponse } from '../models/CreateUserResponse';
|
||||||
|
import type { GenerateInviteCodeRequest } from '../models/GenerateInviteCodeRequest';
|
||||||
import type { GenerateInviteCodeResponse } from '../models/GenerateInviteCodeResponse';
|
import type { GenerateInviteCodeResponse } from '../models/GenerateInviteCodeResponse';
|
||||||
import type { GetAllUsersResponse } from '../models/GetAllUsersResponse';
|
import type { GetAllUsersResponse } from '../models/GetAllUsersResponse';
|
||||||
import type { GetManagersResponse } from '../models/GetManagersResponse';
|
import type { GetManagersResponse } from '../models/GetManagersResponse';
|
||||||
@@ -134,10 +135,19 @@ export class UserService {
|
|||||||
* @returns GenerateInviteCodeResponse Successful Response
|
* @returns GenerateInviteCodeResponse Successful Response
|
||||||
* @throws ApiError
|
* @throws ApiError
|
||||||
*/
|
*/
|
||||||
public static generateInviteCode(): CancelablePromise<GenerateInviteCodeResponse> {
|
public static generateInviteCode({
|
||||||
|
requestBody,
|
||||||
|
}: {
|
||||||
|
requestBody: GenerateInviteCodeRequest,
|
||||||
|
}): CancelablePromise<GenerateInviteCodeResponse> {
|
||||||
return __request(OpenAPI, {
|
return __request(OpenAPI, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/user/generate-invite-code',
|
url: '/user/generate-invite-code',
|
||||||
|
body: requestBody,
|
||||||
|
mediaType: 'application/json',
|
||||||
|
errors: {
|
||||||
|
422: `Validation Error`,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,15 @@
|
|||||||
import { UserSchema, UserService } from "../../../../client";
|
import { UserSchema } from "../../../../client";
|
||||||
import { BaseTable } from "../../../../components/BaseTable/BaseTable.tsx";
|
import { BaseTable } from "../../../../components/BaseTable/BaseTable.tsx";
|
||||||
import { ActionIcon, Badge, Button, Flex, Input, rem, Text, Tooltip } from "@mantine/core";
|
import { ActionIcon, Button, Flex, rem, Text, Tooltip } from "@mantine/core";
|
||||||
import { useUsersTableColumns } from "./columns.tsx";
|
import { useUsersTableColumns } from "./columns.tsx";
|
||||||
import { IconEdit, IconQrcode, IconTrash } from "@tabler/icons-react";
|
import { IconEdit, IconTrash } from "@tabler/icons-react";
|
||||||
import { modals } from "@mantine/modals";
|
import { modals } from "@mantine/modals";
|
||||||
import { MRT_TableOptions } from "mantine-react-table";
|
import { MRT_TableOptions } from "mantine-react-table";
|
||||||
import { useUsersTabContext } from "../../tabs/Users/contexts/UsersTabContext.tsx";
|
import { useUsersTabContext } from "../../tabs/Users/contexts/UsersTabContext.tsx";
|
||||||
import { notifications } from "../../../../shared/lib/notifications.ts";
|
|
||||||
import { useClipboard } from "@mantine/hooks";
|
|
||||||
|
|
||||||
|
|
||||||
const UsersTable = () => {
|
const UsersTable = () => {
|
||||||
const columns = useUsersTableColumns();
|
const columns = useUsersTableColumns();
|
||||||
const clipboard = useClipboard();
|
|
||||||
const {
|
const {
|
||||||
usersCrud: {
|
usersCrud: {
|
||||||
items,
|
items,
|
||||||
@@ -66,40 +63,7 @@ const UsersTable = () => {
|
|||||||
size: "md",
|
size: "md",
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const onGenerateQrClick = (user: UserSchema) => {
|
|
||||||
const pdfWindow = window.open(
|
|
||||||
`${import.meta.env.VITE_API_URL}/work-shifts/generate-qr-code/${user.id}`,
|
|
||||||
);
|
|
||||||
if (!pdfWindow) return;
|
|
||||||
pdfWindow.print();
|
|
||||||
};
|
|
||||||
const onCreateInviteCodeClick = async () => {
|
|
||||||
const { inviteCode, ok, message } = await UserService.generateInviteCode();
|
|
||||||
if (!ok || !inviteCode) {
|
|
||||||
notifications.error({ message });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
modals.openConfirmModal({
|
|
||||||
withCloseButton: false,
|
|
||||||
children: (
|
|
||||||
<Flex gap={rem(10)} direction={"column"} justify={"center"} align={"center"}>
|
|
||||||
|
|
||||||
<Text>
|
|
||||||
Ваш код приглашения!
|
|
||||||
</Text>
|
|
||||||
<Badge variant={"default"} style={{cursor:"text"}} radius={"sm"} size={"xl"}>{inviteCode}</Badge>
|
|
||||||
<Input.Description>
|
|
||||||
Код действителен в течении 30 минут
|
|
||||||
</Input.Description>
|
|
||||||
</Flex>
|
|
||||||
|
|
||||||
),
|
|
||||||
labels: { confirm: "Скопировать", cancel: "Закрыть" },
|
|
||||||
onConfirm: () => {
|
|
||||||
clipboard.copy(inviteCode);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<BaseTable
|
<BaseTable
|
||||||
data={items}
|
data={items}
|
||||||
@@ -117,14 +81,7 @@ const UsersTable = () => {
|
|||||||
onClick={() => onCreateClick()}>
|
onClick={() => onCreateClick()}>
|
||||||
Создать пользователя
|
Создать пользователя
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
|
||||||
onClick={() => onCreateInviteCodeClick()}
|
|
||||||
variant={"default"}
|
|
||||||
>
|
|
||||||
Создать код приглашения
|
|
||||||
</Button>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
</Flex>
|
</Flex>
|
||||||
),
|
),
|
||||||
enableRowActions: true,
|
enableRowActions: true,
|
||||||
@@ -148,15 +105,7 @@ const UsersTable = () => {
|
|||||||
<IconTrash />
|
<IconTrash />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip
|
|
||||||
onClick={() => {
|
|
||||||
onGenerateQrClick(row.original);
|
|
||||||
}}
|
|
||||||
label="QR-код">
|
|
||||||
<ActionIcon variant={"default"}>
|
|
||||||
<IconQrcode />
|
|
||||||
</ActionIcon>
|
|
||||||
</Tooltip>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
),
|
),
|
||||||
} as MRT_TableOptions<UserSchema>
|
} as MRT_TableOptions<UserSchema>
|
||||||
|
|||||||
@@ -17,12 +17,13 @@ const UserFormModal = ({
|
|||||||
id,
|
id,
|
||||||
innerProps,
|
innerProps,
|
||||||
}: ContextModalProps<Props>) => {
|
}: ContextModalProps<Props>) => {
|
||||||
|
|
||||||
const isEditing = "element" in innerProps;
|
const isEditing = "element" in innerProps;
|
||||||
const [modalTab, setModalTab] = useState<ModalTab>(ModalTab.COMMON);
|
const [modalTab, setModalTab] = useState<ModalTab>(ModalTab.COMMON);
|
||||||
|
|
||||||
const closeModal = () => {
|
const closeModal = () => {
|
||||||
context.closeContextModal(id);
|
context.closeContextModal(id);
|
||||||
}
|
};
|
||||||
|
|
||||||
if (!isEditing) {
|
if (!isEditing) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { UserRoleEnum } from "../../../../../../shared/enums/UserRole.ts";
|
import { UserRoleEnum } from "../../../../../../shared/enums/UserRole.ts";
|
||||||
import { useForm } from "@mantine/form";
|
import { useForm } from "@mantine/form";
|
||||||
import { UserSchema } from "../../../../../../client";
|
import { UserSchema, UserService } from "../../../../../../client";
|
||||||
import phone from "phone";
|
import phone from "phone";
|
||||||
import BaseFormModal, { CreateEditFormProps } from "../../../../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
|
import BaseFormModal, { CreateEditFormProps } from "../../../../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
|
||||||
import { Checkbox, Fieldset, Input, Stack, Textarea, TextInput } from "@mantine/core";
|
import { Badge, Button, Checkbox, Fieldset, Flex, Input, rem, Stack, Text, Textarea, TextInput } from "@mantine/core";
|
||||||
import { capitalize } from "lodash";
|
import { capitalize } from "lodash";
|
||||||
import { IMaskInput } from "react-imask";
|
import { IMaskInput } from "react-imask";
|
||||||
import PassportImageDropzone from "../../../../components/PassportImageDropzone/PassportImageDropzone.tsx";
|
import PassportImageDropzone from "../../../../components/PassportImageDropzone/PassportImageDropzone.tsx";
|
||||||
@@ -11,6 +11,9 @@ import { BaseFormInputProps } from "../../../../../../types/utils.ts";
|
|||||||
import RoleSelect from "../../../../components/RoleSelect/RoleSelect.tsx";
|
import RoleSelect from "../../../../components/RoleSelect/RoleSelect.tsx";
|
||||||
import PositionSelect from "../../../../components/PositionSelect/PositionSelect.tsx";
|
import PositionSelect from "../../../../components/PositionSelect/PositionSelect.tsx";
|
||||||
import PayRateSelect from "../../../../../../components/Selects/PayRateSelect/PayRateSelect.tsx";
|
import PayRateSelect from "../../../../../../components/Selects/PayRateSelect/PayRateSelect.tsx";
|
||||||
|
import { useClipboard } from "@mantine/hooks";
|
||||||
|
import { notifications } from "../../../../../../shared/lib/notifications.ts";
|
||||||
|
import { modals } from "@mantine/modals";
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -23,6 +26,47 @@ const CommonTab = ({
|
|||||||
formProps,
|
formProps,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const isEditing = "element" in formProps;
|
const isEditing = "element" in formProps;
|
||||||
|
const clipboard = useClipboard();
|
||||||
|
const onCreateInviteCodeClick = async () => {
|
||||||
|
if (!isEditing) return;
|
||||||
|
const {
|
||||||
|
inviteCode,
|
||||||
|
ok,
|
||||||
|
message,
|
||||||
|
} = await UserService.generateInviteCode({ requestBody: { userId: formProps.element.id } });
|
||||||
|
if (!ok || !inviteCode) {
|
||||||
|
notifications.error({ message });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
modals.openConfirmModal({
|
||||||
|
withCloseButton: false,
|
||||||
|
children: (
|
||||||
|
<Flex gap={rem(10)} direction={"column"} justify={"center"} align={"center"}>
|
||||||
|
|
||||||
|
<Text>
|
||||||
|
Ваш код приглашения!
|
||||||
|
</Text>
|
||||||
|
<Badge variant={"default"} style={{ cursor: "text" }} radius={"sm"} size={"xl"}>{inviteCode}</Badge>
|
||||||
|
<Input.Description>
|
||||||
|
Код действителен в течении 30 минут
|
||||||
|
</Input.Description>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
),
|
||||||
|
labels: { confirm: "Скопировать", cancel: "Закрыть" },
|
||||||
|
onConfirm: () => {
|
||||||
|
clipboard.copy(inviteCode);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const onGenerateQrClick = () => {
|
||||||
|
if (!isEditing) return;
|
||||||
|
const pdfWindow = window.open(
|
||||||
|
`${import.meta.env.VITE_API_URL}/work-shifts/generate-qr-code/${formProps.element.id}`,
|
||||||
|
);
|
||||||
|
if (!pdfWindow) return;
|
||||||
|
pdfWindow.print();
|
||||||
|
};
|
||||||
const initialValues = isEditing
|
const initialValues = isEditing
|
||||||
? formProps.element
|
? formProps.element
|
||||||
: {
|
: {
|
||||||
@@ -189,6 +233,15 @@ const CommonTab = ({
|
|||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Fieldset>
|
</Fieldset>
|
||||||
|
{isEditing && (
|
||||||
|
<Fieldset pt={rem(20)}>
|
||||||
|
<Flex h={"100%"} justify={"center"} gap={rem(10)} direction={"column"}>
|
||||||
|
<Button onClick={() => onCreateInviteCodeClick()} variant={"default"}>Код
|
||||||
|
приглашения</Button>
|
||||||
|
<Button onClick={() => onGenerateQrClick()} variant={"default"}>QR Код</Button>
|
||||||
|
</Flex>
|
||||||
|
</Fieldset>)
|
||||||
|
}
|
||||||
</>
|
</>
|
||||||
</BaseFormModal.Body>
|
</BaseFormModal.Body>
|
||||||
</BaseFormModal>
|
</BaseFormModal>
|
||||||
|
|||||||
Reference in New Issue
Block a user