Skip to content

Commit c13742c

Browse files
committed
feat(projects): show event submissions in portfolio
1 parent b581a2d commit c13742c

1 file changed

Lines changed: 131 additions & 65 deletions

File tree

‎apps/web/src/server/routes/projects.ts‎

Lines changed: 131 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,62 @@ import {
1717
import { NotificationService } from "@/features/notifications/service";
1818
import { getCachedOrganizations } from "@community/lib-server/cache/organizations";
1919
import { ContributionType } from "@prisma/client";
20+
import type { EventStatus, Prisma, SubmissionStatus } from "@prisma/client";
2021
import { Hono } from "hono";
2122
import { z } from "zod";
2223
import { createProjectSchema, updateProjectSchema } from "./projects-schemas";
2324

25+
const PUBLIC_EVENT_STATUSES: EventStatus[] = [
26+
"PUBLISHED",
27+
"REGISTRATION_CLOSED",
28+
"ONGOING",
29+
"COMPLETED",
30+
];
31+
32+
const PUBLIC_SUBMISSION_STATUSES: SubmissionStatus[] = [
33+
"SUBMITTED",
34+
"UNDER_REVIEW",
35+
"APPROVED",
36+
"AWARDED",
37+
];
38+
39+
const publicProjectVisibilityWhere: Prisma.ProjectWhereInput = {
40+
user: {
41+
profilePublic: true,
42+
},
43+
OR: [
44+
{
45+
isComplete: true,
46+
},
47+
{
48+
isSubmission: true,
49+
communityUseAuth: true,
50+
eventSubmissions: {
51+
some: {
52+
status: {
53+
in: PUBLIC_SUBMISSION_STATUSES,
54+
},
55+
event: {
56+
status: {
57+
in: PUBLIC_EVENT_STATUSES,
58+
},
59+
},
60+
},
61+
},
62+
},
63+
],
64+
};
65+
66+
function getPublicProjectWhere(
67+
where?: Prisma.ProjectWhereInput,
68+
): Prisma.ProjectWhereInput {
69+
return where
70+
? {
71+
AND: [publicProjectVisibilityWhere, where],
72+
}
73+
: publicProjectVisibilityWhere;
74+
}
75+
2476
// 作品完成度计算函数
2577
function calculateProjectCompletion(data: {
2678
title: string;
@@ -83,36 +135,31 @@ export const projectsRouter = new Hono()
83135
const sort = c.req.query("sort");
84136
const sortOrder = c.req.query("sortOrder") || "desc";
85137

86-
const where: any = {
87-
user: {
88-
profilePublic: true,
89-
},
90-
isComplete: true,
91-
};
138+
const filterWhere: Prisma.ProjectWhereInput = {};
92139

93140
// Handle special stage filters
94141
if (stage === "recruiting") {
95-
where.isRecruiting = true;
142+
filterWhere.isRecruiting = true;
96143
} else if (stage === "featured") {
97-
where.featured = true;
144+
filterWhere.featured = true;
98145
} else if (stage === "early") {
99-
where.stage = {
146+
filterWhere.stage = {
100147
in: ["IDEA_VALIDATION", "DEVELOPMENT", "LAUNCH"],
101148
};
102149
} else if (stage === "mature") {
103-
where.stage = {
150+
filterWhere.stage = {
104151
in: ["GROWTH", "MONETIZATION", "FUNDING", "COMPLETED"],
105152
};
106153
} else if (
107154
stage &&
108155
stage !== "recruiting" &&
109156
stage !== "featured"
110157
) {
111-
where.stage = stage;
158+
filterWhere.stage = stage as any;
112159
}
113160

114161
if (search) {
115-
where.OR = [
162+
filterWhere.OR = [
116163
{
117164
title: {
118165
contains: search,
@@ -134,8 +181,7 @@ export const projectsRouter = new Hono()
134181
}
135182

136183
if (organization) {
137-
where.user = {
138-
...where.user,
184+
filterWhere.user = {
139185
members: {
140186
some: {
141187
organization: {
@@ -146,6 +192,8 @@ export const projectsRouter = new Hono()
146192
};
147193
}
148194

195+
const where = getPublicProjectWhere(filterWhere);
196+
149197
const orderBy: any = [{ featured: "desc" }];
150198
const direction = sortOrder === "asc" ? "asc" : "desc";
151199
if (sort === "latest") {
@@ -159,7 +207,7 @@ export const projectsRouter = new Hono()
159207
}
160208

161209
// 优化后的查询:使用并发查询和缓存组织数据
162-
const [projects, stats, totalProjects, organizations] =
210+
const [projectRows, stats, totalProjects, organizations] =
163211
await Promise.all([
164212
db.project.findMany({
165213
where,
@@ -181,6 +229,17 @@ export const projectsRouter = new Hono()
181229
isRecruiting: true,
182230
recruitmentTags: true,
183231
recruitmentStatus: true,
232+
attachments: {
233+
where: {
234+
fileType: "image",
235+
},
236+
orderBy: {
237+
order: "asc",
238+
},
239+
select: {
240+
fileUrl: true,
241+
},
242+
},
184243
likes: session?.user
185244
? {
186245
where: {
@@ -237,24 +296,21 @@ export const projectsRouter = new Hono()
237296
_count: {
238297
stage: true,
239298
},
240-
where: {
241-
user: {
242-
profilePublic: true,
243-
},
244-
isComplete: true,
245-
},
299+
where: getPublicProjectWhere(),
246300
}),
247301
db.project.count({
248-
where: {
249-
user: {
250-
profilePublic: true,
251-
},
252-
isComplete: true,
253-
},
302+
where: getPublicProjectWhere(),
254303
}),
255304
// 使用缓存的组织数据替代直接查询
256305
getCachedOrganizations(),
257306
]);
307+
const projects = projectRows.map(({ attachments, ...project }) => ({
308+
...project,
309+
screenshots:
310+
project.screenshots.length > 0
311+
? project.screenshots
312+
: attachments.map((attachment) => attachment.fileUrl),
313+
}));
258314

259315
return c.json({
260316
projects,
@@ -916,13 +972,9 @@ export const projectsRouter = new Hono()
916972

917973
// Get user's public projects
918974
const projects = await db.project.findMany({
919-
where: {
975+
where: getPublicProjectWhere({
920976
userId,
921-
user: {
922-
profilePublic: true, // Only show projects if user's profile is public
923-
},
924-
isComplete: true, // 只显示高完成度作品
925-
},
977+
}),
926978
orderBy: [
927979
{ featured: "desc" },
928980
{ order: "asc" },
@@ -941,10 +993,31 @@ export const projectsRouter = new Hono()
941993
featured: true,
942994
createdAt: true,
943995
updatedAt: true,
996+
attachments: {
997+
where: {
998+
fileType: "image",
999+
},
1000+
orderBy: {
1001+
order: "asc",
1002+
},
1003+
select: {
1004+
fileUrl: true,
1005+
},
1006+
},
9441007
},
9451008
});
9461009

947-
return c.json({ projects });
1010+
return c.json({
1011+
projects: projects.map(({ attachments, ...project }) => ({
1012+
...project,
1013+
screenshots:
1014+
project.screenshots.length > 0
1015+
? project.screenshots
1016+
: attachments.map(
1017+
(attachment) => attachment.fileUrl,
1018+
),
1019+
})),
1020+
});
9481021
} catch (error) {
9491022
console.error("Error fetching public projects:", error);
9501023
return c.json({ error: "Internal server error" }, 500);
@@ -964,11 +1037,9 @@ export const projectsRouter = new Hono()
9641037

9651038
// Check if project exists and is public
9661039
const project = await db.project.findFirst({
967-
where: {
968-
...resolveProjectIdentifier(projectId),
969-
user: { profilePublic: true },
970-
isComplete: true, // 确保是高完成度作品
971-
},
1040+
where: getPublicProjectWhere(
1041+
resolveProjectIdentifier(projectId),
1042+
),
9721043
});
9731044

9741045
if (!project) {
@@ -1066,7 +1137,9 @@ export const projectsRouter = new Hono()
10661137

10671138
// Resolve project identifier
10681139
const project = await db.project.findFirst({
1069-
where: resolveProjectIdentifier(projectId),
1140+
where: getPublicProjectWhere(
1141+
resolveProjectIdentifier(projectId),
1142+
),
10701143
select: { id: true },
10711144
});
10721145

@@ -1125,11 +1198,9 @@ export const projectsRouter = new Hono()
11251198

11261199
// Check if project exists and is public
11271200
const project = await db.project.findFirst({
1128-
where: {
1129-
...resolveProjectIdentifier(projectId),
1130-
user: { profilePublic: true },
1131-
isComplete: true, // 确保是高完成度作品
1132-
},
1201+
where: getPublicProjectWhere(
1202+
resolveProjectIdentifier(projectId),
1203+
),
11331204
});
11341205

11351206
if (!project) {
@@ -1186,7 +1257,9 @@ export const projectsRouter = new Hono()
11861257

11871258
// Resolve project identifier
11881259
const project = await db.project.findFirst({
1189-
where: resolveProjectIdentifier(projectId),
1260+
where: getPublicProjectWhere(
1261+
resolveProjectIdentifier(projectId),
1262+
),
11901263
select: { id: true },
11911264
});
11921265

@@ -1240,11 +1313,9 @@ export const projectsRouter = new Hono()
12401313

12411314
// Check if project exists and is public
12421315
const project = await db.project.findFirst({
1243-
where: {
1244-
...resolveProjectIdentifier(projectId),
1245-
user: { profilePublic: true },
1246-
isComplete: true, // 确保是高完成度作品
1247-
},
1316+
where: getPublicProjectWhere(
1317+
resolveProjectIdentifier(projectId),
1318+
),
12481319
});
12491320

12501321
if (!project) {
@@ -1327,7 +1398,9 @@ export const projectsRouter = new Hono()
13271398

13281399
// Get project with user information and counts
13291400
const project = await db.project.findFirst({
1330-
where: resolveProjectIdentifier(projectId),
1401+
where: getPublicProjectWhere(
1402+
resolveProjectIdentifier(projectId),
1403+
),
13311404
include: {
13321405
user: {
13331406
select: {
@@ -1348,12 +1421,7 @@ export const projectsRouter = new Hono()
13481421
},
13491422
});
13501423

1351-
if (
1352-
!project ||
1353-
!project.user ||
1354-
!project.user.profilePublic ||
1355-
!project.isComplete
1356-
) {
1424+
if (!project || !project.user || !project.user.profilePublic) {
13571425
return c.json({ error: "Project not found" }, 404);
13581426
}
13591427

@@ -1401,7 +1469,9 @@ export const projectsRouter = new Hono()
14011469

14021470
// Get the project to find the user ID
14031471
const project = await db.project.findFirst({
1404-
where: resolveProjectIdentifier(projectId),
1472+
where: getPublicProjectWhere(
1473+
resolveProjectIdentifier(projectId),
1474+
),
14051475
select: {
14061476
id: true,
14071477
userId: true,
@@ -1419,14 +1489,10 @@ export const projectsRouter = new Hono()
14191489

14201490
// Get related projects from the same user
14211491
const relatedProjects = await db.project.findMany({
1422-
where: {
1492+
where: getPublicProjectWhere({
14231493
userId: project.userId,
14241494
id: { not: project.id },
1425-
user: {
1426-
profilePublic: true,
1427-
},
1428-
isComplete: true,
1429-
},
1495+
}),
14301496
include: {
14311497
user: {
14321498
select: {

0 commit comments

Comments
 (0)