diff --git a/client/package-lock.json b/client/package-lock.json index bfacabe..5e663e6 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -19,6 +19,7 @@ "express": "^4.18.3", "html-to-text": "^9.0.5", "jodit-react": "^4.0.15", + "lucide-react": "^0.453.0", "react": "^18.2.0", "react-chartjs-2": "^5.2.0", "react-dom": "^18.2.0", @@ -13513,6 +13514,14 @@ "yallist": "^3.0.2" } }, + "node_modules/lucide-react": { + "version": "0.453.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.453.0.tgz", + "integrity": "sha512-kL+RGZCcJi9BvJtzg2kshO192Ddy9hv3ij+cPrVPWSRzgCWCVazoQJxOjAwgK53NomL07HB7GPHW120FimjNhQ==", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" + } + }, "node_modules/lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", @@ -29563,6 +29572,12 @@ "yallist": "^3.0.2" } }, + "lucide-react": { + "version": "0.453.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.453.0.tgz", + "integrity": "sha512-kL+RGZCcJi9BvJtzg2kshO192Ddy9hv3ij+cPrVPWSRzgCWCVazoQJxOjAwgK53NomL07HB7GPHW120FimjNhQ==", + "requires": {} + }, "lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", diff --git a/client/package.json b/client/package.json index 500d978..2c472bd 100644 --- a/client/package.json +++ b/client/package.json @@ -23,6 +23,7 @@ "express": "^4.18.3", "html-to-text": "^9.0.5", "jodit-react": "^4.0.15", + "lucide-react": "^0.453.0", "react": "^18.2.0", "react-chartjs-2": "^5.2.0", "react-dom": "^18.2.0", diff --git a/client/src/components/Dashboard/MyProfile.js b/client/src/components/Dashboard/MyProfile.js index 9e314eb..461fdbb 100644 --- a/client/src/components/Dashboard/MyProfile.js +++ b/client/src/components/Dashboard/MyProfile.js @@ -7,6 +7,8 @@ import { ACCOUNT_TYPE } from "../../utils/constant"; import { formattedDate } from "../../utils/formattedDate"; import { fetchUserDetails } from "../../services/operations/settingsAPI"; import { setLoading, setUserDetails } from "../../slices/profileSlice"; +import { MapPin, Clock, Award, Briefcase, Plus } from 'lucide-react'; +import AboutCard from "../../components/UI/AboutCard" import React from "react"; export default function MyProfile() { // const { user, userDetails, loading, error } = useSelector((state) => ({ @@ -78,104 +80,130 @@ export default function MyProfile() { console.log("userDetails", userDetails); return ( -
-

- My Profile -

-
-
+
+ {/* Header Section */} +
+
+
+

My Profile

+ navigate("/dashboard/settings")} + > + + +
+ +
{`profile-${user?.firstName}`} -
-

- {user?.firstName + " " + user?.lastName} -

-

{user?.email}

+ +
+
+

+ {user?.firstName + " " + user?.lastName} +

+

{user?.email}

+
+ +
+
+

Follower

+

{user?.followers?.length || 0}

+
+
+

Following

+

{user?.following?.length || 0}

+
+
+

{user?.blogs?.length || 0}

+

Blogs

+
+
-
-

Follower

-

{user?.followers?.length}

+
+
+ + {/* Stats Section */} +
+
+ +
+
3+ Years
+
Experience
-
- {" "} -

Following

-

{user?.following?.length}

+
+ +
+ +
+
5 Certificates
+
Achieved
-
-

{user?.blogs?.length}

-

Blogs

+
+ +
+ +
+
2 Internship
+
Completed
-
-
-

About

+
- { - navigate("/dashboard/settings"); - }} - > - - -
-

+

+

About

+ navigate("/dashboard/settings")} > - {userDetails?.about ?? "Write Something About Yourself"} -

-
-
-
-

First Name

-

- {user?.firstName} -

-
-
-

Email

-

- {user?.username} -

-
-
-

Gender

-

- {userDetails?.gender ?? "Add Gender"} -

-
-
-
-
-

Last Name

-

- {user?.lastName} -

-
-
-

Phone Number

-

- {userDetails?.contactNo ?? "Add Contact Number"} -

-
+ + +
+ +

+ {userDetails?.about ?? "Write Something About Yourself"} +

-
-

- Date Of Birth -

-

- {formattedDate(userDetails?.DOB) ?? "Add Date Of Birth"} -

-
-
+
+
+

First Name

+

{user?.firstName}

+
+
+

Last Name

+

{user?.lastName}

