diff --git a/src/Components/Account/PasswordReset.js b/src/Components/Account/PasswordReset.js index d43d83e..6db299b 100644 --- a/src/Components/Account/PasswordReset.js +++ b/src/Components/Account/PasswordReset.js @@ -1,5 +1,10 @@ import React, { useState, useEffect } from "react"; -import { checkActionCode, confirmPasswordReset, getAuth, sendPasswordResetEmail } from "firebase/auth"; +import { + checkActionCode, + confirmPasswordReset, + getAuth, + sendPasswordResetEmail, +} from "firebase/auth"; import Button from "../../pageElements/Button"; import { useSearchParams } from "react-router-dom"; @@ -75,122 +80,133 @@ const PasswordResetPage = () => { } finally { setIsBusy(false); } - } + }; const resetMode = mode === "resetPassword" ? "resetPassword" : "enterEmail"; return (
- {resetMode === "enterEmail" ? <> -
-

- Enter Account Email -

-
- {!done ? ( -
-
- setEmail(e.target.value)} - disabled={isBusy} - > - -
-
- {"" !== notice && ( -
- {notice} -
- )} -
-
-
-
- ) : null} - {done && ( -
-

A password reset link was sent.

+ {resetMode === "enterEmail" ? ( + <> +
+

+ Enter Account Email +

- )} - : null} - {resetMode === "resetPassword" ? <> -
-

- Enter New Password -

-
- {!done && isCodeValid !== null && isCodeValid ? ( -
-
- setPassword(e.target.value)} - disabled={isBusy} - > - + {!done ? ( + +
+ setEmail(e.target.value)} + disabled={isBusy} + > + +
+
+ {"" !== notice && ( +
+ {notice} +
+ )} +
+
+
+ + ) : null} + {done && ( +
+

+ A password reset link was sent. +

-
- setConfirmPassword(e.target.value)} - disabled={isBusy} - > - -
-
- {"" !== notice && ( -
- {notice} -
- )} -
-
-
- - ) : null} - {!done && isCodeValid !== null && !isCodeValid && ( -
-

Bad or already used password reset code.

+ )} + + ) : null} + {resetMode === "resetPassword" ? ( + <> +
+

+ Enter New Password +

- )} - {done && ( -
-

Password changed.

-
- )} - : null} + {!done && isCodeValid !== null && isCodeValid ? ( +
+
+ setPassword(e.target.value)} + disabled={isBusy} + > + +
+
+ setConfirmPassword(e.target.value)} + disabled={isBusy} + > + +
+
+ {"" !== notice && ( +
+ {notice} +
+ )} +
+
+
+
+ ) : null} + {!done && isCodeValid !== null && !isCodeValid && ( +
+

+ Bad or already used password reset code. +

+
+ )} + {done && ( +
+

Password changed.

+
+ )} + + ) : null}
diff --git a/src/Components/Case/CaseListPage.js b/src/Components/Case/CaseListPage.js index 274fe21..dcd7271 100644 --- a/src/Components/Case/CaseListPage.js +++ b/src/Components/Case/CaseListPage.js @@ -83,6 +83,7 @@ const CaseListPage = ({ perPage }) => {
); }; + const dropDownOptions = [ { label: "Case name a - z", value: "caption" }, { label: "Case name z - a", value: "caption2" }, @@ -159,11 +160,17 @@ const CaseListPage = ({ perPage }) => { ) : (
-

You have not created any cases yet.

+

Please create your first case.

- To get started, click "Create New Case" and enter case - information. + To create a discovery request or response, you will first enter + some basic information about the case they will pertain to - + i.e. the caption and case number.

+

+ Then, you will upload a document (i.e. interrogatories or a + complaint), for use in generating a request/response. +

+

Click "Create New Case" to get started.

{createNewButton()}
) diff --git a/src/Components/Dashboard/Dashboard.js b/src/Components/Dashboard/Dashboard.js index b7475e6..e1ec455 100644 --- a/src/Components/Dashboard/Dashboard.js +++ b/src/Components/Dashboard/Dashboard.js @@ -15,21 +15,26 @@ import { Typeahead } from "react-bootstrap-typeahead"; import { AppContext } from "../../Hooks/useContext/appContext.js"; import UploadModal from "../Modals/UploadModal.js"; import Button from "react-bootstrap/Button"; +import { getAuth } from "firebase/auth"; const Dashboard = () => { const size = window.innerWidth < 440; const [isMobile, setIsMobile] = useState(size); + const auth = getAuth(); const count = useRef(null); const navigate = useNavigate(); const [allCases, setAllCases] = useState(null); const [selectedCase, setSelectedCase] = useState(null); const [showModal, setShowModal] = useState(); const [docCount, setDocCount] = useState(); + const [isPromoFirstLogin, setIsPromoFirstLogin] = useState(true); const [responseCount, setResponseCount] = useState(); const { appState } = useContext(AppContext); const { group } = appState; const appUserId = group ? group.appUserId : null; const isDashboard = true; + console.log("group on dashbaord page", group); + console.log("auth in dashoabrd page", auth); useEffect(() => { if (count.current == null) { @@ -177,6 +182,31 @@ const Dashboard = () => {
{group.firm}
+ {isPromoFirstLogin ? ( + <> +
+
+
+
+ Welcome to Novodraft, attorney {group.lastName}. We are + excited to introduce you to our application. Review the + step-by-step user guide by clicking "How-to" in the navigation + bar. +
+
+ Your user name for login is:{" "} + {group.email}. Your + temporary password is{" "} + {group.tpe}. You + should change it now, by clicking here. +
+
+
+
+ +
+ + ) : null}
diff --git a/src/Components/Home/HomePage.js b/src/Components/Home/HomePage.js index 61a69a6..07f097b 100644 --- a/src/Components/Home/HomePage.js +++ b/src/Components/Home/HomePage.js @@ -1,284 +1,478 @@ -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { collection, setDoc, doc } from "firebase/firestore"; -import { db } from "../../firebase"; +import { db, auth } from "../../firebase"; import Button from "../../pageElements/Button"; import { v4 as uuidv4 } from "uuid"; import arrow from "../../Assets/Images/Arrow.png"; import { useNavigate } from "react-router-dom"; +import ConfirmModal from "../Modals/ConfirmModal"; +import { createUserWithEmailAndPassword } from "firebase/auth"; +import { stateDataValues } from "../../Constants/Fields/SignupFields"; import "../../styles/homepage.scss"; +import LoadingSpinner from "../../pageElements/LoadingSpinner"; const HomePage = () => { const navigate = useNavigate(); + const [showPromoModal, setShowPromoModal] = useState(false); + const [isBusy, setIsBusy] = useState(false); + const [notice, setNotice] = useState(""); - const handleNavigate = () => { - navigate("/signup"); + const apiUrl = + process.env.NODE_ENV === "development" + ? process.env.REACT_APP_API_DEV + : process.env.REACT_APP_API_PROD; + + async function saveUserData( + authId, + dataValues, + email, + password, + customerId, + subscriptionCreated, + subscriptionPeriodStart, + subscriptionPeriodEnd, + subscriptionId, + isPromotionalMebership = true, + docsAllowedPeMonth = 1 + ) { + if (!email || !password || !dataValues[0]) { + return; + } + const appUserId = uuidv4(); + const firmId = uuidv4(); + const fbAuthUid = authId; + const tpe = password; + let plan = "promo plan"; + let docsAllowedPerMonth; + + docsAllowedPerMonth = 1; + subscriptionId = uuidv4(); + plan = plan; + + const docsGenerated = 0; + + const { + firstName, + lastName, + firm, + telephone, + streetAddress, + city, + state, + zipCode, + barNumber, + practiceArea, + } = dataValues[0]; + + const userState = stateDataValues.filter((value) => { + if (value.name === state) return value; + }); + + const userData = { + docsAllowedPerMonth, + docsGenerated, + appUserId, + fbAuthUid, + firmId, + firstName, + lastName, + firm, + telephone, + streetAddress, + city, + state: userState, + zipCode, + barNumber, + practiceArea, + email, + tpe: tpe, + isPromotionalMebership, + isPromotionalFirstLogin: true, + customerId: customerId, + subscriptionId: subscriptionId, + subscriptionPlan: "flordia-spring-promo-plan", + subscriptionCreated: subscriptionCreated, + subscriptionPeriodStart: subscriptionPeriodStart, + subscriptionPeriodEnd: subscriptionPeriodEnd, + }; + + try { + const usersRef = collection(db, "users"); + const res = await setDoc(doc(usersRef, fbAuthUid), userData); + return res; + } catch (error) { + console.log(`Error saving new user to db: ${error}`); + } + } + + async function getFocusData(code) { + console.log("code in getFocusData", code); + try { + const response = await fetch(`${apiUrl}/v1/get-focused-data/${code}`, { + method: "GET", + }); + const res = await response.json(); + console.log("res in getFocusData", res); + return res; + } catch (err) { + console.log("Error in get rqst:", err); + } + } + + async function handleProcessPromoSubscription(code) { + console.log("code in handleProcessPromoSubscription", code); + setIsBusy(true); + setShowPromoModal(false); + if (!code) { + return; + } + const userData = await getFocusData(code); + console.log("userData in returned from getFocusData", userData); + const email = userData[0].email; + const password = userData[0].password; + if (email && password) { + console.log("123 email, password", email, password); + handlePromoSignup(userData, email, password); + } + } + + async function handlePromoSignup(dataValues, email, password) { + if (!email || !password) { + return; + } + + try { + const customerId = `${uuidv4()}-florida-spring-promo`; + const today = new Date(); + const subscriptionCreated = today; + const subscriptionPeriodStart = today; + console.log("subscriptionPeriodStart", subscriptionPeriodStart); + const subscriptionPeriodEnd = today; + const subscriptionId = uuidv4(); + + const userCredential = await createUserWithEmailAndPassword( + auth, + email, + password + ); + + const user = userCredential.user; + dataValues = { ...dataValues }; + const isPromotionalMebership = true; + console.log("userCredential", userCredential); + const res = await saveUserData( + user.uid, + dataValues, + email, + password, + customerId, + subscriptionCreated, + subscriptionPeriodStart, + subscriptionPeriodEnd, + subscriptionId, + isPromotionalMebership + ); + console.log("res from saveUserData in handlePromoSignup", res); + setIsBusy(false); + navigate("/dashboard"); + } catch (error) { + console.log("Error handling request", error, error.message); + setIsBusy(false); + setNotice("Sorry, something went wrong. Please try again."); + } + } + + const handleTryItButton = () => { + setShowPromoModal(true); }; const handleLogin = () => { navigate("/login"); }; + const handleCancelModal = () => { + setShowPromoModal(!showPromoModal); + navigate("/signup"); + }; + const handleDemo = () => { const supReq = null; navigate("/requestpage/supReq"); }; - return ( - <> -
-
+
+
+
+
+
+

Novodraft: Legal AI

+

Novodraft

+

AI-Assisted Legal Drafting

+

+ Draft documents faster and smarter +

+
+
+
+
Discovery requests
+
dramatically fast
+
+
Draft responses to
+
demands in minutes
+
+
+
+
+
+
+
+
+

+ Discovery requests done dramatically fast – discovery responses + ready in minutes. +

+

+ Reclaim hours every week. Spend time growing your practice, or + just get home by dinner. +

+
+
+
+
+
+
+ {/* Section 2 */} +
+
+
+
+

+ Made by Attorneys, for Attorneys +

+
+ +
+ image of a laptop computer +
+
+
+
+

Made by Attorneys, for Attorneys.

+
+

+ Legal tech developed by people that understand what you need. +

+
+ +

+ Novodraft understands the demands on your time. For example, + that discovery request on your desk. With a few clicks, and + Novodraft's AI assistant on the task, you can draft a + ready-to-serve response in minutes. It's as easy as uploading a + .pdf file. +

+

+ Novodraft cuts through a mire of rote tasks, but does much more + than automate. +

+

+ Intellidraft AI technology powers persuasive arguments and + boosts bland, boilerplate objections. Configurable for level of + authoritative citation and for infering factual context from + pleadings and briefs. Use it to augment your drafting as much or + as little as you prefer. +

+ +
+
+
+
+ {/* Section 3 */} +
+
+

+ AI-Powered Legal Drafting Technology{" "} +

+

+ Novo Drafting Technology +

+

+ Created by litigators to give you an edge. +

+
+
+ {/*********** CARD ONE *********** */} +
+
+ ai hand +
+
+
+
+

Discovery Requests

+
+
+
+ +
+

+ Generate interrogatories and requests for + production/admissions leveraging AI. +

+

+ Edit or add special language with tags. Concise yet + comprehensive demands, done in minutes. +

+
+
+
+ {/*********** CARD TWO *********** */} +
+
+ scales image +
+
+
+
+

Discovery Responses

+
+
+
+ +
+

+ Use Novodraft AI to quickly draft responses including + compelling arguments about what you withhold from disclosure. + Finish in minutes with a downloadable .docx file. +

+
+
+
+ {/*********** CARD THREE *********** */} +
+
+ +
+
+
+
+

Proactive Alerts

+
+
+
+
+

+ Your dashboard displays important deadlines, alerts, and can + be configured to auto-draft documents with reminders for tasks + such as service or hearings. +

+
+
+
+
+
+
+
-
-
-
-
-

Novodraft: Legal AI.

-

Novodraft

-

- AI-Assisted Legal Drafting -

-

- Draft documents faster and smarter. -

-
-
-
-
Discovery requests
-
dramatically fast
-
-
Draft responses to
-
demands in minutes
-
-
-
-
-
-
-
-
-

- Discovery requests done dramatically fast – discovery - responses ready in minutes -

-

- Reclaim hours every week. Spend time growing your practice, or - just get home by dinner. -

-
-
+
+
+
+

+ Questions about our services?

+ We're here to answer! +

+

+ Questions about our products and services? +

+

We're here to answer!

+
+ Novodraft will revolutionize your practice. +
+
+ Request a demo - let us show you how. +
+
+ Revolutionize your practice. +
+
Let us show you how.
+
+
+ +
-
- {/* Section 2 */} -
-
-
-
-

- Made by Attorneys, for Attorneys -

-
+
+
+ {showPromoModal ? ( + + ) : ( + <> + )} +
+ ); -
- image of a laptop computer -
-
-
-
-

Made by Attorneys, for Attorneys

-
-

- Legal tech built by people that get it. -

-
- -

- Novodraft understands the demands on your time. For example, - that discovery request on your desk. With a few clicks, and - Novodraft's AI assistant on the task, you can draft a - ready-to-serve response in minutes. It's as easy as uploading - a .pdf file. -

-

- Novodraft cuts through a mire of rote tasks, but does much - more than automate. -

-

- Intellidraft AI technology powers persuasive arguments and - boosts bland, boilerplate objections. Configurable for level - of authoritative citation and for infering factual context - from pleadings and briefs. Use it to augment your drafting as - much or as little as you prefer. -

- -
-
-
- - {/* Section 3 */} -
-
-

- AI-Powered Legal Drafting Technology{" "} -

-

- Novo Drafting Technology -

-

- Created by litigators to give you an edge. -

-
-
- {/*********** CARD ONE *********** */} -
-
- ai hand -
-
-
-
-

Discovery Requests

-
-
-
- -
-

- Generate discovery requests with AI at your service, edit or - add special language with tags. Concise yet comprehensive - demands, done in minutes and downloadable as .docx. -

-
-
-
- {/*********** CARD TWO *********** */} -
-
- scales image -
-
-
-
-

Discovery Responses

-
-
-
- -
-

- Novodraft's AI powers responses with compelling arguments - about what you choose to disclose and withhold. You'll - finish in minutes with a downloadable .docx file. -

-
-
-
- {/*********** CARD THREE *********** */} -
-
- -
-
-
-
-

Proactive Alerts

-
-
-
-
-

- Your dashboard displays important deadlines, alerts, and can - configure to auto-draft documents and remind you to serve - them. -

-
-
-
-
-
-
-
-
-
-
-

- Questions about our services?

- We're here to answer! -

-

- Questions about our products and services? -

-

We're here to answer!

-
-
- Novodraft will revolutionize your practice. -
-
- Request a demo - let us show you how. -
-
- Revolutionize your practice. -
-
Let us show you how.
-
-
- - -
-
-
-
-
- + return isBusy ? ( + + ) : ( + homeContent ); }; diff --git a/src/Components/Modals/ConfirmModal.js b/src/Components/Modals/ConfirmModal.js index 83be986..5611757 100644 --- a/src/Components/Modals/ConfirmModal.js +++ b/src/Components/Modals/ConfirmModal.js @@ -22,6 +22,7 @@ const ConfirmModal = ({ isPromoModal, cancelButtonText, }) => { + const [inputValue, setInputValue] = useState(""); const title = titleText ? titleText : "Confirmation"; return ( @@ -53,11 +54,11 @@ const ConfirmModal = ({ setIssueText(e.target.value)} + onChange={(e) => setInputValue(e.target.value)} label={ - issueText + inputValue ? "" : isPromoModal ? "Enter your promotional code" @@ -79,7 +80,7 @@ const ConfirmModal = ({