From 23dbff2891df4a9c16d074b71d1c224618c30577 Mon Sep 17 00:00:00 2001 From: fakz9 Date: Mon, 22 Jul 2024 12:46:12 +0300 Subject: [PATCH] k --- src/client/index.ts | 19 ++ src/client/models/CreatePayRateRequest.ts | 9 + src/client/models/CreatePayRateResponse.ts | 9 + .../models/CreatePaymentRecordRequest.ts | 9 + .../models/CreatePaymentRecordResponse.ts | 9 + src/client/models/DeletePayRateRequest.ts | 8 + src/client/models/DeletePayRateResponse.ts | 9 + .../models/DeletePaymentRecordRequest.ts | 8 + .../models/DeletePaymentRecordResponse.ts | 9 + src/client/models/GetAllPayRatesResponse.ts | 9 + .../models/GetAllPayrollSchemeResponse.ts | 9 + .../models/GetPaymentRecordsResponse.ts | 11 ++ src/client/models/PayRateSchema.ts | 14 ++ src/client/models/PayRateSchemaBase.ts | 13 ++ .../models/PaymentRecordCreateSchema.ts | 12 ++ src/client/models/PaymentRecordGetSchema.ts | 18 ++ src/client/models/PayrollSchemeSchema.ts | 9 + src/client/models/UpdatePayRateRequest.ts | 9 + src/client/models/UpdatePayRateResponse.ts | 9 + src/client/models/UserSchema.ts | 2 + src/client/models/UserUpdate.ts | 2 + src/client/services/PayrollService.ts | 168 ++++++++++++++++++ .../DealSummaryCard.module.css | 2 +- .../BaseMarketplaceSelect.tsx | 2 +- .../Selects/PayRateSelect/PayRateSelect.tsx | 19 ++ .../PayrollSchemeSelect.tsx | 19 ++ src/hooks/objectList.tsx | 32 +++- src/hooks/usePaymentRecordsList.tsx | 11 ++ src/hooks/usePayrollSchemasList.tsx | 9 + src/modals/modals.ts | 6 +- src/pages/AdminPage/AdminPage.tsx | 21 ++- .../components/PayRateTable/PayRateTable.tsx | 94 ++++++++++ .../components/PayRateTable/columns.tsx | 32 ++++ .../PaymentRecordsTable.tsx | 123 +++++++++++++ .../PaymentRecordsTable/columns.tsx | 58 ++++++ .../components/UsersTable/UsersTable.tsx | 15 +- .../components/UsersTable/columns.tsx | 21 +-- src/pages/AdminPage/hooks/usePayRatesList.tsx | 9 + .../CreatePaymentRecordModal.tsx | 130 ++++++++++++++ .../PayRateFormModal/PayRateFormModal.tsx | 98 ++++++++++ .../modals/UserFormModal/UserFormModal.tsx | 21 ++- .../AdminPage/tabs/Finances/FinancesTab.tsx | 97 ++++++++++ src/routes/test.lazy.tsx | 8 +- src/shared/enums/PaySchemeType.ts | 5 + src/types/Pagination.ts | 4 + src/types/utils.ts | 3 + 46 files changed, 1173 insertions(+), 40 deletions(-) create mode 100644 src/client/models/CreatePayRateRequest.ts create mode 100644 src/client/models/CreatePayRateResponse.ts create mode 100644 src/client/models/CreatePaymentRecordRequest.ts create mode 100644 src/client/models/CreatePaymentRecordResponse.ts create mode 100644 src/client/models/DeletePayRateRequest.ts create mode 100644 src/client/models/DeletePayRateResponse.ts create mode 100644 src/client/models/DeletePaymentRecordRequest.ts create mode 100644 src/client/models/DeletePaymentRecordResponse.ts create mode 100644 src/client/models/GetAllPayRatesResponse.ts create mode 100644 src/client/models/GetAllPayrollSchemeResponse.ts create mode 100644 src/client/models/GetPaymentRecordsResponse.ts create mode 100644 src/client/models/PayRateSchema.ts create mode 100644 src/client/models/PayRateSchemaBase.ts create mode 100644 src/client/models/PaymentRecordCreateSchema.ts create mode 100644 src/client/models/PaymentRecordGetSchema.ts create mode 100644 src/client/models/PayrollSchemeSchema.ts create mode 100644 src/client/models/UpdatePayRateRequest.ts create mode 100644 src/client/models/UpdatePayRateResponse.ts create mode 100644 src/client/services/PayrollService.ts create mode 100644 src/components/Selects/PayRateSelect/PayRateSelect.tsx create mode 100644 src/components/Selects/PayrollSchemeSelect/PayrollSchemeSelect.tsx create mode 100644 src/hooks/usePaymentRecordsList.tsx create mode 100644 src/hooks/usePayrollSchemasList.tsx create mode 100644 src/pages/AdminPage/components/PayRateTable/PayRateTable.tsx create mode 100644 src/pages/AdminPage/components/PayRateTable/columns.tsx create mode 100644 src/pages/AdminPage/components/PaymentRecordsTable/PaymentRecordsTable.tsx create mode 100644 src/pages/AdminPage/components/PaymentRecordsTable/columns.tsx create mode 100644 src/pages/AdminPage/hooks/usePayRatesList.tsx create mode 100644 src/pages/AdminPage/modals/CreatePaymentRecordModal/CreatePaymentRecordModal.tsx create mode 100644 src/pages/AdminPage/modals/PayRateFormModal/PayRateFormModal.tsx create mode 100644 src/pages/AdminPage/tabs/Finances/FinancesTab.tsx create mode 100644 src/shared/enums/PaySchemeType.ts create mode 100644 src/types/Pagination.ts diff --git a/src/client/index.ts b/src/client/index.ts index 45c28b4..dedad37 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -37,6 +37,10 @@ export type { ClientUpdateRequest } from './models/ClientUpdateRequest'; export type { ClientUpdateResponse } from './models/ClientUpdateResponse'; export type { CreateBarcodeTemplateAttributeRequest } from './models/CreateBarcodeTemplateAttributeRequest'; export type { CreateBarcodeTemplateAttributeResponse } from './models/CreateBarcodeTemplateAttributeResponse'; +export type { CreatePaymentRecordRequest } from './models/CreatePaymentRecordRequest'; +export type { CreatePaymentRecordResponse } from './models/CreatePaymentRecordResponse'; +export type { CreatePayRateRequest } from './models/CreatePayRateRequest'; +export type { CreatePayRateResponse } from './models/CreatePayRateResponse'; export type { CreatePositionRequest } from './models/CreatePositionRequest'; export type { CreatePositionResponse } from './models/CreatePositionResponse'; export type { DealAddProductRequest } from './models/DealAddProductRequest'; @@ -80,24 +84,36 @@ export type { DealUpdateServiceQuantityRequest } from './models/DealUpdateServic export type { DealUpdateServiceQuantityResponse } from './models/DealUpdateServiceQuantityResponse'; export type { DealUpdateServiceRequest } from './models/DealUpdateServiceRequest'; export type { DealUpdateServiceResponse } from './models/DealUpdateServiceResponse'; +export type { DeletePaymentRecordRequest } from './models/DeletePaymentRecordRequest'; +export type { DeletePaymentRecordResponse } from './models/DeletePaymentRecordResponse'; +export type { DeletePayRateRequest } from './models/DeletePayRateRequest'; +export type { DeletePayRateResponse } from './models/DeletePayRateResponse'; export type { DeletePositionRequest } from './models/DeletePositionRequest'; export type { DeletePositionResponse } from './models/DeletePositionResponse'; export type { GetAllBarcodeTemplateAttributesResponse } from './models/GetAllBarcodeTemplateAttributesResponse'; export type { GetAllBarcodeTemplateSizesResponse } from './models/GetAllBarcodeTemplateSizesResponse'; export type { GetAllBarcodeTemplatesResponse } from './models/GetAllBarcodeTemplatesResponse'; export type { GetAllBaseMarketplacesResponse } from './models/GetAllBaseMarketplacesResponse'; +export type { GetAllPayRatesResponse } from './models/GetAllPayRatesResponse'; +export type { GetAllPayrollSchemeResponse } from './models/GetAllPayrollSchemeResponse'; export type { GetAllPositionsResponse } from './models/GetAllPositionsResponse'; export type { GetAllRolesResponse } from './models/GetAllRolesResponse'; export type { GetAllShippingWarehousesResponse } from './models/GetAllShippingWarehousesResponse'; export type { GetAllUsersResponse } from './models/GetAllUsersResponse'; export type { GetBarcodeTemplateByIdRequest } from './models/GetBarcodeTemplateByIdRequest'; export type { GetBarcodeTemplateByIdResponse } from './models/GetBarcodeTemplateByIdResponse'; +export type { GetPaymentRecordsResponse } from './models/GetPaymentRecordsResponse'; export type { GetProductBarcodePdfRequest } from './models/GetProductBarcodePdfRequest'; export type { GetProductBarcodePdfResponse } from './models/GetProductBarcodePdfResponse'; export type { GetProductBarcodeRequest } from './models/GetProductBarcodeRequest'; export type { GetProductBarcodeResponse } from './models/GetProductBarcodeResponse'; export type { HTTPValidationError } from './models/HTTPValidationError'; export type { PaginationInfoSchema } from './models/PaginationInfoSchema'; +export type { PaymentRecordCreateSchema } from './models/PaymentRecordCreateSchema'; +export type { PaymentRecordGetSchema } from './models/PaymentRecordGetSchema'; +export type { PayRateSchema } from './models/PayRateSchema'; +export type { PayRateSchemaBase } from './models/PayRateSchemaBase'; +export type { PayrollSchemeSchema } from './models/PayrollSchemeSchema'; export type { PermissionSchema } from './models/PermissionSchema'; export type { PositionSchema } from './models/PositionSchema'; export type { ProductAddBarcodeRequest } from './models/ProductAddBarcodeRequest'; @@ -130,6 +146,8 @@ export type { ServiceSchema } from './models/ServiceSchema'; export type { ServiceUpdateRequest } from './models/ServiceUpdateRequest'; export type { ServiceUpdateResponse } from './models/ServiceUpdateResponse'; export type { ShippingWarehouseSchema } from './models/ShippingWarehouseSchema'; +export type { UpdatePayRateRequest } from './models/UpdatePayRateRequest'; +export type { UpdatePayRateResponse } from './models/UpdatePayRateResponse'; export type { UpdateUserRequest } from './models/UpdateUserRequest'; export type { UpdateUserResponse } from './models/UpdateUserResponse'; export type { UserSchema } from './models/UserSchema'; @@ -141,6 +159,7 @@ export { BarcodeService } from './services/BarcodeService'; export { ClientService } from './services/ClientService'; export { DealService } from './services/DealService'; export { MarketplaceService } from './services/MarketplaceService'; +export { PayrollService } from './services/PayrollService'; export { PositionService } from './services/PositionService'; export { ProductService } from './services/ProductService'; export { RoleService } from './services/RoleService'; diff --git a/src/client/models/CreatePayRateRequest.ts b/src/client/models/CreatePayRateRequest.ts new file mode 100644 index 0000000..c80d1d9 --- /dev/null +++ b/src/client/models/CreatePayRateRequest.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { PayRateSchemaBase } from './PayRateSchemaBase'; +export type CreatePayRateRequest = { + data: PayRateSchemaBase; +}; + diff --git a/src/client/models/CreatePayRateResponse.ts b/src/client/models/CreatePayRateResponse.ts new file mode 100644 index 0000000..475dc0f --- /dev/null +++ b/src/client/models/CreatePayRateResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type CreatePayRateResponse = { + ok: boolean; + message: string; +}; + diff --git a/src/client/models/CreatePaymentRecordRequest.ts b/src/client/models/CreatePaymentRecordRequest.ts new file mode 100644 index 0000000..1924939 --- /dev/null +++ b/src/client/models/CreatePaymentRecordRequest.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { PaymentRecordCreateSchema } from './PaymentRecordCreateSchema'; +export type CreatePaymentRecordRequest = { + data: PaymentRecordCreateSchema; +}; + diff --git a/src/client/models/CreatePaymentRecordResponse.ts b/src/client/models/CreatePaymentRecordResponse.ts new file mode 100644 index 0000000..d46a924 --- /dev/null +++ b/src/client/models/CreatePaymentRecordResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type CreatePaymentRecordResponse = { + ok: boolean; + message: string; +}; + diff --git a/src/client/models/DeletePayRateRequest.ts b/src/client/models/DeletePayRateRequest.ts new file mode 100644 index 0000000..abbe8c6 --- /dev/null +++ b/src/client/models/DeletePayRateRequest.ts @@ -0,0 +1,8 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type DeletePayRateRequest = { + payRateId: number; +}; + diff --git a/src/client/models/DeletePayRateResponse.ts b/src/client/models/DeletePayRateResponse.ts new file mode 100644 index 0000000..39cafd5 --- /dev/null +++ b/src/client/models/DeletePayRateResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type DeletePayRateResponse = { + ok: boolean; + message: string; +}; + diff --git a/src/client/models/DeletePaymentRecordRequest.ts b/src/client/models/DeletePaymentRecordRequest.ts new file mode 100644 index 0000000..019db5a --- /dev/null +++ b/src/client/models/DeletePaymentRecordRequest.ts @@ -0,0 +1,8 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type DeletePaymentRecordRequest = { + paymentRecordId: number; +}; + diff --git a/src/client/models/DeletePaymentRecordResponse.ts b/src/client/models/DeletePaymentRecordResponse.ts new file mode 100644 index 0000000..5c0ec01 --- /dev/null +++ b/src/client/models/DeletePaymentRecordResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type DeletePaymentRecordResponse = { + ok: boolean; + message: string; +}; + diff --git a/src/client/models/GetAllPayRatesResponse.ts b/src/client/models/GetAllPayRatesResponse.ts new file mode 100644 index 0000000..0a6e589 --- /dev/null +++ b/src/client/models/GetAllPayRatesResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { PayRateSchema } from './PayRateSchema'; +export type GetAllPayRatesResponse = { + payRates: Array; +}; + diff --git a/src/client/models/GetAllPayrollSchemeResponse.ts b/src/client/models/GetAllPayrollSchemeResponse.ts new file mode 100644 index 0000000..2f6d34e --- /dev/null +++ b/src/client/models/GetAllPayrollSchemeResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { PayrollSchemeSchema } from './PayrollSchemeSchema'; +export type GetAllPayrollSchemeResponse = { + payrollSchemas: Array; +}; + diff --git a/src/client/models/GetPaymentRecordsResponse.ts b/src/client/models/GetPaymentRecordsResponse.ts new file mode 100644 index 0000000..88e969a --- /dev/null +++ b/src/client/models/GetPaymentRecordsResponse.ts @@ -0,0 +1,11 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { PaginationInfoSchema } from './PaginationInfoSchema'; +import type { PaymentRecordGetSchema } from './PaymentRecordGetSchema'; +export type GetPaymentRecordsResponse = { + paymentRecords: Array; + paginationInfo: PaginationInfoSchema; +}; + diff --git a/src/client/models/PayRateSchema.ts b/src/client/models/PayRateSchema.ts new file mode 100644 index 0000000..45b904a --- /dev/null +++ b/src/client/models/PayRateSchema.ts @@ -0,0 +1,14 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { PayrollSchemeSchema } from './PayrollSchemeSchema'; +export type PayRateSchema = { + name: string; + payrollScheme: PayrollSchemeSchema; + baseRate: number; + overtimeRate?: (number | null); + overtimeThreshold?: (number | null); + id: number; +}; + diff --git a/src/client/models/PayRateSchemaBase.ts b/src/client/models/PayRateSchemaBase.ts new file mode 100644 index 0000000..1d1b7ec --- /dev/null +++ b/src/client/models/PayRateSchemaBase.ts @@ -0,0 +1,13 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { PayrollSchemeSchema } from './PayrollSchemeSchema'; +export type PayRateSchemaBase = { + name: string; + payrollScheme: PayrollSchemeSchema; + baseRate: number; + overtimeRate?: (number | null); + overtimeThreshold?: (number | null); +}; + diff --git a/src/client/models/PaymentRecordCreateSchema.ts b/src/client/models/PaymentRecordCreateSchema.ts new file mode 100644 index 0000000..d79f5dc --- /dev/null +++ b/src/client/models/PaymentRecordCreateSchema.ts @@ -0,0 +1,12 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { UserSchema } from './UserSchema'; +export type PaymentRecordCreateSchema = { + startDate: string; + endDate: string; + workUnits: number; + user: UserSchema; +}; + diff --git a/src/client/models/PaymentRecordGetSchema.ts b/src/client/models/PaymentRecordGetSchema.ts new file mode 100644 index 0000000..f5ea489 --- /dev/null +++ b/src/client/models/PaymentRecordGetSchema.ts @@ -0,0 +1,18 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { PayrollSchemeSchema } from './PayrollSchemeSchema'; +import type { UserSchema } from './UserSchema'; +export type PaymentRecordGetSchema = { + startDate: string; + endDate: string; + workUnits: number; + user: UserSchema; + id: number; + createdByUser: UserSchema; + payrollScheme: PayrollSchemeSchema; + amount: number; + createdAt: string; +}; + diff --git a/src/client/models/PayrollSchemeSchema.ts b/src/client/models/PayrollSchemeSchema.ts new file mode 100644 index 0000000..4681f1e --- /dev/null +++ b/src/client/models/PayrollSchemeSchema.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type PayrollSchemeSchema = { + key: string; + name: string; +}; + diff --git a/src/client/models/UpdatePayRateRequest.ts b/src/client/models/UpdatePayRateRequest.ts new file mode 100644 index 0000000..b737859 --- /dev/null +++ b/src/client/models/UpdatePayRateRequest.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { PayRateSchema } from './PayRateSchema'; +export type UpdatePayRateRequest = { + data: PayRateSchema; +}; + diff --git a/src/client/models/UpdatePayRateResponse.ts b/src/client/models/UpdatePayRateResponse.ts new file mode 100644 index 0000000..2e01ef1 --- /dev/null +++ b/src/client/models/UpdatePayRateResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type UpdatePayRateResponse = { + ok: boolean; + message: string; +}; + diff --git a/src/client/models/UserSchema.ts b/src/client/models/UserSchema.ts index 5d621d6..2a3195c 100644 --- a/src/client/models/UserSchema.ts +++ b/src/client/models/UserSchema.ts @@ -2,6 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ +import type { PayRateSchema } from './PayRateSchema'; import type { PositionSchema } from './PositionSchema'; import type { RoleSchema } from './RoleSchema'; export type UserSchema = { @@ -15,6 +16,7 @@ export type UserSchema = { isBlocked: boolean; isDeleted: boolean; roleKey: string; + payRate?: (PayRateSchema | null); role: RoleSchema; position?: (PositionSchema | null); }; diff --git a/src/client/models/UserUpdate.ts b/src/client/models/UserUpdate.ts index 2424d63..350f6bd 100644 --- a/src/client/models/UserUpdate.ts +++ b/src/client/models/UserUpdate.ts @@ -2,6 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ +import type { PayRateSchema } from './PayRateSchema'; export type UserUpdate = { id: number; telegramId: number; @@ -13,6 +14,7 @@ export type UserUpdate = { isBlocked: boolean; isDeleted: boolean; roleKey: string; + payRate?: (PayRateSchema | null); positionKey?: (string | null); }; diff --git a/src/client/services/PayrollService.ts b/src/client/services/PayrollService.ts new file mode 100644 index 0000000..f747d92 --- /dev/null +++ b/src/client/services/PayrollService.ts @@ -0,0 +1,168 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { CreatePaymentRecordRequest } from '../models/CreatePaymentRecordRequest'; +import type { CreatePaymentRecordResponse } from '../models/CreatePaymentRecordResponse'; +import type { CreatePayRateRequest } from '../models/CreatePayRateRequest'; +import type { CreatePayRateResponse } from '../models/CreatePayRateResponse'; +import type { DeletePaymentRecordRequest } from '../models/DeletePaymentRecordRequest'; +import type { DeletePaymentRecordResponse } from '../models/DeletePaymentRecordResponse'; +import type { DeletePayRateRequest } from '../models/DeletePayRateRequest'; +import type { DeletePayRateResponse } from '../models/DeletePayRateResponse'; +import type { GetAllPayRatesResponse } from '../models/GetAllPayRatesResponse'; +import type { GetAllPayrollSchemeResponse } from '../models/GetAllPayrollSchemeResponse'; +import type { GetPaymentRecordsResponse } from '../models/GetPaymentRecordsResponse'; +import type { UpdatePayRateRequest } from '../models/UpdatePayRateRequest'; +import type { UpdatePayRateResponse } from '../models/UpdatePayRateResponse'; +import type { CancelablePromise } from '../core/CancelablePromise'; +import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; +export class PayrollService { + /** + * Get All Schemas + * @returns GetAllPayrollSchemeResponse Successful Response + * @throws ApiError + */ + public static getAllPayrollSchemas(): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/payroll/scheme/get-all', + }); + } + /** + * Get All Pay Rates + * @returns GetAllPayRatesResponse Successful Response + * @throws ApiError + */ + public static getAllPayRates(): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/payroll/pay-rate/get-all', + }); + } + /** + * Create Pay Rate + * @returns CreatePayRateResponse Successful Response + * @throws ApiError + */ + public static createPayRate({ + requestBody, + }: { + requestBody: CreatePayRateRequest, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/payroll/pay-rate/create', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + /** + * Update Pay Rate + * @returns UpdatePayRateResponse Successful Response + * @throws ApiError + */ + public static updatePayRate({ + requestBody, + }: { + requestBody: UpdatePayRateRequest, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/payroll/pay-rate/update', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + /** + * Update Pay Rate + * @returns DeletePayRateResponse Successful Response + * @throws ApiError + */ + public static deletePayRate({ + requestBody, + }: { + requestBody: DeletePayRateRequest, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/payroll/pay-rate/delete', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + /** + * Get Payment Records + * @returns GetPaymentRecordsResponse Successful Response + * @throws ApiError + */ + public static getPaymentRecords({ + page, + itemsPerPage, + }: { + page?: (number | null), + itemsPerPage?: (number | null), + }): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/payroll/payment-record/get', + query: { + 'page': page, + 'items_per_page': itemsPerPage, + }, + errors: { + 422: `Validation Error`, + }, + }); + } + /** + * Create Payment Records + * @returns CreatePaymentRecordResponse Successful Response + * @throws ApiError + */ + public static createPaymentRecord({ + requestBody, + }: { + requestBody: CreatePaymentRecordRequest, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/payroll/payment-record/create', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + /** + * Delete Payment Record + * @returns DeletePaymentRecordResponse Successful Response + * @throws ApiError + */ + public static deletePaymentRecord({ + requestBody, + }: { + requestBody: DeletePaymentRecordRequest, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/payroll/payment-record/delete', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } +} diff --git a/src/components/Dnd/DealSummaryCard/DealSummaryCard.module.css b/src/components/Dnd/DealSummaryCard/DealSummaryCard.module.css index c865f31..2405864 100644 --- a/src/components/Dnd/DealSummaryCard/DealSummaryCard.module.css +++ b/src/components/Dnd/DealSummaryCard/DealSummaryCard.module.css @@ -14,7 +14,7 @@ flex-wrap: wrap; @mixin light { - background-color: var(--mantine-color-gray-0); + background-color: var(--mantine-color-gray-1); } @mixin dark { background-color: var(--mantine-color-dark-5); diff --git a/src/components/Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx b/src/components/Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx index 1163f71..d9ace15 100644 --- a/src/components/Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx +++ b/src/components/Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx @@ -12,7 +12,7 @@ const BaseMarketplaceSelect: FC = (props) => { <> - + baseMarketplace.option.value === el.key)?.iconUrl || ""}/> diff --git a/src/components/Selects/PayRateSelect/PayRateSelect.tsx b/src/components/Selects/PayRateSelect/PayRateSelect.tsx new file mode 100644 index 0000000..1a1cd1c --- /dev/null +++ b/src/components/Selects/PayRateSelect/PayRateSelect.tsx @@ -0,0 +1,19 @@ +import ObjectSelect, {ObjectSelectProps} from "../../ObjectSelect/ObjectSelect.tsx"; +import {PayRateSchema} from "../../../client"; +import {FC} from "react"; +import usePayRatesList from "../../../pages/AdminPage/hooks/usePayRatesList.tsx"; + +type Props = Omit, 'data' | 'getValueFn' | 'getLabelFn'> + +const PayRateSelect: FC = (props) => { + const {objects: payRates} = usePayRatesList(); + return ( + baseMarketplace.id.toLocaleString()} + getLabelFn={(baseMarketplace) => baseMarketplace.name} + data={payRates} + {...props} + /> + ) +} +export default PayRateSelect; \ No newline at end of file diff --git a/src/components/Selects/PayrollSchemeSelect/PayrollSchemeSelect.tsx b/src/components/Selects/PayrollSchemeSelect/PayrollSchemeSelect.tsx new file mode 100644 index 0000000..3b8c893 --- /dev/null +++ b/src/components/Selects/PayrollSchemeSelect/PayrollSchemeSelect.tsx @@ -0,0 +1,19 @@ +import ObjectSelect, {ObjectSelectProps} from "../../ObjectSelect/ObjectSelect.tsx"; +import {PayrollSchemeSchema} from "../../../client"; +import {FC} from "react"; +import usePayrollSchemasList from "../../../hooks/usePayrollSchemasList.tsx"; + +type Props = Omit, 'data' | 'getValueFn' | 'getLabelFn'> + +const PayrollSchemeSelect: FC = (props) => { + const {objects: payrollSchemeSchemas} = usePayrollSchemasList(); + return ( + baseMarketplace.key} + getLabelFn={(baseMarketplace) => baseMarketplace.name} + data={payrollSchemeSchemas} + {...props} + /> + ) +} +export default PayrollSchemeSelect \ No newline at end of file diff --git a/src/hooks/objectList.tsx b/src/hooks/objectList.tsx index a5071ea..e43edcd 100644 --- a/src/hooks/objectList.tsx +++ b/src/hooks/objectList.tsx @@ -1,5 +1,6 @@ import {QueryObserverResult, RefetchOptions, useQuery} from "@tanstack/react-query"; -import {CancelablePromise} from "../client"; +import {CancelablePromise, PaginationInfoSchema} from "../client"; +import {Pagination} from "../types/Pagination.ts"; type Props = { queryFn: () => CancelablePromise, @@ -18,4 +19,33 @@ const ObjectList = (props: Props): Response => { const objects = isPending || error || !data ? ([] as K[]) : props.getObjectsFn(data); return {objects, refetch} } + +interface ObjectWithPagination { + paginationInfo: PaginationInfoSchema +} + +type PropsWithPagination = { + queryFn: () => CancelablePromise, + getObjectsFn: (response: T) => K[], + queryKey: string, + pagination: Pagination +} +type ResponseWithPagination = { + objects: K[], + pagination?: PaginationInfoSchema, + refetch: (options?: RefetchOptions) => Promise> +} +export const ObjectListWithPagination = (props: PropsWithPagination): ResponseWithPagination => { + const {isPending, error, data, refetch} = useQuery({ + queryKey: [props.queryKey, props, props.pagination.itemsPerPage, props.pagination.page], + queryFn: props.queryFn, + }); + const objects = isPending || error || !data ? ([] as K[]) : props.getObjectsFn(data); + return { + objects, + pagination: data?.paginationInfo, + refetch + } +} + export default ObjectList \ No newline at end of file diff --git a/src/hooks/usePaymentRecordsList.tsx b/src/hooks/usePaymentRecordsList.tsx new file mode 100644 index 0000000..680b3fa --- /dev/null +++ b/src/hooks/usePaymentRecordsList.tsx @@ -0,0 +1,11 @@ +import {ObjectListWithPagination} from "./objectList.tsx"; +import {PayrollService} from "../client"; +import {Pagination} from "../types/Pagination.ts"; + + +export const usePaymentRecordsList = (pagination: Pagination) => ObjectListWithPagination({ + queryFn: () => PayrollService.getPaymentRecords(pagination), + queryKey: "getPaymentRecords", + getObjectsFn: (response) => response.paymentRecords, + pagination +}) \ No newline at end of file diff --git a/src/hooks/usePayrollSchemasList.tsx b/src/hooks/usePayrollSchemasList.tsx new file mode 100644 index 0000000..e8376d5 --- /dev/null +++ b/src/hooks/usePayrollSchemasList.tsx @@ -0,0 +1,9 @@ +import ObjectList from "./objectList.tsx"; +import {PayrollService} from "../client"; + +const usePayrollSchemasList = () => ObjectList({ + queryFn: PayrollService.getAllPayrollSchemas, + getObjectsFn: (response) => response.payrollSchemas, + queryKey: "getAllPayrollSchemas" +}) +export default usePayrollSchemasList; \ No newline at end of file diff --git a/src/modals/modals.ts b/src/modals/modals.ts index d78fde1..f194b1f 100644 --- a/src/modals/modals.ts +++ b/src/modals/modals.ts @@ -14,6 +14,8 @@ import UserFormModal from "../pages/AdminPage/modals/UserFormModal/UserFormModal import EmployeeSelectModal from "./EmployeeSelectModal/EmployeeSelectModal.tsx"; import EmployeeTableModal from "./EmployeeTableModal/EmployeeTableModal.tsx"; import PositionFormModal from "./PositionFormModal/PositionFormModal.tsx"; +import PayRateFormModal from "../pages/AdminPage/modals/PayRateFormModal/PayRateFormModal.tsx"; +import CreatePaymentRecordModal from "../pages/AdminPage/modals/CreatePaymentRecordModal/CreatePaymentRecordModal.tsx"; export const modals = { enterDeadline: EnterDeadlineModal, @@ -30,5 +32,7 @@ export const modals = { userFormModal: UserFormModal, employeeSelect: EmployeeSelectModal, employeeTable: EmployeeTableModal, - positionForm: PositionFormModal + positionForm: PositionFormModal, + payRateForm: PayRateFormModal, + createPaymentRecord: CreatePaymentRecordModal } diff --git a/src/pages/AdminPage/AdminPage.tsx b/src/pages/AdminPage/AdminPage.tsx index a66d335..aa9fcac 100644 --- a/src/pages/AdminPage/AdminPage.tsx +++ b/src/pages/AdminPage/AdminPage.tsx @@ -1,10 +1,11 @@ import styles from './AdminPage.module.css'; import {Tabs} from "@mantine/core"; import PageBlock from "../../components/PageBlock/PageBlock.tsx"; -import {IconBriefcase, IconUser} from "@tabler/icons-react"; +import {IconBriefcase, IconCurrencyDollar, IconUser} from "@tabler/icons-react"; import RolesAndPositionsTab from "./tabs/RolesAndPositions/RolesAndPositionsTab.tsx"; import UsersTab from "./tabs/Users/UsersTab.tsx"; import {motion} from "framer-motion"; +import FinancesTab from "./tabs/Finances/FinancesTab.tsx"; const AdminPage = () => { @@ -16,13 +17,15 @@ const AdminPage = () => { }> Пользователи + }> + Финансы + }> Должности - {/*}>*/} - {/* Сотрудники*/} - {/**/} + + { > - @@ -43,6 +45,15 @@ const AdminPage = () => { + + + + + diff --git a/src/pages/AdminPage/components/PayRateTable/PayRateTable.tsx b/src/pages/AdminPage/components/PayRateTable/PayRateTable.tsx new file mode 100644 index 0000000..91a6665 --- /dev/null +++ b/src/pages/AdminPage/components/PayRateTable/PayRateTable.tsx @@ -0,0 +1,94 @@ +import {CRUDTableProps} from "../../../../types/CRUDTable.tsx"; +import {PayRateSchema} from "../../../../client"; +import {FC} from "react"; +import {BaseTable} from "../../../../components/BaseTable/BaseTable.tsx"; +import {usePayRatesTableColumns} from "./columns.tsx"; +import {ActionIcon, Button, Flex, rem, Text, Tooltip} from "@mantine/core"; +import {modals} from "@mantine/modals"; +import {IconEdit, IconTrash} from "@tabler/icons-react"; +import {MRT_TableOptions} from "mantine-react-table"; + +type Props = CRUDTableProps; + +const PayRateTable: FC = ({items, onCreate, onChange, onDelete}) => { + const columns = usePayRatesTableColumns(); + + const onCreateClick = () => { + if (!onCreate) return; + modals.openContextModal({ + modal: "payRateForm", + withCloseButton: false, + innerProps: { + onCreate: onCreate + } + }) + } + const onEditClick = (payRate: PayRateSchema) => { + if (!onChange) return; + modals.openContextModal({ + modal: "payRateForm", + withCloseButton: false, + innerProps: { + onChange: (event) => onChange({...event, id: payRate.id}), + element: payRate + } + }) + } + const onDeleteClick = (payRate: PayRateSchema) => { + if (!onDelete) return; + modals.openConfirmModal({ + title: 'Удаление тарифа', + children: ( + + Вы уверены что хотите удалить тариф {payRate.name} + + ), + labels: {confirm: 'Да', cancel: "Нет"}, + confirmProps: {color: 'red'}, + onConfirm: () => onDelete(payRate) + }); + } + + return ( + + + + + + ), + enableRowActions: true, + renderRowActions: ({row}) => ( + + + onEditClick(row.original)} + variant={"default"}> + + + + + onDeleteClick(row.original)} variant={"default"}> + + + + + ) + } as MRT_TableOptions} + /> + ) +} + +export default PayRateTable; \ No newline at end of file diff --git a/src/pages/AdminPage/components/PayRateTable/columns.tsx b/src/pages/AdminPage/components/PayRateTable/columns.tsx new file mode 100644 index 0000000..6cd6c39 --- /dev/null +++ b/src/pages/AdminPage/components/PayRateTable/columns.tsx @@ -0,0 +1,32 @@ +import {useMemo} from "react"; +import {MRT_ColumnDef} from "mantine-react-table"; +import {PayRateSchema} from "../../../../client"; + +export const usePayRatesTableColumns = () => { + return useMemo[]>(() => [ + { + accessorKey: "name", + header: "Название тарифа" + }, + { + accessorKey: "payrollScheme.name", + header: "Система оплаты" + }, + { + accessorKey: "baseRate", + header: "Базовая ставка", + Cell: ({row}) => `${row.original.baseRate.toLocaleString("ru")}₽` + + }, + { + accessorKey: "overtimeThreshold", + header: "Порог сверхурочных" + }, + { + accessorKey: "overtimeRate", + header: "Сверхурочная ставка", + Cell: ({row}) => row.original.overtimeRate && `${row.original.overtimeRate.toLocaleString("ru")}₽` + + } + ], []); +} \ No newline at end of file diff --git a/src/pages/AdminPage/components/PaymentRecordsTable/PaymentRecordsTable.tsx b/src/pages/AdminPage/components/PaymentRecordsTable/PaymentRecordsTable.tsx new file mode 100644 index 0000000..7109cb2 --- /dev/null +++ b/src/pages/AdminPage/components/PaymentRecordsTable/PaymentRecordsTable.tsx @@ -0,0 +1,123 @@ +import {FC, useEffect, useState} from "react"; +import {ActionIcon, Button, Flex, Pagination, rem, Text, Tooltip} from "@mantine/core"; +import {usePaymentRecordsList} from "../../../../hooks/usePaymentRecordsList.tsx"; +import {BaseTable} from "../../../../components/BaseTable/BaseTable.tsx"; +import {usePaymentRecordsTableColumns} from "./columns.tsx"; +import {modals} from "@mantine/modals"; +import {PaymentRecordCreateSchema, PaymentRecordGetSchema, PayrollService} from "../../../../client"; +import {notifications} from "../../../../shared/lib/notifications.ts"; +import {IconTrash} from "@tabler/icons-react"; +import {MRT_TableOptions} from "mantine-react-table"; +import {formatDate} from "../../../../types/utils.ts"; + +const PaymentRecordsTable: FC = () => { + const [totalPages, setTotalPages] = useState(10); + const [page, setPage] = useState(1); + const { + pagination: paginationInfo, + objects: paymentRecords, + refetch + } = usePaymentRecordsList({page: page, itemsPerPage: 10}); + useEffect(() => { + if (!paginationInfo) return; + setTotalPages(paginationInfo.totalPages); + }, [paginationInfo]); + + const onCreate = (request: PaymentRecordCreateSchema) => { + PayrollService.createPaymentRecord({ + requestBody: { + data: request + } + }).then(async ({ok, message}) => { + notifications.guess(ok, {message}); + if (!ok) return; + await refetch(); + }) + } + const onCreateClick = () => { + modals.openContextModal({ + modal: "createPaymentRecord", + title: "Создание начисления", + innerProps: { + onCreate: onCreate + }, + }) + } + const onDelete = (record: PaymentRecordGetSchema) => { + PayrollService.deletePaymentRecord({ + requestBody: { + paymentRecordId: record.id + } + }).then(async ({ok, message}) => { + notifications.guess(ok, {message}); + if (!ok) return; + await refetch(); + }) + } + const onDeleteClick = (record: PaymentRecordGetSchema) => { + modals.openConfirmModal({ + title: 'Удаление начисления', + children: ( + + Вы уверены что хотите удалить начисление + пользователю {record.user.firstName} {record.user.secondName} от {formatDate(record.createdAt)} + + ), + labels: {confirm: 'Да', cancel: "Нет"}, + confirmProps: {color: 'red'}, + onConfirm: () => onDelete(record) + }) + } + const columns = usePaymentRecordsTableColumns(); + return ( + + + + + + ), + enableRowActions: true, + renderRowActions: ({row}) => ( + + + + onDeleteClick(row.original)} variant={"default"}> + + + + + ) + } as MRT_TableOptions} + /> + {totalPages > 1 && + + setPage(event)} + value={page} + total={totalPages} + /> + } + + + ) +} +export default PaymentRecordsTable; \ No newline at end of file diff --git a/src/pages/AdminPage/components/PaymentRecordsTable/columns.tsx b/src/pages/AdminPage/components/PaymentRecordsTable/columns.tsx new file mode 100644 index 0000000..ebc1756 --- /dev/null +++ b/src/pages/AdminPage/components/PaymentRecordsTable/columns.tsx @@ -0,0 +1,58 @@ +import {useMemo} from "react"; +import {MRT_ColumnDef} from "mantine-react-table"; +import {PaymentRecordGetSchema} from "../../../../client"; +import {PaySchemeType} from "../../../../shared/enums/PaySchemeType.ts"; +import {getPluralForm} from "../../../../shared/lib/utils.ts"; +import {formatDate} from "../../../../types/utils.ts"; +import {isEqual} from "lodash"; + +export const usePaymentRecordsTableColumns = () => { + const getWorkUnitsText = (paymentRecord: PaymentRecordGetSchema) => { + const payrollScheme = paymentRecord.payrollScheme; + if (payrollScheme.key === PaySchemeType.HOURLY) { + return getPluralForm(paymentRecord.workUnits, "час", "часа", "часов") + } else if ( + payrollScheme.key === PaySchemeType.DAILY + ) { + return getPluralForm(paymentRecord.workUnits, "день", "дня", "дней") + } else if ( + payrollScheme.key === PaySchemeType.MONTHLY + ) { + return getPluralForm(paymentRecord.workUnits, "месяц", "месяца", "месяцев"); + } + return ""; + } + const getDateRangesText = (paymentRecord: PaymentRecordGetSchema) => { + if (paymentRecord.endDate && !isEqual(paymentRecord.startDate, paymentRecord.endDate)) { + return `${formatDate(paymentRecord.startDate)} - ${formatDate(paymentRecord.endDate)}` + } + return `${formatDate(paymentRecord.startDate)}`; + } + + return useMemo[]>(() => [ + { + header: "Дата начисления", + Cell: ({row}) => new Date(row.original.createdAt).toLocaleString('ru-RU') + }, + { + header: "Получил начисление", + Cell: ({row}) => `${row.original.user.firstName} ${row.original.user.secondName}` + }, + { + header: "Создал начисление", + Cell: ({row}) => `${row.original.createdByUser.firstName} ${row.original.createdByUser.secondName}` + }, + { + header: "Количество", + Cell: ({row}) => `${row.original.workUnits} ${getWorkUnitsText(row.original)}` + }, + { + header: "Сумма начисления", + Cell: ({row}) => row.original.amount.toLocaleString("ru-RU") + }, + { + header: "Временной промежуток", + Cell: ({row}) => getDateRangesText(row.original) + } + ], []) +} diff --git a/src/pages/AdminPage/components/UsersTable/UsersTable.tsx b/src/pages/AdminPage/components/UsersTable/UsersTable.tsx index 1c30c75..0aa0faf 100644 --- a/src/pages/AdminPage/components/UsersTable/UsersTable.tsx +++ b/src/pages/AdminPage/components/UsersTable/UsersTable.tsx @@ -52,13 +52,7 @@ const UsersTable: FC = ({items, onChange, onDelete}) => { enableRowActions: true, renderRowActions: ({row}) => ( - { - onDeleteClick(row.original); - }} label="Удалить"> - - - - + { onEditClick(row.original) @@ -69,6 +63,13 @@ const UsersTable: FC = ({items, onChange, onDelete}) => { + { + onDeleteClick(row.original); + }} label="Удалить"> + + + + ), } as MRT_TableOptions} diff --git a/src/pages/AdminPage/components/UsersTable/columns.tsx b/src/pages/AdminPage/components/UsersTable/columns.tsx index cd3a6ff..866c8c3 100644 --- a/src/pages/AdminPage/components/UsersTable/columns.tsx +++ b/src/pages/AdminPage/components/UsersTable/columns.tsx @@ -5,17 +5,10 @@ import {IconCheck, IconX} from "@tabler/icons-react"; export const useUsersTableColumns = () => { return useMemo[]>(() => [ + { - accessorKey: "firstName", - header: "Имя" - }, - { - accessorKey: "secondName", - header: "Фамилия" - }, - { - accessorKey: "telegramId", - header: "ID Телеграм" + header: "ФИО", + Cell: ({row}) => `${row.original.firstName} ${row.original.secondName}` }, { accessorKey: "phoneNumber", @@ -25,6 +18,14 @@ export const useUsersTableColumns = () => { accessorKey: "role.name", header: "Роль" }, + { + accessorKey: "position.name", + header: "Должность" + }, + { + accessorKey: "payRate.name", + header: "Тариф" + }, { accessorKey: "comment", header: "Дополнительная информация" diff --git a/src/pages/AdminPage/hooks/usePayRatesList.tsx b/src/pages/AdminPage/hooks/usePayRatesList.tsx new file mode 100644 index 0000000..11ad3b8 --- /dev/null +++ b/src/pages/AdminPage/hooks/usePayRatesList.tsx @@ -0,0 +1,9 @@ +import {PayrollService} from "../../../client"; +import ObjectList from "../../../hooks/objectList.tsx"; + +const usePayRatesList = () => ObjectList({ + queryFn: PayrollService.getAllPayRates, + getObjectsFn: response => response.payRates, + queryKey: "getAllPayRates" +}) +export default usePayRatesList; \ No newline at end of file diff --git a/src/pages/AdminPage/modals/CreatePaymentRecordModal/CreatePaymentRecordModal.tsx b/src/pages/AdminPage/modals/CreatePaymentRecordModal/CreatePaymentRecordModal.tsx new file mode 100644 index 0000000..aa590a4 --- /dev/null +++ b/src/pages/AdminPage/modals/CreatePaymentRecordModal/CreatePaymentRecordModal.tsx @@ -0,0 +1,130 @@ +import BaseFormModal, {CreateProps} from "../../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx"; +import {PaymentRecordCreateSchema} from "../../../../client"; +import {ContextModalProps} from "@mantine/modals"; +import {useForm} from "@mantine/form"; +import {Flex, NumberInput, rem} from "@mantine/core"; +import {DatePickerInput, MonthPickerInput} from "@mantine/dates"; +import {useEffect, useState} from "react"; +import {dateWithoutTimezone} from "../../../../shared/lib/utils.ts"; +import UserSelect from "../../../../components/Selects/UserSelect/UserSelect.tsx"; +import {PaySchemeType} from "../../../../shared/enums/PaySchemeType.ts"; +import {motion} from "framer-motion"; + +type Props = CreateProps; +const CreatePaymentRecordModal = ({ + context, + id, + innerProps + }: ContextModalProps) => { + const form = useForm>({ + validate: { + user: (user) => !user && "Необходимо выбрать сотрудника", + startDate: (startDate) => !startDate && "Необходимо указать временной промежуток", + workUnits: (workUnits) => !workUnits && "Укажите количество" + } + }) + const [dateRange, setDateRange] = useState<[Date | null, Date | null]>([null, null]); + useEffect(() => { + + const setDates = (start: string | undefined, end: string | undefined) => { + form.setFieldValue("startDate", start); + form.setFieldValue("endDate", end); + }; + + if (dateRange.every(dr => dr == null)) { + setDates(undefined, undefined); + return + } else { + const notNullValues = dateRange.filter((dr): dr is Date => dr !== null).map(dateWithoutTimezone); + const startDate = notNullValues[0]; + const endDate = notNullValues[1] || startDate; + setDates(startDate, endDate); + } + }, [dateRange]); + + const getDateRangeInput = () => { + if (!form.values.user) return <> + const payRate = form.values.user.payRate; + if (!payRate) return <>; + if (payRate.payrollScheme.key == PaySchemeType.MONTHLY) + return ( + + ) + return (); + } + const getAmountLabel = () => { + const user = form.values.user; + if (!user) return ""; + const payRate = user?.payRate; + if (!payRate) return ""; + if (payRate.payrollScheme.key == PaySchemeType.HOURLY) return "Количество часов"; + if (payRate.payrollScheme.key == PaySchemeType.MONTHLY) return "Количество месяцев"; + if (payRate.payrollScheme.key == PaySchemeType.DAILY) return "Количество дней"; + return ""; + } + const getAmountPlaceholder = () => { + return "Укажите " + getAmountLabel().toLowerCase(); + } + return ( context.closeContextModal(id)} + {...innerProps} + > + + <> + + !!user.payRate} + {...form.getInputProps("user")} + /> + + {form.values.user && + <> + + + + {getDateRangeInput()} + + + + + } + + + + ) +} +export default CreatePaymentRecordModal; \ No newline at end of file diff --git a/src/pages/AdminPage/modals/PayRateFormModal/PayRateFormModal.tsx b/src/pages/AdminPage/modals/PayRateFormModal/PayRateFormModal.tsx new file mode 100644 index 0000000..48309b1 --- /dev/null +++ b/src/pages/AdminPage/modals/PayRateFormModal/PayRateFormModal.tsx @@ -0,0 +1,98 @@ +import BaseFormModal, {CreateEditFormProps} from "../../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx"; +import {PayRateSchemaBase} from "../../../../client"; +import {ContextModalProps} from "@mantine/modals"; +import {useForm} from "@mantine/form"; +import {Fieldset, Flex, NumberInput, rem, TextInput} from "@mantine/core"; +import PayrollSchemeSelect from "../../../../components/Selects/PayrollSchemeSelect/PayrollSchemeSelect.tsx"; +import {PaySchemeType} from "../../../../shared/enums/PaySchemeType.ts"; + +type Props = CreateEditFormProps + +const PayRateFormModal = ({ + context, + id, + innerProps + }: ContextModalProps) => { + const isEditing = 'element' in innerProps; + const initialValue: Partial = isEditing ? innerProps.element : {}; + + const form = useForm>({ + initialValues: initialValue, + validate: { + name: (name) => !name && "Необходимо указать название тарифа", + payrollScheme: (scheme) => !scheme && "Необходимо выбрать систему оплаты", + baseRate: (baseRate) => !baseRate && "Небходимо указать базовую ставку" + } + }); + return ( + context.closeContextModal(id)} + {...innerProps} + > + + <> +
+ + + + + + +
+
+ + + + {form.values.payrollScheme?.key === PaySchemeType.HOURLY && + <> + + + + + } + + +
+ +
+
+ ) +} + +export default PayRateFormModal; \ No newline at end of file diff --git a/src/pages/AdminPage/modals/UserFormModal/UserFormModal.tsx b/src/pages/AdminPage/modals/UserFormModal/UserFormModal.tsx index bf6d51b..72444d6 100644 --- a/src/pages/AdminPage/modals/UserFormModal/UserFormModal.tsx +++ b/src/pages/AdminPage/modals/UserFormModal/UserFormModal.tsx @@ -9,6 +9,7 @@ import {UserRoleEnum} from "../../../../shared/enums/UserRole.ts"; import {capitalize} from "lodash"; import {IMaskInput} from "react-imask"; import phone from "phone"; +import PayRateSelect from "../../../../components/Selects/PayRateSelect/PayRateSelect.tsx"; type Props = EditProps; const UserFormModal = ({context, id, innerProps}: ContextModalProps) => { @@ -65,21 +66,27 @@ const UserFormModal = ({context, id, innerProps}: ContextModalProps) => {
- {form.values.role.key === UserRoleEnum.EMPLOYEE && - + <> + + + + } -
diff --git a/src/pages/AdminPage/tabs/Finances/FinancesTab.tsx b/src/pages/AdminPage/tabs/Finances/FinancesTab.tsx new file mode 100644 index 0000000..f7086b1 --- /dev/null +++ b/src/pages/AdminPage/tabs/Finances/FinancesTab.tsx @@ -0,0 +1,97 @@ +import {Tabs} from "@mantine/core"; +import {IconBusinessplan, IconHistory} from "@tabler/icons-react"; +import {motion} from "framer-motion"; +import PayRateTable from "../../components/PayRateTable/PayRateTable.tsx"; +import usePayRatesList from "../../hooks/usePayRatesList.tsx"; +import {CRUDTableProps} from "../../../../types/CRUDTable.tsx"; +import {PayRateSchema, PayRateSchemaBase, PayrollService} from "../../../../client"; +import {notifications} from "../../../../shared/lib/notifications.ts"; +import PaymentRecordsTable from "../../components/PaymentRecordsTable/PaymentRecordsTable.tsx"; + +const payRateTableState = (): CRUDTableProps => { + const {objects: items, refetch} = usePayRatesList(); + const onCreate = (item: PayRateSchemaBase) => { + PayrollService.createPayRate({ + requestBody: { + data: item + } + }).then(async ({ok, message}) => { + notifications.guess(ok, {message}); + if (!ok) return; + await refetch(); + }); + } + const onChange = (item: PayRateSchema) => { + PayrollService.updatePayRate({ + requestBody: { + data: item + } + }).then(async ({ok, message}) => { + notifications.guess(ok, {message}); + if (!ok) return; + await refetch(); + }); + } + const onDelete = (item: PayRateSchema) => { + PayrollService.deletePayRate({ + requestBody: { + payRateId: item.id + } + }).then(async ({ok, message}) => { + notifications.guess(ok, {message}); + if (!ok) return; + await refetch(); + }); + } + return {items, onCreate, onChange, onDelete}; +} + +const FinancesTab = () => { + const payRateState = payRateTableState(); + return ( + <> + + + }> + Начисления + + }> + Тарифы + + + + + + + + + + + + + + + + + ) +} + +export default FinancesTab \ No newline at end of file diff --git a/src/routes/test.lazy.tsx b/src/routes/test.lazy.tsx index 6ac3809..f62e763 100644 --- a/src/routes/test.lazy.tsx +++ b/src/routes/test.lazy.tsx @@ -1,7 +1,4 @@ import {createLazyFileRoute} from "@tanstack/react-router"; -import {Button} from '@mantine/core'; -import {modals} from "@mantine/modals"; -import BaseMarketplaceSelect from "../components/Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx"; export const Route = createLazyFileRoute('/test')({ component: TestPage @@ -9,12 +6,9 @@ export const Route = createLazyFileRoute('/test')({ function TestPage() { + return ( <> - { - }} - /> ); } \ No newline at end of file diff --git a/src/shared/enums/PaySchemeType.ts b/src/shared/enums/PaySchemeType.ts new file mode 100644 index 0000000..eaa5642 --- /dev/null +++ b/src/shared/enums/PaySchemeType.ts @@ -0,0 +1,5 @@ +export enum PaySchemeType { + HOURLY = 'hourly', + DAILY = 'daily', + MONTHLY = 'monthly' +} \ No newline at end of file diff --git a/src/types/Pagination.ts b/src/types/Pagination.ts new file mode 100644 index 0000000..8bb1269 --- /dev/null +++ b/src/types/Pagination.ts @@ -0,0 +1,4 @@ +export type Pagination = { + itemsPerPage: number, + page: number +} \ No newline at end of file diff --git a/src/types/utils.ts b/src/types/utils.ts index db1522c..9866dc8 100644 --- a/src/types/utils.ts +++ b/src/types/utils.ts @@ -7,4 +7,7 @@ export type BaseFormInputProps = { onChange: (value: T) => void; value: T; error?: string | null; +} +export const formatDate = (date: string) => { + return new Date(date).toLocaleDateString("ru-RU"); } \ No newline at end of file