From 16edd5bc5cfc11b96fd005ace5be8c50e475fa1b Mon Sep 17 00:00:00 2001 From: Sachin Mundassery Date: Mon, 13 Jan 2025 08:37:05 +0530 Subject: [PATCH 1/3] added user profile component --- src/components/user-profile/UserProfile.jsx | 18 +-- .../pecha-user-profile/PechaUserProfile.jsx | 57 +++++++++ .../pecha-user-profile/PechaUserProfile.scss | 112 ++++++++++++++++++ 3 files changed, 173 insertions(+), 14 deletions(-) create mode 100644 src/components/user-profile/pecha-user-profile/PechaUserProfile.jsx create mode 100644 src/components/user-profile/pecha-user-profile/PechaUserProfile.scss diff --git a/src/components/user-profile/UserProfile.jsx b/src/components/user-profile/UserProfile.jsx index b3a9c67..20b14c6 100644 --- a/src/components/user-profile/UserProfile.jsx +++ b/src/components/user-profile/UserProfile.jsx @@ -4,6 +4,7 @@ import { useAuth0 } from "@auth0/auth0-react"; import { Card } from "react-bootstrap"; import { Link } from "react-router-dom"; import { useTranslation } from "react-i18next"; +import PechaUserProfile from "./pecha-user-profile/PechaUserProfile.jsx"; function UserProfile() { const {user, isAuthenticated} = useAuth0(); @@ -33,27 +34,16 @@ function UserProfile() { ) } - function renderProfileViaPechaLogin(){ + function renderProfileViaPechaLogin() { return ( - - -
- -

To be implemented

-
- - Email:randomEmail@mail.com
- -
-
-
+ ) } return (
{ - isAuthenticated ? renderProfileViaSocialLogin() : renderProfileViaPechaLogin() + false ? renderProfileViaSocialLogin() : renderProfileViaPechaLogin() }
); diff --git a/src/components/user-profile/pecha-user-profile/PechaUserProfile.jsx b/src/components/user-profile/pecha-user-profile/PechaUserProfile.jsx new file mode 100644 index 0000000..2175ea8 --- /dev/null +++ b/src/components/user-profile/pecha-user-profile/PechaUserProfile.jsx @@ -0,0 +1,57 @@ +import React, { useState } from "react"; +import "./PechaUserProfile.scss"; + +const PechaUserProfile = () => { + const [profilePicture, setProfilePicture] = useState(null); + + const handlePictureUpload = (event) => { + const file = event.target.files[0]; + if (file) { + const reader = new FileReader(); + reader.onload = () => setProfilePicture(reader.result); + reader.readAsDataURL(file); + } + }; + + return ( +
+
+

John Doe

+

Senior Software Engineer

+

+ Bangalore + · + Master of Computer ApplIcation (MCA) + · + Bachelor of Science, Physics +

+
+ + +

Logout

+
+
+
+
+ {profilePicture ? ( + Profile + ) : ( + + )} +
+
+
+ ); +}; + +export default PechaUserProfile; diff --git a/src/components/user-profile/pecha-user-profile/PechaUserProfile.scss b/src/components/user-profile/pecha-user-profile/PechaUserProfile.scss new file mode 100644 index 0000000..60c81cb --- /dev/null +++ b/src/components/user-profile/pecha-user-profile/PechaUserProfile.scss @@ -0,0 +1,112 @@ +.pecha-user-profile { + display: flex; + justify-content: center; // Center horizontally + align-items: flex-start; // Align to the top vertically + gap: 2rem; + padding: 2rem; + + .profile-left { + display: flex; + flex-direction: column; + max-width: 300px; + text-align: left; + + .profile-name { + font-size: 1.5rem; + font-weight: bold; + } + + .profile-job-title { + font-weight: bold; + font-size: 1rem; + color: #555; + } + + .profile-details { + font-size: 0.9rem; + color: #777; + + .separator { + margin: 0 0.5rem; + } + } + + .actions-row { + display: flex; + align-items: center; + gap: 1rem; + + .edit-profile-btn, + .settings-btn { + padding: 0.5rem 1rem; + font-size: 0.9rem; + border: 1px solid #ddd; + border-radius: 4px; + background-color: white; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + cursor: pointer; + transition: all 0.3s ease; + + &:hover { + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + } + } + + .logout-text { + font-size: 0.8rem; + color: grey; + cursor: pointer; + transition: color 0.3s ease; + margin-bottom: 0; + + &:hover { + color: black; + } + } + } + } + + .profile-right { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + + .profile-picture { + position: relative; + width: 120px; + height: 120px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + background-color: #f5f5f5; + border: 2px dashed #ccc; + + .profile-image { + width: 100%; + height: 100%; + border-radius: 50%; + object-fit: cover; + } + + .add-picture-btn { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + font-size: 0.9rem; + color: #555; + text-align: center; + cursor: pointer; + border-radius: 50%; + transition: background-color 0.3s ease; + + &:hover { + background-color: #e0e0e0; + } + } + } + } +} From 1bc470fe6fab0fdcbb7040ad442457e5b7a4e2f6 Mon Sep 17 00:00:00 2001 From: Sachin Mundassery Date: Mon, 13 Jan 2025 23:35:40 +0530 Subject: [PATCH 2/3] added edit user profile component --- package-lock.json | 16 + package.json | 1 + src/App.jsx | 2 + src/components/user-profile/UserProfile.jsx | 22 +- .../edit-user-profile/EditUserProfile.jsx | 285 ++++++++++++++++++ .../edit-user-profile/EditUserProfile.scss | 54 ++++ .../pecha-user-profile/PechaUserProfile.jsx | 138 ++++++--- .../pecha-user-profile/PechaUserProfile.scss | 201 +++++++----- 8 files changed, 583 insertions(+), 136 deletions(-) create mode 100644 src/components/user-profile/edit-user-profile/EditUserProfile.jsx create mode 100644 src/components/user-profile/edit-user-profile/EditUserProfile.scss diff --git a/package-lock.json b/package-lock.json index 8e3cf04..16dcaed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@auth0/auth0-react": "^2.2.4", "axios": "^1.7.7", "bootstrap": "^5.3.3", + "bootstrap-icons": "^1.11.3", "crypto-js": "^4.2.0", "i18next": "^23.16.6", "i18next-browser-languagedetector": "^8.0.0", @@ -1963,6 +1964,21 @@ "@popperjs/core": "^2.11.8" } }, + "node_modules/bootstrap-icons": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.3.tgz", + "integrity": "sha512-+3lpHrCw/it2/7lBL15VR0HEumaBss0+f/Lb6ZvHISn1mlK83jjFpooTLsMWbIjJMDjDjOExMsTxnXSIT4k4ww==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ] + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", diff --git a/package.json b/package.json index e7d0e0f..49d42ae 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@auth0/auth0-react": "^2.2.4", "axios": "^1.7.7", "bootstrap": "^5.3.3", + "bootstrap-icons": "^1.11.3", "crypto-js": "^4.2.0", "i18next": "^23.16.6", "i18next-browser-languagedetector": "^8.0.0", diff --git a/src/App.jsx b/src/App.jsx index 1baf875..98cda58 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -13,6 +13,7 @@ import { useEffect, useState } from "react"; import axiosInstance from "./components/config/axios-config.js"; import { ACCESS_TOKEN, LOGGED_IN_VIA, REFRESH_TOKEN } from "./utils/Constants.js"; import { useAuth } from "./components/config/AuthContext.jsx"; +import EditUserProfile from "./components/user-profile/edit-user-profile/EditUserProfile.jsx"; const tokenExpiryTime = import.meta.env.VITE_TOKEN_EXPIRY_TIME_SEC; @@ -70,6 +71,7 @@ function App() { } /> } /> } /> + } /> } /> } /> } /> diff --git a/src/components/user-profile/UserProfile.jsx b/src/components/user-profile/UserProfile.jsx index 20b14c6..e9e86d3 100644 --- a/src/components/user-profile/UserProfile.jsx +++ b/src/components/user-profile/UserProfile.jsx @@ -14,36 +14,20 @@ function UserProfile() { function renderProfileViaSocialLogin() { return ( - - -
- {`${user.name}'s -

{user.given_name} {user.family_name}

-
Nickname: {user.nickname}
-
- - Email: {user.email}
- Email Verified: {user.email_verified ? 'Yes' : 'No'}
- Last Updated: {new Date(user.updated_at).toLocaleString()}
- - {t("resetPassword")} - -
-
-
+ ) } function renderProfileViaPechaLogin() { return ( - + ) } return (
{ - false ? renderProfileViaSocialLogin() : renderProfileViaPechaLogin() + isAuthenticated ? renderProfileViaSocialLogin() : renderProfileViaPechaLogin() }
); diff --git a/src/components/user-profile/edit-user-profile/EditUserProfile.jsx b/src/components/user-profile/edit-user-profile/EditUserProfile.jsx new file mode 100644 index 0000000..4c133cd --- /dev/null +++ b/src/components/user-profile/edit-user-profile/EditUserProfile.jsx @@ -0,0 +1,285 @@ +import React, { useState } from "react"; +import { Form, Button, Row, Col } from "react-bootstrap"; +import "./EditUserProfile.scss"; +import {useLocation} from "react-router-dom"; + +const EditUserProfile = () => { + + const location = useLocation(); + const userInfo = location.state?.userInfo || {}; + const [formData, setFormData] = useState({ + firstName: userInfo.firstName || userInfo.given_name|| "", + lastName: userInfo.lastName || userInfo.family_name || "", + title: userInfo.title || "", + organization: userInfo.organization || "", + website: userInfo.website || "", + location: userInfo.location || "", + education: userInfo.education || [""], + aboutMe: userInfo.aboutMe || "", + email: userInfo.email || "", + profileUrl: userInfo.profileUrl || "", + twitterHandle: userInfo.twitterHandle || "", + linkedIn: userInfo.linkedIn || "", + facebook: userInfo.facebook || "", + youtubeChannel: userInfo.youtubeChannel || "", + }); + console.log(userInfo) + const handleChange = (e) => { + const { name, value } = e.target; + setFormData({ ...formData, [name]: value }); + }; + + const handleEducationChange = (index, value) => { + const updatedEducation = [...formData.education]; + updatedEducation[index] = value; + setFormData({ ...formData, education: updatedEducation }); + }; + + const addEducation = () => { + setFormData({ ...formData, education: [...formData.education, ""] }); + }; + + const handleSubmit = (e) => { + e.preventDefault(); + console.log("Form Data:", formData); + }; + + return ( +
+

Edit Your Profile

+
+
+ {/* Personal Details Section */} +

Personal Details

+ + + + First Name + + + + + + Last Name + + + + + + + + + Title + + + + + + Organization + + + + + + + + + Website + + + + + + Location + + + + + + + Education + {formData.education.map((edu, index) => ( + + + handleEducationChange(index, e.target.value)} + placeholder="Enter your education" + /> + + + + {index !== 0 && } + + + ))} + + + + About Me + + + +
+ + {/* Contact Section */} +

Contact

+ + + + Email + + + + + + Profile URL + + + + + + + + + Twitter Handle + + + + + + LinkedIn + + + + + + + + + Facebook + + + + + + YouTube Channel + + + + + +
+ + +
+ +
+
+ ); +}; + +export default EditUserProfile; diff --git a/src/components/user-profile/edit-user-profile/EditUserProfile.scss b/src/components/user-profile/edit-user-profile/EditUserProfile.scss new file mode 100644 index 0000000..9863e44 --- /dev/null +++ b/src/components/user-profile/edit-user-profile/EditUserProfile.scss @@ -0,0 +1,54 @@ +.edit-user-profile { + max-width: 800px; + margin: 20px auto; + padding: 20px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 8px; + h2 { + text-align: center; + margin-bottom: 1.5rem; + } + + .form-buttons { + display: flex; + justify-content: center; + gap: 1rem; + margin-top: 2rem; + + button { + width: 48%; + padding: 0.75rem; + font-size: 1rem; + font-weight: bold; + border-radius: 4px; + transition: all 0.3s ease-in-out; + box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); + + &:hover { + box-shadow: 0px 6px 8px rgba(0, 0, 0, 0.15); + } + } + + .btn-secondary { + color: #ff4d4f; /* Light red */ + border: 2px solid #ff4d4f; + background-color: transparent; + + &:hover { + background-color: rgba(255, 77, 79, 0.1); + } + } + + .btn-primary { + color: #fff; + border: none; + background-color: #52c41a; + + &:hover { + background-color: #389e0d; + } + } + + } +} diff --git a/src/components/user-profile/pecha-user-profile/PechaUserProfile.jsx b/src/components/user-profile/pecha-user-profile/PechaUserProfile.jsx index 2175ea8..9b559c8 100644 --- a/src/components/user-profile/pecha-user-profile/PechaUserProfile.jsx +++ b/src/components/user-profile/pecha-user-profile/PechaUserProfile.jsx @@ -1,8 +1,12 @@ import React, { useState } from "react"; import "./PechaUserProfile.scss"; +import { Tabs, Tab } from "react-bootstrap"; +import "bootstrap-icons/font/bootstrap-icons.css"; +import {useNavigate} from "react-router-dom"; -const PechaUserProfile = () => { +const PechaUserProfile = ({userInfo}) => { const [profilePicture, setProfilePicture] = useState(null); + const navigate = useNavigate(); const handlePictureUpload = (event) => { const file = event.target.files[0]; @@ -12,46 +16,112 @@ const PechaUserProfile = () => { reader.readAsDataURL(file); } }; + const handleEditProfile = () => { + navigate("/edit-profile", { state: { userInfo } }); + }; return (
-
-

John Doe

-

Senior Software Engineer

-

- Bangalore - · - Master of Computer ApplIcation (MCA) - · - Bachelor of Science, Physics -

-
- - -

Logout

+
+
+

John Doe

+

Senior Software Engineer

+

+ Bangalore + · + Master of Computer Application (MCA) + · + Bachelor of Science, Physics +

+
+ + +

Logout

+
+
+ 0 Followers + 0 Following +
-
-
-
- {profilePicture ? ( - Profile - ) : ( - - )} +
+
+ {profilePicture ? ( + Profile + ) : ( + + )} +
+ +
+ + + Sheets + + } + > +
+

Sheets

+

Manage your sheets and documents here.

+
+
+ + Collections + + } + > +
+

Collections

+

Manage your data collections here.

+
+
+ + Notes + + } + > +
+

Notes

+

Write and manage your notes here.

+
+
+ + Buddhist Text Tracker + + } + > +
+

Buddhist Text Tracker

+

Track your progress in Buddhist texts here.

+
+
+
+
); }; -export default PechaUserProfile; +export default PechaUserProfile; \ No newline at end of file diff --git a/src/components/user-profile/pecha-user-profile/PechaUserProfile.scss b/src/components/user-profile/pecha-user-profile/PechaUserProfile.scss index 60c81cb..dbae9bf 100644 --- a/src/components/user-profile/pecha-user-profile/PechaUserProfile.scss +++ b/src/components/user-profile/pecha-user-profile/PechaUserProfile.scss @@ -1,112 +1,147 @@ .pecha-user-profile { display: flex; - justify-content: center; // Center horizontally - align-items: flex-start; // Align to the top vertically - gap: 2rem; - padding: 2rem; + flex-direction: column; + align-items: center; + padding: 20px; - .profile-left { + .section1 { display: flex; - flex-direction: column; - max-width: 300px; - text-align: left; + justify-content: space-between; + align-items: flex-start; + width: 100%; + margin-bottom: 20px; - .profile-name { - font-size: 1.5rem; - font-weight: bold; - } - - .profile-job-title { - font-weight: bold; - font-size: 1rem; - color: #555; - } + .profile-left { + flex: 4; + padding-right: 20px; + text-align: left; - .profile-details { - font-size: 0.9rem; - color: #777; + .profile-name { + font-size: 24px; + font-weight: bold; + } - .separator { - margin: 0 0.5rem; + .profile-job-title { + font-size: 18px; + color: #666; } - } - .actions-row { - display: flex; - align-items: center; - gap: 1rem; - - .edit-profile-btn, - .settings-btn { - padding: 0.5rem 1rem; - font-size: 0.9rem; - border: 1px solid #ddd; - border-radius: 4px; - background-color: white; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); - cursor: pointer; - transition: all 0.3s ease; - - &:hover { - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + .profile-details { + margin: 10px 0; + font-size: 14px; + color: #888; + + .separator { + margin: 0 5px; } } - .logout-text { - font-size: 0.8rem; - color: grey; - cursor: pointer; - transition: color 0.3s ease; - margin-bottom: 0; + .actions-row { + display: flex; + gap: 10px; + button { + padding: 10px 20px; + font-size: 14px; + background-color: white; + border: 1px solid #ccc; + border-radius: 4px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + cursor: pointer; + } - &:hover { - color: black; + .logout-text { + font-size: 14px; + color: #888; + cursor: pointer; + margin-top: 1rem; + + &:hover { + color: #000; + } + } + } + + .followers{ + display: flex; + gap: 1rem; + margin-top: 1rem; + .number-followers, .number-following{ + font-size: 14px; + color: #888; + cursor: pointer; + &:hover { + color: #000; + } } } } - } - .profile-right { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - - .profile-picture { - position: relative; - width: 120px; - height: 120px; - border-radius: 50%; + .profile-right { + flex: 1; display: flex; - align-items: center; justify-content: center; - background-color: #f5f5f5; - border: 2px dashed #ccc; + align-items: center; - .profile-image { - width: 100%; - height: 100%; + .profile-picture { + width: 120px; + height: 120px; border-radius: 50%; - object-fit: cover; - } - - .add-picture-btn { + overflow: hidden; + border: 2px solid #ccc; display: flex; - align-items: center; justify-content: center; - width: 100%; - height: 100%; - font-size: 0.9rem; - color: #555; - text-align: center; - cursor: pointer; - border-radius: 50%; - transition: background-color 0.3s ease; + align-items: center; + + .profile-image { + width: 100%; + height: 100%; + object-fit: cover; + } + + .add-picture-btn { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + cursor: pointer; + text-align: center; + background-color: #f5f5f5; + color: #666; + border-radius: 50%; + } + } + } + } + + .section2 { + width: 100%; + margin-top: 2rem; + + .nav-tabs { + border-bottom: 2px solid #ddd; - &:hover { - background-color: #e0e0e0; + .nav-item { + .nav-link { + color: #666; + font-size: 16px; + + &.active { + font-weight: bold; + border-color: #007bff #007bff #fff; + color: #007bff; + } + + i { + margin-right: 5px; + } } } } + + .tab-content { + padding: 20px; + font-size: 16px; + } } } From 709fccb879852403b6314ef5cc5e906a52933935 Mon Sep 17 00:00:00 2001 From: Sachin Mundassery Date: Wed, 15 Jan 2025 22:32:13 +0530 Subject: [PATCH 3/3] added basic ui for add and edit user profile --- src/components/user-profile/UserProfile.jsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/user-profile/UserProfile.jsx b/src/components/user-profile/UserProfile.jsx index e9e86d3..75a8159 100644 --- a/src/components/user-profile/UserProfile.jsx +++ b/src/components/user-profile/UserProfile.jsx @@ -1,16 +1,18 @@ import React from "react"; import "./UserProfile.scss"; import { useAuth0 } from "@auth0/auth0-react"; -import { Card } from "react-bootstrap"; -import { Link } from "react-router-dom"; import { useTranslation } from "react-i18next"; import PechaUserProfile from "./pecha-user-profile/PechaUserProfile.jsx"; +import {useQuery} from "react-query"; +import axiosInstance from "../config/axios-config.js"; function UserProfile() { const {user, isAuthenticated} = useAuth0(); const {t} = useTranslation(); - - console.log(user); + const userInfo = useQuery("userInfo",async () => { + return await axiosInstance.get("/api/v1/users/info"); + }) + console.log(userInfo) function renderProfileViaSocialLogin() { return (