Skip to content

Commit bebd078

Browse files
Merge pull request #641 from utahkanz-ops/feature/460-release-notes
feat: implement Release Notes with Lazy Loading (#460)
2 parents 76e69e5 + f7e0da8 commit bebd078

4 files changed

Lines changed: 117 additions & 0 deletions

File tree

src/app/release-notes/page.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React, { lazy } from 'react';
2+
import LazyLoadingManager from '@/components/performance/LazyLoadingManager';
3+
4+
const LazyReleaseNotes = lazy(() => import('@/components/shared/ReleaseNotes'));
5+
6+
export default function ReleaseNotesPage() {
7+
return (
8+
<div className="min-h-screen bg-gray-50 dark:bg-gray-900 py-12 px-4 sm:px-6 lg:px-8">
9+
<div className="max-w-3xl mx-auto">
10+
<h1 className="text-3xl font-extrabold text-gray-900 dark:text-white mb-8 text-center">
11+
What's New in TeachLink
12+
</h1>
13+
<LazyLoadingManager componentName="ReleaseNotes">
14+
<LazyReleaseNotes />
15+
</LazyLoadingManager>
16+
</div>
17+
</div>
18+
);
19+
}

src/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ export { BulkImporter } from './BulkImporter';
2222
export type { BulkImporterProps, TargetFieldDef } from './BulkImporter';
2323
export { Tooltip } from './ui/Tooltip';
2424
export type { TooltipProps, TooltipPlacement } from './ui/Tooltip';
25+
export * from './shared/ReleaseNotes';
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from 'react';
2+
import { render, screen, waitFor } from '@testing-library/react';
3+
import '@testing-library/jest-dom';
4+
import ReleaseNotes from './ReleaseNotes';
5+
6+
describe('ReleaseNotes', () => {
7+
it('renders loading state initially', () => {
8+
render(<ReleaseNotes />);
9+
expect(screen.getByTestId('loading-skeleton')).toBeInTheDocument();
10+
});
11+
12+
it('renders release notes after loading', async () => {
13+
render(<ReleaseNotes />);
14+
15+
// Wait for the component to finish "fetching" (500ms mock delay)
16+
await waitFor(() => {
17+
expect(screen.getByText('Release Notes')).toBeInTheDocument();
18+
}, { timeout: 1000 });
19+
20+
expect(screen.getByText('v1.2.0')).toBeInTheDocument();
21+
expect(screen.getByText('v1.1.0')).toBeInTheDocument();
22+
expect(screen.getByText('Added Lazy Loading support')).toBeInTheDocument();
23+
});
24+
});
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import React, { useState, useEffect } from 'react';
2+
3+
export interface ReleaseNote {
4+
version: string;
5+
date: string;
6+
changes: string[];
7+
}
8+
9+
export const ReleaseNotes: React.FC = () => {
10+
const [notes, setNotes] = useState<ReleaseNote[]>([]);
11+
const [loading, setLoading] = useState(true);
12+
13+
useEffect(() => {
14+
// Simulate fetching release notes
15+
const fetchNotes = async () => {
16+
try {
17+
// Mock data
18+
const data: ReleaseNote[] = [
19+
{
20+
version: '1.2.0',
21+
date: '2026-05-30',
22+
changes: ['Added Lazy Loading support', 'Improved performance', 'Fixed bugs'],
23+
},
24+
{
25+
version: '1.1.0',
26+
date: '2026-05-15',
27+
changes: ['Added Release Notes feature', 'Updated dependencies'],
28+
},
29+
];
30+
31+
// Simulate network delay
32+
await new Promise(resolve => setTimeout(resolve, 500));
33+
setNotes(data);
34+
} catch (error) {
35+
console.error('Failed to fetch release notes:', error);
36+
} finally {
37+
setLoading(false);
38+
}
39+
};
40+
41+
fetchNotes();
42+
}, []);
43+
44+
if (loading) {
45+
return <div className="p-4 animate-pulse bg-gray-100 dark:bg-gray-800 rounded-lg h-32" data-testid="loading-skeleton"></div>;
46+
}
47+
48+
return (
49+
<div className="release-notes space-y-4 p-4 border rounded-lg shadow-sm bg-white dark:bg-gray-900 dark:border-gray-700">
50+
<h2 className="text-2xl font-bold mb-4">Release Notes</h2>
51+
{notes.length === 0 ? (
52+
<p>No release notes available.</p>
53+
) : (
54+
<ul className="space-y-4">
55+
{notes.map((note) => (
56+
<li key={note.version} className="border-b pb-4 last:border-b-0 dark:border-gray-800">
57+
<h3 className="text-lg font-semibold text-blue-600 dark:text-blue-400">
58+
v{note.version} <span className="text-sm font-normal text-gray-500 dark:text-gray-400">({note.date})</span>
59+
</h3>
60+
<ul className="list-disc pl-5 mt-2 space-y-1">
61+
{note.changes.map((change, idx) => (
62+
<li key={idx} className="text-gray-700 dark:text-gray-300">{change}</li>
63+
))}
64+
</ul>
65+
</li>
66+
))}
67+
</ul>
68+
)}
69+
</div>
70+
);
71+
};
72+
73+
export default ReleaseNotes;

0 commit comments

Comments
 (0)