diff --git a/src/Components/SignupPage/SignupPage.js b/src/Components/SignupPage/SignupPage.js index 5ec5057..52100b0 100644 --- a/src/Components/SignupPage/SignupPage.js +++ b/src/Components/SignupPage/SignupPage.js @@ -19,9 +19,11 @@ import { import { objectMap } from "../../Utils/Object"; import { signupFields } 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 Stripe from "stripe"; const SignupPage = () => { const navigate = useNavigate(); @@ -33,10 +35,14 @@ const SignupPage = () => { getFormDataDefaults(paymentfields) ); const [showPaymentModal, setShowPaymentModal] = useState(false); + const [showSelectPlan, setShowSelectPlan] = useState(true); + const [activeRadioOption, setActiveRadioOption] = useState("monthlyBasic"); const modalText = "Description of monthly and annual subscriptions"; - + const [selectedPlan, setSelectedPlan] = useState({}); // this could also go in App.js if needed in the future - const stripe = new Stripe('pk_test_51NNoasBi8p7FeGFrI5SfpM6HuNMoxwImx6NRKyKbgbt6OPxMxQDiZ9I1GqvDa9qUwB3D3jlJOng6MyjPppWofxzP00Exvr8dBy') + const stripe = new Stripe( + "pk_test_51NNoasBi8p7FeGFrI5SfpM6HuNMoxwImx6NRKyKbgbt6OPxMxQDiZ9I1GqvDa9qUwB3D3jlJOng6MyjPppWofxzP00Exvr8dBy" + ); const apiUrl = process.env.NODE_ENV === "development" @@ -62,6 +68,20 @@ const SignupPage = () => { } }; + const handleChangeRadioInput = (value) => { + const tempPlan = signupRadioFields.filter((field) => { + return field.value === value; + }); + console.log("tempPlan", tempPlan); + setSelectedPlan(tempPlan); + const temp = value; + setActiveRadioOption(temp); + }; + + signupRadioFields.map((option) => { + console.log(option.value); + }); + const validateData = () => { const newData = getValidatedFormData(data, signupFields); const hasErrors = isFormDataHasErrors(newData); @@ -127,6 +147,11 @@ const SignupPage = () => { const handleProceedToPayment = (e) => { e.preventDefault(); + setShowPaymentModal(true); + }; + + const handleOpenSelectPlan = (e) => { + e.preventDefault(); if (isBusy) { return; } @@ -135,15 +160,12 @@ const SignupPage = () => { if (dataValues === null) { return; } - - setShowPaymentModal(true); }; - - async function handleStripeAuthorization(user, paymentDataValues, customerDataValues) { - // Do: calls to Stripe API - // if success, return some truthy value or - // handle failure in handleSignup - + async function handleStripeAuthorization( + user, + paymentDataValues, + customerDataValues + ) { let error = false; let subscriptionId = null; let customerId = null; @@ -154,52 +176,53 @@ const SignupPage = () => { exp_month: paymentDataValues.cardExpirationMonth, exp_year: paymentDataValues.cardExpirationYear, cvc: paymentDataValues.cardCvvCode, - name: paymentDataValues.cardFirstName + ' ' + paymentDataValues.cardLastName, - } - }) + name: + paymentDataValues.cardFirstName + + " " + + paymentDataValues.cardLastName, + }, + }); try { let response = await fetch(`${apiUrl}/create-subscription`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", }, body: JSON.stringify({ - type: 'monthly', // TODO: replace this with the user-chosen value later when we have the UI for it + type: "monthly", // TODO: replace this with the user-chosen value later when we have the UI for it customerData: { email: customerDataValues.email, - name: customerDataValues.firstName + ' ' + customerDataValues.lastName, + name: + customerDataValues.firstName + " " + customerDataValues.lastName, }, token, }), - }) + }); - response = await response.json() + response = await response.json(); subscriptionId = response.subscriptionId; customerId = response.customerId; - console.log('response', response); + console.log("response", response); return { subscriptionId, customerId, - } - } - catch (error) { - console.log(error) + }; + } catch (error) { + console.log(error); error = true; } - if(error) { - return false + if (error) { + return false; } return { subscriptionId, customerId, - } - - return !error; + }; } const handleSignup = async (e) => { @@ -216,38 +239,43 @@ const SignupPage = () => { setIsBusy(true); - try { - const userCredential = await createUserWithEmailAndPassword( - auth, - dataValues.email, - dataValues.password - ); - const user = userCredential.user; + if (paymentDataValues && dataValues) { + try { + const userCredential = await createUserWithEmailAndPassword( + auth, + dataValues.email, + dataValues.password + ); + const user = userCredential.user; - const paymentResponse = await handleStripeAuthorization(user, paymentDataValues, dataValues); + const paymentResponse = await handleStripeAuthorization( + user, + paymentDataValues, + dataValues + ); - if(paymentResponse === false) { - // handle payment failure + if (paymentResponse === false) { + // handle payment failure + setIsBusy(false); + setNotice("Sorry, something went wrong. Please try again."); + return; + } else { + dataValues = { ...dataValues, ...paymentResponse }; + + await saveUserData(user.uid, dataValues); + navigate("/"); + } + } catch (error) { setIsBusy(false); setNotice( - "Sorry, something went wrong. Please try again." + error.message || "Sorry, something went wrong. Please try again." ); - return; } - else { - dataValues = {...dataValues, ...paymentResponse}; - - await saveUserData(user.uid, dataValues); - navigate("/"); - } - } catch (error) { - setIsBusy(false); - setNotice( - error.message || "Sorry, something went wrong. Please try again." - ); } }; + const showNoticeOnPage = "" !== notice && !showPaymentModal; + return (
@@ -281,7 +309,7 @@ const SignupPage = () => { ))} ))} - + { /> - + { className="primary-button signup-proceed" type="button" size="lg" - onClick={handleProceedToPayment} + onClick={handleOpenSelectPlan} disabled={isBusy} - labelText="Proceed to Payment" + labelText="Select A Plan" /> -
- - Go to login - -
- {"" !== notice && ( + {showNoticeOnPage ? ( <>

{notice}
+ ) : ( + <> )}
+ {showSelectPlan ? ( +
+
+
+
+ Select your subscription plan +
+
+
+ {signupRadioFields?.map((option, i) => ( + + ))} +
+
+
+
+
Order summary
+
{`{subVar} subscription type`}
+
{`{subVar} subscription mini description`}
+
{`Total billed today: {subVar} `}
+
Plus aplicable sales tax -toooltip
+
+
+
+
+
+ ) : ( + <> + )} {showPaymentModal ? ( { handleChangePaymentInput={handleChangePaymentInput} handleSignup={handleSignup} modalText={modalText} + notice={notice} + setNotice={setNotice} /> ) : ( <> diff --git a/src/Constants/Fields/RadioFields.js b/src/Constants/Fields/RadioFields.js new file mode 100644 index 0000000..6866b88 --- /dev/null +++ b/src/Constants/Fields/RadioFields.js @@ -0,0 +1,26 @@ +export const signupRadioFields = [ + { + name: "Monthly - basic", + label: "Monthly - basic", + value: "monthlyBasic", + description: "Generate 1 document per month", + details: "Billed every month", + price: 89, + }, + { + name: "Monthly - pro", + label: "Monthly - pro", + value: "monthlyProPlan", + description: "Generate up to 3 documents per month", + details: "Billed every three months. A xxx percent savings", + price: 159, + }, + { + name: "Annual - unlimted annual", + label: "Annual - unlimited annual", + value: "annualUnlimited", + description: "Generate unlimited documents. Billed annualy", + details: "Billed annualy. A xxx percent savings", + price: 1489, + }, +]; diff --git a/src/Constants/Fields/SignupFields.js b/src/Constants/Fields/SignupFields.js index 4eeb216..0c9d58d 100644 --- a/src/Constants/Fields/SignupFields.js +++ b/src/Constants/Fields/SignupFields.js @@ -31,7 +31,13 @@ export const signupFields = { }, barNumber: { required: true, label: "Bar Number", maxLength: 45 }, practiceArea: { required: true, label: "Practice Area", maxLength: 45 }, - email: { required: true, label: "Email", maxLength: 45, type: "email" }, + email: { + required: true, + label: "Email", + maxLength: 45, + type: "email", + inputWidth: "80%", + }, password: { required: true, label: "Password", diff --git a/src/Utils/Form.js b/src/Utils/Form.js index 0ac9d9e..c719043 100644 --- a/src/Utils/Form.js +++ b/src/Utils/Form.js @@ -84,6 +84,11 @@ export const getValidatedFormData = (data, fields) => }, data); export const handleFormDataChange = (e, name, data, fields) => { + console.log("fields", fields); + if (!fields) { + return; + } + const value = (typeof e?.target?.value === "undefined" ? e.value : e.target.value) || ""; const field = fields[name]; diff --git a/src/pageElements/Radio.js b/src/pageElements/Radio.js index e4313cb..20b3e5e 100644 --- a/src/pageElements/Radio.js +++ b/src/pageElements/Radio.js @@ -1,23 +1,73 @@ +import { CircleFill, Circle } from "react-bootstrap-icons"; +import "../styles/radio.scss"; -const Radio = ({ - rightLabel, - leftLabel, - containerClassName, - labelClassName, - ...props -}) => { +const Radio = (props) => { + console.log("hello"); + const { + name, + description, + onClick, + value, + price, + disabled, + activeRadioOption, + details, + } = props; + const classCheckbox = "checkbox"; + const classOption = "option"; + console.log("value, activeRadioOption", value, activeRadioOption); return ( -
- +
+
!disabled && onClick && onClick(value)} + > + {value == activeRadioOption ? ( + <> +
+
+
+ +
+
{`${name}`}
+
+
{`${price}`}
+
+
+ +
+
+
+ {" "} + {`${description}`}{" "} +
+
{`${details}`}
+
+
+ + ) : ( + <> +
+
+
+ +
+
{`${name}`}
+
+
{`${price}`}
+
+
+
+
{`${description}`}
+
{`${details}`}
+
+
+ + )} +
); }; export default Radio; - -// diff --git a/src/pageElements/Radiogroup.js b/src/pageElements/Radiogroup.js index a05a790..1ecd057 100644 --- a/src/pageElements/Radiogroup.js +++ b/src/pageElements/Radiogroup.js @@ -11,7 +11,7 @@ const Radiogroup = (props) => { onClick, value, options, - disabled + disabled, } = props; const classCheckbox = "checkbox"; const classOption = "option"; @@ -90,7 +90,3 @@ const Radiogroup = (props) => { */ export default Radiogroup; - -/* - - */ diff --git a/src/styles/radio.scss b/src/styles/radio.scss new file mode 100644 index 0000000..a99f924 --- /dev/null +++ b/src/styles/radio.scss @@ -0,0 +1,49 @@ +.radio-circle-container { + display: flex; + flex-direction: column; + background-color: #fff; + height: 160px; + margin: 10px 8px 0px 8px; + border-radius: 5px; + border: 1px solid #d4d4d4; +} + +.radio-circle-top { + height: 40px; + display: flex; + flex-direction: row; +} + +.radio-circle-lower { + display: flex; + flex-direction: column; + margin-left: 18px; + padding-left: 26px; +} + +.radio-circle-box { + height: 40px; + margin: 12px 8px; +} + +.radio-name-box { + height: 40px; + width: 50%; + font-family: var(--main-font); + font-family: Roboto; + font-weight: 500; + letter-spacing: 0.05rem; + margin: 13px 8px; +} + +.radio-price-box { + display: flex; + flex-direction: row-reverse; + margin: 16px 8px; + width: 30%; +} + +.radio-price { + width: 20px; + float: right; +} diff --git a/src/styles/signup.scss b/src/styles/signup.scss index 5fbd148..941400a 100644 --- a/src/styles/signup.scss +++ b/src/styles/signup.scss @@ -32,12 +32,21 @@ font-size: 2rem; } +.signup-subheader-text { + letter-spacing: -0.6px; + font-weight: 400; + font-size: 1.7rem; + margin-left: 5px; + margin-top: 6px; +} + .signup-form { width: 880px; } .signup-button-box { width: 100%; + margin-bottom: 24px; display: flex; flex-direction: column; align-items: flex-end; @@ -46,3 +55,70 @@ .signup-proceed { width: 160px; } + +.select-plan-container { + display: flex; + flex-direction: row; + margin-top: 24px; + width: 920px; + height: 600px; +} + +.select-sub-left { + width: 60%; + border-radius: 10px; + background-color: rgb(240, 247, 250); + margin-right: 8px; + border: 1px solid #e9e9e9; + padding: 6px; +} + +.select-sub-right { + width: 40%; + border-radius: 10px; + background-color: rgb(240, 247, 250); + margin-left: 8px; + border: 1px solid #e9e9e9; + padding: 6px; +} + +.signup-radio-wrapper { + background-color: #fff; + display: flex; + flex-direction: column; +} + +.signup-option-div { + display: flex; + flex-direction: column; +} + +.radio-group-box { + display: flex; + flex-direction: column; + padding: 6px; + width: 100%; + height: 300px; +} + +.select-plan-summary-box { + display: flex; + flex-direction: column; + height: 250px; + width: 100%; + border-radius: 10px; + background-color: #fff; + border: 1px solid #e9e9e9; + padding: 6px; +} + +.selectplan-payment-button-wrapper { + display: flex; + flex-direction: row-reverse; + margin: 6px; + padding: 6px; +} + +.signup-option { + width: 100% !important; +}