This commit is contained in:
omkieit 2024-10-06 19:25:53 +05:30
parent 98707b20fc
commit 14fd066fe0
9 changed files with 4526 additions and 2137 deletions

View File

@ -0,0 +1,74 @@
import mongoose from "mongoose";
// Schema for property tax information
const propertyTaxInfoSchema = mongoose.Schema({
propertytaxowned: { type: String },
ownedyear: { type: String },
taxassessed: { type: String },
taxyear: { type: String },
});
// Schema for images
const imageSchema = mongoose.Schema({
title: { type: String }, // Title of the image
file: { type: String }, // Uploaded image URL
});
const propertySchema = mongoose.Schema({
address: { type: String, required: true },
city: { type: String, required: true },
state: { type: String, required: true },
county: { type: String, required: true },
zip: { type: String, required: true },
parcel: { type: String, required: true },
subdivision: { type: String, required: true },
legal: { type: String, required: true },
costpersqft: { type: String, required: true },
propertyType: { type: String, required: true },
lotacres: { type: String, required: true },
yearBuild: { type: String, required: true },
totallivingsqft: { type: String, required: true },
beds: { type: String, required: true },
baths: { type: String, required: true },
stories: { type: String, required: true },
garage: { type: String, required: true },
garagesqft: { type: String, required: true },
poolspa: { type: String, required: true },
fireplaces: { type: String, required: true },
ac: { type: String, required: true },
heating: { type: String, required: true },
buildingstyle: { type: String, required: true },
sitevacant: { type: String, required: true },
extwall: { type: String, required: true },
roofing: { type: String, required: true },
totalSqft: { type: String, required: true },
// Remove individual property tax fields and replace with array
propertyTaxInfo: [propertyTaxInfoSchema], // Array of tax info objects
images: [imageSchema],
googleMapLink: { type: String },
userfirstname: String,
usermiddlename: String,
userlastname: String,
usertitle: String,
creator: String,
useremail: String,
propertyId: String,
userId: String,
createdAt: {
type: Date,
default: new Date(),
},
publishedAt: {
type: Date,
default: new Date(),
},
currentYear: {
type: Number,
default: new Date().getFullYear(),
},
});
const PropertyModal = mongoose.model("property", propertySchema);
export default PropertyModal;

View File

