From 6f211d84353e64e3030953550e7c3c6c039e49f7 Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Tue, 7 May 2024 09:48:49 +0100 Subject: [PATCH] Added the corporate user balance to the User Card --- src/components/UserCard.tsx | 1362 ++++++++++++++++------------------- 1 file changed, 612 insertions(+), 750 deletions(-) diff --git a/src/components/UserCard.tsx b/src/components/UserCard.tsx index 8e9c7ce7..08d97df0 100644 --- a/src/components/UserCard.tsx +++ b/src/components/UserCard.tsx @@ -1,15 +1,15 @@ import useStats from "@/hooks/useStats"; -import { EMPLOYMENT_STATUS, User } from "@/interfaces/user"; -import { groupBySession, averageScore } from "@/utils/stats"; -import { RadioGroup } from "@headlessui/react"; +import {CorporateInformation, CorporateUser, EMPLOYMENT_STATUS, User} from "@/interfaces/user"; +import {groupBySession, averageScore} from "@/utils/stats"; +import {RadioGroup} from "@headlessui/react"; import axios from "axios"; import clsx from "clsx"; import moment from "moment"; -import { Divider } from "primereact/divider"; -import { useEffect, useState } from "react"; +import {Divider} from "primereact/divider"; +import {useEffect, useState} from "react"; import ReactDatePicker from "react-datepicker"; -import { BsFileEarmarkText, BsPencil, BsStar } from "react-icons/bs"; -import { toast } from "react-toastify"; +import {BsFileEarmarkText, BsPencil, BsPerson, BsPersonAdd, BsStar} from "react-icons/bs"; +import {toast} from "react-toastify"; import Button from "./Low/Button"; import Checkbox from "./Low/Checkbox"; import CountrySelect from "./Low/CountrySelect"; @@ -17,776 +17,638 @@ import Input from "./Low/Input"; import ProfileSummary from "./ProfileSummary"; import Select from "react-select"; import useUsers from "@/hooks/useUsers"; -import { USER_TYPE_LABELS } from "@/resources/user"; -import { CURRENCIES } from "@/resources/paypal"; +import {USER_TYPE_LABELS} from "@/resources/user"; +import {CURRENCIES} from "@/resources/paypal"; +import useCodes from "@/hooks/useCodes"; const expirationDateColor = (date: Date) => { - const momentDate = moment(date); - const today = moment(new 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"; }; interface Props { - user: User; - loggedInUser: User; - onClose: (reload?: boolean) => void; - onViewStudents?: () => void; - onViewTeachers?: () => void; - onViewCorporate?: () => void; - disabled?: boolean; - disabledFields?: { - countryManager?: boolean; - }; + user: User; + loggedInUser: User; + onClose: (reload?: boolean) => void; + onViewStudents?: () => void; + onViewTeachers?: () => void; + onViewCorporate?: () => void; + disabled?: boolean; + disabledFields?: { + countryManager?: boolean; + }; } const USER_STATUS_OPTIONS = [ - { - value: "active", - label: "Active", - }, - { - value: "disabled", - label: "Disabled", - }, - { - value: "paymentDue", - label: "Payment Due", - }, + { + value: "active", + label: "Active", + }, + { + value: "disabled", + label: "Disabled", + }, + { + value: "paymentDue", + label: "Payment Due", + }, ]; const USER_TYPE_OPTIONS = Object.keys(USER_TYPE_LABELS).map((type) => ({ - value: type, - label: USER_TYPE_LABELS[type as keyof typeof USER_TYPE_LABELS], + value: type, + label: USER_TYPE_LABELS[type as keyof typeof USER_TYPE_LABELS], })); -const CURRENCIES_OPTIONS = CURRENCIES.map(({ label, currency }) => ({ - value: currency, - label, +const CURRENCIES_OPTIONS = CURRENCIES.map(({label, currency}) => ({ + value: currency, + label, })); -const UserCard = ({ - user, - loggedInUser, - onClose, - onViewStudents, - onViewTeachers, - onViewCorporate, - disabled = false, - disabledFields = {}, -}: Props) => { - const [expiryDate, setExpiryDate] = useState( - user.subscriptionExpirationDate, - ); - const [type, setType] = useState(user.type); - const [status, setStatus] = useState(user.status); - const [referralAgentLabel, setReferralAgentLabel] = useState(); - const [position, setPosition] = useState( - user.type === "corporate" - ? user.demographicInformation?.position - : undefined, - ); - const [passport_id, setPassportID] = useState( - user.type === "student" - ? user.demographicInformation?.passport_id - : undefined, - ); +const UserCard = ({user, loggedInUser, onClose, onViewStudents, onViewTeachers, onViewCorporate, disabled = false, disabledFields = {}}: Props) => { + const [expiryDate, setExpiryDate] = useState(user.subscriptionExpirationDate); + const [type, setType] = useState(user.type); + const [status, setStatus] = useState(user.status); + const [referralAgentLabel, setReferralAgentLabel] = useState(); + const [position, setPosition] = useState(user.type === "corporate" ? user.demographicInformation?.position : undefined); + const [passport_id, setPassportID] = useState(user.type === "student" ? user.demographicInformation?.passport_id : undefined); - const [referralAgent, setReferralAgent] = useState( - user.type === "corporate" - ? user.corporateInformation?.referralAgent - : undefined, - ); - const [companyName, setCompanyName] = useState( - user.type === "corporate" - ? user.corporateInformation?.companyInformation.name - : user.type === "agent" - ? user.agentInformation?.companyName - : undefined, - ); - const [arabName, setArabName] = useState( - user.type === "agent" ? user.agentInformation?.companyArabName : undefined, - ); - const [commercialRegistration, setCommercialRegistration] = useState( - user.type === "agent" - ? user.agentInformation?.commercialRegistration - : undefined, - ); - const [userAmount, setUserAmount] = useState( - user.type === "corporate" - ? user.corporateInformation?.companyInformation.userAmount - : undefined, - ); - const [paymentValue, setPaymentValue] = useState( - user.type === "corporate" - ? user.corporateInformation?.payment?.value - : undefined, - ); - const [paymentCurrency, setPaymentCurrency] = useState( - user.type === "corporate" - ? user.corporateInformation?.payment?.currency - : "EUR", - ); - const [monthlyDuration, setMonthlyDuration] = useState( - user.type === "corporate" - ? user.corporateInformation?.monthlyDuration - : undefined, - ); - const [commissionValue, setCommission] = useState( - user.type === "corporate" - ? user.corporateInformation?.payment?.commission - : undefined, - ); - const { stats } = useStats(user.id); - const { users } = useUsers(); + const [referralAgent, setReferralAgent] = useState(user.type === "corporate" ? user.corporateInformation?.referralAgent : undefined); + const [companyName, setCompanyName] = useState( + user.type === "corporate" + ? user.corporateInformation?.companyInformation.name + : user.type === "agent" + ? user.agentInformation?.companyName + : undefined, + ); + const [arabName, setArabName] = useState(user.type === "agent" ? user.agentInformation?.companyArabName : undefined); + const [commercialRegistration, setCommercialRegistration] = useState( + user.type === "agent" ? user.agentInformation?.commercialRegistration : undefined, + ); + const [userAmount, setUserAmount] = useState(user.type === "corporate" ? user.corporateInformation?.companyInformation.userAmount : undefined); + const [paymentValue, setPaymentValue] = useState(user.type === "corporate" ? user.corporateInformation?.payment?.value : undefined); + const [paymentCurrency, setPaymentCurrency] = useState(user.type === "corporate" ? user.corporateInformation?.payment?.currency : "EUR"); + const [monthlyDuration, setMonthlyDuration] = useState(user.type === "corporate" ? user.corporateInformation?.monthlyDuration : undefined); + const [commissionValue, setCommission] = useState(user.type === "corporate" ? user.corporateInformation?.payment?.commission : undefined); + const {stats} = useStats(user.id); + const {users} = useUsers(); + const {codes} = useCodes(user.id); - useEffect(() => { - if (users && users.length > 0) { - if (!referralAgent) { - setReferralAgentLabel("No manager"); - return; - } + useEffect(() => { + if (users && users.length > 0) { + if (!referralAgent) { + setReferralAgentLabel("No manager"); + return; + } - const agent = users.find((x) => x.id === referralAgent); - setReferralAgentLabel(`${agent?.name} - ${agent?.email}`); - } - }, [users, referralAgent]); + const agent = users.find((x) => x.id === referralAgent); + setReferralAgentLabel(`${agent?.name} - ${agent?.email}`); + } + }, [users, referralAgent]); - const updateUser = () => { - if (user.type === "corporate" && (!paymentValue || paymentValue < 0)) - return toast.error( - "Please set a price for the user's package before updating!", - ); - if (!confirm(`Are you sure you want to update ${user.name}'s account?`)) - return; + const updateUser = () => { + if (user.type === "corporate" && (!paymentValue || paymentValue < 0)) + return toast.error("Please set a price for the user's package before updating!"); + if (!confirm(`Are you sure you want to update ${user.name}'s account?`)) return; - axios - .post<{ user?: User; ok?: boolean }>(`/api/users/update?id=${user.id}`, { - ...user, - subscriptionExpirationDate: expiryDate, - type, - status, - agentInformation: - type === "agent" - ? { - companyName, - commercialRegistration, - arabName, - } - : undefined, - corporateInformation: - type === "corporate" - ? { - referralAgent, - monthlyDuration, - companyInformation: { - name: companyName, - userAmount, - }, - payment: { - value: paymentValue, - currency: paymentCurrency, - ...(referralAgent === "" - ? {} - : { commission: commissionValue }), - }, - } - : undefined, - }) - .then(() => { - toast.success("User updated successfully!"); - onClose(true); - }) - .catch(() => { - toast.error("Something went wrong!", { toastId: "update-error" }); - }); - }; + axios + .post<{user?: User; ok?: boolean}>(`/api/users/update?id=${user.id}`, { + ...user, + subscriptionExpirationDate: expiryDate, + type, + status, + agentInformation: + type === "agent" + ? { + companyName, + commercialRegistration, + arabName, + } + : undefined, + corporateInformation: + type === "corporate" + ? { + referralAgent, + monthlyDuration, + companyInformation: { + name: companyName, + userAmount, + }, + payment: { + value: paymentValue, + currency: paymentCurrency, + ...(referralAgent === "" ? {} : {commission: commissionValue}), + }, + } + : undefined, + }) + .then(() => { + toast.success("User updated successfully!"); + onClose(true); + }) + .catch(() => { + toast.error("Something went wrong!", {toastId: "update-error"}); + }); + }; - return ( - <> - - ), - value: Object.keys(groupBySession(stats)).length, - label: "Exams", - }, - { - icon: ( - - ), - value: stats.length, - label: "Modules", - }, - { - icon: ( - - ), - value: `${stats.length > 0 ? averageScore(stats) : 0}%`, - label: "Average Score", - }, - ]} - /> + const generalProfileItems = [ + { + icon: , + value: Object.keys(groupBySession(stats)).length, + label: "Exams", + }, + { + icon: , + value: stats.length, + label: "Modules", + }, + { + icon: , + value: `${stats.length > 0 ? averageScore(stats) : 0}%`, + label: "Average Score", + }, + ]; - {user.type === "agent" && ( - <> -
- - - -
- - - )} - {user.type === "corporate" && ( - <> -
- - setUserAmount(e ? parseInt(e) : undefined)} - placeholder="Enter number of users" - defaultValue={userAmount} - disabled={disabled} - /> - setMonthlyDuration(e ? parseInt(e) : undefined)} - placeholder="Enter monthly duration" - defaultValue={monthlyDuration} - disabled={disabled} - /> -
- -
- setPaymentValue(e ? parseInt(e) : undefined)} - type="number" - defaultValue={paymentValue || 0} - className="col-span-3" - disabled={disabled} - /> - u.type === "agent") - .map((x) => ({ - value: x.id, - label: `${x.name} - ${x.email}`, - })), - ]} - defaultValue={{ - value: referralAgent, - label: referralAgentLabel, - }} - menuPortalTarget={document?.body} - onChange={(value) => setReferralAgent(value?.value)} - styles={{ - menuPortal: (base) => ({ ...base, zIndex: 9999 }), - control: (styles) => ({ - ...styles, - paddingLeft: "4px", - border: "none", - outline: "none", - ":focus": { - outline: "none", - }, - }), - option: (styles, state) => ({ - ...styles, - backgroundColor: state.isFocused - ? "#D5D9F0" - : state.isSelected - ? "#7872BF" - : "white", - color: state.isFocused ? "black" : styles.color, - }), - }} - // editing country manager should only be available for dev/admin - isDisabled={ - !["developer", "admin"].includes(loggedInUser.type) || - disabledFields.countryManager - } - /> - )} -
-
- {referralAgent !== "" && loggedInUser.type !== "corporate" ? ( - <> - - setCommission(e ? parseInt(e) : undefined)} - type="number" - defaultValue={commissionValue || 0} - className="col-span-3" - disabled={disabled || loggedInUser.type === "agent"} - /> - - ) : ( -
- )} -
-
- - - )} -
-
- null} - placeholder="Enter your name" - defaultValue={user.name} - disabled - /> - null} - placeholder="Enter email address" - defaultValue={user.email} - disabled - /> -
+ const corporateProfileItems = + user.type === "corporate" + ? [ + { + icon: , + value: codes.length, + label: "Users Used", + }, + { + icon: , + value: user.corporateInformation.companyInformation.userAmount, + label: "Number of Users", + }, + ] + : []; -
-
- - -
- null} - placeholder="Enter phone number" - defaultValue={user.demographicInformation?.phone} - disabled - /> -
+ return ( + <> + - {user.type === "student" && ( - null} - placeholder="Enter National ID or Passport number" - value={ - user.type === "student" - ? user.demographicInformation?.passport_id - : undefined - } - disabled - required - /> - )} + {user.type === "agent" && ( + <> +
+ + + +
+ + + )} + {user.type === "corporate" && ( + <> +
+ + setUserAmount(e ? parseInt(e) : undefined)} + placeholder="Enter number of users" + defaultValue={userAmount} + disabled={disabled} + /> + setMonthlyDuration(e ? parseInt(e) : undefined)} + placeholder="Enter monthly duration" + defaultValue={monthlyDuration} + disabled={disabled} + /> +
+ +
+ setPaymentValue(e ? parseInt(e) : undefined)} + type="number" + defaultValue={paymentValue || 0} + className="col-span-3" + disabled={disabled} + /> + u.type === "agent") + .map((x) => ({ + value: x.id, + label: `${x.name} - ${x.email}`, + })), + ]} + defaultValue={{ + value: referralAgent, + label: referralAgentLabel, + }} + menuPortalTarget={document?.body} + onChange={(value) => setReferralAgent(value?.value)} + styles={{ + menuPortal: (base) => ({...base, zIndex: 9999}), + control: (styles) => ({ + ...styles, + paddingLeft: "4px", + border: "none", + outline: "none", + ":focus": { + outline: "none", + }, + }), + option: (styles, state) => ({ + ...styles, + backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white", + color: state.isFocused ? "black" : styles.color, + }), + }} + // editing country manager should only be available for dev/admin + isDisabled={!["developer", "admin"].includes(loggedInUser.type) || disabledFields.countryManager} + /> + )} +
+
+ {referralAgent !== "" && loggedInUser.type !== "corporate" ? ( + <> + + setCommission(e ? parseInt(e) : undefined)} + type="number" + defaultValue={commissionValue || 0} + className="col-span-3" + disabled={disabled || loggedInUser.type === "agent"} + /> + + ) : ( +
+ )} +
+
+ + + )} +
+
+ null} + placeholder="Enter your name" + defaultValue={user.name} + disabled + /> + null} + placeholder="Enter email address" + defaultValue={user.email} + disabled + /> +
-
- {user.type !== "corporate" && ( -
- - - {EMPLOYMENT_STATUS.map(({ status, label }) => ( - - {({ checked }) => ( - - {label} - - )} - - ))} - -
- )} - {user.type === "corporate" && ( - - )} -
-
- - - - {({ checked }) => ( - - Male - - )} - - - {({ checked }) => ( - - Female - - )} - - - {({ checked }) => ( - - Other - - )} - - -
-
-
- - - setExpiryDate( - checked - ? user.subscriptionExpirationDate || new Date() - : null, - ) - } - disabled={disabled} - > - Enabled - -
- {!expiryDate && ( -
- {!expiryDate && "Unlimited"} - {expiryDate && moment(expiryDate).format("DD/MM/YYYY")} -
- )} - {expiryDate && ( - - moment(date).isAfter(new Date()) && - (loggedInUser.subscriptionExpirationDate - ? moment(date).isBefore( - moment(loggedInUser.subscriptionExpirationDate), - ) - : true) - } - dateFormat="dd/MM/yyyy" - selected={moment(expiryDate).toDate()} - onChange={(date) => setExpiryDate(date)} - disabled={disabled} - /> - )} -
-
-
- {(loggedInUser.type === "developer" || - loggedInUser.type === "admin") && ( - <> - -
-
- - o.value === type)} - onChange={(value) => - setType(value?.value as typeof user.type) - } - styles={{ - control: (styles) => ({ - ...styles, - paddingLeft: "4px", - border: "none", - outline: "none", - ":focus": { - outline: "none", - }, - }), - menuPortal: (base) => ({ ...base, zIndex: 9999 }), - option: (styles, state) => ({ - ...styles, - backgroundColor: state.isFocused - ? "#D5D9F0" - : state.isSelected - ? "#7872BF" - : "white", - color: state.isFocused ? "black" : styles.color, - }), - }} - isDisabled={disabled} - /> -
-
- - )} -
+
+
+ + +
+ null} + placeholder="Enter phone number" + defaultValue={user.demographicInformation?.phone} + disabled + /> +
-
-
- {onViewCorporate && ["student", "teacher"].includes(user.type) && ( - - )} - {onViewStudents && ["corporate", "teacher"].includes(user.type) && ( - - )} - {onViewTeachers && ["student", "corporate"].includes(user.type) && ( - - )} -
-
- - -
-
- - ); + {user.type === "student" && ( + null} + placeholder="Enter National ID or Passport number" + value={user.type === "student" ? user.demographicInformation?.passport_id : undefined} + disabled + required + /> + )} + +
+ {user.type !== "corporate" && ( +
+ + + {EMPLOYMENT_STATUS.map(({status, label}) => ( + + {({checked}) => ( + + {label} + + )} + + ))} + +
+ )} + {user.type === "corporate" && ( + + )} +
+
+ + + + {({checked}) => ( + + Male + + )} + + + {({checked}) => ( + + Female + + )} + + + {({checked}) => ( + + Other + + )} + + +
+
+
+ + setExpiryDate(checked ? user.subscriptionExpirationDate || new Date() : null)} + disabled={disabled}> + Enabled + +
+ {!expiryDate && ( +
+ {!expiryDate && "Unlimited"} + {expiryDate && moment(expiryDate).format("DD/MM/YYYY")} +
+ )} + {expiryDate && ( + + moment(date).isAfter(new Date()) && + (loggedInUser.subscriptionExpirationDate + ? moment(date).isBefore(moment(loggedInUser.subscriptionExpirationDate)) + : true) + } + dateFormat="dd/MM/yyyy" + selected={moment(expiryDate).toDate()} + onChange={(date) => setExpiryDate(date)} + disabled={disabled} + /> + )} +
+
+
+ {(loggedInUser.type === "developer" || loggedInUser.type === "admin") && ( + <> + +
+
+ + o.value === type)} + onChange={(value) => setType(value?.value as typeof user.type)} + styles={{ + control: (styles) => ({ + ...styles, + paddingLeft: "4px", + border: "none", + outline: "none", + ":focus": { + outline: "none", + }, + }), + menuPortal: (base) => ({...base, zIndex: 9999}), + option: (styles, state) => ({ + ...styles, + backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white", + color: state.isFocused ? "black" : styles.color, + }), + }} + isDisabled={disabled} + /> +
+
+ + )} +
+ +
+
+ {onViewCorporate && ["student", "teacher"].includes(user.type) && ( + + )} + {onViewStudents && ["corporate", "teacher"].includes(user.type) && ( + + )} + {onViewTeachers && ["student", "corporate"].includes(user.type) && ( + + )} +
+
+ + +
+
+ + ); }; export default UserCard;