done
This commit is contained in:
parent
3b144c93f5
commit
f05a2f5432
|
@ -1,6 +1,5 @@
|
|||
import mysql from "mysql2";
|
||||
|
||||
|
||||
import pool from "../db/db.js";
|
||||
|
||||
const db = mysql.createConnection({
|
||||
host: "db-mysql-nyc1-99306-do-user-12431193-0.b.db.ondigitalocean.com",
|
||||
|
@ -99,3 +98,28 @@ export const searchMySQL = (req, res) => {
|
|||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Controller function to search for MYSQL properties by house_id
|
||||
export const PropertiesMysqlView = async (req, res) => {
|
||||
const { house_id } = req.params;
|
||||
console.log("hu", house_id);
|
||||
|
||||
try {
|
||||
const query = `
|
||||
SELECT address, city, county, state, total_living_sqft, year_built, cost_per_sqft
|
||||
FROM home_information
|
||||
WHERE house_id = ?
|
||||
`;
|
||||
|
||||
const [rows] = await pool.query(query, [house_id]);
|
||||
|
||||
if (rows.length > 0) {
|
||||
res.status(200).json(rows[0]); // Send property details if found
|
||||
} else {
|
||||
res.status(404).json({ message: "Property not found" });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching property details:", error);
|
||||
res.status(500).json({ error: "Internal Server Error" });
|
||||
}
|
||||
};
|
|
@ -31,7 +31,7 @@ export const createProperty = async (req, res) => {
|
|||
|
||||
};
|
||||
|
||||
// Fetch property by userId
|
||||
// Fetch property by userId.. Gets the specif user properties
|
||||
export const getUserProperties = async (req, res) => {
|
||||
try {
|
||||
const userId = req.params.userId;
|
||||
|
@ -42,7 +42,7 @@ export const getUserProperties = async (req, res) => {
|
|||
}
|
||||
};
|
||||
|
||||
// Fetch property by ID
|
||||
// Fetch property by ID.. which is property view page
|
||||
export const getPropertyById = async (req, res) => {
|
||||
const { propertyId } = req.params;
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
import mysql from "mysql2/promise"; // Use promise-based API
|
||||
|
||||
// Create a pool instead of a single connection
|
||||
const pool = mysql.createPool({
|
||||
host: "db-mysql-nyc1-99306-do-user-12431193-0.b.db.ondigitalocean.com",
|
||||
user: "doadmin",
|
||||
password: "AVNS_EPHqPilzmVjZfm8GH4G",
|
||||
database: "defaultdb",
|
||||
port: "25060",
|
||||
waitForConnections: true,
|
||||
connectionLimit: 10, // Number of connections in the pool
|
||||
queueLimit: 0, // No limit on queued connection requests
|
||||
connectTimeout: 20000 // 20 seconds
|
||||
});
|
||||
|
||||
// Test the pool connection
|
||||
pool.getConnection()
|
||||
.then(conn => {
|
||||
console.log("Connected to the MySQL POOL database.");
|
||||
conn.release(); // Release the connection back to the pool
|
||||
})
|
||||
.catch(err => {
|
||||
console.error("Database connection failed: " + err.stack);
|
||||
});
|
||||
|
||||
export default pool;
|
|
@ -20,6 +20,7 @@
|
|||
"morgan": "^1.10.0",
|
||||
"mysql": "^2.18.1",
|
||||
"mysql2": "^3.11.3",
|
||||
"mysql2-promise": "^0.1.4",
|
||||
"nodemailer": "^6.9.14",
|
||||
"nodemon": "^3.1.5",
|
||||
"uuid": "^10.0.0"
|
||||
|
@ -62,6 +63,12 @@
|
|||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/ansicolors": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.2.1.tgz",
|
||||
"integrity": "sha512-tOIuy1/SK/dr94ZA0ckDohKXNeBNqZ4us6PjMVLs5h1w2GBB6uPtOknp2+VF4F/zcy9LI70W+Z+pE2Soajky1w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/anymatch": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
|
@ -141,6 +148,12 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/bn.js": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-2.0.0.tgz",
|
||||
"integrity": "sha512-NmOLApC80+n+P28y06yHgwGlOCkq/X4jRh5s590959FZXSrM+I/61h0xxuIaYsg0mD44mEAZYG/rnclWuRoz+A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/body-parser": {
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
|
||||
|
@ -230,6 +243,19 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/cardinal": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/cardinal/-/cardinal-0.4.4.tgz",
|
||||
"integrity": "sha512-3MxV0o9wOpQcobrcSrRpaSxlYkohCcZu0ytOjJUww/Yo/223q4Ecloo7odT+M0SI5kPgb1JhvSaF4EEuVXOLAQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansicolors": "~0.2.1",
|
||||
"redeyed": "~0.4.0"
|
||||
},
|
||||
"bin": {
|
||||
"cdl": "bin/cdl.js"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||
|
@ -381,6 +407,12 @@
|
|||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/double-ended-queue": {
|
||||
"version": "2.0.0-0",
|
||||
"resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.0.0-0.tgz",
|
||||
"integrity": "sha512-t5ouWOpItmHrm0J0+bX/cFrIjBFWnJkk5LbIJq6bbU/M4aLX2c3LrM4QYsBptwvlPe3WzdpQefQ0v1pe/A5wjg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ecdsa-sig-formatter": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||
|
@ -436,6 +468,18 @@
|
|||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/esprima": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz",
|
||||
"integrity": "sha512-rp5dMKN8zEs9dfi9g0X1ClLmV//WRyk/R15mppFNICIFRG5P92VP7Z04p8pk++gABo9W2tY+kHyu6P1mEHgmTA==",
|
||||
"bin": {
|
||||
"esparse": "bin/esparse.js",
|
||||
"esvalidate": "bin/esvalidate.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/etag": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
|
@ -1203,6 +1247,74 @@
|
|||
"node": ">= 8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mysql2-promise": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/mysql2-promise/-/mysql2-promise-0.1.4.tgz",
|
||||
"integrity": "sha512-/h8ubU/36aIPpbfB6CENw9ZdbzIhZMZOIbstJUHVKp4J9JBRSLScrYImVx+3yZilgag732UhpQMMK5+ktdhLCw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mysql2": "^0.15.7",
|
||||
"q": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mysql2-promise/node_modules/isarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mysql2-promise/node_modules/lru-cache": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz",
|
||||
"integrity": "sha512-dVmQmXPBlTgFw77hm60ud//l2bCuDKkqC2on1EBoM7s9Urm9IQDrnujwZ93NFnAq0dVZ0HBXTS7PwEG+YE7+EQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mysql2-promise/node_modules/mysql2": {
|
||||
"version": "0.15.8",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-0.15.8.tgz",
|
||||
"integrity": "sha512-3x5o6C20bfwJYPSoT74MOoad7/chJoq4qXHDL5VAuRBBrIyErovLoj04Dz/5EY9X2kTxWSGNiTegtxpROTd2YQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bn.js": "2.0.0",
|
||||
"cardinal": "0.4.4",
|
||||
"double-ended-queue": "2.0.0-0",
|
||||
"named-placeholders": "0.1.3",
|
||||
"readable-stream": "1.0.33"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/mysql2-promise/node_modules/named-placeholders": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-0.1.3.tgz",
|
||||
"integrity": "sha512-Mt79RtxZ6MYTIEemPGv/YDKpbuavcAyGHb0r37xB2mnE5jej3uBzc4+nzOeoZ4nZiii1M32URKt9IjkSTZAmTA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lru-cache": "2.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mysql2-promise/node_modules/readable-stream": {
|
||||
"version": "1.0.33",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz",
|
||||
"integrity": "sha512-72KxhcKi8bAvHP/cyyWSP+ODS5ef0DIRs0OzrhGXw31q41f19aoELCbvd42FjhpyEDxQMRiiC5rq9rfE5PzTqg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.1",
|
||||
"isarray": "0.0.1",
|
||||
"string_decoder": "~0.10.x"
|
||||
}
|
||||
},
|
||||
"node_modules/mysql2-promise/node_modules/string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mysql2/node_modules/iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
|
@ -1417,6 +1529,17 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/q": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
|
||||
"integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==",
|
||||
"deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.6.0",
|
||||
"teleport": ">=0.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
|
@ -1498,6 +1621,15 @@
|
|||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/redeyed": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/redeyed/-/redeyed-0.4.4.tgz",
|
||||
"integrity": "sha512-pnk1vsaNLu1UAAClKsImKz9HjBvg9i8cbRqTRzJbiCjGF0fZSMqpdcA5W3juO3c4etFvTrabECkq9wjC45ZyxA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esprima": "~1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
"morgan": "^1.10.0",
|
||||
"mysql": "^2.18.1",
|
||||
"mysql2": "^3.11.3",
|
||||
"mysql2-promise": "^0.1.4",
|
||||
"nodemailer": "^6.9.14",
|
||||
"nodemon": "^3.1.5",
|
||||
"uuid": "^10.0.0"
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import express from "express";
|
||||
import { searchMySQL } from "../controllers/mysqlproperty.js";
|
||||
import { searchMySQL, PropertiesMysqlView } from "../controllers/mysqlproperty.js";
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Define the route
|
||||
router.get("/searchmysql", searchMySQL);
|
||||
router.get("/properties/:house_id", PropertiesMysqlView);
|
||||
|
||||
export default router;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -42,7 +42,7 @@
|
|||
<!-- <script src="https://stackpath.bootstrapcdn.com/bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script> -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<script type="module" crossorigin src="/assets/index-tUPF5Gax.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-DdbR_cuq.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DlbKQED5.css">
|
||||
</head>
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import Registrationsuccess from "./components/Registrationsuccess";
|
|||
import PropertyView from "./components/PropertyView";
|
||||
import SearchMysql from "./components/SearchMysql";
|
||||
import Services from "./components/Services";
|
||||
import PropertyMysqlView from "./components/PropertyMysqlView";
|
||||
|
||||
|
||||
const App = () => {
|
||||
|
@ -58,8 +59,7 @@ const App = () => {
|
|||
{/* <Route path="/addproperty" element={ <PrivateRoute><Addproperty /></PrivateRoute>}></Route> */}
|
||||
|
||||
<Route path="/property/:id" element={<PropertyView />} />
|
||||
<Route path="/properties/:id" element={<PropertyView />} />
|
||||
|
||||
<Route path="/properties/:house_id" element={<PropertyMysqlView />} />
|
||||
<Route path="/searchmyproperties" element={<SearchMysql />} />
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import axios from "axios";
|
||||
import Navbar from "./Navbar";
|
||||
import Footer from "./Footer";
|
||||
|
||||
const PropertyMysqlView = () => {
|
||||
const { house_id } = useParams(); // Get house_id from the URL
|
||||
|
||||
console.log("house_id", house_id);
|
||||
const [propertyDetails, setPropertyDetails] = useState(null); // State for property details
|
||||
const [loading, setLoading] = useState(true); // Loader state
|
||||
|
||||
// Fetch property details from API
|
||||
useEffect(() => {
|
||||
const fetchPropertyDetails = async () => {
|
||||
try {
|
||||
const res = await axios.get(
|
||||
`${import.meta.env.VITE_REACT_APP_SECRET}/mysql/properties/${house_id}`
|
||||
);
|
||||
setPropertyDetails(res.data); // Set the property details
|
||||
} catch (err) {
|
||||
console.log("Error fetching property details:", err);
|
||||
} finally {
|
||||
setLoading(false); // Stop loading
|
||||
}
|
||||
};
|
||||
|
||||
fetchPropertyDetails();
|
||||
}, [house_id]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
<br /> <br /> <br /> <br /> <br /> <br /> <br /> <br />
|
||||
<div className="container">
|
||||
{loading ? (
|
||||
<div className="loader">Loading...</div> // Loader
|
||||
) : propertyDetails ? (
|
||||
<div className="property-details">
|
||||
<h2>Property Details</h2>
|
||||
<p><strong>Address:</strong> {propertyDetails.address}</p>
|
||||
<p><strong>City:</strong> {propertyDetails.city}</p>
|
||||
<p><strong>County:</strong> {propertyDetails.county}</p>
|
||||
<p><strong>State:</strong> {propertyDetails.state}</p>
|
||||
<p><strong>Total Living Square Foot:</strong> {propertyDetails.total_living_sqft}</p>
|
||||
<p><strong>Year Built:</strong> {propertyDetails.year_built}</p>
|
||||
<p><strong>Cost per Square Foot:</strong> ${propertyDetails.cost_per_sqft}/sqft</p>
|
||||
</div>
|
||||
) : (
|
||||
<p>No property details found.</p>
|
||||
)}
|
||||
</div>
|
||||
<br /> <br /> <br /> <br />
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PropertyMysqlView;
|
|
@ -1,4 +1,4 @@
|
|||
import { useEffect, useState, useCallback } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { NavLink } from "react-router-dom";
|
||||
import axios from "axios";
|
||||
import Navbar from "./Navbar";
|
||||
|
@ -8,59 +8,45 @@ import "../searchmysqlresults.css";
|
|||
const SearchMysql = () => {
|
||||
const [properties, setProperties] = useState([]);
|
||||
const [totalRecords, setTotalRecords] = useState(0);
|
||||
const [page, setPage] = useState(0); // Page number
|
||||
const [limit] = useState(10); // Items per page
|
||||
const [search, setSearch] = useState(""); // Search query state
|
||||
const [loading, setLoading] = useState(false); // Loader state
|
||||
const [page, setPage] = useState(0);
|
||||
const [limit] = useState(10);
|
||||
const [search, setSearch] = useState("");
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [showResultsMessage, setShowResultsMessage] = useState(false);
|
||||
|
||||
// Fetch properties from API
|
||||
const fetchProperties = async () => {
|
||||
setLoading(true);
|
||||
setIsLoading(true);
|
||||
setShowResultsMessage(false); // Reset message before fetching
|
||||
try {
|
||||
const res = await axios.get(
|
||||
`${import.meta.env.VITE_REACT_APP_SECRET}/mysql/searchmysql`,
|
||||
{
|
||||
params: { limit, offset: page * limit, search },
|
||||
headers: { "Cache-Control": "no-cache" }, // Disable caching
|
||||
headers: { "Cache-Control": "no-cache" },
|
||||
}
|
||||
);
|
||||
setProperties(res.data.data); // Set properties
|
||||
setTotalRecords(res.data.totalRecords); // Set total records
|
||||
setProperties(res.data.data);
|
||||
setTotalRecords(res.data.totalRecords);
|
||||
if (search.trim()) {
|
||||
setShowResultsMessage(true); // Show message if there's a search term
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("Error fetching data:", err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Debounce the search input
|
||||
const debounce = (func, delay) => {
|
||||
let timer;
|
||||
return (...args) => {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => func(...args), delay);
|
||||
};
|
||||
};
|
||||
|
||||
// Debounced fetch properties
|
||||
const debouncedFetchProperties = useCallback(
|
||||
debounce(() => {
|
||||
if (search.trim() === "") {
|
||||
fetchProperties(); // Fetch default properties when search is empty
|
||||
} else {
|
||||
fetchProperties(); // Fetch properties with new search term
|
||||
}
|
||||
}, 3000), // 3 seconds delay
|
||||
[search, page]
|
||||
);
|
||||
|
||||
// Handle search input change
|
||||
const handleSearchChange = (e) => {
|
||||
setSearch(e.target.value);
|
||||
// Trigger search only if input is non-empty
|
||||
if (e.target.value.trim() === "") {
|
||||
setPage(0); // Reset to first page
|
||||
fetchProperties(); // Fetch default properties immediately
|
||||
setProperties([]); // Clear properties
|
||||
setTotalRecords(0); // Clear total records
|
||||
setShowResultsMessage(false); // Hide message
|
||||
fetchProperties(); // Fetch default properties
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -68,33 +54,21 @@ const SearchMysql = () => {
|
|||
const handleKeyPress = (e) => {
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
if (search.trim()) {
|
||||
debouncedFetchProperties(); // Fetch properties on Enter key
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Handle input blur to fetch results after typing
|
||||
const handleBlur = () => {
|
||||
if (search.trim() !== "") {
|
||||
debouncedFetchProperties(); // Fetch properties after typing is complete
|
||||
fetchProperties(); // Fetch properties on Enter key
|
||||
}
|
||||
};
|
||||
|
||||
// Use effect to fetch properties when search or page changes
|
||||
useEffect(() => {
|
||||
// Fetch default properties when the component mounts or page changes
|
||||
if (search.trim() === "") {
|
||||
fetchProperties(); // Fetch default properties
|
||||
}
|
||||
}, [page]);
|
||||
fetchProperties();
|
||||
}, [search, page]); // Fetch when search or page changes
|
||||
|
||||
const totalPages = Math.ceil(totalRecords / limit);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
<br /> <br /> <br /> <br /> <br /> <br />
|
||||
{/* Display properties */}
|
||||
<br /> <br /> <br /> <br /> <br /> <br />
|
||||
<div className="container col-12">
|
||||
<div className="row">
|
||||
<div className="col-lg-12 card-margin col-12">
|
||||
|
@ -114,10 +88,8 @@ const SearchMysql = () => {
|
|||
value={search}
|
||||
onChange={handleSearchChange}
|
||||
onKeyDown={handleKeyPress}
|
||||
onBlur={handleBlur} // Trigger search on blur
|
||||
/>
|
||||
</div>
|
||||
<div className="col-lg-1 col-md-3 col-sm-12 p-0"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -130,147 +102,106 @@ const SearchMysql = () => {
|
|||
<div className="col-12">
|
||||
<div className="card card-margin">
|
||||
<div className="card-body">
|
||||
{loading ? (
|
||||
<div className="loader" style={{color:"#fda417"}}><span style={{color:"#fda417", fontSize: "25px"}}>Loading...</span></div>
|
||||
) : (
|
||||
<div className="row search-body">
|
||||
<div className="col-lg-12">
|
||||
<div className="search-result col-12">
|
||||
<div className="result-header">
|
||||
<div className="row">
|
||||
<div className="col-lg-6">
|
||||
<div className="records">
|
||||
{/* Pagination Controls */}
|
||||
<div>
|
||||
<button
|
||||
onClick={() => setPage(page - 1)}
|
||||
disabled={page === 0}
|
||||
style={{
|
||||
backgroundColor: "#fda417",
|
||||
border: "#fda417",
|
||||
}}
|
||||
>
|
||||
Previous
|
||||
</button>
|
||||
<span>
|
||||
{" "}
|
||||
Page {page + 1} of {totalPages}{" "}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => setPage(page + 1)}
|
||||
disabled={page + 1 >= totalPages}
|
||||
style={{
|
||||
backgroundColor: "#fda417",
|
||||
border: "#fda417",
|
||||
}}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="result-body">
|
||||
<div className="table-responsive">
|
||||
<table className="table widget-26">
|
||||
{/* Add table headers */}
|
||||
<thead style={{color:"#fda417", fontSize: "15px"}}>
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<th>Total Living Square Foot</th>
|
||||
<th>Year Built</th>
|
||||
<th>Cost per Square Foot</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{properties.length > 0 ? (
|
||||
properties.map((property, index) => (
|
||||
<tr key={index}>
|
||||
<td>
|
||||
<div className="widget-26-job-title">
|
||||
<NavLink
|
||||
to={`/properties/${property.house_id}`}
|
||||
className="link-primary text-decoration-none"
|
||||
>
|
||||
{property.address}
|
||||
</NavLink>
|
||||
<p className="m-0">
|
||||
<span className="employer-name">
|
||||
<i
|
||||
className="fa fa-map-marker"
|
||||
style={{ color: "#F74B02" }}
|
||||
/>
|
||||
{property.city}, {property.county},
|
||||
{property.state}
|
||||
</span>{" "}
|
||||
<p className="text-muted m-0">
|
||||
House Id: {property.house_id}
|
||||
</p>
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div className="widget-26-job-info">
|
||||
<p className="m-0">
|
||||
{property.total_living_sqft}
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div className="widget-26-job-info">
|
||||
<p className="m-0">
|
||||
{property.year_built}
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div className="widget-26-job-salary">
|
||||
$ {property.cost_per_sqft}/sqft
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
) : (
|
||||
<tr>
|
||||
<td colSpan="4">No results found</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{/* Pagination Controls */}
|
||||
<div>
|
||||
<button
|
||||
onClick={() => setPage(page - 1)}
|
||||
disabled={page === 0}
|
||||
style={{
|
||||
backgroundColor: "#fda417",
|
||||
border: "#fda417",
|
||||
}}
|
||||
>
|
||||
Previous
|
||||
</button>
|
||||
<span>
|
||||
{" "}
|
||||
Page {page + 1} of {totalPages}{" "}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => setPage(page + 1)}
|
||||
disabled={page + 1 >= totalPages}
|
||||
style={{
|
||||
backgroundColor: "#fda417",
|
||||
border: "#fda417",
|
||||
}}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{showResultsMessage && properties.length > 0 && (
|
||||
<div>
|
||||
Showing search results for the keyword <span style={{ color: "#fda417", fontSize: "25px" }}>{search}</span>
|
||||
|
||||
</div>
|
||||
)}
|
||||
<div className="table-responsive">
|
||||
<table className="table widget-26">
|
||||
<thead style={{ color: "#fda417", fontSize: "15px" }}>
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<th>Total Living Square Foot</th>
|
||||
<th>Year Built</th>
|
||||
<th>Cost per Square Foot</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{properties.length > 0 ? (
|
||||
properties.map((property, index) => (
|
||||
<tr key={index}>
|
||||
<td>
|
||||
<div className="widget-26-job-title">
|
||||
<NavLink
|
||||
to={`/properties/${property.house_id}`}
|
||||
className="link-primary text-decoration-none"
|
||||
target="_blank"
|
||||
>
|
||||
{property.address}
|
||||
</NavLink>
|
||||
<p className="m-0">
|
||||
<span className="employer-name">
|
||||
<i
|
||||
className="fa fa-map-marker"
|
||||
style={{ color: "#F74B02" }}
|
||||
/>
|
||||
{property.city}, {property.county},
|
||||
{property.state}
|
||||
</span>
|
||||
<p className="text-muted m-0">
|
||||
House Id: {property.house_id}
|
||||
</p>
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div className="widget-26-job-info">
|
||||
<p className="m-0">
|
||||
{property.total_living_sqft}
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div className="widget-26-job-info">
|
||||
<p className="m-0">
|
||||
{property.year_built}
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div className="widget-26-job-salary">
|
||||
$ {property.cost_per_sqft}/sqft
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
) : (
|
||||
<tr>
|
||||
<td colSpan="4">No results found</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/* Pagination Controls */}
|
||||
<div>
|
||||
<button
|
||||
onClick={() => setPage(page - 1)}
|
||||
disabled={page === 0 || isLoading}
|
||||
style={{
|
||||
backgroundColor: "#fda417",
|
||||
border: "#fda417",
|
||||
}}
|
||||
>
|
||||
Previous
|
||||
</button>
|
||||
<span>
|
||||
{" "}
|
||||
Page {page + 1} of {totalPages}{" "}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => setPage(page + 1)}
|
||||
disabled={page + 1 >= totalPages || isLoading}
|
||||
style={{
|
||||
backgroundColor: "#fda417",
|
||||
border: "#fda417",
|
||||
}}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue