This commit is contained in:
omkieit 2024-10-12 23:55:32 +05:30
parent 5ac5779b1f
commit e365da1c7a
3 changed files with 1961 additions and 1417 deletions

File diff suppressed because one or more lines are too long

View File

@ -45,7 +45,7 @@
<script type="module" crossorigin src="/assets/index-MWSD7APw.js"></script>
<script type="module" crossorigin src="/assets/index-BiIJaVB0.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-iEl-il0E.css">
</head>

View File

@ -3,6 +3,7 @@ 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 = () => {
@ -23,11 +24,21 @@ const EditProperty = () => {
const { selectedProperty } = useSelector((state) => state.property);
const [formData, setFormData] = useState({
// propertyType: "",
// yearBuild: "",
// totalSqft: "",
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
renovationRisk: null,
turnTime: "",
});
const renovationRiskOptions = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // Array of options
useEffect(() => {
dispatch(fetchPropertyById(id));
}, [dispatch, id]);
@ -35,10 +46,53 @@ const EditProperty = () => {
useEffect(() => {
if (selectedProperty) {
setFormData({
address:selectedProperty.address,
propertyType: selectedProperty.propertyType,
yearBuild: selectedProperty.yearBuild,
totalSqft: selectedProperty.totalSqft,
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,
// sellingPriceBtoC:selectedProperty.sellingPriceBtoC,
// fundspriortoclosing:selectedProperty.fundspriortoclosing,
// shorttermrental:selectedProperty.shorttermrental,
// OtherIncome:selectedProperty.OtherIncome,
// InsuranceClaim:selectedProperty.InsuranceClaim,
// LongTermRental:selectedProperty.LongTermRental,
propertyTaxInfo: selectedProperty.propertyTaxInfo || [
{
propertytaxowned: "0",
ownedyear: "0",
taxassessed: "0",
taxyear: "0",
},
],
images: selectedProperty.images || [{ title: "", file: "" }],
googleMapLink: selectedProperty.googleMapLink,
rateofreturn: selectedProperty.rateofreturn,
});
}
}, [selectedProperty]);
@ -47,17 +101,110 @@ const EditProperty = () => {
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 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
}
};
return (
<>
<Navbar />
<br /> <br /> <br /> <br /> <br /> <br />
<div className="d-flex justify-content-center align-items-center" >
<div className="d-flex justify-content-center align-items-center">
<div className="card justify-content-center">
<ul className="nav nav-tabs" role="tablist">
<li
@ -650,7 +797,9 @@ const EditProperty = () => {
</option>
<option value="Wood Siding">Wood Siding</option>
<option value="Vinyl Siding">Vinyl Siding</option>
<option value="Aluminium Siding">Aluminium Siding</option>
<option value="Aluminium Siding">
Aluminium Siding
</option>
<option value="Wood/Vinyl Siding">
Alum/Vinyl Siding
</option>
@ -669,7 +818,9 @@ const EditProperty = () => {
<option value="N/A">N/A</option>
<option value="Asphalt Shingle">Asphalt Shingle</option>
<option value="Green Roofs">Green Roofs</option>
<option value="Built-up Roofing">Built-up Roofing</option>
<option value="Built-up Roofing">
Built-up Roofing
</option>
<option value="Composition Shingle">
Composition Shingle
</option>
@ -723,6 +874,91 @@ const EditProperty = () => {
height: "1px", // Optional: Set height to match the border width
}}
/>
{formData.propertyTaxInfo &&
formData.propertyTaxInfo.map((taxInfo, index) => (
<div className="row gy-4" key={index}>
<div className="col-md-3">
<div className="form-floating mb-3">
Property Tax Owned
<input
type="text"
className="form-control"
name="propertytaxowned"
value={taxInfo.propertytaxowned}
onChange={(e) =>
handleInputChange(e, index, "propertyTaxInfo")
}
required
/>
</div>
</div>
<div className="col-md-2">
<div className="form-floating mb-2">
Owned Year
<input
type="text"
className="form-control"
name="ownedyear"
value={taxInfo.ownedyear}
onChange={(e) =>
handleInputChange(e, index, "propertyTaxInfo")
}
required
/>
</div>
</div>
<div className="col-md-2">
<div className="form-floating mb-2">
Tax Assessed
<input
type="text"
className="form-control"
name="taxassessed"
value={taxInfo.taxassessed}
onChange={(e) =>
handleInputChange(e, index, "propertyTaxInfo")
}
required
/>
</div>
</div>
<div className="col-md-2">
<div className="form-floating mb-2">
Tax Year
<input
type="text"
className="form-control"
name="taxyear"
value={taxInfo.taxyear}
onChange={(e) =>
handleInputChange(e, index, "propertyTaxInfo")
}
required
/>
</div>
</div>
<div className="col-md-3">
<div className="form-floating mb-2">
<br />
<button
className="btn btn-danger"
onClick={() => deletePropertyTaxField(index)}
style={{ height: "25px", width: "35px" }}
>
X
</button>
</div>
</div>
</div>
))}
<button
className="btn btn-secondary"
onClick={addPropertyTaxField}
>
+ Add Another Property Tax Info
</button>
</form>
<button
@ -756,6 +992,65 @@ const EditProperty = () => {
height: "1px", // Optional: Set height to match the border width
}}
/>
{formData.images.map((image, index) => (
<div key={index} className="row gy-3 align-items-center">
<div className="col-md-4">
<input
type="text"
className="form-control"
value={image.title}
placeholder="Image Title"
onChange={(e) => handleImageTitleChange(index, e)}
/>
</div>
<div className="col-md-4 d-flex align-items-center">
<FileBase64
multiple={false}
onDone={(file) => handleImageChange(file, index)}
/>
<button
type="button"
className="btn btn-danger"
onClick={() => handleDeleteImage(index)}
style={{
marginLeft: "5px", // Adjust this to minimize space between the buttons
}}
>
Delete
</button>
</div>
{image.file && (
<div className="col-md-12">
<img
src={image.file}
alt="uploaded"
style={{ width: "150px", height: "150px" }}
/>
</div>
)}
</div>
))}
<button
type="button"
className="btn btn-primary"
onClick={handleAddImage}
style={{ backgroundColor: "#fda417", border: "#fda417" }}
>
+ Add Image
</button>
<hr
style={{
borderColor: "#fda417", // Set the color of the line
borderWidth: "1px", // Optional: Adjust the thickness of the line
backgroundColor: "#fda417", // Optional: Apply color if using for background
height: "1px", // Optional: Set height to match the border width
}}
/>
<div className="mb-3">
<label htmlFor="googleMapLink" className="form-label">
<h3
@ -819,6 +1114,235 @@ const EditProperty = () => {
>
<br />
<div className="row gy-3">
{/* Close Date A to B */}
<div className="col-md-4">
<input
type="text"
className="form-control"
placeholder="Close Date A to B"
required
disabled
/>
</div>
<div className="col-md-4">
<input
type="date"
className="form-control"
name="closeDateAtoB"
value={formData.closeDateAtoB}
onChange={(e) => {
const value = e.target.value;
setFormData({
...formData,
closeDateAtoB: value,
});
calculateTurnTime(value, formData.closeDateBtoC);
}}
placeholder="Close Date A to B"
style={{ textAlign: "right" }}
required
/>
</div>
<div>
<p>
<span
style={{
color: "#fda417",
fontSize: "14px",
fontWeight: "bold",
}}
>
[M-D-Y]{" "}
</span>
:{" "}
<span
style={{
color: "#000000",
fontSize: "14px",
fontWeight: "normal",
}}
>
{new Date(formData.closeDateAtoB).toLocaleDateString(
"en-US",
{
month: "numeric",
day: "numeric",
year: "numeric",
}
)}
</span>
</p>
</div>
</div>
<div className="row gy-3">
{/* Close Date B to C */}
<div className="col-md-4">
<input
type="text"
className="form-control"
placeholder="Close Date B to C"
required
disabled
/>
</div>
<div className="col-md-4">
<input
type="date"
className="form-control"
name="closeDateBtoC"
value={formData.closeDateBtoC}
onChange={(e) => {
const value = e.target.value;
setFormData({
...formData,
closeDateBtoC: value,
});
calculateTurnTime(formData.closeDateAtoB, value);
}}
placeholder="Close Date B to C"
style={{ textAlign: "right" }}
required
/>
</div>
<div>
<p>
<span
style={{
color: "#fda417",
fontSize: "14px",
fontWeight: "bold",
}}
>
[M-D-Y] :{" "}
</span>
<span
style={{
color: "#000000",
fontSize: "14px",
fontWeight: "normal",
}}
>
{new Date(formData.closeDateBtoC).toLocaleDateString(
"en-US",
{
month: "numeric",
day: "numeric",
year: "numeric",
}
)}
</span>
</p>
</div>
</div>
<div className="row gy-3 align-items-center">
<span
className="col-md-4"
style={{
color: "#fda417",
fontSize: "14px",
fontWeight: "bold",
}}
>
Renovation Risk
</span>
<div className="col-md-7">
{renovationRiskOptions.map((option) => (
<div
className="form-check form-check-inline"
key={option}
>
<input
className="form-check-input"
type="radio"
name="renovationRisk"
id={`renovationRisk${option}`}
value={option}
checked={formData.renovationRisk === option}
onChange={(e) => {
const value = parseInt(e.target.value, 10);
setFormData({
...formData,
renovationRisk: value,
});
}}
/>
<label
className="form-check-label"
htmlFor={`renovationRisk${option}`}
>
{option}
</label>
</div>
))}
</div>
</div>
<br />
<div className="row gy-3 align-items-center">
<span
className="col-md-4"
style={{
color: "#fda417",
fontSize: "14px",
fontWeight: "bold",
}}
>
Rate of Return
</span>
<div className="col-md-4">
<input
type="text"
className="form-control"
name="rateofreturn"
// value={`$ ${calculaterateofreturn().toFixed(2)}`}
readOnly
style={{
borderColor: "#fda417", // Custom border color for the input field
color: "#fda417", // Optionally apply text color to the input text
textAlign: "right",
}}
required
/>
</div>
</div>
<br />
<div className="row gy-3 align-items-center">
<span
className="col-md-4"
style={{
color: "#fda417",
fontSize: "14px",
fontWeight: "bold",
}}
>
Turn Time
</span>
<div className="col-md-4">
<input
type="text"
className="form-control"
value={turnTime}
readOnly
style={{
borderColor: "#fda417", // Custom border color for the input field
color: "#fda417", // Optionally apply text color to the input text
textAlign: "right",
}}
required
/>
</div>
</div>
<br />
<br />
<hr
@ -1147,7 +1671,9 @@ const EditProperty = () => {
<input
type="text"
className={`form-control ${
formData.isfundspriortoclosingInvalid ? "is-invalid" : ""
formData.isfundspriortoclosingInvalid
? "is-invalid"
: ""
}`}
value={formData.fundspriortoclosing}
name="fundspriortoclosing"
@ -1163,7 +1689,10 @@ const EditProperty = () => {
onKeyPress={(e) => {
const charCode = e.charCode;
// Allow only numbers and decimal points
if ((charCode < 48 || charCode > 57) && charCode !== 46) {
if (
(charCode < 48 || charCode > 57) &&
charCode !== 46
) {
e.preventDefault(); // Prevent non-numeric input
setFormData({
...formData,
@ -1228,7 +1757,10 @@ const EditProperty = () => {
onKeyPress={(e) => {
const charCode = e.charCode;
// Allow only numbers and decimal points
if ((charCode < 48 || charCode > 57) && charCode !== 46) {
if (
(charCode < 48 || charCode > 57) &&
charCode !== 46
) {
e.preventDefault(); // Prevent non-numeric input
setFormData({
...formData,
@ -1279,7 +1811,10 @@ const EditProperty = () => {
onKeyPress={(e) => {
const charCode = e.charCode;
// Allow only numbers and decimal points
if ((charCode < 48 || charCode > 57) && charCode !== 46) {
if (
(charCode < 48 || charCode > 57) &&
charCode !== 46
) {
e.preventDefault(); // Prevent non-numeric input
setFormData({
...formData,
@ -1330,7 +1865,10 @@ const EditProperty = () => {
onKeyPress={(e) => {
const charCode = e.charCode;
// Allow only numbers and decimal points
if ((charCode < 48 || charCode > 57) && charCode !== 46) {
if (
(charCode < 48 || charCode > 57) &&
charCode !== 46
) {
e.preventDefault(); // Prevent non-numeric input
setFormData({
...formData,
@ -1381,7 +1919,10 @@ const EditProperty = () => {
onKeyPress={(e) => {
const charCode = e.charCode;
// Allow only numbers and decimal points
if ((charCode < 48 || charCode > 57) && charCode !== 46) {
if (
(charCode < 48 || charCode > 57) &&
charCode !== 46
) {
e.preventDefault(); // Prevent non-numeric input
setFormData({
...formData,
@ -1449,7 +1990,10 @@ const EditProperty = () => {
onKeyPress={(e) => {
const charCode = e.charCode;
// Allow only numbers and decimal points
if ((charCode < 48 || charCode > 57) && charCode !== 46) {
if (
(charCode < 48 || charCode > 57) &&
charCode !== 46
) {
e.preventDefault(); // Prevent non-numeric input
setFormData({
...formData,