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 { FinishShiftByIdResponse } from './models/FinishShiftByIdResponse';
 | 
			
		||||
export type { FinishShiftResponse } from './models/FinishShiftResponse';
 | 
			
		||||
export type { GenerateInviteCodeRequest } from './models/GenerateInviteCodeRequest';
 | 
			
		||||
export type { GenerateInviteCodeResponse } from './models/GenerateInviteCodeResponse';
 | 
			
		||||
export type { GetAllBarcodeTemplateAttributesResponse } from './models/GetAllBarcodeTemplateAttributesResponse';
 | 
			
		||||
export type { GetAllBarcodeTemplateSizesResponse } from './models/GetAllBarcodeTemplateSizesResponse';
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
import type { Body_upload_passport_image } from '../models/Body_upload_passport_image';
 | 
			
		||||
import type { CreateUserRequest } from '../models/CreateUserRequest';
 | 
			
		||||
import type { CreateUserResponse } from '../models/CreateUserResponse';
 | 
			
		||||
import type { GenerateInviteCodeRequest } from '../models/GenerateInviteCodeRequest';
 | 
			
		||||
import type { GenerateInviteCodeResponse } from '../models/GenerateInviteCodeResponse';
 | 
			
		||||
import type { GetAllUsersResponse } from '../models/GetAllUsersResponse';
 | 
			
		||||
import type { GetManagersResponse } from '../models/GetManagersResponse';
 | 
			
		||||
@@ -134,10 +135,19 @@ export class UserService {
 | 
			
		||||
     * @returns GenerateInviteCodeResponse Successful Response
 | 
			
		||||
     * @throws ApiError
 | 
			
		||||
     */
 | 
			
		||||
    public static generateInviteCode(): CancelablePromise<GenerateInviteCodeResponse> {
 | 
			
		||||
    public static generateInviteCode({
 | 
			
		||||
        requestBody,
 | 
			
		||||
    }: {
 | 
			
		||||
        requestBody: GenerateInviteCodeRequest,
 | 
			
		||||
    }): CancelablePromise<GenerateInviteCodeResponse> {
 | 
			
		||||
        return __request(OpenAPI, {
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            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 { 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 { IconEdit, IconQrcode, IconTrash } from "@tabler/icons-react";
 | 
			
		||||
import { IconEdit, IconTrash } from "@tabler/icons-react";
 | 
			
		||||
import { modals } from "@mantine/modals";
 | 
			
		||||
import { MRT_TableOptions } from "mantine-react-table";
 | 
			
		||||
import { useUsersTabContext } from "../../tabs/Users/contexts/UsersTabContext.tsx";
 | 
			
		||||
import { notifications } from "../../../../shared/lib/notifications.ts";
 | 
			
		||||
import { useClipboard } from "@mantine/hooks";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const UsersTable = () => {
 | 
			
		||||
    const columns = useUsersTableColumns();
 | 
			
		||||
    const clipboard = useClipboard();
 | 
			
		||||
    const {
 | 
			
		||||
        usersCrud: {
 | 
			
		||||
            items,
 | 
			
		||||
@@ -66,40 +63,7 @@ const UsersTable = () => {
 | 
			
		||||
            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 (
 | 
			
		||||
        <BaseTable
 | 
			
		||||
            data={items}
 | 
			
		||||
@@ -117,14 +81,7 @@ const UsersTable = () => {
 | 
			
		||||
                                    onClick={() => onCreateClick()}>
 | 
			
		||||
                                    Создать пользователя
 | 
			
		||||
                                </Button>
 | 
			
		||||
                                <Button
 | 
			
		||||
                                    onClick={() => onCreateInviteCodeClick()}
 | 
			
		||||
                                    variant={"default"}
 | 
			
		||||
                                >
 | 
			
		||||
                                    Создать код приглашения
 | 
			
		||||
                                </Button>
 | 
			
		||||
                            </Flex>
 | 
			
		||||
 | 
			
		||||
                        </Flex>
 | 
			
		||||
                    ),
 | 
			
		||||
                    enableRowActions: true,
 | 
			
		||||
@@ -148,15 +105,7 @@ const UsersTable = () => {
 | 
			
		||||
                                    <IconTrash />
 | 
			
		||||
                                </ActionIcon>
 | 
			
		||||
                            </Tooltip>
 | 
			
		||||
                            <Tooltip
 | 
			
		||||
                                onClick={() => {
 | 
			
		||||
                                    onGenerateQrClick(row.original);
 | 
			
		||||
                                }}
 | 
			
		||||
                                label="QR-код">
 | 
			
		||||
                                <ActionIcon variant={"default"}>
 | 
			
		||||
                                    <IconQrcode />
 | 
			
		||||
                                </ActionIcon>
 | 
			
		||||
                            </Tooltip>
 | 
			
		||||
 | 
			
		||||
                        </Flex>
 | 
			
		||||
                    ),
 | 
			
		||||
                } as MRT_TableOptions<UserSchema>
 | 
			
		||||
 
 | 
			
		||||
@@ -17,12 +17,13 @@ const UserFormModal = ({
 | 
			
		||||
                           id,
 | 
			
		||||
                           innerProps,
 | 
			
		||||
                       }: ContextModalProps<Props>) => {
 | 
			
		||||
 | 
			
		||||
    const isEditing = "element" in innerProps;
 | 
			
		||||
    const [modalTab, setModalTab] = useState<ModalTab>(ModalTab.COMMON);
 | 
			
		||||
 | 
			
		||||
    const closeModal = () => {
 | 
			
		||||
        context.closeContextModal(id);
 | 
			
		||||
    }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (!isEditing) {
 | 
			
		||||
        return (
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
import { UserRoleEnum } from "../../../../../../shared/enums/UserRole.ts";
 | 
			
		||||
import { useForm } from "@mantine/form";
 | 
			
		||||
import { UserSchema } from "../../../../../../client";
 | 
			
		||||
import { UserSchema, UserService } from "../../../../../../client";
 | 
			
		||||
import phone from "phone";
 | 
			
		||||
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 { IMaskInput } from "react-imask";
 | 
			
		||||
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 PositionSelect from "../../../../components/PositionSelect/PositionSelect.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 = {
 | 
			
		||||
@@ -23,6 +26,47 @@ const CommonTab = ({
 | 
			
		||||
                       formProps,
 | 
			
		||||
                   }: Props) => {
 | 
			
		||||
    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
 | 
			
		||||
        ? formProps.element
 | 
			
		||||
        : {
 | 
			
		||||
@@ -189,6 +233,15 @@ const CommonTab = ({
 | 
			
		||||
                            />
 | 
			
		||||
                        </Stack>
 | 
			
		||||
                    </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>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user