From 49011c09162317639bdbd249405c9df2ff8589a7 Mon Sep 17 00:00:00 2001 From: Linh Nguyen <78007881+linhnnk@users.noreply.github.com> Date: Mon, 25 Mar 2024 21:14:04 -0700 Subject: [PATCH] feat(profile): Add other user's profile detail in appointment (#722) --- app/web/__tests__/ProfileDetail.test.tsx | 2 +- .../ProfilePicture.test.tsx.snap | 4 +- app/web/src/app/actions.ts | 15 ++ app/web/src/app/profile/[withUser]/page.tsx | 40 +++++ app/web/src/app/{user => }/profile/page.tsx | 8 +- .../inbox/ConversationDropdownMenu.tsx | 2 +- .../appointment/inbox/ConversationList.tsx | 5 +- .../appointment/inbox/ConversationViewer.tsx | 6 +- .../src/components/layout/ProfilePicture.tsx | 2 +- .../profile/OtherUserProfileDetails.tsx | 163 ++++++++++++++++++ .../{user => profile}/ProfileDetails.tsx | 4 +- 11 files changed, 235 insertions(+), 16 deletions(-) create mode 100644 app/web/src/app/profile/[withUser]/page.tsx rename app/web/src/app/{user => }/profile/page.tsx (84%) create mode 100644 app/web/src/components/profile/OtherUserProfileDetails.tsx rename app/web/src/components/{user => profile}/ProfileDetails.tsx (95%) diff --git a/app/web/__tests__/ProfileDetail.test.tsx b/app/web/__tests__/ProfileDetail.test.tsx index 9d110744..bb88864c 100644 --- a/app/web/__tests__/ProfileDetail.test.tsx +++ b/app/web/__tests__/ProfileDetail.test.tsx @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { ProfileDetails } from "@components/profile/ProfileDetails"; import "@testing-library/jest-dom"; -import { ProfileDetails } from "@components/user/ProfileDetails"; import { render, screen } from "@testing-library/react"; import { User } from "next-auth"; diff --git a/app/web/__tests__/__snapshots__/ProfilePicture.test.tsx.snap b/app/web/__tests__/__snapshots__/ProfilePicture.test.tsx.snap index efe73e68..58ee3279 100644 --- a/app/web/__tests__/__snapshots__/ProfilePicture.test.tsx.snap +++ b/app/web/__tests__/__snapshots__/ProfilePicture.test.tsx.snap @@ -6,7 +6,7 @@ exports[`ProfilePicture matches snapshot 1`] = ` "baseElement":
, "container":
{ + try { + const users = await getUsrList("username", username); + if (users && users.length > 0) { + return users[0]; + } + return null; + } catch (error) { + console.error("Error fetching user by username:", error); + return null; + } +} + export async function getUserAppointments(user: User) { const appointments = await db.appointment.findMany({ where: { diff --git a/app/web/src/app/profile/[withUser]/page.tsx b/app/web/src/app/profile/[withUser]/page.tsx new file mode 100644 index 00000000..270d4755 --- /dev/null +++ b/app/web/src/app/profile/[withUser]/page.tsx @@ -0,0 +1,40 @@ +/* + * Copyright [2023] [Privacypal Authors] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { OtherUserProfileDetails } from "@components/profile/OtherUserProfileDetails"; +import React from "react"; +import { auth } from "src/auth"; +import { Metadata } from "next"; + +export const metadata: Metadata = { + title: "Other User Profile Detail", +}; + +export default async function OtherUserProfilePage({ + params, +}: { + params: { withUser: string }; +}) { + const session = await auth(); + if (!session) { + return
Not logged in
; + } + return ( +
+ +
+ ); +} diff --git a/app/web/src/app/user/profile/page.tsx b/app/web/src/app/profile/page.tsx similarity index 84% rename from app/web/src/app/user/profile/page.tsx rename to app/web/src/app/profile/page.tsx index cfc49024..1e9e9f8e 100644 --- a/app/web/src/app/user/profile/page.tsx +++ b/app/web/src/app/profile/page.tsx @@ -14,9 +14,13 @@ * limitations under the License. */ import Content from "@components/layout/Content"; -import { ProfileDetails } from "@components/user/ProfileDetails"; -import UserUpdateForm from "@components/user/UserUpdateForm"; +import { ProfileDetails } from "@components/profile/ProfileDetails"; import { auth } from "src/auth"; +import { Metadata } from "next"; + +export const metadata: Metadata = { + title: "Profile Detail", +}; export default async function UserDashboardPage() { const session = await auth(); diff --git a/app/web/src/components/appointment/inbox/ConversationDropdownMenu.tsx b/app/web/src/components/appointment/inbox/ConversationDropdownMenu.tsx index 71c865f7..1779c5e8 100644 --- a/app/web/src/components/appointment/inbox/ConversationDropdownMenu.tsx +++ b/app/web/src/components/appointment/inbox/ConversationDropdownMenu.tsx @@ -70,7 +70,7 @@ export const ConversationDropdownMenu = () => { Homepage - + Profile diff --git a/app/web/src/components/appointment/inbox/ConversationList.tsx b/app/web/src/components/appointment/inbox/ConversationList.tsx index 18e47bbe..19ceb173 100644 --- a/app/web/src/components/appointment/inbox/ConversationList.tsx +++ b/app/web/src/components/appointment/inbox/ConversationList.tsx @@ -99,7 +99,7 @@ const userMetaStyle: CSS = { }; const profileLinkStyle: CSS = { - fontSize: "0.75rem", + fontSize: "1rem", }; interface ConversationListProps { @@ -166,8 +166,7 @@ export const ConversationList = ({ {user.email}
- {/* TODO: possibly remove this link (do users have profiles?) */} - + View Profile diff --git a/app/web/src/components/appointment/inbox/ConversationViewer.tsx b/app/web/src/components/appointment/inbox/ConversationViewer.tsx index bcb1638a..afa6a364 100644 --- a/app/web/src/components/appointment/inbox/ConversationViewer.tsx +++ b/app/web/src/components/appointment/inbox/ConversationViewer.tsx @@ -14,13 +14,13 @@ * limitations under the License. */ "use client"; - import { Panel, PanelHeader, PanelMain, Title } from "@patternfly/react-core"; import { InboxAvatar } from "./InboxAvatar"; import pfAvatar from "@assets/pf_avatar.svg"; import { CSS } from "@lib/utils"; import { User } from "next-auth"; import { CognitoUser } from "@lib/cognito"; +import Link from "next/link"; const panelStyle: CSS = { display: "flex", @@ -86,7 +86,6 @@ interface ConversationViewerProps { withUser: CognitoUser | undefined; children?: React.ReactNode; } - export const ConversationViewer = ({ withUser, children, @@ -94,7 +93,7 @@ export const ConversationViewer = ({ const headerText = withUser ? withUser.firstName + " " + withUser.lastName : "No appointment selected."; - + const profilepage = `/profile/${withUser?.username}`; return ( @@ -107,6 +106,7 @@ export const ConversationViewer = ({ {withUser.email} ) : null}
+ {withUser && View profile} {children} diff --git a/app/web/src/components/layout/ProfilePicture.tsx b/app/web/src/components/layout/ProfilePicture.tsx index 8def5eef..b3fac34a 100644 --- a/app/web/src/components/layout/ProfilePicture.tsx +++ b/app/web/src/components/layout/ProfilePicture.tsx @@ -66,7 +66,7 @@ export default function ProfilePicture({ // link to dashboard in place of user profile const avatar = ( diff --git a/app/web/src/components/profile/OtherUserProfileDetails.tsx b/app/web/src/components/profile/OtherUserProfileDetails.tsx new file mode 100644 index 00000000..16452764 --- /dev/null +++ b/app/web/src/components/profile/OtherUserProfileDetails.tsx @@ -0,0 +1,163 @@ +/* + * Copyright [2023] [Privacypal Authors] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +"use client"; +import React, { useEffect, useState } from "react"; +import { + Card, + CardTitle, + CardBody, + CardHeader, + Flex, + Title, + FlexItem, + Divider, + CardFooter, + Alert, +} from "@patternfly/react-core"; +import { User } from "next-auth"; +import { UserRole } from "@lib/userRole"; +import { CognitoUser } from "@lib/cognito"; +import { getUserByUsername } from "@app/actions"; +import { CSS } from "@lib/utils"; + +const cardContainer: CSS = { + display: "flex", + justifyContent: "center", + filter: "drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25))", +}; + +const cardStyle: CSS = { + width: "25%", +}; + +interface ProfileDetailsProps { + user: User; + withUser: string; +} + +export const OtherUserProfileDetails = ({ + user, + withUser, +}: ProfileDetailsProps) => { + const [userDetails, setUserDetails] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const fetchUserDetails = async () => { + try { + const user = await getUserByUsername(withUser); + if (user) { + setUserDetails(user); + setLoading(false); + } else { + setLoading(false); + setError("User details not found"); + } + } catch (error) { + console.error("Error fetching user details:", error); + setLoading(false); + setError("Error fetching user details"); + } + }; + + fetchUserDetails(); + }, [withUser]); + + if (loading) { + return
Loading...
; + } + + if (error) { + return ( + + ); + } + + if (!userDetails) { + return ( + + ); + } + + const withUserRole = + user.role === UserRole.PROFESSIONAL + ? UserRole.CLIENT + : UserRole.PROFESSIONAL; + + return ( +
+ + + + Professional's Information + + + + + + + + + + Username: + {userDetails.username} + + + + Email: + {userDetails.email} + + + + Full Name: + + {userDetails.firstName} {userDetails.lastName} + + + + Role: + {withUserRole} + + + + + + {/* */} + + + + +
+ ); +}; diff --git a/app/web/src/components/user/ProfileDetails.tsx b/app/web/src/components/profile/ProfileDetails.tsx similarity index 95% rename from app/web/src/components/user/ProfileDetails.tsx rename to app/web/src/components/profile/ProfileDetails.tsx index 43fa3cf0..f4e7a876 100644 --- a/app/web/src/components/user/ProfileDetails.tsx +++ b/app/web/src/components/profile/ProfileDetails.tsx @@ -28,8 +28,6 @@ import { import ProfilePicture from "@components/layout/ProfilePicture"; import { User } from "next-auth"; import Link from "next/link"; -import { UserRole } from "@lib/userRole"; -import { CognitoUser } from "@lib/cognito"; interface ProfileDetailsProps { user: User; } @@ -48,7 +46,7 @@ export const ProfileDetails = ({ user }: ProfileDetailsProps) => {