Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,31 @@

# Interface: InterfaceGroupModal

Defined in: [src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx:62](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx#L62)
Defined in: [src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx:63](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx#L63)

## Properties

### eventId

> **eventId**: `string`

Defined in: [src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx:65](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx#L65)
Defined in: [src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx:66](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx#L66)

***

### group

> **group**: [`InterfaceVolunteerGroupInfo`](../../../../../../utils/interfaces/interfaces/InterfaceVolunteerGroupInfo.md)

Defined in: [src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx:66](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx#L66)
Defined in: [src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx:67](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx#L67)

***

### hide()

> **hide**: () => `void`

Defined in: [src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx:64](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx#L64)
Defined in: [src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx:65](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx#L65)

#### Returns

Expand All @@ -40,15 +40,15 @@ Defined in: [src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx:64](https://

> **isOpen**: `boolean`

Defined in: [src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx:63](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx#L63)
Defined in: [src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx:64](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx#L64)

***

### refetchGroups()

> **refetchGroups**: () => `void`

Defined in: [src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx:67](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx#L67)
Defined in: [src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx:68](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx#L68)

#### Returns

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@

> `const` **default**: `React.FC`\<[`InterfaceGroupModal`](../interfaces/InterfaceGroupModal.md)\>

Defined in: [src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx:70](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx#L70)
Defined in: [src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx:71](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx#L71)
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

> **default**(`__namedParameters`): `ReactElement`\<`unknown`, `string` \| `JSXElementConstructor`\<`any`\>\>

Defined in: [src/shared-components/SidebarOrgSection/SidebarOrgSection.tsx:60](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/shared-components/SidebarOrgSection/SidebarOrgSection.tsx#L60)
Defined in: [src/shared-components/SidebarOrgSection/SidebarOrgSection.tsx:56](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/shared-components/SidebarOrgSection/SidebarOrgSection.tsx#L56)

## Parameters

Expand Down
56 changes: 21 additions & 35 deletions src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
* Success or error messages are displayed using toast notifications based on the result of the mutation.
*/
import type { ChangeEvent } from 'react';
import { Button, Form, Modal } from 'react-bootstrap';
import { Button, Form } from 'react-bootstrap';
import type {
InterfaceCreateVolunteerGroup,
InterfaceVolunteerGroupInfo,
Expand Down Expand Up @@ -56,8 +56,9 @@ import {
import { PiUserListBold } from 'react-icons/pi';
import { TbListDetails } from 'react-icons/tb';
import { USER_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Queries/EventVolunteerQueries';
import Avatar from 'components/Avatar/Avatar';
import { FaXmark } from 'react-icons/fa6';
import { ProfileAvatarDisplay } from 'shared-components/ProfileAvatarDisplay/ProfileAvatarDisplay';
import BaseModal from 'shared-components/BaseModal/BaseModal';

export interface InterfaceGroupModal {
isOpen: boolean;
Expand Down Expand Up @@ -187,19 +188,14 @@ const GroupModal: React.FC<InterfaceGroupModal> = ({
);

return (
<Modal className={styles.groupModal} onHide={hide} show={isOpen}>
<Modal.Header>
<p className={styles.titlemodal}>{t('manageGroup')}</p>
<Button
variant="danger"
onClick={hide}
className={styles.modalCloseBtn}
data-testid="modalCloseBtn"
>
<i className="fa fa-times"></i>
</Button>
</Modal.Header>
<Modal.Body>
<BaseModal
className={styles.groupModal}
show={isOpen}
onHide={hide}
title={t('manageGroup')}
data-testid="groupModal"
>
Comment on lines +191 to +197
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

❌ Fix incorrect prop name: data-testiddataTestId.

Line 196 uses data-testid but BaseModal expects dataTestId (camelCase) per its interface definition. This will cause a TypeScript error.

🔧 Proposed fix
     <BaseModal
       className={styles.groupModal}
       show={isOpen}
       onHide={hide}
       title={t('manageGroup')}
-      data-testid="groupModal"
+      dataTestId="groupModal"
     >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<BaseModal
className={styles.groupModal}
show={isOpen}
onHide={hide}
title={t('manageGroup')}
data-testid="groupModal"
>
<BaseModal
className={styles.groupModal}
show={isOpen}
onHide={hide}
title={t('manageGroup')}
dataTestId="groupModal"
>
🤖 Prompt for AI Agents
In @src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx around lines 191 -
197, The BaseModal usage passes a hyphenated prop name `data-testid` which
doesn’t match the component’s TypeScript interface; change the prop to camelCase
`dataTestId` on the BaseModal element (the instance that sets
className={styles.groupModal}, show={isOpen}, onHide={hide},
title={t('manageGroup')}) so it conforms to BaseModal’s expected prop name and
resolves the type error.

<>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Remove unnecessary fragment wrapper.

The <> and </> wrappers around the modal content (lines 198, 393) are unnecessary since BaseModal accepts children directly without requiring a fragment. Removing them will simplify the code structure.

♻️ Proposed refactor
     <BaseModal
       className={styles.groupModal}
       show={isOpen}
       onHide={hide}
       title={t('manageGroup')}
       dataTestId="groupModal"
     >
-      <>
         <div
           className={`btn-group ${styles.toggleGroup} mt-0 px-3 mb-4 w-100`}
           role="group"
         >
           {/* ...rest of content... */}
         </div>
-      </>
     </BaseModal>

Also applies to: 393-393

🤖 Prompt for AI Agents
In @src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx at line 198, In
GroupModal, remove the unnecessary React fragment tokens ("<>" and "</>")
wrapping the modal children passed into BaseModal—locate the fragment around the
modal content inside the GroupModal component (surrounding the BaseModal
children) and delete both the opening and closing fragment so BaseModal receives
its children directly; ensure the remaining JSX stays valid and that no other
wrapper is required for multiple sibling elements.

<div
className={`btn-group ${styles.toggleGroup} mt-0 px-3 mb-4 w-100`}
role="group"
Expand Down Expand Up @@ -349,24 +345,14 @@ const GroupModal: React.FC<InterfaceGroupModal> = ({
className="d-flex gap-1 align-items-center"
data-testid="userName"
>
{avatarURL ? (
<img
src={avatarURL}
alt={t('volunteerAlt')}
data-testid={`image${id + 1}`}
className={styles.TableImage}
/>
) : (
<div className={styles.avatarContainer}>
<Avatar
key={id + '1'}
containerStyle={styles.imageContainer}
avatarStyle={styles.TableImage}
name={name}
alt={name}
/>
</div>
)}
<ProfileAvatarDisplay
key={id + '1'}
imageUrl={avatarURL}
fallbackName={t('volunteerAlt')}
data-testid={`image${id + 1}`}
className={styles.TableImage}
/>

{name}
</TableCell>
<TableCell component="th" scope="row">
Expand Down Expand Up @@ -404,8 +390,8 @@ const GroupModal: React.FC<InterfaceGroupModal> = ({
)}
</div>
)}
</Modal.Body>
</Modal>
</>
</BaseModal>
);
};
export default GroupModal;
19 changes: 19 additions & 0 deletions src/shared-components/OrganizationCard/OrganizationCard.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ vi.mock('react-i18next', () => ({
'users.membershipStatus.member': 'Membership status: Member',
'users.membershipStatus.pending': 'Membership status: Pending',
'users.membershipStatus.notMember': 'Membership status: Not a member',
'profileAvatar.altText': 'Test Org',
};

return translations[key] || key;
Expand Down Expand Up @@ -361,6 +362,15 @@ describe('OrganizationCard', () => {
},
},
},
{
request: {
query: ORGANIZATION_LIST,
variables: {},
},
result: {
data: {},
},
},
];

render(
Expand Down Expand Up @@ -574,6 +584,15 @@ describe('OrganizationCard', () => {
},
},
},
{
request: {
query: ORGANIZATION_LIST,
variables: {},
},
result: {
data: {},
},
},
];

render(
Expand Down
24 changes: 7 additions & 17 deletions src/shared-components/OrganizationCard/OrganizationCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ import Button from 'react-bootstrap/Button';
import { useTranslation } from 'react-i18next';
import styles from 'style/app-fixed.module.css';
import { Tooltip } from '@mui/material';
import Avatar from 'components/Avatar/Avatar';
import { useNavigate } from 'react-router-dom';
import { InterfaceOrganizationCardProps } from 'types/OrganizationCard/interface';
import { ApolloError, useMutation } from '@apollo/client';
Expand All @@ -56,6 +55,7 @@ import { ORGANIZATION_LIST } from 'GraphQl/Queries/Queries';
import { USER_JOINED_ORGANIZATIONS_PG } from 'GraphQl/Queries/OrganizationQueries';
import { NotificationToast } from 'components/NotificationToast/NotificationToast';
import useLocalStorage from 'utils/useLocalstorage';
import { ProfileAvatarDisplay } from 'shared-components/ProfileAvatarDisplay/ProfileAvatarDisplay';

export interface InterfaceOrganizationCardPropsPG {
data: InterfaceOrganizationCardProps;
Expand Down Expand Up @@ -171,22 +171,12 @@ function OrganizationCard({
<div className={styles.innerContainer} data-cy="orgCardContainer">
{/* Container for the organization image */}
<div className={styles.orgImgContainer}>
{avatarURL ? (
<img
src={avatarURL}
alt={name}
crossOrigin="anonymous"
referrerPolicy="no-referrer"
loading="lazy"
decoding="async"
/>
) : (
<Avatar
name={name}
alt={name}
dataTestId="emptyContainerForImage"
/>
)}
<ProfileAvatarDisplay
fallbackName={name}
imageUrl={avatarURL}
dataTestId="emptyContainerForImage"
enableEnlarge
/>
</div>
<div className={styles.content}>
<div>
Expand Down
58 changes: 43 additions & 15 deletions src/shared-components/SidebarOrgSection/SidebarOrgSection.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,41 @@ vi.mock('assets/svgs/angleRight.svg?react', () => ({
),
}));

// Mock ProfileAvatarDisplay
vi.mock('shared-components/ProfileAvatarDisplay/ProfileAvatarDisplay', () => ({
ProfileAvatarDisplay: ({
imageUrl,
fallbackName,
crossOrigin,
}: {
imageUrl?: string;
fallbackName: string;
crossOrigin?: 'anonymous' | 'use-credentials' | '';
}) => (
<div
data-testid="mock-profile-avatar-display"
data-image-url={imageUrl}
data-fallback-name={fallbackName}
>
{imageUrl && (
<img src={imageUrl} alt={fallbackName} crossOrigin={crossOrigin} />
)}
</div>
),
}));

// Mock translations
vi.mock('react-i18next', async () => {
const actual = await vi.importActual('react-i18next');
return {
...actual,
useTranslation: () => ({
t: (key: string, options?: { entity?: string }) =>
options?.entity ? `Error loading ${options.entity}` : key,
t: (key: string, options?: { entity?: string; name?: string }) => {
if (key === 'profileAvatar.altText') {
return options?.name || 'Avatar';
}
return options?.entity ? `Error loading ${options.entity}` : key;
},
}),
};
});
Expand Down Expand Up @@ -89,7 +116,7 @@ describe('SidebarOrgSection Component', () => {
{
request: {
query: GET_ORGANIZATION_DATA_PG,
variables: { id: mockOrgId, first: 10, after: null },
variables: { id: mockOrgId, first: 1, after: null },
},
result: {
data: mockOrganizationData,
Expand All @@ -101,7 +128,7 @@ describe('SidebarOrgSection Component', () => {
{
request: {
query: GET_ORGANIZATION_DATA_PG,
variables: { id: mockOrgId, first: 10, after: null },
variables: { id: mockOrgId, first: 1, after: null },
},
delay: 1000000, // Very long delay to keep in loading state
result: {
Expand All @@ -114,7 +141,7 @@ describe('SidebarOrgSection Component', () => {
{
request: {
query: GET_ORGANIZATION_DATA_PG,
variables: { id: mockOrgId, first: 10, after: null },
variables: { id: mockOrgId, first: 1, after: null },
},
result: {
data: { organization: null },
Expand All @@ -126,7 +153,7 @@ describe('SidebarOrgSection Component', () => {
{
request: {
query: GET_ORGANIZATION_DATA_PG,
variables: { id: mockOrgId, first: 10, after: null },
variables: { id: mockOrgId, first: 1, after: null },
},
result: {
data: mockOrganizationWithoutAvatar,
Expand All @@ -138,7 +165,7 @@ describe('SidebarOrgSection Component', () => {
{
request: {
query: GET_ORGANIZATION_DATA_PG,
variables: { id: mockOrgId, first: 10, after: null },
variables: { id: mockOrgId, first: 1, after: null },
},
result: {
data: mockOrganizationWithoutCity,
Expand Down Expand Up @@ -268,18 +295,19 @@ describe('SidebarOrgSection Component', () => {
await waitFor(() => {
const img = screen.getByAltText('Test Organization');
expect(img).toHaveAttribute('crossOrigin', 'anonymous');
expect(img).toHaveAttribute('referrerPolicy', 'no-referrer');
expect(img).toHaveAttribute('loading', 'lazy');
expect(img).toHaveAttribute('decoding', 'async');
});
});

it('renders Avatar component when avatarURL is not provided', async () => {
it('renders ProfileAvatarDisplay with correct props when avatarURL is not provided', async () => {
renderComponent({}, noAvatarMocks);
await waitFor(() => {
const avatar = screen.getByTestId('avatar');
expect(avatar).toBeInTheDocument();
expect(avatar).toHaveAttribute('data-name', 'Test Organization');
const avatarDisplay = screen.getByTestId('mock-profile-avatar-display');
expect(avatarDisplay).toBeInTheDocument();
expect(avatarDisplay).toHaveAttribute(
'data-fallback-name',
'Test Organization',
);
expect(avatarDisplay).not.toHaveAttribute('data-image-url');
});
});

Expand Down Expand Up @@ -315,7 +343,7 @@ describe('SidebarOrgSection Component', () => {
{
request: {
query: GET_ORGANIZATION_DATA_PG,
variables: { id: customOrgId, first: 10, after: null },
variables: { id: customOrgId, first: 1, after: null },
},
result: {
data: mockOrganizationData,
Expand Down
Loading
Loading