diff --git a/src/app/release-notes/page.tsx b/src/app/release-notes/page.tsx new file mode 100644 index 0000000..0c9a714 --- /dev/null +++ b/src/app/release-notes/page.tsx @@ -0,0 +1,19 @@ +import React, { lazy } from 'react'; +import LazyLoadingManager from '@/components/performance/LazyLoadingManager'; + +const LazyReleaseNotes = lazy(() => import('@/components/shared/ReleaseNotes')); + +export default function ReleaseNotesPage() { + return ( +
+
+

+ What's New in TeachLink +

+ + + +
+
+ ); +} diff --git a/src/components/index.ts b/src/components/index.ts index b02e098..490b771 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -22,3 +22,4 @@ export { BulkImporter } from './BulkImporter'; export type { BulkImporterProps, TargetFieldDef } from './BulkImporter'; export { Tooltip } from './ui/Tooltip'; export type { TooltipProps, TooltipPlacement } from './ui/Tooltip'; +export * from './shared/ReleaseNotes'; diff --git a/src/components/shared/ReleaseNotes.test.tsx b/src/components/shared/ReleaseNotes.test.tsx new file mode 100644 index 0000000..3108df9 --- /dev/null +++ b/src/components/shared/ReleaseNotes.test.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { render, screen, waitFor } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import ReleaseNotes from './ReleaseNotes'; + +describe('ReleaseNotes', () => { + it('renders loading state initially', () => { + render(); + expect(screen.getByTestId('loading-skeleton')).toBeInTheDocument(); + }); + + it('renders release notes after loading', async () => { + render(); + + // Wait for the component to finish "fetching" (500ms mock delay) + await waitFor(() => { + expect(screen.getByText('Release Notes')).toBeInTheDocument(); + }, { timeout: 1000 }); + + expect(screen.getByText('v1.2.0')).toBeInTheDocument(); + expect(screen.getByText('v1.1.0')).toBeInTheDocument(); + expect(screen.getByText('Added Lazy Loading support')).toBeInTheDocument(); + }); +}); diff --git a/src/components/shared/ReleaseNotes.tsx b/src/components/shared/ReleaseNotes.tsx new file mode 100644 index 0000000..eae7f0c --- /dev/null +++ b/src/components/shared/ReleaseNotes.tsx @@ -0,0 +1,73 @@ +import React, { useState, useEffect } from 'react'; + +export interface ReleaseNote { + version: string; + date: string; + changes: string[]; +} + +export const ReleaseNotes: React.FC = () => { + const [notes, setNotes] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + // Simulate fetching release notes + const fetchNotes = async () => { + try { + // Mock data + const data: ReleaseNote[] = [ + { + version: '1.2.0', + date: '2026-05-30', + changes: ['Added Lazy Loading support', 'Improved performance', 'Fixed bugs'], + }, + { + version: '1.1.0', + date: '2026-05-15', + changes: ['Added Release Notes feature', 'Updated dependencies'], + }, + ]; + + // Simulate network delay + await new Promise(resolve => setTimeout(resolve, 500)); + setNotes(data); + } catch (error) { + console.error('Failed to fetch release notes:', error); + } finally { + setLoading(false); + } + }; + + fetchNotes(); + }, []); + + if (loading) { + return
; + } + + return ( +
+

Release Notes

+ {notes.length === 0 ? ( +

No release notes available.

+ ) : ( +
    + {notes.map((note) => ( +
  • +

    + v{note.version} ({note.date}) +

    +
      + {note.changes.map((change, idx) => ( +
    • {change}
    • + ))} +
    +
  • + ))} +
+ )} +
+ ); +}; + +export default ReleaseNotes;