Skip to content

Commit 1431e2d

Browse files
committed
update project image
1 parent fcd2f1a commit 1431e2d

13 files changed

Lines changed: 355 additions & 66 deletions

File tree

backend/src/models/project.model.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,44 @@ const projectSchema = new mongoose.Schema(
6767

6868
projectSchema.index({ technologies: 1 });
6969

70+
const normalizeImages = (value) => {
71+
if (!value) return [];
72+
const list = Array.isArray(value) ? value : [value];
73+
return list
74+
.map((item) => {
75+
if (typeof item === "string") return item.trim();
76+
if (item?.url) return String(item.url).trim();
77+
if (item?.value) return String(item.value).trim();
78+
return "";
79+
})
80+
.filter(Boolean);
81+
};
82+
83+
const normalizeIdList = (value) => {
84+
if (!Array.isArray(value)) return [];
85+
return value.filter((id) => mongoose.isValidObjectId(id));
86+
};
87+
7088
projectSchema.pre("validate", function (next) {
7189
const imagesModified = this.isModified("images");
7290
const imageModified = this.isModified("image");
91+
const categoryModified = this.isModified("category");
92+
const technologiesModified = this.isModified("technologies");
93+
94+
if (imagesModified) {
95+
this.images = normalizeImages(this.images);
96+
}
97+
if (imageModified && typeof this.image === "string") {
98+
this.image = this.image.trim();
99+
}
100+
if (categoryModified && this.category) {
101+
if (!mongoose.isValidObjectId(this.category)) {
102+
this.category = undefined;
103+
}
104+
}
105+
if (technologiesModified) {
106+
this.technologies = normalizeIdList(this.technologies);
107+
}
73108

74109
if (imagesModified) {
75110
if (Array.isArray(this.images) && this.images.length) {

frontend/src/components/cart/CartItem.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React, { useEffect } from "react";
33
import { useDispatch, useSelector } from "react-redux";
44
import { asyncupdateuser } from "../../store/actions/userActions";
55
import { Link } from "react-router-dom";
6+
import { getPrimaryImage } from "../../utils/projectImages";
67

78
const Carts = () => {
89
const dispatch = useDispatch();
@@ -29,7 +30,10 @@ const Carts = () => {
2930
if (!item?.product) return null;
3031

3132
const project = item.product;
32-
const { image, title, id, category } = project;
33+
const { title, id, category } = project;
34+
const image =
35+
getPrimaryImage(project?.image, project?.images) ||
36+
"https://via.placeholder.com/120";
3337

3438
return (
3539
<div

frontend/src/components/home/AwardProjects.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Award, ArrowRight } from "lucide-react";
33
import { Link } from "react-router-dom";
44
import { useMemo } from "react";
55
import { useAwards } from "../../api/awards";
6+
import { getPrimaryImage } from "../../utils/projectImages";
67

78
const formatAward = (award) => {
89
if (!award) return null;
@@ -75,7 +76,7 @@ const AwardProjects = () => {
7576
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
7677
{featured.map(({ project, awards }) => {
7778
const projectId = project?.id || project?._id;
78-
const image = project?.images?.[0] || project?.image;
79+
const image = getPrimaryImage(project?.image, project?.images);
7980
const title = project?.title || "Awarded Project";
8081
const description = project?.description;
8182
return (

frontend/src/components/home/FeaturedProject.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { motion, useReducedMotion } from "framer-motion";
22
import { ArrowRight, Sparkles } from "lucide-react";
33
import { Link } from "react-router-dom";
44
import { useProjects } from "../../api/projects";
5+
import { getPrimaryImage } from "../../utils/projectImages";
56

67
const FeaturedProject = () => {
78
const shouldReduceMotion = useReducedMotion();
@@ -21,7 +22,7 @@ const FeaturedProject = () => {
2122
.filter(Boolean)
2223
.slice(0, 4)
2324
: [];
24-
const image = project?.images?.[0] || project?.image;
25+
const image = getPrimaryImage(project?.image, project?.images);
2526

2627
const sectionMotion = shouldReduceMotion
2728
? {}

frontend/src/components/home/TrendingProjects.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { motion, useReducedMotion } from "framer-motion";
22
import { ArrowRight } from "lucide-react";
33
import { Link } from "react-router-dom";
44
import { useProjects } from "../../api/projects";
5+
import { getPrimaryImage } from "../../utils/projectImages";
56

67
const awardLabel = (award) => {
78
if (!award) return null;
@@ -57,7 +58,7 @@ const TrendingProjects = () => {
5758
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
5859
{projects.map((project) => {
5960
const projectId = project?.id || project?._id;
60-
const image = project?.images?.[0] || project?.image;
61+
const image = getPrimaryImage(project?.image, project?.images);
6162
const title = project?.title || "Untitled Project";
6263
const developer =
6364
project?.developerId?.name ||

frontend/src/components/project/ProjectCard.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ import { Link } from "react-router-dom";
22
import { useMemo, useState } from "react";
33
import { motion } from "framer-motion";
44
import { ExternalLink, Eye, Github, Heart } from "lucide-react";
5+
import { getPrimaryImage } from "../../utils/projectImages";
56

67
const ProjectCard = ({ p }) => {
78
const [isWishlisted, setIsWishlisted] = useState(false);
89

910
const image =
10-
p?.images?.[0] ||
11-
p?.image ||
11+
getPrimaryImage(p?.image, p?.images) ||
1212
"https://via.placeholder.com/600x450?text=Project+Preview";
1313
const title = p?.title || "Untitled Project";
1414
const description = p?.description || "No description available.";

0 commit comments

Comments
 (0)