+
+
+

Email

+

{user?.username}

+
+
+

Phone Number

+

+ {userDetails?.contactNo ?? "Add Contact Number"} +

+
+
+

Gender

+

+ {userDetails?.gender ?? "Add Gender"} +

+
+
+

Date Of Birth

+

+ {formattedDate(userDetails?.DOB) ?? "Add Date Of Birth"} +

-
+ +
); } diff --git a/client/src/components/UI/AboutCard.js b/client/src/components/UI/AboutCard.js new file mode 100644 index 0000000..69483a6 --- /dev/null +++ b/client/src/components/UI/AboutCard.js @@ -0,0 +1,111 @@ +import React from 'react'; + +const Card = ({ + children, + className = "", + title, + subtitle, + icon, + rightElement, + dateRange, + location +}) => { + return ( +
+ {/* Card Header - Only rendered if title exists */} + {(title || rightElement) && ( +
+
+ {/* Icon/Image Container */} + {icon && ( +
+ {icon} +
+ )} + + {/* Title Section */} +
+ {title &&

{title}

} + {subtitle &&

{subtitle}

} +
+
+ + {/* Right Element (e.g., date, buttons) */} + {rightElement && ( +
+ {dateRange && ( +
+ + + + + {dateRange} +
+ )} + {location && ( +
+ + + + + {location} +
+ )} + {rightElement} +
+ )} +
+ )} + + {/* Card Content */} +
+ {children} +
+
+ ); +}; + +// Usage Examples +const ExampleUsage = () => { + return ( +
+ {/* Basic Card */} + +

Simple card with just content

+
+ + {/* Job Experience Card */} + } + dateRange="Feb 2016 - Dec 2017" + location="New York, USA" + > +

+ There are many variations of passages of Lorem Ipsum available... +

+
+ + {/* Profile Info Card */} + + + + + + Edit + + } + > +

+ Profile content goes here... +

+
+
+ ); +}; + +export default Card; \ No newline at end of file diff --git a/client/src/pages/UserProfile.js b/client/src/pages/UserProfile.js index 7d2122a..4f945f4 100644 --- a/client/src/pages/UserProfile.js +++ b/client/src/pages/UserProfile.js @@ -22,6 +22,7 @@ import { removeModeratorAPI, } from "../services/operations/blogAPI"; import { setUserDetails } from "../slices/profileSlice"; +import AboutCard from "../components/UI/AboutCard"; function UserProfile() { const { username } = useParams(); const { token } = useSelector((state) => state.auth); @@ -123,7 +124,13 @@ function UserProfile() { console.log("user inside userprofile", user); console.log("userDetails which user login", userDetails); return ( -
+ +
+ {/* Profile Header Card */} + + + +
@@ -178,85 +185,117 @@ function UserProfile() { )}
-
-
    -
  • - - {user?.blogs?.length} - {" "} - posts -
  • + {/* Profile Info */} +
    +
    +
    +

    {user?.username}

    +

    + {user?.firstName} {user?.lastName} +

    +
    -
  • - - {user?.followers.length} - {" "} - followers -
  • -
  • - - {user?.following?.length} - {" "} - following -
  • -
+ {/* Action Buttons */} +
+ {isFollowing ? ( + + ) : ( + + )} + + {/* Admin Controls */} + {userDetails?.data?.role === ACCOUNT_TYPE.ADMIN && ( + + )} +
-
-

- - {user.firstName} {user.lastName} - - {/*

  • */} - - - {user?.contributions} contributions - {" "} - {/*
  • */} - - {user?.additionalDetails?.about} - -

    + + {/* Stats */} +
    +
    + {user?.blogs?.length} + posts +
    +
    + {user?.followers?.length} + followers +
    +
    + {user?.following?.length} + following +
    +
    + + {/* Bio & Contributions */} +
    +
    + + {user?.contributions} contributions +
    +

    {user?.additionalDetails?.about}

    -
    -
    -
    - {/* Render gallery items */} - {user?.blogs.map((item) => ( - -
    - -
    -
  • - Likes: - {" "} - {item?.title} -
  • -
      -
    • - - Likes: - -
    • +
    + -
  • - Comments: -
  • - + {/* Blog Gallery */} +
    + {user?.blogs.map((blog) => ( + + +
    + {blog.title} + {/* Overlay */} +
    +

    {blog.title}

    +
    +
    + + {blog.upvotes.length} +
    +
    + + {blog.comments.length}
    - - ))} -
    - {/*
    */} -
    -
    +
    +
    + + + ))}
    +
    ); }