diff --git a/frontend/__tests__/a11y/components/CardDetailsPage.a11y.test.tsx b/frontend/__tests__/a11y/components/CardDetailsPage.a11y.test.tsx
index dc23d3de6e..f79e721540 100644
--- a/frontend/__tests__/a11y/components/CardDetailsPage.a11y.test.tsx
+++ b/frontend/__tests__/a11y/components/CardDetailsPage.a11y.test.tsx
@@ -1,12 +1,13 @@
-import { mockChapterData } from '@mockData/mockChapterData'
import { render } from '@testing-library/react'
import { axe } from 'jest-axe'
import { useTheme } from 'next-themes'
import React from 'react'
import { FaCode, FaTags } from 'react-icons/fa6'
-import { ExperienceLevelEnum } from 'types/__generated__/graphql'
-import { DetailsCardProps } from 'types/card'
-import DetailsCard from 'components/CardDetailsPage'
+import CardDetailsHeader from 'components/CardDetailsPage/CardDetailsHeader'
+import CardDetailsMetadata from 'components/CardDetailsPage/CardDetailsMetadata'
+import CardDetailsPageWrapper from 'components/CardDetailsPage/CardDetailsPageWrapper'
+import CardDetailsSummary from 'components/CardDetailsPage/CardDetailsSummary'
+import CardDetailsTags from 'components/CardDetailsPage/CardDetailsTags'
jest.mock('next/link', () => {
return function MockLink({
@@ -74,49 +75,17 @@ jest.mock('@apollo/client/react', () => ({
useMutation: jest.fn(() => [jest.fn()]),
}))
-const mockHealthMetricsData = [
- {
- ageDays: 365,
- ageDaysRequirement: 365,
- id: 'test-id',
- createdAt: '2023-01-01',
- contributorsCount: 10,
- forksCount: 5,
- isFundingRequirementsCompliant: true,
- isLeaderRequirementsCompliant: true,
- lastCommitDays: 1,
- lastCommitDaysRequirement: 30,
- lastPullRequestDays: 2,
- lastPullRequestDaysRequirement: 30,
- lastReleaseDays: 10,
- lastReleaseDaysRequirement: 90,
- openIssuesCount: 5,
- openPullRequestsCount: 3,
- owaspPageLastUpdateDays: 30,
- owaspPageLastUpdateDaysRequirement: 90,
- projectName: 'Test Project',
- projectKey: 'test-project',
- recentReleasesCount: 2,
- score: 85,
- starsCount: 100,
- totalIssuesCount: 20,
- totalReleasesCount: 5,
- unassignedIssuesCount: 2,
- unansweredIssuesCount: 1,
- },
-]
-
const mockStats = [
{
icon: FaCode,
pluralizedName: 'repositories',
- unit: '',
+ unit: 'Repository',
value: 10,
},
{
icon: FaTags,
- pluralizedName: 'stars',
- unit: '',
+ pluralizedName: 'Stars',
+ unit: 'Star',
value: 100,
},
]
@@ -127,26 +96,6 @@ const mockDetails = [
{ label: 'Status', value: 'Active' },
]
-const defaultProps: DetailsCardProps = {
- title: 'Test Project',
- description: 'A test project for demonstration',
- type: 'project',
- details: mockDetails,
- stats: mockStats,
- isActive: true,
- showAvatar: true,
- languages: ['JavaScript', 'TypeScript'],
- topics: ['web', 'frontend'],
- repositories: [],
- recentIssues: [],
- recentMilestones: [],
- recentReleases: [],
- pullRequests: [],
- topContributors: [],
- healthMetricsData: mockHealthMetricsData,
- socialLinks: [],
-}
-
describe.each([
{ theme: 'light', name: 'light' },
{ theme: 'dark', name: 'dark' },
@@ -155,69 +104,56 @@ describe.each([
;(useTheme as jest.Mock).mockReturnValue({ theme, setTheme: jest.fn() })
document.documentElement.classList.toggle('dark', theme === 'dark')
})
- it('should have no accessibility violations', async () => {
- const { container } = render(
{stats.commits}
-{stats.pullRequests}
-{stats.issues}
-{stats.total}
- > - )} -Complex user summary
-{props.summary}
-{props.summary}
+ } +}) + +jest.mock('components/CardDetailsPage/CardDetailsMetadata', () => { + return function MockMetadata(props: { details?: Array<{ label: string; value: string }> }) { + return ( +{description}
- {summary && ( -{description}
} + > + ) +} + +export default CardDetailsHeader diff --git a/frontend/src/components/CardDetailsPage/CardDetailsIssuesMilestones.tsx b/frontend/src/components/CardDetailsPage/CardDetailsIssuesMilestones.tsx new file mode 100644 index 0000000000..8a906878ad --- /dev/null +++ b/frontend/src/components/CardDetailsPage/CardDetailsIssuesMilestones.tsx @@ -0,0 +1,208 @@ +import { Tooltip } from '@heroui/tooltip' +import Image from 'next/image' +import Link from 'next/link' +import { useState } from 'react' +import { + FaCalendar, + FaCircleCheck, + FaCircleExclamation, + FaFolderOpen, + FaSignsPost, + FaCodeBranch, + FaChevronDown, + FaChevronUp, +} from 'react-icons/fa6' +import type { Issue } from 'types/issue' +import type { Milestone } from 'types/milestone' +import type { PullRequest } from 'types/pullRequest' +import type { Release } from 'types/release' +import { formatDate } from 'utils/dateFormatter' +import AnchorTitle from 'components/AnchorTitle' +import MentorshipPullRequest from 'components/MentorshipPullRequest' +import Milestones from 'components/Milestones' +import RecentIssues from 'components/RecentIssues' +import RecentPullRequests from 'components/RecentPullRequests' +import RecentReleases from 'components/RecentReleases' +import SecondaryCard from 'components/SecondaryCard' +import ShowMoreButton from 'components/ShowMoreButton' +import { TruncatedText } from 'components/TruncatedText' + +interface CardDetailsIssuesMilestonesProps { + recentIssues?: Issue[] + recentMilestones?: Milestone[] + pullRequests?: PullRequest[] + recentReleases?: Release[] + showAvatar?: boolean + onLoadMorePullRequests?: () => void + onResetPullRequests?: () => void + isFetchingMore?: boolean + isMilestoneOnly?: boolean + isPullRequestOnly?: boolean +} + +const MILESTONE_LIMIT = 4 + +const CardDetailsIssuesMilestones = ({ + recentIssues, + recentMilestones, + pullRequests, + recentReleases, + showAvatar = true, + onLoadMorePullRequests, + onResetPullRequests, + isFetchingMore = false, + isMilestoneOnly = false, + isPullRequestOnly = false, +}: CardDetailsIssuesMilestonesProps) => { + const [showAllMilestones, setShowAllMilestones] = useState(false) + const [showAllPRs, setShowAllPRs] = useState(false) + + const prDisplayLimit = onLoadMorePullRequests || onResetPullRequests || showAllPRs ? undefined : 4 + + return ( + <> + {!isMilestoneOnly && !isPullRequestOnly && ( +