import { useDispatch, useSelector } from "react-redux"; import { submitProperty } from "../redux/features/propertySlice"; import { useState, useEffect } from "react"; import Navbar from "./Navbar"; import { toast } from "react-toastify"; import "react-toastify/dist/ReactToastify.css"; import FileBase64 from "react-file-base64"; import "../addproperty.css"; const Addproperty = () => { const [activeTab, setActiveTab] = useState("propertydetails"); const handleContinue = () => { if (activeTab === "propertydetails") setActiveTab("Images"); if (activeTab === "Images") setActiveTab("Accounting"); if (activeTab === "Accounting") setActiveTab("IAB"); if (activeTab === "IAB") setActiveTab("IAB"); }; const handleBack = () => { if (activeTab === "Images") setActiveTab("propertydetails"); if (activeTab === "Accounting") setActiveTab("Images"); if (activeTab === "IAB") setActiveTab("Accounting"); }; const dispatch = useDispatch(); const { status, error } = useSelector((state) => state.property); const { user } = useSelector((state) => ({ ...state.auth })); const renovationRiskOptions = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // Array of options const [formData, setFormData] = useState({ propertyTaxInfo: [ { propertytaxowned: "0", ownedyear: "0", taxassessed: "0", taxyear: "0" }, ], images: [{ title: "", file: "" }], googleMapLink: "", // Field for Google Maps link renovationRisk: null, purchaseCost: "0", costPaidAtoB: [ { title: "Closing Fees - Settlement Fee", price: "0" }, { title: "Closing Fees - Owner's Title Insurance", price: "0" }, { title: "Courier Fees", price: "0" }, { title: "Wire Fee", price: "0" }, { title: "E recording Fee", price: "0" }, { title: "Recording Fee", price: "0" }, { title: "Property Tax", price: "0" }, ], credits: [{ title: "Credits", price: "0" }], cashAdjustments: [{ title: "Cash Adjustments", price: "0" }], incidentalCost: [ { title: "Accounting Fees", price: "0" }, { title: "Bank Charges", price: "0" }, { title: "Legal Fees", price: "0" }, { title: "Property Taxes", price: "0" }, { title: "Travel Expenses", price: "0" }, ], carryCosts: [ { title: "Electricity", price: "0" }, { title: "Water and Sewer", price: "0" }, { title: "Natural Gas", price: "0" }, { title: "Trash and Recycling", price: "0" }, { title: "Internet and Cable", price: "0" }, { title: "Heating Oil/Propane", price: "0" }, { title: "HOA fees", price: "0" }, { title: "Dump fees", price: "0" }, { title: "Insurance", price: "0" }, { title: "Interest on Loans", price: "0" }, { title: "Loan Payment", price: "0" }, { title: "Property Taxes", price: "0" }, { title: "Security", price: "0" }, { title: "Real Estates fees", price: "0" }, ], renovationCost: [ { title: "Demolition: Removing existing structures or finishes", price: "0", }, { title: "Framing: Making structural changes or additions", price: "0" }, { title: "Plumbing: Installing or modifying plumbing systems", price: "0", }, { title: "Electrical: Updating wiring and fixtures", price: "0" }, { title: "HVAC: Installing or upgrading heating and cooling systems", price: "0", }, { title: "Insulation: Adding or replacing insulation", price: "0" }, { title: "Drywall: Hanging and finishing drywall", price: "0" }, { title: "Interior Finishes: Painting, flooring, cabinetry, and fixtures", price: "0", }, { title: "Exterior Work: Addressing siding, roofing, or landscaping, if applicable", price: "0", }, { title: "Final Inspections: Ensuring everything meets codes", price: "0", }, { title: "Punch List: Completing any remaining task", price: "0" }, ], sellingPriceBtoC: "0", costPaidOutofClosing: [ { title: "Buyers Agent Commission", price: "0" }, { title: "Sellers Agent Commission", price: "0" }, { title: "Home Warranty", price: "0" }, { title: "Document Preparation", price: "0" }, { title: "Excise Tax", price: "0" }, { title: "Legal Fees", price: "0" }, { title: "Wire Fees/courier Fees", price: "0" }, { title: "County Taxes", price: "0" }, { title: "HOA Fee", price: "0" }, { title: "Payoff of 1st Mortgage", price: "0" }, { title: "Payoff of 2nd Mortgage", price: "0" }, { title: "Payoff 3rd Mortgage", price: "0" }, ], adjustments: [{ title: "adjustments", price: "0" }], incomestatement: [ { title: "income statement", price: "0" }, { title: "income statement", price: "0" }, ], fundspriortoclosing: "0", shorttermrental: "0", OtherIncome: "0", InsuranceClaim: "0", LongTermRental: "0", FinancingCostClosingCost: "0", TradesinRenovations: [ { title: "Planning & Design", price: "0" }, { title: "Demolition & Cleanup", price: "0" }, { title: "Framing", price: "0" }, { title: "Rough-in Services", price: "0" }, { title: "Structural Repairs", price: "0" }, { title: "Insulation & Drywall", price: "0" }, { title: "Cabinetry & Countertops", price: "0" }, { title: "Fixtures & Appliances", price: "0" }, { title: "Flooring and Tiling", price: "0" }, { title: "Plumbing", price: "0" }, { title: "Electrical", price: "0" }, { title: "HVAC", price: "0" }, { title: "Painting", price: "0" }, { title: "Interior Finishes", price: "0" }, { title: "Exterior Work", price: "0" }, { title: "Final Inspections", price: "0" }, { title: "Punch List", price: "0" }, { title: "Staging", price: "0" }, ], IAB: [{ title: "IAB Title", URL: "Please enter URL" }], files: [{ title: "", file: "" }], }); const [submitted, setSubmitted] = useState(false); const handleImageChange = (file, index) => { console.log("File received:", file); // Debugging log to check the file object const updatedImages = [...formData.images]; updatedImages[index].file = file.base64; // store base64 format of image setFormData({ ...formData, images: updatedImages }); }; const handleAddImage = () => { setFormData({ ...formData, images: [...formData.images, { title: "", file: "" }], }); }; const handleDeleteImage = (index) => { const updatedImages = formData.images.filter((_, i) => i !== index); setFormData({ ...formData, images: updatedImages }); }; const handleImageTitleChange = (index, e) => { const updatedImages = [...formData.images]; updatedImages[index].title = e.target.value; setFormData({ ...formData, images: updatedImages }); }; const handleInputChange = (e, index, fieldName) => { const { name, value } = e.target; if (fieldName === "propertyTaxInfo") { const updatedPropertyTaxInfo = [...formData.propertyTaxInfo]; updatedPropertyTaxInfo[index][name] = value; setFormData({ ...formData, propertyTaxInfo: updatedPropertyTaxInfo }); } else { setFormData({ ...formData, [name]: value }); } }; const addPropertyTaxField = () => { setFormData({ ...formData, propertyTaxInfo: [ ...formData.propertyTaxInfo, { propertytaxowned: "", ownedyear: "", taxassessed: "", taxyear: "" }, ], }); }; const deletePropertyTaxField = (index) => { const updatedPropertyTaxInfo = formData.propertyTaxInfo.filter( (_, i) => i !== index ); setFormData({ ...formData, propertyTaxInfo: updatedPropertyTaxInfo }); }; const addCost = () => { setFormData((prevData) => ({ ...prevData, costPaidAtoB: [...prevData.costPaidAtoB, { title: "", price: "" }], })); }; const deleteCost = (index) => { const updatedCosts = formData.costPaidAtoB.filter((_, i) => i !== index); setFormData((prevData) => ({ ...prevData, costPaidAtoB: updatedCosts, })); }; // Function to handle changes to title and price const handleCostChange = (index, field, value) => { const updatedCosts = [...formData.costPaidAtoB]; updatedCosts[index][field] = value; setFormData((prevData) => ({ ...prevData, costPaidAtoB: updatedCosts, })); }; const handlePriceChange = (e, index) => { let value = e.target.value; // Remove the dollar sign before validating value = value.replace(/^\$/, "").trim(); // Remove '$' if it exists // Use a regular expression to allow only numbers and decimals const isNumber = /^\d*\.?\d*$/.test(value); // If valid number, update state, otherwise show the alert if (isNumber || value === "") { const updatedCosts = formData.costPaidAtoB.map((cost, i) => i === index ? { ...cost, price: value, isInvalid: false } // Reset isInvalid if valid number : cost ); setFormData({ ...formData, costPaidAtoB: updatedCosts }); } else { const updatedCosts = formData.costPaidAtoB.map((cost, i) => i === index ? { ...cost, isInvalid: true } // Keep isInvalid true for invalid input : cost ); setFormData({ ...formData, costPaidAtoB: updatedCosts }); } }; const calculateTotalPurchaseCosts = () => { const totalCostsFromArray = formData.costPaidAtoB.reduce((total, cost) => { const price = parseFloat(cost.price) || 0; // Convert price to number return total + price; }, 0); const purchaseCost = parseFloat(formData.purchaseCost) || 0; // Convert purchase cost to number return totalCostsFromArray + purchaseCost; // Return the total }; const addCredits = () => { setFormData((prevData) => ({ ...prevData, credits: [...prevData.credits, { title: "", price: "" }], })); }; const deleteCredits = (index) => { const updatedCredits = formData.credits.filter((_, i) => i !== index); setFormData((prevData) => ({ ...prevData, credits: updatedCredits, })); }; // Function to handle changes to credits title and price const handleCreditChange = (index, field, value) => { const updatedCredits = [...formData.credits]; updatedCredits[index][field] = value; setFormData((prevData) => ({ ...prevData, credits: updatedCredits, })); }; const handleCreditPriceChange = (e, index) => { const value = e.target.value; // Regular expression to allow only numbers and optional decimals const isNumber = /^\d*\.?\d*$/.test(value); // If valid number, update state, otherwise show the alert if (isNumber || value === "") { const updatedCredits = formData.credits.map((credit, i) => i === index ? { ...credit, price: value, isInvalid: false } // Reset isInvalid if valid number : credit ); setFormData({ ...formData, credits: updatedCredits }); } else { const updatedCredits = formData.credits.map((credit, i) => i === index ? { ...credit, isInvalid: true } // Set isInvalid true for invalid input : credit ); setFormData({ ...formData, credits: updatedCredits }); } }; const calculateTotalCredits = () => { return formData.credits.reduce((total, credits) => { const price = parseFloat(credits.price); return total + (isNaN(price) ? 0 : price); // Ensure only valid numbers are added }, 0); }; const calculateTotalPurchaseCostsWithCredits = () => { // Calculate total from costPaidAtoB array const totalCostsFromArray = formData.costPaidAtoB.reduce((total, cost) => { const price = parseFloat(cost.price) || 0; // Convert price to number return total + price; }, 0); // Calculate total from credits array const totalCreditsFromArray = formData.credits.reduce((total, credit) => { const price = parseFloat(credit.price) || 0; // Convert price to number return total + price; }, 0); // Convert purchase cost to number const purchaseCost = parseFloat(formData.purchaseCost) || 0; return totalCostsFromArray + totalCreditsFromArray + purchaseCost; }; const addcashAdjustments = () => { setFormData((prevData) => ({ ...prevData, cashAdjustments: [...prevData.cashAdjustments, { title: "", price: "" }], })); }; const deletecashAdjustments = (index) => { const updatedcashAdjustments = formData.cashAdjustments.filter( (_, i) => i !== index ); setFormData((prevData) => ({ ...prevData, cashAdjustments: updatedcashAdjustments, })); }; // Function to handle changes to cashAdjustments title and price const handlecashAdjustmentsTitle = (index, field, value) => { const updatedcashAdjustments = [...formData.cashAdjustments]; updatedcashAdjustments[index][field] = value; setFormData((prevData) => ({ ...prevData, cashAdjustments: updatedcashAdjustments, })); }; const handlecashAdjustmentsCostChange = (e, index) => { const value = e.target.value; // Regular expression to allow only numbers and optional decimals const isNumber = /^\d*\.?\d*$/.test(value); // If valid number, update state, otherwise show the alert if (isNumber || value === "") { const updatedcashAdjustments = formData.cashAdjustments.map( (cashAdjustments, i) => i === index ? { ...cashAdjustments, price: value, isInvalid: false } // Reset isInvalid if valid number : cashAdjustments ); setFormData({ ...formData, cashAdjustments: updatedcashAdjustments }); } else { const updatedcashAdjustments = formData.cashAdjustments.map( (cashAdjustments, i) => i === index ? { ...cashAdjustments, isInvalid: true } // Set isInvalid true for invalid input : cashAdjustments ); setFormData({ ...formData, cashAdjustments: updatedcashAdjustments }); } }; // Calculate total from cash Adjustments array const calculatecashAdjustments = () => { return formData.cashAdjustments.reduce((total, cashAdjustments) => { const price = parseFloat(cashAdjustments.price); return total + (isNaN(price) ? 0 : price); // Ensure only valid numbers are added }, 0); }; const calculateTotalCashRequiredonSettlement = () => { const totalcashAdjustments = calculatecashAdjustments(); const totalcredits = calculateTotalCredits(); const totalPurchaseCosts = calculateTotalPurchaseCosts(); // Sum up all the values from the three functions return totalcashAdjustments + totalcredits + totalPurchaseCosts; }; const addincidentalCost = () => { setFormData((prevData) => ({ ...prevData, incidentalCost: [...prevData.incidentalCost, { title: "", price: "" }], })); }; const deleteincidentalCost = (index) => { const updatedincidentalCost = formData.incidentalCost.filter( (_, i) => i !== index ); setFormData((prevData) => ({ ...prevData, incidentalCost: updatedincidentalCost, })); }; // Function to handle changes to incidentalCost title and price const handleincidentalCostTitle = (index, field, value) => { const updatedincidentalCost = [...formData.incidentalCost]; updatedincidentalCost[index][field] = value; setFormData((prevData) => ({ ...prevData, incidentalCost: updatedincidentalCost, })); }; const handleincidentalCostChange = (e, index) => { const value = e.target.value; // Regular expression to allow only numbers and optional decimals const isNumber = /^\d*\.?\d*$/.test(value); // If valid number, update state, otherwise show the alert if (isNumber || value === "") { const updatedincidentalCost = formData.incidentalCost.map( (incidentalCost, i) => i === index ? { ...incidentalCost, price: value, isInvalid: false } // Reset isInvalid if valid number : incidentalCost ); setFormData({ ...formData, incidentalCost: updatedincidentalCost }); } else { const updatedincidentalCost = formData.incidentalCost.map( (incidentalCost, i) => i === index ? { ...incidentalCost, isInvalid: true } // Set isInvalid true for invalid input : incidentalCost ); setFormData({ ...formData, incidentalCost: updatedincidentalCost }); } }; // Calculate total from incidentalCost array const calculateTotalincidentalCost = () => { return formData.incidentalCost.reduce((total, incidentalCost) => { const price = parseFloat(incidentalCost.price); return total + (isNaN(price) ? 0 : price); // Ensure only valid numbers are added }, 0); }; const addcarryCosts = () => { setFormData((prevData) => ({ ...prevData, carryCosts: [...prevData.carryCosts, { title: "", price: "" }], })); }; const deletecarryCosts = (index) => { const updatedcarryCosts = formData.carryCosts.filter((_, i) => i !== index); setFormData((prevData) => ({ ...prevData, carryCosts: updatedcarryCosts, })); }; // Function to handle changes to incidentalCost title and price const handlecarryCostsTitle = (index, field, value) => { const updatedcarryCosts = [...formData.carryCosts]; updatedcarryCosts[index][field] = value; setFormData((prevData) => ({ ...prevData, carryCosts: updatedcarryCosts, })); }; const handlecarryCostsChange = (e, index) => { const value = e.target.value; // Regular expression to allow only numbers and optional decimals const isNumber = /^\d*\.?\d*$/.test(value); // If valid number, update state, otherwise show the alert if (isNumber || value === "") { const updatedcarryCosts = formData.carryCosts.map((carryCosts, i) => i === index ? { ...carryCosts, price: value, isInvalid: false } // Reset isInvalid if valid number : carryCosts ); setFormData({ ...formData, carryCosts: updatedcarryCosts }); } else { const updatedcarryCosts = formData.carryCosts.map((carryCosts, i) => i === index ? { ...carryCosts, isInvalid: true } // Set isInvalid true for invalid input : carryCosts ); setFormData({ ...formData, carryCosts: updatedcarryCosts }); } }; // Calculate total from incidentalCost array const calculatetotalcarryCosts = () => { return formData.carryCosts.reduce((total, carryCosts) => { const price = parseFloat(carryCosts.price); return total + (isNaN(price) ? 0 : price); // Ensure only valid numbers are added }, 0); }; const addrenovationCost = () => { setFormData((prevData) => ({ ...prevData, renovationCost: [...prevData.renovationCost, { title: "", price: "" }], })); }; const deleterenovationCost = (index) => { const updatedrenovationCost = formData.renovationCost.filter( (_, i) => i !== index ); setFormData((prevData) => ({ ...prevData, renovationCost: updatedrenovationCost, })); }; // Function to handle changes to renovation Cost title and price const handlerenovationCostTitle = (index, field, value) => { const updatedrenovationCost = [...formData.renovationCost]; updatedrenovationCost[index][field] = value; setFormData((prevData) => ({ ...prevData, renovationCost: updatedrenovationCost, })); }; const handlerenovationCostChange = (e, index) => { const value = e.target.value; // Regular expression to allow only numbers and optional decimals const isNumber = /^\d*\.?\d*$/.test(value); // If valid number, update state, otherwise show the alert if (isNumber || value === "") { const updatedrenovationCost = formData.renovationCost.map( (renovationCost, i) => i === index ? { ...renovationCost, price: value, isInvalid: false } // Reset isInvalid if valid number : renovationCost ); setFormData({ ...formData, renovationCost: updatedrenovationCost }); } else { const updatedrenovationCost = formData.renovationCost.map( (renovationCost, i) => i === index ? { ...renovationCost, isInvalid: true } // Set isInvalid true for invalid input : renovationCost ); setFormData({ ...formData, renovationCost: updatedrenovationCost }); } }; // Calculate total from incidentalCost array const calculaterenovationCost = () => { return formData.renovationCost.reduce((total, renovationCost) => { const price = parseFloat(renovationCost.price); return total + (isNaN(price) ? 0 : price); // Ensure only valid numbers are added }, 0); }; const calculatetotalRenovationsandHoldingCost = () => { const totalIncidentalCost = calculateTotalincidentalCost(); const totalcarryCosts = calculatetotalcarryCosts(); const totalRenovationCost = calculaterenovationCost(); // Sum up all the values from the three functions return totalIncidentalCost + totalcarryCosts + totalRenovationCost; }; const calculatetotalCoststoBuyAtoB = () => { const totalRenovationsandHoldingCost = calculatetotalRenovationsandHoldingCost(); const totalCashRequiredonSettlement = calculateTotalCashRequiredonSettlement(); // Sum up all the values from the three functions return totalRenovationsandHoldingCost + totalCashRequiredonSettlement; }; const addcostPaidOutofClosing = () => { setFormData((prevData) => ({ ...prevData, costPaidOutofClosing: [ ...prevData.costPaidOutofClosing, { title: "", price: "" }, ], })); }; const deletecostPaidOutofClosing = (index) => { const updatedcostPaidOutofClosing = formData.costPaidOutofClosing.filter( (_, i) => i !== index ); setFormData((prevData) => ({ ...prevData, costPaidOutofClosing: updatedcostPaidOutofClosing, })); }; // Function to handle changes to incidentalCost title and price const handlecostPaidOutofClosingTitle = (index, field, value) => { const updatedcostPaidOutofClosing = [...formData.costPaidOutofClosing]; updatedcostPaidOutofClosing[index][field] = value; setFormData((prevData) => ({ ...prevData, costPaidOutofClosing: updatedcostPaidOutofClosing, })); }; const handlecostPaidOutofClosingChange = (e, index) => { const value = e.target.value; // Regular expression to allow only numbers and optional decimals const isNumber = /^\d*\.?\d*$/.test(value); // If valid number, update state, otherwise show the alert if (isNumber || value === "") { const updatedcostPaidOutofClosing = formData.costPaidOutofClosing.map( (costPaidOutofClosing, i) => i === index ? { ...costPaidOutofClosing, price: value, isInvalid: false } // Reset isInvalid if valid number : costPaidOutofClosing ); setFormData({ ...formData, costPaidOutofClosing: updatedcostPaidOutofClosing, }); } else { const updatedcostPaidOutofClosing = formData.costPaidOutofClosing.map( (costPaidOutofClosing, i) => i === index ? { ...costPaidOutofClosing, isInvalid: true } // Set isInvalid true for invalid input : costPaidOutofClosing ); setFormData({ ...formData, costPaidOutofClosing: updatedcostPaidOutofClosing, }); } }; // Calculate total from costPaidOutofClosing array const calculateTotalcostPaidOutofClosing = () => { return formData.costPaidOutofClosing.reduce( (total, costPaidOutofClosing) => { const price = parseFloat(costPaidOutofClosing.price); return total + (isNaN(price) ? 0 : price); // Ensure only valid numbers are added }, 0 ); }; const calculateTotalCosttoSellBtoC = () => { const sekkingPriceBtoC = formData.sellingPriceBtoC; const costPaidOutofClosing = calculateTotalcostPaidOutofClosing(); return sekkingPriceBtoC - costPaidOutofClosing; }; const addadjustments = () => { setFormData((prevData) => ({ ...prevData, adjustments: [...prevData.adjustments, { title: "", price: "" }], })); }; const deleteadjustments = (index) => { const updatedadjustments = formData.adjustments.filter( (_, i) => i !== index ); setFormData((prevData) => ({ ...prevData, adjustments: updatedadjustments, })); }; // Function to handle changes to incidentalCost title and price const handleadjustmentsTitle = (index, field, value) => { const updatedadjustments = [...formData.adjustments]; updatedadjustments[index][field] = value; setFormData((prevData) => ({ ...prevData, adjustments: updatedadjustments, })); }; const handleadjustmentsChange = (e, index) => { const value = e.target.value; // Regular expression to allow only numbers and optional decimals const isNumber = /^\d*\.?\d*$/.test(value); // If valid number, update state, otherwise show the alert if (isNumber || value === "") { const updatedadjustments = formData.adjustments.map((adjustments, i) => i === index ? { ...adjustments, price: value, isInvalid: false } // Reset isInvalid if valid number : adjustments ); setFormData({ ...formData, adjustments: updatedadjustments }); } else { const updatedadjustments = formData.adjustments.map((adjustments, i) => i === index ? { ...adjustments, isInvalid: true } // Set isInvalid true for invalid input : adjustments ); setFormData({ ...formData, adjustments: updatedadjustments }); } }; // Calculate total from incidentalCost array const calculateTotaladjustments = () => { return formData.adjustments.reduce((total, adjustments) => { const price = parseFloat(adjustments.price); return total + (isNaN(price) ? 0 : price); // Ensure only valid numbers are added }, 0); }; const calculatefundsavailablefordistribution = () => { const sellingPriceBtoC = calculateTotalCosttoSellBtoC(); const totaladjustments = calculateTotaladjustments(); return sellingPriceBtoC + totaladjustments; }; const addincomestatement = () => { setFormData((prevData) => ({ ...prevData, incomestatement: [...prevData.incomestatement, { title: "", price: "" }], })); }; const deleteincomestatement = (index) => { const updatedincomestatement = formData.incomestatement.filter( (_, i) => i !== index ); setFormData((prevData) => ({ ...prevData, incomestatement: updatedincomestatement, })); }; // Function to handle changes to incidentalCost title and price const handleincomestatementTitle = (index, field, value) => { const updatedincomestatement = [...formData.incomestatement]; updatedincomestatement[index][field] = value; setFormData((prevData) => ({ ...prevData, incomestatement: updatedincomestatement, })); }; const handleincomestatementChange = (e, index) => { const value = e.target.value; // Regular expression to allow only numbers and optional decimals const isNumber = /^\d*\.?\d*$/.test(value); // If valid number, update state, otherwise show the alert if (isNumber || value === "") { const updatedincomestatement = formData.incomestatement.map( (incomestatement, i) => i === index ? { ...incomestatement, price: value, isInvalid: false } // Reset isInvalid if valid number : incomestatement ); setFormData({ ...formData, incomestatement: updatedincomestatement }); } else { const updatedincomestatement = formData.incomestatement.map( (incomestatement, i) => i === index ? { ...incomestatement, isInvalid: true } // Set isInvalid true for invalid input : incomestatement ); setFormData({ ...formData, incomestatement: updatedincomestatement }); } }; // Calculate total from incidentalCost array const calculateTotalincomestatement = () => { return formData.incomestatement.reduce((total, incomestatement) => { const price = parseFloat(incomestatement.price); return total + (isNaN(price) ? 0 : price); // Ensure only valid numbers are added }, 0); }; const calculatenetBtoCsalevalue = () => { const totalincomestatement = calculateTotalincomestatement(); const totalcosttosellbtoc = calculateTotalCosttoSellBtoC(); return totalincomestatement + totalcosttosellbtoc; }; const calculateNetProfitBeforeFinancingCosts = () => { // const netBtoCsalevalue = parseFloat(calculatenetBtoCsalevalue()); // const shorttermrental = parseFloat(formData.shorttermrental); // const OtherIncome = parseFloat(formData.OtherIncome); // const InsuranceClaim = parseFloat(formData.InsuranceClaim); // const LongTermRental = parseFloat(formData.LongTermRental); // const totalCoststoBuyAtoB = parseFloat(calculatetotalCoststoBuyAtoB()); const netBtoCsalevalue = isNaN(parseFloat(calculatenetBtoCsalevalue())) ? 0 : parseFloat(calculatenetBtoCsalevalue()); const shorttermrental = isNaN(parseFloat(formData.shorttermrental)) ? 0 : parseFloat(formData.shorttermrental); const OtherIncome = isNaN(parseFloat(formData.OtherIncome)) ? 0 : parseFloat(formData.OtherIncome); const InsuranceClaim = isNaN(parseFloat(formData.InsuranceClaim)) ? 0 : parseFloat(formData.InsuranceClaim); const LongTermRental = isNaN(parseFloat(formData.LongTermRental)) ? 0 : parseFloat(formData.LongTermRental); const totalCoststoBuyAtoB = isNaN( parseFloat(calculatetotalCoststoBuyAtoB()) ) ? 0 : parseFloat(calculatetotalCoststoBuyAtoB()); // Calculate the sum first, then subtract the total costs const totalIncome = netBtoCsalevalue + shorttermrental + OtherIncome + InsuranceClaim + LongTermRental; const netProfitBeforeFinancingCosts = totalIncome - totalCoststoBuyAtoB; return netProfitBeforeFinancingCosts; }; const calculateNetProfit = () => { const NetProfitBeforeFinancingCosts = calculateNetProfitBeforeFinancingCosts(); const FinancingCostClosingCost = formData.FinancingCostClosingCost; return NetProfitBeforeFinancingCosts - FinancingCostClosingCost; }; const calculaterateofreturn = () => { const rateofreturn = calculateNetProfit(); return rateofreturn; }; const handleSubmit = () => { if ( formData.address && formData.city && formData.state && formData.county && formData.zip && formData.parcel && formData.subdivision && formData.legal && formData.costpersqft && formData.propertyType && formData.lotacres && formData.yearBuild && formData.totallivingsqft && formData.beds && formData.baths && formData.stories && formData.garage && formData.garagesqft && formData.poolspa && formData.fireplaces && formData.ac && formData.heating && formData.buildingstyle && formData.sitevacant && formData.extwall && formData.roofing && formData.totalSqft && formData.renovationRisk && formData.closeDateAtoB && formData.closeDateBtoC && formData.purchaseCost && formData.sellingPriceBtoC && formData.fundspriortoclosing && formData.shorttermrental && formData.OtherIncome && formData.InsuranceClaim && formData.LongTermRental && formData.FinancingCostClosingCost && formData.TradesinRenovations ) { const rateofreturn = calculaterateofreturn(); const totalPurchaseCosts = calculateTotalPurchaseCosts(); const totalPurchaseCostsaftercredits = calculateTotalPurchaseCostsWithCredits(); const totalcashAdjustments = calculatecashAdjustments(); const totalincidentalCost = calculateTotalincidentalCost(); const totalcredits = calculateTotalCredits(); const totalcashrequiredonsettlement = calculateTotalCashRequiredonSettlement(); const totalcarryCosts = calculatetotalcarryCosts(); const totalrenovationCost = calculaterenovationCost(); const totalRenovationsandHoldingCost = calculatetotalRenovationsandHoldingCost(); const totalCoststoBuyAtoB = calculatetotalCoststoBuyAtoB(); const totalcostPaidOutofClosing = calculateTotalcostPaidOutofClosing(); const totaladjustments = calculateTotaladjustments(); const fundsavailablefordistribution = calculatefundsavailablefordistribution(); const grossproceedsperHUD = calculateTotalCosttoSellBtoC(); const totalCosttoSellBtoC = calculateTotalCosttoSellBtoC(); const totalincomestatement = calculateTotalincomestatement(); const netBtoCsalevalue = calculatenetBtoCsalevalue(); const netprofitbeforefinancingcosts = calculateNetProfitBeforeFinancingCosts(); const NetProfit = calculateNetProfit(); // Add user info to formData, including the propertyTaxInfo array const formDataWithUserInfo = { ...formData, userfirstname: user?.result?.firstName, usermiddlename: user?.result?.middleName, userlastname: user?.result?.lastName, usertitle: user?.result?.title, useremail: user?.result?.email, userId: user?.result?.userId, totalPurchaseCosts: totalPurchaseCosts, totalcredits: totalcredits, totalPurchaseCostsaftercredits: totalPurchaseCostsaftercredits, totalcashAdjustments: totalcashAdjustments, totalcashrequiredonsettlement: totalcashrequiredonsettlement, totalincidentalCost: totalincidentalCost, totalcarryCosts: totalcarryCosts, totalrenovationCost: totalrenovationCost, totalRenovationsandHoldingCost: totalRenovationsandHoldingCost, totalCoststoBuyAtoB: totalCoststoBuyAtoB, totalcostPaidOutofClosing: totalcostPaidOutofClosing, totaladjustments: totaladjustments, fundsavailablefordistribution: fundsavailablefordistribution, grossproceedsperHUD: grossproceedsperHUD, totalCosttoSellBtoC: totalCosttoSellBtoC, totalincomestatement: totalincomestatement, netBtoCsalevalue: netBtoCsalevalue, netprofitbeforefinancingcosts: netprofitbeforefinancingcosts, NetProfit: NetProfit, rateofreturn: rateofreturn, }; // Check if propertyTaxInfo is an array and has values if ( Array.isArray(formData.propertyTaxInfo) && formData.propertyTaxInfo.length > 0 ) { formDataWithUserInfo.propertyTaxInfo = formData.propertyTaxInfo; // Include propertyTaxInfo } else { formDataWithUserInfo.propertyTaxInfo = []; // Ensure it's an empty array if not filled } // Dispatch the form data with user info dispatch(submitProperty(formDataWithUserInfo)); setSubmitted(true); } else { toast.error("Please fill all fields before submitting", { position: "top-right", autoClose: 3000, }); } }; useEffect(() => { if (submitted) { if (status === "succeeded") { toast.success("Property submitted successfully!", { position: "top-right", autoClose: 3000, }); setSubmitted(false); } else if (status === "failed") { toast.error(`Failed to submit: ${error}`, { position: "top-right", autoClose: 3000, }); setSubmitted(false); } } }, [status, error, submitted]); const [turnTime, setTurnTime] = useState("0 days"); // Store the calculated turn time const calculateTurnTime = (closeDateAtoB, closeDateBtoC) => { if (closeDateAtoB && closeDateBtoC) { const dateA = new Date(closeDateAtoB); const dateB = new Date(closeDateBtoC); // Calculate difference in time const diffTime = Math.abs(dateB - dateA); // Calculate difference in days const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); // Update state with the calculated turn time // setTurnTime(diffDays); setTurnTime(`${diffDays} days`); } else { setTurnTime("0 days"); // Reset if dates are not available } }; const addTrade = () => { setFormData((prevData) => ({ ...prevData, TradesinRenovations: [...prevData.TradesinRenovations, { title: "", price: "" }], })); }; const deleteTrade = (index) => { const updatedCosts = formData.TradesinRenovations.filter((_, i) => i !== index); setFormData((prevData) => ({ ...prevData, TradesinRenovations: updatedCosts, })); }; // Function to handle changes to title and price const handleTrade = (index, field, value) => { const updatedCosts = [...formData.TradesinRenovations]; updatedCosts[index][field] = value; setFormData((prevData) => ({ ...prevData, TradesinRenovations: updatedCosts, })); }; const handleTradePrice = (e, index) => { let value = e.target.value; // Remove the dollar sign before validating value = value.replace(/^\$/, "").trim(); // Remove '$' if it exists // Use a regular expression to allow only numbers and decimals const isNumber = /^\d*\.?\d*$/.test(value); // If valid number, update state, otherwise show the alert if (isNumber || value === "") { const updatedCosts = formData.TradesinRenovations.map((cost, i) => i === index ? { ...cost, price: value, isInvalid: false } // Reset isInvalid if valid number : cost ); setFormData({ ...formData, TradesinRenovations: updatedCosts }); } else { const updatedCosts = formData.TradesinRenovations.map((cost, i) => i === index ? { ...cost, isInvalid: true } // Keep isInvalid true for invalid input : cost ); setFormData({ ...formData, TradesinRenovations: updatedCosts }); } }; const addIAB = () => { setFormData((prevData) => ({ ...prevData, IAB: [...prevData.IAB, { title: "", URL: "" }], })); }; const deleteIAB = (index) => { const updatedIAB = formData.IAB.filter( (_, i) => i !== index ); setFormData((prevData) => ({ ...prevData, IAB: updatedIAB, })); }; // Function to handle changes to incidentalCost title and price const handleIABTitle = (index, field, value) => { const updatedIAB = [...formData.IAB]; updatedIAB[index][field] = value; setFormData((prevData) => ({ ...prevData, IAB: updatedIAB, })); }; const handleIABChange = (index, field, value) => { const updatedIAB = [...formData.IAB]; updatedIAB[index][field] = value; setFormData((prevData) => ({ ...prevData, IAB: updatedIAB, })); }; return ( <>
[M-D-Y]{" "} :{" "} {new Date(formData.closeDateAtoB).toLocaleDateString( "en-US", { month: "numeric", day: "numeric", year: "numeric", } )}
[M-D-Y] :{" "} {new Date(formData.closeDateBtoC).toLocaleDateString( "en-US", { month: "numeric", day: "numeric", year: "numeric", } )}