Merge pull request #147 from kjannette/pulla

Pulla
This commit is contained in:
S Jannette
2024-03-10 22:33:05 -05:00
committed by GitHub
3 changed files with 72 additions and 679 deletions

View File

@@ -137,7 +137,7 @@ function App() {
/> />
<Route <Route
exact exact
path="/docedit/:documentId/:responseGenerations/:caseId/:documentType" path="/docedit/:documentId/:caseId"
element={ element={
<PrivateRoute> <PrivateRoute>
<DocEditPage /> <DocEditPage />

View File

@@ -134,8 +134,7 @@ const CaseDetailsPage = () => {
const handleNavigate = (docId, caseId) => { const handleNavigate = (docId, caseId) => {
console.log("handle navigate fired docId", docId); console.log("handle navigate fired docId", docId);
const responseGenerations = 1; navigate(`/docedit/${docId}/${caseId}`);
navigate(`/docedit/${docId}/${responseGenerations}/${caseId}`);
}; };
const handleNavEdit = (documentId, caseId) => { const handleNavEdit = (documentId, caseId) => {

View File

@@ -22,184 +22,68 @@ import LoadingSpinner from "../../pageElements/LoadingSpinner";
import { docEditCopy } from "../../Constants/Copy/docEditCopy.js"; import { docEditCopy } from "../../Constants/Copy/docEditCopy.js";
import "../../styles/docedit-page.scss"; import "../../styles/docedit-page.scss";
const DocEditPage = () => { const DocEditPage = (props) => {
const { documentId, responseGenerations, caseId, documentType } = useParams(); const { documentId, caseId } = useParams();
const navigate = useNavigate();
const [parsedRogs, setParsedRogs] = useState();
const [responses, setResponses] = useState([1]);
const [fetchedCase, setFetchedCase] = useState();
const [showInputEle, setShowInputEle] = useState(true);
const [document, setDocument] = useState(null); const [document, setDocument] = useState(null);
const [docType, setDocType] = useState(null);
const [fetchedCase, setFetchedCase] = useState(null);
const [parsedRogs, setParsedRogs] = useState(null);
const [docLoaded, setDocLoaded] = useState(false);
const { appState } = useContext(AppContext); const { appState } = useContext(AppContext);
const { group } = appState; const { group } = appState;
const appUserId = group ? group.appUserId : null; const appUserId = group ? group.appUserId : null;
const [docId, setDocId] = useState(documentId);
const [saveDocumentId, setSaveDocumentId] = useState("");
const [showSaveModal, setShowSaveModal] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [isReport, setIsReport] = useState(false);
const [issueText, setIssueText] = useState("");
const [showErrorModal, setShowErrorModal] = useState(false);
const [responsesCreated, setResponsesCreated] = useState(
parseInt(responseGenerations)
);
const [index, setIndex] = useState(0);
const [isBusy, setIsBusy] = useState(false);
const fbUserId = group ? group.fbAuthUid : null;
// For document generation:
const state = group?.state[0] ? group.state[0].code : "ny";
const lawFirm = group ? group?.firm : null;
const streetAdd = group ? group?.streetAddress : null;
const city = group ? group?.city : null;
const usState = group?.state[0] ? group?.state[0].code : "ny";
const zipCode = group ? group?.zipCode : null;
const telephone = group ? group?.telephone : null;
const apiUrl = const apiUrl =
process.env.NODE_ENV === "development" process.env.NODE_ENV === "development"
? process.env.REACT_APP_API_DEV ? process.env.REACT_APP_API_DEV
: process.env.REACT_APP_API_PROD; : process.env.REACT_APP_API_PROD;
const displayCopy = async function getParsedRequests(docId, docType) {
state === "ny"
? docEditCopy.NewYork
: state === "nj"
? docEditCopy.NewJersey
: docEditCopy.NewYork;
const headerPicker = () => {
switch (state) {
case "ny":
return (
<NewYorkCaption
displayCopy={displayCopy}
fetchedCase={fetchedCase}
onScrollClick={onScrollClick}
/>
);
case "nj":
return (
<NewJerseyCaption
displayCopy={displayCopy}
fetchedCase={fetchedCase}
onScrollClick={onScrollClick}
/>
);
case "fl":
return (
<FloridaCaption
displayCopy={displayCopy}
fetchedCase={fetchedCase}
onScrollClick={onScrollClick}
/>
);
default:
return (
<NewYorkCaption
displayCopy={displayCopy}
fetchedCase={fetchedCase}
onScrollClick={onScrollClick}
/>
);
}
};
const headerString =
documentType === "interrogatories" ? (
"Response to Interrogatories"
) : documentType === "admissions" ? (
"Response to Request for Admissions"
) : documentType === "production" ? (
"Response to Request for Production"
) : documentType === "combined-numbered" ? (
"Response to Interrogatories and Request for Production"
) : (
<></>
);
const servingParty =
fetchedCase?.clientPosition === "Defendant"
? fetchedCase?.plaintiffParties
: fetchedCase?.defendantParties;
const messages = [
"Generating responses. Please be patient, this may take several minutes.",
];
/*
* GET docuement data from Firebase
* */
useEffect(() => {
if (!appUserId || !docId) {
setDocument(null);
return;
}
try { try {
getCase(caseId); const response = await fetch(
getDocument(); `${apiUrl}/getParsedRequests/${documentId}/${docType}`,
{
method: "GET",
}
);
const res = await response.json();
console.log("res", res);
const req = res[0].requests;
if (req.length > 1) {
setParsedRogs(req);
}
} catch (err) { } catch (err) {
console.log("Error:", err); console.log("Error occured GET parsed req:", err);
} }
}, [appUserId, docId, caseId]); }
/* async function getDocument(docId) {
* GET parsed requests. try {
* GET completions if already generated const docRef = doc(db, "documents", `${docId}`);
*/ const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
useEffect(() => { const bar = docSnap.data();
if (!documentId || !documentType) { if (bar.docType) {
return; console.log(bar.docType);
} let zib = bar.docType;
// TODO: possible *BUG* sometimes sends network req to gen repsonses after first (maybe state is not updating?) console.log("zib", zib);
getParsedRequests(documentId, documentType); getz(docId, zib);
if (responsesCreated > 0) {
getCompletions(documentId)
.then((data) => {
const resp = data[0].responses.map((item, index) => {
// NEVER CHANGE THIS:
return { showInputEle: false, resp: item.text, index: index };
});
setResponses(resp);
})
.catch((err) => console.log(err));
}
}, [documentId]);
/*
* If response completions = 0, generate responses
*/
useEffect(() => {
if (responsesCreated > 0) {
return;
}
if (responsesCreated < 1) {
if (documentType == "combined-numbered") {
try {
const res = generateResponsesCombined(documentId);
} catch (err) {
console.log(err);
} }
} else { } else {
try { console.log("DB item does not exist");
const res = generateResponses(documentId);
} catch (err) {
console.log(err);
}
} }
} catch (error) {
console.log(`A system error has occurred: ${error}`);
} }
}, [responsesCreated, documentId]); }
async function getCase(parentCaseId) { async function getCase(caseId) {
try { try {
const docRef = doc(db, "cases", `${parentCaseId}`); const docRef = doc(db, "cases", `${caseId}`);
const docSnap = await getDoc(docRef); const docSnap = await getDoc(docRef);
if (docSnap.exists()) { if (docSnap.exists()) {
const _case = docSnap.data(); const _case = docSnap.data();
_case.id = docSnap._key.path.segments[1]; _case.id = docSnap._key.path.segments[1];
console.log("_case", _case);
setFetchedCase(_case); setFetchedCase(_case);
} else { } else {
console.log("DB item does not exist"); console.log("DB item does not exist");
@@ -209,537 +93,47 @@ const DocEditPage = () => {
} }
} }
function getDocument() { async function getz(docId, zib) {
const docRef = doc(db, "documents", `${docId}`); console.log("zibbbt", zib);
const unsub = onSnapshot(docRef, (snapshot) => {
if (snapshot.exists() && snapshot.data().ownerId === appUserId) {
setDocument({ ...snapshot.data(), documentId: snapshot.id });
} else {
setDocument(null);
}
});
return unsub;
}
async function getParsedRequests(documentId) {
if (documentId) {
const docType = String(documentType);
try {
const response = await fetch(
`${apiUrl}/getParsedRequests/${documentId}/${docType}`,
{
method: "GET",
}
);
const res = await response.json();
const req = res[0].requests;
if (req.length > 1) {
setParsedRogs(req);
}
} catch (err) {
console.log("Error occured:", err);
}
}
}
async function getCompletions(docId) {
const docType = String(documentType);
const response = await fetch(`${apiUrl}/completions/${docId}/${docType}`, {
method: "GET",
});
const req = await response.json();
return req;
}
async function generateResponsesCombined(documentId) {
if (responsesCreated > 0) {
return;
}
const docType = String(documentType);
let mode;
//TODO: remove isRequests var if not goign to use
const isRequests = false;
console.log(
"generateResponsesCombined docmentId docType",
documentId,
docType
);
try { try {
setIsLoading(true); fetch(`${apiUrl}/v1/get-parsed-requests/${documentId}/${zib}`, {
fetch( method: "GET",
`${apiUrl}/genResponseFromArrayCombined/${documentId}/${docType}/${isRequests}`,
{
method: "GET",
}
)
.then(function (response) {
return response.json();
})
.then((data) => {
console.log("data in genResponseFromArrayCombined", data);
const respArray = data[0].responses;
const result = respArray?.map((item, index) => {
let obj = {};
obj["showInputEle"] = false;
obj["resp"] = item.text;
obj["index"] = index;
return obj;
});
setResponses(result);
updateRespGenerationCount(documentId);
updateUserAccountDocsGenerated(fbUserId);
setIsLoading(false);
})
.catch((err) => console.log(err));
} catch (err) {
console.log("err", err);
}
}
async function generateResponses(documentId) {
if (responsesCreated > 0) {
return;
}
const docType = String(documentType);
let mode;
//TODO: remove isRequests var
const isRequests = false;
try {
setIsLoading(true);
fetch(
`${apiUrl}/genResponseFromArray/${documentId}/${docType}/${isRequests}`,
{
method: "GET",
}
)
.then(function (response) {
return response.json();
})
.then((data) => {
console.log("data in genResponseFromArray ", data);
const respArray = data[0].responses;
const result = respArray?.map((item, index) => {
let obj = {};
obj["showInputEle"] = false;
obj["resp"] = item.text;
obj["index"] = index;
return obj;
});
setResponses(result);
updateRespGenerationCount(documentId);
setIsLoading(false);
})
.catch((err) => console.log(err));
} catch (err) {
console.log("err", err);
}
}
async function postEditedResponses() {
let obj = {};
obj["type"] = documentType;
obj["id"] = docId;
obj["requests"] = responses;
const data = JSON.stringify(obj);
try {
const response = await fetch(`${apiUrl}/v1/store-edited-completions`, {
method: "POST",
headers: { "Content-Type": "application/json" },
json: true,
body: data,
});
const res = response;
return res;
} catch (error) {
console.error("Error sending responses to the server:", error);
}
}
async function createAndReturnDocx() {
setIsBusy(true);
const response = await handleCreateDocx();
if (response.status === 200) {
setTimeout(getDocx, 5000);
setTimeout(cleanUpDocx, 10000);
} else {
setShowErrorModal(true);
}
setIsBusy(false);
}
async function cleanUpDocx() {
const docId = documentId;
const reqType = documentType;
fetch(`${apiUrl}/cleanUpDocx/${docId}/${reqType}`, {
method: "GET",
})
.then((response) => {
console.log(response);
}) })
.catch((err) => { .then(function (response) {
console.log(err); return response.json();
}); })
} .then((data) => {
const respArray = data[0].responses;
async function getDocx() { const result = respArray?.map((item, index) => {
const docId = documentId; let obj = {};
const reqType = documentType; obj["showInputEle"] = false;
fetch(`${apiUrl}/getDocx/${docId}/${reqType}`, { obj["resp"] = item.text;
method: "GET", obj["index"] = index;
}).then((response) => { return obj;
response.blob().then((blob) => { });
let url = window.URL.createObjectURL(blob); setParsedRogs(result);
let a = window.document.createElement("a"); console.log("parsedRogs", parsedRogs);
a.href = url; });
a.download = `${reqType}-repsonse.docx`; } catch (err) {
a.click(); console.log("Error occured:", err);
});
});
}
async function handleCreateDocx() {
// TODO: compare to see if any changes made before gen, save those
const docId = documentId;
const leadAttorneys = fetchedCase?.leadAttorneys
? fetchedCase?.leadAttorneys
: null;
const reqType = documentType;
const captionOne = fetchedCase?.caption;
const captionTwo = fetchedCase?.captionTwo;
const caseNum = fetchedCase?.caseNumber;
const plaintiffs = fetchedCase?.plaintiffParties;
const defendants = fetchedCase?.defendantParties;
const venued = fetchedCase?.venue;
const juris = fetchedCase?.jurisdiction;
const judge = fetchedCase?.judge;
const clientPosition = fetchedCase?.clientPosition
? fetchedCase?.clientPosition
: null;
try {
const response = await fetch(`${apiUrl}/genDocx/${docId}/${reqType}`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
caseCaption1: captionOne,
caseCaption2: captionTwo,
caseNumber: caseNum,
clientPosition: clientPosition,
defendant: defendants,
firm: lawFirm,
firmCity: city,
firmState: usState.code,
firmStreetAddress: streetAdd,
firmZip: zipCode,
judge: judge,
jurisdiction: juris,
leadAttorneys: leadAttorneys,
plaintiff: plaintiffs,
state: state,
tel: telephone,
venue: venued,
}),
});
return response;
} catch (error) {
console.error("Error sending responses to the server:", error);
} }
} }
useEffect(() => {
async function updateUserAccountDocsGenerated(fbUserId) { if (!documentId) {
await updateDoc(doc(db, "users", fbUserId), {
docsGenerated: increment(1),
});
}
async function updateRespGenerationCount(docId) {
if (!docId) {
return; return;
} }
await updateDoc(doc(db, "documents", docId), { getDocument(documentId);
responseGenerations: increment(1), }, [documentId]);
});
setResponsesCreated((responsesCreated) => responsesCreated + 1);
}
function saveDocument(documentId) { useEffect(() => {
setSaveDocumentId(documentId); if (!caseId) {
setShowSaveModal(!showSaveModal); return;
}
async function postEditedResponses() {
let obj = {};
obj["type"] = "INTERROGATORY";
obj["id"] = docId;
obj["requests"] = responses;
const data = JSON.stringify(obj);
try {
const response = await fetch(`${apiUrl}/storeeditedcompletions`, {
method: "POST",
headers: { "Content-Type": "application/json" },
json: true,
body: data,
});
const res = response;
return res;
} catch (error) {
console.error("Error sending responses to the server:", error);
} }
} getCase(caseId);
getDocument(documentId);
}, [caseId, documentId]);
const handleBlur = (e, i) => { return <div>Doc Edit</div>;
const newSelectedResponses = responses?.map((r) => {
if (r.index === i) {
return {
...r,
showInputEle: !showInputEle,
};
}
return r;
});
setResponses(newSelectedResponses);
};
const handleFocus = (arg, i) => {
const newSelectedResponses = responses?.map((r) => {
if (r.index === i) {
return {
...r,
showInputEle: !showInputEle,
};
}
return r;
});
setResponses(newSelectedResponses);
};
const handleEditValue = (e, i) => {
const editingRes = responses?.map((r) => {
if (r.index === i) {
return {
...r,
resp: e.target.value,
};
}
return r;
});
setResponses(editingRes);
};
const handleBack = () => {
navigate(`/documents`);
};
const handleCancelSave = () => {
setShowSaveModal(false);
};
const handleSave = () => {
postEditedResponses();
setShowSaveModal(false);
};
const handleConfirmSave = () => {
setShowSaveModal(true);
};
const handleReport = () => {
setShowSaveModal(false);
setIsReport(false);
};
const handleConfirmReport = () => {
setShowSaveModal(true);
setIsReport(true);
};
async function reportDoc() {
const data = {
documentId: documentId,
caseId: caseId,
appUserId: appUserId,
issueDescription: issueText,
};
try {
const reportRef = collection(db, "supportrequests");
await setDoc(doc(reportRef, documentId), data);
} catch (err) {
console.log("Error saving case to db:", err);
}
}
const onScrollClick = () => {
const bottom = window.document.scrollingElement.scrollHeight;
const place = window.scrollY;
if (place > bottom / 2) {
window.scrollTo({ top: 0, behavior: "smooth" });
} else if (place < bottom / 2) {
window.scrollTo({ top: bottom, behavior: "smooth" });
}
};
const numberingContent = (i) => {
let numText;
if (documentType === "interrogatories") {
numText = "INTERROGATORY NO..";
} else if (documentType === "admissions") {
numText = "REQUEST FOR ADMISSION NO.";
} else if (documentType === "production") {
numText = "REQUEST FOR PRODUCTION NO.";
} else {
numText = "REQUEST NO.";
}
return <div className="numbering-container">{`${numText}${i + 1} `}</div>;
};
const respondent =
fetchedCase?.clientPosition == "Defendant"
? fetchedCase?.defendantParties
: fetchedCase?.plaintiffParties;
console.log("responses", responses);
console.log("parsedRogs", parsedRogs);
const editingContent = () => {
return (
<>
<div> {headerPicker()}</div>
<div className="doc-editing-wrapper">
<div className="pleading-header">{headerString}</div>
<div>
{displayCopy.prelimaryStatement(
documentType,
respondent,
servingParty
)}
</div>
<div className="doc-editing-sub-wrapper">
{parsedRogs?.map((rog, i) => (
<div className="req-item-outer-div">
<div className="request-text-up">
{numberingContent(i)}
{rog?.text}
</div>
<div className="req-item-inner-div">
<EditElement
value={
responses && responses.length > 2
? // NEVER CHANGE THIS
responses[i].resp
: null
}
setShowInputEle={setShowInputEle}
showInputEle={
responses && responses.length > 2
? responses[i].showInputEle
: null
}
handleFocus={handleFocus}
handleEditValue={handleEditValue}
handleBlur={handleBlur}
i={i}
/>
</div>
</div>
))}
<div
className="docedit-report-container"
onClick={() => handleConfirmReport()}
>
<div className="docedit-report-link">Report an issue</div>
</div>
<div className="doc-editing-button-container">
<div className="generate-button-box">
{/* TODO: add tooltip: "This will save the document and create a .docx file that will (be downloaded? saved somewhere?" */}
<Button
className="primary-button create-gen-button"
onClick={createAndReturnDocx}
labelText={"Create .docx File"}
/>
</div>
<div className="details-button-box">
<div>
<Button
className="pt-2 pb-2 mr-4 secondary-button edit-back-button"
onClick={handleBack}
labelText="Back To Documents Page"
/>
</div>
<div>
<Button
className="pt-2 pb-2 mr-2 primary-button"
onClick={handleConfirmSave}
labelText="Save Changes"
/>
</div>
</div>
</div>
</div>
</div>
{showSaveModal && !isReport && documentId !== null ? (
<ConfirmModal
onCancel={handleCancelSave}
onConfirm={handleSave}
buttonLabelText="Confirm Save"
modalText={
"Are you sure? This will overrwrite any previously-saved edits."
}
/>
) : null}
{showSaveModal && isReport && documentId !== null ? (
<ConfirmModal
isReport={isReport}
onCancel={handleCancelSave}
onConfirm={handleReport}
buttonLabelText="Report Issue"
documentId={documentId}
caseId={caseId}
appUserId={appUserId}
issuetext={issueText}
setIssueText={setIssueText}
modalText={
"Date/time and document id automatically logged. Support will address this within 24 hours."
}
/>
) : null}
{showErrorModal ? (
<ConfirmModal
onCancel={() => setShowErrorModal(false)}
onConfirm={() => setShowErrorModal(false)}
buttonLabelText="Confirm"
modalText={
"There was a problem. Support was notified and will respond within 24 hours."
}
/>
) : null}
</>
);
};
const readyToEdit = fetchedCase && responses.length > 1;
return isLoading ? (
<LoadingSpinner message={messages[0]} />
) : isBusy ? (
<LoadingSpinner message={"Downloading .docx"} loaderType="MoonLoader" />
) : readyToEdit ? (
editingContent()
) : (
<div className="docedit-errstate-container">
<div className="nodocs-text-container">
<p>
{" "}
Response content for this document cannot be displayed at this time.
</p>
<p>Support has been notified and will respond within 24 hours.</p>
<Link to="/dashboard">Return to Dashboard</Link>
</div>
</div>
);
}; };
export default DocEditPage; export default DocEditPage;