This commit is contained in:
omkieit 2024-09-22 16:33:36 +05:30
parent dd8f1e6463
commit 7be342c671
9 changed files with 158 additions and 70 deletions

View File

@ -1,5 +1,5 @@
import mysql from "mysql2"; import mysql from "mysql2";
import pool from "../db/db.js"; // import pool from "../db/db.js";
const db = mysql.createConnection({ const db = mysql.createConnection({
host: "db-mysql-nyc1-99306-do-user-12431193-0.b.db.ondigitalocean.com", host: "db-mysql-nyc1-99306-do-user-12431193-0.b.db.ondigitalocean.com",

View File

@ -5,15 +5,16 @@ import mongoose from "mongoose";
export const createProperty = async (req, res) => { export const createProperty = async (req, res) => {
const propertyData = req.body; const propertyData = req.body;
// console.log('Property received:', propertyData); console.log('Property received:', propertyData);
function generateRandomNumber() { function generateRandomNumber() {
return Math.floor(Math.random() * 90000) + 10000; return Math.floor(Math.random() * 90000) + 10000;
} }
const randomNumber = generateRandomNumber().toString(); const randomNumber = generateRandomNumber().toString();
const propertyId = `EFPI${randomNumber}`; const propertyId = `ELPI${randomNumber}`;
const newProperty = new PropertyModal({ const newProperty = new PropertyModal({
...propertyData, ...propertyData,
_id: new mongoose.Types.ObjectId(), // Explicitly generating _id
creator: req.userId, creator: req.userId,
createdAt: new Date().toISOString(), createdAt: new Date().toISOString(),
publishedAt: new Date().toISOString(), publishedAt: new Date().toISOString(),
@ -21,27 +22,49 @@ export const createProperty = async (req, res) => {
propertyId: propertyId, propertyId: propertyId,
}); });
console.log('newProperty received:', newProperty);
try { try {
await newProperty.save(); await newProperty.save();
res.status(201).json(newProperty); res.status(201).json(newProperty);
} catch (error) { } catch (error) {
res.status(404).json({ message: "Something went wrong" }); // Log the full error object to see what's inside
} console.log("Error fetching properties:", error);
// Capture and return a meaningful error message
if (error.response && error.response.data) {
return rejectWithValue(error.response.data);
} else {
return rejectWithValue({ message: "Unknown error occurred" });
}
}
}; };
// Fetch property by userId.. Gets the specif user properties // Fetch property by userId.. Gets the specific user properties
export const getUserProperties = async (req, res) => { export const getUserProperties = async (req, res) => {
const { userId } = req.params;
const { page = 1, limit = 10 } = req.query; // Defaults to page 1 and limit 10
const skip = (page - 1) * limit;
try { try {
const userId = req.params.userId; const properties = await PropertyModal.find({ userId: userId })
const properties = await PropertyModal.find({ userId: userId }); .skip(skip)
res.status(200).json(properties); .limit(Number(limit));
const total = await PropertyModal.countDocuments({ userId });
const totalPages = Math.ceil(total / limit);
res.json({
properties,
totalPages,
currentPage: Number(page),
});
} catch (error) { } catch (error) {
res.status(500).json({ message: "Error retrieving properties", error }); res.status(500).json({ message: "Error retrieving properties", error });
} }
}; };
// Fetch property by ID.. which is property view page // Fetch property by ID.. which is property view page
export const getPropertyById = async (req, res) => { export const getPropertyById = async (req, res) => {
const { propertyId } = req.params; const { propertyId } = req.params;

View File

@ -25,7 +25,7 @@ export const signup = async (req, res) => {
// Hash the password // Hash the password
const hashedPassword = await bcrypt.hash(password, 12); const hashedPassword = await bcrypt.hash(password, 12);
const randomNumber = generateRandomNumber().toString(); const randomNumber = generateRandomNumber().toString();
const userId = `EF${randomNumber}`; const userId = `ELUI${randomNumber}`;
// Create new user // Create new user
const result = await UserModal.create({ const result = await UserModal.create({

View File

@ -1,7 +1,6 @@
import mongoose from "mongoose"; import mongoose from "mongoose";
const propertySchema = mongoose.Schema({ const propertySchema = mongoose.Schema({
_id: { type: String, required: true }, // Allow string IDs
propertyType: {type: String, required: true }, propertyType: {type: String, required: true },
title: {type: String, required: true }, title: {type: String, required: true },
yearBuild: {type: String, required: true }, yearBuild: {type: String, required: true },

File diff suppressed because one or more lines are too long

View File

@ -45,7 +45,7 @@
<script type="module" crossorigin src="/assets/index-Bn1lHNVo.js"></script> <script type="module" crossorigin src="/assets/index-BbUOB2Bi.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BtU0nZSp.css"> <link rel="stylesheet" crossorigin href="/assets/index-BtU0nZSp.css">
</head> </head>

View File

@ -1,51 +1,97 @@
import { useEffect } from "react"; import { useEffect, useState } from "react";
import { useSelector, useDispatch } from "react-redux"; import { useSelector, useDispatch } from "react-redux";
import { fetchUserProperties } from "../redux/features/propertySlice"; import { fetchUserProperties } from "../redux/features/propertySlice";
import { NavLink } from "react-router-dom"; import { NavLink } from "react-router-dom";
const UserProperties = () => { const UserProperties = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { user } = useSelector((state) => ({ ...state.auth })); const { user } = useSelector((state) => ({ ...state.auth }));
const { userProperties} = useSelector((state) => state.property); const { userProperties, totalPages } = useSelector(
(state) => state.property
);
const [page, setPage] = useState(1);
const limit = 5; // Number of properties per page
// Fetch user properties when "Active Properties" tab is selected // Fetch user properties when "Active Properties" tab is selected
useEffect(() => { useEffect(() => {
dispatch(fetchUserProperties({ userId: user.result.userId, page, limit }));
},[dispatch, user?.result?.userId, page]);
dispatch(fetchUserProperties(user?.result?.userId)); // Pagination handler
const handlePageChange = (newPage) => {
}, [dispatch, user?.result?.userId]); setPage(newPage);
};
return ( return (
<> <>
{userProperties.length > 0 ? ( {userProperties.length > 0 ? (
<>
<ul> <ul>
{userProperties.map((property) => ( {userProperties.map((property) => (
<li key={property._id}> <li key={property._id}>
<NavLink to={`/property/${property.propertyId}`} target="_blank"> <NavLink
to={`/property/${property.propertyId}`}
target="_blank"
>
{property.title} {property.title}
{"....."} {"....."}
</NavLink> </NavLink>
<NavLink to={`/editproperty/${property.propertyId}`} target="_blank"> <NavLink
to={`/editproperty/${property.propertyId}`}
target="_blank"
>
Edit Edit
{"....."} {"....."}
</NavLink> </NavLink>
</li> </li>
))} ))}
</ul> </ul>
{/* Pagination Controls */}
<div className="pagination">
<button
onClick={() => handlePageChange(page - 1)}
disabled={page === 1}
>
Previous
</button>
{/* Show page numbers */}
{Array.from({ length: totalPages }, (_, index) => index + 1).map(
(pageNumber) =>
pageNumber === page || // Current page
pageNumber === 1 || // First page
pageNumber === totalPages || // Last page
(pageNumber >= page - 1 && pageNumber <= page + 1) // Pages near current page
? (
<button
key={pageNumber}
onClick={() => handlePageChange(pageNumber)}
disabled={page === pageNumber}
>
{pageNumber}
</button>
)
: pageNumber === 2 || pageNumber === totalPages - 1 // Add "..." between non-adjacent pages
? <span key={pageNumber}>...</span>
: null
)}
<button
onClick={() => handlePageChange(page + 1)}
disabled={page === totalPages}
>
Next
</button>
</div>
</>
) : ( ) : (
<p>No active properties found.</p> <p>No active properties found.</p>
)} )}
</> </>
) );
} };
export default UserProperties export default UserProperties;

View File

@ -20,7 +20,9 @@ export const signUp = (formData) => API.post("/users/signup", formData);
export const signIn = (formData) => API.post("/users/signin", formData); export const signIn = (formData) => API.post("/users/signin", formData);
export const verifyEmail = (id, token, data) => API.get(`/users/${id}/verify/${token}`, data); export const verifyEmail = (id, token, data) => API.get(`/users/${id}/verify/${token}`, data);
export const submitProperty = (propertyData) => API.post("/properties", propertyData); export const submitProperty = (propertyData) => API.post("/properties", propertyData);
export const fetchUserProperties = (userId) => API.get(`/properties/user/${userId}`, userId); // export const fetchUserProperties = (userId) => API.get(`/properties/user/${userId}`, userId);
export const fetchUserProperties = (userId, page, limit) => API.get( `/properties/user/${userId}?page=${page}&limit=${limit}`, userId);
export const fetchPropertyById = (id) => API.get(`/properties/${id}`, id); export const fetchPropertyById = (id) => API.get(`/properties/${id}`, id);
export const updateProperty = (id, propertyData) => API.put(`/properties/${id}`, propertyData); export const updateProperty = (id, propertyData) => API.put(`/properties/${id}`, propertyData);

View File

@ -13,11 +13,25 @@ export const submitProperty = createAsyncThunk(
} }
); );
// Action to fetch user properties without pagination
// export const fetchUserProperties = createAsyncThunk(
// "property/fetchUserProperties",
// async (userId, { rejectWithValue }) => {
// try {
// const response = await api.fetchUserProperties(userId);
// return response.data;
// } catch (error) {
// return rejectWithValue(error.response.data);
// }
// }
// );
// Action to fetch user properties with pagination
export const fetchUserProperties = createAsyncThunk( export const fetchUserProperties = createAsyncThunk(
"property/fetchUserProperties", "property/fetchUserProperties",
async (userId, { rejectWithValue }) => { async ({ userId, page, limit }, { rejectWithValue }) => {
try { try {
const response = await api.fetchUserProperties(userId); const response = await api.fetchUserProperties(userId, page, limit);
return response.data; return response.data;
} catch (error) { } catch (error) {
return rejectWithValue(error.response.data); return rejectWithValue(error.response.data);
@ -49,7 +63,6 @@ export const updateProperty = createAsyncThunk(
} }
); );
const propertySlice = createSlice({ const propertySlice = createSlice({
name: "property", name: "property",
initialState: { initialState: {
@ -58,6 +71,9 @@ const propertySlice = createSlice({
error: null, error: null,
userProperties: [], userProperties: [],
selectedProperty: null, selectedProperty: null,
totalPages: 0,
currentPage: 1,
loading: false,
}, },
reducers: {}, reducers: {},
extraReducers: (builder) => { extraReducers: (builder) => {
@ -75,15 +91,17 @@ const propertySlice = createSlice({
}) })
.addCase(fetchUserProperties.pending, (state) => { .addCase(fetchUserProperties.pending, (state) => {
state.status = "loading"; state.loading = true;
}) })
.addCase(fetchUserProperties.fulfilled, (state, action) => { .addCase(fetchUserProperties.fulfilled, (state, { payload }) => {
state.status = "succeeded"; state.loading = false;
state.userProperties = action.payload; state.userProperties = payload.properties;
state.totalPages = payload.totalPages;
state.currentPage = payload.currentPage;
}) })
.addCase(fetchUserProperties.rejected, (state, action) => { .addCase(fetchUserProperties.rejected, (state, { payload }) => {
state.status = "failed"; state.loading = false;
state.error = action.payload; state.error = payload;
}) })
.addCase(fetchPropertyById.pending, (state) => { .addCase(fetchPropertyById.pending, (state) => {