"use client"; import { FC, useEffect, useMemo, useState } from "react"; import { useSearchParams } from "next/navigation"; // services import { AuthService } from "@/services/auth.service"; // ui import { Button, Input, Spinner } from "@plane/ui"; // components import { Banner } from "components/common"; // icons import { Eye, EyeOff } from "lucide-react"; // helpers import { API_BASE_URL } from "@/helpers/common.helper"; // service initialization const authService = new AuthService(); // error codes enum EErrorCodes { INSTANCE_NOT_CONFIGURED = "INSTANCE_NOT_CONFIGURED", REQUIRED_EMAIL_PASSWORD = "REQUIRED_EMAIL_PASSWORD", INVALID_EMAIL = "INVALID_EMAIL", USER_DOES_NOT_EXIST = "USER_DOES_NOT_EXIST", AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED", } type TError = { type: EErrorCodes | undefined; message: string | undefined; }; // form data type TFormData = { email: string; password: string; }; const defaultFromData: TFormData = { email: "", password: "", }; export const InstanceSignInForm: FC = (props) => { const {} = props; // search params const searchParams = useSearchParams(); const emailParam = searchParams.get("email") || undefined; const errorCode = searchParams.get("error_code") || undefined; const errorMessage = searchParams.get("error_message") || undefined; // state const [showPassword, setShowPassword] = useState(false); const [csrfToken, setCsrfToken] = useState(undefined); const [formData, setFormData] = useState(defaultFromData); const [isSubmitting, setIsSubmitting] = useState(false); const handleFormChange = (key: keyof TFormData, value: string | boolean) => setFormData((prev) => ({ ...prev, [key]: value })); useEffect(() => { if (csrfToken === undefined) authService.requestCSRFToken().then((data) => data?.csrf_token && setCsrfToken(data.csrf_token)); }, [csrfToken]); useEffect(() => { if (emailParam) setFormData((prev) => ({ ...prev, email: emailParam })); }, [emailParam]); // derived values const errorData: TError = useMemo(() => { if (errorCode && errorMessage) { switch (errorCode) { case EErrorCodes.INSTANCE_NOT_CONFIGURED: return { type: EErrorCodes.INVALID_EMAIL, message: errorMessage }; case EErrorCodes.REQUIRED_EMAIL_PASSWORD: return { type: EErrorCodes.REQUIRED_EMAIL_PASSWORD, message: errorMessage }; case EErrorCodes.INVALID_EMAIL: return { type: EErrorCodes.INVALID_EMAIL, message: errorMessage }; case EErrorCodes.USER_DOES_NOT_EXIST: return { type: EErrorCodes.USER_DOES_NOT_EXIST, message: errorMessage }; case EErrorCodes.AUTHENTICATION_FAILED: return { type: EErrorCodes.AUTHENTICATION_FAILED, message: errorMessage }; default: return { type: undefined, message: undefined }; } } else return { type: undefined, message: undefined }; }, [errorCode, errorMessage]); const isButtonDisabled = useMemo( () => (!isSubmitting && formData.email && formData.password ? false : true), [formData.email, formData.password, isSubmitting] ); return (

Manage your Plane instance

Configure instance-wide settings to secure your instance

{errorData.type && errorData?.message && }
setIsSubmitting(true)} onError={() => setIsSubmitting(false)} >
handleFormChange("email", e.target.value)} autoFocus />
handleFormChange("password", e.target.value)} /> {showPassword ? ( ) : ( )}
); };