Files
fast-next-template/frontend/src/components/dashboard/Dashboard.tsx
Felipe Cardoso 70009676a3 fix(dashboard): disable SSE in demo mode and remove unused hooks
- Skip SSE connection in demo mode (MSW doesn't support SSE).
- Remove unused `useProjectEvents` and related real-time hooks from `Dashboard`.
- Temporarily disable activity feed SSE until a global endpoint is available.
2026-01-06 02:29:00 +01:00

125 lines
4.2 KiB
TypeScript

/**
* Dashboard Component
*
* Main dashboard layout orchestrator.
* Combines all dashboard sub-components into a cohesive layout.
*
* Layout:
* +------------------------------------------+------------------+
* | Welcome Header | ACTIVITY |
* +------------------------------------------+ FEED |
* | Quick Stats (4 cards) | SIDEBAR |
* +------------------------------------------+ |
* | Recent Projects (3-6 cards) | |
* +------------------------------------------+ |
* | Pending Approvals (if any) | |
* +------------------------------------------+------------------+
*
* @see Issue #53
*/
'use client';
import { useCallback } from 'react';
import { toast } from 'sonner';
import { Card } from '@/components/ui/card';
import { ActivityFeed } from '@/components/activity/ActivityFeed';
import { WelcomeHeader } from './WelcomeHeader';
import { DashboardQuickStats } from './DashboardQuickStats';
import { RecentProjects } from './RecentProjects';
import { PendingApprovals } from './PendingApprovals';
import { EmptyState } from './EmptyState';
import { useDashboard, type PendingApproval } from '@/lib/api/hooks/useDashboard';
import { useAuth } from '@/lib/auth/AuthContext';
export interface DashboardProps {
/** Additional CSS classes */
className?: string;
}
export function Dashboard({ className }: DashboardProps) {
const { user } = useAuth();
const { data, isLoading, error } = useDashboard();
// Get user's first name for empty state
const firstName = user?.first_name || user?.email?.split('@')[0] || 'there';
// Handle approval actions
const handleApprove = useCallback((approval: PendingApproval) => {
// TODO: Implement actual approval API call
toast.success(`Approved: ${approval.title}`, {
description: `${approval.projectName}`,
});
}, []);
const handleReject = useCallback((approval: PendingApproval) => {
// TODO: Implement actual rejection API call
toast.info(`Rejected: ${approval.title}`, {
description: `${approval.projectName}`,
});
}, []);
// Show error state
if (error) {
toast.error('Failed to load dashboard data', {
description: 'Please try refreshing the page',
});
}
// Check if user has no projects (empty state)
const hasNoProjects = !isLoading && (!data?.recentProjects || data.recentProjects.length === 0);
return (
<div className={className}>
<div className="container mx-auto px-4 py-6">
{/* Welcome Header - always shown */}
<WelcomeHeader className="mb-6" />
{hasNoProjects ? (
// Empty state for new users
<EmptyState userName={firstName} />
) : (
// Main dashboard layout
<div className="grid gap-6 lg:grid-cols-[1fr_350px]">
{/* Main Content */}
<div className="space-y-6">
{/* Quick Stats */}
<DashboardQuickStats stats={data?.stats} isLoading={isLoading} />
{/* Recent Projects */}
<RecentProjects projects={data?.recentProjects} isLoading={isLoading} />
{/* Pending Approvals */}
<PendingApprovals
approvals={data?.pendingApprovals}
isLoading={isLoading}
onApprove={handleApprove}
onReject={handleReject}
/>
</div>
{/* Activity Feed Sidebar */}
{/* TODO: Enable when global activity SSE endpoint is implemented */}
{/* Currently disabled - there's no dashboard-wide SSE endpoint */}
<div className="hidden lg:block">
<Card className="sticky top-4">
<ActivityFeed
events={[]}
connectionState="disconnected"
isLoading={isLoading}
maxHeight={600}
showHeader
title="Recent Activity"
enableFiltering={false}
enableSearch={false}
compact
/>
</Card>
</div>
</div>
)}
</div>
</div>
);
}