/* eslint-disable @next/next/no-img-element */ import CardList from "@/components/High/CardList"; import Select from "@/components/Low/Select"; import Input from "@/components/Low/Input"; import Checkbox from "@/components/Low/Checkbox"; import Tooltip from "@/components/Low/Tooltip"; import { useEntityPermission } from "@/hooks/useEntityPermissions"; import { EntityWithRoles, Role } from "@/interfaces/entity"; import { User } from "@/interfaces/user"; import { sessionOptions } from "@/lib/session"; import { USER_TYPE_LABELS } from "@/resources/user"; import { findBy, mapBy, redirect, serialize } from "@/utils"; import { getEntityWithRoles } from "@/utils/entities.be"; import { shouldRedirectHome } from "@/utils/navigation.disabled"; import { doesEntityAllow } from "@/utils/permissions"; import { getUserName, isAdmin } from "@/utils/users"; import { filterAllowedUsers, getEntitiesUsers, getEntityUsers, getUsers, } from "@/utils/users.be"; import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react"; import axios from "axios"; import clsx from "clsx"; import { withIronSessionSsr } from "iron-session/next"; import moment from "moment"; import Head from "next/head"; import Link from "next/link"; import { useRouter } from "next/router"; import { Divider } from "primereact/divider"; import { useEffect, useState } from "react"; import ReactDatePicker from "react-datepicker"; import { CURRENCIES } from "@/resources/paypal"; import { BsCheck, BsChevronLeft, BsClockFill, BsEnvelopeFill, BsHash, BsPerson, BsPlus, BsStopwatchFill, BsTag, BsTrash, BsX, } from "react-icons/bs"; import { toast } from "react-toastify"; import entities from "../../api/entities"; 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"; }; const CURRENCIES_OPTIONS = CURRENCIES.map(({ label, currency }) => ({ value: currency, label, })); const USER_DATA_SCHEMA = { _id: 0, id: 1, name: 1, type: 1, profilePicture: 1, email: 1, lastLogin: 1, subscriptionExpirationDate: 1, entities: 1, corporateInformation: 1, }; export const getServerSideProps = withIronSessionSsr( async ({ req, params }) => { const user = req.session.user as User; if (!user) return redirect("/login"); if (shouldRedirectHome(user)) return redirect("/"); const { id } = params as { id: string }; const entity = await getEntityWithRoles(id); if (!entity) return redirect("/entities"); if (!doesEntityAllow(user, entity, "view_entities")) return redirect(`/entities`); const [linkedUsers, entityUsers] = await Promise.all([ isAdmin(user) ? getUsers({}, 0, {}, USER_DATA_SCHEMA) : getEntitiesUsers( mapBy(user.entities, "id"), { $and: [ { type: { $ne: "developer" } }, { type: { $ne: "admin" } }, ], }, 0, USER_DATA_SCHEMA ), isAdmin(user) ? getEntityUsers( id, 0, { id: { $ne: user.id }, }, USER_DATA_SCHEMA ) : filterAllowedUsers(user, [entity], USER_DATA_SCHEMA), ]); const usersWithRole = entityUsers.map((u) => { const e = u?.entities?.find((e) => e.id === id); return { ...u, role: findBy(entity.roles, "id", e?.role) }; }); return { props: serialize({ user, entity, users: usersWithRole, linkedUsers: linkedUsers.filter( (x) => !mapBy(entityUsers, "id").includes(x.id) ), }), }; }, sessionOptions ); type UserWithRole = User & { role?: Role }; interface Props { user: User; entity: EntityWithRoles; users: UserWithRole[]; linkedUsers: User[]; } export default function Home({ user, entity, users, linkedUsers }: Props) { const [isAdding, setIsAdding] = useState(false); const [isLoading, setIsLoading] = useState(false); const [selectedUsers, setSelectedUsers] = useState([]); const [expiryDate, setExpiryDate] = useState(entity?.expiryDate); const [paymentPrice, setPaymentPrice] = useState(entity?.payment?.price); const [paymentCurrency, setPaymentCurrency] = useState( entity?.payment?.currency ); const router = useRouter(); const canRenameEntity = useEntityPermission(user, entity, "rename_entity"); const canViewRoles = useEntityPermission(user, entity, "view_entity_roles"); const canDeleteEntity = useEntityPermission(user, entity, "delete_entity"); const canAddMembers = useEntityPermission(user, entity, "add_to_entity"); const canRemoveMembers = useEntityPermission( user, entity, "remove_from_entity" ); const canAssignRole = useEntityPermission(user, entity, "assign_to_role"); const canPay = useEntityPermission(user, entity, "pay_entity"); const toggleUser = (u: User) => setSelectedUsers((prev) => prev.includes(u.id) ? prev.filter((p) => p !== u.id) : [...prev, u.id] ); const removeParticipants = () => { if (selectedUsers.length === 0) return; if (!canRemoveMembers) return; if ( !confirm( `Are you sure you want to remove ${selectedUsers.length} member${ selectedUsers.length === 1 ? "" : "s" } from this entity?` ) ) return; setIsLoading(true); axios .patch(`/api/entities/${entity.id}/users`, { add: false, members: selectedUsers, }) .then(() => { toast.success("The entity has been updated successfully!"); router.replace(router.asPath); setSelectedUsers([]); }) .catch((e) => { console.error(e); toast.error("Something went wrong!"); }) .finally(() => setIsLoading(false)); }; const addParticipants = () => { if (selectedUsers.length === 0) return; if (!canAddMembers || !isAdding) return; if ( !confirm( `Are you sure you want to add ${selectedUsers.length} member${ selectedUsers.length === 1 ? "" : "s" } to this entity?` ) ) return; setIsLoading(true); const defaultRole = findBy(entity.roles, "isDefault", true)!; axios .patch(`/api/entities/${entity.id}/users`, { add: true, members: selectedUsers, role: defaultRole.id, }) .then(() => { toast.success("The entity has been updated successfully!"); router.replace(router.asPath); setIsAdding(false); }) .catch((e) => { console.error(e); toast.error("Something went wrong!"); }) .finally(() => setIsLoading(false)); }; const renameGroup = () => { if (!canRenameEntity) return; const label = prompt("Rename this entity:", entity.label); if (!label) return; setIsLoading(true); axios .patch(`/api/entities/${entity.id}`, { label }) .then(() => { toast.success("The entity has been updated successfully!"); router.replace(router.asPath); }) .catch((e) => { console.error(e); toast.error("Something went wrong!"); }) .finally(() => setIsLoading(false)); }; const updateExpiryDate = () => { if (!isAdmin(user)) return; setIsLoading(true); axios .patch(`/api/entities/${entity.id}`, { expiryDate }) .then(() => { toast.success("The entity has been updated successfully!"); router.replace(router.asPath); }) .catch((e) => { console.error(e); toast.error("Something went wrong!"); }) .finally(() => setIsLoading(false)); }; const updatePayment = () => { if (!isAdmin(user)) return; setIsLoading(true); axios .patch(`/api/entities/${entity.id}`, { payment: { price: paymentPrice, currency: paymentCurrency }, }) .then(() => { toast.success("The entity has been updated successfully!"); router.replace(router.asPath); }) .catch((e) => { console.error(e); toast.error("Something went wrong!"); }) .finally(() => setIsLoading(false)); }; const editLicenses = () => { if (!isAdmin(user)) return; const licenses = prompt( "Update the number of licenses:", (entity.licenses || 0).toString() ); if (!licenses) return; if (!parseInt(licenses) || parseInt(licenses) <= 0) return toast.error("Write a valid number of licenses!"); setIsLoading(true); axios .patch(`/api/entities/${entity.id}`, { licenses }) .then(() => { toast.success("The entity has been updated successfully!"); router.replace(router.asPath); }) .catch((e) => { console.error(e); toast.error("Something went wrong!"); }) .finally(() => setIsLoading(false)); }; const deleteGroup = () => { if (!canDeleteEntity) return; if (!confirm("Are you sure you want to delete this entity?")) return; setIsLoading(true); axios .delete(`/api/entities/${entity.id}`) .then(() => { toast.success("This entity has been successfully deleted!"); router.replace("/entities"); }) .catch((e) => { console.error(e); toast.error("Something went wrong!"); }) .finally(() => setIsLoading(false)); }; const assignUsersToRole = (role: string) => { if (!canAssignRole) return; if (selectedUsers.length === 0) return; setIsLoading(true); axios .post(`/api/roles/${role}/users`, { users: selectedUsers }) .then(() => { toast.success("The role has been assigned successfully!"); router.replace(router.asPath); }) .catch((e) => { console.error(e); toast.error("Something went wrong!"); }) .finally(() => setIsLoading(false)); }; const renderCard = (u: UserWithRole) => { return ( ); }; useEffect(() => setSelectedUsers([]), [isAdding]); return ( <> {entity.label} | EnCoach <>

{entity.label}{" "} {isAdmin(user) && `- ${entity.licenses || 0} licenses`}

{!isAdmin(user) && canPay && ( {!entity.expiryDate && "Unlimited"} {entity.expiryDate && moment(entity.expiryDate).format("DD/MM/YYYY")} )}
{isAdmin(user) && ( )}
{isAdmin(user) && ( <>
{!!expiryDate && ( moment(date).isAfter(new Date())} dateFormat="dd/MM/yyyy" selected={expiryDate ? moment(expiryDate).toDate() : null} onChange={(date) => setExpiryDate(date)} /> )} {!expiryDate && (
Unlimited
)} setExpiryDate( checked ? entity.expiryDate || new Date() : null ) } > Enable expiry date
setPaymentPrice(e ? parseInt(e) : undefined) } type="number" defaultValue={entity.payment?.price || 0} thin />