Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge from develop-postgres prior to code freeze #3234

Merged
merged 2 commits into from
Jan 10, 2025

Conversation

palisadoes
Copy link
Contributor

@palisadoes palisadoes commented Jan 10, 2025

Merge from develop-postgres prior to code freeze

Summary by CodeRabbit

Based on the comprehensive summary of changes, here are the high-level release notes:

Release Notes for Talawa Admin

New Features

  • Added chat functionality with localized titles in multiple languages
  • Introduced a new SortingButton component to replace dropdowns across various screens
  • Enhanced user interface with improved sorting and filtering options
  • Added localization support for chat titles in English, French, Hindi, Spanish, and Chinese

Improvements

  • Streamlined sorting and filtering mechanisms in multiple components
  • Updated test suites to use Vitest testing framework
  • Improved responsive image sizing in user interfaces
  • Enhanced error handling in various components

Bug Fixes

  • Fixed minor typos in comments and documentation
  • Corrected test identifiers for more consistent testing

Performance

  • Simplified component logic by consolidating dropdown functionalities
  • Improved code maintainability through modular component design

Testing

  • Migrated from Jest to Vitest for more robust testing
  • Added comprehensive test coverage for new and existing features

Localization

  • Added chat title translations for multiple languages
  • Maintained support for existing multi-language interfaces

Chores

  • Removed deprecated code and comments
  • Updated import statements and removed unused dependencies

@palisadoes palisadoes added the ignore-sensitive-files-pr The contributor has a legitimate reason for editiing protected files label Jan 10, 2025
Copy link
Contributor

coderabbitai bot commented Jan 10, 2025

Walkthrough

This pull request introduces a comprehensive set of changes across the Talawa Admin project, focusing on refactoring UI components, improving test configurations, and enhancing localization. The primary modifications include replacing dropdown components with a new SortingButton, migrating test suites from Jest to Vitest, updating localization files, and making minor adjustments to various components' styling and functionality.

Changes

File/Group Change Summary
.husky/pre-commit Removed shebang line and Husky script initialization
jest.config.js Reduced coverage threshold from 20% to 1% for lines and statements
package.json Updated prepare script from husky install to husky
public/locales/**/translation.json Added "title": "Chats" to userChat section in multiple language files
setup.ts Enhanced setup process with modular functions and improved error handling
src/assets/css/app.css Updated button hover effects and added new CSS properties
Multiple Components Replaced Dropdown components with new SortingButton
Test Files Migrated from Jest to Vitest in multiple test suites

Sequence Diagram

sequenceDiagram
    participant User
    participant SortingButton
    participant Component
    participant State

    User->>SortingButton: Click to open options
    SortingButton->>User: Display sorting/filtering options
    User->>SortingButton: Select an option
    SortingButton->>Component: Trigger onSortChange
    Component->>State: Update state with selected option
    State-->>Component: Reflect new state
    Component->>User: Update UI based on new state
Loading

Possibly related issues

Possibly related PRs

Poem

🐰 Hopping through code with glee,
Dropdowns vanish, buttons set free!
SortingButton dances with grace,
Tests migrate at lightning pace.
A rabbit's refactor, clean and bright! 🌟

Finishing Touches

  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

Our Pull Request Approval Process

Thanks for contributing!

Testing Your Code

Remember, your PRs won't be reviewed until these criteria are met:

  1. We don't merge PRs with poor code quality.
    1. Follow coding best practices such that CodeRabbit.ai approves your PR.
  2. We don't merge PRs with failed tests.
    1. When tests fail, click on the Details link to learn more.
    2. Write sufficient tests for your changes (CodeCov Patch Test). Your testing level must be better than the target threshold of the repository
    3. Tests may fail if you edit sensitive files. Ask to add the ignore-sensitive-files-pr label if the edits are necessary.
  3. We cannot merge PRs with conflicting files. These must be fixed.

Our policies make our code better.

Reviewers

Do not assign reviewers. Our Queue Monitors will review your PR and assign them.
When your PR has been assigned reviewers contact them to get your code reviewed and approved via:

  1. comments in this PR or
  2. our slack channel

Reviewing Your Code

Your reviewer(s) will have the following roles:

  1. arbitrators of future discussions with other contributors about the validity of your changes
  2. point of contact for evaluating the validity of your work
  3. person who verifies matching issues by others that should be closed.
  4. person who gives general guidance in fixing your tests

CONTRIBUTING.md

Read our CONTRIBUTING.md file. Most importantly:

  1. PRs with issues not assigned to you will be closed by the reviewer
  2. Fix the first comment in the PR so that each issue listed automatically closes

Other

  1. 🎯 Please be considerate of our volunteers' time. Contacting the person who assigned the reviewers is not advised unless they ask for your input. Do not @ the person who did the assignment otherwise.
  2. Read the CONTRIBUTING.md file make

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 13

🔭 Outside diff range comments (2)
src/components/EventListCard/EventListCard.tsx (2)

Line range hint 36-36: Rename component to follow React naming convention

React components should use PascalCase naming convention. Rename eventListCard to EventListCard.

-function eventListCard(props: InterfaceEventListCardProps): JSX.Element {
+function EventListCard(props: InterfaceEventListCardProps): JSX.Element {

Line range hint 77-82: Improve accessibility for clickable card

The div element is being used as a clickable component but lacks proper accessibility support. Consider the following improvements:

  • Use a button element or add proper ARIA attributes
  • Add keyboard interaction support
 <div
   className={styles.cardsEventListCard}
   onClick={showViewModal}
+  role="button"
+  tabIndex={0}
+  onKeyDown={(e) => e.key === 'Enter' && showViewModal()}
   data-testid="card"
 >
🧹 Nitpick comments (50)
src/components/Venues/VenueModal.spec.tsx (3)

297-336: Consider enhancing error scenario coverage

The test effectively verifies the error toast, but could be strengthened by:

  • Verifying form state remains unchanged after error
  • Asserting that the venue creation wasn't completed
   await wait();

   expect(toast.error).toHaveBeenCalledWith('Failed to create venue');
+  // Verify form state persists
+  expect(screen.getByDisplayValue('Error Venue')).toBeInTheDocument();
+  expect(screen.getByDisplayValue('This should fail')).toBeInTheDocument();
+  expect(screen.getByDisplayValue('50')).toBeInTheDocument();
+
+  // Verify refetch wasn't called
+  expect(props[0].refetchVenues).not.toHaveBeenCalled();

338-378: Enhance update error scenario coverage

The test effectively verifies the error toast, but could be strengthened by:

  • Verifying form state remains unchanged after error
  • Asserting that the modal stays open
  • Verifying the venue update wasn't completed
   await wait();

   expect(toast.error).toHaveBeenCalledWith('Failed to update venue');
+  // Verify form state persists
+  expect(screen.getByDisplayValue('Failed Update Venue')).toBeInTheDocument();
+  expect(screen.getByDisplayValue('Failed update description')).toBeInTheDocument();
+  expect(screen.getByDisplayValue('150')).toBeInTheDocument();
+
+  // Verify modal remains open
+  expect(screen.getByTestId('updateVenueBtn')).toBeInTheDocument();
+
+  // Verify refetch wasn't called
+  expect(props[1].refetchVenues).not.toHaveBeenCalled();

295-379: Consider organizing test suites by functionality

The test organization is good, but could be improved by grouping related tests together. Consider restructuring the test suites to group creation and update tests separately:

describe('VenueModal', () => {
  describe('Venue Creation', () => {
    test('creates venue successfully', ...);
    test('displays error when creation fails', ...);
  });

  describe('Venue Update', () => {
    test('updates venue successfully', ...);
    test('displays error when update fails', ...);
  });

  describe('Form Validation', () => {
    test('shows error when venue name is empty', ...);
    test('shows error when capacity is not positive', ...);
  });
});
src/screens/UserPortal/Settings/Settings.spec.tsx (3)

127-185: Consider adding edge cases to mock data.

The mock data covers basic success and error scenarios, but consider adding tests for:

  • Empty/null values
  • Special characters in names
  • International phone number formats
  • Maximum length validation

524-559: Enhance success test case assertions.

While the test verifies basic functionality, consider adding assertions for:

  • All form field values post-update
  • Loading state during update
  • Disabled state of the save button during submission
 expect(lastNameInput).toHaveValue('randomUpdated');
 expect(toastSuccessSpy).toHaveBeenCalledWith('Profile updated Successfully');
+expect(saveButton).toBeEnabled();
+expect(screen.queryByRole('progressbar')).not.toBeInTheDocument();
+expect(screen.getByTestId('inputFirstName')).toHaveValue('John');
+expect(screen.getByTestId('inputPhoneNumber')).toHaveValue('+174567890');

561-598: Add timeout handling to error test case.

The error test should verify timeout scenarios and loading states.

 expect(errorHandler).toHaveBeenCalled();
+// Verify loading state
+expect(saveButton).toBeDisabled();
+expect(screen.getByRole('progressbar')).toBeInTheDocument();
+
+// Verify timeout scenario
+await act(async () => {
+  vi.advanceTimersByTime(30000); // Simulate timeout
+});
+expect(errorHandler).toHaveBeenCalledWith(expect.any(Error));
src/components/OrgListCard/TruncatedText.tsx (3)

51-54: Document the character width calculation formula

The character width calculation uses magic numbers without explanation. This makes it difficult to understand or adjust the formula if needed.

Add comments explaining the formula or extract it to a documented constant:

-      const charPerPx = 0.065 + fontSize * 0.002;
+      // Base character width ratio (0.065) plus font size adjustment factor (0.002)
+      // These values were determined empirically for the current font family
+      const BASE_CHAR_WIDTH_RATIO = 0.065;
+      const FONT_SIZE_ADJUSTMENT_FACTOR = 0.002;
+      const charPerPx = BASE_CHAR_WIDTH_RATIO + fontSize * FONT_SIZE_ADJUSTMENT_FACTOR;

73-77: Add title attribute for accessibility

The truncated text should have a title attribute to show the full text on hover, improving accessibility.

   return (
-    <h6 ref={textRef} className="text-secondary">
+    <h6 ref={textRef} className="text-secondary" title={text}>
       {truncatedText}
     </h6>
   );

38-40: Consider increasing debounce delay

A 100ms debounce might be too aggressive for resize events, potentially causing unnecessary recalculations.

Consider increasing the delay to 250-300ms for better performance:

   const { debouncedCallback, cancel } = useDebounce(() => {
     truncateText();
-  }, 100);
+  }, 250);
setup.ts (3)

12-42: Refine Error Handling in askAndSetRecaptcha

In the askAndSetRecaptcha function, consider enhancing error feedback to the user. Currently, in the validation function at line 27, invalid input returns a generic error message. Providing more specific guidance on why the input was invalid can improve user experience.


55-57: Ensure Consistent Environment Variable Settings

In askAndSetLogErrors, when the user opts not to log errors, the ALLOW_LOGS environment variable is not updated. To maintain consistency, consider explicitly setting ALLOW_LOGS to 'NO' when the user selects this option.

