done
This commit is contained in:
parent
dd8f1e6463
commit
7be342c671
|
@ -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",
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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({
|
||||||
|
|
|
@ -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
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
);
|
||||||
|
|
||||||
// Fetch user properties when "Active Properties" tab is selected
|
const [page, setPage] = useState(1);
|
||||||
useEffect(() => {
|
const limit = 5; // Number of properties per page
|
||||||
|
|
||||||
dispatch(fetchUserProperties(user?.result?.userId));
|
// Fetch user properties when "Active Properties" tab is selected
|
||||||
|
useEffect(() => {
|
||||||
}, [dispatch, user?.result?.userId]);
|
dispatch(fetchUserProperties({ userId: user.result.userId, page, limit }));
|
||||||
|
},[dispatch, user?.result?.userId, page]);
|
||||||
|
|
||||||
|
// Pagination handler
|
||||||
|
const handlePageChange = (newPage) => {
|
||||||
|
setPage(newPage);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{userProperties.length > 0 ? (
|
{userProperties.length > 0 ? (
|
||||||
<ul>
|
<>
|
||||||
{userProperties.map((property) => (
|
<ul>
|
||||||
<li key={property._id}>
|
{userProperties.map((property) => (
|
||||||
<NavLink to={`/property/${property.propertyId}`} target="_blank">
|
<li key={property._id}>
|
||||||
{property.title}
|
<NavLink
|
||||||
{"....."}
|
to={`/property/${property.propertyId}`}
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
{property.title}
|
||||||
|
{"....."}
|
||||||
|
</NavLink>
|
||||||
|
|
||||||
</NavLink>
|
<NavLink
|
||||||
|
to={`/editproperty/${property.propertyId}`}
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
{"....."}
|
||||||
|
</NavLink>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
<NavLink to={`/editproperty/${property.propertyId}`} target="_blank">
|
{/* Pagination Controls */}
|
||||||
Edit
|
<div className="pagination">
|
||||||
{"....."}
|
<button
|
||||||
|
onClick={() => handlePageChange(page - 1)}
|
||||||
</NavLink>
|
disabled={page === 1}
|
||||||
|
>
|
||||||
</li>
|
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
|
||||||
</ul>
|
onClick={() => handlePageChange(page + 1)}
|
||||||
) : (
|
disabled={page === totalPages}
|
||||||
<p>No active properties found.</p>
|
>
|
||||||
)}
|
Next
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<p>No active properties found.</p>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
</>
|
export default UserProperties;
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default UserProperties
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
Loading…
Reference in New Issue