import React, { useState } from "react"; import Col from "react-bootstrap/Col"; import Form from "react-bootstrap/Form"; import Row from "react-bootstrap/Row"; import Button from "../../pageElements/Button"; import { useParams } from "react-router-dom"; import { db, auth } from "../../firebase"; import { createUserWithEmailAndPassword } from "firebase/auth"; import { useNavigate } from "react-router-dom"; import Toggle from "../../pageElements/Toggle"; import TextInput from "../../pageElements/TextInput"; import { v4 as uuidv4 } from "uuid"; import { collection, setDoc, doc } from "firebase/firestore"; import { splitEvery } from "../../Utils/Array"; import { getFormDataDefaults, getValidatedFormData, handleFormDataChange, isFormDataHasErrors, } from "../../Utils/Form"; import { objectMap } from "../../Utils/Object"; import { signupFields, stateDataValues, } from "../../Constants/Fields/SignupFields"; import { paymentfields } from "../../Constants/Fields/PaymentFields"; import { signupRadioFields } from "../../Constants/Fields/RadioFields"; import PaymentModal from "../Modals/PaymentModal"; import Radio from "../../pageElements/Radio"; import "../../styles/signup.scss"; import Stripe from "stripe"; import { stripeApiKey } from "../../secrets"; const SignupPage = () => { const { isUpgrade, currentPlan } = useParams(); const navigate = useNavigate(); const [notice, setNotice] = useState(""); const fieldsChunkSize = 2; const [isBusy, setIsBusy] = useState(false); const [data, setData] = useState(getFormDataDefaults(signupFields)); const [paymentData, setPaymentData] = useState( getFormDataDefaults(paymentfields) ); const [showPaymentModal, setShowPaymentModal] = useState(false); const [showSelectPlan, setShowSelectPlan] = useState( isUpgrade ? true : false ); const [activeRadioOption, setActiveRadioOption] = useState("partner"); const [selectedPlan, setSelectedPlan] = useState([signupRadioFields[1]]); const [isAnnual, setIsAnnual] = useState(1); const stripe = new Stripe(stripeApiKey); const apiUrl = process.env.NODE_ENV === "development" ? process.env.REACT_APP_API_DEV : process.env.REACT_APP_API_PROD; const [showAddAccount, setShowAddAccount] = useState(false); const [numberOfAccountsToAdd, setNumberOfAccountsToAdd] = useState(); const handleChangeInput = (e, name) => { const newData = handleFormDataChange(e, name, data, signupFields); if (newData !== null) { setData(newData); } }; const handleChangeAccountSelect = (e, name) => { const num = e.target.value; const temp = Number(num); setNumberOfAccountsToAdd(temp); }; const handleChangePaymentInput = (e, name) => { const newPaymentData = handleFormDataChange( e, name, paymentData, paymentfields ); if (newPaymentData !== null) { setPaymentData(newPaymentData); } }; const handleChangeRadioInput = (value) => { const tempPlan = signupRadioFields.filter((plan) => { if (plan.value === value) { return plan; } }); setSelectedPlan(tempPlan); setActiveRadioOption(tempPlan[0].value); }; const vals = [ [1, 2, 3, 4, 5, 6, 7, 8], [1, 2], ]; const selectAdditionalAccountValues = selectedPlan[0].value === "partner" ? vals[1] : vals[0]; const validateUserData = () => { const newData = getValidatedFormData(data, signupFields); const hasErrors = isFormDataHasErrors(newData); setData(newData); return hasErrors ? null : objectMap(({ value }) => value, newData); }; const validatePaymentData = () => { const newPaymentData = getValidatedFormData(paymentData, paymentfields); const hasErrors = isFormDataHasErrors(newPaymentData); setPaymentData(newPaymentData); return hasErrors ? null : objectMap(({ value }) => value, newPaymentData); }; async function saveLeadData(dataValues) { const signupId = uuidv4(); const { firstName, lastName, firm, telephone, streetAddress, city, state, zipCode, barNumber, practiceArea, email, } = dataValues; const userData = { firstName, lastName, firm, telephone, streetAddress, city, state, zipCode, barNumber, practiceArea, email, signupId, }; try { const collecRef = collection(db, "signupLeads"); await setDoc(doc(collecRef, `${signupId}`), userData); } catch (error) { console.log(`Error saving new user to db: ${error}`); } } async function saveUserData(authId, dataValues, customerId, subscriptionId) { const appUserId = uuidv4(); const firmId = uuidv4(); const fbAuthUid = authId; const plan = selectedPlan; const docsAllowed = plan === "associate" ? 1 : plan === "partner" ? 3 : plan === "unlimited" ? 4000 : 0; const docsGenerated = 0; const { firstName, lastName, firm, telephone, streetAddress, city, state, zipCode, barNumber, practiceArea, email, } = dataValues; const userState = stateDataValues.filter((value) => { if (value.name === state) return value; }); const userData = { docsAllowed, docsGenerated, appUserId, fbAuthUid, firmId, firstName, lastName, firm, telephone, streetAddress, city, state: userState, zipCode, barNumber, practiceArea, email, customerId: customerId, subscriptionId: subscriptionId, subscriptionPlan: plan, }; try { const usersRef = collection(db, "users"); await setDoc(doc(usersRef, fbAuthUid), userData); } catch (error) { console.log(`Error saving new user to db: ${error}`); } } const handleProceedToPayment = (e) => { e.preventDefault(); setShowPaymentModal(true); }; const handleAdd = () => { //add accounts, close section setShowAddAccount(!showAddAccount); setShowPaymentModal(true); }; const handleOpenSelectPlan = (e) => { e.preventDefault(); if (isBusy) { return; } const dataValues = validateUserData(); if (dataValues === null) { return; } saveLeadData(dataValues); setShowSelectPlan(!showSelectPlan); }; const handleToggle = (e) => { if (isAnnual === e) { return; } else { setIsAnnual(e); } }; const handleAddAccounts = () => { setShowAddAccount(!showAddAccount); }; const handleCancelAdd = () => { setShowAddAccount(!showAddAccount); }; // ******************** STRIPE PAYMENT API CALL ******************** // async function handleStripeAuthorization( paymentDataValues, customerDataValues ) { const additionalAccounts = numberOfAccountsToAdd ? numberOfAccountsToAdd : 0; let error = false; let subscriptionId = null; let customerId = null; const token = await stripe.tokens.create({ card: { number: paymentDataValues.cardNumber, exp_month: paymentDataValues.cardExpirationMonth, exp_year: paymentDataValues.cardExpirationYear, cvc: paymentDataValues.cardCvvCode, name: paymentDataValues.cardFirstName + " " + paymentDataValues.cardLastName, }, }); const type = selectedPlan[0].value ? selectedPlan[0].value : null; const tempAnnual = isAnnual === 1 ? true : false; try { const response = await fetch(`${apiUrl}/create-subscription`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ planType: type, additionalAccounts: additionalAccounts, isAnnual: tempAnnual, customerData: { email: customerDataValues.email, name: `${customerDataValues.firstName} ${customerDataValues.lastName}`, }, token, }), }); const data = await response.json(); //subscriptionId = response.subscriptionId; //customerId = response.customerId; return { data, }; } catch (error) { console.log(error); return error; } } // ******************** END STRIPE PAYMENT API CALL ******************** // const handleSignup = async (e) => { e.preventDefault(); const paymentDataValues = validatePaymentData(); if (paymentDataValues === null) { return; } let dataValues = validateUserData(); if (dataValues === null) { return; } //const planType = determinePlan(isAnnual, activeRadioOption); setIsBusy(true); if (paymentDataValues && dataValues) { try { const data = await handleStripeAuthorization( paymentDataValues, dataValues ); const customerId = data.data.customerId; const subscriptionCreated = data.data.subscriptionCreated; const subscriptionPeriodStart = data.data.subscriptionPeriodStart; const subscriptionPeriodEnd = data.data.subscriptionPeriodEnd; const subscriptionId = data.data.subscriptionId; if (data === undefined) { setIsBusy(false); setNotice("Sorry, something went wrong. Please try again."); return; } else { const userCredential = await createUserWithEmailAndPassword( auth, dataValues.email, dataValues.password ); const user = userCredential.user; dataValues = { ...dataValues, ...data }; console.log( "customerId, subscriptionId in handleSignup right before saveUserData", customerId, subscriptionId ); await saveUserData( user.uid, dataValues, customerId, subscriptionCreated, subscriptionPeriodStart, subscriptionPeriodEnd, subscriptionId ); navigate("/dashboard"); } } catch (error) { setIsBusy(false); setNotice( error.message || "Sorry, something went wrong. Please try again." ); } } }; const showNoticeOnPage = "" !== notice && !showPaymentModal; const addAccountCopy = selectedPlan[0]?.value === "seniorPartner" ? "Add up to eight" : "Add up to two"; const showAddAccountBtn = selectedPlan[0].value === "seniorPartner" || selectedPlan[0].value === "partner"; const signupForm = (

Create A Novodraft Account

{!isUpgrade ? (
Start a free trial - save hours and draft better discovery
) : ( <> )}
{splitEvery( Object.keys(signupFields).slice(0, -2), fieldsChunkSize ).map((names, j) => ( {names.map((name, i) => ( handleChangeInput(e, name)} error={data[name].error} message={data[name].message} label={ data[name].value.length === 0 ? signupFields[name].label : "" } type={signupFields[name].type} values={signupFields[name].values} disabled={isBusy} /> ))} ))} handleChangeInput(e, "password")} disabled={isBusy} /> handleChangeInput(e, "confirmPassword")} disabled={isBusy} />
Free trial available!
{showNoticeOnPage ? ( <>

{notice}
) : ( <> )}
); const disableIndex = currentPlan === "associate" ? 1 : currentPlan === "partner" ? 2 : 0; return (
{!isUpgrade ? signupForm : <>} {showSelectPlan ? (
Select a subscription plan

Billed annually

Billed montly

{signupRadioFields?.map((option, index) => (
))}
{showAddAccount ? (
Add additional accounts

User profiles will be setup later

) : ( <> )}
{!showAddAccount ? ( <> {showAddAccountBtn ? (
) : ( <> )} {showPaymentModal ? ( ) : ( <> )} ); }; export default SignupPage; /* const userDataValues = { barNumber: "232323", city: "broolyn", email: "j@s.com", firm: "asdf", firstName: "ghghg", lastName: "hhhhh", password: "123344556", practiceArea: "dfdfdf", state: "New York", streetAddress: "123 Main", telephone: "(313) 555-5555", zipCode: "12345", }; */