Apply this diff to address the issue:

       updateEnvFile('ALLOW_LOGS', 'YES');
+    } else {
+      updateEnvFile('ALLOW_LOGS', 'NO');
     }

66-68: Avoid Reading .env Immediately After Modification

After calling askAndSetDockerOption(), which may modify the .env file, reading it again at lines 66-68 can lead to race conditions or stale data. Consider using the value directly returned from askAndSetDockerOption() to determine if Docker is used, or ensure that file writes are completed before reading.

src/setup/askAndUpdatePort/askAndUpdatePort.ts (1)

17-19: Consolidate Port Validation Logic

The port validation at lines 17-19 could be centralized within the askForCustomPort() function. This promotes reusability and ensures consistent validation wherever custom ports are requested.

src/setup/askAndSetDockerOption/askAndSetDockerOption.ts (1)

23-28: Enhance Docker Command Instructions for Users

The Docker command instructions could be formatted more clearly to improve readability. Removing unnecessary whitespace and aligning the text can help users follow the steps without confusion.

Apply this diff to improve the console output:

 console.log(`
-        
-          Run the commands below after setup:-
-                1. docker build -t ${DOCKER_NAME} .
-                2. docker run -d -p ${DOCKER_PORT_NUMBER}:${DOCKER_PORT_NUMBER} ${DOCKER_NAME}
-                
+        Run the commands below after setup:
+          1. docker build -t ${DOCKER_NAME} .
+          2. docker run -d -p ${DOCKER_PORT_NUMBER}:${DOCKER_PORT_NUMBER} ${DOCKER_NAME}
    `);
src/setup/askAndUpdatePort/askForUpdatePort.spec.ts (2)

16-28: Consider adding port range validation test cases.

While the test for invalid port (800) is good, consider adding edge cases:

  • Port exactly at 1024 (lower bound)
  • Port exactly at 65535 (upper bound)
  • Port just below 1024
  • Port just above 65535
it('should accept port at lower bound (1024)', async () => {
  vi.mocked(inquirer.prompt).mockResolvedValueOnce({
    shouldSetCustomPortResponse: true,
  });
  vi.mocked(askForCustomPort).mockResolvedValueOnce(1024);

  await askAndUpdatePort();
  expect(updateEnvFile).toHaveBeenCalledWith('PORT', '1024');
});

it('should accept port at upper bound (65535)', async () => {
  vi.mocked(inquirer.prompt).mockResolvedValueOnce({
    shouldSetCustomPortResponse: true,
  });
  vi.mocked(askForCustomPort).mockResolvedValueOnce(65535);

  await askAndUpdatePort();
  expect(updateEnvFile).toHaveBeenCalledWith('PORT', '65535');
});

43-54: Enhance error test coverage.

The error test case could be expanded to verify:

  1. Error message content matches exactly
  2. No calls to updateEnvFile are made when error occurs
it('should throw an error for an invalid port without updating env', async () => {
  vi.mocked(inquirer.prompt).mockResolvedValueOnce({
    shouldSetCustomPortResponse: true,
  });
  vi.mocked(askForCustomPort).mockResolvedValueOnce(800);

  await expect(askAndUpdatePort()).rejects.toThrowError(
    'Port must be between 1024 and 65535'
  );
  expect(updateEnvFile).not.toHaveBeenCalled();
});
src/setup/askAndSetDockerOption/askAndSetDockerOption.spec.ts (2)

51-60: Enhance error handling test coverage.

The error test should verify that no environment updates occur when an error is thrown.

it('should handle errors without updating environment', async () => {
  vi.mocked(inquirer.prompt).mockResolvedValueOnce({
    useDocker: true,
  });
  vi.mocked(askForDocker).mockRejectedValueOnce(
    new Error('Docker error')
  );

  await expect(askAndSetDockerOption()).rejects.toThrow('Docker error');
  expect(updateEnvFile).not.toHaveBeenCalled();
});

24-61: Add missing test scenarios.

Consider adding tests for:

  1. Invalid Docker port values
  2. Environment variable update failures
  3. Order of operations (USE_DOCKER should be set before DOCKER_PORT)

Example test case:

it('should set USE_DOCKER before DOCKER_PORT', async () => {
  vi.mocked(inquirer.prompt).mockResolvedValueOnce({
    useDocker: true,
  });
  vi.mocked(askForDocker).mockResolvedValueOnce(8080);
  
  const updates: string[] = [];
  vi.mocked(updateEnvFile).mockImplementation((key) => {
    updates.push(key);
    return Promise.resolve();
  });

  await askAndSetDockerOption();
  expect(updates[0]).toBe('USE_DOCKER');
  expect(updates[1]).toBe('DOCKER_PORT');
});
src/screens/OrgSettings/OrgSettings.tsx (1)

Line range hint 44-68: Consider enhancing mobile responsiveness

With the removal of the dropdown, consider adding responsive design improvements for the button-based navigation:

  1. Stack buttons vertically on smaller screens
  2. Add scrollable container for many categories
 <div className={styles.settingsTabs}>
+  <div className="d-flex flex-column flex-md-row overflow-auto">
   {settingtabs.map((setting, index) => (
     <Button
       key={index}
-      className={`me-3 border rounded-3 ${styles.headerBtn}`}
+      className={`me-md-3 mb-2 mb-md-0 border rounded-3 ${styles.headerBtn}`}
       variant={tab === setting ? `success` : `none`}
       onClick={() => setTab(setting)}
       data-testid={`${setting}Settings`}
     >
       {t(setting)}
     </Button>
   ))}
+  </div>
 </div>
src/components/EventManagement/EventAttendance/EventAttendance.spec.tsx (1)

106-114: Enhance sort functionality test coverage

The sort functionality test should verify multiple sorting scenarios and the complete sorted order, not just the first item.

Consider expanding the test:

  it('Sort functionality changes attendee order', async () => {
    renderEventAttendance();
    await wait();

    const sortDropdown = screen.getByTestId('sort-dropdown');
    userEvent.click(sortDropdown);
    const sortOption = screen.getByText('Ascending');
    userEvent.click(sortOption);

    await waitFor(() => {
-     const attendees = screen.getAllByTestId('attendee-name-0');
-     expect(attendees[0]).toHaveTextContent('Bruce Garza');
+     const attendees = screen.getAllByTestId(/attendee-name-/);
+     // Verify complete sorted order
+     expect(attendees[0]).toHaveTextContent('Bruce Garza');
+     expect(attendees[1]).toHaveTextContent('Jane Smith');
+     // Verify descending sort
+     userEvent.click(screen.getByText('Descending'));
+     expect(attendees[0]).toHaveTextContent('Jane Smith');
+     expect(attendees[1]).toHaveTextContent('Bruce Garza');
    });
  });
src/components/LeftDrawer/LeftDrawer.tsx (1)

Line range hint 26-26: Follow component naming convention

The component name should follow PascalCase convention.

