Skip to content

Commit 4640f02

Browse files
author
pengyu
committed
add my project and community project
1 parent 7d87301 commit 4640f02

File tree

1 file changed

+95
-28
lines changed

1 file changed

+95
-28
lines changed

frontend/src/components/root/projects-section.tsx

Lines changed: 95 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,125 @@
1+
'use client';
2+
13
import { useQuery } from '@apollo/client';
24
import { FETCH_PUBLIC_PROJECTS } from '@/graphql/request';
35
import { ExpandableCard } from './expand-card';
6+
import { useContext, useState } from 'react';
7+
import { ProjectContext } from '../chat/code-engine/project-context';
8+
import { redirectChatPage } from '../chat-page-navigation';
9+
import { Button } from '@/components/ui/button';
10+
import { RotateCwIcon } from 'lucide-react';
11+
import { useRouter } from 'next/navigation';
12+
import { useAuthContext } from '@/providers/AuthProvider';
413

514
export function ProjectsSection() {
6-
// Execute the GraphQL query with provided variables
15+
const [view, setView] = useState<'my' | 'community'>('my');
16+
17+
const { user } = useAuthContext();
18+
const username = user?.username || '';
19+
const { setChatId } = useContext(ProjectContext);
20+
const [currentChatid, setCurrentChatid] = useState('');
21+
const router = useRouter();
22+
723
const { data, loading, error } = useQuery(FETCH_PUBLIC_PROJECTS, {
8-
// Make sure strategy matches the backend definition (e.g., 'latest' or 'trending')
9-
variables: { input: { size: 10, strategy: 'latest' } },
24+
variables: { input: { size: 100, strategy: 'latest' } },
25+
});
26+
27+
const allProjects = data?.fetchPublicProjects || [];
28+
29+
// 筛选我的项目 vs 社区项目
30+
const filteredProjects = allProjects.filter((project) => {
31+
const projectUsername = project.user?.username || '';
32+
return view === 'my'
33+
? projectUsername === username
34+
: projectUsername !== username;
1035
});
1136

12-
const fetchedProjects = data?.fetchPublicProjects || [];
13-
14-
// Transform fetched data to match the component's expected format
15-
const transformedProjects = fetchedProjects.map((project) => ({
16-
id: project.id,
17-
name: project.projectName,
18-
path: project.projectPath,
19-
createDate: project.createdAt
20-
? new Date(project.createdAt).toISOString().split('T')[0]
21-
: '2025-01-01',
22-
author: project.user?.username || 'Unknown',
23-
forkNum: project.subNumber || 0,
24-
image:
25-
project.photoUrl || `https://picsum.photos/500/250?random=${project.id}`,
26-
}));
37+
const transformedProjects = filteredProjects.map((project) => {
38+
const isReady = Boolean(project.projectPath);
39+
return {
40+
id: project.id,
41+
name: project.projectName,
42+
path: project.projectPath,
43+
isReady,
44+
createDate: project.createdAt
45+
? new Date(project.createdAt).toISOString().split('T')[0]
46+
: '2025-01-01',
47+
author: project.user?.username || 'Unknown',
48+
forkNum: project.subNumber || 0,
49+
image:
50+
project.photoUrl ||
51+
`https://picsum.photos/500/250?random=${project.id}`,
52+
};
53+
});
54+
55+
const handleOpenChat = (chatId: string) => {
56+
redirectChatPage(chatId, setCurrentChatid, setChatId, router);
57+
};
2758

2859
return (
2960
<section className="w-full max-w-7xl mx-auto px-4">
3061
<div className="mb-8">
31-
{/* Header and "View All" button always visible */}
62+
{/* Header with View Toggle */}
3263
<div className="flex items-center justify-between mb-4">
3364
<h2 className="text-2xl font-semibold dark:text-white">
34-
Featured Projects
65+
{view === 'my' ? 'My Projects' : 'Community Projects'}
3566
</h2>
36-
<button className="text-primary-600 dark:text-primary-400 hover:underline">
37-
View All &rarr;
38-
</button>
67+
<div className="flex gap-2">
68+
<Button
69+
variant={view === 'my' ? 'default' : 'outline'}
70+
onClick={() => setView('my')}
71+
>
72+
My Projects
73+
</Button>
74+
<Button
75+
variant={view === 'community' ? 'default' : 'outline'}
76+
onClick={() => setView('community')}
77+
>
78+
Community
79+
</Button>
80+
</div>
3981
</div>
4082

83+
{/* Content */}
4184
{loading ? (
4285
<div className="text-center py-10">Loading...</div>
4386
) : error ? (
44-
<div className="text-center py-10">Error: {error.message}</div>
87+
<div className="text-center py-10 text-red-500">
88+
Error: {error.message}
89+
</div>
4590
) : (
46-
<div>
91+
<>
4792
{transformedProjects.length > 0 ? (
48-
<ExpandableCard projects={transformedProjects} />
93+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
94+
{transformedProjects.map((project) =>
95+
view === 'my' && !project.isReady ? (
96+
<div
97+
key={project.id}
98+
className="border border-gray-200 dark:border-zinc-700 rounded-lg p-6 flex flex-col justify-center items-center bg-gray-50 dark:bg-zinc-800 text-center"
99+
>
100+
<RotateCwIcon className="animate-spin h-6 w-6 text-gray-500 mb-3" />
101+
<p className="text-sm text-gray-500 dark:text-gray-400 mb-4">
102+
Generating project...
103+
</p>
104+
<Button
105+
variant="ghost"
106+
size="sm"
107+
onClick={() => handleOpenChat(project.id)}
108+
>
109+
Open Chat
110+
</Button>
111+
</div>
112+
) : (
113+
<ExpandableCard key={project.id} projects={[project]} />
114+
)
115+
)}
116+
</div>
49117
) : (
50-
// Show message when no projects are available
51118
<div className="text-center py-10 text-gray-500 dark:text-gray-400">
52119
No projects available.
53120
</div>
54121
)}
55-
</div>
122+
</>
56123
)}
57124
</div>
58125
</section>

0 commit comments

Comments
 (0)