diff --git a/src/pages/profile.tsx b/src/pages/profile.tsx index dbc2ca9d..2548b9c6 100644 --- a/src/pages/profile.tsx +++ b/src/pages/profile.tsx @@ -1,783 +1,655 @@ /* eslint-disable @next/next/no-img-element */ import Head from "next/head"; -import { withIronSessionSsr } from "iron-session/next"; -import { sessionOptions } from "@/lib/session"; -import { - ChangeEvent, - Dispatch, - ReactNode, - SetStateAction, - useEffect, - useRef, - useState, -} from "react"; +import {withIronSessionSsr} from "iron-session/next"; +import {sessionOptions} from "@/lib/session"; +import {ChangeEvent, Dispatch, ReactNode, SetStateAction, useEffect, useRef, useState} from "react"; import useUser from "@/hooks/useUser"; -import { toast, ToastContainer } from "react-toastify"; +import {toast, ToastContainer} from "react-toastify"; import Layout from "@/components/High/Layout"; import Input from "@/components/Low/Input"; import Button from "@/components/Low/Button"; import Link from "next/link"; import axios from "axios"; -import { ErrorMessage } from "@/constants/errors"; +import {ErrorMessage} from "@/constants/errors"; import clsx from "clsx"; -import { - CorporateUser, - EmploymentStatus, - EMPLOYMENT_STATUS, - Gender, - User, -} from "@/interfaces/user"; +import {CorporateUser, EmploymentStatus, EMPLOYMENT_STATUS, Gender, User} from "@/interfaces/user"; import CountrySelect from "@/components/Low/CountrySelect"; -import { shouldRedirectHome } from "@/utils/navigation.disabled"; +import {shouldRedirectHome} from "@/utils/navigation.disabled"; import moment from "moment"; -import { BsCamera, BsQuestionCircleFill } from "react-icons/bs"; -import { USER_TYPE_LABELS } from "@/resources/user"; +import {BsCamera, BsQuestionCircleFill} from "react-icons/bs"; +import {USER_TYPE_LABELS} from "@/resources/user"; import useGroups from "@/hooks/useGroups"; import useUsers from "@/hooks/useUsers"; -import { convertBase64 } from "@/utils"; -import { Divider } from "primereact/divider"; +import {convertBase64} from "@/utils"; +import {Divider} from "primereact/divider"; import GenderInput from "@/components/High/GenderInput"; import EmploymentStatusInput from "@/components/High/EmploymentStatusInput"; import TimezoneSelect from "@/components/Low/TImezoneSelect"; import Modal from "@/components/Modal"; -import { Module } from "@/interfaces"; +import {Module} from "@/interfaces"; import ModuleLevelSelector from "@/components/Medium/ModuleLevelSelector"; import Select from "@/components/Low/Select"; -import { InstructorGender } from "@/interfaces/exam"; -import { capitalize } from "lodash"; +import {InstructorGender} from "@/interfaces/exam"; +import {capitalize} from "lodash"; import TopicModal from "@/components/Medium/TopicModal"; -import { v4 } from "uuid"; -export const getServerSideProps = withIronSessionSsr(({ req, res }) => { - const user = req.session.user; +import {v4} from "uuid"; +export const getServerSideProps = withIronSessionSsr(({req, res}) => { + const user = req.session.user; - if (!user || !user.isVerified) { - return { - redirect: { - destination: "/login", - permanent: false, - }, - }; - } + if (!user || !user.isVerified) { + return { + redirect: { + destination: "/login", + permanent: false, + }, + }; + } - if (shouldRedirectHome(user)) { - return { - redirect: { - destination: "/", - permanent: false, - }, - }; - } + if (shouldRedirectHome(user)) { + return { + redirect: { + destination: "/", + permanent: false, + }, + }; + } - return { - props: { user: req.session.user }, - }; + return { + props: {user: req.session.user}, + }; }, sessionOptions); interface Props { - user: User; - mutateUser: Function; + user: User; + mutateUser: Function; } -const DoubleColumnRow = ({ children }: { children: ReactNode }) => ( -
{children}
-); +const DoubleColumnRow = ({children}: {children: ReactNode}) =>
{children}
; -function UserProfile({ user, mutateUser }: Props) { - const [bio, setBio] = useState(user.bio || ""); - const [name, setName] = useState(user.name || ""); - const [email, setEmail] = useState(user.email || ""); - const [password, setPassword] = useState(""); - const [newPassword, setNewPassword] = useState(""); - const [isLoading, setIsLoading] = useState(false); - const [profilePicture, setProfilePicture] = useState(user.profilePicture); +function UserProfile({user, mutateUser}: Props) { + const [bio, setBio] = useState(user.bio || ""); + const [name, setName] = useState(user.name || ""); + const [email, setEmail] = useState(user.email || ""); + const [password, setPassword] = useState(""); + const [newPassword, setNewPassword] = useState(""); + const [isLoading, setIsLoading] = useState(false); + const [profilePicture, setProfilePicture] = useState(user.profilePicture); - const [desiredLevels, setDesiredLevels] = useState< - { [key in Module]: number } | undefined - >( - ["developer", "student"].includes(user.type) - ? user.desiredLevels - : undefined, - ); + const [desiredLevels, setDesiredLevels] = useState<{[key in Module]: number} | undefined>( + ["developer", "student"].includes(user.type) ? user.desiredLevels : undefined, + ); + const [focus, setFocus] = useState<"academic" | "general">(user.focus); - const [country, setCountry] = useState( - user.demographicInformation?.country || "", - ); - const [phone, setPhone] = useState( - user.demographicInformation?.phone || "", - ); - const [gender, setGender] = useState( - user.demographicInformation?.gender || undefined, - ); - const [employment, setEmployment] = useState( - user.type === "corporate" - ? undefined - : user.demographicInformation?.employment, - ); - const [passport_id, setPassportID] = useState( - user.type === "student" - ? user.demographicInformation?.passport_id - : undefined, - ); + const [country, setCountry] = useState(user.demographicInformation?.country || ""); + const [phone, setPhone] = useState(user.demographicInformation?.phone || ""); + const [gender, setGender] = useState(user.demographicInformation?.gender || undefined); + const [employment, setEmployment] = useState( + user.type === "corporate" ? undefined : user.demographicInformation?.employment, + ); + const [passport_id, setPassportID] = useState(user.type === "student" ? user.demographicInformation?.passport_id : undefined); - const [preferredGender, setPreferredGender] = useState< - InstructorGender | undefined - >( - user.type === "student" || user.type === "developer" - ? user.preferredGender || "varied" - : undefined, - ); - const [preferredTopics, setPreferredTopics] = useState( - user.type === "student" || user.type === "developer" - ? user.preferredTopics - : undefined, - ); + const [preferredGender, setPreferredGender] = useState( + user.type === "student" || user.type === "developer" ? user.preferredGender || "varied" : undefined, + ); + const [preferredTopics, setPreferredTopics] = useState( + user.type === "student" || user.type === "developer" ? user.preferredTopics : undefined, + ); - const [position, setPosition] = useState( - user.type === "corporate" - ? user.demographicInformation?.position - : undefined, - ); - const [corporateInformation, setCorporateInformation] = useState( - user.type === "corporate" ? user.corporateInformation : undefined, - ); - const [companyName, setCompanyName] = useState( - user.type === "agent" ? user.agentInformation?.companyName : undefined, - ); - const [commercialRegistration, setCommercialRegistration] = useState< - string | undefined - >( - user.type === "agent" - ? user.agentInformation?.commercialRegistration - : undefined, - ); - const [arabName, setArabName] = useState( - user.type === "agent" ? user.agentInformation?.companyArabName : undefined, - ); + const [position, setPosition] = useState(user.type === "corporate" ? user.demographicInformation?.position : undefined); + const [corporateInformation, setCorporateInformation] = useState(user.type === "corporate" ? user.corporateInformation : undefined); + const [companyName, setCompanyName] = useState(user.type === "agent" ? user.agentInformation?.companyName : undefined); + const [commercialRegistration, setCommercialRegistration] = useState( + user.type === "agent" ? user.agentInformation?.commercialRegistration : undefined, + ); + const [arabName, setArabName] = useState(user.type === "agent" ? user.agentInformation?.companyArabName : undefined); - const [timezone, setTimezone] = useState( - user.demographicInformation?.timezone || moment.tz.guess(), - ); + const [timezone, setTimezone] = useState(user.demographicInformation?.timezone || moment.tz.guess()); - const [isPreferredTopicsOpen, setIsPreferredTopicsOpen] = useState(false); + const [isPreferredTopicsOpen, setIsPreferredTopicsOpen] = useState(false); - const { groups } = useGroups(); - const { users } = useUsers(); + const {groups} = useGroups(); + const {users} = useUsers(); - const profilePictureInput = useRef(null); - const expirationDateColor = (date: Date) => { - const momentDate = moment(date); - const today = moment(new Date()); + const profilePictureInput = useRef(null); + const expirationDateColor = (date: Date) => { + const momentDate = moment(date); + const today = moment(new Date()); - if (today.add(1, "days").isAfter(momentDate)) - return "!bg-mti-red-ultralight border-mti-red-light"; - if (today.add(3, "days").isAfter(momentDate)) - return "!bg-mti-rose-ultralight border-mti-rose-light"; - if (today.add(7, "days").isAfter(momentDate)) - return "!bg-mti-orange-ultralight border-mti-orange-light"; - }; + if (today.add(1, "days").isAfter(momentDate)) return "!bg-mti-red-ultralight border-mti-red-light"; + if (today.add(3, "days").isAfter(momentDate)) return "!bg-mti-rose-ultralight border-mti-rose-light"; + if (today.add(7, "days").isAfter(momentDate)) return "!bg-mti-orange-ultralight border-mti-orange-light"; + }; - const uploadProfilePicture = async (event: ChangeEvent) => { - if (event.target.files && event.target.files[0]) { - const picture = event.target.files[0]; - const base64 = await convertBase64(picture); - setProfilePicture(base64 as string); - } - }; + const uploadProfilePicture = async (event: ChangeEvent) => { + if (event.target.files && event.target.files[0]) { + const picture = event.target.files[0]; + const base64 = await convertBase64(picture); + setProfilePicture(base64 as string); + } + }; - const updateUser = async () => { - setIsLoading(true); - if (email !== user?.email && !password) { - toast.error("To update your e-mail you need to input your password!"); - setIsLoading(false); - return; - } + const updateUser = async () => { + setIsLoading(true); + if (email !== user?.email && !password) { + toast.error("To update your e-mail you need to input your password!"); + setIsLoading(false); + return; + } - if (newPassword && !password) { - toast.error( - "To update your password you need to input your current one!", - ); - setIsLoading(false); - return; - } + if (newPassword && !password) { + toast.error("To update your password you need to input your current one!"); + setIsLoading(false); + return; + } - if (email !== user?.email) { - const userAdmins = groups - .filter((x) => x.participants.includes(user.id)) - .map((x) => x.admin); - const message = - users.filter((x) => userAdmins.includes(x.id) && x.type === "corporate") - .length > 0 - ? "If you change your e-mail address, you will lose all benefits from your university/institute. Are you sure you want to continue?" - : "Are you sure you want to update your e-mail address?"; + if (email !== user?.email) { + const userAdmins = groups.filter((x) => x.participants.includes(user.id)).map((x) => x.admin); + const message = + users.filter((x) => userAdmins.includes(x.id) && x.type === "corporate").length > 0 + ? "If you change your e-mail address, you will lose all benefits from your university/institute. Are you sure you want to continue?" + : "Are you sure you want to update your e-mail address?"; - if (!confirm(message)) { - setIsLoading(false); - return; - } - } + if (!confirm(message)) { + setIsLoading(false); + return; + } + } - axios - .post("/api/users/update", { - bio, - name, - email, - password, - newPassword, - profilePicture, - desiredLevels, - preferredGender, - preferredTopics, - demographicInformation: { - phone, - country, - employment: user?.type === "corporate" ? undefined : employment, - position: user?.type === "corporate" ? position : undefined, - gender, - passport_id, - timezone, - }, - ...(user.type === "corporate" ? { corporateInformation } : {}), - ...(user.type === "agent" - ? { - agentInformation: { - companyName, - commercialRegistration, - arabName, - }, - } - : {}), - }) - .then((response) => { - if (response.status === 200) { - toast.success("Your profile has been updated!"); - mutateUser((response.data as { user: User }).user); - setIsLoading(false); - return; - } - }) - .catch((error) => { - console.log(error); - toast.error((error.response.data as ErrorMessage).message); - }) - .finally(() => { - setIsLoading(false); - }); - }; + axios + .post("/api/users/update", { + bio, + name, + email, + password, + newPassword, + profilePicture, + desiredLevels, + preferredGender, + preferredTopics, + focus, + demographicInformation: { + phone, + country, + employment: user?.type === "corporate" ? undefined : employment, + position: user?.type === "corporate" ? position : undefined, + gender, + passport_id, + timezone, + }, + ...(user.type === "corporate" ? {corporateInformation} : {}), + ...(user.type === "agent" + ? { + agentInformation: { + companyName, + commercialRegistration, + arabName, + }, + } + : {}), + }) + .then((response) => { + if (response.status === 200) { + toast.success("Your profile has been updated!"); + mutateUser((response.data as {user: User}).user); + setIsLoading(false); + return; + } + }) + .catch((error) => { + console.log(error); + toast.error((error.response.data as ErrorMessage).message); + }) + .finally(() => { + setIsLoading(false); + }); + }; - const ExpirationDate = () => ( -
- - - {!user.subscriptionExpirationDate && "Unlimited"} - {user.subscriptionExpirationDate && - moment(user.subscriptionExpirationDate).format("DD/MM/YYYY")} - -
- ); + const ExpirationDate = () => ( +
+ + + {!user.subscriptionExpirationDate && "Unlimited"} + {user.subscriptionExpirationDate && moment(user.subscriptionExpirationDate).format("DD/MM/YYYY")} + +
+ ); - const TimezoneInput = () => ( -
- - -
- ); + const TimezoneInput = () => ( +
+ + +
+ ); - const manualDownloadLink = ["student", "teacher", "corporate"].includes( - user.type, - ) - ? `/manuals/${user.type}.pdf` - : ""; + const manualDownloadLink = ["student", "teacher", "corporate"].includes(user.type) ? `/manuals/${user.type}.pdf` : ""; - return ( - -
-

Edit Profile

-
-
-

Edit Profile

-
e.preventDefault()} - > - - {user.type !== "corporate" ? ( - setName(e)} - placeholder="Enter your name" - defaultValue={name} - required - /> - ) : ( - - setCorporateInformation((prev) => ({ - ...prev!, - companyInformation: { - ...prev!.companyInformation, - name: e, - }, - })) - } - placeholder="Enter your company's name" - defaultValue={corporateInformation?.companyInformation.name} - required - /> - )} + return ( + +
+

Edit Profile

+
+
+

Edit Profile

+ e.preventDefault()}> + + {user.type !== "corporate" ? ( + setName(e)} + placeholder="Enter your name" + defaultValue={name} + required + /> + ) : ( + + setCorporateInformation((prev) => ({ + ...prev!, + companyInformation: { + ...prev!.companyInformation, + name: e, + }, + })) + } + placeholder="Enter your company's name" + defaultValue={corporateInformation?.companyInformation.name} + required + /> + )} - {user.type === "agent" && ( - setArabName(e)} - placeholder="Enter your arab name" - defaultValue={arabName} - required - /> - )} + {user.type === "agent" && ( + setArabName(e)} + placeholder="Enter your arab name" + defaultValue={arabName} + required + /> + )} - setEmail(e)} - placeholder="Enter email address" - defaultValue={email} - required - /> - - - setPassword(e)} - placeholder="Enter your password" - required - /> - setNewPassword(e)} - placeholder="Enter your new password (optional)" - /> - - {user.type === "agent" && ( -
- null} - placeholder="Enter your company's name" - defaultValue={companyName} - disabled - /> - null} - placeholder="Enter commercial registration" - defaultValue={commercialRegistration} - disabled - /> -
- )} + setEmail(e)} + placeholder="Enter email address" + defaultValue={email} + required + /> + + + setPassword(e)} + placeholder="Enter your password" + required + /> + setNewPassword(e)} + placeholder="Enter your new password (optional)" + /> + + {user.type === "agent" && ( +
+ null} + placeholder="Enter your company's name" + defaultValue={companyName} + disabled + /> + null} + placeholder="Enter commercial registration" + defaultValue={commercialRegistration} + disabled + /> +
+ )} - -
- - -
- setPhone(e)} - placeholder="Enter phone number" - defaultValue={phone} - required - /> -
+ +
+ + +
+ setPhone(e)} + placeholder="Enter phone number" + defaultValue={phone} + required + /> +
- {user.type === "student" ? ( - - setPassportID(e)} - placeholder="Enter National ID or Passport number" - value={passport_id} - required - /> - - - ) : ( - - )} + {user.type === "student" ? ( + + setPassportID(e)} + placeholder="Enter National ID or Passport number" + value={passport_id} + required + /> + + + ) : ( + + )} - + - {desiredLevels && - ["developer", "student"].includes(user.type) && ( -
- - - > - } - /> -
- )} + {desiredLevels && ["developer", "student"].includes(user.type) && ( + <> +
+ + >} + /> +
+
+ +
+ + +
+
+ + )} - {preferredGender && - ["developer", "student"].includes(user.type) && ( - <> - - -
- - (value ? setPreferredGender(value.value as InstructorGender) : null)} + options={[ + {value: "male", label: "Male"}, + {value: "female", label: "Female"}, + {value: "varied", label: "Varied"}, + ]} + /> +
+
+ + +
+
- setIsPreferredTopicsOpen(false)} - selectTopics={setPreferredTopics} - initialTopics={preferredTopics || []} - /> + setIsPreferredTopicsOpen(false)} + selectTopics={setPreferredTopics} + initialTopics={preferredTopics || []} + /> - - - )} + + + )} - {user.type === "corporate" && ( - <> - - null} - label="Number of users" - defaultValue={ - user.corporateInformation.companyInformation.userAmount - } - disabled - required - /> - null} - label="Pricing" - defaultValue={`${user.corporateInformation.payment?.value} ${user.corporateInformation.payment?.currency}`} - disabled - required - /> - - - - )} + {user.type === "corporate" && ( + <> + + null} + label="Number of users" + defaultValue={user.corporateInformation.companyInformation.userAmount} + disabled + required + /> + null} + label="Pricing" + defaultValue={`${user.corporateInformation.payment?.value} ${user.corporateInformation.payment?.currency}`} + disabled + required + /> + + + + )} - {user.type === "corporate" && ( - <> - - - setName(e)} - placeholder="Enter your name" - defaultValue={name} - required - /> - - - - )} + {user.type === "corporate" && ( + <> + + + setName(e)} + placeholder="Enter your name" + defaultValue={name} + required + /> + + + + )} - {user.type === "corporate" && - user.corporateInformation.referralAgent && ( - <> - - - null} - defaultValue={ - users.find( - (x) => - x.id === user.corporateInformation.referralAgent, - )?.name - } - type="text" - label="Country Manager's Name" - placeholder="Not available" - required - disabled - /> - null} - defaultValue={ - users.find( - (x) => - x.id === user.corporateInformation.referralAgent, - )?.email - } - type="text" - label="Country Manager's E-mail" - placeholder="Not available" - required - disabled - /> - - -
- - - x.id === - user.corporateInformation.referralAgent, - )?.demographicInformation?.country - } - onChange={() => null} - disabled - /> -
+ {user.type === "corporate" && user.corporateInformation.referralAgent && ( + <> + + + null} + defaultValue={users.find((x) => x.id === user.corporateInformation.referralAgent)?.name} + type="text" + label="Country Manager's Name" + placeholder="Not available" + required + disabled + /> + null} + defaultValue={users.find((x) => x.id === user.corporateInformation.referralAgent)?.email} + type="text" + label="Country Manager's E-mail" + placeholder="Not available" + required + disabled + /> + + +
+ + x.id === user.corporateInformation.referralAgent)?.demographicInformation + ?.country + } + onChange={() => null} + disabled + /> +
- null} - placeholder="Not available" - defaultValue={ - users.find( - (x) => - x.id === user.corporateInformation.referralAgent, - )?.demographicInformation?.phone - } - disabled - required - /> -
- - )} + null} + placeholder="Not available" + defaultValue={ + users.find((x) => x.id === user.corporateInformation.referralAgent)?.demographicInformation?.phone + } + disabled + required + /> +
+ + )} - {user.type !== "corporate" && ( - - + {user.type !== "corporate" && ( + + -
- - -
-
- )} - -
-
-
(profilePictureInput.current as any)?.click()} - > -
-
- -
- {user.name} -
- - (profilePictureInput.current as any)?.click()} - className="cursor-pointer text-mti-purple-light text-sm" - > - Change picture - -
- {USER_TYPE_LABELS[user.type]} -
-
- {user.type === "agent" && ( -
- { -
- )} - {manualDownloadLink && ( - - - - )} -
-
-
- Bio -