feat: implement project showcase section with database integration, filtering, and detail modals

This commit is contained in:
Yolando
2026-04-03 18:29:10 +07:00
parent e511a50021
commit 9554674c79
16 changed files with 550 additions and 391 deletions

View File

@@ -21,6 +21,9 @@ export async function createProjectAction(prevState: any, formData: FormData) {
liveUrl: formData.get("liveUrl") as string,
isPublished: formData.get("isPublished") === "on",
image: formData.get("image") as File | null,
techStack: formData.get("techStack") as string,
year: formData.get("year") as string,
highlights: formData.get("highlights") as string,
};
const validation = projectSchema.safeParse(data);
@@ -51,12 +54,15 @@ export async function createProjectAction(prevState: any, formData: FormData) {
liveUrl: validation.data.liveUrl || null,
isPublished: validation.data.isPublished,
imageUrl: imageUrl,
techStack: validation.data.techStack ? validation.data.techStack.split(",").map(s => s.trim()).filter(s => s) : [],
year: validation.data.year || null,
highlights: validation.data.highlights ? validation.data.highlights.split(",").map(s => s.trim()).filter(s => s) : [],
},
});
revalidatePath("/admin/dashboard");
revalidatePath("/");
return { success: true };
} catch (error: any) {
console.error("DB Error:", error);
@@ -80,6 +86,9 @@ export async function updateProjectAction(id: string, prevState: any, formData:
liveUrl: formData.get("liveUrl") as string,
isPublished: formData.get("isPublished") === "on",
image: formData.get("image") as File | null,
techStack: formData.get("techStack") as string,
year: formData.get("year") as string,
highlights: formData.get("highlights") as string,
};
const validation = projectSchema.safeParse(data);
@@ -108,13 +117,16 @@ export async function updateProjectAction(id: string, prevState: any, formData:
liveUrl: validation.data.liveUrl || null,
isPublished: validation.data.isPublished,
...(imageUrl && { imageUrl }), // only update image if a new one was uploaded
techStack: validation.data.techStack ? validation.data.techStack.split(",").map(s => s.trim()).filter(s => s) : [],
year: validation.data.year || null,
highlights: validation.data.highlights ? validation.data.highlights.split(",").map(s => s.trim()).filter(s => s) : [],
},
});
revalidatePath("/admin/dashboard");
revalidatePath("/admin/dashboard/projects");
revalidatePath("/");
return { success: true };
} catch (error: any) {
if (error?.code === "P2002") {