From 1e0cd00b5e0d68ff8df01d117e49821738a8f863 Mon Sep 17 00:00:00 2001 From: sameersharmadev Date: Thu, 11 Dec 2025 09:03:17 +0530 Subject: [PATCH 01/18] fix: add contrast improvement styles to global error component --- frontend/__tests__/unit/global-error.test.tsx | 5 +++++ frontend/src/app/global-error.tsx | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/__tests__/unit/global-error.test.tsx b/frontend/__tests__/unit/global-error.test.tsx index 83105b058d..efff91b6c7 100644 --- a/frontend/__tests__/unit/global-error.test.tsx +++ b/frontend/__tests__/unit/global-error.test.tsx @@ -105,6 +105,11 @@ describe('GlobalError component', () => { expect(Sentry.captureException).toHaveBeenCalledWith(error) expect(screen.getByText('Server Error')).toBeInTheDocument() + const button = screen.getByRole('button', { name: 'Return to Home' }) + expect(button).toHaveClass( + 'bg-owasp-blue', + 'dark:bg-slate-800' + ) }) }) diff --git a/frontend/src/app/global-error.tsx b/frontend/src/app/global-error.tsx index 69d7b766fc..b10eeb1e8d 100644 --- a/frontend/src/app/global-error.tsx +++ b/frontend/src/app/global-error.tsx @@ -40,7 +40,8 @@ export const ErrorDisplay: React.FC = ({ statusCode, title, m

{message}

From 17140aa05bfcb14c7c1d8f8b272fa1946fa8d76c Mon Sep 17 00:00:00 2001 From: Kate Date: Thu, 11 Dec 2025 19:26:32 -0800 Subject: [PATCH 02/18] Address make-check issues --- frontend/__tests__/unit/global-error.test.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frontend/__tests__/unit/global-error.test.tsx b/frontend/__tests__/unit/global-error.test.tsx index efff91b6c7..eade658650 100644 --- a/frontend/__tests__/unit/global-error.test.tsx +++ b/frontend/__tests__/unit/global-error.test.tsx @@ -106,10 +106,7 @@ describe('GlobalError component', () => { expect(Sentry.captureException).toHaveBeenCalledWith(error) expect(screen.getByText('Server Error')).toBeInTheDocument() const button = screen.getByRole('button', { name: 'Return to Home' }) - expect(button).toHaveClass( - 'bg-owasp-blue', - 'dark:bg-slate-800' - ) + expect(button).toHaveClass('bg-owasp-blue', 'dark:bg-slate-800') }) }) From e5125ac8e32f2c5f7b504c22c8ea32b5c1d7db74 Mon Sep 17 00:00:00 2001 From: sameersharmadev Date: Wed, 10 Dec 2025 13:18:51 +0530 Subject: [PATCH 03/18] migrate to react-icons icons changed: fausers->hiusergroup, sun->mdlightmode, famoon->mddarkmode --- frontend/src/app/about/page.tsx | 42 ++--- .../src/app/board/[year]/candidates/page.tsx | 32 +--- frontend/src/app/chapters/page.tsx | 4 +- .../app/committees/[committeeKey]/page.tsx | 20 +-- frontend/src/app/committees/page.tsx | 4 +- .../src/app/community/snapshots/[id]/page.tsx | 10 +- frontend/src/app/community/snapshots/page.tsx | 6 +- frontend/src/app/contribute/page.tsx | 9 +- frontend/src/app/members/[memberKey]/page.tsx | 18 +-- frontend/src/app/members/page.tsx | 4 +- frontend/src/app/my/mentorship/page.tsx | 7 +- .../[moduleKey]/issues/[issueId]/page.tsx | 25 ++- .../organizations/[organizationKey]/page.tsx | 20 +-- .../repositories/[repositoryKey]/page.tsx | 21 +-- frontend/src/app/organizations/page.tsx | 4 +- frontend/src/app/page.tsx | 108 ++++++------- .../src/app/projects/[projectKey]/page.tsx | 20 +-- .../dashboard/metrics/[projectKey]/page.tsx | 40 ++--- .../app/projects/dashboard/metrics/page.tsx | 21 +-- frontend/src/app/projects/dashboard/page.tsx | 51 +++--- frontend/src/app/projects/page.tsx | 5 +- frontend/src/app/settings/api-keys/page.tsx | 32 ++-- frontend/src/components/AnchorTitle.tsx | 5 +- frontend/src/components/Badges.tsx | 5 +- frontend/src/components/BarChart.tsx | 4 +- frontend/src/components/BreadCrumbs.tsx | 10 +- frontend/src/components/CalendarButton.tsx | 7 +- frontend/src/components/Card.tsx | 39 +++-- frontend/src/components/CardDetailsPage.tsx | 72 +++++---- frontend/src/components/DashboardCard.tsx | 8 +- frontend/src/components/DisplayIcon.tsx | 15 +- frontend/src/components/DonutBarChart.tsx | 4 +- frontend/src/components/EntityActions.tsx | 8 +- frontend/src/components/Footer.tsx | 34 ++-- .../components/GeneralCompliantComponent.tsx | 14 +- frontend/src/components/Header.tsx | 30 ++-- frontend/src/components/HealthMetrics.tsx | 24 +-- frontend/src/components/InfoBlock.tsx | 8 +- frontend/src/components/InfoItem.tsx | 12 +- frontend/src/components/ItemCardList.tsx | 4 +- frontend/src/components/Leaders.tsx | 8 +- frontend/src/components/LineChart.tsx | 4 +- frontend/src/components/LoginPageContent.tsx | 10 +- .../src/components/MenteeContributorsList.tsx | 7 +- frontend/src/components/MenteeIssues.tsx | 22 +-- frontend/src/components/MetricsPDFButton.tsx | 6 +- frontend/src/components/Milestones.tsx | 25 ++- frontend/src/components/Modal.tsx | 7 +- frontend/src/components/ModeToggle.tsx | 12 +- frontend/src/components/ModuleCard.tsx | 25 ++- frontend/src/components/MultiSearch.tsx | 38 ++--- frontend/src/components/NavButton.tsx | 7 +- frontend/src/components/NavDropDown.tsx | 9 +- frontend/src/components/Pagination.tsx | 5 +- .../components/ProjectTypeDashboardCard.tsx | 4 +- .../components/ProjectsDashboardDropDown.tsx | 23 ++- .../components/ProjectsDashboardNavBar.tsx | 10 +- frontend/src/components/RecentIssues.tsx | 9 +- .../src/components/RecentPullRequests.tsx | 9 +- frontend/src/components/RecentReleases.tsx | 4 +- frontend/src/components/Release.tsx | 7 +- frontend/src/components/RepositoryCard.tsx | 12 +- frontend/src/components/ScrollToTop.tsx | 5 +- frontend/src/components/Search.tsx | 9 +- frontend/src/components/SecondaryCard.tsx | 8 +- frontend/src/components/ShowMoreButton.tsx | 7 +- frontend/src/components/SingleModuleCard.tsx | 7 +- frontend/src/components/SnapshotCard.tsx | 10 +- frontend/src/components/SortBy.tsx | 13 +- frontend/src/components/StatusBadge.tsx | 17 +- frontend/src/components/ToggleableList.tsx | 8 +- .../src/components/TopContributorsList.tsx | 4 +- frontend/src/components/UserCard.tsx | 26 +-- frontend/src/components/UserMenu.tsx | 5 +- frontend/src/types/button.ts | 6 +- frontend/src/types/card.ts | 6 +- frontend/src/types/icon.ts | 3 +- frontend/src/types/level.ts | 3 +- frontend/src/utils/constants.ts | 18 ++- frontend/src/utils/data.ts | 151 ++++++------------ frontend/src/utils/milestoneProgress.ts | 8 +- frontend/src/utils/urlIconMappings.ts | 84 +++++----- frontend/src/utils/utility.ts | 3 +- frontend/src/wrappers/IconWrapper.tsx | 13 ++ 84 files changed, 648 insertions(+), 835 deletions(-) create mode 100644 frontend/src/wrappers/IconWrapper.tsx diff --git a/frontend/src/app/about/page.tsx b/frontend/src/app/about/page.tsx index 798b9c20bb..8f0e336dd2 100644 --- a/frontend/src/app/about/page.tsx +++ b/frontend/src/app/about/page.tsx @@ -1,22 +1,14 @@ 'use client' import { useQuery } from '@apollo/client/react' -import { - faCircleCheck, - faClock, - faMapSigns, - faScroll, - faUsers, - faTools, - faBullseye, - faUser, - faUsersGear, -} from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { Tooltip } from '@heroui/tooltip' import upperFirst from 'lodash/upperFirst' import Image from 'next/image' import Link from 'next/link' import { useEffect, useState } from 'react' +import { FaMapSigns, FaTools } from 'react-icons/fa' +import { FaCircleCheck, FaClock, FaScroll, FaBullseye, FaUser, FaUsersGear } from 'react-icons/fa6' +import { HiUserGroup } from 'react-icons/hi' +import { IconWrapper } from 'wrappers/IconWrapper' import { ErrorDisplay, handleAppError } from 'app/global-error' import { GetProjectMetadataDocument, @@ -61,12 +53,12 @@ const getMilestoneStatus = (progress: number): string => { const getMilestoneIcon = (progress: number) => { if (progress === 100) { - return faCircleCheck + return FaCircleCheck } if (progress > 0) { - return faUsersGear + return FaUsersGear } - return faClock + return FaClock } const About = () => { @@ -140,16 +132,16 @@ const About = () => {

About

- }> + }>

{missionContent.mission}

- }> + }>

