import { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { fetchPropertyById } from "../redux/features/propertySlice";
import { updateProperty } from "../redux/features/propertySlice";
import { useParams } from "react-router-dom";
import FileBase64 from "react-file-base64";
import Navbar from "./Navbar";
const EditProperty = () => {
const { id } = useParams();
const dispatch = useDispatch();
const [activeTab, setActiveTab] = useState("propertydetails");
const handleContinue = () => {
if (activeTab === "propertydetails") setActiveTab("Images");
if (activeTab === "Images") setActiveTab("Accounting");
};
const handleBack = () => {
if (activeTab === "Images") setActiveTab("propertydetails");
if (activeTab === "Accounting") setActiveTab("Images");
};
const { selectedProperty } = useSelector((state) => state.property);
const [formData, setFormData] = useState({
address: "",
city: "",
state: "",
zip: "",
propertyTaxInfo: [
{ propertytaxowned: "0", ownedyear: "0", taxassessed: "0", taxyear: "0" },
],
images: [{ title: "", file: "" }], // Array to hold image objects
googleMapLink: "", // Field for Google Maps link
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" },
],
renovationRisk: null,
turnTime: "",
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",
});
const renovationRiskOptions = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // Array of options
useEffect(() => {
dispatch(fetchPropertyById(id));
}, [dispatch, id]);
useEffect(() => {
if (selectedProperty) {
setFormData({
address: selectedProperty.address || "",
city: selectedProperty.city || "",
state: selectedProperty.state || "",
zip: selectedProperty.zip || "",
parcel: selectedProperty.parcel || "",
subdivision: selectedProperty.subdivision || "",
legal: selectedProperty.legal || "",
costpersqft: selectedProperty.costpersqft || "",
propertyType: selectedProperty.propertyType || "",
lotacres: selectedProperty.lotacres || "",
yearBuild: selectedProperty.yearBuild || "",
totallivingsqft: selectedProperty.totallivingsqft || "",
beds: selectedProperty.beds || "",
baths: selectedProperty.baths || "",
stories: selectedProperty.stories || "",
garage: selectedProperty.garage || "",
garagesqft: selectedProperty.garagesqft || "",
poolspa: selectedProperty.poolspa || "",
fireplaces: selectedProperty.fireplaces || "",
ac: selectedProperty.ac || "",
heating: selectedProperty.heating || "",
buildingstyle: selectedProperty.buildingstyle || "",
sitevacant: selectedProperty.sitevacant || "",
extwall: selectedProperty.extwall || "",
roofing: selectedProperty.roofing || "",
totalSqft: selectedProperty.totalSqft || "",
renovationRisk: selectedProperty.renovationRisk,
closeDateAtoB: selectedProperty.closeDateAtoB,
closeDateBtoC: selectedProperty.closeDateBtoC,
purchaseCost: selectedProperty.purchaseCost,
costPaidAtoB: selectedProperty.costPaidAtoB,
totalPurchaseCosts: selectedProperty.totalPurchaseCosts,
credits: selectedProperty.credits,
totalPurchaseCostsaftercredits:
selectedProperty.totalPurchaseCostsaftercredits,
cashAdjustments: selectedProperty.cashAdjustments,
totalcashrequiredonsettlement:
selectedProperty.totalcashrequiredonsettlement,
incidentalCost: selectedProperty.incidentalCost,
carryCosts: selectedProperty.carryCosts,
renovationCost: selectedProperty.renovationCost,
sellingPriceBtoC: selectedProperty.sellingPriceBtoC,
costPaidOutofClosing: selectedProperty.costPaidOutofClosing,
totalCosttoSellBtoC: selectedProperty.totalCosttoSellBtoC,
grossproceedsperHUD: selectedProperty.grossproceedsperHUD,
adjustments: selectedProperty.adjustments,
fundsavailablefordistribution:
selectedProperty.fundsavailablefordistribution,
incomestatement: selectedProperty.incomestatement,
fundspriortoclosing: selectedProperty.fundspriortoclosing,
shorttermrental: selectedProperty.shorttermrental,
OtherIncome: selectedProperty.OtherIncome,
InsuranceClaim: selectedProperty.InsuranceClaim,
LongTermRental: selectedProperty.LongTermRental,
netprofitbeforefinancingcosts:
selectedProperty.netprofitbeforefinancingcosts,
FinancingCostClosingCost: selectedProperty.FinancingCostClosingCost,
propertyTaxInfo: selectedProperty.propertyTaxInfo || [
{
propertytaxowned: "0",
ownedyear: "0",
taxassessed: "0",
taxyear: "0",
},
],
images: selectedProperty.images || [{ title: "", file: "" }],
googleMapLink: selectedProperty.googleMapLink,
rateofreturn: selectedProperty.rateofreturn,
});
}
}, [selectedProperty]);
const handleChange = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
// Handle specific changes for propertyTaxInfo array
const handleInputChange = (e, index) => {
const { name, value } = e.target;
// Make a shallow copy of the propertyTaxInfo array
const updatedPropertyTaxInfo = [...formData.propertyTaxInfo];
// Make a shallow copy of the object you want to modify (taxInfo at index)
const updatedTaxInfo = { ...updatedPropertyTaxInfo[index] };
// Update the field in the copied object
updatedTaxInfo[name] = value;
// Replace the old object with the updated one in the array
updatedPropertyTaxInfo[index] = updatedTaxInfo;
// Finally, update the formData with the updated propertyTaxInfo array
setFormData({ ...formData, propertyTaxInfo: updatedPropertyTaxInfo });
};
// const handleSubmit = (e) => {
// e.preventDefault();
// dispatch(updateProperty({ id, propertyData: formData }));
// };
const handleSubmit = (e) => {
e.preventDefault();
// Calculate total purchase costs and update the formData
const totalPurchaseCosts = calculateTotalPurchaseCosts();
const totalcredits = calculateTotalCredits();
const totalPurchaseCostsaftercredits =
calculateTotalPurchaseCostsWithCredits();
const totalcashAdjustments = calculatecashAdjustments();
const totalcashrequiredonsettlement =
calculateTotalCashRequiredonSettlement();
const totalincidentalCost = calculateTotalincidentalCost();
const totalcarryCosts = calculatetotalcarryCosts();
const totalrenovationCost = calculaterenovationCost();
const totalRenovationsandHoldingCost =
calculatetotalRenovationsandHoldingCost();
const totalCoststoBuyAtoB = calculatetotalCoststoBuyAtoB();
const totalcostPaidOutofClosing = calculateTotalcostPaidOutofClosing();
const totalCosttoSellBtoC = calculateTotalCosttoSellBtoC();
const grossproceedsperHUD = calculateTotalCosttoSellBtoC();
const totaladjustments = calculateTotaladjustments();
const fundsavailablefordistribution =
calculatefundsavailablefordistribution();
const totalincomestatement = calculateTotalincomestatement();
const netBtoCsalevalue = calculatenetBtoCsalevalue();
const netprofitbeforefinancingcosts =
calculateNetProfitBeforeFinancingCosts();
const netprofit = calculateNetProfit();
// Update the formData with the calculated total purchase cost
const updatedFormData = {
...formData,
totalPurchaseCosts: totalPurchaseCosts.toFixed(2), // Store as a string with 2 decimal places
totalcredits: totalcredits.toFixed(2),
totalPurchaseCostsaftercredits: totalPurchaseCostsaftercredits.toFixed(2),
totalcashAdjustments: totalcashAdjustments.toFixed(2),
totalcashrequiredonsettlement: totalcashrequiredonsettlement.toFixed(2),
totalincidentalCost: totalincidentalCost.toFixed(2),
totalcarryCosts: totalcarryCosts.toFixed(2),
totalrenovationCost: totalrenovationCost.toFixed(2),
totalRenovationsandHoldingCost: totalRenovationsandHoldingCost.toFixed(2),
totalCoststoBuyAtoB: totalCoststoBuyAtoB.toFixed(2),
totalcostPaidOutofClosing: totalcostPaidOutofClosing.toFixed(2),
totalCosttoSellBtoC: totalCosttoSellBtoC.toFixed(2),
grossproceedsperHUD: grossproceedsperHUD.toFixed(2),
totaladjustments: totaladjustments.toFixed(2),
fundsavailablefordistribution: fundsavailablefordistribution.toFixed(2),
totalincomestatement: totalincomestatement.toFixed(2),
netBtoCsalevalue: netBtoCsalevalue.toFixed(2),
netprofitbeforefinancingcosts: netprofitbeforefinancingcosts.toFixed(2),
netprofit: netprofit.toFixed(2),
};
// Dispatch the updated formData
dispatch(updateProperty({ id, propertyData: updatedFormData }));
};
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 handleImageChange = (file, index) => {
const updatedImages = [...formData.images];
updatedImages[index] = {
...updatedImages[index],
file: file.base64, // Store the base64 format of the 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] = {
...updatedImages[index],
title: e.target.value,
};
setFormData({ ...formData, images: updatedImages });
};
useEffect(() => {
calculateTurnTime(formData.closeDateAtoB, formData.closeDateBtoC);
}, [formData.closeDateAtoB, formData.closeDateBtoC]);
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 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;
};
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", } )}