This commit is contained in:
omkieit 2024-10-23 00:13:17 +05:30
parent 2dd33296d0
commit d02de3dafa
11 changed files with 379 additions and 366 deletions

View File

@ -35,3 +35,13 @@ export const getFundDetailsById = async (req, res) => {
res.status(500).json({ message: error.message });
}
};
export const getAllFunds = async (req, res) => {
try {
// const allFunds = await FundDetailsModal.find();
const allFunds = await FundDetailsModal.findOne();
res.status(200).json(allFunds);
} catch (error) {
res.status(500).json({ message: "Server error" });
}
};

View File

@ -80,9 +80,10 @@ export const getPropertyById = async (req, res) => {
export const updatePropertyById = async (req, res) => {
const { id } = req.params; // This should be the propertyId
const updateData = req.body;
const fundDetails=req.body
console.log("Received propertyId:", id); // Log the received propertyId
console.log("updateData", updateData);
console.log("fundDetails", fundDetails);
try {
// Find the property by propertyId instead of _id

View File

@ -302,6 +302,7 @@ const propertySchema = mongoose.Schema({
type: Number,
required: true, // Set to true if this field is mandatory
},
fundDetails:[],
});
const PropertyModal = mongoose.model("property", propertySchema);

View File

@ -1,10 +1,12 @@
import express from 'express';
const router = express.Router();
import { submitFundDetails, getFundDetailsById } from '../controllers/fundDetails.js';
import { getAllFunds } from '../controllers/fundDetails.js';
router.post('/', submitFundDetails);
router.get("/allFunds", getAllFunds);
router.get("/:id", getFundDetailsById);
export default router;

File diff suppressed because one or more lines are too long

View File

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

View File

@ -20,6 +20,7 @@ import EditProperty from "./components/EditProperty";
import SearchProperties from "./components/SearchProperties";
import ProfileView from "./components/ProfileView";
const App = () => {
return (
<BrowserRouter>
@ -31,6 +32,7 @@ const App = () => {
<Route path="/contact" element={<Contact />}></Route>
<Route path="/register" element={<Register />}></Route>
<Route
path="/registrationsuccess"
element={

View File

@ -1,110 +0,0 @@
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 Navbar from "./Navbar";
import Footer from "./Footer";
const EditProperty = () => {
const { id } = useParams();
const dispatch = useDispatch();
const { selectedProperty } = useSelector((state) => state.property);
const [formData, setFormData] = useState({
propertyType: "",
yearBuild: "",
totalSqft: "",
});
useEffect(() => {
dispatch(fetchPropertyById(id));
}, [dispatch, id]);
useEffect(() => {
if (selectedProperty) {
setFormData({
propertyType: selectedProperty.propertyType,
yearBuild: selectedProperty.yearBuild,
totalSqft: selectedProperty.totalSqft,
});
}
}, [selectedProperty]);
const handleChange = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
const handleSubmit = (e) => {
e.preventDefault();
dispatch(updateProperty({ id, propertyData: formData }));
};
return (
<>
<Navbar />
<br /> <br /> <br /> <br /> <br /> <br />
<div className="edit-property-form">
<h2>Edit Property</h2>
<form onSubmit={handleSubmit}>
<div>
<select
className="form-floating mb-3 form-control"
name="propertyType"
value={formData.propertyType}
onChange={handleChange}
required
>
<option value="">Please Select Property Type</option>
<option value="Residential">Residential</option>
<option value="Land">Land</option>
<option value="Commercial">Commercial</option>
<option value="Industrial">Industrial</option>
<option value="Water">Water</option>
</select>
</div>
<div className="col-12">
<div className="form-floating mb-3">
<input
type="text"
className="form-control"
name="yearBuild"
value={formData.yearBuild}
onChange={handleChange}
placeholder="Year build"
required
/>
<label htmlFor="yearBuild" className="form-label">
Year Build
</label>
</div>
</div>
<div className="form-floating mb-3">
<input
type="text"
className="form-control"
name="totalSqft"
value={formData.totalSqft}
onChange={handleChange}
placeholder="Total SQFT"
required
/>
<label htmlFor="totalSqft" className="form-label">
Total SQFT
</label>
</div>
<button type="submit">Update Property</button>
</form>
</div>
<Footer />
</>
);
};
export default EditProperty;

View File

@ -6,7 +6,10 @@ import propertydummy from "../img/propertydummy.jpg";
import Navbar from "./Navbar";
import Footer from "./Footer";
import { Modal, Button, Form } from "react-bootstrap"; // Importing Modal components
import { submitFundDetails } from "../redux/features/fundDetailsSlice";
import {
submitFundDetails,
getFundDetailsById,
} from "../redux/features/fundDetailsSlice";
import { useNavigate } from "react-router-dom";
const PropertyView = () => {
@ -17,22 +20,39 @@ const PropertyView = () => {
(state) => state.property
);
const { user } = useSelector((state) => ({ ...state.auth }));
const { fundDetails } = useSelector((state) => state.fundDetails);
console.log("funddetails", fundDetails);
const [activeTab, setActiveTab] = useState("propertydetails");
const [loading, setLoading] = useState(true); // Loader state
const [showModal, setShowModal] = useState(false); // Modal state
const [fundValue, setFundValue] = useState(""); // Fund value state
const [fundPercentage, setFundPercentage] = useState(""); // Fund percentage state
useEffect(() => {
// Fetch the property by ID when the component loads
if (id) {
dispatch(fetchPropertyById(id));
setLoading(false);
dispatch(getFundDetailsById(id));
}
}, [id, dispatch]);
if (status === "loading") {
return <p>Loading property details...</p>;
useEffect(() => {
if (status === "succeeded") {
setLoading(false);
}
}, [status]);
useEffect(() => {
if (fundDetails) {
setFundValue(fundDetails.investmentAmount);
setFundPercentage(fundDetails.ownershipPercentage);
}
}, [fundDetails]);
// if (status === "loading") {
// return <p>Loading property details...</p>;
// }
if (status === "failed") {
return <p>Error loading property: {error}</p>;
@ -53,6 +73,10 @@ const PropertyView = () => {
// Inside your PropertyView component
const handleSubmit = (e) => {
e.preventDefault();
if (fundValue <= 0 || fundPercentage <= 0 || fundPercentage > 100) {
alert("Please enter valid values.");
return;
}
const fundDetails = {
propertyOwnerId: selectedProperty?.userId,
@ -70,6 +94,44 @@ const PropertyView = () => {
<>
<Navbar />
<br /> <br /> <br /> <br />
<br /> <br />
<div className="container tabs-wrap col-12">
<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 === "Funding Details" ? "active tab" : "tab"}
>
<a onClick={() => setActiveTab("Funding Details")} role="tab">
Funding Details
</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 container tab-pane active col-12"
>
<div className="container col-12">
{loading ? (
<div className="loader">Loading...</div> // Loader
@ -79,14 +141,18 @@ const PropertyView = () => {
<div className="row">
<div className="col-md-5 mt-3">
<div>
{selectedProperty.images && selectedProperty.images[0] ? (
{selectedProperty.images &&
selectedProperty.images[0] ? (
<img
src={selectedProperty.images[0].file || propertydummy}
src={
selectedProperty.images[0].file ||
propertydummy
}
alt="Property Thumbnail"
style={{
marginTop: "0px",
maxWidth: "500px",
maxHeight: "500px",
maxWidth: "400px",
maxHeight: "400px",
}}
/>
) : (
@ -95,11 +161,18 @@ const PropertyView = () => {
alt="Default Property Thumbnail"
style={{
marginTop: "0px",
maxWidth: "500px",
maxHeight: "500px",
maxWidth: "400px",
maxHeight: "400px",
}}
/>
)}
{/* <img
src={selectedProperty.images?.[0]?.file || propertydummy}
alt="Property Thumbnail"
style={{ marginTop: "0px", maxWidth: "400px", maxHeight: "400px" }}
loading="lazy"
/> */}
</div>
<br />
<div className="label-stock border">
@ -111,8 +184,10 @@ const PropertyView = () => {
fontWeight: "normal",
}}
>
Total Funding Amount:{" "}
<span style={{ color: "#000000", fontSize: "25px" }}>
Funding Required:{" "}
<span
style={{ color: "#000000", fontSize: "25px" }}
>
<span
className="fa fa-dollar"
style={{ color: "#F74B02" }}
@ -129,7 +204,9 @@ const PropertyView = () => {
}}
>
Net profit:{" "}
<span style={{ color: "#000000", fontSize: "25px" }}>
<span
style={{ color: "#000000", fontSize: "25px" }}
>
<span
className="fa fa-dollar"
style={{ color: "#F74B02" }}
@ -143,9 +220,14 @@ const PropertyView = () => {
{/* "Willing to Invest/Fund" Button and Conditional Messages */}
<button
className="btn btn-primary back"
style={{ backgroundColor: "#fda417", border: "#fda417" }}
style={{
backgroundColor: "#fda417",
border: "#fda417",
}}
disabled={isOwner || !isLoggedIn}
onClick={isOwner || !isLoggedIn ? null : handleShowModal} // Show modal only if not owner or logged in
onClick={
isOwner || !isLoggedIn ? null : handleShowModal
} // Show modal only if not owner or logged in
>
<span
style={{
@ -158,12 +240,12 @@ const PropertyView = () => {
</button>
{isOwner && (
<span style={{ color: "red", marginTop: "10px" }}>
You cannot invest on your property.
You cannot invest in your own property.
</span>
)}
{!isLoggedIn && (
<span style={{ color: "red", marginTop: "10px" }}>
Please login to submit.
Please login to invest.
</span>
)}
</div>
@ -181,24 +263,32 @@ const PropertyView = () => {
</h4>
<hr />
<p className="product-path">
<span style={{ color: "#fda417", fontSize: "15px" }}>
<span
style={{ color: "#fda417", fontSize: "15px" }}
>
City:{" "}
</span>{" "}
{selectedProperty.city}
{" "} /{" "}
{" "}
{" "}
<span style={{ color: "#fda417", fontSize: "15px" }}>
<span
style={{ color: "#fda417", fontSize: "15px" }}
>
County:{" "}
</span>{" "}
{selectedProperty.county} {" "}/{" "}
{" "}
<span style={{ color: "#fda417", fontSize: "15px" }}>
<span
style={{ color: "#fda417", fontSize: "15px" }}
>
State:{" "}
</span>{" "}
{selectedProperty.state} {" "}/ {" "}
{" "}
<span style={{ color: "#fda417", fontSize: "15px" }}>
<span
style={{ color: "#fda417", fontSize: "15px" }}
>
Zipcode:{" "}
</span>{" "}
{selectedProperty.zip}
@ -260,17 +350,19 @@ const PropertyView = () => {
</div>
<div className="card-body">
<p>
Lorem Ipsum is simply dummy text of the printing and
typesetting industry. Lorem Ipsum has been the
industry's standard dummy text ever since the 1500s,
when an unknown printer took a galley of type and
scrambled it to make a type specimen book. It has
survived not only five centuries, but also the leap into
electronic typesetting, remaining essentially unchanged.
It was popularised in the 1960s with the release of
Letraset sheets containing Lorem Ipsum passages, and
more recently with desktop publishing software like
Aldus PageMaker including versions of Lorem Ipsum.
Lorem Ipsum is simply dummy text of the printing
and typesetting industry. Lorem Ipsum has been
the industry's standard dummy text ever since
the 1500s, when an unknown printer took a galley
of type and scrambled it to make a type specimen
book. It has survived not only five centuries,
but also the leap into electronic typesetting,
remaining essentially unchanged. It was
popularised in the 1960s with the release of
Letraset sheets containing Lorem Ipsum passages,
and more recently with desktop publishing
software like Aldus PageMaker including versions
of Lorem Ipsum.
</p>
</div>
</div>
@ -282,6 +374,31 @@ const PropertyView = () => {
<p>No property found.</p>
)}
</div>
</div>
)}
{activeTab === "Funding Details" && (
<div>
{activeTab === "Funding Details" && (
<div className="tab-pane active">
{fundDetails ? (
<div>
<p>Investment Amount: ${fundDetails.investmentAmount}</p>
<p>
Ownership Percentage: {fundDetails.ownershipPercentage}%
</p>
</div>
) : (
<p>No funding details available.</p>
)}
</div>
)}
</div>
)}
{activeTab === "Accounting" && <div></div>}
</div>
</div>
<Footer />
{/* Modal for Investment/Funding */}
<Modal show={showModal} onHide={handleCloseModal}>
@ -290,42 +407,25 @@ const PropertyView = () => {
</Modal.Header>
<Modal.Body>
<Form onSubmit={handleSubmit}>
<Form.Group controlId="fundValue">
<Form.Label>Investment Amount ($)</Form.Label>
<Form.Group>
<Form.Label>Fund Value</Form.Label>
<Form.Control
type="number"
placeholder="Enter amount"
value={fundValue}
onChange={(e) => setFundValue(e.target.value)}
required
/>
</Form.Group>
<Form.Group controlId="fundPercentage">
<Form.Label>Ownership Percentage (%)</Form.Label>
<Form.Group>
<Form.Label>Fund Percentage</Form.Label>
<Form.Control
type="number"
placeholder="Enter percentage"
value={fundPercentage}
onChange={(e) => setFundPercentage(e.target.value)}
required
/>
</Form.Group>
<Button
variant="primary"
type="submit"
style={{ backgroundColor: "#fda417", border: "#fda417" }}
>
<Button variant="primary" type="submit">
Submit
</Button>
{" "}
<Button
variant="primary"
onClick={handleCloseModal}
style={{ backgroundColor: "#d80b0b", border: "#d80b0b" }}
>
close
</Button>
</Form>
</Modal.Body>
</Modal>

View File

@ -26,7 +26,8 @@ export const fetchUserProperties = (userId, page, limit) => API.get( `/propertie
export const fetchPropertyById = (id) => API.get(`/properties/${id}`, id);
export const updateProperty = (id, propertyData) => API.put(`/properties/${id}`, propertyData);
export const showUser = (userId) => API.get(`/users/${userId}`);
export const submitFundDetails = (fundDetails) => API.post(`/fundDetails`, fundDetails);
export const submitFundDetails = (fundDetailsArray) => API.post(`/fundDetails`, fundDetailsArray);
export const getFundDetailsById = (fundDetails) => API.post(`/fundDetails`, fundDetails);

View File

@ -64,6 +64,10 @@ export const updateProperty = createAsyncThunk(
}
);
// export const getProperties = createAsyncThunk("property/getProperties", async () => {
// const response = await axios.get(`${import.meta.env.VITE_REACT_APP_SECRET}/properties`); // Backend endpoint
// return response.data;
@ -164,6 +168,8 @@ const propertySlice = createSlice({
state.loading = false;
state.error = action.error.message;
})
;
},
});