@ -42,7 +42,6 @@ const propertySchema = mongoose.Schema({
extwall: { type: String, required: true },
roofing: { type: String, required: true },
totalSqft: { type: String, required: true },
// Remove individual property tax fields and replace with array
propertyTaxInfo: [propertyTaxInfoSchema], // Array of tax info objects
images: [imageSchema],
@ -67,6 +66,42 @@ const propertySchema = mongoose.Schema({
type: Number,
default: new Date().getFullYear(),
},
purchaseCost: {
type: Number,
required: true, // Set to true if this field is mandatory
},
costPaidAtoB: [
{
title: {
type: String,
required: true, // Set to true if this field is mandatory
},
price: {
type: Number,
required: true, // Set to true if this field is mandatory
},
},
],
totalCostsAtoB: {
type: Number,
required: true, // Set to true if this field is mandatory
},
credits: [
{
title: {
type: String,
required: true, // Set to true if this field is mandatory
},
price: {
type: Number,
required: true, // Set to true if this field is mandatory
},
},
],
totalCostsAtoBaftercredits: {
type: Number,
required: true, // Set to true if this field is mandatory
},
});
const PropertyModal = mongoose.model("property", propertySchema);

File diff suppressed because one or more lines are too long

85
ef-ui/dist/assets/index-DfwOztBd.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

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

View File

@ -0,0 +1,880 @@
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");
};
const handleBack = () => {
if (activeTab === "Images") setActiveTab("propertydetails");
if (activeTab === "Accounting") setActiveTab("Images");
};
const dispatch = useDispatch();
const { status, error } = useSelector((state) => state.property);
const { user } = useSelector((state) => ({ ...state.auth }));
const [formData, setFormData] = useState({
poolspa: "",
propertyTaxInfo: [
{ propertytaxowned: "", ownedyear: "", taxassessed: "", taxyear: "" },
],
images: [{ title: "", file: "" }], // Array to hold image objects
googleMapLink: "", // Field for Google Maps link
purchaseCost: "",
costPaidAtoB: [
{ title: "Closing Fees - Settlement Fee", price: "" },
{ title: "Closing Fees - Owner's Title Insurance", price: "" },
{ title: "Courier Fees", price: "" },
{ title: "Wire Fee", price: "" },
{ title: "E recording Fee", price: "" },
{ title: "Recording Fee", price: "" },
{ title: "Property Tax", price: "" },
],
credits: [{ title: "Credits received on settlement", price: "" }],
});
const [submitted, setSubmitted] = useState(false);
const handleImageChange = (file, index) => {
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) => {
const value = e.target.value;
// 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 calculateTotalCosts = () => {
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 calculateTotalCostsWithCredits = () => {
// 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 the sum of total costs from both arrays and purchase cost
return totalCostsFromArray + totalCreditsFromArray + purchaseCost;
};
const handleSubmit = () => {
if (formData.poolspa) {
const totalCostsAtoB = calculateTotalCosts();
const totalCostsAtoBaftercredits = calculateTotalCostsWithCredits();
// 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,
totalCostsAtoB: totalCostsAtoB,
totalCostsAtoBaftercredits: totalCostsAtoBaftercredits,
};
// 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]);
return (
<>
<div className="container tabs-wrap">
<Navbar />
<ul className="nav nav-tabs" role="tablist">
<li
role="presentation"
className={activeTab === "propertydetails" ? "active tab" : "tab"}
>
<a onClick={() => setActiveTab("propertydetails")} role="tab">
Property Details
</a>
</li>
<li
role="presentation"
className={activeTab === "Images" ? "active tab" : "tab"}
>
<a onClick={() => setActiveTab("Images")} role="tab">
Images, Maps
</a>
</li>
<li
role="presentation"
className={activeTab === "Accounting" ? "active tab" : "tab"}
>
<a onClick={() => setActiveTab("Accounting")} role="tab">
Accounting
</a>
</li>
</ul>
<div className="tab-content">
{activeTab === "propertydetails" && (
<div role="tabpanel" className="card tab-pane active">
<form>
<h3
style={{
color: "#fda417",
border: "#fda417",
fontSize: "20px",
fontWeight: "normal",
}}
>
Property Location
</h3>
<hr />
<div className="row gy-3">
<div className="col-md-4">
Please Select Pool/SPA
<select
className="form-floating mb-3 form-control"
name="poolspa"
value={formData.poolspa}
onChange={handleInputChange}
required
>
<option value="">Please Select</option>
<option value="N/A">N/A</option>
<option value="Yes- Pool Only">Yes- Pool Only</option>
<option value="Yes- SPA only">Yes- SPA only</option>
<option value="Yes - Both Pool and SPA">
Yes - Both Pool and SPA
</option>
<option value="4">None</option>
</select>
</div>
</div>
<div className="row gy-3"></div>
<h3
style={{
color: "#fda417",
border: "#fda417",
fontSize: "20px",
fontWeight: "normal",
}}
>
<br />
Property Tax Information
</h3>
<hr />
{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">
Owed 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
className="btn btn-primary continue"
onClick={handleContinue}
style={{ backgroundColor: "#fda417", border: "#fda417" }}
>
Continue
</button>
</div>
)}
{activeTab === "Images" && (
<div role="tabpanel" className="card tab-pane active">
<h3
style={{
color: "#fda417",
border: "#fda417",
fontSize: "20px",
fontWeight: "normal",
}}
>
Upload Images{" "}
</h3>
<form>
{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 />
<div className="mb-3">
<label htmlFor="googleMapLink" className="form-label">
<h3
style={{
color: "#fda417",
border: "#fda417",
fontSize: "20px",
fontWeight: "normal",
}}
>
Google Maps Link{" "}
</h3>
</label>
<input
type="text"
className="form-control"
name="googleMapLink"
value={formData.googleMapLink}
onChange={handleInputChange}
placeholder="Enter Google Maps link"
/>
</div>
{formData.googleMapLink && (
<iframe
title="Google Map"
width="100%"
height="300"
src={`https://www.google.com/maps/embed/v1/view?key=YOUR_API_KEY&center=${formData.googleMapLink}&zoom=10`}
frameBorder="0"
allowFullScreen
></iframe>
)}
</form>
<button
className="btn btn-primary back"
onClick={handleBack}
style={{ backgroundColor: "#fda417", border: "#fda417" }}
>
Go Back
</button>{" "}
<button
className="btn btn-primary continue"
onClick={handleContinue}
style={{ backgroundColor: "#fda417", border: "#fda417" }}
>
Continue
</button>
</div>
)}
{activeTab === "Accounting" && (
<div
className="card"
style={{
color: "#fda417",
border: "1px solid #fda417",
padding: "10px",
borderRadius: "8px",
}}
>
<h3
style={{
color: "#fda417",
border: "#fda417",
fontSize: "20px",
fontWeight: "normal",
}}
>
Property Acquisition A to B:
</h3>
<br />
{/* <div className="form-floating mb-3">
<span style={{
color: "#fda417",
fontSize: "14px",
fontWeight: "bold",
}}>Purchase Cost</span>
<input
type="text"
className="form-control"
value={formData.purchaseCost}
onChange={(e) =>
setFormData({
...formData,
purchaseCost: e.target.value,
})
}
placeholder="Enter Purchase Cost"
required
/>
</div> */}
<div className="row gy-3">
<div className="col-md-4">
<input
type="text"
className="form-control"
placeholder="Purchase Cost"
required
disabled
/>
</div>
<div className="col-md-4">
<input
type="text"
className="form-control"
value={formData.purchaseCost}
onChange={(e) =>
setFormData({
...formData,
purchaseCost: e.target.value,
})
}
placeholder="Enter Purchase Cost"
style={{ textAlign: "right" }}
required
/>
</div>
</div>
<br />
<span
style={{
color: "#fda417",
fontSize: "14px",
fontWeight: "bold",
}}
>
Costs paid out of Closing Hud A to B:
</span>
{formData.costPaidAtoB.map((cost, index) => (
<div key={index} className="row gy-3 align-items-center">
<div className="col-md-4">
<input
type="text"
className="form-control"
value={cost.title}
onChange={(e) =>
handleCostChange(index, "title", e.target.value)
}
placeholder="Title"
required
/>
</div>
<div className="col-md-4">
<input
type="text"
className={`form-control ${
cost.isInvalid ? "is-invalid" : ""
}`} // Apply 'is-invalid' class when invalid
value={cost.price}
onChange={(e) => handlePriceChange(e, index)} // Use a new handler for price validation
placeholder="Price"
style={{ textAlign: "right" }}
required
/>
{cost.isInvalid && (
<div className="invalid-feedback">
Please enter a valid number.
</div>
)}
</div>
<div className="col-md-2 d-flex justify-content-start">
<button
className="btn btn-danger"
onClick={() => deleteCost(index)}
style={{ marginLeft: "5px" }}
>
x
</button>
</div>
</div>
))}
<div className="col-md-4">
<button
onClick={addCost}
className="btn btn-primary back"
style={{ backgroundColor: "#fda417", border: "#fda417" }}
>
<span
style={{
fontSize: "20px",
fontWeight: "normal",
}}
>
+
</span>{" "}
Add Extra Cost
</button>
</div>
<div className="row gy-3 align-items-center">
<span
className="col-md-4"
style={{
color: "#fda417",
fontSize: "14px",
fontWeight: "bold",
}}
>
Total Costs to Buy A to B
</span>
<div className="col-md-4">
<input
type="text"
className="form-control"
name="totalCostsAtoB"
value={calculateTotalCosts()}
readOnly
style={{
borderColor: "#fda417", // Custom border color for the input field
color: "#fda417", // Optionally apply text color to the input text
textAlign: "right",
}}
placeholder="Total Costs to Buy A to B"
required
/>
</div>
</div>
<span
style={{
color: "#fda417",
fontSize: "14px",
fontWeight: "bold",
}}
>
Credits
</span>
{formData.credits.map((credits, index) => (
<div key={index} className="row gy-3 align-items-center">
<div className="col-md-4">
<input
type="text"
className="form-control"
value={credits.title}
onChange={(e) =>
handleCreditChange(index, "title", e.target.value)
}
placeholder="credits"
required
/>
</div>
<div className="col-md-4">
<input
type="text"
className={`form-control ${
credits.isInvalid ? "is-invalid" : ""
}`} // Apply 'is-invalid' class when invalid
value={credits.price}
onChange={(e) => handleCreditPriceChange(e, index)} // New handler for price validation
placeholder="Price"
style={{ textAlign: "right" }}
required
/>
{credits.isInvalid && (
<div className="invalid-feedback">
Please enter a valid number.
</div>
)}
</div>
<div className="col-md-2 d-flex justify-content-start">
<button
className="btn btn-danger"
onClick={() => deleteCredits(index)}
style={{ marginLeft: "5px" }}
>
x
</button>
</div>
</div>
))}
<div className="col-md-4">
<button
className="btn btn-primary back"
onClick={addCredits}
style={{ backgroundColor: "#fda417", border: "#fda417" }}
>
<span
style={{
fontSize: "20px",
fontWeight: "normal",
}}
>
+
</span>{" "}
Add credits
</button>
</div>
<div className="row gy-3 align-items-center">
<span
className="col-md-4"
style={{
color: "#fda417",
fontSize: "14px",
fontWeight: "bold",
}}
>
Total Costs to Buy A to B After credits
</span>
<div className="col-md-4">
<input
type="text"
className="form-control"
name="totalCostsAtoBaftercredits"
value={calculateTotalCostsWithCredits()}
readOnly
style={{
borderColor: "#fda417", // Custom border color for the input field
color: "#fda417", // Optionally apply text color to the input text
textAlign: "right",
}}
placeholder="Total Costs to Buy A to B After credits"
required
/>
</div>
</div>
<hr />
<div className="col-md-4">
<button
className="btn btn-primary back"
onClick={handleBack}
style={{ backgroundColor: "#fda417", border: "#fda417" }}
>
Go Back
</button>{" "}
<button
type="button"
className="btn btn-primary continue"
style={{ backgroundColor: "#fda417", border: "#fda417" }}
onClick={handleSubmit}
>
Submit
</button>{" "}
</div>
<br />
</div>
)}
</div>
</div>
</>
);
};
export default Addproperty;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,61 +0,0 @@
import { useState } from 'react';
import "../addproperty.css";
const Addproperty = () => {
const [activeTab, setActiveTab] = useState('billing');
const handleContinue = () => {
if (activeTab === 'billing') setActiveTab('shipping');
else if (activeTab === 'shipping') setActiveTab('review');
};
const handleBack = () => {
if (activeTab === 'review') setActiveTab('shipping');
else if (activeTab === 'shipping') setActiveTab('billing');
};
return (
<div className="container tabs-wrap">
<ul className="nav nav-tabs" role="tablist">
<li role="presentation" className={activeTab === 'billing' ? 'active tab' : 'tab'}>
<a onClick={() => setActiveTab('billing')} role="tab">Billing Address</a>
</li>
<li role="presentation" className={activeTab === 'shipping' ? 'active tab' : 'tab'}>
<a onClick={() => setActiveTab('shipping')} role="tab">Delivery Address</a>
</li>
<li role="presentation" className={activeTab === 'review' ? 'active tab' : 'tab'}>
<a onClick={() => setActiveTab('review')} role="tab">Review &amp; Payment</a>
</li>
</ul>
<div className="tab-content">
{activeTab === 'billing' && (
<div role="tabpanel" className="tab-pane active">
<h3>Billing Address</h3>
<p>Billing Address Form</p>
<button className="btn btn-primary continue" onClick={handleContinue}>Continue</button>
</div>
)}
{activeTab === 'shipping' && (
<div role="tabpanel" className="tab-pane active">
<h3>Shipping Address</h3>
<p>Shipping Address Form</p>
<button className="btn btn-primary back" onClick={handleBack}>Go Back </button>{" "}
<button className="btn btn-primary continue" onClick={handleContinue}>Continue</button>
</div>
)}
{activeTab === 'review' && (
<div role="tabpanel" className="tab-pane active">
<h3>Review &amp; Place Order</h3>
<p>Review &amp; Payment Tab</p>
<button className="btn btn-primary back" onClick={handleBack}>Go Back</button>{" "}
<button className="btn btn-primary continue">Place Order</button>
</div>
)}
</div>
</div>
);
};
export default Addproperty;