Skip to content

Commit

Permalink
chore: splitted the code for project creation form
Browse files Browse the repository at this point in the history
  • Loading branch information
gakshita committed Aug 7, 2024
1 parent b094197 commit 836c3be
Show file tree
Hide file tree
Showing 13 changed files with 487 additions and 423 deletions.
80 changes: 80 additions & 0 deletions web/ce/components/projects/create/attributes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { Controller, useFormContext } from "react-hook-form";
import { IProject } from "@plane/types";
import { CustomSelect } from "@plane/ui";
import { MemberDropdown } from "@/components/dropdowns";
import { NETWORK_CHOICES } from "@/constants/project";

const ProjectAttributes = () => {
const { control } = useFormContext<IProject>();
return (
<div className="flex flex-wrap items-center gap-2">
<Controller
name="network"
control={control}
render={({ field: { onChange, value } }) => {
const currentNetwork = NETWORK_CHOICES.find((n) => n.key === value);

return (
<div className="flex-shrink-0 h-7" tabIndex={4}>
<CustomSelect
value={value}
onChange={onChange}
label={
<div className="flex items-center gap-1 h-full">
{currentNetwork ? (
<>
<currentNetwork.icon className="h-3 w-3" />
{currentNetwork.label}
</>
) : (
<span className="text-custom-text-400">Select network</span>
)}
</div>
}
placement="bottom-start"
className="h-full"
buttonClassName="h-full"
noChevron
tabIndex={4}
>
{NETWORK_CHOICES.map((network) => (
<CustomSelect.Option key={network.key} value={network.key}>
<div className="flex items-start gap-2">
<network.icon className="h-3.5 w-3.5" />
<div className="-mt-1">
<p>{network.label}</p>
<p className="text-xs text-custom-text-400">{network.description}</p>
</div>
</div>
</CustomSelect.Option>
))}
</CustomSelect>
</div>
);
}}
/>
<Controller
name="project_lead"
control={control}
render={({ field: { value, onChange } }) => {
if (value === undefined || value === null || typeof value === "string")
return (
<div className="flex-shrink-0 h-7" tabIndex={5}>
<MemberDropdown
value={value}
onChange={(lead) => onChange(lead === value ? null : lead)}
placeholder="Lead"
multiple={false}
buttonVariant="border-with-text"
tabIndex={5}
/>
</div>
);
else return <></>;
}}
/>
</div>
);
};

export default ProjectAttributes;
138 changes: 138 additions & 0 deletions web/ce/components/projects/create/root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
"use client";

import { useState, FC } from "react";
import { observer } from "mobx-react";
import { FormProvider, useForm } from "react-hook-form";
import { IProject } from "@plane/types";
// ui
import { setToast, TOAST_TYPE } from "@plane/ui";
// constants
import ProjectCommonAttributes from "@/components/project/create/common-attributes";
import ProjectCreateHeader from "@/components/project/create/header";
import ProjectCreateButtons from "@/components/project/create/project-create-buttons";
import { PROJECT_CREATED } from "@/constants/event-tracker";
import { PROJECT_UNSPLASH_COVERS } from "@/constants/project";
// helpers
import { getRandomEmoji } from "@/helpers/emoji.helper";
// hooks
import { useEventTracker, useProject } from "@/hooks/store";
import { usePlatformOS } from "@/hooks/use-platform-os";
import ProjectAttributes from "./attributes";

type Props = {
setToFavorite?: boolean;
workspaceSlug: string;
onClose: () => void;
handleNextStep: (projectId: string) => void;
};

const defaultValues: Partial<IProject> = {
cover_image: PROJECT_UNSPLASH_COVERS[Math.floor(Math.random() * PROJECT_UNSPLASH_COVERS.length)],
description: "",
logo_props: {
in_use: "emoji",
emoji: {
value: getRandomEmoji(),
},
},
identifier: "",
name: "",
network: 2,
project_lead: null,
};

export const CreateProjectForm: FC<Props> = observer((props) => {
const { setToFavorite, workspaceSlug, onClose, handleNextStep } = props;
// store
const { captureProjectEvent } = useEventTracker();
const { addProjectToFavorites, createProject } = useProject();
// states
const [isChangeInIdentifierRequired, setIsChangeInIdentifierRequired] = useState(true);
// form info
const methods = useForm<IProject>({
defaultValues,
reValidateMode: "onChange",
});
const { handleSubmit, reset, setValue } = methods;
const { isMobile } = usePlatformOS();
const handleAddToFavorites = (projectId: string) => {
if (!workspaceSlug) return;

addProjectToFavorites(workspaceSlug.toString(), projectId).catch(() => {
setToast({
type: TOAST_TYPE.ERROR,
title: "Error!",
message: "Couldn't remove the project from favorites. Please try again.",
});
});
};

const onSubmit = async (formData: Partial<IProject>) => {
// Upper case identifier
formData.identifier = formData.identifier?.toUpperCase();

return createProject(workspaceSlug.toString(), formData)
.then((res) => {
const newPayload = {
...res,
state: "SUCCESS",
};
captureProjectEvent({
eventName: PROJECT_CREATED,
payload: newPayload,
});
setToast({
type: TOAST_TYPE.SUCCESS,
title: "Success!",
message: "Project created successfully.",
});
if (setToFavorite) {
handleAddToFavorites(res.id);
}
handleNextStep(res.id);
})
.catch((err) => {
Object.keys(err.data).map((key) => {
setToast({
type: TOAST_TYPE.ERROR,
title: "Error!",
message: err.data[key],
});
captureProjectEvent({
eventName: PROJECT_CREATED,
payload: {
...formData,
state: "FAILED",
},
});
});
});
};

const handleClose = () => {
onClose();
setIsChangeInIdentifierRequired(true);
setTimeout(() => {
reset();
}, 300);
};

return (
<FormProvider {...methods}>
<ProjectCreateHeader handleClose={handleClose} />

<form onSubmit={handleSubmit(onSubmit)} className="px-3">
<div className="mt-9 space-y-6 pb-5">
<ProjectCommonAttributes
setValue={setValue}
isMobile={isMobile}
isChangeInIdentifierRequired={isChangeInIdentifierRequired}
setIsChangeInIdentifierRequired={setIsChangeInIdentifierRequired}
/>
<ProjectAttributes />
</div>
<ProjectCreateButtons handleClose={handleClose} />
</form>
</FormProvider>
);
});
3 changes: 3 additions & 0 deletions web/ce/types/projects/projects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { IProject } from "@plane/types";

export type TProject = IProject;
Loading

0 comments on commit 836c3be

Please sign in to comment.