"use client"; import { zodResolver } from "@hookform/resolvers/zod"; import * as RadioGroup from "@radix-ui/react-radio-group"; import classNames from "classnames"; import Link from "next/link"; import { useCallback, useState } from "react"; import { Controller, FormProvider, useForm, useFormState } from "react-hook-form"; import { z } from "zod"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import type { RouterInputs, RouterOutputs } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react"; import { Button } from "@calcom/ui/components/button"; import { TextField } from "@calcom/ui/components/form"; import { Icon } from "@calcom/ui/components/icon"; type LicenseSelectionFormValues = { licenseKey: string; signatureToken?: string; }; type LicenseOption = "FREE" | "EXISTING"; const LicenseSelection = ( props: { value: LicenseOption; onChange: (value: LicenseOption) => void; onSubmit: (value: LicenseSelectionFormValues) => void; onSuccess?: ( data: RouterOutputs["viewer"]["deploymentSetup"]["update"], variables: RouterInputs["viewer"]["deploymentSetup"]["update"] ) => void; onPrevStep: () => void; onNextStep: () => void; } & Omit ) => { const { value: initialValue = "FREE", onChange, onSubmit, onSuccess, onPrevStep, onNextStep, ...rest } = props; const [value, setValue] = useState(initialValue); const { t } = useLocale(); const mutation = trpc.viewer.deploymentSetup.update.useMutation({ onSuccess, }); const [licenseKeyInput, setLicenseKeyInput] = useState(""); const [licenseTouched, setLicenseTouched] = useState(false); // Use TRPC query for validation const { data: licenseValidation, isLoading: checkLicenseLoading } = trpc.viewer.deploymentSetup.validateLicense.useQuery( { licenseKey: licenseKeyInput }, { enabled: licenseTouched && licenseKeyInput.trim().length > 0, } ); const schemaLicenseKey = useCallback( () => z.object({ licenseKey: z .string() .min(1, t("license_key_required")) .refine(() => !licenseTouched || (licenseValidation ? licenseValidation.valid : true), { message: licenseValidation?.message || t("invalid_license_key"), }), signatureToken: z.string().optional(), }), [licenseValidation, licenseTouched, t] ); const formMethods = useForm({ defaultValues: { licenseKey: "", signatureToken: "", }, resolver: zodResolver(schemaLicenseKey()), }); const handleSubmit = formMethods.handleSubmit((values) => { onSubmit(values); if (value === "EXISTING" && values.licenseKey) { mutation.mutate(values); } }); const { isDirty, errors } = useFormState(formMethods); const handleRadioChange = (newValue: LicenseOption) => { setValue(newValue); onChange(newValue); }; return (
{ e.preventDefault(); if (value === "FREE") { onSubmit({ licenseKey: "", signatureToken: "" }); } else { handleSubmit(); } }}> handleRadioChange(value as LicenseOption)}>

{t("agplv3_license")}

{t("free_license_fee")}

{t("forever_open_and_free")}

  • {t("required_to_keep_your_code_open_source")}
  • {t("cannot_repackage_and_resell")}
  • {t("no_enterprise_features")}

{t("enter_license_key")}

{t("enter_existing_license")}

{t("enter_your_license_key")}

{t("need_a_license")}{" "} {t("purchase_license")}

{value === "EXISTING" && (
( ) : licenseValidation?.valid && licenseTouched ? ( ) : undefined } color={errors.licenseKey ? "warn" : ""} onBlur={(e) => { setLicenseTouched(true); onBlur(); }} onChange={(e) => { setLicenseKeyInput(e.target.value); onChange(e.target.value); }} /> )} /> {errors.licenseKey && (

{errors.licenseKey.message}

)}
( ) => { onChange(e.target.value); formMethods.setValue("signatureToken", e.target.value); }} /> )} />

{t("signature_token_description")}

)}
{value === "EXISTING" ? ( ) : ( )}
); }; export default LicenseSelection;