import { ChangeEvent, useCallback, useState } from "react"; import { useRouter } from "next/router"; import axios from "axios"; import { v4 as uuidv4 } from "uuid"; import { BasicProgressMessageBox, BasicTextField, ProgressMessageBoxState, SingleSelectOption, BasicSingleSelect, BasicToggleField, SolidButton, FormRoot, } from "@instill-ai/design-system"; import { useUpdateUser, useAmplitudeCtx, sendAmplitudeData, type User, type Nullable, } from "@instill-ai/toolkit"; import { mgmtRoleOptions } from "../lib"; import { useAccessToken } from "../lib/useAccessToken"; export type OnboardingFormValues = { email: Nullable; orgName: Nullable; role: Nullable; newsletterSubscription: Nullable; }; type OnboardingFormErrors = { email: Nullable; orgName: Nullable; role: Nullable; }; export const OnboardingForm = () => { const router = useRouter(); const updateUser = useUpdateUser(); const { amplitudeIsInit } = useAmplitudeCtx(); const accessToken = useAccessToken(); const [fieldValues, setFieldValues] = useState({ email: null, orgName: null, role: null, newsletterSubscription: true, }); const [selectedRoleOption, setSelectedRoleOption] = useState< Nullable >(mgmtRoleOptions.find((e) => e.value === fieldValues.role) || null); const [messageBoxState, setMessageBoxState] = useState({ activate: false, message: null, description: null, status: null, }); // Handle fields change and per-field validation here const handleFieldChange = useCallback( (key: keyof OnboardingFormValues, event: ChangeEvent) => { const value = key === "newsletterSubscription" ? event.target.checked : event.target.value; if (key === "email") { let error: Nullable = null; if (!value) { error = "Email is required"; } else { if ( !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test( event.target.value ) ) { error = "Invalid email address"; } } setFieldErrors((prev) => ({ ...prev, email: error, })); } if (key === "orgName") { let error: Nullable = null; if (!value) { error = "Company name is required"; } setFieldErrors((prev) => ({ ...prev, orgName: error, })); } setFieldValues((prev) => ({ ...prev, [key]: key === "newsletterSubscription" ? event.target.checked : event.target.value, })); }, [] ); const handleRoleChange = useCallback( (option: Nullable) => { if (!option) return; setSelectedRoleOption(option); let error: Nullable = null; if (!option.value) { error = "Role is required"; } setFieldErrors((prev) => ({ ...prev, role: error, })); setFieldValues((prev) => ({ ...prev, role: option.value as string, })); }, [] ); // Validate form and deal with error handling const [fieldErrors, setFieldErrors] = useState({ email: null, orgName: null, role: null, }); const handleSubmit = useCallback(() => { if (!accessToken.isSuccess) { return; } const errors = {} as OnboardingFormErrors; if (!fieldValues.email) { errors["email"] = "Email is required"; } else { if ( !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(fieldValues.email) ) { errors["email"] = "Invalid email address"; } } if (!fieldValues.orgName) { errors["orgName"] = "Company name is required"; } if (!fieldValues.role) { errors["role"] = "Role is required"; } setFieldErrors(errors); if (Object.keys(errors).length !== 0) { return; } let token: string | undefined = undefined; token = uuidv4(); const payload: Partial = { email: fieldValues.email as string, org_name: fieldValues.orgName as string, role: fieldValues.role as string, newsletter_subscription: fieldValues.newsletterSubscription ? fieldValues.newsletterSubscription : false, cookie_token: token, }; setMessageBoxState(() => ({ activate: true, status: "progressing", description: null, message: "Uploading...", })); updateUser.mutate( { payload, accessToken: accessToken.data }, { onSuccess: async (user) => { if (amplitudeIsInit) { sendAmplitudeData("submit_onboarding_form", { type: "critical_action", }); } setMessageBoxState(() => ({ activate: true, status: "success", description: null, message: "Succeed.", })); await axios.post("/api/set-user-cookie", { key: "instill-ai-user", value: JSON.stringify({ cookie_token: token, }), }); await router.push(`/${user.id}/pipelines`); }, onError: (error) => { if (error instanceof Error) { setMessageBoxState(() => ({ activate: true, status: "error", description: null, message: error.message, })); } else { setMessageBoxState(() => ({ activate: true, status: "error", description: null, message: "Something went wrong when upload the form", })); } }, } ); }, [ fieldValues, amplitudeIsInit, router, updateUser, accessToken.data, accessToken.isSuccess, ]); return (
handleFieldChange("email", event)} error={fieldErrors.email} /> handleFieldChange("orgName", event)} error={fieldErrors.orgName} /> handleFieldChange("newsletterSubscription", event) } />
setMessageBoxState((prev) => ({ ...prev, activate, })) } width="w-[25vw]" closable={true} /> Start
); };