From 3129ffc5d3cdf88480940329c55f310751629507 Mon Sep 17 00:00:00 2001 From: Dragos-Paul Strat Date: Wed, 25 Sep 2024 13:50:33 +0300 Subject: [PATCH 1/5] feat: [contracts] add delete contract on web --- .../documents/document-contract.controller.ts | 11 +++ .../exceptions/contract.exceptions.ts | 11 +++ .../delete-document-contract.usecase.ts | 80 +++++++++++++++++++ backend/src/usecases/use-case.module.ts | 2 + .../src/assets/locales/ro/translation.json | 6 +- .../common/errors/entities/contract.errors.ts | 6 ++ .../src/components/DocumentContractsTable.tsx | 58 ++++++++++++-- .../document-contracts.api.ts | 4 + 8 files changed, 171 insertions(+), 7 deletions(-) create mode 100644 backend/src/usecases/documents/new_contracts/delete-document-contract.usecase.ts diff --git a/backend/src/api/documents/document-contract.controller.ts b/backend/src/api/documents/document-contract.controller.ts index 0fed8ce23..9eef53045 100644 --- a/backend/src/api/documents/document-contract.controller.ts +++ b/backend/src/api/documents/document-contract.controller.ts @@ -1,6 +1,7 @@ import { Body, Controller, + Delete, Get, Param, Patch, @@ -32,6 +33,7 @@ import { GetOneDocumentContractForNgoUsecase } from 'src/usecases/documents/new_ import { DocumentContractStatisticsPresenter } from './presenters/document-contract-statistics.presenter'; import { GetDocumentContractStatisticsUsecase } from 'src/usecases/documents/new_contracts/get-document-contract-statistics.usecase'; import { SignDocumentContractByNgoDto } from './dto/sign-document-contract-by-ngo.dto'; +import { DeleteDocumentContractUsecase } from 'src/usecases/documents/new_contracts/delete-document-contract.usecase'; @ApiBearerAuth() @UseGuards(WebJwtAuthGuard) @@ -45,6 +47,7 @@ export class DocumentContractController { private readonly signDocumentContractByNGO: SignDocumentContractByNgoUsecase, private readonly getOneDocumentContractForNgoUsecase: GetOneDocumentContractForNgoUsecase, private readonly getDocumentContractStatisticsUsecase: GetDocumentContractStatisticsUsecase, + private readonly deleteDocumentContractUsecase: DeleteDocumentContractUsecase, ) {} @Post() @@ -146,4 +149,12 @@ export class DocumentContractController { admin, }); } + + @Delete(':id') + async deleteDocumentContract( + @Param('id', UuidValidationPipe) id: string, + @ExtractUser() admin: IAdminUserModel, + ): Promise { + await this.deleteDocumentContractUsecase.execute(id, admin); + } } diff --git a/backend/src/modules/documents/exceptions/contract.exceptions.ts b/backend/src/modules/documents/exceptions/contract.exceptions.ts index a341ae617..cdcfdeb35 100644 --- a/backend/src/modules/documents/exceptions/contract.exceptions.ts +++ b/backend/src/modules/documents/exceptions/contract.exceptions.ts @@ -14,6 +14,8 @@ export enum ContractExceptionCodes { CONTRACT_011 = 'CONTRACT_011', CONTRACT_012 = 'CONTRACT_012', CONTRACT_013 = 'CONTRACT_013', + CONTRACT_014 = 'CONTRACT_014', + CONTRACT_015 = 'CONTRACT_015', } type ContractExceptionCodeType = keyof typeof ContractExceptionCodes; @@ -75,4 +77,13 @@ export const ContractExceptionMessages: Record< code_error: ContractExceptionCodes.CONTRACT_013, message: '[Create Contract] Missing volunteer personal data', }, + [ContractExceptionCodes.CONTRACT_014]: { + code_error: ContractExceptionCodes.CONTRACT_014, + message: + 'Cannot delete a contract when it has been signed by any of the parties', + }, + [ContractExceptionCodes.CONTRACT_015]: { + code_error: ContractExceptionCodes.CONTRACT_015, + message: 'Error while deleting the contract', + }, }; diff --git a/backend/src/usecases/documents/new_contracts/delete-document-contract.usecase.ts b/backend/src/usecases/documents/new_contracts/delete-document-contract.usecase.ts new file mode 100644 index 000000000..87b101980 --- /dev/null +++ b/backend/src/usecases/documents/new_contracts/delete-document-contract.usecase.ts @@ -0,0 +1,80 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { JSONStringifyError } from 'src/common/helpers/utils'; +import { IUseCaseService } from 'src/common/interfaces/use-case-service.interface'; +import { ExceptionsService } from 'src/infrastructure/exceptions/exceptions.service'; +import { ActionsArchiveFacade } from 'src/modules/actions-archive/actions-archive.facade'; +import { TrackedEventName } from 'src/modules/actions-archive/enums/action-resource-types.enum'; +import { DocumentContractStatus } from 'src/modules/documents/enums/contract-status.enum'; +import { ContractExceptionMessages } from 'src/modules/documents/exceptions/contract.exceptions'; +import { DocumentContractFacade } from 'src/modules/documents/services/document-contract.facade'; +import { IAdminUserModel } from 'src/modules/user/models/admin-user.model'; + +@Injectable() +export class DeleteDocumentContractUsecase implements IUseCaseService { + private readonly logger = new Logger(DeleteDocumentContractUsecase.name); + constructor( + private readonly documentContractFacade: DocumentContractFacade, + private readonly exceptionService: ExceptionsService, + private readonly actionsArchiveFacade: ActionsArchiveFacade, + ) {} + + public async execute(id: string, admin: IAdminUserModel): Promise { + try { + // 1. Does the contract exists in the callers' organization? + const contract = await this.documentContractFacade.findOne({ + id, + organizationId: admin.organizationId, + }); + + if (!contract) { + this.exceptionService.notFoundException( + ContractExceptionMessages.CONTRACT_002, + ); + } + + // 2. Status of the contract must not be signed by any of the parties + if ( + [ + DocumentContractStatus.PENDING_APPROVAL_NGO, + DocumentContractStatus.PENDING_NGO_REPRESENTATIVE_SIGNATURE, + DocumentContractStatus.APPROVED, + DocumentContractStatus.REJECTED_NGO, + DocumentContractStatus.ACTION_EXPIRED, + ].includes(contract.status) + ) { + this.exceptionService.badRequestException( + ContractExceptionMessages.CONTRACT_014, + ); + } + + await this.documentContractFacade.delete(id); + + // 10. Track event + this.actionsArchiveFacade.trackEvent( + TrackedEventName.DELETE_DOCUMENT_CONTRACT, + { + organizationId: contract.organizationId, + volunteerId: contract.volunteerId, + volunteerName: contract.volunteer.user.name, + documentContractId: contract.id, + documentContractNumber: contract.documentNumber, + }, + admin, + ); + } catch (error) { + if (error?.status === 400) { + // Rethrow errors that we've thrown above, and catch the others + throw error; + } + + this.logger.error({ + ...ContractExceptionMessages.CONTRACT_015, + error: JSONStringifyError(error), + }); + this.exceptionService.internalServerErrorException({ + ...ContractExceptionMessages.CONTRACT_015, + details: JSONStringifyError(error), + }); + } + } +} diff --git a/backend/src/usecases/use-case.module.ts b/backend/src/usecases/use-case.module.ts index aee841484..f2a22370c 100644 --- a/backend/src/usecases/use-case.module.ts +++ b/backend/src/usecases/use-case.module.ts @@ -153,6 +153,7 @@ import { RejectDocumentContractByNgoUsecase } from './documents/new_contracts/re import { GetOneDocumentContractForNgoUsecase } from './documents/new_contracts/get-one-document-contract-for-ngo.usecase'; import { UpdateDocumentTemplateUsecase } from './documents/new_contracts/update-document-template.usecase'; import { GetDocumentContractStatisticsUsecase } from './documents/new_contracts/get-document-contract-statistics.usecase'; +import { DeleteDocumentContractUsecase } from './documents/new_contracts/delete-document-contract.usecase'; const providers = [ // Organization @@ -313,6 +314,7 @@ const providers = [ RejectDocumentContractByNgoUsecase, GetOneDocumentContractForNgoUsecase, GetDocumentContractStatisticsUsecase, + DeleteDocumentContractUsecase, // Notifications UpdateSettingsUsecase, ]; diff --git a/frontend/src/assets/locales/ro/translation.json b/frontend/src/assets/locales/ro/translation.json index 316778062..2b5d5e51a 100644 --- a/frontend/src/assets/locales/ro/translation.json +++ b/frontend/src/assets/locales/ro/translation.json @@ -961,7 +961,9 @@ "CONTRACT_002": "Contractul nu a fost găsit!", "CONTRACT_001": "Eroare la încărcarea contractului!", "CONTRACT_003": "Eroare la upload-ul documentului!", - "CONTRACT_006": "Nu se poate șterge un contract deja aprobat!" + "CONTRACT_006": "Nu se poate șterge un contract deja aprobat!", + "CONTRACT_014": "Nu se poate șterge un contract care a fost semnat de una dintre părți!", + "CONTRACT_015": "Eroare la ștergerea contractului!" } }, "upload": { @@ -1274,4 +1276,4 @@ "clear": "Șterge", "apply_all": "Aplică pentru toate" } -} \ No newline at end of file +} diff --git a/frontend/src/common/errors/entities/contract.errors.ts b/frontend/src/common/errors/entities/contract.errors.ts index 9d6e6f4f5..9ee8c9ad7 100644 --- a/frontend/src/common/errors/entities/contract.errors.ts +++ b/frontend/src/common/errors/entities/contract.errors.ts @@ -11,6 +11,9 @@ export enum CONTRACT_ERRORS { CONTRACT_001 = 'CONTRACT_001', CONTRACT_003 = 'CONTRACT_003', CONTRACT_006 = 'CONTRACT_006', + + CONTRACT_014 = 'CONTRACT_014', + CONTRACT_015 = 'CONTRACT_015', } export class ContractError extends ErrorClass { @@ -29,6 +32,9 @@ export class ContractError extends ErrorClass { [CONTRACT_ERRORS.CONTRACT_001]: i18n.t('documents:contract.submit.errors.CONTRACT_001'), [CONTRACT_ERRORS.CONTRACT_003]: i18n.t('documents:contract.submit.errors.CONTRACT_003'), [CONTRACT_ERRORS.CONTRACT_006]: i18n.t('documents:contract.submit.errors.CONTRACT_006'), + + [CONTRACT_ERRORS.CONTRACT_014]: i18n.t('documents:contract.submit.errors.CONTRACT_014'), + [CONTRACT_ERRORS.CONTRACT_015]: i18n.t('documents:contract.submit.errors.CONTRACT_015'), }); } diff --git a/frontend/src/components/DocumentContractsTable.tsx b/frontend/src/components/DocumentContractsTable.tsx index d7a104fb5..29e63fc0e 100644 --- a/frontend/src/components/DocumentContractsTable.tsx +++ b/frontend/src/components/DocumentContractsTable.tsx @@ -5,7 +5,7 @@ import CardBody from './CardBody'; import Card from '../layouts/CardLayout'; import { IHOCQueryProps } from '../common/interfaces/hoc-query-props.interface'; import i18n from '../common/config/i18n'; -import { ArrowDownTrayIcon, EyeIcon, PlusIcon } from '@heroicons/react/24/outline'; +import { ArrowDownTrayIcon, EyeIcon, PlusIcon, TrashIcon } from '@heroicons/react/24/outline'; import { SortOrder, TableColumn } from 'react-data-table-component'; import { OrderDirection } from '../common/enums/order-direction.enum'; import Popover from './Popover'; @@ -26,7 +26,7 @@ import { useNavigate } from 'react-router-dom'; import { VolunteerTabsOptions } from '../pages/Volunteer'; import { useTranslation } from 'react-i18next'; import { getContractsForDownload } from '../services/contracts/contracts.api'; -import { useGetDocumentsContractsQuery } from '../services/document-contracts/document-contracts.service'; +import { useDeleteDocumentContractMutation, useGetDocumentsContractsQuery } from '../services/document-contracts/document-contracts.service'; import { ApprovedDocumentContractStatus, DocumentContractStatus, @@ -34,6 +34,9 @@ import { import { IPaginationQueryParams } from '../common/constants/pagination'; import { IDocumentContract } from '../common/interfaces/document-contract.interface'; import DocumentsContractSidePanel from './DocumentsContractSidePanel'; +import ConfirmationModal from './ConfirmationModal'; +import { useErrorToast, useSuccessToast } from '../hooks/useToast'; +import { InternalErrors } from '../common/errors/internal-errors.class'; // const StatusOptions: SelectItem[] = [ // { @@ -159,6 +162,7 @@ const ContractsTable = ({ }: DocumentContractsTableProps) => { // selected contract id const [selectedContract, setSelectedContract] = useState(); + const [selectedDeleteContract, setSelectedDeleteContract] = useState(null); // side panel state const [isViewContractSidePanelOpen, setIsViewContractSidePanelOpen] = useState(false); // translation @@ -166,7 +170,7 @@ const ContractsTable = ({ // navigation const navigate = useNavigate(); - const { data: contracts, isLoading: isLoadingContracts } = useGetDocumentsContractsQuery({ + const { data: contracts, isLoading: isLoadingContracts, refetch } = useGetDocumentsContractsQuery({ page: query?.page as number, limit: query?.limit as number, search: query?.search, @@ -176,6 +180,8 @@ const ContractsTable = ({ status: query?.status as DocumentContractStatus, }); + const { mutate: deleteContract } = useDeleteDocumentContractMutation(); + const onView = (row: IDocumentContract) => { setSelectedContract(row.documentId); setIsViewContractSidePanelOpen(true); @@ -196,6 +202,26 @@ const ContractsTable = ({ downloadExcel(data as BlobPart, t('contracts.download')); }; + const showDeleteContractModal = (row: IDocumentContract) => { + setSelectedDeleteContract(row); + }; + + const confirmDelete = () => { + if (selectedDeleteContract) { + const contractId = selectedDeleteContract.documentId; + deleteContract(contractId, { + onSuccess: () => { + useSuccessToast(t('contract.submit.delete')); + refetch(); + }, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + onError: (error: any) => { + useErrorToast(InternalErrors.CONTRACT_ERRORS.getError(error?.response?.data.code_error)); + }, + }); + } + }; + const buildContractActionColumn = (): TableColumn => { const contractsMenuItems = [ { @@ -213,17 +239,29 @@ const ContractsTable = ({ }, ]; + const deleteContractsMenuItems = [ + ...contractsMenuItems, + { + label: t('general:delete'), + icon: , + onClick: showDeleteContractModal, + alert: true, + }, + ]; + + const mapContractStatusToPopoverItems = (status: DocumentContractStatus) => { switch (status) { case DocumentContractStatus.APPROVED: case DocumentContractStatus.SCHEDULED: + case DocumentContractStatus.CREATED: + case DocumentContractStatus.PENDING_VOLUNTEER_SIGNATURE: + return deleteContractsMenuItems; case DocumentContractStatus.ACTION_EXPIRED: case DocumentContractStatus.REJECTED_NGO: case DocumentContractStatus.REJECTED_VOLUNTEER: - case DocumentContractStatus.CREATED: case DocumentContractStatus.PENDING_APPROVAL_NGO: case DocumentContractStatus.PENDING_NGO_REPRESENTATIVE_SIGNATURE: - case DocumentContractStatus.PENDING_VOLUNTEER_SIGNATURE: return contractsMenuItems; default: return []; @@ -453,6 +491,16 @@ const ContractsTable = ({ isOpen={isViewContractSidePanelOpen} contractId={selectedContract} /> + {selectedDeleteContract && ( + + )} ); }; diff --git a/frontend/src/services/document-contracts/document-contracts.api.ts b/frontend/src/services/document-contracts/document-contracts.api.ts index 1539ab306..6ba23b316 100644 --- a/frontend/src/services/document-contracts/document-contracts.api.ts +++ b/frontend/src/services/document-contracts/document-contracts.api.ts @@ -30,3 +30,7 @@ export const approveDocumentContract = (id: string) => { export const rejectDocumentContract = (id: string, body: IRejectDocumentContractBody) => { return API.patch(`/documents/contracts/${id}/reject`, body).then((res) => res.data); }; + +export const deleteDocumentContract = (id: string) => { + return API.delete(`/documents/contracts/${id}`).then((res) => res.data); +}; From 7864d3d81dfe317840bb5fce196aec33b37c5620 Mon Sep 17 00:00:00 2001 From: Dragos-Paul Strat Date: Wed, 25 Sep 2024 13:51:14 +0300 Subject: [PATCH 2/5] feat: [contracts] add missing mutation --- .../document-contracts/document-contracts.service.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frontend/src/services/document-contracts/document-contracts.service.ts b/frontend/src/services/document-contracts/document-contracts.service.ts index b22d32f5e..647865b3e 100644 --- a/frontend/src/services/document-contracts/document-contracts.service.ts +++ b/frontend/src/services/document-contracts/document-contracts.service.ts @@ -2,6 +2,7 @@ import { useMutation, useQuery } from 'react-query'; import { addDocumentContract, approveDocumentContract, + deleteDocumentContract, getDocumentContract, getDocumentsContracts, rejectDocumentContract, @@ -104,3 +105,11 @@ export const useRejectcontractMutation = () => { }, ); }; + +export const useDeleteDocumentContractMutation = () => { + return useMutation((id: string) => deleteDocumentContract(id), { + onError: (error) => { + console.log(`⛔️ ERROR IN DELETE DOCUMENT CONTRACT ⛔️`, error); + }, + }); +}; From d260f3f5bbeeaf8d19d9d405a482b8492afa8a15 Mon Sep 17 00:00:00 2001 From: Dragos-Paul Strat Date: Wed, 25 Sep 2024 13:52:25 +0300 Subject: [PATCH 3/5] feat: [contracts] fix typo --- frontend/src/assets/locales/ro/translation.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/assets/locales/ro/translation.json b/frontend/src/assets/locales/ro/translation.json index 34d261e87..18ba1217f 100644 --- a/frontend/src/assets/locales/ro/translation.json +++ b/frontend/src/assets/locales/ro/translation.json @@ -1140,7 +1140,7 @@ "download_uncompleted": "Descarcă necompletat" }, "table_header": { - "create": "Creeaază template", + "create": "Creează template", "download_all": "Descarcă toate" } }, From 21393ddb4568aced201dd5f752e72c57abfe6421 Mon Sep 17 00:00:00 2001 From: luciatugui Date: Wed, 25 Sep 2024 14:23:02 +0300 Subject: [PATCH 4/5] wip: [Contracts] - table filters --- .../src/assets/locales/en/translation.json | 1 + .../src/assets/locales/ro/translation.json | 5 +- .../src/components/DocumentContractsTable.tsx | 230 ++++++++---------- .../DocumentContractsTableWithQueryParams.tsx | 9 +- 4 files changed, 108 insertions(+), 137 deletions(-) diff --git a/frontend/src/assets/locales/en/translation.json b/frontend/src/assets/locales/en/translation.json index 04b3072a1..0ed391714 100644 --- a/frontend/src/assets/locales/en/translation.json +++ b/frontend/src/assets/locales/en/translation.json @@ -8,6 +8,7 @@ "close": "Close", "name": "Name", "people": "People", + "volunteer": "Volunteer", "contract": "Contract", "age": "Age", "hours": "Ore", diff --git a/frontend/src/assets/locales/ro/translation.json b/frontend/src/assets/locales/ro/translation.json index 316778062..26e599f0e 100644 --- a/frontend/src/assets/locales/ro/translation.json +++ b/frontend/src/assets/locales/ro/translation.json @@ -8,6 +8,7 @@ "close": "Închide", "name": "Nume", "people": "Persoane", + "volunteer": "Voluntar", "contract": "Contract", "age": "Vârsta", "hours": "Ore", @@ -1042,8 +1043,8 @@ "DONE": "Încheiat", "NOT_STARTED": "Neînceput" }, - "REJECTED_VOLUNTEER": "Refuzat", - "REJECTED_NGO": "Refuzat", + "REJECTED_VOLUNTEER": "Refuzat Voluntar", + "REJECTED_NGO": "Refuzat NGO", "ACTION_EXPIRED": "Expirat" } }, diff --git a/frontend/src/components/DocumentContractsTable.tsx b/frontend/src/components/DocumentContractsTable.tsx index d7a104fb5..2682392ae 100644 --- a/frontend/src/components/DocumentContractsTable.tsx +++ b/frontend/src/components/DocumentContractsTable.tsx @@ -32,45 +32,64 @@ import { DocumentContractStatus, } from '../common/enums/document-contract-status.enum'; import { IPaginationQueryParams } from '../common/constants/pagination'; + import { IDocumentContract } from '../common/interfaces/document-contract.interface'; import DocumentsContractSidePanel from './DocumentsContractSidePanel'; +import VolunteerSelect from '../containers/VolunteerSelect'; +import { ListItem } from '../common/interfaces/list-item.interface'; +import { SelectItem } from './Select'; +import SelectFilter from '../containers/SelectFilter'; + +interface StatusOption { + key: string; + internalValue: DocumentContractStatus; + value: string; +} -// const StatusOptions: SelectItem[] = [ -// { -// key: ContractStatus.ACTIVE, -// value: `${i18n.t(`documents:contract.status.${ContractStatus.ACTIVE}`)}`, -// }, -// { -// key: ContractStatus.CLOSED, -// value: `${i18n.t(`documents:contract.status.${ContractStatus.CLOSED}`)}`, -// }, -// { -// key: ContractStatus.NOT_STARTED, -// value: `${i18n.t(`documents:contract.status.${ContractStatus.NOT_STARTED}`)}`, -// }, -// { -// key: ContractStatus.REJECTED, -// value: `${i18n.t(`documents:contract.status.${ContractStatus.REJECTED}`)}`, -// }, -// { -// key: ContractStatus.PENDING_ADMIN, -// value: `${i18n.t(`documents:contract.status.${ContractStatus.PENDING_ADMIN}`)}`, -// }, -// { -// key: ContractStatus.PENDING_VOLUNTEER, -// value: `${i18n.t(`documents:contract.status.${ContractStatus.PENDING_VOLUNTEER}`)}`, -// }, -// ]; +const StatusOptions = Object.values(DocumentContractStatus).flatMap((status: string) => { + if (status === DocumentContractStatus.APPROVED) { + return [ + { + key: ApprovedDocumentContractStatus.ACTIVE, + internalValue: DocumentContractStatus.APPROVED, + value: i18n.t( + `document_contract:contract.status.${DocumentContractStatus.APPROVED}.${ApprovedDocumentContractStatus.ACTIVE}`, + ), + }, + { + key: ApprovedDocumentContractStatus.DONE, + internalValue: DocumentContractStatus.APPROVED, + value: i18n.t( + `document_contract:contract.status.${DocumentContractStatus.APPROVED}.${ApprovedDocumentContractStatus.DONE}`, + ), + }, + { + key: ApprovedDocumentContractStatus.NOT_STARTED, + internalValue: DocumentContractStatus.APPROVED, + value: i18n.t( + `document_contract:contract.status.${DocumentContractStatus.APPROVED}.${ApprovedDocumentContractStatus.NOT_STARTED}`, + ), + }, + ]; + } + return [ + { + key: status, + value: i18n.t(`document_contract:contract.status.${status}`), + internalValue: status, + }, + ]; +}); const ContractsTableHeader = [ { - id: 'contractNumber', + id: 'documentNumber', name: i18n.t('documents:contracts.headers.contract_number'), sortable: true, selector: (row: IDocumentContract) => row.documentNumber, }, { - id: 'volunteer', + id: 'volunteerName', name: i18n.t('documents:contracts.headers.volunteer'), grow: 2, sortable: true, @@ -79,13 +98,13 @@ const ContractsTableHeader = [ ), }, { - id: 'startDate', + id: 'documentStartDate', name: i18n.t('documents:contracts.headers.start_date'), sortable: true, selector: (row: IDocumentContract) => formatDate(row.documentStartDate), }, { - id: 'endDate', + id: 'documentEndDate', name: i18n.t('documents:contracts.headers.end_date'), sortable: true, selector: (row: IDocumentContract) => formatDate(row.documentEndDate), @@ -138,6 +157,7 @@ const ContractsTableHeader = [ interface DocumentContractsTableQueryProps extends IPaginationQueryParams { volunteerId?: string; + volunteerName?: string; search?: string; startDate?: Date; endDate?: Date; @@ -146,19 +166,11 @@ interface DocumentContractsTableQueryProps extends IPaginationQueryParams { } type DocumentContractsTableBasicProps = IHOCQueryProps; -interface DocumentContractsTableProps extends DocumentContractsTableBasicProps { - volunteerName?: string; - volunteerId?: string; -} -const ContractsTable = ({ - query, - setQuery, - volunteerName, - volunteerId, -}: DocumentContractsTableProps) => { +const DocumentContractsTable = ({ query, setQuery }: DocumentContractsTableBasicProps) => { // selected contract id const [selectedContract, setSelectedContract] = useState(); + const [selectedVolunteer, setSelectedVolunteer] = useState(); // side panel state const [isViewContractSidePanelOpen, setIsViewContractSidePanelOpen] = useState(false); // translation @@ -172,8 +184,10 @@ const ContractsTable = ({ search: query?.search, orderBy: query?.orderBy as string, orderDirection: query?.orderDirection as OrderDirection, - volunteerId, + volunteerId: query?.volunteerId as string, status: query?.status as DocumentContractStatus, + startDate: query?.startDate as Date, + endDate: query?.endDate as Date, }); const onView = (row: IDocumentContract) => { @@ -190,9 +204,8 @@ const ContractsTable = ({ startDate: query?.startDate, endDate: query?.endDate, // status: query?.status as ContractStatus, - volunteerId, + volunteerId: query?.volunteerId, }); - downloadExcel(data as BlobPart, t('contracts.download')); }; @@ -284,16 +297,14 @@ const ContractsTable = ({ setQuery({ endDate: endDate as Date }); }; - // const onVolunteerChange = (volunteer: ListItem) => { - // setQuery({ volunteer: volunteer.label }); - // }; + const onVolunteerChange = (volunteer: ListItem) => { + setSelectedVolunteer(volunteer); + setQuery({ volunteerId: volunteer.value }); + }; const onResetFilters = () => { - if (volunteerName) { - setQuery({ activeTab: VolunteerTabsOptions.DOCUMENTS }, 'push'); - } else { - setQuery({}, 'push'); - } + setSelectedVolunteer(undefined); + setQuery({}, 'push'); }; const onSearch = (search: string) => { @@ -302,15 +313,27 @@ const ContractsTable = ({ }); }; - // const onStatusChange = (item: SelectItem | undefined) => { - // setQuery({ status: item?.key }); - // }; - - // const onCloseSidePanel = (shouldRefetch?: boolean) => { - // setIsViewContractSidePanelOpen(false); - // setSelectedContract(undefined); - // if (shouldRefetch) refetch(); - // }; + const onStatusChange = (item: StatusOption) => { + if (item.key === 'ACTIVE') { + // setQuery({ status: item?.internalValue as DocumentContractStatus, endDate: new Date() }); + } else if (item.key === 'DONE') { + const yesterday = new Date(); + yesterday.setDate(yesterday.getDate() - 1); + setQuery({ + status: item?.internalValue as DocumentContractStatus, + endDate: new Date(yesterday), + }); + } else if (item.key === 'NOT_STARTED') { + const tomorrow = new Date(); + tomorrow.setDate(tomorrow.getDate() + 1); + setQuery({ + status: item?.internalValue as DocumentContractStatus, + startDate: new Date(tomorrow), + }); + } else { + setQuery({ status: item?.internalValue as DocumentContractStatus }); + } + }; // todo: do we need shouldRefetch? const onCloseSidePanel = () => { @@ -318,68 +341,6 @@ const ContractsTable = ({ setSelectedContract(undefined); }; - // const confirmReject = (rejectMessage?: string) => { - // if (showRejectContract) - // rejectContract( - // { - // id: showRejectContract.id, - // rejectMessage, - // }, - // { - // onSuccess: () => { - // useSuccessToast(t('contract.submit.reject')); - // // refetch(); - // }, - // onError: (error) => { - // useErrorToast(InternalErrors.CONTRACT_ERRORS.getError(error.response?.data.code_error)); - // }, - // onSettled: () => { - // setShowRejectContract(null); - // }, - // }, - // ); - // }; - - // const confirmDelete = () => { - // if (showDeleteContract) { - // const contractId = showDeleteContract.id; - // setShowDeleteContract(null); - // deleteContract(contractId, { - // onSuccess: () => { - // useSuccessToast(t('contract.submit.delete')); - // // refetch(); - // }, - // onError: (error) => { - // useErrorToast(InternalErrors.CONTRACT_ERRORS.getError(error.response?.data.code_error)); - // }, - // }); - // } - // }; - - // const onConfirmSign = (contract?: File) => { - // if (!contract) return; - - // // store id and close modal - // const contractId = showApproveContract?.id; - // setShowApproveContract(null); - - // // approval process - // approveContract( - // { - // id: contractId as string, - // contract, - // }, - // { - // onSuccess: () => { - // useSuccessToast(t('contract.submit.confirm')); - // }, - // onError: (error) => { - // useErrorToast(InternalErrors.CONTRACT_ERRORS.getError(error.response?.data.code_error)); - // }, - // }, - // ); - // }; - return ( <> - {/* {!volunteerName && ( + { - )} */} + } - {/*