{missionContent.whoItsFor}

- }> + }>
{keyFeatures.map((feature) => (
@@ -165,13 +157,13 @@ const About = () => { {topContributors && ( )} - }> + }>
{technologies.map((tech) => ( @@ -204,7 +196,7 @@ const About = () => {
- }> + }>

{getInvolvedContent.description}

    {getInvolvedContent.ways.map((way) => ( @@ -217,7 +209,7 @@ const About = () => { {projectMetadata.recentMilestones.length > 0 && ( - }> + }>
    {[...projectMetadata.recentMilestones] .filter((milestone) => milestone.state !== 'closed') @@ -248,7 +240,7 @@ const About = () => { showArrow > - +
    @@ -259,7 +251,7 @@ const About = () => {
)} - }> + }> {projectStory.map((text) => (
@@ -268,7 +260,7 @@ const About = () => {
))} - }> + }>
{[...projectTimeline].reverse().map((milestone, index) => (
diff --git a/frontend/src/app/board/[year]/candidates/page.tsx b/frontend/src/app/board/[year]/candidates/page.tsx index a5b87a718c..2f0c03b061 100644 --- a/frontend/src/app/board/[year]/candidates/page.tsx +++ b/frontend/src/app/board/[year]/candidates/page.tsx @@ -1,13 +1,5 @@ 'use client' import { useQuery, useApolloClient } from '@apollo/client/react' -import { faLinkedin } from '@fortawesome/free-brands-svg-icons' -import { - faCode, - faCodeBranch, - faCodeMerge, - faExclamationCircle, -} from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { Button } from '@heroui/button' import dayjs from 'dayjs' import relativeTime from 'dayjs/plugin/relativeTime' @@ -16,6 +8,8 @@ import Image from 'next/image' import Link from 'next/link' import { useParams } from 'next/navigation' import { useEffect, useState } from 'react' +import { FaCode, FaExclamationCircle } from 'react-icons/fa' +import { FaLinkedin, FaCodeBranch, FaCodeMerge } from 'react-icons/fa6' import { handleAppError, ErrorDisplay } from 'app/global-error' import { @@ -346,7 +340,7 @@ const BoardCandidatesPage = () => { className="text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300" aria-label={`${candidate.memberName}'s LinkedIn profile`} > - + )} @@ -426,10 +420,7 @@ const BoardCandidatesPage = () => {
- +

Commits

@@ -438,10 +429,7 @@ const BoardCandidatesPage = () => {

- +

PRs

@@ -450,10 +438,7 @@ const BoardCandidatesPage = () => {

- +

Issues

@@ -462,10 +447,7 @@ const BoardCandidatesPage = () => {

- +

Total

diff --git a/frontend/src/app/chapters/page.tsx b/frontend/src/app/chapters/page.tsx index e79d3c81b0..03236429e4 100644 --- a/frontend/src/app/chapters/page.tsx +++ b/frontend/src/app/chapters/page.tsx @@ -2,7 +2,7 @@ import { useSearchPage } from 'hooks/useSearchPage' import { useRouter } from 'next/navigation' import { useEffect, useState } from 'react' -import FontAwesomeIconWrapper from 'wrappers/FontAwesomeIconWrapper' +import { FaRightToBracket } from 'react-icons/fa6' import { fetchAlgoliaData } from 'server/fetchAlgoliaData' import type { AlgoliaResponse } from 'types/algolia' import type { Chapter } from 'types/chapter' @@ -57,7 +57,7 @@ const ChaptersPage = () => { const submitButton = { label: 'View Details', - icon: , + icon: , onclick: handleButtonClick, } diff --git a/frontend/src/app/committees/[committeeKey]/page.tsx b/frontend/src/app/committees/[committeeKey]/page.tsx index dea63a3afe..2cc02da765 100644 --- a/frontend/src/app/committees/[committeeKey]/page.tsx +++ b/frontend/src/app/committees/[committeeKey]/page.tsx @@ -1,15 +1,11 @@ 'use client' import { useQuery } from '@apollo/client/react' -import { - faCode, - faCodeFork, - faExclamationCircle, - faStar, - faUsers, -} from '@fortawesome/free-solid-svg-icons' import Link from 'next/link' import { useParams } from 'next/navigation' import { useState, useEffect } from 'react' +import { FaExclamationCircle } from 'react-icons/fa' +import { FaCode, FaCodeFork, FaStar } from 'react-icons/fa6' +import { HiUserGroup } from 'react-icons/hi' import { ErrorDisplay, handleAppError } from 'app/global-error' import { GetCommitteeDataDocument } from 'types/__generated__/committeeQueries.generated' import type { Committee } from 'types/committee' @@ -67,16 +63,16 @@ export default function CommitteeDetailsPage() { ] const committeeStats = [ - { icon: faUsers, value: committee.contributorsCount, unit: 'Contributor' }, - { icon: faCodeFork, value: committee.forksCount, unit: 'Fork' }, - { icon: faStar, value: committee.starsCount, unit: 'Star' }, + { icon: HiUserGroup, value: committee.contributorsCount, unit: 'Contributor' }, + { icon: FaCodeFork, value: committee.forksCount, unit: 'Fork' }, + { icon: FaStar, value: committee.starsCount, unit: 'Star' }, { - icon: faCode, + icon: FaCode, value: committee.repositoriesCount, unit: 'Repository', pluralizedName: 'Repositories', }, - { icon: faExclamationCircle, value: committee.issuesCount, unit: 'Issue' }, + { icon: FaExclamationCircle, value: committee.issuesCount, unit: 'Issue' }, ] return ( diff --git a/frontend/src/app/committees/page.tsx b/frontend/src/app/committees/page.tsx index e6d59dc054..748757e269 100644 --- a/frontend/src/app/committees/page.tsx +++ b/frontend/src/app/committees/page.tsx @@ -1,7 +1,7 @@ 'use client' import { useSearchPage } from 'hooks/useSearchPage' import { useRouter } from 'next/navigation' -import FontAwesomeIconWrapper from 'wrappers/FontAwesomeIconWrapper' +import { FaRightToBracket } from 'react-icons/fa6' import type { Committee } from 'types/committee' import { getFilteredIcons, handleSocialUrls } from 'utils/utility' import Card from 'components/Card' @@ -31,7 +31,7 @@ const CommitteesPage = () => { const submitButton = { label: 'View Details', - icon: , + icon: , onclick: handleButtonClick, } diff --git a/frontend/src/app/community/snapshots/[id]/page.tsx b/frontend/src/app/community/snapshots/[id]/page.tsx index 2cfc0f215e..94b4efcacc 100644 --- a/frontend/src/app/community/snapshots/[id]/page.tsx +++ b/frontend/src/app/community/snapshots/[id]/page.tsx @@ -1,10 +1,8 @@ 'use client' import { useQuery } from '@apollo/client/react' -import { faCalendar } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { useRouter, useParams } from 'next/navigation' import React, { useState, useEffect } from 'react' -import FontAwesomeIconWrapper from 'wrappers/FontAwesomeIconWrapper' +import { FaCalendar, FaRightToBracket } from 'react-icons/fa6' import { handleAppError, ErrorDisplay } from 'app/global-error' import { GetSnapshotDetailsDocument } from 'types/__generated__/snapshotQueries.generated' import type { Chapter } from 'types/chapter' @@ -49,7 +47,7 @@ const SnapshotDetailsPage: React.FC = () => { const submitButton = { label: 'View Details', - icon: , + icon: , onclick: handleButtonClick, } @@ -78,7 +76,7 @@ const SnapshotDetailsPage: React.FC = () => { const submitButton = { label: 'View Details', - icon: , + icon: , onclick: handleButtonClick, } @@ -119,7 +117,7 @@ const SnapshotDetailsPage: React.FC = () => {

- + {formatDate(snapshot.startAt)} - {formatDate(snapshot.endAt)} diff --git a/frontend/src/app/community/snapshots/page.tsx b/frontend/src/app/community/snapshots/page.tsx index ea23a3577b..11d864ca87 100644 --- a/frontend/src/app/community/snapshots/page.tsx +++ b/frontend/src/app/community/snapshots/page.tsx @@ -3,7 +3,7 @@ import { useQuery } from '@apollo/client/react' import { addToast } from '@heroui/toast' import { useRouter } from 'next/navigation' import React, { useState, useEffect } from 'react' -import FontAwesomeIconWrapper from 'wrappers/FontAwesomeIconWrapper' +import { FaRightToBracket } from 'react-icons/fa6' import { GetCommunitySnapshotsDocument } from 'types/__generated__/snapshotQueries.generated' import type { Snapshot } from 'types/snapshot' import SnapshotSkeleton from 'components/skeletons/SnapshotSkeleton' @@ -41,8 +41,8 @@ const SnapshotsPage: React.FC = () => { const renderSnapshotCard = (snapshot: Snapshot) => { const SubmitButton = { - label: 'View Snapshot', - icon: , + label: 'View Details', + icon: , onclick: () => handleButtonClick(snapshot), } diff --git a/frontend/src/app/contribute/page.tsx b/frontend/src/app/contribute/page.tsx index 5d07bf3a52..898e982e81 100644 --- a/frontend/src/app/contribute/page.tsx +++ b/frontend/src/app/contribute/page.tsx @@ -1,12 +1,9 @@ 'use client' -import { faGithub } from '@fortawesome/free-brands-svg-icons' import { useSearchPage } from 'hooks/useSearchPage' import React, { useState } from 'react' - -import FontAwesomeIconWrapper from 'wrappers/FontAwesomeIconWrapper' +import { FaGithub, FaWandMagicSparkles } from 'react-icons/fa6' import type { Issue } from 'types/issue' import { getFilteredIcons } from 'utils/utility' - import Card from 'components/Card' import DialogComp from 'components/Modal' import SearchPageLayout from 'components/SearchPageLayout' @@ -33,13 +30,13 @@ const ContributePage = () => { const SubmitButton = { label: 'Read More', - icon: , + icon: , onclick: () => setModalOpenIndex(index), } const viewIssueButton = { label: 'View Issue', - icon: , + icon: , url: issue.url, } diff --git a/frontend/src/app/members/[memberKey]/page.tsx b/frontend/src/app/members/[memberKey]/page.tsx index e4a56e148d..6464d956f5 100644 --- a/frontend/src/app/members/[memberKey]/page.tsx +++ b/frontend/src/app/members/[memberKey]/page.tsx @@ -1,16 +1,11 @@ 'use client' import { useQuery } from '@apollo/client/react' -import { - faCodeMerge, - faFolderOpen, - faPersonWalkingArrowRight, - faUserPlus, -} from '@fortawesome/free-solid-svg-icons' import Image from 'next/image' import Link from 'next/link' import { useParams } from 'next/navigation' import { useTheme } from 'next-themes' import React, { useState, useEffect, useRef } from 'react' +import { FaCodeMerge, FaFolderOpen, FaPersonWalkingArrowRight, FaUserPlus } from 'react-icons/fa6' import { handleAppError, ErrorDisplay } from 'app/global-error' import { GetUserDataDocument } from 'types/__generated__/userQueries.generated' @@ -76,7 +71,6 @@ const UserDetailsPage: React.FC = () => { }, [memberKey, user]) const formattedBio = user?.bio?.split(' ').map((word, index) => { - // Regex to match GitHub usernames, but if last character is not a word character or @, it's a punctuation const mentionMatch = word.match(/^@([\w-]+(?:\.[\w-]+)*)([^\w@])?$/) if (mentionMatch && mentionMatch.length > 1) { const username = mentionMatch[1] @@ -121,15 +115,15 @@ const UserDetailsPage: React.FC = () => { ] const userStats = [ - { icon: faPersonWalkingArrowRight, value: user?.followersCount || 0, unit: 'Follower' }, - { icon: faUserPlus, value: user?.followingCount || 0, unit: 'Following' }, + { icon: FaPersonWalkingArrowRight, value: user?.followersCount || 0, unit: 'Follower' }, + { icon: FaUserPlus, value: user?.followingCount || 0, unit: 'Following' }, { - icon: faFolderOpen, + icon: FaFolderOpen, pluralizedName: 'Repositories', unit: 'Repository', value: user?.publicRepositoriesCount ?? 0, }, - { icon: faCodeMerge, value: user?.contributionsCount || 0, unit: 'Contribution' }, + { icon: FaCodeMerge, value: user?.contributionsCount || 0, unit: 'Contribution' }, ] const Heatmap = () => { @@ -211,7 +205,7 @@ const UserDetailsPage: React.FC = () => { diff --git a/frontend/src/app/members/page.tsx b/frontend/src/app/members/page.tsx index 88ca788835..73726c8819 100644 --- a/frontend/src/app/members/page.tsx +++ b/frontend/src/app/members/page.tsx @@ -1,7 +1,7 @@ 'use client' import { useSearchPage } from 'hooks/useSearchPage' import { useRouter } from 'next/navigation' -import FontAwesomeIconWrapper from 'wrappers/FontAwesomeIconWrapper' +import { FaRightToBracket } from 'react-icons/fa6' import type { User } from 'types/user' import SearchPageLayout from 'components/SearchPageLayout' import UserCard from 'components/UserCard' @@ -29,7 +29,7 @@ const UsersPage = () => { const renderUserCard = (user: User) => { const submitButton = { label: 'View Details', - icon: , + icon: , onclick: () => handleButtonClick(user), } diff --git a/frontend/src/app/my/mentorship/page.tsx b/frontend/src/app/my/mentorship/page.tsx index 04bb8a0093..f622a68a66 100644 --- a/frontend/src/app/my/mentorship/page.tsx +++ b/frontend/src/app/my/mentorship/page.tsx @@ -1,13 +1,12 @@ 'use client' import { useQuery } from '@apollo/client/react' -import { faPlus, faGraduationCap } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { addToast } from '@heroui/toast' import { debounce } from 'lodash' import { useRouter, useSearchParams } from 'next/navigation' import { useSession } from 'next-auth/react' import React, { useEffect, useMemo, useState } from 'react' +import { FaPlus, FaGraduationCap } from 'react-icons/fa6' import { GetMyProgramsDocument } from 'types/__generated__/programsQueries.generated' import type { ExtendedSession } from 'types/auth' @@ -89,7 +88,7 @@ const MyMentorshipPage: React.FC = () => { if (!isProjectLeader) { return (
- +

Access Denied

Only project leaders can access this page. @@ -106,7 +105,7 @@ const MyMentorshipPage: React.FC = () => {

Programs you've created or joined

- + {'Create Program'}
diff --git a/frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/issues/[issueId]/page.tsx b/frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/issues/[issueId]/page.tsx index 322ef9f27b..c8bcf54c50 100644 --- a/frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/issues/[issueId]/page.tsx +++ b/frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/issues/[issueId]/page.tsx @@ -1,19 +1,12 @@ 'use client' import { useQuery } from '@apollo/client/react' -import { - faCodeBranch, - faLink, - faPlus, - faTags, - faUsers, - faXmark, -} from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { useIssueMutations } from 'hooks/useIssueMutations' import Image from 'next/image' import Link from 'next/link' import { useParams } from 'next/navigation' +import { FaCodeBranch, FaLink, FaPlus, FaTags, FaXmark } from 'react-icons/fa6' +import { HiUserGroup } from 'react-icons/hi' import { ErrorDisplay } from 'app/global-error' import { GetModuleIssueViewDocument } from 'types/__generated__/issueQueries.generated' import ActionButton from 'components/ActionButton' @@ -134,7 +127,7 @@ const ModuleIssueDetailsPage = () => {
- View on GitHub + View on GitHub
@@ -232,7 +225,7 @@ const ModuleIssueDetailsPage = () => {

- +
Labels
@@ -254,7 +247,7 @@ const ModuleIssueDetailsPage = () => {

- +
Assignees
@@ -300,7 +293,7 @@ const ModuleIssueDetailsPage = () => { className={getButtonClassName(!issueId || unassigning)} title={unassigning ? 'Unassigning…' : `Unassign @${a.login}`} > - +

))} @@ -308,7 +301,7 @@ const ModuleIssueDetailsPage = () => {
)} - +
{issue.pullRequests?.length ? ( issue.pullRequests.map((pr) => ( @@ -382,7 +375,7 @@ const ModuleIssueDetailsPage = () => {

- +
Interested Users
@@ -426,7 +419,7 @@ const ModuleIssueDetailsPage = () => { !issueId ? 'Loading issue…' : assigning ? 'Assigning…' : 'Assign to this user' } > - + Assign

diff --git a/frontend/src/app/organizations/[organizationKey]/page.tsx b/frontend/src/app/organizations/[organizationKey]/page.tsx index 1541f91d95..a466dcf927 100644 --- a/frontend/src/app/organizations/[organizationKey]/page.tsx +++ b/frontend/src/app/organizations/[organizationKey]/page.tsx @@ -1,15 +1,11 @@ 'use client' import { useQuery } from '@apollo/client/react' -import { - faCodeFork, - faExclamationCircle, - faFolderOpen, - faStar, - faUsers, -} from '@fortawesome/free-solid-svg-icons' import Link from 'next/link' import { useParams } from 'next/navigation' import { useState, useEffect } from 'react' +import { FaExclamationCircle } from 'react-icons/fa' +import { FaCodeFork, FaFolderOpen, FaStar } from 'react-icons/fa6' +import { HiUserGroup } from 'react-icons/hi' import { handleAppError, ErrorDisplay } from 'app/global-error' import { GetOrganizationDataDocument } from 'types/__generated__/organizationQueries.generated' import { formatDate } from 'utils/dateFormatter' @@ -85,27 +81,27 @@ const OrganizationDetailsPage = () => { const organizationStats = [ { - icon: faStar, + icon: FaStar, value: organization.stats.totalStars, unit: 'Star', }, { - icon: faCodeFork, + icon: FaCodeFork, value: organization.stats.totalForks, unit: 'Fork', }, { - icon: faUsers, + icon: HiUserGroup, value: organization.stats.totalContributors, unit: 'Contributor', }, { - icon: faExclamationCircle, + icon: FaExclamationCircle, value: organization.stats.totalIssues, unit: 'Issue', }, { - icon: faFolderOpen, + icon: FaFolderOpen, value: organization.stats.totalRepositories, unit: 'Repository', pluralizedName: 'Repositories', diff --git a/frontend/src/app/organizations/[organizationKey]/repositories/[repositoryKey]/page.tsx b/frontend/src/app/organizations/[organizationKey]/repositories/[repositoryKey]/page.tsx index 9e4d82c3b1..0ee25859ec 100644 --- a/frontend/src/app/organizations/[organizationKey]/repositories/[repositoryKey]/page.tsx +++ b/frontend/src/app/organizations/[organizationKey]/repositories/[repositoryKey]/page.tsx @@ -1,15 +1,11 @@ 'use client' import { useQuery } from '@apollo/client/react' -import { - faCodeCommit, - faCodeFork, - faExclamationCircle, - faStar, - faUsers, -} from '@fortawesome/free-solid-svg-icons' import Link from 'next/link' import { useParams } from 'next/navigation' import { useEffect, useState } from 'react' +import { FaExclamationCircle } from 'react-icons/fa' +import { FaCodeCommit, FaCodeFork, FaStar } from 'react-icons/fa6' +import { HiUserGroup } from 'react-icons/hi' import { handleAppError, ErrorDisplay } from 'app/global-error' import { GetRepositoryDataDocument } from 'types/__generated__/repositoryQueries.generated' import type { Contributor } from 'types/contributor' @@ -81,28 +77,27 @@ const RepositoryDetailsPage = () => { const RepositoryStats = [ { - icon: faStar, + icon: FaStar, value: repository.starsCount, unit: 'Star', }, { - icon: faCodeFork, + icon: FaCodeFork, value: repository.forksCount, unit: 'Fork', }, { - icon: faUsers, + icon: HiUserGroup, value: repository.contributorsCount, unit: 'Contributor', }, - { - icon: faExclamationCircle, + icon: FaExclamationCircle, value: repository.openIssuesCount, unit: 'Issue', }, { - icon: faCodeCommit, + icon: FaCodeCommit, value: repository.commitsCount, unit: 'Commit', }, diff --git a/frontend/src/app/organizations/page.tsx b/frontend/src/app/organizations/page.tsx index 754d517045..c8056ae101 100644 --- a/frontend/src/app/organizations/page.tsx +++ b/frontend/src/app/organizations/page.tsx @@ -1,7 +1,7 @@ 'use client' import { useSearchPage } from 'hooks/useSearchPage' import { useRouter } from 'next/navigation' -import FontAwesomeIconWrapper from 'wrappers/FontAwesomeIconWrapper' +import { FaRightToBracket } from 'react-icons/fa6' import type { Organization } from 'types/organization' import SearchPageLayout from 'components/SearchPageLayout' import UserCard from 'components/UserCard' @@ -30,7 +30,7 @@ const OrganizationPage = () => { const submitButton = { label: 'View Profile', - icon: , + icon: , onclick: handleButtonClick, } diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index 84c2301fed..deb35f7b09 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -1,25 +1,24 @@ 'use client' import { useQuery } from '@apollo/client/react' -import { IconProp } from '@fortawesome/fontawesome-svg-core' -import { - faBook, - faCalendar, - faCalendarAlt, - faCode, - faFileCode, - faFolder, - faGlobe, - faMapMarkerAlt, - faNewspaper, - faTag, - faUser, - faUsers, -} from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { addToast } from '@heroui/toast' import upperFirst from 'lodash/upperFirst' import Link from 'next/link' import { useEffect, useState } from 'react' +import { IconType } from 'react-icons' +import { FaCalendarAlt, FaMapMarkerAlt } from 'react-icons/fa' +import { + FaBook, + FaCalendar, + FaCode, + FaFileCode, + FaFolder, + FaGlobe, + FaNewspaper, + FaTag, + FaUser, +} from 'react-icons/fa6' +import { HiUserGroup } from 'react-icons/hi' +import { IconWrapper } from 'wrappers/IconWrapper' import { fetchAlgoliaData } from 'server/fetchAlgoliaData' import { GetMainPageDataDocument } from 'types/__generated__/homeQueries.generated' import type { AlgoliaResponse } from 'types/algolia' @@ -96,18 +95,18 @@ export default function Home() { return } - const getProjectIcon = (projectType: string) => { + const getProjectIcon = (projectType: string): IconType => { switch (projectType.toLowerCase()) { case 'code': - return faCode + return FaCode case 'documentation': - return faBook + return FaBook case 'other': - return faFileCode + return FaFileCode case 'tool': - return faTag + return FaTag default: - return faFileCode + return FaFileCode } } @@ -156,7 +155,7 @@ export default function Home() {
@@ -176,27 +175,27 @@ export default function Home() { > +
- + + {formatDateRange(event.startDate, event.endDate)}
{event.suggestedLocation && (
- +
)} @@ -217,7 +216,7 @@ export default function Home() {
@@ -238,11 +237,11 @@ export default function Home() {
- + {formatDate(chapter.createdAt)}
- +
@@ -250,7 +249,7 @@ export default function Home() { {chapter.leaders.length > 0 && (
{' '} - +
)} @@ -259,7 +258,7 @@ export default function Home() {
@@ -277,20 +276,17 @@ export default function Home() {
- + {formatDate(project.createdAt)}
- +
{project.leaders.length > 0 && (
- +
)} @@ -301,11 +297,7 @@ export default function Home() {
- +
@@ -334,7 +326,7 @@ export default function Home() {
@@ -360,11 +352,11 @@ export default function Home() {
- + {formatDate(post.publishedAt)}
- +
diff --git a/frontend/src/app/projects/[projectKey]/page.tsx b/frontend/src/app/projects/[projectKey]/page.tsx index 77fbf46021..f7fc8a1169 100644 --- a/frontend/src/app/projects/[projectKey]/page.tsx +++ b/frontend/src/app/projects/[projectKey]/page.tsx @@ -1,16 +1,12 @@ 'use client' import { useQuery } from '@apollo/client/react' -import { - faCodeFork, - faExclamationCircle, - faFolderOpen, - faStar, - faUsers, -} from '@fortawesome/free-solid-svg-icons' import upperFirst from 'lodash/upperFirst' import Link from 'next/link' import { useParams } from 'next/navigation' import { useState, useEffect } from 'react' +import { FaExclamationCircle } from 'react-icons/fa' +import { FaCodeFork, FaFolderOpen, FaStar } from 'react-icons/fa6' +import { HiUserGroup } from 'react-icons/hi' import { ErrorDisplay, handleAppError } from 'app/global-error' import { GetProjectDocument } from 'types/__generated__/projectQueries.generated' import type { Contributor } from 'types/contributor' @@ -69,20 +65,20 @@ const ProjectDetailsPage = () => { }, ] const projectStats = [ - { icon: faStar, value: project.starsCount, unit: 'Star' }, - { icon: faCodeFork, value: project.forksCount, unit: 'Fork' }, + { icon: FaStar, value: project.starsCount, unit: 'Star' }, + { icon: FaCodeFork, value: project.forksCount, unit: 'Fork' }, { - icon: faUsers, + icon: HiUserGroup, value: project.contributorsCount, unit: 'Contributor', }, { - icon: faExclamationCircle, + icon: FaExclamationCircle, value: project.issuesCount, unit: 'Issue', }, { - icon: faFolderOpen, + icon: FaFolderOpen, value: project.repositoriesCount, unit: 'Repository', pluralizedName: 'Repositories', diff --git a/frontend/src/app/projects/dashboard/metrics/[projectKey]/page.tsx b/frontend/src/app/projects/dashboard/metrics/[projectKey]/page.tsx index 08a934aa64..020acd6ccf 100644 --- a/frontend/src/app/projects/dashboard/metrics/[projectKey]/page.tsx +++ b/frontend/src/app/projects/dashboard/metrics/[projectKey]/page.tsx @@ -1,18 +1,18 @@ 'use client' import { useQuery } from '@apollo/client/react' -import { - faPeopleGroup, - faCodeFork, - faDollar, - faCodePullRequest, - faChartArea, - faExclamationCircle, - faHandshake, - faStar, - faTags, -} from '@fortawesome/free-solid-svg-icons' import { useParams } from 'next/navigation' import { FC, useState, useEffect } from 'react' +import { + FaPeopleGroup, + FaCodeFork, + FaDollarSign, + FaCodePullRequest, + FaChartArea, + FaExclamationCircle, + FaHandshake, + FaStar, + FaTags, +} from 'react-icons/fa6' import { handleAppError } from 'app/global-error' import { GetProjectHealthMetricsDetailsDocument } from 'types/__generated__/projectsHealthDashboardQueries.generated' import { HealthMetricsProps } from 'types/healthMetrics' @@ -78,7 +78,7 @@ const ProjectHealthMetricsDetails: FC = () => { ? 'Funding Requirements Compliant' : 'Funding Requirements Not Compliant' } - icon={faDollar} + icon={FaDollarSign} compliant={metricsLatest.isFundingRequirementsCompliant} /> { ? 'Leader Requirements Compliant' : 'Leader Requirements Not Compliant' } - icon={faHandshake} + icon={FaHandshake} compliant={metricsLatest.isLeaderRequirementsCompliant} />
@@ -95,7 +95,7 @@ const ProjectHealthMetricsDetails: FC = () => {
{ /> {
{ /> {
{ /> {
{ - if (isActiveSortDesc) { - return faSortDown - } else if (isActiveSortAsc) { - return faSortUp - } else { - return faSort - } - })() + const iconType: IconType = isActiveSortDesc ? FaSortDown : isActiveSortAsc ? FaSortUp : FaSort return (
@@ -114,8 +107,8 @@ const SortableColumnHeader: FC<{ aria-pressed={isActive} > {label} - @@ -272,7 +265,7 @@ const MetricsPage: FC = () => {
{
) } + const projectsCardsItems: { type: 'healthy' | 'needsAttention' | 'unhealthy' count: number - icon: IconProp + icon: IconType }[] = [ { type: 'healthy', count: stats.projectsCountHealthy, - icon: faCheck, + icon: FaCheck, }, { type: 'needsAttention', count: stats.projectsCountNeedAttention, - icon: faWarning, + icon: FaTriangleExclamation, }, { type: 'unhealthy', count: stats.projectsCountUnhealthy, - icon: faRectangleXmark, + icon: FaRectangleXmark, }, ] - const dashboardCardsItems = [ + const dashboardCardsItems: { + title: string + icon: IconType + stats?: string + }[] = [ { title: 'Average Score', - icon: faChartLine, + icon: FaChartLine, stats: `${stats.averageScore.toFixed(1)}`, }, { title: 'Contributors', - icon: faUsers, + icon: HiUserGroup, stats: millify(stats.totalContributors), }, { title: 'Forks', - icon: faCodeBranch, + icon: FaCodeBranch, stats: millify(stats.totalForks), }, { title: 'Stars', - icon: faStar, + icon: FaStar, stats: millify(stats.totalStars), }, ] @@ -118,7 +123,7 @@ const ProjectsDashboardPage: FC = () => {
{ /> { const { items: projects, @@ -39,7 +40,7 @@ const ProjectsPage = () => { const submitButton = { label: 'View Details', - icon: , + icon: , onclick: handleButtonClick, } diff --git a/frontend/src/app/settings/api-keys/page.tsx b/frontend/src/app/settings/api-keys/page.tsx index 94739c7f02..e5bcaf9c6d 100644 --- a/frontend/src/app/settings/api-keys/page.tsx +++ b/frontend/src/app/settings/api-keys/page.tsx @@ -1,22 +1,13 @@ 'use client' import { useMutation, useQuery } from '@apollo/client/react' -import { - faSpinner, - faKey, - faPlus, - faCopy, - faEye, - faEyeSlash, - faInfoCircle, - faTrash, -} from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { Button } from '@heroui/button' import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from '@heroui/modal' import { Input } from '@heroui/react' import { addToast } from '@heroui/toast' import { format, addDays } from 'date-fns' import { useState } from 'react' +import { FaInfoCircle } from 'react-icons/fa' +import { FaSpinner, FaKey, FaPlus, FaCopy, FaEye, FaEyeSlash, FaTrash } from 'react-icons/fa6' import { CreateApiKeyDocument, GetApiKeysDocument, @@ -174,10 +165,7 @@ export default function Page() {
- +

API Key Limits

@@ -201,7 +189,7 @@ export default function Page() {

- +

Your API Keys

@@ -257,7 +245,7 @@ export default function Page() { onPress={() => setKeyToRevoke(key)} className="text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20" > - + @@ -323,10 +311,10 @@ export default function Page() { onPress={() => setShowNewKey(!showNewKey)} isIconOnly > - + {showNewKey ? : }
@@ -399,7 +387,7 @@ export default function Page() { onPress={handleCreateKey} isDisabled={createLoading || !newKeyName.trim()} > - {createLoading && } + {createLoading && } Create API Key @@ -418,7 +406,7 @@ export default function Page() {

- + After revoking this key, you'll be able to create a new one if needed.

diff --git a/frontend/src/components/AnchorTitle.tsx b/frontend/src/components/AnchorTitle.tsx index 6482623e3f..a03cd5f6a4 100644 --- a/frontend/src/components/AnchorTitle.tsx +++ b/frontend/src/components/AnchorTitle.tsx @@ -1,6 +1,5 @@ -import { faLink } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import React, { useEffect, useCallback } from 'react' +import { FaLink } from 'react-icons/fa6' import { scrollToAnchor, scrollToAnchorWithHistory } from 'utils/scrollToAnchor' import slugify from 'utils/slugify' @@ -52,7 +51,7 @@ const AnchorTitle: React.FC = ({ title }) => { onClick={handleClick} aria-label={`Link to ${title} section`} > - +
diff --git a/frontend/src/components/Badges.tsx b/frontend/src/components/Badges.tsx index 1af558aa8a..d8f6b868df 100644 --- a/frontend/src/components/Badges.tsx +++ b/frontend/src/components/Badges.tsx @@ -1,5 +1,5 @@ import { Tooltip } from '@heroui/tooltip' -import FontAwesomeIconWrapper from 'wrappers/FontAwesomeIconWrapper' +import { IconWrapper } from 'wrappers/IconWrapper' import { BADGE_CLASS_MAP } from 'utils/data' type BadgeProps = { @@ -14,7 +14,6 @@ const normalizeCssClass = (cssClass: string | undefined) => { if (!cssClass || cssClass.trim() === '') { return '' } - // Convert backend snake_case format to frontend camelCase format return cssClass.trim().replaceAll(/_([a-z])/g, (_, letter) => letter.toUpperCase()) } @@ -30,7 +29,7 @@ const Badges = ({ name, cssClass, showTooltip = true }: BadgeProps) => { return (
- +
) diff --git a/frontend/src/components/BarChart.tsx b/frontend/src/components/BarChart.tsx index ebe5b0edbd..b8c1d8f271 100644 --- a/frontend/src/components/BarChart.tsx +++ b/frontend/src/components/BarChart.tsx @@ -1,7 +1,7 @@ -import { IconProp } from '@fortawesome/fontawesome-svg-core' import dynamic from 'next/dynamic' import { useTheme } from 'next-themes' import React from 'react' +import type { IconType } from 'react-icons' import { ApexBarChartDataSeries } from 'types/healthMetrics' import AnchorTitle from 'components/AnchorTitle' import SecondaryCard from 'components/SecondaryCard' @@ -13,7 +13,7 @@ const Chart = dynamic(() => import('react-apexcharts'), { const BarChart: React.FC<{ title: string - icon?: IconProp + icon?: IconType labels: string[] days: number[] requirements: number[] diff --git a/frontend/src/components/BreadCrumbs.tsx b/frontend/src/components/BreadCrumbs.tsx index ebc27cb868..2df6047782 100644 --- a/frontend/src/components/BreadCrumbs.tsx +++ b/frontend/src/components/BreadCrumbs.tsx @@ -1,7 +1,6 @@ -import { faChevronRight } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { Breadcrumbs, BreadcrumbItem as HeroUIBreadcrumbItem } from '@heroui/react' import Link from 'next/link' +import { FaChevronRight } from 'react-icons/fa' import type { BreadcrumbItem } from 'types/breadcrumb' type BreadCrumbRendererProps = Readonly<{ @@ -14,12 +13,7 @@ export default function BreadCrumbRenderer({ items }: BreadCrumbRendererProps) {
- } + separator={} className="text-gray-800 dark:text-gray-200" itemClasses={{ base: 'transition-colors duration-200', diff --git a/frontend/src/components/CalendarButton.tsx b/frontend/src/components/CalendarButton.tsx index 089cc5fe10..8646432d83 100644 --- a/frontend/src/components/CalendarButton.tsx +++ b/frontend/src/components/CalendarButton.tsx @@ -1,6 +1,5 @@ -import { faCalendar, faCalendarPlus } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { useState } from 'react' +import { FaCalendarPlus } from 'react-icons/fa6' import type { CalendarButtonProps } from 'types/calendar' import getGoogleCalendarUrl from 'utils/getGoogleCalendarUrl' @@ -29,9 +28,7 @@ export default function CalendarButton(props: Readonly) { onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > - {icon || ( - - )} + {icon || } {showLabel && {label}} ) diff --git a/frontend/src/components/Card.tsx b/frontend/src/components/Card.tsx index 26d785a1d5..7dbb47a3c2 100644 --- a/frontend/src/components/Card.tsx +++ b/frontend/src/components/Card.tsx @@ -1,8 +1,7 @@ -import { faCalendar } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { Tooltip } from '@heroui/tooltip' import Link from 'next/link' -import FontAwesomeIconWrapper from 'wrappers/FontAwesomeIconWrapper' +import { FaCalendar } from 'react-icons/fa6' +import { IconWrapper } from 'wrappers/IconWrapper' import type { CardProps } from 'types/card' import { ICONS } from 'utils/data' import { formatDateRange } from 'utils/dateFormatter' @@ -45,7 +44,7 @@ const Card = ({ className="flex h-8 w-8 min-w-8 items-center justify-center rounded-full text-xs shadow" style={{ backgroundColor: level.color }} > - + )} @@ -80,7 +79,7 @@ const Card = ({ {/* Timeline Section (Optional) */} {timeline?.start && timeline?.end && (
- + {formatDateRange(timeline.start, timeline.end)}
)} @@ -106,21 +105,21 @@ const Card = ({ {social && social.length > 0 && (
- {social.map((item) => ( - - - - ))} + {social.map((item) => { + const SocialIcon = getSocialIcon(item.url) + return ( + + + + ) + })}
)} diff --git a/frontend/src/components/CardDetailsPage.tsx b/frontend/src/components/CardDetailsPage.tsx index ab5d4a2314..a138984e7b 100644 --- a/frontend/src/components/CardDetailsPage.tsx +++ b/frontend/src/components/CardDetailsPage.tsx @@ -1,15 +1,14 @@ -import { - faCircleInfo, - faChartPie, - faFolderOpen, - faCode, - faTags, - faUsers, - faRectangleList, -} from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import upperFirst from 'lodash/upperFirst' import { useSession } from 'next-auth/react' +import { + FaCircleInfo, + FaChartPie, + FaFolderOpen, + FaCode, + FaTags, + FaRectangleList, +} from 'react-icons/fa6' +import { HiUserGroup } from 'react-icons/hi' import type { ExtendedSession } from 'types/auth' import type { DetailsCardProps } from 'types/card' import { IS_PROJECT_HEALTH_ENABLED } from 'utils/env.client' @@ -120,7 +119,7 @@ const DetailsCard = ({

{description}

{summary && ( - }> + }>

{summary}

)} @@ -128,7 +127,7 @@ const DetailsCard = ({ {userSummary && {userSummary}}
} className={secondaryCardStyles} > @@ -154,7 +153,7 @@ const DetailsCard = ({ type === 'user' || type === 'organization') && ( } className="md:col-span-2" > @@ -194,12 +193,12 @@ const DetailsCard = ({ {languages.length !== 0 && ( } /> )} {topics.length !== 0 && ( - } /> + } /> )}
)} @@ -212,7 +211,7 @@ const DetailsCard = ({ {tags?.length > 0 && ( } isDisabled={true} /> @@ -220,7 +219,7 @@ const DetailsCard = ({ {domains?.length > 0 && ( } isDisabled={true} /> @@ -231,7 +230,7 @@ const DetailsCard = ({
} isDisabled={true} /> @@ -243,13 +242,13 @@ const DetailsCard = ({ {topContributors && ( )} {admins && admins.length > 0 && type === 'program' && ( 0 && ( 0 && ( 0 && ( - }> + }> )} {type === 'program' && modules.length > 0 && ( } > @@ -339,17 +338,20 @@ export const SocialLinks = ({ urls }) => {
Social Links
- {urls.map((url) => ( - - - - ))} + {urls.map((url) => { + const SocialIcon = getSocialIcon(url) + return ( + + + + ) + })}
) diff --git a/frontend/src/components/DashboardCard.tsx b/frontend/src/components/DashboardCard.tsx index 4c6787f190..365fe975cc 100644 --- a/frontend/src/components/DashboardCard.tsx +++ b/frontend/src/components/DashboardCard.tsx @@ -1,12 +1,12 @@ -import { IconProp } from '@fortawesome/fontawesome-svg-core' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import React from 'react' +import type { IconType } from 'react-icons' +import { IconWrapper } from 'wrappers/IconWrapper' import AnchorTitle from 'components/AnchorTitle' import SecondaryCard from 'components/SecondaryCard' const DashboardCard: React.FC<{ readonly title: string - readonly icon: IconProp + readonly icon: IconType readonly stats?: string readonly className?: string }> = ({ title, icon, stats, className }) => { @@ -16,7 +16,7 @@ const DashboardCard: React.FC<{ className={`overflow-hidden transition-colors duration-300 hover:bg-blue-100 dark:hover:bg-blue-950 ${className}`} > - + {stats &&

{stats}

}
diff --git a/frontend/src/components/DisplayIcon.tsx b/frontend/src/components/DisplayIcon.tsx index 9bb0f888f5..569e247e7e 100644 --- a/frontend/src/components/DisplayIcon.tsx +++ b/frontend/src/components/DisplayIcon.tsx @@ -1,6 +1,6 @@ import { Tooltip } from '@heroui/tooltip' import { millify } from 'millify' -import FontAwesomeIconWrapper from 'wrappers/FontAwesomeIconWrapper' +import { IconWrapper } from 'wrappers/IconWrapper' import type { Icon } from 'types/icon' import { IconKeys, ICONS } from 'utils/data' @@ -19,7 +19,7 @@ export default function DisplayIcon({ item, icons }: { item: string; icons: Icon .filter(Boolean) .join(' ') - // className for the FontAwesome icon + // className for the icon const iconClassName = [ 'text-gray-600 dark:text-gray-300', item === 'stars_count' || item === 'starsCount' ? 'icon-rotate' : '', @@ -35,7 +35,7 @@ export default function DisplayIcon({ item, icons }: { item: string; icons: Icon return icons[item] ? ( {/* Display formatted number if the value is a number */} - {typeof icons[item] === 'number' - ? millify(icons[item], { precision: 1 }) // Format large numbers using 'millify' library - : icons[item]} + {typeof icons[item] === 'number' ? millify(icons[item], { precision: 1 }) : icons[item]} - +
diff --git a/frontend/src/components/DonutBarChart.tsx b/frontend/src/components/DonutBarChart.tsx index 532c8caaa1..c610275c1b 100644 --- a/frontend/src/components/DonutBarChart.tsx +++ b/frontend/src/components/DonutBarChart.tsx @@ -1,7 +1,7 @@ -import { IconProp } from '@fortawesome/fontawesome-svg-core' import dynamic from 'next/dynamic' import { useTheme } from 'next-themes' import React from 'react' +import type { IconType } from 'react-icons' import { round } from 'utils/round' import AnchorTitle from 'components/AnchorTitle' import SecondaryCard from 'components/SecondaryCard' @@ -12,7 +12,7 @@ const Chart = dynamic(() => import('react-apexcharts'), { }) const DonutBarChart: React.FC<{ - icon: IconProp + icon: IconType title: string series: number[] }> = ({ icon, title, series }) => { diff --git a/frontend/src/components/EntityActions.tsx b/frontend/src/components/EntityActions.tsx index 2af5205da3..8183d0f453 100644 --- a/frontend/src/components/EntityActions.tsx +++ b/frontend/src/components/EntityActions.tsx @@ -1,10 +1,9 @@ 'use client' -import { faEllipsisV } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { useRouter } from 'next/navigation' import type React from 'react' import { useState, useRef, useEffect } from 'react' +import { FaEllipsisV } from 'react-icons/fa' import { ProgramStatusEnum } from 'types/__generated__/graphql' interface EntityActionsProps { @@ -105,10 +104,7 @@ const EntityActions: React.FC = ({ aria-expanded={dropdownOpen} aria-haspopup="true" > - + {dropdownOpen && (
diff --git a/frontend/src/components/Footer.tsx b/frontend/src/components/Footer.tsx index abff0939ce..54e98b3bd2 100644 --- a/frontend/src/components/Footer.tsx +++ b/frontend/src/components/Footer.tsx @@ -1,9 +1,8 @@ 'use client' -import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { Button } from '@heroui/button' import Link from 'next/link' import { useState, useCallback } from 'react' +import { FaChevronDown, FaChevronUp } from 'react-icons/fa6' import type { Section } from 'types/section' import { footerIcons } from 'utils/constants' import { footerSections } from 'utils/constants' @@ -36,9 +35,9 @@ export default function Footer() {

{section.title}

{openSection === section.title ? ( - + ) : ( - + )}
@@ -70,18 +69,21 @@ export default function Footer() { {/* Social Media Icons Section */}
- {footerIcons.map((social) => ( - - - - ))} + {footerIcons.map((social) => { + const SocialIcon = social.icon + return ( + + + + ) + })}
{/* Footer bottom section with copyright and version */}
diff --git a/frontend/src/components/GeneralCompliantComponent.tsx b/frontend/src/components/GeneralCompliantComponent.tsx index df4c36fbe4..c7cdfaf0ad 100644 --- a/frontend/src/components/GeneralCompliantComponent.tsx +++ b/frontend/src/components/GeneralCompliantComponent.tsx @@ -1,22 +1,22 @@ 'use client' -import { IconProp } from '@fortawesome/fontawesome-svg-core' -import { faCertificate } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { Tooltip } from '@heroui/tooltip' import clsx from 'clsx' import { FC } from 'react' +import type { IconType } from 'react-icons' +import { FaCertificate } from 'react-icons/fa6' +import { IconWrapper } from 'wrappers/IconWrapper' const GeneralCompliantComponent: FC<{ readonly compliant: boolean - readonly icon: IconProp + readonly icon: IconType readonly title: string }> = ({ icon, compliant, title }) => { return (
- - Open main menu - {mobileMenuOpen ? ( - - ) : ( - - )} + {mobileMenuOpen ? : }
@@ -217,16 +209,16 @@ export default function Header({ isGitHubAuthEnabled }: { readonly isGitHubAuthE {isMobile && } = ({ data }) => { }, ]} labels={labels} - icon={faExclamationCircle} + icon={FaExclamationCircle} /> = ({ data }) => { }, ]} labels={labels} - icon={faCodePullRequest} + icon={FaCodePullRequest} />
@@ -66,7 +66,7 @@ const HealthMetrics: React.FC<{ data: HealthMetricsProps[] }> = ({ data }) => { }, ]} labels={labels} - icon={faStar} + icon={FaStar} /> = ({ data }) => { }, ]} labels={labels} - icon={faCodeFork} + icon={FaCodeFork} />
- +
{label &&
{label}
} diff --git a/frontend/src/components/InfoItem.tsx b/frontend/src/components/InfoItem.tsx index 9bc10ca295..aa268c2bd6 100644 --- a/frontend/src/components/InfoItem.tsx +++ b/frontend/src/components/InfoItem.tsx @@ -1,7 +1,7 @@ -import { IconDefinition } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { Tooltip } from '@heroui/tooltip' import millify from 'millify' +import type { IconType } from 'react-icons' +import { IconWrapper } from 'wrappers/IconWrapper' import { pluralize } from 'utils/pluralize' const InfoItem = ({ @@ -11,7 +11,7 @@ const InfoItem = ({ unit, value, }: { - icon: IconDefinition + icon: IconType pluralizedName?: string precision?: number unit: string @@ -24,7 +24,7 @@ const InfoItem = ({ return (
- + {name} @@ -39,13 +39,13 @@ export const TextInfoItem = ({ label, value, }: { - icon: IconDefinition + icon: IconType label: string value: string }) => { return (
- + {label}: {value}
) diff --git a/frontend/src/components/ItemCardList.tsx b/frontend/src/components/ItemCardList.tsx index 99a55f97fa..c8fd4c7403 100644 --- a/frontend/src/components/ItemCardList.tsx +++ b/frontend/src/components/ItemCardList.tsx @@ -1,8 +1,8 @@ -import { IconProp } from '@fortawesome/fontawesome-svg-core' import { Tooltip } from '@heroui/tooltip' import Image from 'next/image' import Link from 'next/link' import React, { JSX } from 'react' +import type { IconType } from 'react-icons' import type { Issue } from 'types/issue' import type { Milestone } from 'types/milestone' import type { PullRequest } from 'types/pullRequest' @@ -20,7 +20,7 @@ const ItemCardList = ({ }: { title: React.ReactNode data: Issue[] | Milestone[] | PullRequest[] | Release[] - icon?: IconProp + icon?: IconType showAvatar?: boolean showSingleColumn?: boolean renderDetails: (item: { diff --git a/frontend/src/components/Leaders.tsx b/frontend/src/components/Leaders.tsx index e619f83355..9f824b005e 100644 --- a/frontend/src/components/Leaders.tsx +++ b/frontend/src/components/Leaders.tsx @@ -1,7 +1,7 @@ -import { faPersonWalkingArrowRight, faRightToBracket } from '@fortawesome/free-solid-svg-icons' import { useRouter } from 'next/navigation' import React from 'react' -import FontAwesomeIconWrapper from 'wrappers/FontAwesomeIconWrapper' +import { FaPersonWalkingArrowRight, FaRightToBracket } from 'react-icons/fa6' +import { IconWrapper } from 'wrappers/IconWrapper' import type { Leader } from 'types/leader' import AnchorTitle from 'components/AnchorTitle' import SecondaryCard from 'components/SecondaryCard' @@ -23,14 +23,14 @@ const Leaders: React.FC = ({ users }) => { } return ( - }> + }>
{users.map((user) => ( , + icon: , label: 'View Profile', onclick: () => handleButtonClick(user), }} diff --git a/frontend/src/components/LineChart.tsx b/frontend/src/components/LineChart.tsx index cecb5df6ec..d8eb32cd75 100644 --- a/frontend/src/components/LineChart.tsx +++ b/frontend/src/components/LineChart.tsx @@ -1,7 +1,7 @@ -import { IconProp } from '@fortawesome/fontawesome-svg-core' import dynamic from 'next/dynamic' import { useTheme } from 'next-themes' import React from 'react' +import { IconType } from 'react-icons' import type { ApexLineChartSeries } from 'types/healthMetrics' import AnchorTitle from 'components/AnchorTitle' import SecondaryCard from 'components/SecondaryCard' @@ -14,7 +14,7 @@ const LineChart: React.FC<{ title: string series: ApexLineChartSeries[] labels?: string[] - icon?: IconProp + icon?: IconType round?: boolean }> = ({ title, series, labels, icon, round }) => { const { theme } = useTheme() diff --git a/frontend/src/components/LoginPageContent.tsx b/frontend/src/components/LoginPageContent.tsx index 29e0e30e01..281200b453 100644 --- a/frontend/src/components/LoginPageContent.tsx +++ b/frontend/src/components/LoginPageContent.tsx @@ -1,12 +1,10 @@ 'use client' -import { faGithub } from '@fortawesome/free-brands-svg-icons' -import { faSpinner } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { addToast } from '@heroui/toast' import { useRouter } from 'next/navigation' import { useSession, signIn } from 'next-auth/react' import { FC, useCallback, useEffect } from 'react' +import { FaGithub, FaSpinner } from 'react-icons/fa' import { userAuthStatus } from 'utils/constants' type LoginPageContentProps = { @@ -45,7 +43,7 @@ const LoginPageContent: FC = ({ isGitHubAuthEnabled }) => if (status === userAuthStatus.LOADING) { return (
- + Checking session...
) @@ -54,7 +52,7 @@ const LoginPageContent: FC = ({ isGitHubAuthEnabled }) => if (status === userAuthStatus.AUTHENTICATED) { return (
- + Redirecting...
) @@ -75,7 +73,7 @@ const LoginPageContent: FC = ({ isGitHubAuthEnabled }) => onClick={() => signIn('github', { callbackUrl: '/' })} className="flex w-full items-center justify-center gap-2 rounded-lg bg-black px-4 py-2 font-medium text-white transition-colors hover:bg-gray-900/90" > - + Sign In with GitHub
diff --git a/frontend/src/components/MenteeContributorsList.tsx b/frontend/src/components/MenteeContributorsList.tsx index 9517cd38d0..800639b958 100644 --- a/frontend/src/components/MenteeContributorsList.tsx +++ b/frontend/src/components/MenteeContributorsList.tsx @@ -1,8 +1,9 @@ -import type { IconProp } from '@fortawesome/fontawesome-svg-core' import upperFirst from 'lodash/upperFirst' import Image from 'next/image' import Link from 'next/link' import { useState } from 'react' +import type { IconType } from 'react-icons' +import { IconWrapper } from 'wrappers/IconWrapper' import type { Contributor } from 'types/contributor' import AnchorTitle from 'components/AnchorTitle' import SecondaryCard from 'components/SecondaryCard' @@ -12,7 +13,7 @@ interface MenteeContributorsListProps { contributors: Contributor[] label?: string maxInitialDisplay?: number - icon?: IconProp + icon?: IconType programKey: string moduleKey: string } @@ -42,7 +43,7 @@ const MenteeContributorsList = ({ return ( : undefined} title={
diff --git a/frontend/src/components/MenteeIssues.tsx b/frontend/src/components/MenteeIssues.tsx index b793284a06..71c4f230fd 100644 --- a/frontend/src/components/MenteeIssues.tsx +++ b/frontend/src/components/MenteeIssues.tsx @@ -1,7 +1,7 @@ -import { faBug, faCheckCircle, faClock } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import type React from 'react' import { useState } from 'react' +import { FaBug, FaCheckCircle, FaClock } from 'react-icons/fa' +import { IconWrapper } from 'wrappers/IconWrapper' import type { Issue } from 'types/issue' import { formatDate } from 'utils/dateFormatter' import SecondaryCard from 'components/SecondaryCard' @@ -31,11 +31,11 @@ const MenteeIssues: React.FC = ({ openIssues, closedIssues, m const getStateIcon = (state: string) => { switch (state.toLowerCase()) { case 'open': - return faBug + return FaBug case 'closed': - return faCheckCircle + return FaCheckCircle default: - return faClock + return FaClock } } @@ -43,8 +43,8 @@ const MenteeIssues: React.FC = ({ openIssues, closedIssues, m
{issues.length === 0 ? (
-

No {title.toLowerCase()} issues

@@ -58,7 +58,7 @@ const MenteeIssues: React.FC = ({ openIssues, closedIssues, m
- @@ -113,7 +113,7 @@ const MenteeIssues: React.FC = ({ openIssues, closedIssues, m ) return ( - + {/* Tab Navigation */}
diff --git a/frontend/src/components/MetricsPDFButton.tsx b/frontend/src/components/MetricsPDFButton.tsx index 1a1db63d0d..bfe5d88aee 100644 --- a/frontend/src/components/MetricsPDFButton.tsx +++ b/frontend/src/components/MetricsPDFButton.tsx @@ -1,9 +1,8 @@ 'use client' -import { faFileArrowDown } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { Tooltip } from '@heroui/tooltip' import { FC } from 'react' +import { FaFileArrowDown } from 'react-icons/fa6' import { fetchMetricsPDF } from 'server/fetchMetricsPDF' const MetricsPDFButton: FC<{ @@ -19,8 +18,7 @@ const MetricsPDFButton: FC<{ closeDelay={100} showArrow > - await fetchMetricsPDF(path, fileName)} /> diff --git a/frontend/src/components/Milestones.tsx b/frontend/src/components/Milestones.tsx index 2e0102fc38..ef02809d4f 100644 --- a/frontend/src/components/Milestones.tsx +++ b/frontend/src/components/Milestones.tsx @@ -1,13 +1,12 @@ -import { - faCalendar, - faFolderOpen, - faSignsPost, - faCircleCheck, - faCircleExclamation, -} from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { useRouter } from 'next/navigation' import React from 'react' +import { + FaCalendar, + FaFolderOpen, + FaSignsPost, + FaCircleCheck, + FaCircleExclamation, +} from 'react-icons/fa6' import type { Milestone } from 'types/milestone' import { formatDate } from 'utils/dateFormatter' import AnchorTitle from 'components/AnchorTitle' @@ -36,25 +35,25 @@ const Milestones: React.FC = ({ } data={data} showAvatar={showAvatar} - icon={faSignsPost} + icon={FaSignsPost} showSingleColumn={showSingleColumn} renderDetails={(item) => (
- + {formatDate(item.createdAt)}
- + {item.closedIssuesCount} closed
- + {item.openIssuesCount} open
{item?.repositoryName && (
- + diff --git a/frontend/src/components/ModuleCard.tsx b/frontend/src/components/ModuleCard.tsx index 75669f283d..f8b0bcae20 100644 --- a/frontend/src/components/ModuleCard.tsx +++ b/frontend/src/components/ModuleCard.tsx @@ -1,15 +1,14 @@ -import { - faChevronDown, - faChevronUp, - faLevelUpAlt, - faCalendarAlt, - faHourglassHalf, -} from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import upperFirst from 'lodash/upperFirst' import Link from 'next/link' import { usePathname } from 'next/navigation' import { useState } from 'react' +import { + FaChevronDown, + FaChevronUp, + FaLevelUpAlt, + FaCalendarAlt, + FaHourglassHalf, +} from 'react-icons/fa' import type { Module } from 'types/mentorship' import { formatDate } from 'utils/dateFormatter' import { TextInfoItem } from 'components/InfoItem' @@ -49,11 +48,11 @@ const ModuleCard = ({ modules, accessLevel, admins }: ModuleCardProps) => { > {showAllModule ? ( <> - Show less + Show less ) : ( <> - Show more + Show more )} @@ -73,10 +72,10 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) = > - - + + diff --git a/frontend/src/components/MultiSearch.tsx b/frontend/src/components/MultiSearch.tsx index b70fb4611a..8ea4a5cc8f 100644 --- a/frontend/src/components/MultiSearch.tsx +++ b/frontend/src/components/MultiSearch.tsx @@ -1,19 +1,11 @@ -import { faAlgolia } from '@fortawesome/free-brands-svg-icons' -import { - faSearch, - faTimes, - faUser, - faCalendar, - faFolder, - faBuilding, - faLocationDot, -} from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { sendGAEvent } from '@next/third-parties/google' import { debounce } from 'lodash' import { useRouter } from 'next/navigation' import type React from 'react' import { useState, useEffect, useMemo, useCallback, useRef } from 'react' +import { FaTimes, FaSearch } from 'react-icons/fa' +import { FaUser, FaCalendar, FaFolder, FaBuilding, FaLocationDot } from 'react-icons/fa6' +import { SiAlgolia } from 'react-icons/si' import { fetchAlgoliaData } from 'server/fetchAlgoliaData' import type { Chapter } from 'types/chapter' import type { Event } from 'types/event' @@ -207,17 +199,17 @@ const MultiSearchBar: React.FC = ({ const getIconForIndex = (indexName: string) => { switch (indexName) { case 'chapters': - return faLocationDot + return case 'events': - return faCalendar + return case 'organizations': - return faBuilding + return case 'projects': - return faFolder + return case 'users': - return faUser + return default: - return faSearch + return } } @@ -226,8 +218,7 @@ const MultiSearchBar: React.FC = ({
{isLoaded ? ( <> -
diff --git a/frontend/src/components/NavButton.tsx b/frontend/src/components/NavButton.tsx index 946b1f0913..bfc91998bb 100644 --- a/frontend/src/components/NavButton.tsx +++ b/frontend/src/components/NavButton.tsx @@ -1,6 +1,7 @@ -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import Link from 'next/link' import { useState } from 'react' +import type { IconType } from 'react-icons' +import { IconWrapper } from 'wrappers/IconWrapper' import type { NavButtonProps } from 'types/button' import { cn } from 'utils/utility' @@ -12,7 +13,7 @@ const NavButton = ({ hoverIconColor, text, className, -}: NavButtonProps) => { +}: NavButtonProps & { defaultIcon: IconType; hoverIcon: IconType }) => { const [isHovered, setIsHovered] = useState(false) return ( @@ -27,7 +28,7 @@ const NavButton = ({ onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > - sub.href).includes(pathname) && + link.submenu?.map((sub) => sub.href).includes(pathname) && 'font-bold text-blue-800 dark:text-white' )} > @@ -60,7 +59,7 @@ export default function NavDropdown({ link, pathname }: NavDropDownProps) { aria-hidden="true" style={{ transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)' }} > - + {isOpen && ( @@ -68,7 +67,7 @@ export default function NavDropdown({ link, pathname }: NavDropDownProps) { id={dropdownId} className="absolute top-full left-0 z-10 mt-1 w-48 overflow-hidden rounded-md bg-white shadow-lg dark:bg-slate-800" > - {link.submenu.map((submenu, idx) => ( + {link.submenu?.map((submenu, idx) => ( = ({ role="presentation" aria-label="More pages" > - + ) : (
} data={data} - icon={faCodePullRequest} + icon={FaCodePullRequest} showAvatar={showAvatar} renderDetails={(item) => (
- + {formatDate(item.createdAt)}
{item?.repositoryName && (
- +
- +
- +
- - + + - + ) } diff --git a/frontend/src/components/Search.tsx b/frontend/src/components/Search.tsx index 0d514e66f4..b1d1607e02 100644 --- a/frontend/src/components/Search.tsx +++ b/frontend/src/components/Search.tsx @@ -1,10 +1,9 @@ -import { faSearch, faTimes } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { Skeleton } from '@heroui/skeleton' import { sendGTMEvent } from '@next/third-parties/google' import { debounce } from 'lodash' import { usePathname } from 'next/navigation' import React, { useEffect, useRef, useState, useMemo } from 'react' +import { FaSearch, FaTimes } from 'react-icons/fa' interface SearchProps { isLoaded: boolean @@ -72,9 +71,9 @@ const SearchBar: React.FC = ({
{!isLoaded ? ( <> -