-
-
-
-
+ {/* Header with search, filter and Create Button */}
+
+
+
setSearchValue(e.target.value)}
+ onKeyUp={(e) => {
+ if (e.key === 'Enter') {
+ setSearchTerm(searchValue);
+ } else if (e.key === 'Backspace' && searchValue === '') {
+ setSearchTerm('');
+ }
+ }}
+ data-testid="searchBy"
+ />
+
+
+
+
+
+
-
+ {tCommon('searchBy', { item: '' })}
+
+
+ setSearchBy('assignee')}
+ data-testid="assignee"
>
-
-
-
- {orderBy === 'Latest' ? t('latest') : t('earliest')}
-
-
- handleSorting('Latest')}
- data-testid="latest"
- >
- {t('latest')}
-
- handleSorting('Earliest')}
- data-testid="earliest"
- >
- {t('earliest')}
-
-
-
-
-
+ setSearchBy('category')}
+ data-testid="category"
+ >
+ {t('category')}
+
+
+
+
+
-
+ {tCommon('sort')}
+
+
+ setSortBy('dueDate_DESC')}
+ data-testid="dueDate_DESC"
>
-
- {actionItemCategoryName === ''
- ? t('actionItemCategory')
- : actionItemCategoryName}
-
-
- {t('actionItemCategory')}
-
-
-
- {actionItemCategories?.map((category, index) => (
- {
- setActionItemCategoryId(category._id);
- setActionItemCategoryName(category.name);
- }}
- >
- {category.name}
-
- ))}
-
-
-
-
+ setSortBy('dueDate_ASC')}
+ data-testid="dueDate_ASC"
+ >
+ {t('earliestDueDate')}
+
+
+
+
+
-
+ {t('status')}
+
+
+ setStatus(null)}
+ data-testid="statusAll"
>
-
- {actionItemStatus === '' ? t('status') : actionItemStatus}
-
- {t('status')}
-
-
- handleStatusFilter('Active')}
- data-testid="activeActionItems"
- >
- {t('active')}
-
- handleStatusFilter('Completed')}
- data-testid="completedActionItems"
- >
- {t('completed')}
-
-
-
-
-
-
- {!actionItemCategoryName && !actionItemStatus && (
-
- {tCommon('noFiltersApplied')}
-
- )}
-
- {actionItemCategoryName !== '' && (
-
- {actionItemCategoryName}
- {
- setActionItemCategoryName('');
- setActionItemCategoryId('');
- }}
- data-testid="clearActionItemCategoryFilter"
- />
-
- )}
-
- {actionItemStatus !== '' && (
-
- {actionItemStatus}
- setActionItemStatus('')}
- data-testid="clearActionItemStatusFilter"
- />
-
- )}
-
-
-
+ {tCommon('all')}
+
+
setStatus(ItemStatus.Pending)}
+ data-testid="statusPending"
+ >
+ {tCommon('pending')}
+
+
setStatus(ItemStatus.Completed)}
+ data-testid="statusCompleted"
+ >
+ {tCommon('completed')}
+
+
+
+
+
+
-
+ {/* Table with Action Items */}
+
row._id}
+ slots={{
+ noRowsOverlay: () => (
+
+ {t('noActionItems')}
+
+ ),
+ }}
+ sx={dataGridStyle}
+ getRowClassName={() => `${styles.rowBackground}`}
+ autoHeight
+ rowHeight={65}
+ rows={actionItems.map((actionItem, index) => ({
+ id: index + 1,
+ ...actionItem,
+ }))}
+ columns={columns}
+ isRowSelectable={() => false}
+ />
-
-
+ {/* Item Modal (Create/Edit) */}
+
closeModal(ModalState.SAME)}
+ orgId={orgId}
+ actionItemsRefetch={actionItemsRefetch}
+ actionItem={actionItem}
+ editMode={modalMode === 'edit'}
+ />
+
+ closeModal(ModalState.DELETE)}
+ actionItem={actionItem}
+ actionItemsRefetch={actionItemsRefetch}
+ />
- {/* Create Modal */}
- closeModal(ModalState.STATUS)}
+ actionItemsRefetch={actionItemsRefetch}
/>
+
+ {/* View Modal */}
+ {actionItem && (
+ closeModal(ModalState.VIEW)}
+ item={actionItem}
+ />
+ )}
);
}
diff --git a/src/screens/OrganizationActionItems/OrganizationActionItemsErrorMocks.ts b/src/screens/OrganizationActionItems/OrganizationActionItemsErrorMocks.ts
deleted file mode 100644
index bedba6572b..0000000000
--- a/src/screens/OrganizationActionItems/OrganizationActionItemsErrorMocks.ts
+++ /dev/null
@@ -1,266 +0,0 @@
-import { CREATE_ACTION_ITEM_MUTATION } from 'GraphQl/Mutations/mutations';
-
-import {
- ACTION_ITEM_CATEGORY_LIST,
- ACTION_ITEM_LIST,
- MEMBERS_LIST,
-} from 'GraphQl/Queries/Queries';
-
-export const MOCKS_ERROR_ACTION_ITEM_CATEGORY_LIST_QUERY = [
- {
- request: {
- query: ACTION_ITEM_CATEGORY_LIST,
- variables: { organizationId: '123' },
- },
- error: new Error('Mock Graphql Error'),
- },
-];
-
-export const MOCKS_ERROR_MEMBERS_LIST_QUERY = [
- {
- request: {
- query: ACTION_ITEM_CATEGORY_LIST,
- variables: { organizationId: '123' },
- },
- result: {
- data: {
- actionItemCategoriesByOrganization: [
- {
- _id: 'actionItemCategory1',
- name: 'ActionItemCategory 1',
- isDisabled: false,
- },
- ],
- },
- },
- },
- {
- request: {
- query: MEMBERS_LIST,
- variables: { id: '123' },
- },
- error: new Error('Mock Graphql Error'),
- },
-];
-
-export const MOCKS_ERROR_ACTION_ITEM_LIST_QUERY = [
- {
- request: {
- query: ACTION_ITEM_CATEGORY_LIST,
- variables: { organizationId: '123' },
- },
- result: {
- data: {
- actionItemCategoriesByOrganization: [
- {
- _id: 'actionItemCategory1',
- name: 'ActionItemCategory 1',
- isDisabled: false,
- },
- ],
- },
- },
- },
- {
- request: {
- query: MEMBERS_LIST,
- variables: { id: '123' },
- },
- result: {
- data: {
- organizations: [
- {
- _id: '123',
- members: [
- {
- _id: 'user1',
- firstName: 'Harve',
- lastName: 'Lance',
- email: 'harve@example.com',
- image: '',
- organizationsBlockedBy: [],
- createdAt: '2024-02-14',
- },
- ],
- },
- ],
- },
- },
- },
- {
- request: {
- query: ACTION_ITEM_LIST,
- variables: { id: '123' },
- },
- error: new Error('Mock Graphql Error'),
- },
-];
-
-export const MOCKS_ERROR_MUTATIONS = [
- {
- request: {
- query: ACTION_ITEM_CATEGORY_LIST,
- variables: { organizationId: '123' },
- },
- result: {
- data: {
- actionItemCategoriesByOrganization: [
- {
- _id: 'actionItemCategory1',
- name: 'ActionItemCategory 1',
- isDisabled: false,
- },
- ],
- },
- },
- },
- {
- request: {
- query: MEMBERS_LIST,
- variables: { id: '123' },
- },
- result: {
- data: {
- organizations: [
- {
- _id: '123',
- members: [
- {
- _id: 'user1',
- firstName: 'Harve',
- lastName: 'Lance',
- email: 'harve@example.com',
- image: '',
- organizationsBlockedBy: [],
- createdAt: '2024-02-14',
- },
- ],
- },
- ],
- },
- },
- },
- {
- request: {
- query: ACTION_ITEM_LIST,
- variables: {
- organizationId: '123',
- orderBy: 'createdAt_DESC',
- actionItemCategoryId: '',
- isActive: false,
- isCompleted: false,
- },
- },
- result: {
- data: {
- actionItemsByOrganization: [
- {
- _id: 'actionItem1',
- assignee: {
- _id: 'user1',
- firstName: 'Harve',
- lastName: 'Lance',
- },
- actionItemCategory: {
- _id: 'actionItemCategory1',
- name: 'ActionItemCategory 1',
- },
- preCompletionNotes: 'Pre Completion Notes',
- postCompletionNotes: 'Post Completion Notes',
- assignmentDate: '2024-02-14',
- dueDate: '2024-02-21',
- completionDate: '2024-02-21',
- isCompleted: false,
- assigner: {
- _id: 'user0',
- firstName: 'Wilt',
- lastName: 'Shepherd',
- },
- event: {
- _id: 'event1',
- title: 'event 1',
- },
- creator: {
- _id: 'user0',
- firstName: 'Wilt',
- lastName: 'Shepherd',
- },
- },
- ],
- },
- },
- },
- {
- request: {
- query: ACTION_ITEM_LIST,
- variables: {
- organizationId: '123',
- eventId: 'event1',
- orderBy: 'createdAt_DESC',
- },
- },
- result: {
- data: {
- actionItemsByOrganization: [
- {
- _id: 'actionItem1',
- assignee: {
- _id: 'user1',
- firstName: 'Harve',
- lastName: 'Lance',
- },
- actionItemCategory: {
- _id: 'actionItemCategory1',
- name: 'ActionItemCategory 1',
- },
- preCompletionNotes: 'Pre Completion Notes',
- postCompletionNotes: 'Post Completion Notes',
- assignmentDate: '2024-02-14',
- dueDate: '2024-02-21',
- completionDate: '2024-02-21',
- isCompleted: false,
- assigner: {
- _id: 'user0',
- firstName: 'Wilt',
- lastName: 'Shepherd',
- },
- event: {
- _id: 'event1',
- title: 'event 1',
- },
- creator: {
- _id: 'user0',
- firstName: 'Wilt',
- lastName: 'Shepherd',
- },
- },
- ],
- },
- },
- },
- {
- request: {
- query: CREATE_ACTION_ITEM_MUTATION,
- variables: {
- actionItemCategoryId: 'actionItemCategory1',
- assigneeId: 'user1',
- preCompletionNotes: 'pre completion notes',
- dueDate: '2024-02-14',
- },
- },
- error: new Error('Mock Graphql Error'),
- },
- {
- request: {
- query: CREATE_ACTION_ITEM_MUTATION,
- variables: {
- eventId: 'event1',
- actionItemCategoryId: 'actionItemCategory1',
- assigneeId: 'user1',
- preCompletionNotes: 'pre completion notes',
- dueDate: '2024-02-14',
- },
- },
- error: new Error('Mock Graphql Error'),
- },
-];
diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx b/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx
index e377826a73..dde6b3120f 100644
--- a/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx
+++ b/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx
@@ -1,5 +1,5 @@
import { MockedProvider } from '@apollo/react-testing';
-import { act, fireEvent, render, screen } from '@testing-library/react';
+import { fireEvent, render, screen } from '@testing-library/react';
import 'jest-location-mock';
import { I18nextProvider } from 'react-i18next';
import { Provider } from 'react-redux';
@@ -13,7 +13,7 @@ import i18nForTest from 'utils/i18nForTest';
import useLocalStorage from 'utils/useLocalstorage';
import OrganizationDashboard from './OrganizationDashboard';
import { EMPTY_MOCKS, ERROR_MOCKS, MOCKS } from './OrganizationDashboardMocks';
-import React from 'react';
+import React, { act } from 'react';
const { setItem } = useLocalStorage();
import type { InterfaceQueryOrganizationEventListItem } from 'utils/interfaces';
diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.tsx b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx
index c19cce6880..6927e4f874 100644
--- a/src/screens/OrganizationDashboard/OrganizationDashboard.tsx
+++ b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx
@@ -11,11 +11,11 @@ import {
ORGANIZATION_EVENT_CONNECTION_LIST,
ORGANIZATION_POST_LIST,
} from 'GraphQl/Queries/Queries';
-import { ReactComponent as AdminsIcon } from 'assets/svgs/admin.svg';
-import { ReactComponent as BlockedUsersIcon } from 'assets/svgs/blockedUser.svg';
-import { ReactComponent as EventsIcon } from 'assets/svgs/events.svg';
-import { ReactComponent as PostsIcon } from 'assets/svgs/post.svg';
-import { ReactComponent as UsersIcon } from 'assets/svgs/users.svg';
+import AdminsIcon from 'assets/svgs/admin.svg?react';
+import BlockedUsersIcon from 'assets/svgs/blockedUser.svg?react';
+import EventsIcon from 'assets/svgs/events.svg?react';
+import PostsIcon from 'assets/svgs/post.svg?react';
+import UsersIcon from 'assets/svgs/users.svg?react';
import CardItem from 'components/OrganizationDashCards/CardItem';
import CardItemLoading from 'components/OrganizationDashCards/CardItemLoading';
import DashBoardCard from 'components/OrganizationDashCards/DashboardCard';
diff --git a/src/screens/OrganizationEvents/OrganizationEvents.tsx b/src/screens/OrganizationEvents/OrganizationEvents.tsx
index 2998e89c39..4c90777c6e 100644
--- a/src/screens/OrganizationEvents/OrganizationEvents.tsx
+++ b/src/screens/OrganizationEvents/OrganizationEvents.tsx
@@ -170,8 +170,8 @@ function organizationEvents(): JSX.Element {
endDate: dayjs(endDate).format('YYYY-MM-DD'),
allDay: alldaychecked,
location: formState.location,
- startTime: !alldaychecked ? formState.startTime + 'Z' : undefined,
- endTime: !alldaychecked ? formState.endTime + 'Z' : undefined,
+ startTime: !alldaychecked ? formState.startTime : undefined,
+ endTime: !alldaychecked ? formState.endTime : undefined,
recurrenceStartDate: recurringchecked
? dayjs(recurrenceStartDate).format('YYYY-MM-DD')
: undefined,
@@ -196,7 +196,7 @@ function organizationEvents(): JSX.Element {
});
if (createEventData) {
- toast.success(t('eventCreated'));
+ toast.success(t('eventCreated') as string);
refetchEvents();
hideCreateEventModal();
setFormState({
diff --git a/src/screens/OrganizationEvents/OrganizationEventsMocks.ts b/src/screens/OrganizationEvents/OrganizationEventsMocks.ts
index 3ff2d73d5a..4f844d33fa 100644
--- a/src/screens/OrganizationEvents/OrganizationEventsMocks.ts
+++ b/src/screens/OrganizationEvents/OrganizationEventsMocks.ts
@@ -106,8 +106,8 @@ export const MOCKS = [
startDate: '2022-03-28',
endDate: '2022-03-30',
allDay: false,
- startTime: '09:00:00Z',
- endTime: '17:00:00Z',
+ startTime: '09:00:00',
+ endTime: '17:00:00',
},
},
result: {
@@ -132,8 +132,8 @@ export const MOCKS = [
startDate: '2022-03-28',
endDate: '2022-03-30',
allDay: false,
- startTime: '09:00:00Z',
- endTime: '17:00:00Z',
+ startTime: '09:00:00',
+ endTime: '17:00:00',
recurrenceStartDate: '2022-03-28',
recurrenceEndDate: null,
frequency: 'DAILY',
@@ -162,8 +162,8 @@ export const MOCKS = [
startDate: '2022-03-28',
endDate: '2022-03-30',
allDay: false,
- startTime: '09:00:00Z',
- endTime: '17:00:00Z',
+ startTime: '09:00:00',
+ endTime: '17:00:00',
recurrenceStartDate: '2022-03-28',
recurrenceEndDate: null,
frequency: 'WEEKLY',
diff --git a/src/screens/OrganizationFundCampaign/CampaignDeleteModal.test.tsx b/src/screens/OrganizationFundCampaign/CampaignDeleteModal.test.tsx
deleted file mode 100644
index 7baf9bd933..0000000000
--- a/src/screens/OrganizationFundCampaign/CampaignDeleteModal.test.tsx
+++ /dev/null
@@ -1,95 +0,0 @@
-import React from 'react';
-import type { ApolloLink } from '@apollo/client';
-import { MockedProvider } from '@apollo/react-testing';
-import { LocalizationProvider } from '@mui/x-date-pickers';
-import type { RenderResult } from '@testing-library/react';
-import { fireEvent, render, screen, waitFor } from '@testing-library/react';
-import { I18nextProvider } from 'react-i18next';
-import { Provider } from 'react-redux';
-import { BrowserRouter } from 'react-router-dom';
-import { store } from 'state/store';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import i18nForTest from '../../utils/i18nForTest';
-import { StaticMockLink } from 'utils/StaticMockLink';
-import { toast } from 'react-toastify';
-import { MOCKS, MOCK_ERROR } from './OrganizationFundCampaignMocks';
-import CampaignDeleteModal, {
- type InterfaceDeleteCampaignModal,
-} from './CampaignDeleteModal';
-
-jest.mock('react-toastify', () => ({
- toast: {
- success: jest.fn(),
- error: jest.fn(),
- },
-}));
-
-const link1 = new StaticMockLink(MOCKS);
-const link2 = new StaticMockLink(MOCK_ERROR);
-const translations = JSON.parse(
- JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.fundCampaign),
-);
-
-const campaignProps: InterfaceDeleteCampaignModal = {
- isOpen: true,
- hide: jest.fn(),
- campaign: {
- _id: 'campaignId1',
- name: 'Campaign 1',
- fundingGoal: 100,
- startDate: new Date('2021-01-01'),
- endDate: new Date('2024-01-01'),
- currency: 'USD',
- createdAt: '2021-01-01',
- },
- refetchCampaign: jest.fn(),
-};
-const renderFundDeleteModal = (
- link: ApolloLink,
- props: InterfaceDeleteCampaignModal,
-): RenderResult => {
- return render(
-
-
-
-
-
-
-
-
-
-
- ,
- );
-};
-
-describe('CampaignDeleteModal', () => {
- it('should render CampaignDeleteModal', () => {
- renderFundDeleteModal(link1, campaignProps);
- expect(screen.getByTestId('deleteCampaignCloseBtn')).toBeInTheDocument();
- });
-
- it('should successfully Delete Campaign', async () => {
- renderFundDeleteModal(link1, campaignProps);
- expect(screen.getByTestId('deleteCampaignCloseBtn')).toBeInTheDocument();
-
- fireEvent.click(screen.getByTestId('deleteyesbtn'));
-
- await waitFor(() => {
- expect(campaignProps.refetchCampaign).toHaveBeenCalled();
- expect(campaignProps.hide).toHaveBeenCalled();
- expect(toast.success).toHaveBeenCalledWith(translations.deletedCampaign);
- });
- });
-
- it('should fail to Delete Campaign', async () => {
- renderFundDeleteModal(link2, campaignProps);
- expect(screen.getByTestId('deleteCampaignCloseBtn')).toBeInTheDocument();
-
- fireEvent.click(screen.getByTestId('deleteyesbtn'));
-
- await waitFor(() => {
- expect(toast.error).toHaveBeenCalledWith('Mock graphql error');
- });
- });
-});
diff --git a/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx b/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx
deleted file mode 100644
index c6c0b5a35e..0000000000
--- a/src/screens/OrganizationFundCampaign/CampaignDeleteModal.tsx
+++ /dev/null
@@ -1,90 +0,0 @@
-import React from 'react';
-import { Button, Modal } from 'react-bootstrap';
-import styles from './OrganizationFundCampaign.module.css';
-import { useMutation } from '@apollo/client';
-import { DELETE_CAMPAIGN_MUTATION } from 'GraphQl/Mutations/CampaignMutation';
-import type { InterfaceCampaignInfo } from 'utils/interfaces';
-import { toast } from 'react-toastify';
-import { useTranslation } from 'react-i18next';
-
-/**
- * Props for the CampaignDeleteModal component.
- */
-export interface InterfaceDeleteCampaignModal {
- isOpen: boolean;
- hide: () => void;
- campaign: InterfaceCampaignInfo | null;
- refetchCampaign: () => void;
-}
-
-/**
- * Modal component for confirming the deletion of a campaign.
- *
- * @param props - The props for the CampaignDeleteModal component.
- * @returns JSX.Element
- */
-const CampaignDeleteModal: React.FC
= ({
- isOpen,
- hide,
- campaign,
- refetchCampaign,
-}) => {
- const { t } = useTranslation('translation', {
- keyPrefix: 'fundCampaign',
- });
- const { t: tCommon } = useTranslation('common');
-
- const [deleteCampaign] = useMutation(DELETE_CAMPAIGN_MUTATION);
-
- /**
- * Handles the campaign deletion.
- *
- * @returns Promise
- */
- const deleteCampaignHandler = async (): Promise => {
- try {
- await deleteCampaign({
- variables: {
- id: campaign?._id,
- },
- });
- toast.success(t('deletedCampaign'));
- refetchCampaign();
- hide();
- } catch (error: unknown) {
- toast.error((error as Error).message);
- }
- };
- return (
- <>
-
-
- {t('deleteCampaign')}
-
-
-
- {t('deleteCampaignMsg')}
-
-
-
-
-
-
- >
- );
-};
-export default CampaignDeleteModal;
diff --git a/src/screens/OrganizationFundCampaign/CampaignModal.tsx b/src/screens/OrganizationFundCampaign/CampaignModal.tsx
index 1a31dd8242..63d1e8de3a 100644
--- a/src/screens/OrganizationFundCampaign/CampaignModal.tsx
+++ b/src/screens/OrganizationFundCampaign/CampaignModal.tsx
@@ -106,7 +106,7 @@ const CampaignModal: React.FC = ({
fundId,
},
});
- toast.success(t('createdCampaign'));
+ toast.success(t('createdCampaign') as string);
setFormState({
campaignName: '',
campaignCurrency: 'USD',
@@ -166,7 +166,7 @@ const CampaignModal: React.FC = ({
});
refetchCampaign();
hide();
- toast.success(t('updatedCampaign'));
+ toast.success(t('updatedCampaign') as string);
} catch (error: unknown) {
toast.error((error as Error).message);
}
diff --git a/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx b/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx
index 8abba9bab6..1c6dbf2cc6 100644
--- a/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx
+++ b/src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx
@@ -13,7 +13,6 @@ import React, { useCallback, useMemo, useState } from 'react';
import dayjs from 'dayjs';
import Loader from 'components/Loader/Loader';
import CampaignModal from './CampaignModal';
-import CampaignDeleteModal from './CampaignDeleteModal';
import { FUND_CAMPAIGN } from 'GraphQl/Queries/fundQueries';
import styles from './OrganizationFundCampaign.module.css';
import { currencySymbols } from 'utils/currency';
@@ -43,33 +42,26 @@ const dataGridStyle = {
},
};
-enum ModalState {
- SAME = 'same',
- DELETE = 'delete',
-}
/**
* `orgFundCampaign` component displays a list of fundraising campaigns for a specific fund within an organization.
- * It allows users to search, sort, view, edit, and delete campaigns.
+ * It allows users to search, sort, view and edit campaigns.
*
* ### Functionality
* - Displays a data grid with campaigns information, including their names, start and end dates, funding goals, and actions.
* - Provides search functionality to filter campaigns by name.
* - Offers sorting options based on funding goal and end date.
- * - Opens modals for creating, editing, or deleting campaigns.
+ * - Opens modals for creating or editing campaigns.
*
*
* ### State
* - `campaign`: The current campaign being edited or deleted.
* - `searchTerm`: The term used for searching campaigns by name.
* - `sortBy`: The current sorting criteria for campaigns.
- * - `modalState`: An object indicating the visibility of different modals (`same` for create/edit and `delete` for deletion).
+ * - `modalState`: An object indicating the visibility of different modals (`same` for create/edit).
* - `campaignModalMode`: Determines if the modal is in 'edit' or 'create' mode.
*
* ### Methods
- * - `openModal(modal: ModalState)`: Opens the specified modal.
- * - `closeModal(modal: ModalState)`: Closes the specified modal.
* - `handleOpenModal(campaign: InterfaceCampaignInfo | null, mode: 'edit' | 'create')`: Opens the modal for creating or editing a campaign.
- * - `handleDeleteClick(campaign: InterfaceCampaignInfo)`: Opens the delete confirmation modal.
* - `handleClick(campaignId: string)`: Navigates to the pledge details page for a specific campaign.
*
* ### GraphQL Queries
@@ -77,7 +69,7 @@ enum ModalState {
*
* ### Rendering
* - Renders a `DataGrid` component with campaigns information.
- * - Displays modals for creating, editing, and deleting campaigns.
+ * - Displays modals for creating and editing campaigns.
* - Shows error and loading states using `Loader` and error message components.
*
* @returns The rendered component including breadcrumbs, search and filter controls, data grid, and modals.
@@ -99,36 +91,18 @@ const orgFundCampaign = (): JSX.Element => {
const [searchTerm, setSearchTerm] = useState('');
const [sortBy, setSortBy] = useState(null);
- const [modalState, setModalState] = useState<{
- [key in ModalState]: boolean;
- }>({
- [ModalState.SAME]: false,
- [ModalState.DELETE]: false,
- });
+ const [modalState, setModalState] = useState(false);
const [campaignModalMode, setCampaignModalMode] = useState<'edit' | 'create'>(
'create',
);
- const openModal = (modal: ModalState): void =>
- setModalState((prevState) => ({ ...prevState, [modal]: true }));
-
- const closeModal = (modal: ModalState): void =>
- setModalState((prevState) => ({ ...prevState, [modal]: false }));
const handleOpenModal = useCallback(
(campaign: InterfaceCampaignInfo | null, mode: 'edit' | 'create'): void => {
setCampaign(campaign);
setCampaignModalMode(mode);
- openModal(ModalState.SAME);
- },
- [openModal],
- );
-
- const handleDeleteClick = useCallback(
- (campaign: InterfaceCampaignInfo): void => {
- setCampaign(campaign);
- openModal(ModalState.DELETE);
+ setModalState(true);
},
- [openModal],
+ [],
);
const {
@@ -157,10 +131,11 @@ const orgFundCampaign = (): JSX.Element => {
navigate(`/fundCampaignPledge/${orgId}/${campaignId}`);
};
- const campaigns = useMemo(() => {
- if (campaignData?.getFundById?.campaigns)
- return campaignData.getFundById.campaigns;
- return [];
+ const { campaigns, fundName, isArchived } = useMemo(() => {
+ const fundName = campaignData?.getFundById?.name || 'Fund';
+ const isArchived = campaignData?.getFundById?.isArchived || false;
+ const campaigns = campaignData?.getFundById?.campaigns || [];
+ return { fundName, campaigns, isArchived };
}, [campaignData]);
if (campaignLoading) {
@@ -319,17 +294,6 @@ const orgFundCampaign = (): JSX.Element => {
>
-
>
);
},
@@ -370,9 +334,9 @@ const orgFundCampaign = (): JSX.Element => {
data-testid="fundsLink"
onClick={() => navigate(`/orgfunds/${orgId}`)}
>
- {tCommon('Funds')}
+ {fundName}
- FundRaising Campaign
+ {t('title')}
@@ -440,6 +404,7 @@ const orgFundCampaign = (): JSX.Element => {
className={styles.orgFundCampaignButton}
onClick={() => handleOpenModal(null, 'create')}
data-testid="addCampaignBtn"
+ disabled={isArchived}
>
{t('addCampaign')}
@@ -474,21 +439,14 @@ const orgFundCampaign = (): JSX.Element => {
{/* Create Campaign ModalState */}
closeModal(ModalState.SAME)}
+ isOpen={modalState}
+ hide={() => setModalState(false)}
refetchCampaign={refetchCampaign}
fundId={fundId}
orgId={orgId}
campaign={campaign}
mode={campaignModalMode}
/>
-
- closeModal(ModalState.DELETE)}
- campaign={campaign}
- refetchCampaign={refetchCampaign}
- />
);
};
diff --git a/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx b/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx
index 74f646f51a..9c169e355a 100644
--- a/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx
+++ b/src/screens/OrganizationFundCampaign/OrganizationFundCampaign.test.tsx
@@ -173,22 +173,6 @@ describe('FundCampaigns Screen', () => {
);
});
- it('open and closes delete campaign modal', async () => {
- renderFundCampaign(link1);
-
- const deleteCampaignBtn = await screen.findAllByTestId('deleteCampaignBtn');
- await waitFor(() => expect(deleteCampaignBtn[0]).toBeInTheDocument());
- userEvent.click(deleteCampaignBtn[0]);
-
- await waitFor(() =>
- expect(screen.getByText(translations.deleteCampaign)).toBeInTheDocument(),
- );
- userEvent.click(screen.getByTestId('deleteCampaignCloseBtn'));
- await waitFor(() =>
- expect(screen.queryByTestId('deleteCampaignCloseBtn')).toBeNull(),
- );
- });
-
it('Search the Campaigns list by Name', async () => {
renderFundCampaign(link1);
const searchField = await screen.findByTestId('searchFullName');
diff --git a/src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.ts b/src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.ts
index 6ec2521665..fa871c3593 100644
--- a/src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.ts
+++ b/src/screens/OrganizationFundCampaign/OrganizationFundCampaignMocks.ts
@@ -1,6 +1,5 @@
import {
CREATE_CAMPAIGN_MUTATION,
- DELETE_CAMPAIGN_MUTATION,
UPDATE_CAMPAIGN_MUTATION,
} from 'GraphQl/Mutations/CampaignMutation';
import { FUND_CAMPAIGN } from 'GraphQl/Queries/fundQueries';
@@ -18,6 +17,8 @@ export const MOCKS = [
result: {
data: {
getFundById: {
+ name: 'Fund 1',
+ isArchived: false,
campaigns: [
{
_id: 'campaignId1',
@@ -52,6 +53,8 @@ export const MOCKS = [
result: {
data: {
getFundById: {
+ name: 'Fund 1',
+ isArchived: false,
campaigns: [
{
_id: '2',
@@ -78,6 +81,8 @@ export const MOCKS = [
result: {
data: {
getFundById: {
+ name: 'Fund 1',
+ isArchived: false,
campaigns: [
{
_id: '1',
@@ -112,6 +117,8 @@ export const MOCKS = [
result: {
data: {
getFundById: {
+ name: 'Fund 1',
+ isArchived: false,
campaigns: [
{
_id: '2',
@@ -146,6 +153,8 @@ export const MOCKS = [
result: {
data: {
getFundById: {
+ name: 'Fund 1',
+ isArchived: false,
campaigns: [
{
_id: '2',
@@ -180,6 +189,8 @@ export const MOCKS = [
result: {
data: {
getFundById: {
+ name: 'Fund 1',
+ isArchived: false,
campaigns: [
{
_id: '1',
@@ -242,21 +253,6 @@ export const MOCKS = [
},
},
},
- {
- request: {
- query: DELETE_CAMPAIGN_MUTATION,
- variables: {
- id: 'campaignId1',
- },
- },
- result: {
- data: {
- removeFundraisingCampaign: {
- _id: 'campaignId1',
- },
- },
- },
- },
];
export const MOCK_ERROR = [
@@ -299,15 +295,6 @@ export const MOCK_ERROR = [
},
error: new Error('Mock graphql error'),
},
- {
- request: {
- query: DELETE_CAMPAIGN_MUTATION,
- variables: {
- id: 'campaignId1',
- },
- },
- error: new Error('Mock graphql error'),
- },
];
export const EMPTY_MOCKS = [
@@ -323,6 +310,8 @@ export const EMPTY_MOCKS = [
result: {
data: {
getFundById: {
+ name: 'Fund 1',
+ isArchived: false,
campaigns: [],
},
},
diff --git a/src/screens/OrganizationFunds/FundDeleteModal.test.tsx b/src/screens/OrganizationFunds/FundDeleteModal.test.tsx
deleted file mode 100644
index 41fcd3ec5e..0000000000
--- a/src/screens/OrganizationFunds/FundDeleteModal.test.tsx
+++ /dev/null
@@ -1,100 +0,0 @@
-import React from 'react';
-import type { ApolloLink } from '@apollo/client';
-import { MockedProvider } from '@apollo/react-testing';
-import { LocalizationProvider } from '@mui/x-date-pickers';
-import type { RenderResult } from '@testing-library/react';
-import { fireEvent, render, screen, waitFor } from '@testing-library/react';
-import { I18nextProvider } from 'react-i18next';
-import { Provider } from 'react-redux';
-import { BrowserRouter } from 'react-router-dom';
-import { store } from 'state/store';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import i18nForTest from '../../utils/i18nForTest';
-import { StaticMockLink } from 'utils/StaticMockLink';
-import { toast } from 'react-toastify';
-import type { InterfaceDeleteFundModal } from './FundDeleteModal';
-import FundDeleteModal from './FundDeleteModal';
-import { MOCKS, MOCKS_ERROR } from './OrganizationFundsMocks';
-
-jest.mock('react-toastify', () => ({
- toast: {
- success: jest.fn(),
- error: jest.fn(),
- },
-}));
-
-const link1 = new StaticMockLink(MOCKS);
-const link2 = new StaticMockLink(MOCKS_ERROR);
-const translations = JSON.parse(
- JSON.stringify(i18nForTest.getDataByLanguage('en')?.translation.funds),
-);
-
-const fundProps: InterfaceDeleteFundModal = {
- isOpen: true,
- hide: jest.fn(),
- fund: {
- _id: 'fundId',
- name: 'Fund 1',
- refrenceNumber: '1111',
- taxDeductible: true,
- isArchived: false,
- isDefault: false,
- createdAt: '2024-06-22',
- organizationId: 'orgId',
- creator: {
- _id: 'creatorId1',
- firstName: 'John',
- lastName: 'Doe',
- },
- },
- refetchFunds: jest.fn(),
-};
-const renderFundDeleteModal = (
- link: ApolloLink,
- props: InterfaceDeleteFundModal,
-): RenderResult => {
- return render(
-
-
-
-
-
-
-
-
-
-
- ,
- );
-};
-
-describe('FundDeleteModal', () => {
- it('should render FundDeleteModal', () => {
- renderFundDeleteModal(link1, fundProps);
- expect(screen.getByTestId('deleteFundCloseBtn')).toBeInTheDocument();
- });
-
- it('should successfully Delete Fund', async () => {
- renderFundDeleteModal(link1, fundProps);
- expect(screen.getByTestId('deleteFundCloseBtn')).toBeInTheDocument();
-
- fireEvent.click(screen.getByTestId('deleteyesbtn'));
-
- await waitFor(() => {
- expect(fundProps.refetchFunds).toHaveBeenCalled();
- expect(fundProps.hide).toHaveBeenCalled();
- expect(toast.success).toHaveBeenCalledWith(translations.fundDeleted);
- });
- });
-
- it('should fail to Delete Fund', async () => {
- renderFundDeleteModal(link2, fundProps);
- expect(screen.getByTestId('deleteFundCloseBtn')).toBeInTheDocument();
-
- fireEvent.click(screen.getByTestId('deleteyesbtn'));
-
- await waitFor(() => {
- expect(toast.error).toHaveBeenCalledWith('Mock graphql error');
- });
- });
-});
diff --git a/src/screens/OrganizationFunds/FundDeleteModal.tsx b/src/screens/OrganizationFunds/FundDeleteModal.tsx
deleted file mode 100644
index bca92614ca..0000000000
--- a/src/screens/OrganizationFunds/FundDeleteModal.tsx
+++ /dev/null
@@ -1,100 +0,0 @@
-import React from 'react';
-import { useTranslation } from 'react-i18next';
-import type { InterfaceFundInfo } from 'utils/interfaces';
-import styles from './OrganizationFunds.module.css';
-import { Button, Modal } from 'react-bootstrap';
-import { REMOVE_FUND_MUTATION } from 'GraphQl/Mutations/FundMutation';
-import { useMutation } from '@apollo/client';
-import { toast } from 'react-toastify';
-
-export interface InterfaceDeleteFundModal {
- isOpen: boolean;
- hide: () => void;
- fund: InterfaceFundInfo | null;
- refetchFunds: () => void;
-}
-/**
- * `FundDeleteModal` component provides a modal dialog for confirming the deletion of a fund.
- * It prompts the user to confirm or cancel the deletion of a specific fund.
- *
- * ### Props
- * - `isOpen`: A boolean indicating whether the modal is open or closed.
- * - `hide`: A function to close the modal.
- * - `fund`: The fund object to be deleted or `null` if no fund is selected.
- * - `refetchFunds`: A function to refetch the list of funds after a successful deletion.
- *
- * ### Methods
- * - `deleteFundHandler()`: Asynchronously handles the deletion of the fund using the `REMOVE_FUND_MUTATION` mutation.
- * - `onClose()`: Closes the modal without deleting the fund.
- *
- * ### Behavior
- * - Displays a confirmation modal when `isOpen` is `true`.
- * - On confirmation, it triggers the `deleteFundHandler` to perform the deletion.
- * - On successful deletion, it calls `refetchFunds`, hides the modal, and shows a success toast notification.
- * - On failure, it shows an error toast notification.
- *
- * @returns The rendered modal dialog.
- */
-const FundDeleteModal: React.FC = ({
- isOpen,
- hide,
- fund,
- refetchFunds,
-}) => {
- const { t } = useTranslation('translation', {
- keyPrefix: 'funds',
- });
- const { t: tCommon } = useTranslation('common');
-
- const [deleteFund] = useMutation(REMOVE_FUND_MUTATION);
-
- const deleteFundHandler = async (): Promise => {
- try {
- await deleteFund({
- variables: {
- id: fund?._id,
- },
- });
- refetchFunds();
- hide();
- toast.success(t('fundDeleted'));
- } catch (error: unknown) {
- toast.error((error as Error).message);
- }
- };
-
- return (
- <>
-
-
- {t('fundDelete')}
-
-
-
- {t('deleteFundMsg')}
-
-
-
-
-
-
- >
- );
-};
-
-export default FundDeleteModal;
diff --git a/src/screens/OrganizationFunds/FundModal.tsx b/src/screens/OrganizationFunds/FundModal.tsx
index d347d02111..0f112cba9b 100644
--- a/src/screens/OrganizationFunds/FundModal.tsx
+++ b/src/screens/OrganizationFunds/FundModal.tsx
@@ -107,7 +107,7 @@ const FundModal: React.FC = ({
taxDeductible: false,
isArchived: false,
});
- toast.success(t('fundCreated'));
+ toast.success(t('fundCreated') as string);
refetchFunds();
hide();
} catch (error: unknown) {
@@ -155,7 +155,7 @@ const FundModal: React.FC = ({
});
refetchFunds();
hide();
- toast.success(t('fundUpdated'));
+ toast.success(t('fundUpdated') as string);
} catch (error: unknown) {
if (error instanceof Error) {
toast.error(error.message);
diff --git a/src/screens/OrganizationFunds/OrganizationFunds.test.tsx b/src/screens/OrganizationFunds/OrganizationFunds.test.tsx
index a1b49e68eb..c6983e1d6d 100644
--- a/src/screens/OrganizationFunds/OrganizationFunds.test.tsx
+++ b/src/screens/OrganizationFunds/OrganizationFunds.test.tsx
@@ -149,22 +149,6 @@ describe('OrganizationFunds Screen =>', () => {
);
});
- it('open and closes delete fund modal', async () => {
- renderOrganizationFunds(link1);
-
- const deleteFundBtn = await screen.findAllByTestId('deleteFundBtn');
- await waitFor(() => expect(deleteFundBtn[0]).toBeInTheDocument());
- userEvent.click(deleteFundBtn[0]);
-
- await waitFor(() =>
- expect(screen.getByText(translations.fundDelete)).toBeInTheDocument(),
- );
- userEvent.click(screen.getByTestId('deleteFundCloseBtn'));
- await waitFor(() =>
- expect(screen.queryByTestId('deleteFundCloseBtn')).toBeNull(),
- );
- });
-
it('Search the Funds list by name', async () => {
renderOrganizationFunds(link1);
const searchField = await screen.findByTestId('searchByName');
diff --git a/src/screens/OrganizationFunds/OrganizationFunds.tsx b/src/screens/OrganizationFunds/OrganizationFunds.tsx
index 56ed17b377..29ffb0d865 100644
--- a/src/screens/OrganizationFunds/OrganizationFunds.tsx
+++ b/src/screens/OrganizationFunds/OrganizationFunds.tsx
@@ -13,7 +13,6 @@ import React, { useCallback, useMemo, useState } from 'react';
import dayjs from 'dayjs';
import Loader from 'components/Loader/Loader';
import FundModal from './FundModal';
-import FundDeleteModal from './FundDeleteModal';
import { FUND_LIST } from 'GraphQl/Queries/fundQueries';
import styles from './OrganizationFunds.module.css';
import type { InterfaceFundInfo } from 'utils/interfaces';
@@ -39,24 +38,20 @@ const dataGridStyle = {
},
};
-enum ModalState {
- SAME = 'same',
- DELETE = 'delete',
-}
/**
* `organizationFunds` component displays a list of funds for a specific organization,
- * allowing users to search, sort, view, edit, and delete funds.
+ * allowing users to search, sort, view and edit funds.
*
* This component utilizes the `DataGrid` from Material-UI to present the list of funds in a tabular format,
* and includes functionality for filtering and sorting. It also handles the opening and closing of modals
- * for creating, editing, and deleting funds.
+ * for creating and editing.
*
* It includes:
* - A search input field to filter funds by name.
* - A dropdown menu to sort funds by creation date.
* - A button to create a new fund.
* - A table to display the list of funds with columns for fund details and actions.
- * - Modals for creating, editing, and deleting funds.
+ * - Modals for creating and editing funds.
*
* ### GraphQL Queries
* - `FUND_LIST`: Fetches a list of funds for the given organization, filtered and sorted based on the provided parameters.
@@ -68,14 +63,11 @@ enum ModalState {
* - `fund`: The currently selected fund for editing or deletion.
* - `searchTerm`: The current search term used for filtering funds.
* - `sortBy`: The current sorting order for funds.
- * - `modalState`: The state of the modals (edit/create or delete).
+ * - `modalState`: The state of the modals (edit/create).
* - `fundModalMode`: The mode of the fund modal (edit or create).
*
* ### Methods
- * - `openModal(modal: ModalState)`: Opens the specified modal.
- * - `closeModal(modal: ModalState)`: Closes the specified modal.
* - `handleOpenModal(fund: InterfaceFundInfo | null, mode: 'edit' | 'create')`: Opens the fund modal with the given fund and mode.
- * - `handleDeleteClick(fund: InterfaceFundInfo)`: Opens the delete modal for the specified fund.
* - `handleClick(fundId: string)`: Navigates to the campaign page for the specified fund.
*
* @returns The rendered component.
@@ -99,29 +91,18 @@ const organizationFunds = (): JSX.Element => {
'createdAt_DESC',
);
- const [modalState, setModalState] = useState<{
- [key in ModalState]: boolean;
- }>({
- [ModalState.SAME]: false,
- [ModalState.DELETE]: false,
- });
+ const [modalState, setModalState] = useState(false);
const [fundModalMode, setFundModalMode] = useState<'edit' | 'create'>(
'create',
);
- const openModal = (modal: ModalState): void =>
- setModalState((prevState) => ({ ...prevState, [modal]: true }));
-
- const closeModal = (modal: ModalState): void =>
- setModalState((prevState) => ({ ...prevState, [modal]: false }));
-
const handleOpenModal = useCallback(
(fund: InterfaceFundInfo | null, mode: 'edit' | 'create'): void => {
setFund(fund);
setFundModalMode(mode);
- openModal(ModalState.SAME);
+ setModalState(true);
},
- [openModal],
+ [],
);
const {
@@ -144,14 +125,6 @@ const organizationFunds = (): JSX.Element => {
},
});
- const handleDeleteClick = useCallback(
- (fund: InterfaceFundInfo): void => {
- setFund(fund);
- openModal(ModalState.DELETE);
- },
- [openModal],
- );
-
const funds = useMemo(() => fundData?.fundsByOrganization ?? [], [fundData]);
const handleClick = (fundId: string): void => {
@@ -277,15 +250,6 @@ const organizationFunds = (): JSX.Element => {
>
-
>
);
},
@@ -405,20 +369,13 @@ const organizationFunds = (): JSX.Element => {
isRowSelectable={() => false}
/>
closeModal(ModalState.SAME)}
+ isOpen={modalState}
+ hide={() => setModalState(false)}
refetchFunds={refetchFunds}
fund={fund}
orgId={orgId}
mode={fundModalMode}
/>
-
- closeModal(ModalState.DELETE)}
- fund={fund}
- refetchFunds={refetchFunds}
- />
);
};
diff --git a/src/screens/OrganizationFunds/OrganizationFundsMocks.ts b/src/screens/OrganizationFunds/OrganizationFundsMocks.ts
index cd03dc7f31..81e5a0fb64 100644
--- a/src/screens/OrganizationFunds/OrganizationFundsMocks.ts
+++ b/src/screens/OrganizationFunds/OrganizationFundsMocks.ts
@@ -1,6 +1,5 @@
import {
CREATE_FUND_MUTATION,
- REMOVE_FUND_MUTATION,
UPDATE_FUND_MUTATION,
} from 'GraphQl/Mutations/FundMutation';
import { FUND_LIST } from 'GraphQl/Queries/fundQueries';
@@ -169,21 +168,6 @@ export const MOCKS = [
},
},
},
- {
- request: {
- query: REMOVE_FUND_MUTATION,
- variables: {
- id: 'fundId',
- },
- },
- result: {
- data: {
- removeFund: {
- _id: 'fundId',
- },
- },
- },
- },
];
export const NO_FUNDS = [
@@ -230,15 +214,6 @@ export const MOCKS_ERROR = [
},
error: new Error('Mock graphql error'),
},
- {
- request: {
- query: REMOVE_FUND_MUTATION,
- variables: {
- id: 'fundId',
- },
- },
- error: new Error('Mock graphql error'),
- },
{
request: {
query: UPDATE_FUND_MUTATION,
diff --git a/src/screens/OrganizationPeople/AddMember.tsx b/src/screens/OrganizationPeople/AddMember.tsx
index 7a780b9f7c..ff5811b519 100644
--- a/src/screens/OrganizationPeople/AddMember.tsx
+++ b/src/screens/OrganizationPeople/AddMember.tsx
@@ -32,6 +32,7 @@ import type {
InterfaceQueryUserListItem,
} from 'utils/interfaces';
import styles from './OrganizationPeople.module.css';
+import Avatar from 'components/Avatar/Avatar';
const StyledTableCell = styled(TableCell)(({ theme }) => ({
[`&.${tableCellClasses.head}`]: {
@@ -107,7 +108,7 @@ function AddMember(): JSX.Element {
orgid: currentUrl,
},
});
- toast.success(tCommon('addedSuccessfully', { item: 'Member' }));
+ toast.success(tCommon('addedSuccessfully', { item: 'Member' }) as string);
memberRefetch({
orgId: currentUrl,
});
@@ -199,11 +200,11 @@ function AddMember(): JSX.Element {
createUserVariables.lastName
)
) {
- toast.error(translateOrgPeople('invalidDetailsMessage'));
+ toast.error(translateOrgPeople('invalidDetailsMessage') as string);
} else if (
createUserVariables.password !== createUserVariables.confirmPassword
) {
- toast.error(translateOrgPeople('passwordNotMatch'));
+ toast.error(translateOrgPeople('passwordNotMatch') as string);
} else {
try {
const registeredUser = await registerMutation({
@@ -372,6 +373,9 @@ function AddMember(): JSX.Element {