-
-
Notifications
You must be signed in to change notification settings - Fork 872
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
Merge from develop-postgres
prior to code freeze
#3234
Conversation
…n of merging develop-postgres into develop cleanly
WalkthroughThis 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 Changes
Sequence DiagramsequenceDiagram
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
Possibly related issues
Possibly related PRs
Poem
Finishing Touches
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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
Documentation and Community
|
Our Pull Request Approval ProcessThanks for contributing! Testing Your CodeRemember, your PRs won't be reviewed until these criteria are met:
Our policies make our code better. ReviewersDo not assign reviewers. Our Queue Monitors will review your PR and assign them.
Reviewing Your CodeYour reviewer(s) will have the following roles:
CONTRIBUTING.mdRead our CONTRIBUTING.md file. Most importantly:
Other
|
There was a problem hiding this 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 conventionReact components should use PascalCase naming convention. Rename
eventListCard
toEventListCard
.-function eventListCard(props: InterfaceEventListCardProps): JSX.Element { +function EventListCard(props: InterfaceEventListCardProps): JSX.Element {
Line range hint
77-82
: Improve accessibility for clickable cardThe 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 coverageThe 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 coverageThe 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 functionalityThe 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 formulaThe 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 accessibilityThe 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 delayA 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 inaskAndSetRecaptcha
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 SettingsIn
askAndSetLogErrors
, when the user opts not to log errors, theALLOW_LOGS
environment variable is not updated. To maintain consistency, consider explicitly settingALLOW_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 ModificationAfter 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 fromaskAndSetDockerOption()
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 LogicThe 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 UsersThe 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:
- Error message content matches exactly
- 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:
- Invalid Docker port values
- Environment variable update failures
- 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 responsivenessWith the removal of the dropdown, consider adding responsive design improvements for the button-based navigation:
- Stack buttons vertically on smaller screens
- 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 coverageThe 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 conventionThe 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 thetitle
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
vsblockedUsers
(noun vs noun)- Consider standardizing to either
allMembers
/blockedMembers
orallUsers
/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.
- Define a type for search options
- 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 prefixThe current
searchBy
prefix could be more specific, likesearchTypeSelector
to better indicate its purpose.- dataTestIdPrefix="searchBy" + dataTestIdPrefix="searchTypeSelector"src/screens/OrgList/OrgList.spec.tsx (1)
528-528
: Consider consistent naming for test IDsThe 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 optionsConsider 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()
withprops.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 optionsThe 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 optionsThe 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 optionsBoth 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:
- Remove commented out code if no longer needed
- 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:
- Separating Bootstrap CSS into a vendor styles file
- Keeping only custom Talawa styles in this file
- 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
📒 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 codebaseThe 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.tsxLength of output: 1822
jest.config.js (1)
75-76
:⚠️ Potential issueReconsider lowering coverage thresholds.
Reducing coverage thresholds from 20% to 1% significantly lowers the quality bar and could allow untested code to reach production. Consider:
- Maintaining the original thresholds
- Gradually increasing coverage through incremental improvements
- 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 descriptionThe implementation safely handles undefined description using optional chaining and fallback to empty string.
setup.ts (1)
6-9
: Verify Import Paths and Module NamesThere might be inconsistencies in the import paths, particularly with
askAndUpdateTalawaApiUrl
being imported from'./src/setup/askForDocker/askForDocker'
. It seems unusual that a function namedaskAndUpdateTalawaApiUrl
is being imported from a module namedaskForDocker
. 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 navigationThe dropdown menu for settings navigation has been removed. While this simplifies the interface, please ensure this change:
- Aligns with the overall UX strategy
- Doesn't negatively impact mobile users who might have found the dropdown more convenient
- Is consistent with the behavior in other similar settings pages
src/screens/UserPortal/UserScreen/UserScreen.tsx (1)
20-20
: Verify chat functionality implementationThe 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-caseLength 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 suggestionAdd 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
fromvitest
is correctly added for the Jest to Vitest migration.
26-31
: LGTM!The mock for
react-toastify
is correctly migrated from Jest to Vitest usingvi.mock
.
33-40
: LGTM!The mock for
@mui/x-date-pickers/DateTimePicker
is correctly migrated usingvi.mock
andvi.importActual
to import the actual component.
51-51
: LGTM!Mock functions are correctly migrated from
jest.fn()
tovi.fn()
.Also applies to: 63-63, 68-68, 80-80
105-105
: LGTM!The cleanup function is correctly migrated from
jest.clearAllMocks()
tovi.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
toall
.Also applies to: 130-130
140-140
: LGTM!The test ID for the "Disabled" status filter is correctly updated from
statusDisabled
todisabled
.Also applies to: 142-142
157-157
: LGTM!The test ID for the "Active" status filter is correctly updated from
statusActive
toactive
.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
toall
.
192-192
: LGTM!The test ID for the "Group" filter is correctly updated from
filterGroup
togroup
.
213-213
: LGTM!The test ID for the "Individual" filter is correctly updated from
filterIndividual
toindividual
.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 thesubComponents
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 suggestionComponent name should follow React naming convention.
React component names should use PascalCase. Rename the component from
organizationFunds
toOrganizationFunds
.-const organizationFunds = (): JSX.Element => { +const OrganizationFunds = (): JSX.Element => {Likely invalid or redundant comment.
src/screens/UserPortal/Volunteer/Groups/Groups.tsx (1)
1-1
: 🛠️ Refactor suggestionComponent name should follow React naming convention.
React component names should use PascalCase. Rename the component from
groups
toGroups
.-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()
toit()
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 SortingButtonLength 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 SortingButtonLength 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 jsxLength 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 issueReplace 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 consistentThe 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 correctThe 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.
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 }; | ||
} |
There was a problem hiding this comment.
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.
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 }; | |
} |
{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> |
There was a problem hiding this comment.
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.
{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> |
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); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
import updateEnvFile from 'setup/updateEnvFile/updateEnvFile'; | ||
import { askForCustomPort } from 'setup/askForCustomPort/askForCustomPort'; | ||
import inquirer from 'inquirer'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
import inquirer from 'inquirer'; | ||
import updateEnvFile from 'setup/updateEnvFile/updateEnvFile'; | ||
import { askForDocker } from 'setup/askForDocker/askForDocker'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
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'; |
<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')} | ||
/> |
There was a problem hiding this comment.
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:
-
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.
-
The
buttonLabel
prop is redundant as it's set to the same value astitle
. WhenbuttonLabel
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
// 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 || '', | ||
// ); | ||
// }); |
There was a problem hiding this comment.
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:
- Updated to test the new SortingButton functionality, or
- 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
<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')} | ||
/> |
There was a problem hiding this comment.
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.
<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'; |
There was a problem hiding this comment.
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.
/* .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; | ||
} */ |
There was a problem hiding this comment.
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:
- Move them to a separate development/experimental CSS file
- 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;
-} */
Codecov ReportAttention: Patch coverage is
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. |
7ce0153
into
PalisadoesFoundation:develop
Merge from
develop-postgres
prior to code freezeSummary by CodeRabbit
Based on the comprehensive summary of changes, here are the high-level release notes:
Release Notes for Talawa Admin
New Features
SortingButton
component to replace dropdowns across various screensImprovements
Bug Fixes
Performance
Testing
Localization
Chores