mohammed-ahad

edit profile

Sep 27th, 2023
34
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.46 KB | None | 0 0
  1. import React, { Fragment, useEffect, useState } from "react";
  2. import { useForm } from "react-hook-form";
  3. import { zodResolver } from "@hookform/resolvers/zod";
  4. import * as z from "zod";
  5. import Page from "../../../components/Page";
  6. import { PhotoIcon, UserCircleIcon } from "@heroicons/react/24/solid";
  7. import HobbiesDropdown from "../../../components/DropdownMenu";
  8. import DayPicker from "../../../components/DayPicker";
  9. import {
  10. DEPARTMENT_NAME_QUERY,
  11. DepartmentName,
  12. } from "../../../gql/departmentQuery";
  13. import { useQuery } from "@apollo/client";
  14. import { useMutation } from "@apollo/client";
  15. import { EDIT_STAFF_MUTATION } from "../../../gql/staffMutation";
  16. import { UserI } from "../../../types";
  17. import { getUser } from "../../../utils/getUser";
  18. import { UseQueryResult, useQuery as reactUseQuery } from "react-query";
  19. import Upload from "../../../components/UploadAntDesign";
  20. import { useToasts } from "react-toast-notifications";
  21. import useStaffData from "../../../common/getLoggedInUserHook";
  22. import Avatar from "../../../components/Nav/components/Avatar";
  23. import { getPeoplePhotoUrl } from "../../../common/peoplePhoto";
  24. import { StaffData } from "../../../gql/staffQuery";
  25. import { BiPencil } from "react-icons/bi";
  26. import { useUser } from "../../../utils/userContext";
  27.  
  28. export default function UpdateProfileForm() {
  29. const [selectedDepartment, setSelectedDepartment] = useState("");
  30. const [selectedTeam, setSelectedTeam] = useState("");
  31. const [action, setAction] = useState("");
  32. const azureUserData = useUser().userData;
  33. const { addToast } = useToasts();
  34.  
  35. const handleDepartmentChange = (
  36. event: React.ChangeEvent<HTMLSelectElement>
  37. ) => {
  38. setSelectedDepartment(event.target.value);
  39. clearErrors("department");
  40. };
  41.  
  42. const handleTeamChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
  43. setSelectedTeam(event.target.value);
  44. clearErrors("team");
  45. };
  46.  
  47. const handlePurposeChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
  48. setAction(event.target.value);
  49. };
  50.  
  51. const { loading, error, data } = useQuery<DepartmentName>(
  52. DEPARTMENT_NAME_QUERY
  53. );
  54.  
  55. console.log(data);
  56.  
  57. const MAX_FILE_SIZE = 500000;
  58. const ACCEPTED_IMAGE_TYPES = [
  59. "image/jpeg",
  60. "image/jpg",
  61. "image/png",
  62. "image/webp",
  63. ];
  64.  
  65. const formSchema = z.object({
  66. technology: z.string().nonempty("Technology is required"),
  67. dropDownMenu: z.array(z.string()).max(3, "You can only select up to 3 hobbies").optional(),
  68. });
  69.  
  70. const {
  71. register,
  72. handleSubmit,
  73. formState: { errors },
  74. control,
  75. getValues,
  76. clearErrors,
  77. } = useForm({
  78. resolver: zodResolver(formSchema),
  79. });
  80.  
  81. const [editStaff] = useMutation(EDIT_STAFF_MUTATION);
  82. const onSubmit = async (data: any) => {
  83. console.log("submit:", data);
  84. try{
  85. const response = await editStaff({
  86. variables: {
  87. modifyStaffId: editProfile?.staff?.id,
  88. technology: editProfile?.staff?.technology,
  89. hobbies: editProfile?.staff?.hobbies.map(hobby => hobby.icon).join(", "),
  90. imageLink: editProfile?.staff?.image,
  91. },
  92. });
  93. console.log("Add request response:", response.data);
  94. addToast("Profile Updated", {
  95. appearance: "success",
  96. autoDismiss: true,
  97. });
  98. } catch (e) {
  99. console.log(e);
  100. addToast("An error occurred", {
  101. appearance: "error",
  102. autoDismiss: true,
  103. });
  104. }
  105. };
  106.  
  107. const dropDownMenu = getValues("dropDownMenu");
  108. const {data: meData, loading: meLoading, error: meError} = useStaffData();
  109. const [editProfile, setEditProfile] = useState<StaffData|undefined>(undefined);
  110.  
  111. // sets the editProfile state to the current user data
  112. useEffect(() => {
  113. if ((editProfile === undefined || meLoading) && meData !== null){
  114. setEditProfile(meData);
  115. }
  116. }, [meLoading, meData]);
  117.  
  118. return (
  119. <Page>
  120. {
  121. editProfile !== undefined? (
  122. <div className="grid place-items-center py-12">
  123. <div
  124. className="absolute inset-x-0 -top-40 -z-20 transform-gpu overflow-hidden blur-3xl sm:-top-80"
  125. aria-hidden="true"
  126. >
  127. <div
  128. className="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#bfdbfe] to-[#2563eb] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
  129. style={{
  130. clipPath:
  131. "polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)",
  132. }}
  133. />
  134. </div>
  135. <div className="mx-auto max-w-2xl">
  136. <h1 className="text-4xl font-semibold tracking-tight text-text-primary sm:text-6xl animate__animated animate__slideInDown flex pl-4 justify-center">
  137. Edit Profile
  138. </h1>
  139. </div>
  140.  
  141. <div className="py-12 w-9/12">
  142. <form
  143. className="bg-neutral shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl"
  144. onSubmit={handleSubmit(onSubmit)}
  145. >
  146. <div className="px-4 py-6 sm:p-8">
  147. <div>
  148. <div className="mb-5">
  149. <div className="grid grid-cols-2 gap-x-28 gap-y-8">
  150. {/* <div className="flex flex-col gap-3">
  151. <h1 className="text-3xl font-bold text-text-primary">
  152. {meData?.staff?.name}
  153. </h1>
  154. <p className="text-text-primary">{meData?.staff?.role}</p>
  155. </div> */}
  156. </div>
  157. </div>
  158. <div className="col-span-full">
  159. <label htmlFor="photo" className="block text-sm font-medium leading-6 text-gray-900">
  160. Photo
  161. </label>
  162. <div className="flex flex-col">
  163. <div className="flex flex-row">
  164. <div className="mt-2 flex items-center gap-x-3 mb-5">
  165. <Avatar
  166. avatar={getPeoplePhotoUrl(meData?.staff?.image === undefined? "" : meData?.staff?.image, true) as Blob}
  167. loading={loading}
  168. size={50}
  169. user={meData?.staff}
  170. userLoading={loading}
  171. grayed={false}
  172. />
  173. <button
  174. type="button"
  175. className="rounded-md bg-white px-2.5 py-1.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50"
  176. >
  177. <BiPencil/>
  178. </button>
  179. </div>
  180. </div>
  181. <div className="grid grid-cols-2 gap-x-28 gap-y-8 z-40 pb-8">
  182. <label
  183. htmlFor="name"
  184. className="block text-sm font-medium leading-6 text-text-primary"
  185. >
  186. Employee's Name{" "}
  187. <span className="text-red-500">*</span>
  188. </label>
  189. <input
  190. type="text"
  191. name="name"
  192. id="name"
  193. disabled={true}
  194. value={editProfile?.staff.name}
  195. onChange={(e) => {
  196. setEditProfile({
  197. ...editProfile,
  198. staff: {
  199. ...editProfile?.staff,
  200. name: e.target.value,
  201. },
  202. });
  203. }}
  204. className="block w-full rounded-md bg-neutral-shadow border-0 py-1.5 text-text-primary shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:max-w-xs sm:text-sm sm:leading-6"
  205. placeholder="Enter Favourite Technology"
  206. />
  207. </div>
  208. <div className="grid grid-cols-2 gap-x-28 gap-y-8 z-40 pb-8">
  209. <label
  210. htmlFor="name"
  211. className="block text-sm font-medium leading-6 text-text-primary"
  212. >
  213. Employee's Job Title{" "}
  214. <span className="text-red-500">*</span>
  215. </label>
  216. <input
  217. type="text"
  218. name="role"
  219. id="role"
  220. disabled={true}
  221. value={editProfile?.staff.role}
  222. onChange={(e) => {
  223. setEditProfile({
  224. ...editProfile,
  225. staff: {
  226. ...editProfile?.staff,
  227. role: e.target.value,
  228. },
  229. });
  230. }}
  231. className="block w-full rounded-md bg-neutral-shadow border-0 py-1.5 text-text-primary shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:max-w-xs sm:text-sm sm:leading-6"
  232. placeholder="Enter Favourite Technology"
  233. />
  234. </div>
  235. <div className="grid grid-cols-2 gap-x-28 gap-y-8 z-40 pb-8">
  236. <label
  237. htmlFor="name"
  238. className="block text-sm font-medium leading-6 text-text-primary"
  239. >
  240. Employee's Job Start{" "}
  241. <span className="text-red-500">*</span>
  242. </label>
  243. <input
  244. type="text"
  245. name="jobStart"
  246. id="jobStart"
  247. disabled={true}
  248. value={editProfile?.staff.jobStart}
  249. onChange={(e) => {
  250. setEditProfile({
  251. ...editProfile,
  252. staff: {
  253. ...editProfile?.staff,
  254. jobStart: e.target.value,
  255. },
  256. });
  257. }}
  258. className="block w-full rounded-md bg-neutral-shadow border-0 py-1.5 text-text-primary shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:max-w-xs sm:text-sm sm:leading-6"
  259. placeholder="Enter Favourite Technology"
  260. />
  261. </div>
  262. </div>
  263. </div>
  264. <div className="grid grid-cols-2 gap-x-28 gap-y-8 z-40 pb-8">
  265. <label
  266. htmlFor="technology"
  267. className="block text-sm font-medium leading-6 text-text-primary"
  268. >
  269. Employee's Favourite Technology{" "}
  270. <span className="text-red-500">*</span>
  271. </label>
  272. <input
  273. {...register("technology")}
  274. type="text"
  275. name="technology"
  276. id="technology"
  277. value={editProfile?.staff.technology}
  278. onChange={(e) => {
  279. setEditProfile({
  280. ...editProfile,
  281. staff: {
  282. ...editProfile?.staff,
  283. technology: e.target.value,
  284. },
  285. });
  286. }}
  287. className="block w-full rounded-md bg-neutral-dimmed border-0 py-1.5 text-text-primary shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:max-w-xs sm:text-sm sm:leading-6"
  288. placeholder="Enter Favourite Technology"
  289. />
  290. </div>
  291. {/* grayed out inputs with name and title */}
  292. <HobbiesDropdown
  293. register={register}
  294. errors={errors}
  295. formSchema={formSchema}
  296. control={control}
  297. selectedHobbies={editProfile?.staff.hobbies.map(hobby => hobby.icon).sort()}
  298. setSelectedHobbies={(hobbies: string[]) => {
  299. setEditProfile({
  300. ...editProfile,
  301. staff: {
  302. ...editProfile?.staff,
  303. hobbies: hobbies.map(hobby => {
  304. return {
  305. icon: hobby,
  306. name: hobby,
  307. }
  308. }),
  309. },
  310. });
  311. }}
  312. columns={2}
  313. />
  314. </div>
  315. </div>
  316. <div className="flex items-center justify-end gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8">
  317. <input
  318. type="reset"
  319. className="text-sm font-semibold leading-6 text-text-primary"
  320. value="Cancel"
  321. />
  322. <button
  323. type="submit"
  324. className="rounded-md bg-blue-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-blue-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600"
  325. >
  326. Save
  327. </button>
  328. </div>
  329. </form>
  330. </div>
  331. <div
  332. className="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]"
  333. aria-hidden="true"
  334. >
  335. <div
  336. className="relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#bfdbfe] to-[#2563eb] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]"
  337. style={{
  338. clipPath:
  339. "polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)",
  340. }}
  341. />
  342. </div>
  343. </div>
  344. ) : (
  345. <div/>
  346. )
  347. }
  348. {/* Hero Section */}
  349. </Page>
  350. );
  351. }
  352.  
Advertisement
Add Comment
Please, Sign In to add comment