- const leftDrawer = ({
+ const LeftDrawer = ({
src/screens/EventManagement/EventManagement.tsx (1)

270-272: Consider removing commented-out code.

The comment explains why the default case won't be reached, but keeping commented-out code can lead to confusion. Since the initial state ensures the code won't reach this point, it's better to remove the commented code entirely.

-          // no use of default here as the default tab is the dashboard selected in useState code wont reach here
-          // default:
-          //   return null;
src/screens/UserPortal/Volunteer/Groups/Groups.tsx (1)

315-324: Add missing title prop to SortingButton.

For consistency with other instances of SortingButton in the codebase, add the title prop.

 <SortingButton
+  title={tCommon('searchBy', { item: '' })}
   sortingOptions={[
     { label: t('leader'), value: 'leader' },
     { label: t('group'), value: 'group' },
   ]}
   selectedOption={searchBy}
   onSortChange={(value) => setSearchBy(value as 'leader' | 'group')}
   dataTestIdPrefix="searchByToggle"
   buttonLabel={tCommon('searchBy', { item: '' })}
 />
src/screens/FundCampaignPledge/FundCampaignPledge.spec.tsx (2)

23-33: Update mocking implementation for better maintainability.

The mocking implementation could be improved by using a more maintainable approach:

-vi.mock('react-toastify', () => ({
-  toast: {
-    success: vi.fn(),
-    error: vi.fn(),
-  },
-}));
+const mockToast = {
+  success: vi.fn(),
+  error: vi.fn(),
+};
+vi.mock('react-toastify', () => ({
+  toast: mockToast,
+}));

This change makes it easier to access and verify the mock functions in your tests.


44-47: Consider using a test helper for managing mock state.

The mock params state management could be encapsulated in a helper function for better reusability across tests.

+const DEFAULT_MOCK_PARAMS = {
+  orgId: 'orgId',
+  fundCampaignId: 'fundCampaignId',
+};
+
+const resetMockParams = () => {
+  mockParamsState.orgId = DEFAULT_MOCK_PARAMS.orgId;
+  mockParamsState.fundCampaignId = DEFAULT_MOCK_PARAMS.fundCampaignId;
+};

-const mockParamsState = {
-  orgId: 'orgId',
-  fundCampaignId: 'fundCampaignId',
-};
+const mockParamsState = { ...DEFAULT_MOCK_PARAMS };

 beforeEach(() => {
-  mockParamsState.orgId = 'orgId';
-  mockParamsState.fundCampaignId = 'fundCampaignId';
+  resetMockParams();
 });

Also applies to: 88-90

src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx (1)

335-347: Consider adding a default sort option.

The sort implementation could benefit from a default "None" option to allow users to view data in its original order.

 sortingOptions={[
+  { label: t('noSort'), value: null },
   { label: t('mostVolunteers'), value: 'volunteers_DESC' },
   { label: t('leastVolunteers'), value: 'volunteers_ASC' },
 ]}
src/components/EventManagement/EventAttendance/EventAttendance.tsx (1)

180-195: Consider using an enum for filter options.

The filter options could be better managed using an enum to ensure type safety and maintainability.

+enum FilterOption {
+  ThisMonth = 'This Month',
+  ThisYear = 'This Year',
+  All = 'All',
+}

 sortingOptions={[
   {
-    label: FilterPeriod.ThisMonth,
-    value: FilterPeriod.ThisMonth,
+    label: FilterOption.ThisMonth,
+    value: FilterOption.ThisMonth,
   },
   // ... other options
 ]}
src/screens/EventVolunteers/Volunteers/Volunteers.tsx (1)

357-368: Consider adding aria-label for better accessibility.

The status filter button could benefit from improved accessibility.

 <SortingButton
   type="filter"
+  aria-label={t('filterByStatus')}
   sortingOptions={[
     { label: tCommon('all'), value: VolunteerStatus.All },
     { label: tCommon('pending'), value: VolunteerStatus.Pending },
     { label: t('accepted'), value: VolunteerStatus.Accepted },
   ]}
   // ... other props
 />
src/screens/UserPortal/Posts/Posts.spec.tsx (1)

290-294: Consider adding vi.clearAllMocks() to beforeEach.

While the afterAll cleanup is good, adding vi.clearAllMocks() to beforeEach would ensure a clean slate for each test.

 beforeEach(() => {
   mockUseParams.mockReturnValue({ orgId: 'orgId' });
+  vi.clearAllMocks();
 });
src/screens/BlockUser/BlockUser.spec.tsx (1)

356-356: Maintain consistent test ID naming convention.

The test IDs show inconsistent naming patterns:

  • allMembers vs blockedUsers (noun vs noun)
  • Consider standardizing to either allMembers/blockedMembers or allUsers/blockedUsers
-userEvent.click(screen.getByTestId('allMembers'));
+userEvent.click(screen.getByTestId('allUsers'));
// OR
-userEvent.click(screen.getByTestId('blockedUsers'));
+userEvent.click(screen.getByTestId('blockedMembers'));

Also applies to: 386-386, 418-418, 425-425, 462-462, 511-511

src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx (1)

364-382: Consider using TypeScript enum for sort values.

While the implementation is correct, using an enum for sort values would improve type safety and maintainability.

enum SortOrder {
  FUNDING_GOAL_ASC = 'fundingGoal_ASC',
  FUNDING_GOAL_DESC = 'fundingGoal_DESC',
  END_DATE_ASC = 'endDate_ASC',
  END_DATE_DESC = 'endDate_DESC'
}

<SortingButton
  sortingOptions={[
    { label: t('lowestGoal'), value: SortOrder.FUNDING_GOAL_ASC },
    { label: t('highestGoal'), value: SortOrder.FUNDING_GOAL_DESC },
    { label: t('latestEndDate'), value: SortOrder.END_DATE_DESC },
    { label: t('earliestEndDate'), value: SortOrder.END_DATE_ASC },
  ]}
  onSortChange={(value) => setSortBy(value as SortOrder)}
  dataTestIdPrefix="filter"
  buttonLabel={tCommon('sort')}
/>
src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx (1)

173-184: Consider enhancing type safety and state management.

  1. Define a type for search options
  2. Consider using a reducer for related state management
type SearchOption = 'title' | 'location';

interface SearchState {
  searchValue: string;
  searchTerm: string;
  searchBy: SearchOption;
}

const searchOptions: Array<{ label: string; value: SearchOption }> = [
  { label: t('name'), value: 'title' },
  { label: tCommon('location'), value: 'location' },
];

<SortingButton
  sortingOptions={searchOptions}
  selectedOption={searchBy}
  onSortChange={(value) => setSearchBy(value as SearchOption)}
  dataTestIdPrefix="searchByToggle"
  buttonLabel={tCommon('searchBy', { item: '' })}
/>
src/screens/UserPortal/Volunteer/Actions/Actions.tsx (1)

389-399: Consider adding a default sort order.

While the implementation is clean, it would be beneficial to explicitly set a default sort order to ensure consistent initial rendering.

 <SortingButton
   sortingOptions={[
     { label: t('latestDueDate'), value: 'dueDate_DESC' },
     { label: t('earliestDueDate'), value: 'dueDate_ASC' },
   ]}
+  selectedOption="dueDate_DESC"
   onSortChange={(value) =>
     setSortBy(value as 'dueDate_DESC' | 'dueDate_ASC')
   }
   dataTestIdPrefix="sort"
   buttonLabel={tCommon('sort')}
 />
src/screens/OrganizationPeople/OrganizationPeople.tsx (1)

Line range hint 295-297: Consider using an enum for sort order values.

The sort order values are used in multiple places. Consider using an enum to improve type safety and maintainability.

+enum SortOrder {
+  ASCENDING = 'ASCENDING',
+  DESCENDING = 'DESCENDING'
+}

 const handleSortChange = (value: string): void => {
-  setTagSortOrder(value === 'latest' ? 'DESCENDING' : 'ASCENDING');
+  setTagSortOrder(value === 'latest' ? SortOrder.DESCENDING : SortOrder.ASCENDING);
 };
src/screens/OrganizationTags/OrganizationTags.tsx (2)

295-298: Consider using constants for sort values.

The string literals 'latest' and 'oldest' are used directly. Consider extracting them as constants to prevent typos and improve maintainability.

+const SORT_VALUES = {
+  LATEST: 'latest',
+  OLDEST: 'oldest'
+} as const;

 const handleSortChange = (value: string): void => {
-  setTagSortOrder(value === 'latest' ? 'DESCENDING' : 'ASCENDING');
+  setTagSortOrder(value === SORT_VALUES.LATEST ? 'DESCENDING' : 'ASCENDING');
 };

317-331: Consider memoizing the sorting options array.

The sorting options array is recreated on every render. Consider memoizing it to optimize performance.

+const sortingOptions = useMemo(() => [
+  { label: tCommon('Latest'), value: SORT_VALUES.LATEST },
+  { label: tCommon('Oldest'), value: SORT_VALUES.OLDEST },
+], [tCommon]);

 <SortingButton
   title="Sort Tags"
-  sortingOptions={[
-    { label: tCommon('Latest'), value: 'latest' },
-    { label: tCommon('Oldest'), value: 'oldest' },
-  ]}
+  sortingOptions={sortingOptions}
   selectedOption={
     tagSortOrder === 'DESCENDING'
       ? tCommon('Latest')
       : tCommon('Oldest')
   }
   onSortChange={handleSortChange}
   dataTestIdPrefix="sortTags"
   className={styles.dropdown}
 />
src/screens/OrgPost/OrgPost.tsx (1)

305-316: Consider using a more descriptive test ID prefix

The current searchBy prefix could be more specific, like searchTypeSelector to better indicate its purpose.

-  dataTestIdPrefix="searchBy"
+  dataTestIdPrefix="searchTypeSelector"
src/screens/OrgList/OrgList.spec.tsx (1)

528-528: Consider consistent naming for test IDs

The test IDs use different capitalization patterns:

  • 'Latest' uses Title Case
  • 'Earliest' uses Title Case
    Consider using consistent casing across all test IDs for better maintainability.

Also applies to: 540-540

src/screens/OrgList/OrgList.tsx (1)

Line range hint 315-324: Add type safety to sorting options

Consider using an enum or union type for sorting options to prevent potential errors.

type SortOption = 'Latest' | 'Earliest';

const handleSortChange = (value: SortOption): void => {
  setSortingState({
    option: value,
    selectedOption: t(value),
  });
  const orderBy = value === 'Latest' ? 'createdAt_DESC' : 'createdAt_ASC';
  // ... rest of the implementation
};
src/screens/OrganizationActionItems/OrganizationActionItems.tsx (1)

391-441: Consider memoizing the sorting options arrays.

The sorting options arrays are recreated on every render. Consider moving them outside the component or memoizing them with useMemo to optimize performance.

+ const searchByOptions = useMemo(() => [
+   { label: t('assignee'), value: 'assignee' },
+   { label: t('category'), value: 'category' },
+ ], [t]);

+ const sortByOptions = useMemo(() => [
+   { label: t('latestDueDate'), value: 'dueDate_DESC' },
+   { label: t('earliestDueDate'), value: 'dueDate_ASC' },
+ ], [t]);

+ const statusOptions = useMemo(() => [
+   { label: tCommon('all'), value: 'all' },
+   { label: tCommon('pending'), value: ItemStatus.Pending },
+   { label: tCommon('completed'), value: ItemStatus.Completed },
+ ], [tCommon]);

  <SortingButton
    title={tCommon('searchBy')}
-   sortingOptions={[
-     { label: t('assignee'), value: 'assignee' },
-     { label: t('category'), value: 'category' },
-   ]}
+   sortingOptions={searchByOptions}
    // ... rest of the props
  />
src/screens/FundCampaignPledge/FundCampaignPledge.tsx (1)

498-517: Consider type safety improvements for sort values.

The sort values are currently passed as string literals. Consider using a TypeScript enum or union type for better type safety and maintainability.

+ type SortValue = 'amount_ASC' | 'amount_DESC' | 'endDate_ASC' | 'endDate_DESC';

+ const sortOptions = [
+   { label: t('lowestAmount'), value: 'amount_ASC' as SortValue },
+   { label: t('highestAmount'), value: 'amount_DESC' as SortValue },
+   { label: t('latestEndDate'), value: 'endDate_DESC' as SortValue },
+   { label: t('earliestEndDate'), value: 'endDate_ASC' as SortValue },
+ ];

  <SortingButton
-   sortingOptions={[...]}
+   sortingOptions={sortOptions}
    selectedOption={sortBy ?? ''}
    onSortChange={(value) =>
-     setSortBy(
-       value as
-         | 'amount_ASC'
-         | 'amount_DESC'
-         | 'endDate_ASC'
-         | 'endDate_DESC',
-     )
+     setSortBy(value as SortValue)
    }
    // ... rest of the props
  />
src/screens/OrganizationPeople/AddMember.tsx (1)

284-294: Consider adding aria-label for better accessibility.

The SortingButton would benefit from an aria-label to improve accessibility for screen readers.

  <SortingButton
    title={translateOrgPeople('addMembers')}
+   aria-label={translateOrgPeople('addMembersAccessibilityLabel')}
    sortingOptions={[
      { label: translateOrgPeople('existingUser'), value: 'existingUser' },
      { label: translateOrgPeople('newUser'), value: 'newUser' },
    ]}
    // ... rest of the props
  />
src/screens/ManageTag/ManageTag.tsx (1)

380-392: Consider adding error boundary for translation fallback.

The component directly uses translation keys without fallback. Consider wrapping the SortingButton in an error boundary to handle missing translations gracefully.

+ const sortOptions = [
+   { 
+     label: tCommon('Latest') ?? 'Latest',
+     value: 'DESCENDING' as SortedByType
+   },
+   { 
+     label: tCommon('Oldest') ?? 'Oldest',
+     value: 'ASCENDING' as SortedByType
+   },
+ ];

  <SortingButton
    title="Sort People"
-   sortingOptions={[
-     { label: tCommon('Latest'), value: 'DESCENDING' },
-     { label: tCommon('Oldest'), value: 'ASCENDING' },
-   ]}
+   sortingOptions={sortOptions}
    selectedOption={assignedMemberSortOrder}
    onSortChange={(value) =>
      setAssignedMemberSortOrder(value as SortedByType)
    }
    dataTestIdPrefix="sortPeople"
    buttonLabel={tCommon('sort')}
  />
src/components/OrgPeopleListCard/OrgPeopleListCard.tsx (1)

60-60: Excellent improvement to user experience.

Replacing window.location.reload() with props.toggleRemoveModal() provides a smoother user experience by avoiding unnecessary page refreshes.

Consider adding a state update or refetch query to refresh the member list without closing the modal:

 if (data) {
   toast.success(t('memberRemoved') as string);
+  // Optionally refetch the members list
+  await refetchMembers();
   props.toggleRemoveModal();
 }
src/screens/UserPortal/Campaigns/Campaigns.tsx (1)

154-173: Consider adding type safety to sorting options

The sorting options could benefit from using a TypeScript enum or union type to ensure type safety and prevent potential runtime errors.

+ type SortByType = 'fundingGoal_ASC' | 'fundingGoal_DESC' | 'endDate_ASC' | 'endDate_DESC';
+ 
  <SortingButton
    sortingOptions={[
-     { label: t('lowestGoal'), value: 'fundingGoal_ASC' },
-     { label: t('highestGoal'), value: 'fundingGoal_DESC' },
-     { label: t('latestEndDate'), value: 'endDate_DESC' },
-     { label: t('earliestEndDate'), value: 'endDate_ASC' },
+     { label: t('lowestGoal'), value: 'fundingGoal_ASC' as SortByType },
+     { label: t('highestGoal'), value: 'fundingGoal_DESC' as SortByType },
+     { label: t('latestEndDate'), value: 'endDate_DESC' as SortByType },
+     { label: t('earliestEndDate'), value: 'endDate_ASC' as SortByType },
    ]}
    selectedOption={sortBy}
-   onSortChange={(value) =>
-     setSortBy(
-       value as
-         | 'fundingGoal_ASC'
-         | 'fundingGoal_DESC'
-         | 'endDate_ASC'
-         | 'endDate_DESC',
-     )
-   }
+   onSortChange={(value: SortByType) => setSortBy(value)}
    dataTestIdPrefix="filter"
    buttonLabel={tCommon('sort')}
  />
src/screens/SubTags/SubTags.tsx (1)

303-312: Consider adding type safety to sorting options

The sorting options could benefit from using a TypeScript enum or union type for better type safety.

+ type SortOrderType = 'ASCENDING' | 'DESCENDING';

  <SortingButton
    sortingOptions={[
-     { label: tCommon('Latest'), value: 'DESCENDING' },
-     { label: tCommon('Oldest'), value: 'ASCENDING' },
+     { label: tCommon('Latest'), value: 'DESCENDING' as SortOrderType },
+     { label: tCommon('Oldest'), value: 'ASCENDING' as SortOrderType },
    ]}
    selectedOption={tagSortOrder}
-   onSortChange={(value) => setTagSortOrder(value as SortedByType)}
+   onSortChange={(value: SortOrderType) => setTagSortOrder(value)}
    dataTestIdPrefix="sortTags"
    buttonLabel={tCommon('sort')}
  />
src/screens/UserPortal/Pledges/Pledges.tsx (1)

398-430: Add type safety to sorting options

Both SortingButton components could benefit from using TypeScript enums or union types for better type safety.

+ type SearchByType = 'pledgers' | 'campaigns';
+ type SortByType = 'amount_ASC' | 'amount_DESC' | 'endDate_ASC' | 'endDate_DESC';

  <SortingButton
    sortingOptions={[
-     { label: t('pledgers'), value: 'pledgers' },
-     { label: t('campaigns'), value: 'campaigns' },
+     { label: t('pledgers'), value: 'pledgers' as SearchByType },
+     { label: t('campaigns'), value: 'campaigns' as SearchByType },
    ]}
    selectedOption={searchBy}
-   onSortChange={(value) => setSearchBy(value as 'pledgers' | 'campaigns')}
+   onSortChange={(value: SearchByType) => setSearchBy(value)}
    dataTestIdPrefix="searchByDrpdwn"
    buttonLabel={t('searchBy')}
  />

  <SortingButton
    sortingOptions={[
-     { label: t('lowestAmount'), value: 'amount_ASC' },
-     { label: t('highestAmount'), value: 'amount_DESC' },
-     { label: t('latestEndDate'), value: 'endDate_DESC' },
-     { label: t('earliestEndDate'), value: 'endDate_ASC' },
+     { label: t('lowestAmount'), value: 'amount_ASC' as SortByType },
+     { label: t('highestAmount'), value: 'amount_DESC' as SortByType },
+     { label: t('latestEndDate'), value: 'endDate_DESC' as SortByType },
+     { label: t('earliestEndDate'), value: 'endDate_ASC' as SortByType },
    ]}
    selectedOption={sortBy}
-   onSortChange={(value) =>
-     setSortBy(
-       value as
-         | 'amount_ASC'
-         | 'amount_DESC'
-         | 'endDate_ASC'
-         | 'endDate_DESC',
-     )
-   }
+   onSortChange={(value: SortByType) => setSortBy(value)}
    dataTestIdPrefix="filter"
    buttonLabel={tCommon('sort')}
  />
public/locales/sp/translation.json (1)

1268-1268: Consider using a more idiomatic Spanish translation.

While "Chats" is understandable, consider using "Conversaciones" or "Mensajes" which are more commonly used in Spanish interfaces.

-    "title": "Chats",
+    "title": "Conversaciones",
src/assets/css/app.css (2)

14070-14070: Clean up button hover effect implementation.

The current implementation mixes different approaches with some commented out code. Consider:

  1. Remove commented out code if no longer needed
  2. Document why box-shadow and blend mode were chosen over background-color
-  /* isolation: isolate; */
   box-shadow: inset 50px 50px 40px rgba(0, 0, 0, 0.5);
   background-blend-mode: multiply;
-  /* background-color: #6c757d ; */
-  /* filter: brightness(0.85); */

Also applies to: 14084-14087


Line range hint 1-14104: Consider splitting vendor and custom styles.

While the file organization is clear with good documentation, consider:

  1. Separating Bootstrap CSS into a vendor styles file
  2. Keeping only custom Talawa styles in this file
  3. Using proper SCSS imports to manage the separation

This will make it easier to:

  • Update Bootstrap versions
  • Maintain custom styles
  • Reduce file size through proper chunking
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f30baa5 and eb00b71.

📒 Files selected for processing (82)
  • .husky/pre-commit (0 hunks)
  • jest.config.js (1 hunks)
  • package.json (1 hunks)
  • public/locales/en/translation.json (1 hunks)
  • public/locales/fr/translation.json (1 hunks)
  • public/locales/hi/translation.json (1 hunks)
  • public/locales/sp/translation.json (1 hunks)
  • public/locales/zh/translation.json (1 hunks)
  • setup.ts (2 hunks)
  • src/assets/css/app.css (3 hunks)
  • src/components/EventCalendar/EventHeader.spec.tsx (1 hunks)
  • src/components/EventCalendar/EventHeader.tsx (2 hunks)
  • src/components/EventListCard/EventListCard.tsx (1 hunks)
  • src/components/EventManagement/EventAttendance/EventAttendance.spec.tsx (2 hunks)
  • src/components/EventManagement/EventAttendance/EventAttendance.tsx (4 hunks)
  • src/components/EventStats/Statistics/AverageRating.tsx (3 hunks)
  • src/components/LeftDrawer/LeftDrawer.tsx (2 hunks)
  • src/components/OrgListCard/OrgListCard.tsx (2 hunks)
  • src/components/OrgListCard/TruncatedText.tsx (1 hunks)
  • src/components/OrgListCard/useDebounce.tsx (1 hunks)
  • src/components/OrgPeopleListCard/OrgPeopleListCard.spec.tsx (2 hunks)
  • src/components/OrgPeopleListCard/OrgPeopleListCard.tsx (1 hunks)
  • src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.spec.tsx (3 hunks)
  • src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.tsx (3 hunks)
  • src/components/RequestsTableItem/RequestsTableItem.spec.tsx (0 hunks)
  • src/components/RequestsTableItem/RequestsTableItem.tsx (0 hunks)
  • src/components/UsersTableItem/UsersTableItem.tsx (1 hunks)
  • src/components/Venues/VenueModal.spec.tsx (1 hunks)
  • src/components/Venues/VenueModal.tsx (0 hunks)
  • src/screens/BlockUser/BlockUser.spec.tsx (5 hunks)
  • src/screens/BlockUser/BlockUser.tsx (3 hunks)
  • src/screens/EventManagement/EventManagement.spec.tsx (1 hunks)
  • src/screens/EventManagement/EventManagement.test.tsx (0 hunks)
  • src/screens/EventManagement/EventManagement.tsx (2 hunks)
  • src/screens/EventVolunteers/Requests/Requests.tsx (3 hunks)
  • src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx (3 hunks)
  • src/screens/EventVolunteers/Volunteers/Volunteers.spec.tsx (3 hunks)
  • src/screens/EventVolunteers/Volunteers/Volunteers.tsx (4 hunks)
  • src/screens/ForgotPassword/ForgotPassword.tsx (1 hunks)
  • src/screens/FundCampaignPledge/FundCampaignPledge.spec.tsx (4 hunks)
  • src/screens/FundCampaignPledge/FundCampaignPledge.tsx (4 hunks)
  • src/screens/FundCampaignPledge/PledgeDeleteModal.spec.tsx (3 hunks)
  • src/screens/Leaderboard/Leaderboard.spec.tsx (4 hunks)
  • src/screens/Leaderboard/Leaderboard.tsx (3 hunks)
  • src/screens/ManageTag/ManageTag.spec.tsx (2 hunks)
  • src/screens/ManageTag/ManageTag.tsx (2 hunks)
  • src/screens/OrgList/OrgList.spec.tsx (5 hunks)
  • src/screens/OrgList/OrgList.tsx (8 hunks)
  • src/screens/OrgList/OrgListMocks.ts (0 hunks)
  • src/screens/OrgPost/OrgPost.test.tsx (1 hunks)
  • src/screens/OrgPost/OrgPost.tsx (2 hunks)
  • src/screens/OrgSettings/OrgSettings.spec.tsx (1 hunks)
  • src/screens/OrgSettings/OrgSettings.tsx (1 hunks)
  • src/screens/OrganizationActionItems/OrganizationActionItems.spec.tsx (3 hunks)
  • src/screens/OrganizationActionItems/OrganizationActionItems.tsx (4 hunks)
  • src/screens/OrganizationFundCampaign/CampaignModal.spec.tsx (5 hunks)
  • src/screens/OrganizationFundCampaign/OrganizationFundCampagins.tsx (3 hunks)
  • src/screens/OrganizationFundCampaign/OrganizationFundCampaign.spec.tsx (15 hunks)
  • src/screens/OrganizationFunds/OrganizationFunds.tsx (3 hunks)
  • src/screens/OrganizationPeople/AddMember.tsx (3 hunks)
  • src/screens/OrganizationPeople/OrganizationPeople.tsx (7 hunks)
  • src/screens/OrganizationTags/OrganizationTags.tsx (3 hunks)
  • src/screens/OrganizationVenues/OrganizationVenues.tsx (3 hunks)
  • src/screens/SubTags/SubTags.spec.tsx (2 hunks)
  • src/screens/SubTags/SubTags.tsx (2 hunks)
  • src/screens/UserPortal/Campaigns/Campaigns.tsx (3 hunks)
  • src/screens/UserPortal/Pledges/Pledges.tsx (3 hunks)
  • src/screens/UserPortal/Posts/Posts.spec.tsx (6 hunks)
  • src/screens/UserPortal/Settings/Settings.spec.tsx (3 hunks)
  • src/screens/UserPortal/Settings/Settings.tsx (0 hunks)
  • src/screens/UserPortal/UserScreen/UserScreen.spec.tsx (1 hunks)
  • src/screens/UserPortal/UserScreen/UserScreen.tsx (1 hunks)
  • src/screens/UserPortal/Volunteer/Actions/Actions.tsx (3 hunks)
  • src/screens/UserPortal/Volunteer/Groups/Groups.tsx (3 hunks)
  • src/screens/UserPortal/Volunteer/Invitations/Invitations.spec.tsx (3 hunks)
  • src/screens/UserPortal/Volunteer/Invitations/Invitations.tsx (4 hunks)
  • src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx (5 hunks)
  • src/screens/Users/Users.tsx (3 hunks)
  • src/setup/askAndSetDockerOption/askAndSetDockerOption.spec.ts (1 hunks)
  • src/setup/askAndSetDockerOption/askAndSetDockerOption.ts (1 hunks)
  • src/setup/askAndUpdatePort/askAndUpdatePort.ts (1 hunks)
  • src/setup/askAndUpdatePort/askForUpdatePort.spec.ts (1 hunks)
⛔ Files not processed due to max files limit (8)
  • src/setup/askForDocker/askForDocker.spec.ts
  • src/setup/askForDocker/askForDocker.ts
  • src/setup/updateEnvFile/updateEnvFile.spec.ts
  • src/setup/updateEnvFile/updateEnvFile.ts
  • src/setup/validateRecaptcha/validateRecaptcha.spec.ts
  • src/style/app.module.css
  • src/subComponents/SortingButton.tsx
  • src/utils/StaticMockLink.spec.ts
💤 Files with no reviewable changes (7)
  • .husky/pre-commit
  • src/screens/UserPortal/Settings/Settings.tsx
  • src/components/Venues/VenueModal.tsx
  • src/components/RequestsTableItem/RequestsTableItem.tsx
  • src/screens/OrgList/OrgListMocks.ts
  • src/components/RequestsTableItem/RequestsTableItem.spec.tsx
  • src/screens/EventManagement/EventManagement.test.tsx
✅ Files skipped from review due to trivial changes (2)
  • src/screens/ForgotPassword/ForgotPassword.tsx
  • package.json
🧰 Additional context used
📓 Learnings (3)
src/screens/SubTags/SubTags.tsx (1)
Learnt from: meetulr
PR: PalisadoesFoundation/talawa-admin#2387
File: src/screens/OrganizationTags/OrganizationTags.tsx:350-376
Timestamp: 2024-11-12T10:41:04.350Z
Learning: In the `src/screens/OrganizationTags/OrganizationTags.tsx` file, the `OrganizationTags` component uses chunk size with the `InfiniteScroll` component and an outer parent div for handling data loading and scrolling.
src/screens/OrganizationTags/OrganizationTags.tsx (1)
Learnt from: meetulr
PR: PalisadoesFoundation/talawa-admin#2387
File: src/screens/OrganizationTags/OrganizationTags.tsx:350-376
Timestamp: 2024-11-12T10:41:04.350Z
Learning: In the `src/screens/OrganizationTags/OrganizationTags.tsx` file, the `OrganizationTags` component uses chunk size with the `InfiniteScroll` component and an outer parent div for handling data loading and scrolling.
src/screens/OrganizationFundCampaign/CampaignModal.spec.tsx (1)
Learnt from: bitbard3
PR: PalisadoesFoundation/talawa-admin#2588
File: src/components/ChangeLanguageDropdown/ChangeLanguageDropdown.spec.tsx:145-155
Timestamp: 2024-12-02T04:20:11.745Z
Learning: In PRs focused solely on refactoring test cases from Jest to Vitest, avoid suggesting optimizations or changes outside the migration scope.
🪛 GitHub Check: Performs linting, formatting, type-checking, checking for different source and target branch
src/screens/OrgSettings/OrgSettings.spec.tsx

[warning] 133-133:
Some tests seem to be commented

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Test Application
🔇 Additional comments (80)
src/components/EventListCard/EventListCard.tsx (1)

98-98: Verify import statements across the codebase

The change from named export to default export might require updates in files importing this component.

Let's verify the impact:

✅ Verification successful

Export change is already properly reflected

All files importing the EventListCard component are already using the default import syntax, and type imports are correctly using named imports. No updates are required.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for existing imports of EventListCard to ensure they're updated
rg -l "import.*EventListCard.*from.*EventListCard'" 

# Search for potential usages that might need updating
ast-grep --pattern 'import { EventListCard } from "$_"'

Length of output: 430


Script:

#!/bin/bash
# Show the actual import statements for EventListCard
rg "import.*EventListCard.*from" -A 1 src/components/EventListCard/EventListCard.spec.tsx src/components/EventListCard/EventListCardProps.ts src/components/EventListCard/EventListCardModals.tsx src/components/EventCalendar/YearlyEventCalender.tsx src/components/EventCalendar/EventCalendar.tsx src/components/EventManagement/Dashboard/EventDashboard.tsx

Length of output: 1822

jest.config.js (1)

75-76: ⚠️ Potential issue

Reconsider lowering coverage thresholds.

Reducing coverage thresholds from 20% to 1% significantly lowers the quality bar and could allow untested code to reach production. Consider:

  1. Maintaining the original thresholds
  2. Gradually increasing coverage through incremental improvements
  3. Identifying and addressing underlying issues making it difficult to maintain higher coverage

Let's analyze the current test coverage to understand the impact:

src/screens/UserPortal/Settings/Settings.spec.tsx (1)

15-28: LGTM! Well-structured mock implementations.

The mock implementations for toast and errorHandler are clear and properly scoped.

src/components/OrgListCard/OrgListCard.tsx (1)

99-103: LGTM! Good handling of undefined description

The implementation safely handles undefined description using optional chaining and fallback to empty string.

setup.ts (1)

6-9: Verify Import Paths and Module Names

There might be inconsistencies in the import paths, particularly with askAndUpdateTalawaApiUrl being imported from './src/setup/askForDocker/askForDocker'. It seems unusual that a function named askAndUpdateTalawaApiUrl is being imported from a module named askForDocker. Please verify that the module paths and the exported functions are correctly matched.

src/setup/askAndUpdatePort/askForUpdatePort.spec.ts (1)

1-10: LGTM! Clean dependency setup and mocking.

The import statements and mock setup are well-organized, with clear separation between test framework imports and application dependencies.

src/components/EventStats/Statistics/AverageRating.tsx (1)

7-7: Good improvement in styling approach!

Moving from inline styles to CSS modules enhances maintainability and follows React best practices for styling. The changes are well-structured and maintain the component's functionality while improving code organization.

Also applies to: 36-36, 53-55

src/screens/FundCampaignPledge/PledgeDeleteModal.spec.tsx (1)

18-18: Clean migration to Vitest!

The test file has been successfully migrated from Jest to Vitest, maintaining all test functionality while modernizing the testing framework. The mock functions and assertions have been properly updated.

Also applies to: 20-24, 35-35, 51-51

src/screens/OrgSettings/OrgSettings.tsx (1)

2-2: Verify impact of removing dropdown navigation

The dropdown menu for settings navigation has been removed. While this simplifies the interface, please ensure this change:

  1. Aligns with the overall UX strategy
  2. Doesn't negatively impact mobile users who might have found the dropdown more convenient
  3. Is consistent with the behavior in other similar settings pages
src/screens/UserPortal/UserScreen/UserScreen.tsx (1)

20-20: Verify chat functionality implementation

The addition of the chat route mapping needs corresponding chat component implementation and tests.

✅ Verification successful

Chat functionality implementation verified

The chat route mapping is properly supported with corresponding implementations and test coverage:

  • Main chat component at src/screens/UserPortal/Chat/Chat.tsx
  • Supporting components for chat room and chat creation
  • Comprehensive test coverage across all chat-related components
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for chat component implementation
echo "Checking for chat component implementation..."
fd -e tsx -e ts "userChat"

# Check for related test files
echo "Checking for test coverage..."
fd -e spec.tsx -e test.tsx "userChat"

Length of output: 234


Script:

#!/bin/bash
# Search for chat-related component implementations
echo "Searching for chat components..."
rg -l -t typescript -t tsx "chat" --ignore-case

# Search for route definitions
echo "Searching for route definitions..."
ast-grep --pattern 'const $_ = {
  $$$
  chat: $_,
  $$$
}'

# Search for chat-related tests
echo "Searching for chat-related tests..."
rg -l -t typescript -t tsx "chat.*test|test.*chat" --ignore-case

Length of output: 481


Script:

#!/bin/bash
# Search for chat-related implementations
echo "Searching for chat components and routes..."
rg -l "chat" --glob "*.{ts,tsx}"

# Search for specific route configuration
echo "Searching for route configuration..."
rg -A 5 -B 5 "chat.*:.*'userChat'" --glob "*.{ts,tsx}"

# Search for chat-related tests
echo "Searching for chat-related tests..."
rg -l "describe.*chat|test.*chat" --glob "*.{ts,tsx}"

Length of output: 2584

src/components/LeftDrawer/LeftDrawer.tsx (1)

34-38: 🛠️ Refactor suggestion

Add missing dependency to useEffect

The useEffect hook should include setHideDrawer in its dependency array to prevent potential stale closure issues.

  useEffect(() => {
    if (hideDrawer === null) {
      setHideDrawer(false);
    }
-  }, []);
+  }, [setHideDrawer]);

Likely invalid or redundant comment.

src/screens/UserPortal/UserScreen/UserScreen.spec.tsx (1)

133-150: LGTM! Well-structured test case addition.

The new test case for chat title rendering follows the established testing patterns and properly verifies the component's behavior.

src/components/OrgPeopleListCard/OrgPeopleListCard.spec.tsx (3)

86-99: LGTM! Well-structured mock for null data scenario.

The NULL_DATA_MOCKS constant follows the established patterns and properly simulates the null data response scenario.


101-123: LGTM! Comprehensive test coverage for null data handling.

The test case thoroughly verifies the component's behavior when receiving a null response from the mutation.


165-165: LGTM! Updated expectation aligns with current behavior.

The modified expectation correctly verifies the modal toggle instead of page reload.

src/screens/OrganizationVenues/OrganizationVenues.tsx (3)

96-98: LGTM! Well-typed handler function.

The handleSearchByChange function properly handles type safety with appropriate type assertion.


104-105: LGTM! Clean function signature update.

The handleSortChange function has been properly updated to work with the new SortingButton component while maintaining type safety.


166-189: LGTM! Well-structured SortingButton implementation.

The SortingButton components are properly configured with:

  • Clear titles and sorting options
  • Proper translation integration
  • Consistent data-testid attributes for testing
  • Appropriate className handling
src/screens/EventManagement/EventManagement.tsx (1)

Line range hint 1-276: Implementation looks good!

The component is well-structured with proper TypeScript types, comprehensive error handling, and good separation of concerns. The use of enums for tab options and proper handling of missing parameters demonstrates solid engineering practices.

src/screens/EventManagement/EventManagement.spec.tsx (1)

1-253: Well-structured test suite with comprehensive coverage!

The test implementation demonstrates excellent practices:

  • Clear organization using describe blocks for different test categories
  • Thorough testing of navigation paths for different user roles
  • Proper cleanup after tests
  • Comprehensive UI interaction testing
  • Good use of test data attributes for reliable element selection
src/screens/UserPortal/Volunteer/Invitations/Invitations.tsx (2)

161-184: Good use of the new SortingButton component!

The implementation properly handles both sorting and filtering with clear separation of concerns. The type handling for filter values is particularly well done.


Line range hint 1-276: Well-structured component with good practices!

Notable strengths:

  • Proper error handling with user-friendly messages
  • Efficient search implementation with debouncing
  • Clear separation of concerns
  • Good use of TypeScript for type safety
src/screens/EventVolunteers/Volunteers/Volunteers.spec.tsx (1)

Line range hint 165-209: Good alignment of test IDs with new component structure.

The simplified test IDs (all, pending, accepted) are more maintainable and consistent with the new SortingButton implementation across the application.

src/screens/OrganizationFundCampaign/CampaignModal.spec.tsx (5)

24-25: LGTM!

The import of vi from vitest is correctly added for the Jest to Vitest migration.


26-31: LGTM!

The mock for react-toastify is correctly migrated from Jest to Vitest using vi.mock.


33-40: LGTM!

The mock for @mui/x-date-pickers/DateTimePicker is correctly migrated using vi.mock and vi.importActual to import the actual component.


51-51: LGTM!

Mock functions are correctly migrated from jest.fn() to vi.fn().

Also applies to: 63-63, 68-68, 80-80


105-105: LGTM!

The cleanup function is correctly migrated from jest.clearAllMocks() to vi.clearAllMocks().

src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.spec.tsx (3)

128-128: LGTM!

The test ID for the "All" status filter is correctly updated from statusAll to all.

Also applies to: 130-130


140-140: LGTM!

The test ID for the "Disabled" status filter is correctly updated from statusDisabled to disabled.

Also applies to: 142-142


157-157: LGTM!

The test ID for the "Active" status filter is correctly updated from statusActive to active.

Also applies to: 159-159

src/screens/UserPortal/Volunteer/Invitations/Invitations.spec.tsx (3)

174-174: LGTM!

The test ID for the "All" filter is correctly updated from filterAll to all.


192-192: LGTM!

The test ID for the "Group" filter is correctly updated from filterGroup to group.


213-213: LGTM!

The test ID for the "Individual" filter is correctly updated from filterIndividual to individual.

src/screens/EventVolunteers/Requests/Requests.tsx (3)

3-3: LGTM!

The imports are correctly updated to remove unused components and retain only the necessary ones.

Also applies to: 6-6


23-23: LGTM!

The SortingButton component is correctly imported from the subComponents directory.


283-294: LGTM!

The SortingButton component is correctly implemented with:

  • Appropriate sorting options for 'latest' and 'earliest'
  • Proper handling of selected option and sort change
  • Correct data test ID prefix and button label
src/screens/Leaderboard/Leaderboard.tsx (2)

274-285: LGTM! Well-implemented sorting functionality.

The SortingButton implementation for hours sorting is clean, type-safe, and follows best practices with:

  • Clear prop types and values
  • Proper data-testid attributes for testing
  • Consistent translation usage

286-298: LGTM! Well-implemented filtering functionality.

The SortingButton implementation for timeframe filtering is well structured with:

  • Clear separation from sorting functionality
  • Comprehensive timeframe options
  • Proper type handling for filter values
src/screens/Leaderboard/Leaderboard.spec.tsx (1)

176-176: LGTM! Test IDs properly updated.

The test IDs have been consistently updated to match the new SortingButton implementation while maintaining comprehensive test coverage.

Also applies to: 199-199, 220-220, 241-241

src/screens/SubTags/SubTags.spec.tsx (1)

287-289: LGTM! Standardized sorting terminology.

The sort order test IDs have been updated to use more conventional terms ('ASCENDING'/'DESCENDING' instead of 'oldest'/'latest'), improving consistency across the codebase.

Also applies to: 304-306

src/screens/OrganizationFundCampaign/OrganizationFundCampaign.spec.tsx (3)

23-37: LGTM! Well-structured mock implementations.

The mock implementations are properly migrated to Vitest with:

  • Proper async handling for actual component imports
  • Clear mock structure for toast notifications

95-97: LGTM! Good route parameter mocking pattern.

The introduction of mockRouteParams function centralizes and standardizes route parameter mocking, improving test maintainability.


82-88: LGTM! Clean Vitest migration.

The migration to Vitest is well-implemented with:

  • Proper mock cleanup
  • Correct usage of vi.mock for router
  • Proper handling of actual module imports

Also applies to: 92-92

src/screens/BlockUser/BlockUser.tsx (1)

219-251: Well-structured replacement of dropdowns with SortingButton components!

The implementation effectively replaces the dropdown components with SortingButton components while maintaining the same functionality. The code is well-organized with proper typing and translation support.

src/screens/OrganizationFunds/OrganizationFunds.tsx (2)

311-327: Clean implementation of the SortingButton component!

The sorting functionality is well-implemented with proper translation support and type safety.


1-1: 🛠️ Refactor suggestion

Component name should follow React naming convention.

React component names should use PascalCase. Rename the component from organizationFunds to OrganizationFunds.

-const organizationFunds = (): JSX.Element => {
+const OrganizationFunds = (): JSX.Element => {

Likely invalid or redundant comment.

src/screens/UserPortal/Volunteer/Groups/Groups.tsx (1)

1-1: 🛠️ Refactor suggestion

Component name should follow React naming convention.

React component names should use PascalCase. Rename the component from groups to Groups.

-function groups(): JSX.Element {
+function Groups(): JSX.Element {

Likely invalid or redundant comment.

src/components/OrgSettings/ActionItemCategories/OrgActionItemCategories.tsx (1)

309-347: Excellent implementation of SortingButton components!

The implementation is well-structured with:

  • Proper translation support
  • Type-safe props and callbacks
  • Consistent styling through className prop
  • Clear separation of sorting and filtering functionality
src/screens/FundCampaignPledge/FundCampaignPledge.spec.tsx (1)

77-86: LGTM! Clean mock implementation for react-router-dom.

The mock implementation for react-router-dom is well structured, preserving the actual module's functionality while overriding specific functions.

src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx (1)

325-334: LGTM! Well-structured implementation of search criteria filtering.

The SortingButton implementation for search criteria is clean and properly typed.

src/components/EventManagement/EventAttendance/EventAttendance.tsx (2)

153-161: LGTM! Clean layout implementation with proper alignment.

The button and container layout is well-structured with appropriate spacing and alignment.


196-208: LGTM! Well-implemented sorting functionality.

The sort implementation is clean and properly typed with clear option labels.

src/screens/EventVolunteers/Volunteers/Volunteers.tsx (1)

336-355: LGTM! Well-implemented hours sorting with proper type safety.

The sorting implementation for volunteer hours is clean and type-safe.

src/screens/UserPortal/Posts/Posts.spec.tsx (4)

19-19: LGTM! Vitest imports and mock setup are correctly implemented.

The migration from Jest to Vitest is properly done with appropriate imports and mock implementations.

Also applies to: 23-29


31-40: LGTM! Router mocks are properly implemented.

Good practice using vi.importActual to maintain the original module functionality while overriding specific functions.


277-285: LGTM! Window matchMedia mock is properly implemented.

All mock methods are correctly using vi.fn() for consistent Vitest usage.


Line range hint 297-369: LGTM! Test cases are properly migrated to Vitest syntax.

The migration from test() to it() is consistently applied across all test cases.

src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx (1)

94-94: LGTM! Clear and descriptive comment.

The comment effectively explains the purpose of the upcoming code block.

src/screens/UserPortal/Volunteer/Actions/Actions.tsx (1)

377-388: LGTM! Clean implementation of search criteria selection.

The SortingButton implementation for search criteria is well-structured with clear options and proper type handling.

src/screens/OrganizationPeople/OrganizationPeople.tsx (2)

187-232: Well-implemented responsive image sizing!

The implementation handles both image and fallback cases with proper responsive sizing. Good use of computed column width for dynamic scaling.


Line range hint 317-331: LGTM! Clean implementation of role-based sorting.

The SortingButton implementation is well-structured with clear options and proper translation handling.

src/screens/ManageTag/ManageTag.spec.tsx (1)

373-375: Verify test identifiers match component implementation.

The test uses 'ASCENDING' and 'DESCENDING' as test identifiers. Ensure these match the actual implementation in the component.

Also applies to: 390-392

✅ Verification successful

Test identifiers match component implementation correctly

The test identifiers 'ASCENDING' and 'DESCENDING' are correctly implemented as they match the data-testid attributes automatically set by the SortingButton component based on the sorting option values passed to it.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the corresponding component implementation
ast-grep --pattern 'const SortingButton = ({ sortingOptions }) => {
  $$$
}'

# Search for the usage of these test identifiers in the component
rg -A 5 "ASCENDING|DESCENDING" src/screens/ManageTag/

Length of output: 4218


Script:

#!/bin/bash
# Search for data-testid usage with these values
rg -B 2 -A 2 'data-testid.*=.*["'\''](?:ASCENDING|DESCENDING)' src/

# Find components that might render these sorting options
ast-grep --pattern 'data-testid={$_}'

# Look for SortingButton or similar component implementations
fd -e tsx -e ts SortingButton

Length of output: 177


Script:

#!/bin/bash
# View the SortingButton component implementation
cat src/subComponents/SortingButton.tsx

# Search for test files related to SortingButton
fd -e spec.tsx -e test.tsx SortingButton

Length of output: 3408

src/screens/Users/Users.tsx (3)

20-21: LGTM! Clean import of the new SortingButton component.


375-383: LGTM! Well-structured implementation of SortingButton for sorting users.

The component is properly configured with:

  • Translated sorting options
  • Clear data test IDs
  • Proper handling of selected state

384-397: LGTM! Well-implemented filtering functionality using SortingButton.

The component correctly:

  • Handles all user roles (admin, superAdmin, user, cancel)
  • Uses appropriate test IDs
  • Maintains clear separation from sorting functionality
src/screens/OrgPost/OrgPost.tsx (1)

317-329: LGTM! Clean implementation of post sorting functionality.

The SortingButton is well-configured with:

  • Clear sorting options
  • Consistent styling
  • Appropriate test IDs
src/screens/OrgList/OrgList.spec.tsx (2)

29-31: LGTM! Proper migration from jest to vitest configuration.


43-50: LGTM! Proper test setup with Storage spy and cleanup.

src/screens/OrgList/OrgList.tsx (1)

354-364: LGTM! Well-structured SortingButton implementation.

The component is properly configured with:

  • Clear title and options
  • Translated labels
  • Appropriate test IDs
src/screens/OrganizationActionItems/OrganizationActionItems.tsx (1)

139-142: LGTM! The useEffect hook correctly handles data refetching.

The hook properly triggers a refetch when sorting or status filters change, and includes the refetch function in dependencies.

src/screens/OrganizationPeople/AddMember.tsx (1)

274-280: LGTM! The handler function is well-implemented.

The function correctly handles different sorting options and triggers the appropriate modal actions.

src/screens/OrgPost/OrgPost.test.tsx (1)

311-311: Test ID change looks good, but let's verify consistency.

The change from 'searchTitle' to 'Title' appears to be part of a broader standardization of test IDs.

Let's verify that this test ID naming pattern is consistent across the codebase:

src/screens/OrganizationActionItems/OrganizationActionItems.spec.tsx (1)

255-255: Test ID changes align with the standardization effort.

The simplification of test IDs (removing 'status' prefix) improves maintainability while preserving test functionality.

Let's verify the consistency of these status filter test IDs across the codebase:

Also applies to: 259-259, 272-272, 276-276, 317-317, 321-321

✅ Verification successful

Test ID changes are consistent with the codebase standards.

The simplified test IDs ('all', 'pending', 'completed') are used consistently within the OrganizationActionItems component and follow the codebase's pattern of using clear, descriptive identifiers without unnecessary prefixes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for similar status filter test IDs
rg -l 'data-testid=["'\''](?:all|pending|completed)["'\'']' --type tsx --type jsx

Length of output: 111


Script:

#!/bin/bash
# First, let's see what extensions we're dealing with
fd -e tsx -e jsx

# Then search for both old and new patterns with context
rg -C 2 'data-testid=["'\''](status-)?(all|pending|completed)["'\'']'

Length of output: 21538


Script:

#!/bin/bash
# Check the specific file for test IDs
cat src/screens/OrganizationActionItems/OrganizationActionItems.spec.tsx

# Also search with a simpler pattern in case there are similar patterns elsewhere
rg -C 2 "testid=|data-testid=" src/screens/OrganizationActionItems/

Length of output: 43352

src/components/UsersTableItem/UsersTableItem.tsx (1)

164-164: Good use of semantic button styling.

Using Bootstrap's 'btn-success' class for the "View" action follows UI/UX best practices by providing clear visual feedback about the action's nature.

src/screens/UserPortal/Campaigns/Campaigns.tsx (1)

20-20: ⚠️ Potential issue

Replace hardcoded progress bar values

The progress bar uses hardcoded values (200/1000) which should be replaced with actual campaign progress data.

- <ProgressBar
-   now={0}
-   label={`${(200 / 1000) * 100}%`}
-   max={1000}
-   className={styles.progressBar}
-   data-testid="progressBar"
- />
+ <ProgressBar
+   now={campaign.raisedAmount}
+   label={`${(campaign.raisedAmount / campaign.fundingGoal) * 100}%`}
+   max={campaign.fundingGoal}
+   className={styles.progressBar}
+   data-testid="progressBar"
+ />

Likely invalid or redundant comment.

public/locales/zh/translation.json (1)

1265-1265: LGTM! Translation addition is consistent

The new translation key for chat title is correctly added and maintains consistency with other language files.

public/locales/en/translation.json (1)

1265-1265: LGTM! Base translation addition is correct

The new translation key for chat title is correctly added and serves as the base for other language translations.

public/locales/hi/translation.json (1)

1265-1265: LGTM! Accurate Hindi translation for chat title.

The translation "चैट्स" is linguistically accurate and follows Hindi language conventions.

public/locales/fr/translation.json (1)

1265-1265: LGTM! Idiomatic French translation for chat title.

The translation "Discussions" is idiomatic French and appropriately conveys the concept of chats/conversations.

Comment on lines +12 to +40
function useDebounce<T extends (...args: unknown[]) => void>(
callback: T,
delay: number,
): { debouncedCallback: (...args: Parameters<T>) => void; cancel: () => void } {
const timeoutRef = useRef<number | undefined>();

/**
* The debounced version of the provided callback function.
* This function resets the debounce timer on each call, ensuring the callback
* is invoked only after the specified delay has elapsed without further calls.
*
* @param args - The arguments to pass to the callback when invoked.
*/
const debouncedCallback = useCallback(
(...args: Parameters<T>) => {
if (timeoutRef.current) clearTimeout(timeoutRef.current);
timeoutRef.current = window.setTimeout(() => {
callback(...args);
}, delay);
},
[callback, delay],
);

const cancel = useCallback(() => {
if (timeoutRef.current) clearTimeout(timeoutRef.current);
}, []);

return { debouncedCallback, cancel };
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add cleanup on unmount to prevent memory leaks

The hook should clean up any pending timeouts when the component unmounts to prevent memory leaks.

Wrap the hook in a useEffect for cleanup:

 function useDebounce<T extends (...args: unknown[]) => void>(
   callback: T,
   delay: number,
 ): { debouncedCallback: (...args: Parameters<T>) => void; cancel: () => void } {
   const timeoutRef = useRef<number | undefined>();

   const debouncedCallback = useCallback(
     (...args: Parameters<T>) => {
       if (timeoutRef.current) clearTimeout(timeoutRef.current);
       timeoutRef.current = window.setTimeout(() => {
         callback(...args);
       }, delay);
     },
     [callback, delay],
   );

   const cancel = useCallback(() => {
     if (timeoutRef.current) clearTimeout(timeoutRef.current);
   }, []);

+  useEffect(() => {
+    return () => {
+      if (timeoutRef.current) clearTimeout(timeoutRef.current);
+    };
+  }, []);

   return { debouncedCallback, cancel };
 }
📝 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
function useDebounce<T extends (...args: unknown[]) => void>(
callback: T,
delay: number,
): { debouncedCallback: (...args: Parameters<T>) => void; cancel: () => void } {
const timeoutRef = useRef<number | undefined>();
/**
* The debounced version of the provided callback function.
* This function resets the debounce timer on each call, ensuring the callback
* is invoked only after the specified delay has elapsed without further calls.
*
* @param args - The arguments to pass to the callback when invoked.
*/
const debouncedCallback = useCallback(
(...args: Parameters<T>) => {
if (timeoutRef.current) clearTimeout(timeoutRef.current);
timeoutRef.current = window.setTimeout(() => {
callback(...args);
}, delay);
},
[callback, delay],
);
const cancel = useCallback(() => {
if (timeoutRef.current) clearTimeout(timeoutRef.current);
}, []);
return { debouncedCallback, cancel };
}
function useDebounce<T extends (...args: unknown[]) => void>(
callback: T,
delay: number,
): { debouncedCallback: (...args: Parameters<T>) => void; cancel: () => void } {
const timeoutRef = useRef<number | undefined>();
/**
* The debounced version of the provided callback function.
* This function resets the debounce timer on each call, ensuring the callback
* is invoked only after the specified delay has elapsed without further calls.
*
* @param args - The arguments to pass to the callback when invoked.
*/
const debouncedCallback = useCallback(
(...args: Parameters<T>) => {
if (timeoutRef.current) clearTimeout(timeoutRef.current);
timeoutRef.current = window.setTimeout(() => {
callback(...args);
}, delay);
},
[callback, delay],
);
const cancel = useCallback(() => {
if (timeoutRef.current) clearTimeout(timeoutRef.current);
}, []);
useEffect(() => {
return () => {
if (timeoutRef.current) clearTimeout(timeoutRef.current);
};
}, []);
return { debouncedCallback, cancel };
}

Comment on lines +106 to 111
{address?.city && (
<div className={styles.address}>
<h6 className="text-secondary">
<span className="address-line">{address.line1}, </span>
<span className="address-line">{address.city}, </span>
<span className="address-line">{address.countryCode}</span>
</h6>
<TruncatedText
text={`${address?.line1}, ${address?.city}, ${address?.countryCode}`}
/>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add null checks for address fields

The address concatenation could fail if individual address fields are undefined.

Add null checks for each address field:

   {address?.city && (
     <div className={styles.address}>
       <TruncatedText
-        text={`${address?.line1}, ${address?.city}, ${address?.countryCode}`}
+        text={[
+          address?.line1,
+          address?.city,
+          address?.countryCode
+        ].filter(Boolean).join(', ')}
       />
     </div>
   )}
📝 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
{address?.city && (
<div className={styles.address}>
<h6 className="text-secondary">
<span className="address-line">{address.line1}, </span>
<span className="address-line">{address.city}, </span>
<span className="address-line">{address.countryCode}</span>
</h6>
<TruncatedText
text={`${address?.line1}, ${address?.city}, ${address?.countryCode}`}
/>
</div>
{address?.city && (
<div className={styles.address}>
<TruncatedText
text={[
address?.line1,
address?.city,
address?.countryCode
].filter(Boolean).join(', ')}
/>
</div>

Comment on lines +64 to +85
checkEnvFile();
await askAndSetDockerOption();
const envConfig = dotenv.parse(fs.readFileSync('.env', 'utf8'));
const useDocker = envConfig.USE_DOCKER === 'YES';

// Only run these commands if Docker is NOT used
if (!useDocker) {
await askAndUpdatePort();
await askAndUpdateTalawaApiUrl();
}

await askAndSetRecaptcha();
await askAndSetLogErrors();

console.log(
'\nCongratulations! Talawa Admin has been successfully set up! 🥂🎉',
);
} catch (error) {
console.error('\n❌ Setup failed:', error);
console.log('\nPlease try again or contact support if the issue persists.');
process.exit(1);
}
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

Handle Missing or Corrupted .env Files Gracefully

At line 64, checkEnvFile() is called, but if the .env file is missing or corrupted, the application might crash or behave unexpectedly. Implement additional checks to handle such scenarios gracefully, informing the user and possibly regenerating a default .env file.

Comment on lines +1 to +3
import updateEnvFile from 'setup/updateEnvFile/updateEnvFile';
import { askForCustomPort } from 'setup/askForCustomPort/askForCustomPort';
import inquirer from 'inquirer';
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

Correct Relative Import Paths

The import paths at lines 1-3 lack the appropriate relative path notation, which may cause module resolution failures. Ensure the paths correctly reference the modules using '../' or './'.

Apply this diff to correct the import statements:

-import updateEnvFile from 'setup/updateEnvFile/updateEnvFile';
-import { askForCustomPort } from 'setup/askForCustomPort/askForCustomPort';
+import updateEnvFile from '../../updateEnvFile/updateEnvFile';
+import { askForCustomPort } from '../askForCustomPort/askForCustomPort';

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +1 to +3
import inquirer from 'inquirer';
import updateEnvFile from 'setup/updateEnvFile/updateEnvFile';
import { askForDocker } from 'setup/askForDocker/askForDocker';
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

Adjust Import Paths for Proper Module Resolution

Similar to the previous file, the import paths at lines 1-3 may not correctly resolve the modules due to missing relative path indicators. Update the paths to ensure accurate module imports.

Apply this diff to fix the import statements:

-import inquirer from 'inquirer';
-import updateEnvFile from 'setup/updateEnvFile/updateEnvFile';
-import { askForDocker } from 'setup/askForDocker/askForDocker';
+import inquirer from 'inquirer';
+import updateEnvFile from '../../updateEnvFile/updateEnvFile';
+import { askForDocker } from '../askForDocker/askForDocker';
📝 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
import inquirer from 'inquirer';
import updateEnvFile from 'setup/updateEnvFile/updateEnvFile';
import { askForDocker } from 'setup/askForDocker/askForDocker';
import inquirer from 'inquirer';
import updateEnvFile from '../../updateEnvFile/updateEnvFile';
import { askForDocker } from '../askForDocker/askForDocker';

Comment on lines +79 to +90
<SortingButton
title={t('eventType')}
sortingOptions={[
{ label: 'Events', value: 'Events' },
{ label: 'Workshops', value: 'Workshops' },
]}
selectedOption={t('eventType')}
onSortChange={(value) => console.log(`Selected: ${value}`)}
dataTestIdPrefix="eventType"
className={styles.dropdown}
buttonLabel={t('eventType')}
/>
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

🛠️ Refactor suggestion

Implement proper event type selection handler and remove redundant prop

The review comment is correct on both points:

  1. The event type selection handler needs proper implementation instead of just logging to console. Other SortingButton implementations in the codebase show that selections typically update state or trigger filtering.

  2. The buttonLabel prop is redundant as it's set to the same value as title. When buttonLabel is used in other components, it typically serves a different purpose than the title.

  <SortingButton
    title={t('eventType')}
    sortingOptions={[
      { label: 'Events', value: 'Events' },
      { label: 'Workshops', value: 'Workshops' },
    ]}
    selectedOption={t('eventType')}
-   onSortChange={(value) => console.log(`Selected: ${value}`)}
+   onSortChange={handleEventTypeChange}
    dataTestIdPrefix="eventType"
    className={styles.dropdown}
-   buttonLabel={t('eventType')}
  />
🔗 Analysis chain

Implement proper event type selection handler

The event type selection currently only logs to console. Consider implementing proper handling of the selection.

Also, the buttonLabel prop appears redundant as it's the same as the title. Consider removing it:

  <SortingButton
    title={t('eventType')}
    sortingOptions={[
      { label: 'Events', value: 'Events' },
      { label: 'Workshops', value: 'Workshops' },
    ]}
    selectedOption={t('eventType')}
    onSortChange={(value) => console.log(`Selected: ${value}`)}
    dataTestIdPrefix="eventType"
    className={styles.dropdown}
-   buttonLabel={t('eventType')}
  />
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for potential event type handling implementations
rg -l "eventType.*selection|handleEventType" --type ts --type tsx

Length of output: 95


Script:

#!/bin/bash
# Search for event type related code and state management
rg -t ts "eventType|EventType" -A 3
rg "SortingButton.*onSortChange" -A 3

Length of output: 2421


Script:

#!/bin/bash
# Search for other SortingButton implementations
fd -e tsx -e ts | xargs rg "SortingButton" -B 2 -A 4

Length of output: 47279

Comment on lines +133 to +178
// it('should handle dropdown item selection correctly', async () => {
// renderOrganisationSettings();

// await waitFor(() => {
// expect(
// screen.getByTestId('settingsDropdownContainer'),
// ).toBeInTheDocument();
// });

// const dropdownToggle = screen.getByTestId('settingsDropdownToggle');
// userEvent.click(dropdownToggle);

// // Find all dropdown items
// const dropdownItems = screen.getAllByRole('menuitem');
// expect(dropdownItems).toHaveLength(3);

// for (const item of dropdownItems) {
// userEvent.click(item);

// if (item.textContent?.includes('general')) {
// await waitFor(() => {
// expect(screen.getByTestId('generalTab')).toBeInTheDocument();
// });
// } else if (item.textContent?.includes('actionItemCategories')) {
// await waitFor(() => {
// expect(
// screen.getByTestId('actionItemCategoriesTab'),
// ).toBeInTheDocument();
// });
// } else if (item.textContent?.includes('agendaItemCategories')) {
// await waitFor(() => {
// expect(
// screen.getByTestId('agendaItemCategoriesTab'),
// ).toBeInTheDocument();
// });
// }

// if (item !== dropdownItems[dropdownItems.length - 1]) {
// userEvent.click(dropdownToggle);
// }
// }

// expect(dropdownToggle).toHaveTextContent(
// screen.getByTestId('agendaItemCategoriesSettings').textContent || '',
// );
// });
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Remove the commented test case as it's no longer relevant

The dropdown functionality has been replaced with the SortingButton component, as evidenced by:

  • No active implementation of the tested dropdown in OrgSettings.tsx
  • SortingButton being used in ActionItemCategories for similar functionality
  • The test case testing functionality that no longer exists in the codebase
🔗 Analysis chain

Clarify the status of the commented test case.

This test case appears to be testing dropdown functionality that may have been replaced. If the dropdown component has been replaced with a SortingButton component (as suggested by the AI summary), this test should either be:

  1. Updated to test the new SortingButton functionality, or
  2. Removed if it's no longer relevant

Let's verify if the dropdown has been replaced:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the dropdown component has been replaced with SortingButton
rg -l "settingsDropdownContainer|settingsDropdownToggle" .

Length of output: 107


Script:

#!/bin/bash
# Check the OrgSettings component implementation and SortingButton usage
echo "=== OrgSettings Component Implementation ==="
ast-grep --pattern 'data-testid="settingsDropdownContainer"' || ast-grep --pattern 'data-testid="settingsDropdownToggle"'

echo -e "\n=== SortingButton Usage ==="
rg "SortingButton" ./src/screens/OrgSettings/OrgSettings.tsx

Length of output: 293


Script:

#!/bin/bash
# Find OrgSettings files and check their content
echo "=== Finding OrgSettings files ==="
fd OrgSettings

echo -e "\n=== Checking content of OrgSettings files ==="
rg -A 5 "dropdown|Dropdown|SortingButton|sorting" $(fd OrgSettings)

Length of output: 25300

🧰 Tools
🪛 GitHub Check: Performs linting, formatting, type-checking, checking for different source and target branch

[warning] 133-133:
Some tests seem to be commented

Comment on lines +325 to +335
<SortingButton
sortingOptions={[
{ label: t('mostVolunteers'), value: 'volunteers_DESC' },
{ label: t('leastVolunteers'), value: 'volunteers_ASC' },
]}
onSortChange={(value) =>
setSortBy(value as 'volunteers_DESC' | 'volunteers_ASC')
}
dataTestIdPrefix="sort"
buttonLabel={tCommon('sort')}
/>
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add missing selectedOption prop to SortingButton.

The selectedOption prop is required to show the current selection in the button.

 <SortingButton
   sortingOptions={[
     { label: t('mostVolunteers'), value: 'volunteers_DESC' },
     { label: t('leastVolunteers'), value: 'volunteers_ASC' },
   ]}
+  selectedOption={sortBy === 'volunteers_DESC' ? t('mostVolunteers') : t('leastVolunteers')}
   onSortChange={(value) =>
     setSortBy(value as 'volunteers_DESC' | 'volunteers_ASC')
   }
   dataTestIdPrefix="sort"
   buttonLabel={tCommon('sort')}
 />
📝 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
<SortingButton
sortingOptions={[
{ label: t('mostVolunteers'), value: 'volunteers_DESC' },
{ label: t('leastVolunteers'), value: 'volunteers_ASC' },
]}
onSortChange={(value) =>
setSortBy(value as 'volunteers_DESC' | 'volunteers_ASC')
}
dataTestIdPrefix="sort"
buttonLabel={tCommon('sort')}
/>
<SortingButton
sortingOptions={[
{ label: t('mostVolunteers'), value: 'volunteers_DESC' },
{ label: t('leastVolunteers'), value: 'volunteers_ASC' },
]}
selectedOption={sortBy === 'volunteers_DESC' ? t('mostVolunteers') : t('leastVolunteers')}
onSortChange={(value) =>
setSortBy(value as 'volunteers_DESC' | 'volunteers_ASC')
}
dataTestIdPrefix="sort"
buttonLabel={tCommon('sort')}
/>

@@ -19,6 +19,7 @@ import { useQuery } from '@apollo/client';
import type { InterfaceUserCampaign } from 'utils/interfaces';
import { currencySymbols } from 'utils/currency';
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add currency validation

The currency symbol lookup could throw runtime errors if an invalid currency code is provided.

+ const getCurrencySymbol = (currency: string): string => {
+   return currencySymbols[currency as keyof typeof currencySymbols] || '$';
+ };

- currencySymbols[campaign.currency as keyof typeof currencySymbols]
+ getCurrencySymbol(campaign.currency)

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +14090 to +14103
/* .btn-primary{
--hover-bg: #6c757d !important;
}


.btn-primary:hover,
.btn-primary:active{
--hover-bg: hsl(var(--button-hue, 0), 100%, 60%) !important;
}

.btn-primary:hover,
.btn-primary:active{
--hover-bg: hsl(var(--button-hue, 0), 100%, 0%) !important;
} */
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove experimental code from production stylesheet.

Large blocks of commented experimental code should be removed from the production stylesheet. If these experiments are valuable:

  1. Move them to a separate development/experimental CSS file
  2. Consider creating a proper theming system using CSS custom properties
-/* .btn-primary{
-  --hover-bg: #6c757d !important; 
-}
-
-
-.btn-primary:hover,
-.btn-primary:active{
-  --hover-bg: hsl(var(--button-hue, 0), 100%, 60%) !important;
-}
-
-.btn-primary:hover,
-.btn-primary:active{
-  --hover-bg: hsl(var(--button-hue, 0), 100%, 0%) !important;
-} */

Copy link

codecov bot commented Jan 10, 2025

Codecov Report

Attention: Patch coverage is 65.31532% with 77 lines in your changes missing coverage. Please review.

Project coverage is 90.17%. Comparing base (f30baa5) to head (eb00b71).
Report is 1 commits behind head on develop.

Files with missing lines Patch % Lines
src/setup/askForDocker/askForDocker.ts 10.41% 43 Missing ⚠️
setup.ts 0.00% 26 Missing ⚠️
src/components/OrgListCard/useDebounce.tsx 50.00% 3 Missing and 1 partial ⚠️
src/components/OrgListCard/TruncatedText.tsx 91.30% 1 Missing and 1 partial ⚠️
src/screens/OrganizationPeople/AddMember.tsx 80.00% 0 Missing and 1 partial ⚠️
src/setup/updateEnvFile/updateEnvFile.ts 88.88% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           develop    #3234       +/-   ##
============================================
+ Coverage    19.99%   90.17%   +70.17%     
============================================
  Files          302      330       +28     
  Lines         7687     8488      +801     
  Branches      1677     1933      +256     
============================================
+ Hits          1537     7654     +6117     
+ Misses        6054      604     -5450     
- Partials        96      230      +134     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@palisadoes palisadoes merged commit 7ce0153 into PalisadoesFoundation:develop Jan 10, 2025
16 of 18 checks passed
@palisadoes palisadoes deleted the new-develop branch January 10, 2025 03:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ignore-sensitive-files-pr The contributor has a legitimate reason for editiing protected files
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant