Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/app/hooks/__tests__/useDashboardWidgets.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @vitest-environment jsdom
import React, { useEffect } from 'react';
import { describe, it, expect, beforeEach } from 'vitest';
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { createRoot } from 'react-dom/client';
import { act } from 'react-dom/test-utils';
import { useDashboardWidgets } from '../useDashboardWidgets';
Expand Down Expand Up @@ -38,6 +38,7 @@ describe('useDashboardWidgets', () => {
let root: ReturnType<typeof createRoot>;

beforeEach(() => {
vi.useFakeTimers();
// @ts-expect-error - LocalStorageMock for testing
global.localStorage = new LocalStorageMock();
container = document.createElement('div');
Expand All @@ -59,6 +60,12 @@ describe('useDashboardWidgets', () => {

// After first mount, default widgets should be set and saved
expect(api.widgets.length).toBeGreaterThan(0);

// Advance past the 500ms debounce in saveWidgetLayout
await act(async () => {
vi.advanceTimersByTime(600);
});

const saved = JSON.parse(localStorage.getItem('dashboard-widgets') || '[]');
expect(saved.length).toBe(api.widgets.length);
});
Expand Down
218 changes: 75 additions & 143 deletions src/app/hooks/useDashboardWidgets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,77 @@ interface Widget {
settings: Record<string, unknown>;
}

// Default widgets matching Figma design — single source of truth
const DEFAULT_WIDGETS: Widget[] = [
// 4 Summary Stat Cards (small size)
{
id: 'stat-revenue',
type: 'progress-summary',
title: 'Total Revenue',
size: 'small',
position: 0,
isCollapsed: false,
settings: { statType: 'revenue' },
},
{
id: 'stat-students',
type: 'progress-summary',
title: 'Students',
size: 'small',
position: 1,
isCollapsed: false,
settings: { statType: 'students' },
},
{
id: 'stat-views',
type: 'progress-summary',
title: 'Course Views',
size: 'small',
position: 2,
isCollapsed: false,
settings: { statType: 'views' },
},
{
id: 'stat-courses',
type: 'progress-summary',
title: 'Active Courses',
size: 'small',
position: 3,
isCollapsed: false,
settings: { statType: 'courses' },
},
// Recent Sales (medium, left column)
{
id: 'recent-sales',
type: 'recent-sales',
title: 'Recent Sales',
size: 'medium',
position: 4,
isCollapsed: false,
settings: {},
},
// Recent Activity (medium, right column)
{
id: 'recent-activity',
type: 'recent-activity',
title: 'Recent Activity',
size: 'medium',
position: 5,
isCollapsed: false,
settings: {},
},
// Upcoming Schedule (large, full width)
{
id: 'upcoming-schedule',
type: 'upcoming-deadlines',
title: 'Upcoming Schedule',
size: 'large',
position: 6,
isCollapsed: false,
settings: {},
},
];

export const useDashboardWidgets = () => {
const [widgets, setWidgets] = useState<Widget[]>([]);
const [isLoading, setIsLoading] = useState(true);
Expand Down Expand Up @@ -70,78 +141,8 @@ export const useDashboardWidgets = () => {
if (savedWidgets.length > 0) {
setWidgets(savedWidgets);
} else {
// Default widgets matching Figma design
const defaultWidgets: Widget[] = [
// 4 Summary Stat Cards (small size)
{
id: 'stat-revenue',
type: 'progress-summary',
title: 'Total Revenue',
size: 'small',
position: 0,
isCollapsed: false,
settings: { statType: 'revenue' },
},
{
id: 'stat-students',
type: 'progress-summary',
title: 'Students',
size: 'small',
position: 1,
isCollapsed: false,
settings: { statType: 'students' },
},
{
id: 'stat-views',
type: 'progress-summary',
title: 'Course Views',
size: 'small',
position: 2,
isCollapsed: false,
settings: { statType: 'views' },
},
{
id: 'stat-courses',
type: 'progress-summary',
title: 'Active Courses',
size: 'small',
position: 3,
isCollapsed: false,
settings: { statType: 'courses' },
},
// Recent Sales (medium, left column)
{
id: 'recent-sales',
type: 'recent-sales',
title: 'Recent Sales',
size: 'medium',
position: 4,
isCollapsed: false,
settings: {},
},
// Recent Activity (medium, right column)
{
id: 'recent-activity',
type: 'recent-activity',
title: 'Recent Activity',
size: 'medium',
position: 5,
isCollapsed: false,
settings: {},
},
// Upcoming Schedule (large, full width)
{
id: 'upcoming-schedule',
type: 'upcoming-deadlines',
title: 'Upcoming Schedule',
size: 'large',
position: 6,
isCollapsed: false,
settings: {},
},
];
setWidgets(defaultWidgets);
saveWidgetLayout(defaultWidgets);
setWidgets(DEFAULT_WIDGETS);
saveWidgetLayout(DEFAULT_WIDGETS);
}
setIsLoading(false);
}, [loadWidgetLayout, saveWidgetLayout]);
Expand Down Expand Up @@ -231,77 +232,8 @@ export const useDashboardWidgets = () => {

// Reset to default layout
const resetToDefault = useCallback(() => {
const defaultWidgets: Widget[] = [
// 4 Summary Stat Cards (small size)
{
id: 'stat-revenue',
type: 'progress-summary',
title: 'Total Revenue',
size: 'small',
position: 0,
isCollapsed: false,
settings: { statType: 'revenue' },
},
{
id: 'stat-students',
type: 'progress-summary',
title: 'Students',
size: 'small',
position: 1,
isCollapsed: false,
settings: { statType: 'students' },
},
{
id: 'stat-views',
type: 'progress-summary',
title: 'Course Views',
size: 'small',
position: 2,
isCollapsed: false,
settings: { statType: 'views' },
},
{
id: 'stat-courses',
type: 'progress-summary',
title: 'Active Courses',
size: 'small',
position: 3,
isCollapsed: false,
settings: { statType: 'courses' },
},
// Recent Sales (medium, left column)
{
id: 'recent-sales',
type: 'recent-sales',
title: 'Recent Sales',
size: 'medium',
position: 4,
isCollapsed: false,
settings: {},
},
// Recent Activity (medium, right column)
{
id: 'recent-activity',
type: 'recent-activity',
title: 'Recent Activity',
size: 'medium',
position: 5,
isCollapsed: false,
settings: {},
},
// Upcoming Schedule (large, full width)
{
id: 'upcoming-schedule',
type: 'upcoming-deadlines',
title: 'Upcoming Schedule',
size: 'large',
position: 6,
isCollapsed: false,
settings: {},
},
];
setWidgets(defaultWidgets);
saveWidgetLayout(defaultWidgets);
setWidgets(DEFAULT_WIDGETS);
saveWidgetLayout(DEFAULT_WIDGETS);
}, [saveWidgetLayout]);

// Export widget configuration
Expand Down
Loading