import React, { useState, useEffect } from "react"; import { useRouter } from "next/router"; import { mutate } from "swr"; // react-hook-form import { useForm, Controller } from "react-hook-form"; // headless ui import { Dialog, Transition } from "@headlessui/react"; // services import projectServices from "services/project.service"; // hooks import useToast from "hooks/use-toast"; import { useWorkspaceMyMembership } from "contexts/workspace-member.context"; import useWorkspaceMembers from "hooks/use-workspace-members"; // ui import { Input, TextArea, CustomSelect, PrimaryButton, SecondaryButton, Icon, Avatar, CustomSearchSelect, } from "components/ui"; // icons import { XMarkIcon } from "@heroicons/react/24/outline"; // components import { ImagePickerPopover } from "components/core"; import EmojiIconPicker from "components/emoji-icon-picker"; // helpers import { getRandomEmoji, renderEmoji } from "helpers/emoji.helper"; // types import { ICurrentUserResponse, IProject } from "types"; // fetch-keys import { PROJECTS_LIST } from "constants/fetch-keys"; // constants import { NETWORK_CHOICES } from "constants/project"; type Props = { isOpen: boolean; setIsOpen: React.Dispatch>; setToFavorite?: boolean; user: ICurrentUserResponse | undefined; }; const defaultValues: Partial = { cover_image: "https://images.unsplash.com/photo-1531045535792-b515d59c3d1f?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=870&q=80", description: "", emoji_and_icon: getRandomEmoji(), identifier: "", name: "", network: 2, project_lead: null, }; const IsGuestCondition: React.FC<{ setIsOpen: React.Dispatch>; }> = ({ setIsOpen }) => { const { setToastAlert } = useToast(); useEffect(() => { setIsOpen(false); setToastAlert({ title: "Error", type: "error", message: "You don't have permission to create project.", }); }, [setIsOpen, setToastAlert]); return null; }; export const CreateProjectModal: React.FC = ({ isOpen, setIsOpen, setToFavorite = false, user, }) => { const [isChangeInIdentifierRequired, setIsChangeInIdentifierRequired] = useState(true); const { setToastAlert } = useToast(); const router = useRouter(); const { workspaceSlug } = router.query; const { memberDetails } = useWorkspaceMyMembership(); const { workspaceMembers } = useWorkspaceMembers(workspaceSlug?.toString() ?? ""); const { register, formState: { errors, isSubmitting }, handleSubmit, reset, control, watch, setValue, } = useForm({ defaultValues, reValidateMode: "onChange", }); const handleClose = () => { setIsOpen(false); setIsChangeInIdentifierRequired(true); reset(defaultValues); }; const handleAddToFavorites = (projectId: string) => { if (!workspaceSlug) return; mutate( PROJECTS_LIST(workspaceSlug as string, { is_favorite: "all" }), (prevData) => (prevData ?? []).map((p) => (p.id === projectId ? { ...p, is_favorite: true } : p)), false ); projectServices .addProjectToFavorites(workspaceSlug as string, { project: projectId, }) .catch(() => setToastAlert({ type: "error", title: "Error!", message: "Couldn't remove the project from favorites. Please try again.", }) ); }; const onSubmit = async (formData: IProject) => { if (!workspaceSlug) return; const { emoji_and_icon, ...payload } = formData; if (typeof formData.emoji_and_icon === "object") payload.icon_prop = formData.emoji_and_icon; else payload.emoji = formData.emoji_and_icon; await projectServices .createProject(workspaceSlug.toString(), payload, user) .then((res) => { mutate( PROJECTS_LIST(workspaceSlug.toString(), { is_favorite: "all" }), (prevData) => [res, ...(prevData ?? [])], false ); setToastAlert({ type: "success", title: "Success!", message: "Project created successfully.", }); if (setToFavorite) { handleAddToFavorites(res.id); } handleClose(); }) .catch((err) => { Object.keys(err.data).map((key) => setToastAlert({ type: "error", title: "Error!", message: err.data[key], }) ); }); }; const changeIdentifierOnNameChange = (e: React.ChangeEvent) => { if (!isChangeInIdentifierRequired) return; if (e.target.value === "") setValue("identifier", ""); else setValue( "identifier", e.target.value .replace(/[^a-zA-Z0-9]/g, "") .toUpperCase() .substring(0, 5) ); }; const handleIdentifierChange = (e: React.ChangeEvent) => { const { value } = e.target; const alphanumericValue = value.replace(/[^a-zA-Z0-9]/g, ""); setValue("identifier", alphanumericValue.toUpperCase()); setIsChangeInIdentifierRequired(false); }; const options = workspaceMembers?.map((member) => ({ value: member.member.id, query: member.member.display_name, content: (
{member.member.display_name}
), })); const currentNetwork = NETWORK_CHOICES.find((n) => n.key === watch("network")); if (memberDetails && isOpen) if (memberDetails.role <= 10) return ; return (
{watch("cover_image") !== null && ( Cover Image )}
{ setValue("cover_image", image); }} value={watch("cover_image")} />
( {value ? renderEmoji(value) : "Icon"}
} onChange={onChange} value={value} /> )} />
/^[A-Z0-9]+$/.test(value.toUpperCase()) || "Identifier must be in uppercase.", minLength: { value: 1, message: "Identifier must at least be of 1 character", }, maxLength: { value: 12, message: "Identifier must at most be of 12 characters", }, }} />