import React, { useState } from "react"; import { observer } from "mobx-react-lite"; import Image from "next/image"; import { Controller, useForm } from "react-hook-form"; import { Camera, User2 } from "lucide-react"; import { IUser } from "@plane/types"; import { Button, Input } from "@plane/ui"; // components import { UserImageUploadModal } from "@/components/core"; import { OnboardingSidebar, OnboardingStepIndicator } from "@/components/onboarding"; // constants import { USER_DETAILS } from "@/constants/event-tracker"; // hooks import { useEventTracker, useUser, useWorkspace } from "@/hooks/store"; // assets import { FileService } from "@/services/file.service"; import IssuesSvg from "public/onboarding/onboarding-issues.webp"; // services // types const defaultValues: Partial = { first_name: "", avatar: "", use_case: undefined, }; type Props = { user?: IUser; setUserName: (name: string) => void; }; const USE_CASES = [ "Build Products", "Manage Feedbacks", "Service delivery", "Field force management", "Code Repository Integration", "Bug Tracking", "Test Case Management", "Resource allocation", ]; const fileService = new FileService(); export const UserDetails: React.FC = observer((props) => { const { user, setUserName } = props; // states const [isRemoving, setIsRemoving] = useState(false); const [isImageUploadModalOpen, setIsImageUploadModalOpen] = useState(false); // store hooks const { updateCurrentUser } = useUser(); const { workspaces } = useWorkspace(); const { captureEvent } = useEventTracker(); // derived values const workspaceName = workspaces ? Object.values(workspaces)?.[0]?.name : "New Workspace"; // form info const { getValues, handleSubmit, control, watch, setValue, formState: { errors, isSubmitting, isValid }, } = useForm({ defaultValues, mode: "onChange", }); const onSubmit = async (formData: IUser) => { if (!user) return; const payload: Partial = { ...formData, first_name: formData.first_name.split(" ")[0], last_name: formData.first_name.split(" ")[1], use_case: formData.use_case, onboarding_step: { ...user.onboarding_step, profile_complete: true, }, }; await updateCurrentUser(payload) .then(() => { captureEvent(USER_DETAILS, { use_case: formData.use_case, state: "SUCCESS", element: "Onboarding", }); }) .catch(() => { captureEvent(USER_DETAILS, { use_case: formData.use_case, state: "FAILED", element: "Onboarding", }); }); }; const handleDelete = (url: string | null | undefined) => { if (!url) return; setIsRemoving(true); fileService.deleteUserFile(url).finally(() => { setValue("avatar", ""); setIsRemoving(false); }); }; return (
( )} />
( setIsImageUploadModalOpen(false)} isRemoving={isRemoving} handleDelete={() => handleDelete(getValues("avatar"))} onSuccess={(url) => { onChange(url); setIsImageUploadModalOpen(false); }} value={value && value.trim() !== "" ? value : null} /> )} />

What do we call you?

( { setUserName(event.target.value); onChange(event); }} ref={ref} hasError={Boolean(errors.first_name)} placeholder="Enter your full name..." className="w-full border-onboarding-border-100 focus:border-custom-primary-100" /> )} />
{errors.first_name && {errors.first_name.message}}
(

And how will you use Plane{value.length > 0 ? ", " : ""} {value}?

)} />

Choose just one

(
{USE_CASES.map((useCase) => (
onChange(useCase)} > {useCase}
))}
)} />
issue-image
); });