|
2 | 2 | * Dashboard Page |
3 | 3 | * |
4 | 4 | * Protected dashboard page with modern shadcn/ui components and professional design. |
| 5 | + * Integrated with Zustand project store for state management. |
5 | 6 | */ |
6 | 7 |
|
7 | 8 | "use client"; |
8 | 9 |
|
9 | | -import React, { useState, useEffect } from 'react'; |
| 10 | +import React, { useEffect } from 'react'; |
10 | 11 | import { useRouter } from 'next/navigation'; |
11 | 12 | import { ProtectedRoute } from '@/components/auth/ProtectedRoute'; |
12 | 13 | import { useAuth } from '@/components/auth/AuthProvider'; |
13 | 14 | import { BentoGrid } from '@/components/dashboard/bento-grid'; |
14 | 15 | import { Button } from '@/components/ui/button'; |
15 | 16 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; |
16 | | -import { Badge } from '@/components/ui/badge'; |
17 | | -import { api } from '@/lib/api'; |
18 | 17 | import { FolderIcon, CheckCircleIcon, ClockIcon, AlertCircleIcon, LogOutIcon } from 'lucide-react'; |
19 | | -import type { Project } from '../../../../shared/api-contract'; |
| 18 | +import { useProjects, useProjectActions } from '@/lib/store/project'; |
20 | 19 |
|
21 | 20 | function DashboardContent() { |
22 | 21 | const { user, logout } = useAuth(); |
23 | 22 | const router = useRouter(); |
24 | | - const [projects, setProjects] = useState<Project[]>([]); |
25 | | - const [isLoading, setIsLoading] = useState(true); |
26 | | - const [error, setError] = useState<string | null>(null); |
| 23 | + const { projects, isLoading, error, total } = useProjects(); |
| 24 | + const { fetchProjects, clearError } = useProjectActions(); |
27 | 25 |
|
28 | 26 | useEffect(() => { |
29 | | - const fetchProjects = async () => { |
30 | | - try { |
31 | | - setIsLoading(true); |
32 | | - setError(null); |
33 | | - const response = await api.projects.getProjects(); |
34 | | - |
35 | | - if (response.success && response.data) { |
36 | | - setProjects(response.data.items); |
37 | | - } else { |
38 | | - setError(response.error || 'Failed to fetch projects'); |
39 | | - } |
40 | | - } catch (err) { |
41 | | - setError('Failed to fetch projects'); |
42 | | - console.error('Project fetch error:', err); |
43 | | - } finally { |
44 | | - setIsLoading(false); |
45 | | - } |
46 | | - }; |
47 | | - |
48 | 27 | if (user) { |
49 | 28 | fetchProjects(); |
50 | 29 | } |
51 | | - }, [user]); |
| 30 | + }, [user, fetchProjects]); |
52 | 31 |
|
53 | 32 | const handleLogout = async () => { |
54 | 33 | await logout(); |
55 | 34 | }; |
56 | 35 |
|
57 | 36 | const getProjectStats = () => { |
58 | | - const total = projects.length; |
59 | 37 | const ready = projects.filter(p => p.status === 'ready').length; |
60 | 38 | const processing = projects.filter(p => p.status === 'processing').length; |
61 | 39 | return { total, ready, processing }; |
62 | 40 | }; |
63 | 41 |
|
64 | | - const { total, ready, processing } = getProjectStats(); |
65 | | - |
66 | | - const fetchProjects = async () => { |
67 | | - try { |
68 | | - setIsLoading(true); |
69 | | - setError(null); |
70 | | - const response = await api.projects.getProjects(); |
71 | | - |
72 | | - if (response.success && response.data) { |
73 | | - setProjects(response.data.items); |
74 | | - } else { |
75 | | - setError(response.error || 'Failed to fetch projects'); |
76 | | - } |
77 | | - } catch (err) { |
78 | | - setError('Failed to fetch projects'); |
79 | | - console.error('Project fetch error:', err); |
80 | | - } finally { |
81 | | - setIsLoading(false); |
82 | | - } |
83 | | - }; |
| 42 | + const { ready, processing } = getProjectStats(); |
84 | 43 |
|
85 | 44 | return ( |
86 | 45 | <div className="min-h-screen bg-background"> |
@@ -178,9 +137,14 @@ function DashboardContent() { |
178 | 137 | {error && ( |
179 | 138 | <Card className="border-destructive"> |
180 | 139 | <CardContent className="p-4"> |
181 | | - <div className="flex items-center space-x-2"> |
182 | | - <AlertCircleIcon className="h-4 w-4 text-destructive" /> |
183 | | - <p className="text-sm text-destructive">{error}</p> |
| 140 | + <div className="flex items-center justify-between"> |
| 141 | + <div className="flex items-center space-x-2"> |
| 142 | + <AlertCircleIcon className="h-4 w-4 text-destructive" /> |
| 143 | + <p className="text-sm text-destructive">{error}</p> |
| 144 | + </div> |
| 145 | + <Button variant="outline" size="sm" onClick={clearError}> |
| 146 | + Dismiss |
| 147 | + </Button> |
184 | 148 | </div> |
185 | 149 | </CardContent> |
186 | 150 | </Card> |
|
0 commit comments