diff --git a/frontend/src/components/CardDetailsPage.tsx b/frontend/src/components/CardDetailsPage.tsx index 5f872a0ed5..35765ea984 100644 --- a/frontend/src/components/CardDetailsPage.tsx +++ b/frontend/src/components/CardDetailsPage.tsx @@ -11,6 +11,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import upperFirst from 'lodash/upperFirst' import { useRouter } from 'next/navigation' import { useSession } from 'next-auth/react' +import type { JSX } from 'react' +import { useCallback } from 'react' import type { ExtendedSession } from 'types/auth' import type { DetailsCardProps } from 'types/card' import { IS_PROJECT_HEALTH_ENABLED } from 'utils/env.client' @@ -33,6 +35,8 @@ import SecondaryCard from 'components/SecondaryCard' import SponsorCard from 'components/SponsorCard' import ToggleableList from 'components/ToggleableList' import TopContributorsList from 'components/TopContributorsList' +const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[a-z]{2,}$/i +const sanitizeForUrl = (str: string) => encodeURIComponent(str.trim()) const DetailsCard = ({ description, @@ -67,6 +71,63 @@ const DetailsCard = ({ type, userSummary, }: DetailsCardProps) => { + const renderDetailValue = useCallback( + (detail: { label: string; value: string | JSX.Element }) => { + const { label, value } = detail + + if ( + value == null || + value === '' || + value === 'N/A' || + value === 'Not available' || + value === 'Unknown' + ) { + return 'N/A' + } + + if (typeof value !== 'string') { + return value + } + + switch (label) { + case 'Email': + if (!EMAIL_REGEX.test(value)) { + return value + } + return ( + + {value} + + ) + + case 'Company': + if (value.startsWith('@')) { + const companyName = sanitizeForUrl(value.slice(1)) + return ( + + {value} + + ) + } + return value + + default: + return value + } + }, + [] + ) + const { data } = useSession() const router = useRouter() return ( @@ -135,7 +196,7 @@ const DetailsCard = ({ ) : (
- {detail.label}: {detail?.value || 'Unknown'} + {detail.label}: {renderDetailValue(detail)}
) )}