refactor mylistings and my rentals

This commit is contained in:
jackiettran
2025-11-01 22:33:59 -04:00
parent 16272ba373
commit 6d0beccea0
14 changed files with 42 additions and 42 deletions

View File

@@ -53,7 +53,7 @@ const checkAndUpdateReviewVisibility = async (rental) => {
return rental; return rental;
}; };
router.get("/my-rentals", authenticateToken, async (req, res) => { router.get("/renting", authenticateToken, async (req, res) => {
try { try {
const rentals = await Rental.findAll({ const rentals = await Rental.findAll({
where: { renterId: req.user.id }, where: { renterId: req.user.id },
@@ -72,7 +72,7 @@ router.get("/my-rentals", authenticateToken, async (req, res) => {
res.json(rentals); res.json(rentals);
} catch (error) { } catch (error) {
const reqLogger = logger.withRequestId(req.id); const reqLogger = logger.withRequestId(req.id);
reqLogger.error("Error in my-rentals route", { reqLogger.error("Error in renting route", {
error: error.message, error: error.message,
stack: error.stack, stack: error.stack,
userId: req.user.id, userId: req.user.id,
@@ -81,7 +81,7 @@ router.get("/my-rentals", authenticateToken, async (req, res) => {
} }
}); });
router.get("/my-listings", authenticateToken, async (req, res) => { router.get("/owning", authenticateToken, async (req, res) => {
try { try {
const rentals = await Rental.findAll({ const rentals = await Rental.findAll({
where: { ownerId: req.user.id }, where: { ownerId: req.user.id },
@@ -100,7 +100,7 @@ router.get("/my-listings", authenticateToken, async (req, res) => {
res.json(rentals); res.json(rentals);
} catch (error) { } catch (error) {
const reqLogger = logger.withRequestId(req.id); const reqLogger = logger.withRequestId(req.id);
reqLogger.error("Error in my-listings route", { reqLogger.error("Error in owning route", {
error: error.message, error: error.message,
stack: error.stack, stack: error.stack,
userId: req.user.id, userId: req.user.id,

View File

@@ -442,7 +442,7 @@ class EmailService {
<p><strong>Rental Period:</strong> {{startDate}} to {{endDate}}</p> <p><strong>Rental Period:</strong> {{startDate}} to {{endDate}}</p>
{{earningsSection}} {{earningsSection}}
{{stripeSection}} {{stripeSection}}
<p><a href="{{myListingsUrl}}" class="button">View My Listings</a></p> <p><a href="{{owningUrl}}" class="button">View My Listings</a></p>
` `
), ),
@@ -697,7 +697,7 @@ class EmailService {
async sendRentalRequestEmail(rental) { async sendRentalRequestEmail(rental) {
const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000"; const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
const approveUrl = `${frontendUrl}/my-listings?rentalId=${rental.id}`; const approveUrl = `${frontendUrl}/owning?rentalId=${rental.id}`;
// Fetch owner details // Fetch owner details
const owner = await User.findByPk(rental.ownerId, { const owner = await User.findByPk(rental.ownerId, {
@@ -754,7 +754,7 @@ class EmailService {
async sendRentalRequestConfirmationEmail(rental) { async sendRentalRequestConfirmationEmail(rental) {
const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000"; const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
const viewRentalsUrl = `${frontendUrl}/my-rentals`; const viewRentalsUrl = `${frontendUrl}/renting`;
// Fetch renter details // Fetch renter details
const renter = await User.findByPk(rental.renterId, { const renter = await User.findByPk(rental.renterId, {
@@ -1539,7 +1539,7 @@ class EmailService {
paymentMessage: paymentMessage, paymentMessage: paymentMessage,
earningsSection: earningsSection, earningsSection: earningsSection,
stripeSection: stripeSection, stripeSection: stripeSection,
rentalDetailsUrl: `${frontendUrl}/my-listings?rentalId=${rental.id}`, rentalDetailsUrl: `${frontendUrl}/owning?rentalId=${rental.id}`,
}; };
const htmlContent = this.renderTemplate( const htmlContent = this.renderTemplate(
@@ -1615,7 +1615,7 @@ class EmailService {
</ul> </ul>
</div> </div>
<p style="text-align: center;"> <p style="text-align: center;">
<a href="${frontendUrl}/my-rentals?rentalId=${rental.id}&action=review" class="button">Leave a Review</a> <a href="${frontendUrl}/renting?rentalId=${rental.id}&action=review" class="button">Leave a Review</a>
</p> </p>
`; `;
} else { } else {
@@ -1749,7 +1749,7 @@ class EmailService {
returnedDate: returnedDate, returnedDate: returnedDate,
earningsSection: earningsSection, earningsSection: earningsSection,
stripeSection: stripeSection, stripeSection: stripeSection,
myListingsUrl: `${frontendUrl}/my-listings`, owningUrl: `${frontendUrl}/owning`,
}; };
const ownerHtmlContent = this.renderTemplate( const ownerHtmlContent = this.renderTemplate(

View File

@@ -355,7 +355,7 @@
<p>Have more items sitting idle? Turn them into income! List camping gear, tools, party supplies, sports equipment, or anything else that others might need.</p> <p>Have more items sitting idle? Turn them into income! List camping gear, tools, party supplies, sports equipment, or anything else that others might need.</p>
<p style="text-align: center;"> <p style="text-align: center;">
<a href="{{myListingsUrl}}" class="button">View My Listings</a> <a href="{{owningUrl}}" class="button">View My Listings</a>
</p> </p>
<p>Thank you for being an excellent host on RentAll!</p> <p>Thank you for being an excellent host on RentAll!</p>

View File

@@ -66,7 +66,7 @@ describe('Rentals Routes', () => {
jest.clearAllMocks(); jest.clearAllMocks();
}); });
describe('GET /my-rentals', () => { describe('GET /renting', () => {
it('should get rentals for authenticated user', async () => { it('should get rentals for authenticated user', async () => {
const mockRentals = [ const mockRentals = [
{ {
@@ -86,7 +86,7 @@ describe('Rentals Routes', () => {
mockRentalFindAll.mockResolvedValue(mockRentals); mockRentalFindAll.mockResolvedValue(mockRentals);
const response = await request(app) const response = await request(app)
.get('/rentals/my-rentals'); .get('/rentals/renting');
expect(response.status).toBe(200); expect(response.status).toBe(200);
expect(response.body).toEqual(mockRentals); expect(response.body).toEqual(mockRentals);
@@ -108,14 +108,14 @@ describe('Rentals Routes', () => {
mockRentalFindAll.mockRejectedValue(new Error('Database error')); mockRentalFindAll.mockRejectedValue(new Error('Database error'));
const response = await request(app) const response = await request(app)
.get('/rentals/my-rentals'); .get('/rentals/renting');
expect(response.status).toBe(500); expect(response.status).toBe(500);
expect(response.body).toEqual({ error: 'Failed to fetch rentals' }); expect(response.body).toEqual({ error: 'Failed to fetch rentals' });
}); });
}); });
describe('GET /my-listings', () => { describe('GET /owning', () => {
it('should get listings for authenticated user', async () => { it('should get listings for authenticated user', async () => {
const mockListings = [ const mockListings = [
{ {
@@ -129,7 +129,7 @@ describe('Rentals Routes', () => {
mockRentalFindAll.mockResolvedValue(mockListings); mockRentalFindAll.mockResolvedValue(mockListings);
const response = await request(app) const response = await request(app)
.get('/rentals/my-listings'); .get('/rentals/owning');
expect(response.status).toBe(200); expect(response.status).toBe(200);
expect(response.body).toEqual(mockListings); expect(response.body).toEqual(mockListings);
@@ -151,7 +151,7 @@ describe('Rentals Routes', () => {
mockRentalFindAll.mockRejectedValue(new Error('Database error')); mockRentalFindAll.mockRejectedValue(new Error('Database error'));
const response = await request(app) const response = await request(app)
.get('/rentals/my-listings'); .get('/rentals/owning');
expect(response.status).toBe(500); expect(response.status).toBe(500);
expect(response.body).toEqual({ error: 'Failed to fetch listings' }); expect(response.body).toEqual({ error: 'Failed to fetch listings' });

View File

@@ -15,8 +15,8 @@ import ItemDetail from './pages/ItemDetail';
import EditItem from './pages/EditItem'; import EditItem from './pages/EditItem';
import RentItem from './pages/RentItem'; import RentItem from './pages/RentItem';
import CreateItem from './pages/CreateItem'; import CreateItem from './pages/CreateItem';
import MyRentals from './pages/MyRentals'; import Renting from './pages/Renting';
import MyListings from './pages/MyListings'; import Owning from './pages/Owning';
import Profile from './pages/Profile'; import Profile from './pages/Profile';
import PublicProfile from './pages/PublicProfile'; import PublicProfile from './pages/PublicProfile';
import Messages from './pages/Messages'; import Messages from './pages/Messages';
@@ -117,18 +117,18 @@ const AppContent: React.FC = () => {
} }
/> />
<Route <Route
path="/my-rentals" path="/renting"
element={ element={
<PrivateRoute> <PrivateRoute>
<MyRentals /> <Renting />
</PrivateRoute> </PrivateRoute>
} }
/> />
<Route <Route
path="/my-listings" path="/owning"
element={ element={
<PrivateRoute> <PrivateRoute>
<MyListings /> <Owning />
</PrivateRoute> </PrivateRoute>
} }
/> />

View File

@@ -194,13 +194,13 @@ const Navbar: React.FC = () => {
</Link> </Link>
</li> </li>
<li> <li>
<Link className="dropdown-item" to="/my-rentals"> <Link className="dropdown-item" to="/renting">
<i className="bi bi-calendar-check me-2"></i> <i className="bi bi-calendar-check me-2"></i>
Renting Renting
</Link> </Link>
</li> </li>
<li> <li>
<Link className="dropdown-item" to="/my-listings"> <Link className="dropdown-item" to="/owning">
<i className="bi bi-list-ul me-2"></i>Owning <i className="bi bi-list-ul me-2"></i>Owning
{pendingRequestsCount > 0 && ( {pendingRequestsCount > 0 && (
<span className="badge bg-danger rounded-pill ms-2"> <span className="badge bg-danger rounded-pill ms-2">

View File

@@ -36,7 +36,7 @@ const EarningsDashboard: React.FC = () => {
const fetchEarningsData = async () => { const fetchEarningsData = async () => {
try { try {
// Get completed rentals where user is the owner // Get completed rentals where user is the owner
const response = await rentalAPI.getMyListings(); const response = await rentalAPI.getListings();
const rentals = response.data || []; const rentals = response.data || [];
// Filter for completed rentals with earnings data // Filter for completed rentals with earnings data

View File

@@ -173,7 +173,7 @@ const EditItem: React.FC = () => {
const fetchAcceptedRentals = async () => { const fetchAcceptedRentals = async () => {
try { try {
const response = await rentalAPI.getMyListings(); const response = await rentalAPI.getListings();
const rentals: Rental[] = response.data; const rentals: Rental[] = response.data;
// Filter for accepted rentals for this specific item // Filter for accepted rentals for this specific item
const itemRentals = rentals.filter( const itemRentals = rentals.filter(

View File

@@ -48,7 +48,7 @@ const ItemDetail: React.FC = () => {
const checkIfAlreadyRenting = async () => { const checkIfAlreadyRenting = async () => {
try { try {
const response = await rentalAPI.getMyRentals(); const response = await rentalAPI.getRentals();
const rentals: Rental[] = response.data; const rentals: Rental[] = response.data;
// Check if user has an active rental for this item // Check if user has an active rental for this item
const hasActiveRental = rentals.some( const hasActiveRental = rentals.some(

View File

@@ -10,7 +10,7 @@ import DeclineRentalModal from "../components/DeclineRentalModal";
import ConditionCheckModal from "../components/ConditionCheckModal"; import ConditionCheckModal from "../components/ConditionCheckModal";
import ReturnStatusModal from "../components/ReturnStatusModal"; import ReturnStatusModal from "../components/ReturnStatusModal";
const MyListings: React.FC = () => { const Owning: React.FC = () => {
// Helper function to format time // Helper function to format time
const formatTime = (timeString?: string) => { const formatTime = (timeString?: string) => {
if (!timeString || timeString.trim() === "") return ""; if (!timeString || timeString.trim() === "") return "";
@@ -66,12 +66,12 @@ const MyListings: React.FC = () => {
const [rentalForReturn, setRentalForReturn] = useState<Rental | null>(null); const [rentalForReturn, setRentalForReturn] = useState<Rental | null>(null);
useEffect(() => { useEffect(() => {
fetchMyListings(); fetchListings();
fetchOwnerRentals(); fetchOwnerRentals();
fetchAvailableChecks(); fetchAvailableChecks();
}, [user]); }, [user]);
const fetchMyListings = async () => { const fetchListings = async () => {
if (!user) return; if (!user) return;
try { try {
@@ -124,7 +124,7 @@ const MyListings: React.FC = () => {
const fetchOwnerRentals = async () => { const fetchOwnerRentals = async () => {
try { try {
const response = await rentalAPI.getMyListings(); const response = await rentalAPI.getListings();
setOwnerRentals(response.data); setOwnerRentals(response.data);
} catch (err: any) { } catch (err: any) {
console.error("Failed to fetch owner rentals:", err); console.error("Failed to fetch owner rentals:", err);
@@ -698,4 +698,4 @@ const MyListings: React.FC = () => {
); );
}; };
export default MyListings; export default Owning;

View File

@@ -155,7 +155,7 @@ const Profile: React.FC = () => {
); );
// Fetch rentals where user is the owner (rentals on user's items) // Fetch rentals where user is the owner (rentals on user's items)
const ownerRentalsResponse = await rentalAPI.getMyListings(); const ownerRentalsResponse = await rentalAPI.getListings();
const ownerRentals: Rental[] = ownerRentalsResponse.data; const ownerRentals: Rental[] = ownerRentalsResponse.data;
const acceptedRentals = ownerRentals.filter((r) => const acceptedRentals = ownerRentals.filter((r) =>
@@ -194,14 +194,14 @@ const Profile: React.FC = () => {
const fetchRentalHistory = async () => { const fetchRentalHistory = async () => {
try { try {
// Fetch past rentals as a renter // Fetch past rentals as a renter
const renterResponse = await rentalAPI.getMyRentals(); const renterResponse = await rentalAPI.getRentals();
const pastRenterRentals = renterResponse.data.filter((r: Rental) => const pastRenterRentals = renterResponse.data.filter((r: Rental) =>
["completed", "cancelled"].includes(r.status) ["completed", "cancelled"].includes(r.status)
); );
setPastRenterRentals(pastRenterRentals); setPastRenterRentals(pastRenterRentals);
// Fetch past rentals as an owner // Fetch past rentals as an owner
const ownerResponse = await rentalAPI.getMyListings(); const ownerResponse = await rentalAPI.getListings();
const pastOwnerRentals = ownerResponse.data.filter((r: Rental) => const pastOwnerRentals = ownerResponse.data.filter((r: Rental) =>
["completed", "cancelled"].includes(r.status) ["completed", "cancelled"].includes(r.status)
); );

View File

@@ -223,7 +223,7 @@ const RentItem: React.FC = () => {
<div className="d-grid gap-2 d-md-block"> <div className="d-grid gap-2 d-md-block">
<button <button
className="btn btn-primary me-2" className="btn btn-primary me-2"
onClick={() => navigate("/my-rentals")} onClick={() => navigate("/renting")}
> >
View My Rentals View My Rentals
</button> </button>

View File

@@ -7,7 +7,7 @@ import ReviewItemModal from "../components/ReviewModal";
import RentalCancellationModal from "../components/RentalCancellationModal"; import RentalCancellationModal from "../components/RentalCancellationModal";
import ConditionCheckModal from "../components/ConditionCheckModal"; import ConditionCheckModal from "../components/ConditionCheckModal";
const MyRentals: React.FC = () => { const Renting: React.FC = () => {
// Helper function to format time // Helper function to format time
const formatTime = (timeString?: string) => { const formatTime = (timeString?: string) => {
if (!timeString || timeString.trim() === "") return ""; if (!timeString || timeString.trim() === "") return "";
@@ -66,7 +66,7 @@ const MyRentals: React.FC = () => {
const fetchRentals = async () => { const fetchRentals = async () => {
try { try {
const response = await rentalAPI.getMyRentals(); const response = await rentalAPI.getRentals();
setRentals(response.data); setRentals(response.data);
} catch (err: any) { } catch (err: any) {
setError(err.response?.data?.message || "Failed to fetch rentals"); setError(err.response?.data?.message || "Failed to fetch rentals");
@@ -470,4 +470,4 @@ const MyRentals: React.FC = () => {
); );
}; };
export default MyRentals; export default Renting;

View File

@@ -203,8 +203,8 @@ export const itemAPI = {
export const rentalAPI = { export const rentalAPI = {
createRental: (data: any) => api.post("/rentals", data), createRental: (data: any) => api.post("/rentals", data),
getMyRentals: () => api.get("/rentals/my-rentals"), getRentals: () => api.get("/rentals/renting"),
getMyListings: () => api.get("/rentals/my-listings"), getListings: () => api.get("/rentals/owning"),
getPendingRequestsCount: () => api.get("/rentals/pending-requests-count"), getPendingRequestsCount: () => api.get("/rentals/pending-requests-count"),
updateRentalStatus: (id: string, status: string) => updateRentalStatus: (id: string, status: string) =>
api.put(`/rentals/${id}/status`, { status }), api.put(`/rentals/${id}/status`, { status }),