mohammed-ahad

profile

Sep 27th, 2023
16
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.78 KB | None | 0 0
  1. import React, { useEffect, useState } from "react";
  2. import { Link, useParams } from "react-router-dom";
  3. import Page from "../../components/Page";
  4. import Avatar from "../../components/Nav/components/Avatar";
  5. import HobbyIcon from "../../components/HobbyIcon";
  6. import { UseQueryResult, useQuery } from "react-query";
  7. import { getUser } from "../../utils/getUser";
  8. import { UserI } from "../../types";
  9. import { camelCase } from "lodash";
  10. import { ApolloError, useLazyQuery } from '@apollo/client'
  11. import { STAFF_QUERY, StaffData } from '../../gql/staffQuery'
  12. import Skeleton from 'react-loading-skeleton'
  13. import 'react-loading-skeleton/dist/skeleton.css'
  14. import { getPeoplePhotoUrl } from '../../common/peoplePhoto'
  15. import Channel from '../../components/Channel';
  16. import { useNavigate } from 'react-router-dom';
  17. import { BsMicrosoftTeams, BsSlack } from 'react-icons/bs';
  18. import { MdEmail } from 'react-icons/md';
  19. import { useUser } from "../../utils/userContext";
  20.  
  21. function useProfileStaffData() {
  22. const { id } = useParams();
  23. const azureUserData = useUser().userData;
  24. const [lastUserID, setLastUserID] = useState<string | undefined>(undefined);
  25. const [graphQLError, setGraphQLError] = useState<ApolloError | null>(null);
  26. const [graphQLData, setGraphQLData] = useState<StaffData | null>(null);
  27. const [graphQLLoading, setGraphQLLoading] = useState(true);
  28. const [
  29. fetchStaffData,
  30. { called, loading: queryLoading, error: queryError, data: queryData },
  31. ] = useLazyQuery<StaffData>(STAFF_QUERY, {
  32. onCompleted: (data) => {
  33. setGraphQLData(data);
  34. setGraphQLLoading(false);
  35. setGraphQLError(null);
  36. },
  37. onError: (error) => {
  38. setGraphQLData(null);
  39. setGraphQLLoading(false);
  40. setGraphQLError(error);
  41. },
  42. });
  43.  
  44. useEffect(() => {
  45. // Check if azureUserData has data and is not in the loading state
  46. if (
  47. azureUserData && id &&
  48. (graphQLLoading || id !== lastUserID)
  49. ) {
  50. let staffName: string | null = null;
  51. let staffId: number | null = null;
  52.  
  53. setLastUserID(id);
  54.  
  55. // Check if the paramData.id is "me" or a number
  56. if (id === "me") {
  57. // If the paramData.id is "me" or a number, then set the staffName variable
  58. staffName = `${azureUserData.givenName} ${azureUserData.surname}`;
  59. } else {
  60. // If the paramData.id is "me" or a number, then set the staffId variable
  61. staffId = parseInt(id === undefined ? "" : id);
  62. }
  63.  
  64. // Call the fetchStaffData function (trigger the query)
  65. fetchStaffData({
  66. variables: {
  67. staffId,
  68. staffName,
  69. },
  70. });
  71. }
  72. }, [azureUserData, fetchStaffData, graphQLLoading, id, lastUserID]);
  73.  
  74. return { loading: queryLoading, error: graphQLError, data: graphQLData };
  75. }
  76.  
  77. const Profile = () => {
  78. const { id } = useParams();
  79. const navigate = useNavigate();
  80. const { loading, error, data } = useProfileStaffData();
  81.  
  82. const staff = data?.staff;
  83.  
  84. return (
  85. <Page>
  86. <div className="text-text-primary font-bold text-xl">Profile</div>
  87. <div className="flex flex-row gap-5 items-center">
  88. {loading || !staff ? (
  89. <Skeleton width={150} height={150} circle />
  90. ) : (
  91. <Avatar
  92. avatar={getPeoplePhotoUrl(staff?.image, true) as Blob}
  93. loading={loading}
  94. size={150}
  95. user={staff}
  96. userLoading={loading}
  97. grayed={false}
  98. />
  99. )}
  100. <div className="flex flex-col gap-3">
  101. {loading ? (
  102. <Skeleton width={200} height={30} />
  103. ) : (
  104. <h1 className="text-3xl font-bold text-text-primary">
  105. {staff?.name}
  106. </h1>
  107. )}
  108. {loading ? (
  109. <Skeleton width={160} height={15} />
  110. ) : (
  111. <p className="text-text-primary">{staff?.role}</p>
  112. )}
  113. </div>
  114. <div className="flex-grow">
  115. {/* Empty div to make the "About" text align to the end */}
  116. </div>
  117. {
  118. (id === "me") ?
  119. (
  120. <div>
  121. <Link to="/edit-profile">
  122. <button className="bg-sky-orange text-white py-2 px-4 rounded-md transition-all hover:bg-sky-orange-dark">
  123. Edit Profile
  124. </button>
  125. </Link>
  126. </div>
  127. ) : (
  128. <>
  129. <a href={`https://teams.microsoft.com/l/chat/0/0?users=${staff?.email}`}>
  130. <div className="border flex flex-row items-center gap-x-2 text-text-primary border-text-primary py-3 px-8 rounded-md justify-end transition-all hover:border-purple-500 hover:bg-purple-500 hover:text-white">
  131. <BsMicrosoftTeams />
  132. <p className="">Teams</p>
  133. </div>
  134. </a>
  135. <a href={`mailto:${staff?.email}`} >
  136. <div className="border flex flex-row items-center gap-x-2 text-text-primary border-text-primary py-3 px-8 rounded-md justify-end transition-all hover:border-blue-500 hover:bg-blue-500 hover:text-white">
  137. <MdEmail />
  138. <div>
  139. <p className="">Email</p>
  140. </div>
  141. </div>
  142. </a>
  143. </>
  144. )
  145. }
  146. </div>
  147. <div className=" grid grid-cols-3">
  148. <div id="hobbies">
  149. <h2 className="text-text-primary text-lg font-bold">Hobbies</h2>
  150. {loading ? (
  151. <Skeleton width={160} height={35} />
  152. ) : (
  153. <div className="flex flex-row gap-1">
  154. {staff?.hobbies.map((hobby) => (
  155. <HobbyIcon key={hobby.icon} hobby={hobby.icon} />
  156. ))}
  157. </div>
  158. )}
  159. </div>
  160. <div id="technology">
  161. <h2 className="text-text-primary text-lg font-bold">
  162. Favourite Technology
  163. </h2>
  164. <p className=" text-sky-orange">{staff?.technology}</p>
  165. </div>
  166. {
  167. (staff?.initiatives !== undefined && staff?.initiatives.length > 0)? (
  168. <div id="initiatives">
  169. <h2 className="text-text-primary text-lg font-bold">Initiatives</h2>
  170. {staff?.initiatives.map((initiative) => (
  171. <p key={initiative.name} className="text-sky-orange">
  172. {initiative.name}
  173. </p>
  174. ))}
  175. </div>
  176. ) : (
  177. <div/>
  178. )
  179. }
  180. </div>
  181. <div>
  182. <h2 className="text-text-primary text-lg font-bold">Manager</h2>
  183. {loading || staff?.manager != null ? (
  184. <button
  185. onClick={() => {
  186. navigate(`/profile/${staff?.manager.id}`);
  187. }}
  188. className="flex flex-row gap-5 items-center mt-3"
  189. >
  190. {loading || !staff ? (
  191. <Skeleton width={150} height={150} circle />
  192. ) : (
  193. <Avatar
  194. avatar={getPeoplePhotoUrl(staff?.manager.image, true) as Blob}
  195. loading={loading}
  196. size={90}
  197. user={staff}
  198. userLoading={loading}
  199. grayed={false}
  200. />
  201. )}
  202. <div className="flex flex-col gap-3">
  203. <h1 className="text-lg font-bold text-text-primary text-left">
  204. {staff?.manager.name}
  205. </h1>
  206. <p className="text-text-primary text-left">
  207. {staff?.manager.role}
  208. </p>
  209. </div>
  210. </button>
  211. ) : (
  212. <div className="flex flex-row gap-5 items-center mt-3">
  213. <p className="text-text-primary">
  214. {staff?.name} does not have a manager
  215. </p>
  216. </div>
  217. )}
  218. </div>
  219. <div>
  220. <h2 className="text-text-primary text-lg font-bold">Team</h2>
  221. <Link to={`/teams/${camelCase(staff?.team.title)}/${staff?.team.id}`} className=" bg-neutral-dimmed w-full p-5 flex flex-row justify-start gap-3 rounded-lg no-underline">
  222. <div className=" flex flex-col gap-2">
  223. <h1 className="text-lg font-bold text-text-primary text-left">
  224. {staff?.team.title}
  225. </h1>
  226. <a className="text-left text-sky-orange hover:no-underline no-underline">
  227. {staff?.team.distributionList}
  228. </a>
  229. <Channel links={staff?.team.links} />
  230. <p className="text-text-primary text-left">
  231. {staff?.team.description.tagLine}
  232. </p>
  233. <p className="text-text-primary text-left">
  234. {staff?.team.description.description}
  235. </p>
  236. </div>
  237. </Link>
  238. </div>
  239. </Page>
  240. );
  241. };
  242.  
  243. export default Profile;
  244.  
Advertisement
Add Comment
Please, Sign In to add comment