diff --git a/src/assets/styles/basics/_CustomButton.scss b/src/assets/styles/basics/_CustomButton.scss
index bbe34e3..08dfb41 100644
--- a/src/assets/styles/basics/_CustomButton.scss
+++ b/src/assets/styles/basics/_CustomButton.scss
@@ -11,7 +11,6 @@
font-weight: 600;
line-height: 20px;
max-width: 480px;
- min-height: 40px;
min-width: min-content;
overflow: hidden;
padding: 0px;
diff --git a/src/assets/styles/cmps/group-info/_GroupInfo.scss b/src/assets/styles/cmps/group-info/_GroupProfile.scss
similarity index 86%
rename from src/assets/styles/cmps/group-info/_GroupInfo.scss
rename to src/assets/styles/cmps/group-info/_GroupProfile.scss
index 63ea81f..1bb9ce1 100644
--- a/src/assets/styles/cmps/group-info/_GroupInfo.scss
+++ b/src/assets/styles/cmps/group-info/_GroupProfile.scss
@@ -1,4 +1,4 @@
-.group-info {
+.group-profile {
@include fadeIn;
justify-self: center;
margin-top: 20px;
@@ -10,6 +10,7 @@
background: linear-gradient(to bottom right, $mainColor-light0, $mainColor-dark3);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
border-radius: 20px;
+ color: $profileFontColor;
&__header {
position: relative;
@@ -24,10 +25,8 @@
justify-content: center;
align-items: center;
width: 100%;
-
- &:hover .user-profile__profile-banner {
- opacity: 0.8;
- }
+ background-color: white;
+ border-radius: 10px;
}
&__banner-img {
@@ -36,6 +35,15 @@
border-radius: 10px;
width: 100%;
height: 200px;
+ transition: opacity 0.3s;
+
+ &.highlightable {
+ cursor: pointer;
+
+ &:hover {
+ opacity: 0.9;
+ }
+ }
}
&__upload-profile-banner-input {
@@ -58,7 +66,7 @@
button {
background: none;
border: none;
- color: #4b3832;
+ color: $profileFontColor;
font-weight: bold;
font-size: 12px;
cursor: pointer;
@@ -72,13 +80,11 @@
&__profile-picture-container {
position: relative;
display: flex;
- width: fit-content;
- height: fit-content;
+ width: 120px;
+ height: 120px;
margin-left: 30px;
-
- &:hover .user-profile__profile-picture {
- opacity: 0.8;
- }
+ background-color: white;
+ border-radius: 50%;
}
&__profile-img {
@@ -92,6 +98,14 @@
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
object-fit: cover;
transition: opacity 0.3s;
+
+ &.highlightable {
+ cursor: pointer;
+
+ &:hover {
+ opacity: 0.8;
+ }
+ }
}
&__upload-profile-picture-input {
@@ -112,7 +126,7 @@
button {
background: none;
border: none;
- color: #4b3832;
+ color: $profileFontColor;
font-weight: bold;
font-size: 12px;
cursor: pointer;
@@ -143,7 +157,6 @@
font-size: 32px;
font-weight: bold;
margin: 0;
- color: #4b3832;
}
&__divider {
@@ -163,7 +176,6 @@
gap: 10px;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
border-radius: 8px;
- color: #4b3832;
overflow-x: auto;
}
@@ -178,11 +190,10 @@
&__description-container {
@include flex-column;
- padding: 14px;
+ padding: $profileBoxPadding;
background: $mainColor-light0;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
border-radius: 8px;
- color: $mainFontColor;
flex-basis: 60%;
flex-grow: 1;
position: relative;
@@ -194,18 +205,6 @@
gap: 6px;
height: 100%;
- .group-info__edit-description-input {
- flex-grow: 1;
- padding: 6px;
- border-radius: 5px;
- border: 1px solid $mainFontColor;
- background-color: $mainBgColor0;
- font-size: $mainFontSize;
- font-family: $mainFont;
- min-width: 0;
- resize: vertical;
- }
-
button {
background-color: $mainColor-dark0;
color: white;
@@ -222,12 +221,24 @@
}
}
+ &__edit-description-input {
+ flex-grow: 1;
+ padding: 6px;
+ border-radius: 5px;
+ border: 1px solid $mainFontColor;
+ background-color: $mainBgColor0;
+ font-size: $mainFontSize;
+ font-family: $mainFont;
+ min-width: 0;
+ resize: vertical;
+ }
+
&__edit-description-button {
position: absolute;
top: 12px; // Adjust the spacing as needed
right: 12px; // Adjust the spacing as needed
cursor: pointer;
- color: $mainFontColor;
+ color: $profileFontColor;
scale: 0.8;
&:hover {
@@ -251,7 +262,7 @@
button {
background: none;
border: none;
- color: #4b3832;
+ color: $profileFontColor;
font-weight: bold;
font-size: 13px;
cursor: pointer;
@@ -266,19 +277,6 @@
}
}
- &__group-info {
- padding: 20px;
- background: $mainColor-light0;
- box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
- border-radius: 8px;
- color: #4b3832;
- flex-basis: 40%;
-
- &__label {
- font-weight: 800;
- }
- }
-
/* Responsive adjustments */
@media (max-width: 768px) {
&__banner-img {
diff --git a/src/assets/styles/cmps/group-info/_GroupProfileInfoBox.scss b/src/assets/styles/cmps/group-info/_GroupProfileInfoBox.scss
new file mode 100644
index 0000000..af9803a
--- /dev/null
+++ b/src/assets/styles/cmps/group-info/_GroupProfileInfoBox.scss
@@ -0,0 +1,26 @@
+.group-profile {
+ &__group-info {
+ padding: $profileBoxPadding;
+ background: $mainColor-light0;
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
+ border-radius: 8px;
+ flex-basis: 40%;
+
+ &__title {
+ margin-bottom: 12px;
+ }
+
+ &__items {
+ @include flex-column;
+ gap: 20px;
+ }
+
+ &__label {
+ font-weight: 800;
+ }
+
+ &__members {
+ margin-bottom: 10px;
+ }
+ }
+}
diff --git a/src/assets/styles/cmps/popup/show-group-members-popup/_ShowGroupMembersPopup.scss b/src/assets/styles/cmps/popup/show-group-members-popup/_ShowGroupMembersPopup.scss
new file mode 100644
index 0000000..25e51c2
--- /dev/null
+++ b/src/assets/styles/cmps/popup/show-group-members-popup/_ShowGroupMembersPopup.scss
@@ -0,0 +1,51 @@
+.show-group-members-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.5);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 1000;
+
+ &__title {
+ font-size: 1.6rem;
+ margin: 12px;
+ font-weight: 600;
+ font-family: $secondaryFont;
+ }
+
+ &__members-list {
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ width: 100%;
+ padding-inline: 10px;
+ max-height: 60vh;
+ overflow-y: auto;
+ padding: 20px;
+ box-shadow: inset 0px 2px 10px rgba(0, 0, 0, 0.1);
+ margin-top: 10px;
+ border-radius: 8px;
+ background-color: lighten($mainBgColor0, 6%);
+ }
+}
+
+.show-group-members-overlay-container {
+ display: flex;
+ flex-direction: column;
+ padding: 20px;
+ text-align: center;
+ justify-content: center;
+ align-items: center;
+ background: white;
+ border-radius: 10px; /* Slightly more rounded corners */
+ width: 40%; /* Increase the width for more spacious design */
+ max-width: 100%;
+ position: relative;
+ margin-inline: 40px;
+ box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.2); /* Subtle outer shadow for depth */
+ background-color: $mainBgColor0;
+}
diff --git a/src/assets/styles/cmps/popup/show-group-members-popup/_ShowGroupMembersPopupItem.scss b/src/assets/styles/cmps/popup/show-group-members-popup/_ShowGroupMembersPopupItem.scss
new file mode 100644
index 0000000..eaff9c0
--- /dev/null
+++ b/src/assets/styles/cmps/popup/show-group-members-popup/_ShowGroupMembersPopupItem.scss
@@ -0,0 +1,35 @@
+.show-group-members-popup-item {
+ display: flex;
+ gap: 20px;
+ align-items: center;
+ font-size: 1.1rem;
+ font-weight: 300;
+ cursor: pointer;
+ padding: 10px 12px;
+ transition: background-color 0.2s ease;
+
+ &:hover {
+ background-color: darken($grayedOutFontColor, 2%);
+ border-radius: 6px;
+ }
+
+ &__username {
+ cursor: pointer;
+ font-weight: 500;
+ }
+
+ &__role {
+ background-color: $roleNameBgColor;
+ border-radius: 5px;
+ display: inline-block;
+ padding: 4px 12px;
+ flex: 0 0 auto;
+ color: $profileFontColor;
+ margin-left: auto;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ font-size: 0.9rem;
+ font-weight: 500;
+ box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
+ }
+}
diff --git a/src/assets/styles/cmps/profile-picture/_ProfilePicture.scss b/src/assets/styles/cmps/profile-picture/_ProfilePicture.scss
index 3355fa3..fa3e892 100644
--- a/src/assets/styles/cmps/profile-picture/_ProfilePicture.scss
+++ b/src/assets/styles/cmps/profile-picture/_ProfilePicture.scss
@@ -9,4 +9,5 @@
width: 100%;
object-fit: cover;
object-position: center;
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
}
diff --git a/src/assets/styles/cmps/user-profile/_UserProfile.scss b/src/assets/styles/cmps/user-profile/_UserProfile.scss
index bbc686f..c366b57 100644
--- a/src/assets/styles/cmps/user-profile/_UserProfile.scss
+++ b/src/assets/styles/cmps/user-profile/_UserProfile.scss
@@ -11,6 +11,7 @@
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
border-radius: 20px;
overflow: hidden;
+ color: $profileFontColor;
&__header {
position: relative;
@@ -25,11 +26,10 @@
justify-content: center;
align-items: center;
width: 100%;
- cursor: pointer;
- background-color: transparent;
- border-radius: 10px;
border: none;
box-shadow: none;
+ background-color: white;
+ border-radius: 10px;
}
&__banner-img {
@@ -45,6 +45,10 @@
border: none; // Make sure there's no border applied
padding: 0;
margin: 0;
+ }
+
+ &__banner-img.highlightable {
+ cursor: pointer;
&:hover {
opacity: 0.9;
@@ -71,7 +75,7 @@
button {
background: none;
border: none;
- color: #4b3832;
+ color: $profileFontColor;
font-weight: bold;
font-size: 12px;
cursor: pointer;
@@ -88,7 +92,6 @@
width: 120px;
height: 120px;
margin-left: 30px;
- cursor: pointer;
background-color: white;
border-radius: 50%;
}
@@ -106,9 +109,13 @@
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
object-fit: cover;
transition: opacity 0.3s;
+ }
+
+ &__profile-img.highlightable {
+ cursor: pointer;
&:hover {
- opacity: 0.9;
+ opacity: 0.8;
}
}
@@ -130,7 +137,7 @@
button {
background: none;
border: none;
- color: #4b3832;
+ color: $profileFontColor;
font-weight: bold;
font-size: 12px;
cursor: pointer;
@@ -176,12 +183,10 @@
font-size: 32px;
font-weight: bold;
margin: 0;
- color: #4b3832;
}
&__email {
font-size: 18px;
- color: #4b3832;
margin: 5px 0;
}
@@ -204,7 +209,7 @@
&__description-container {
@include flex-column;
- padding: 14px;
+ padding: $profileBoxPadding;
background: $mainColor-light0;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
border-radius: 8px;
@@ -220,18 +225,6 @@
gap: 6px;
height: 100%;
- .user-profile__edit-description-input {
- flex-grow: 1;
- padding: 6px;
- border-radius: 5px;
- border: 1px solid $mainFontColor;
- background-color: $mainBgColor0;
- font-size: $mainFontSize;
- font-family: $mainFont;
- min-width: 0;
- resize: vertical;
- }
-
button {
background-color: $mainColor-dark0;
color: white;
@@ -248,6 +241,18 @@
}
}
+ &__edit-description-input {
+ flex-grow: 1;
+ padding: 6px;
+ border-radius: 5px;
+ border: 1px solid $mainFontColor;
+ background-color: $mainBgColor0;
+ font-size: $mainFontSize;
+ font-family: $mainFont;
+ min-width: 0;
+ resize: vertical;
+ }
+
&__edit-description-button {
position: absolute;
top: 12px; // Adjust the spacing as needed
@@ -277,7 +282,7 @@
button {
background: none;
border: none;
- color: #4b3832;
+ color: $profileFontColor;
font-weight: bold;
font-size: 13px;
cursor: pointer;
@@ -293,11 +298,10 @@
}
&__user-info {
- padding: 20px;
+ padding: $profileBoxPadding;
background: $mainColor-light0;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
border-radius: 8px;
- color: #4b3832;
flex-basis: 40%;
&__label {
@@ -310,7 +314,6 @@
background: $mainColor-light0;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
border-radius: 8px;
- color: #4b3832;
flex-basis: 60%;
width: 100%;
min-width: 100%;
diff --git a/src/assets/styles/main.scss b/src/assets/styles/main.scss
index dccbcaa..22602aa 100644
--- a/src/assets/styles/main.scss
+++ b/src/assets/styles/main.scss
@@ -49,10 +49,13 @@
// * User Profile *
@import "cmps/user-profile/UserProfile";
-// * Group Info *
-@import "cmps/group-info/GroupInfo";
+// * Group Profile *
+@import "cmps/group-info/GroupProfile";
+@import "cmps/group-info/GroupProfileInfoBox";
// * Popup *
+@import "cmps/popup/show-group-members-popup/ShowGroupMembersPopup";
+@import "cmps/popup/show-group-members-popup/ShowGroupMembersPopupItem";
@import "cmps/popup/create-group-popup/CreateGroupPopup";
@import "cmps/popup/add-member-popup/AddMemberPopup";
@import "cmps/popup/remove-member-popup/RemoveMemberPopup";
diff --git a/src/assets/styles/setup/variables.scss b/src/assets/styles/setup/variables.scss
index 34f07d3..67d1be1 100644
--- a/src/assets/styles/setup/variables.scss
+++ b/src/assets/styles/setup/variables.scss
@@ -22,6 +22,7 @@ $errorColor: rgb(117, 26, 26);
// ** Font Colors **
$mainFontColor: black;
$secondaryFontColor: white;
+$profileFontColor: #4b3832;
// ** Background Colors **
$mainBgColor0: peachpuff;
@@ -51,3 +52,6 @@ $loading-icon-color: rgb(6, 68, 36);
// **Form Colors **
$removeColor: rgb(130, 20, 20);
+
+// ** Components Settings **
+$profileBoxPadding: 16px;
diff --git a/src/cmps/global/CustomButton.tsx b/src/cmps/global/CustomButton.tsx
index 4e130bf..229a3d3 100644
--- a/src/cmps/global/CustomButton.tsx
+++ b/src/cmps/global/CustomButton.tsx
@@ -8,7 +8,9 @@ interface BtnProps {
disabled?: boolean;
theme?: "dark" | "light" | "warning";
width?: string;
+ height?: string;
bgColor?: string;
+ fontSize?: string;
}
export default function btn({
@@ -19,7 +21,9 @@ export default function btn({
disabled = false,
theme = "light",
width,
- bgColor
+ height,
+ bgColor,
+ fontSize
}: BtnProps) {
return (
diff --git a/src/cmps/popup/ErrorPopup.tsx b/src/cmps/popup/ErrorPopup.tsx
index ab048b0..dee9dcf 100644
--- a/src/cmps/popup/ErrorPopup.tsx
+++ b/src/cmps/popup/ErrorPopup.tsx
@@ -4,6 +4,7 @@ interface ErrorPopupProps {
message: string;
closeErrorPopup: () => void;
}
+
export default function ErrorPopup({ message, closeErrorPopup }: ErrorPopupProps) {
return (
e.stopPropagation()}>
diff --git a/src/cmps/popup/show-group-members-popup/ShowGroupMembersPopup.tsx b/src/cmps/popup/show-group-members-popup/ShowGroupMembersPopup.tsx
new file mode 100644
index 0000000..0ff1b74
--- /dev/null
+++ b/src/cmps/popup/show-group-members-popup/ShowGroupMembersPopup.tsx
@@ -0,0 +1,36 @@
+import React from "react";
+import CloseButton from "../../global/CloseButton";
+import { GroupMember } from "../../../models/GroupMember.model";
+import ShowGroupMembersPopupItem from "./ShowGroupMembersPopupItem";
+
+interface ShowGroupMembersPopupProps {
+ groupName: string;
+ members: GroupMember[];
+ onClose: () => void;
+}
+
+export default function ShowGroupMembersPopup({
+ groupName,
+ members,
+ onClose
+}: ShowGroupMembersPopupProps) {
+ return (
+
+
e.stopPropagation()}>
+
+
{"Members of " + groupName}
+
+ {members.map((member) => (
+
+ ))}
+
+
+
+ );
+}
diff --git a/src/cmps/popup/show-group-members-popup/ShowGroupMembersPopupItem.tsx b/src/cmps/popup/show-group-members-popup/ShowGroupMembersPopupItem.tsx
new file mode 100644
index 0000000..04ca194
--- /dev/null
+++ b/src/cmps/popup/show-group-members-popup/ShowGroupMembersPopupItem.tsx
@@ -0,0 +1,38 @@
+import React from "react";
+import ProfilePicture from "../../global/ProfilePicture";
+import { useNavigate } from "react-router-dom";
+import defaultProfilePicture from "/imgs/profile/blank-profile-picture.jpg";
+
+interface ShowGroupMembersPopupItemProps {
+ profilePictureUrl: string;
+ userId: string;
+ username: string;
+ roleName: string;
+}
+
+export default function ShowGroupMembersPopupItem({
+ profilePictureUrl,
+ userId,
+ username,
+ roleName
+}: ShowGroupMembersPopupItemProps) {
+ const navigate = useNavigate();
+
+ const navigateToUserProfile = () => {
+ navigate(`/${userId}`);
+ };
+
+ return (
+
+
+ {username}
+ {roleName != "Member" && (
+ {roleName}
+ )}
+
+ );
+}
diff --git a/src/cmps/profile/GroupProfile.tsx b/src/cmps/profile/group/GroupProfile.tsx
similarity index 78%
rename from src/cmps/profile/GroupProfile.tsx
rename to src/cmps/profile/group/GroupProfile.tsx
index 348d817..5677ca9 100644
--- a/src/cmps/profile/GroupProfile.tsx
+++ b/src/cmps/profile/group/GroupProfile.tsx
@@ -1,29 +1,30 @@
import React, { ChangeEvent, useEffect, useState } from "react";
-import LoadingAnimation from "../global/LoadingAnimation";
-import CustomButton from "../global/CustomButton";
+import LoadingAnimation from "../../global/LoadingAnimation";
+import CustomButton from "../../global/CustomButton";
import { useNavigate, useParams } from "react-router-dom";
import {
deleteGroupById,
fetchGroupData,
removeMemberFromGroup,
saveGroupDescription
-} from "../../services/group.service";
-import { GroupData } from "../../models/GroupData.model";
-import { getTimePassed } from "../../services/poll.service";
-import ContentPageMessage from "../content-page/messege/ContentPageMessage";
-import { useGroups } from "../../context/GroupsContext";
-import AddMemberPopup from "../popup/AddMemberPopup";
-import RemoveMemberPopup from "../popup/RemoveMemberPopup";
-import ModifyRolesPopup from "../popup/ModifyRolesPopup";
-import { useMembers } from "../../context/MemebersContext";
-import VerifyPopup from "../popup/VerifyPopup";
-import { UserRoleName } from "../../models/enum/UserRoleName.enum";
-import { fetchUserData } from "../../services/user.profile.service";
+} from "../../../services/group.service";
+import { GroupData } from "../../../models/GroupData.model";
+import { getTimePassed } from "../../../services/poll.service";
+import ContentPageMessage from "../../content-page/messege/ContentPageMessage";
+import { useGroups } from "../../../context/GroupsContext";
+import AddMemberPopup from "../../popup/AddMemberPopup";
+import RemoveMemberPopup from "../../popup/RemoveMemberPopup";
+import ModifyRolesPopup from "../../popup/ModifyRolesPopup";
+import { useMembers } from "../../../context/MemebersContext";
+import VerifyPopup from "../../popup/VerifyPopup";
+import { UserRoleName } from "../../../models/enum/UserRoleName.enum";
+import { fetchUserData } from "../../../services/user.profile.service";
import defaultProfilePictureUrl from "/imgs/profile/blank-group-profile-picture.jpg";
import defaultProfileBannerUrl from "/imgs/profile/blank-profile-banner.jpg";
-import { fetchPicture, uploadGroupProfileImage } from "../../services/media.service";
-import { useUser } from "../../context/UserContext";
+import { uploadGroupProfileImage } from "../../../services/media.service";
+import { useUser } from "../../../context/UserContext";
import EditDescriptionIcon from "@mui/icons-material/MoreVert";
+import GroupProfileInfoBox from "./GroupProfileInfoBox";
export default function GroupInfo() {
const navigate = useNavigate();
@@ -48,10 +49,6 @@ export default function GroupInfo() {
const [isProfileBannerMenuVisible, setIsProfileBannerMenuVisible] = useState
(false);
const [isEditDescriptionMenuVisible, setIsEditDescriptionMenuVisible] = useState(false);
- const [canSetPictures, setCanSetPictures] = useState(false);
- const [profileImageSrc, setProfileImageSrc] = useState(defaultProfilePictureUrl);
- const [bannerImageSrc, setBannerImageSrc] = useState(defaultProfileBannerUrl);
-
const [isUserHasPermissionToAddMember, setIsUserHasPermissionToAddMember] =
useState(false);
const [isUserHasPermissionToRmvMember, setIsUserHasPermissionToRmvMember] =
@@ -60,7 +57,7 @@ export default function GroupInfo() {
useState(false);
const [isUserHasPermissionToModRoles, setIsUserHasPermissionToModRoles] =
useState(false);
- const [isUserHasPermissionToEditDescription, setIsUserHasPermissionToEditDescription] =
+ const [isUserHasPermissionToEditGroupProfile, setIsUserHasPermissionToEditGroupProfile] =
useState(false);
const [timePassed, setTimePassed] = useState();
@@ -88,7 +85,6 @@ export default function GroupInfo() {
console.log("Fetched group data for group with ID: ", groupId, data);
setGroupData(data);
setDescriptionText(data.description || defaultDescription);
- setCanSetPictures(true);
setIsLoading(false);
})
.catch((error) => {
@@ -113,30 +109,6 @@ export default function GroupInfo() {
fetchUserPermissionsInCommandBar();
}, [members]);
- useEffect(() => {
- if (canSetPictures) {
- fetchPicture(groupData?.profilePictureUrl)
- .then((data) => {
- console.log("Fetched group's profile picture");
- setProfileImageSrc(data ?? defaultProfilePictureUrl);
- })
- .catch((error) => {
- console.log("Unable to fetch group's profile picture");
- });
-
- fetchPicture(groupData?.profileBannerUrl)
- .then((data) => {
- console.log("Fetched group's bannner picture");
- setBannerImageSrc(data ?? defaultProfileBannerUrl);
- })
- .catch((error) => {
- console.log("Unable to fetch group's banner picture");
- });
-
- setCanSetPictures(false);
- }
- }, [canSetPictures]);
-
const fetchUserPermissionsInCommandBar = () => {
console.log("Fetching user permissions in group");
const userRole = getMemberRole(userId);
@@ -146,13 +118,13 @@ export default function GroupInfo() {
setIsUserHasPermissionToRmvMember(true);
setIsUserHasPermissionToRmvGroup(true);
setIsUserHasPermissionToModRoles(true);
- setIsUserHasPermissionToEditDescription(true);
+ setIsUserHasPermissionToEditGroupProfile(true);
} else if (userRole === UserRoleName.MODERATOR) {
setIsUserHasPermissionToAddMember(true);
setIsUserHasPermissionToRmvMember(true);
setIsUserHasPermissionToRmvGroup(false);
setIsUserHasPermissionToModRoles(false);
- setIsUserHasPermissionToEditDescription(false);
+ setIsUserHasPermissionToEditGroupProfile(false);
}
};
@@ -203,7 +175,6 @@ export default function GroupInfo() {
(prevGroupData) =>
prevGroupData && { ...prevGroupData, profilePictureUrl: response.imageUrl }
);
- setCanSetPictures(true);
} catch (error) {
console.error("Failed to upload group profile picture: ", error);
}
@@ -219,7 +190,6 @@ export default function GroupInfo() {
(prevGroupData) =>
prevGroupData && { ...prevGroupData, profileBannerUrl: response.imageUrl }
);
- setCanSetPictures(true);
} catch (error) {
console.error("Failed to upload group profile banner: ", error);
}
@@ -316,10 +286,10 @@ export default function GroupInfo() {
}
return (
-
-
+
+
-
+
{isProfileBannerMenuVisible && (
-
+
-
+
-
+
{isProfilePictureMenuVisible && (
-
+
-
-
{groupData.groupName}
+
+
{groupData.groupName}
-
+
-
+
{isUserHasPermissionToAddMember && (
setIsDeleteVerifyPopupOpen(false)}
/>
)}
-
-
- {isUserHasPermissionToEditDescription && (
+
+
+ {isUserHasPermissionToEditGroupProfile && (
)}
{isEditDescriptionMenuVisible && (
-
+
)}
Description:
{isEditingDescription ? (
-
+
@@ -501,12 +483,13 @@ export default function GroupInfo() {
{descriptionText}
)}
-
-
Info:
-
-
Created:
- {timePassed}
-
Group ID:
{groupData?.groupId}
+
+
diff --git a/src/cmps/profile/group/GroupProfileInfoBox.tsx b/src/cmps/profile/group/GroupProfileInfoBox.tsx
new file mode 100644
index 0000000..286a0ec
--- /dev/null
+++ b/src/cmps/profile/group/GroupProfileInfoBox.tsx
@@ -0,0 +1,70 @@
+import React, { useState } from "react";
+import { GroupMember } from "../../../models/GroupMember.model";
+import CustomButton from "../../global/CustomButton";
+import ShowGroupMembersPopup from "../../popup/show-group-members-popup/ShowGroupMembersPopup";
+
+interface GroupProfileInfoBoxProps {
+ groupId: string;
+ groupName: string;
+ timePassed?: string;
+ members?: GroupMember[];
+}
+
+export default function GroupProfileInfoBox({
+ groupId,
+ groupName,
+ timePassed,
+ members
+}: GroupProfileInfoBoxProps) {
+ const [isMembersPopupVisible, setIsMembersPopupVisible] = useState(false);
+
+ const handleShowMembersClick = () => {
+ setIsMembersPopupVisible(true);
+ };
+ const handleCloseMembersPopupClick = () => {
+ setIsMembersPopupVisible(false);
+ };
+
+ return (
+
+
Info:
+
+ {timePassed && (
+
+
Created:
+
{timePassed}
+
+ )}
+ {groupId && (
+
+
Group ID:
+
{groupId}
+
+ )}
+ {members && (
+
+
Group Members:
+
+ {"There are " + members.length + " group members in the group."}
+
+
+ Show Group Members
+
+ {isMembersPopupVisible && (
+
+ )}
+
+ )}
+
+
+ );
+}
diff --git a/src/cmps/profile/UserProfile.tsx b/src/cmps/profile/user/UserProfile.tsx
similarity index 84%
rename from src/cmps/profile/UserProfile.tsx
rename to src/cmps/profile/user/UserProfile.tsx
index 8747f03..2dafb4a 100644
--- a/src/cmps/profile/UserProfile.tsx
+++ b/src/cmps/profile/user/UserProfile.tsx
@@ -1,22 +1,22 @@
import React, { ChangeEvent, useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
-import { UserData } from "../../models/UserData.model";
+import { UserData } from "../../../models/UserData.model";
import {
capitalizeWords,
fetchUserData,
saveUserDescription
-} from "../../services/user.profile.service";
-import LoadingAnimation from "../global/LoadingAnimation";
-import { getTimePassed } from "../../services/poll.service";
-import ContentPageMessage from "../content-page/messege/ContentPageMessage";
-import { fetchPicture, uploadUserProfileImage } from "../../services/media.service";
+} from "../../../services/user.profile.service";
+import LoadingAnimation from "../../global/LoadingAnimation";
+import { getTimePassed } from "../../../services/poll.service";
+import ContentPageMessage from "../../content-page/messege/ContentPageMessage";
+import { uploadUserProfileImage } from "../../../services/media.service";
import defaultProfilePictureUrl from "/imgs/profile/blank-profile-picture.jpg";
import defaultProfileBannerUrl from "/imgs/profile/blank-profile-banner.jpg";
-import ProfilePicture from "../global/ProfilePicture";
-import { fetchUserGroups } from "../../services/group.service";
-import { GroupData } from "../../models/GroupData.model";
+import ProfilePicture from "../../global/ProfilePicture";
+import { fetchUserGroups } from "../../../services/group.service";
+import { GroupData } from "../../../models/GroupData.model";
import EditDescriptionIcon from "@mui/icons-material/MoreVert";
-import { useUser } from "../../context/UserContext";
+import { useUser } from "../../../context/UserContext";
export default function UserProfile() {
const { userId } = useParams();
@@ -30,9 +30,6 @@ export default function UserProfile() {
const [isProfilePictureMenuVisible, setIsProfilePictureMenuVisible] = useState
(false);
const [isProfileBannerMenuVisible, setIsProfileBannerMenuVisible] = useState(false);
- const [canSetPictures, setCanSetPictures] = useState(false);
- const [profileImageSrc, setProfileImageSrc] = useState(defaultProfilePictureUrl);
- const [bannerImageSrc, setBannerImageSrc] = useState(defaultProfileBannerUrl);
const { user } = useUser();
const navigate = useNavigate();
@@ -45,7 +42,7 @@ export default function UserProfile() {
const resetUserDescriptionText = () =>
setDescriptionText(userData ? userData.description || defaultDescription : defaultDescription);
- const isProfileOfLoggedInUser = () => loggedInUser?.userId === userId;
+ const isProfileOfLoggedInUser = loggedInUser?.userId === userId;
useEffect(() => {
setIsLoading(true);
@@ -59,7 +56,6 @@ export default function UserProfile() {
console.log("Fetched user data for user with ID: ", userId, data);
setUserData(data);
setDescriptionText(data.description || defaultDescription);
- setCanSetPictures(true);
setIsLoading(false);
})
.catch((error) => {
@@ -79,30 +75,6 @@ export default function UserProfile() {
});
}, [userId]);
- useEffect(() => {
- if (canSetPictures) {
- fetchPicture(userData?.profilePictureUrl)
- .then((data) => {
- console.log("Fetched user's profile picture");
- setProfileImageSrc(data ?? defaultProfilePictureUrl);
- })
- .catch((error) => {
- console.log("Unable to fetch user's profile picture");
- });
-
- fetchPicture(userData?.profileBannerUrl)
- .then((data) => {
- console.log("Fetched user's bannner picture");
- setBannerImageSrc(data ?? defaultProfileBannerUrl);
- })
- .catch((error) => {
- console.log("Unable to fetch user's banner picture");
- });
-
- setCanSetPictures(false);
- }
- }, [canSetPictures]);
-
const handleProfileImageUpload = async (event: ChangeEvent) => {
console.log("User profile picture was added, uploading...");
const file = event.target.files?.[0];
@@ -122,7 +94,6 @@ export default function UserProfile() {
(prevUserData) =>
prevUserData && { ...prevUserData, profilePictureUrl: response.imageUrl }
);
- setCanSetPictures(true);
} catch (error) {
console.error("Failed to upload user profile picture: ", error);
}
@@ -138,7 +109,6 @@ export default function UserProfile() {
(prevUserData) =>
prevUserData && { ...prevUserData, profileBannerUrl: response.imageUrl }
);
- setCanSetPictures(true);
} catch (error) {
console.error("Failed to upload user profile banner: ", error);
}
@@ -219,7 +189,13 @@ export default function UserProfile() {
-
+
{isProfileBannerMenuVisible && (
@@ -245,7 +221,13 @@ export default function UserProfile() {
onClick={toggleProfilePictureMenu}
>
-
+
{isProfilePictureMenuVisible && (
@@ -276,7 +258,7 @@ export default function UserProfile() {
- {isProfileOfLoggedInUser() && (
+ {isProfileOfLoggedInUser && (
(true);
const { groupId } = useParams();
const { members, setMembers, sortMembers } = useMembers();
- const [isShowingAllGroups, setIsShowingAllGroups] = useState(true);
+ const [isShowingFriendsList, setIsShowingFriendsList] = useState(true);
const { registerForUpdate } = useUpdateContext(); // Access context
const { userId } = useParams();
+ const location = useLocation();
const cmpName = "MEMBERS_SIDEBAR ";
// Initial fetch on component render
useEffect(() => {
updateMembers();
- }, [groupId, userId]);
+ }, [groupId, userId, location.pathname]);
const updateMembers = useCallback(async () => {
- if (groupId && !userId) {
+ const isInFeedPage = location.pathname.startsWith("/feed");
+ const isInGroupPage = location.pathname.startsWith("/group");
+
+ if (isInFeedPage && groupId && !userId) {
+ // On specific group feed page
setIsLoading(true);
- setIsShowingAllGroups(false);
+ setIsShowingFriendsList(false);
try {
const fetchedMembers = await fetchGroupMembers(groupId);
console.log("Fetched members: " + fetchedMembers[0].userData);
@@ -35,13 +40,20 @@ export default function MembersSidebar() {
console.error(cmpName + error);
setIsLoading(false);
}
- } else {
- if (!userId) {
- setIsShowingAllGroups(true);
- setMembers([]);
- }
+ } else if (!isInFeedPage && !groupId && userId) {
+ // On user profile page
+ setIsShowingFriendsList(true);
+ setMembers(undefined);
+ } else if (isInGroupPage) {
+ // On group profile page
+ setIsShowingFriendsList(true);
+ setMembers(undefined);
+ } else if (isInFeedPage) {
+ // On all groups feed page
+ setIsShowingFriendsList(true);
+ setMembers(undefined);
}
- }, [groupId, userId]);
+ }, [groupId, userId, location.pathname]);
useEffect(() => {
// Register the updateMembers function and handle unregistration
@@ -59,11 +71,11 @@ export default function MembersSidebar() {
return (
-
- {!isShowingAllGroups && "Group Members:"}
+
+ {!isShowingFriendsList && "Group Members:"}
- {isLoading && !isShowingAllGroups && (
+ {isLoading && !isShowingFriendsList && (
)}
{!isLoading &&
diff --git a/src/pages/ContentPage.tsx b/src/pages/ContentPage.tsx
index ceace97..e400a40 100644
--- a/src/pages/ContentPage.tsx
+++ b/src/pages/ContentPage.tsx
@@ -3,8 +3,8 @@ import AppHeader from "../cmps/app-header/AppHeader";
import GroupsSidebar from "../cmps/sidebar/GroupsSidebar";
import Feed from "../cmps/feed/FeedContent";
import MembersSidebar from "../cmps/sidebar/MembersSidebar";
-import UserProfile from "../cmps/profile/UserProfile";
-import GroupInfo from "../cmps/profile/GroupProfile";
+import UserProfile from "../cmps/profile/user/UserProfile";
+import GroupInfo from "../cmps/profile/group/GroupProfile";
import { fetchUserData } from "../services/user.profile.service";
import { UserData } from "../models/UserData.model";
import LoadingAnimation from "../cmps/global/LoadingAnimation";
diff --git a/src/services/media.service.ts b/src/services/media.service.ts
index d8cdd82..0992497 100644
--- a/src/services/media.service.ts
+++ b/src/services/media.service.ts
@@ -98,19 +98,3 @@ export async function uploadGroupProfileImage(
throw throwAxiosErr(err);
}
}
-
-export async function fetchPicture(pictureUrl: string | undefined) : Promise {
- console.log(cmpName, "Sending request to receive picture url: " + pictureUrl);
- if(pictureUrl){
- try{
- const response = await axios.get(pictureUrl, {
- responseType: "blob",
- });
-
- return URL.createObjectURL(response.data);
- } catch (err) {
- console.error(cmpName, "Error getting the picture: " + pictureUrl + " Error: " + err);
- throwAxiosErr(err);
- }
- }
-}