Compare commits
3 Commits
16272ba373
...
9c258177ae
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c258177ae | ||
|
|
6ec7858bbd | ||
|
|
6d0beccea0 |
@@ -53,7 +53,7 @@ const checkAndUpdateReviewVisibility = async (rental) => {
|
||||
return rental;
|
||||
};
|
||||
|
||||
router.get("/my-rentals", authenticateToken, async (req, res) => {
|
||||
router.get("/renting", authenticateToken, async (req, res) => {
|
||||
try {
|
||||
const rentals = await Rental.findAll({
|
||||
where: { renterId: req.user.id },
|
||||
@@ -72,7 +72,7 @@ router.get("/my-rentals", authenticateToken, async (req, res) => {
|
||||
res.json(rentals);
|
||||
} catch (error) {
|
||||
const reqLogger = logger.withRequestId(req.id);
|
||||
reqLogger.error("Error in my-rentals route", {
|
||||
reqLogger.error("Error in renting route", {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
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 {
|
||||
const rentals = await Rental.findAll({
|
||||
where: { ownerId: req.user.id },
|
||||
@@ -100,7 +100,7 @@ router.get("/my-listings", authenticateToken, async (req, res) => {
|
||||
res.json(rentals);
|
||||
} catch (error) {
|
||||
const reqLogger = logger.withRequestId(req.id);
|
||||
reqLogger.error("Error in my-listings route", {
|
||||
reqLogger.error("Error in owning route", {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
userId: req.user.id,
|
||||
|
||||
@@ -442,7 +442,7 @@ class EmailService {
|
||||
<p><strong>Rental Period:</strong> {{startDate}} to {{endDate}}</p>
|
||||
{{earningsSection}}
|
||||
{{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) {
|
||||
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
|
||||
const owner = await User.findByPk(rental.ownerId, {
|
||||
@@ -754,7 +754,7 @@ class EmailService {
|
||||
|
||||
async sendRentalRequestConfirmationEmail(rental) {
|
||||
const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
|
||||
const viewRentalsUrl = `${frontendUrl}/my-rentals`;
|
||||
const viewRentalsUrl = `${frontendUrl}/renting`;
|
||||
|
||||
// Fetch renter details
|
||||
const renter = await User.findByPk(rental.renterId, {
|
||||
@@ -1539,7 +1539,7 @@ class EmailService {
|
||||
paymentMessage: paymentMessage,
|
||||
earningsSection: earningsSection,
|
||||
stripeSection: stripeSection,
|
||||
rentalDetailsUrl: `${frontendUrl}/my-listings?rentalId=${rental.id}`,
|
||||
rentalDetailsUrl: `${frontendUrl}/owning?rentalId=${rental.id}`,
|
||||
};
|
||||
|
||||
const htmlContent = this.renderTemplate(
|
||||
@@ -1615,7 +1615,7 @@ class EmailService {
|
||||
</ul>
|
||||
</div>
|
||||
<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>
|
||||
`;
|
||||
} else {
|
||||
@@ -1749,7 +1749,7 @@ class EmailService {
|
||||
returnedDate: returnedDate,
|
||||
earningsSection: earningsSection,
|
||||
stripeSection: stripeSection,
|
||||
myListingsUrl: `${frontendUrl}/my-listings`,
|
||||
owningUrl: `${frontendUrl}/owning`,
|
||||
};
|
||||
|
||||
const ownerHtmlContent = this.renderTemplate(
|
||||
|
||||
@@ -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 style="text-align: center;">
|
||||
<a href="{{myListingsUrl}}" class="button">View My Listings</a>
|
||||
<a href="{{owningUrl}}" class="button">View My Listings</a>
|
||||
</p>
|
||||
|
||||
<p>Thank you for being an excellent host on RentAll!</p>
|
||||
|
||||
@@ -66,7 +66,7 @@ describe('Rentals Routes', () => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('GET /my-rentals', () => {
|
||||
describe('GET /renting', () => {
|
||||
it('should get rentals for authenticated user', async () => {
|
||||
const mockRentals = [
|
||||
{
|
||||
@@ -86,7 +86,7 @@ describe('Rentals Routes', () => {
|
||||
mockRentalFindAll.mockResolvedValue(mockRentals);
|
||||
|
||||
const response = await request(app)
|
||||
.get('/rentals/my-rentals');
|
||||
.get('/rentals/renting');
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body).toEqual(mockRentals);
|
||||
@@ -108,14 +108,14 @@ describe('Rentals Routes', () => {
|
||||
mockRentalFindAll.mockRejectedValue(new Error('Database error'));
|
||||
|
||||
const response = await request(app)
|
||||
.get('/rentals/my-rentals');
|
||||
.get('/rentals/renting');
|
||||
|
||||
expect(response.status).toBe(500);
|
||||
expect(response.body).toEqual({ error: 'Failed to fetch rentals' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /my-listings', () => {
|
||||
describe('GET /owning', () => {
|
||||
it('should get listings for authenticated user', async () => {
|
||||
const mockListings = [
|
||||
{
|
||||
@@ -129,7 +129,7 @@ describe('Rentals Routes', () => {
|
||||
mockRentalFindAll.mockResolvedValue(mockListings);
|
||||
|
||||
const response = await request(app)
|
||||
.get('/rentals/my-listings');
|
||||
.get('/rentals/owning');
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body).toEqual(mockListings);
|
||||
@@ -151,7 +151,7 @@ describe('Rentals Routes', () => {
|
||||
mockRentalFindAll.mockRejectedValue(new Error('Database error'));
|
||||
|
||||
const response = await request(app)
|
||||
.get('/rentals/my-listings');
|
||||
.get('/rentals/owning');
|
||||
|
||||
expect(response.status).toBe(500);
|
||||
expect(response.body).toEqual({ error: 'Failed to fetch listings' });
|
||||
|
||||
@@ -15,8 +15,8 @@ import ItemDetail from './pages/ItemDetail';
|
||||
import EditItem from './pages/EditItem';
|
||||
import RentItem from './pages/RentItem';
|
||||
import CreateItem from './pages/CreateItem';
|
||||
import MyRentals from './pages/MyRentals';
|
||||
import MyListings from './pages/MyListings';
|
||||
import Renting from './pages/Renting';
|
||||
import Owning from './pages/Owning';
|
||||
import Profile from './pages/Profile';
|
||||
import PublicProfile from './pages/PublicProfile';
|
||||
import Messages from './pages/Messages';
|
||||
@@ -117,18 +117,18 @@ const AppContent: React.FC = () => {
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/my-rentals"
|
||||
path="/renting"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<MyRentals />
|
||||
<Renting />
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/my-listings"
|
||||
path="/owning"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<MyListings />
|
||||
<Owning />
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -6,9 +6,10 @@ interface AuthButtonProps {
|
||||
className?: string;
|
||||
children: React.ReactNode;
|
||||
asLink?: boolean;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
const AuthButton: React.FC<AuthButtonProps> = ({ mode, className = '', children, asLink = false }) => {
|
||||
const AuthButton: React.FC<AuthButtonProps> = ({ mode, className = '', children, asLink = false, style }) => {
|
||||
const { openAuthModal } = useAuth();
|
||||
|
||||
const handleClick = (e: React.MouseEvent) => {
|
||||
@@ -22,6 +23,7 @@ const AuthButton: React.FC<AuthButtonProps> = ({ mode, className = '', children,
|
||||
href="#"
|
||||
onClick={handleClick}
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
@@ -32,6 +34,7 @@ const AuthButton: React.FC<AuthButtonProps> = ({ mode, className = '', children,
|
||||
<button
|
||||
onClick={handleClick}
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
|
||||
@@ -4,135 +4,47 @@ import { Link } from 'react-router-dom';
|
||||
const Footer: React.FC = () => {
|
||||
return (
|
||||
<footer className="bg-dark text-white">
|
||||
<div className="container-fluid py-4" style={{ maxWidth: '1800px' }}>
|
||||
<div className="row">
|
||||
<div className="col-lg-3">
|
||||
<h5 className="mb-3">
|
||||
<i className="bi bi-box-seam me-2"></i>
|
||||
CommunityRentals.App
|
||||
</h5>
|
||||
<p className="small text-white-50">
|
||||
The marketplace for renting anything, from anyone, anywhere.
|
||||
</p>
|
||||
<div className="container py-4">
|
||||
<div className="text-center">
|
||||
{/* Social Media Icons */}
|
||||
<div className="mb-3">
|
||||
<a href="#" className="text-white-50 me-3">
|
||||
<i className="bi bi-facebook"></i>
|
||||
</a>
|
||||
<a href="#" className="text-white-50 me-3">
|
||||
<i className="bi bi-twitter"></i>
|
||||
</a>
|
||||
<a href="#" className="text-white-50 me-3">
|
||||
<i className="bi bi-instagram"></i>
|
||||
</a>
|
||||
<a href="#" className="text-white-50">
|
||||
<i className="bi bi-linkedin"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div className="col-lg-2 col-md-6">
|
||||
<h6 className="mb-3">FAQ</h6>
|
||||
<ul className="list-unstyled small">
|
||||
<li className="mb-2">
|
||||
<Link to="/faq/renters" className="text-decoration-none text-white-50">
|
||||
Renter FAQ
|
||||
</Link>
|
||||
</li>
|
||||
<li className="mb-2">
|
||||
<Link to="/faq/owners" className="text-decoration-none text-white-50">
|
||||
Owner FAQ
|
||||
</Link>
|
||||
</li>
|
||||
<li className="mb-2">
|
||||
<Link to="/faq/payments" className="text-decoration-none text-white-50">
|
||||
Payments
|
||||
</Link>
|
||||
</li>
|
||||
<li className="mb-2">
|
||||
<Link to="/help" className="text-decoration-none text-white-50">
|
||||
Help Center
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="col-lg-2 col-md-6">
|
||||
<h6 className="mb-3">For Renters</h6>
|
||||
<ul className="list-unstyled small">
|
||||
<li className="mb-2">
|
||||
<Link to="/items" className="text-decoration-none text-white-50">
|
||||
Browse Items
|
||||
</Link>
|
||||
</li>
|
||||
<li className="mb-2">
|
||||
<Link to="/how-it-works" className="text-decoration-none text-white-50">
|
||||
How It Works
|
||||
</Link>
|
||||
</li>
|
||||
<li className="mb-2">
|
||||
<Link to="/safety" className="text-decoration-none text-white-50">
|
||||
Safety Tips
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="col-lg-2 col-md-6">
|
||||
<h6 className="mb-3">For Owners</h6>
|
||||
<ul className="list-unstyled small">
|
||||
<li className="mb-2">
|
||||
<Link to="/create-item" className="text-decoration-none text-white-50">
|
||||
List an Item
|
||||
</Link>
|
||||
</li>
|
||||
<li className="mb-2">
|
||||
<Link to="/owner-guide" className="text-decoration-none text-white-50">
|
||||
Owner Guide
|
||||
</Link>
|
||||
</li>
|
||||
<li className="mb-2">
|
||||
<Link to="/insurance" className="text-decoration-none text-white-50">
|
||||
Insurance
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="col-lg-2 col-md-6">
|
||||
<h6 className="mb-3">Company</h6>
|
||||
<ul className="list-unstyled small">
|
||||
<li className="mb-2">
|
||||
<Link to="/about" className="text-decoration-none text-white-50">
|
||||
About Us
|
||||
</Link>
|
||||
</li>
|
||||
<li className="mb-2">
|
||||
<Link to="/contact" className="text-decoration-none text-white-50">
|
||||
Contact
|
||||
</Link>
|
||||
</li>
|
||||
<li className="mb-2">
|
||||
<Link to="/careers" className="text-decoration-none text-white-50">
|
||||
Careers
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="col-lg-1 col-md-6">
|
||||
<h6 className="mb-3">Follow Us</h6>
|
||||
<div className="d-flex gap-3">
|
||||
<a href="#" className="text-white-50">
|
||||
<i className="bi bi-facebook"></i>
|
||||
</a>
|
||||
<a href="#" className="text-white-50">
|
||||
<i className="bi bi-twitter"></i>
|
||||
</a>
|
||||
<a href="#" className="text-white-50">
|
||||
<i className="bi bi-instagram"></i>
|
||||
</a>
|
||||
<a href="#" className="text-white-50">
|
||||
<i className="bi bi-linkedin"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr className="my-4 bg-secondary" />
|
||||
<div className="row">
|
||||
<div className="col-md-6">
|
||||
<p className="small text-white-50 mb-0">
|
||||
© 2025 CommunityRentals.App. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
<div className="col-md-6 text-md-end">
|
||||
<Link to="/privacy" className="text-decoration-none text-white-50 small me-3">
|
||||
|
||||
{/* Essential Links */}
|
||||
<div className="mb-3 small">
|
||||
<Link to="/about" className="text-decoration-none text-white-50 me-2">
|
||||
About
|
||||
</Link>
|
||||
<span className="text-white-50">•</span>
|
||||
<Link to="/contact" className="text-decoration-none text-white-50 mx-2">
|
||||
Contact
|
||||
</Link>
|
||||
<span className="text-white-50">•</span>
|
||||
<Link to="/privacy" className="text-decoration-none text-white-50 mx-2">
|
||||
Privacy Policy
|
||||
</Link>
|
||||
<Link to="/terms" className="text-decoration-none text-white-50 small">
|
||||
<span className="text-white-50">•</span>
|
||||
<Link to="/terms" className="text-decoration-none text-white-50 ms-2">
|
||||
Terms of Service
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Copyright */}
|
||||
<p className="small text-white-50 mb-0">
|
||||
© 2025 CommunityRentals.App. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -111,10 +111,11 @@ const Navbar: React.FC = () => {
|
||||
}
|
||||
/>
|
||||
<span
|
||||
className="input-group-text bg-white text-muted"
|
||||
className="input-group-text text-muted"
|
||||
style={{
|
||||
borderLeft: "0",
|
||||
borderRight: "1px solid #dee2e6",
|
||||
backgroundColor: "#f8f9fa",
|
||||
}}
|
||||
>
|
||||
in
|
||||
@@ -127,7 +128,6 @@ const Navbar: React.FC = () => {
|
||||
onChange={(e) =>
|
||||
handleSearchInputChange("location", e.target.value)
|
||||
}
|
||||
style={{ borderLeft: "0" }}
|
||||
/>
|
||||
<button className="btn btn-outline-secondary" type="submit">
|
||||
<i className="bi bi-search"></i>
|
||||
@@ -194,13 +194,13 @@ const Navbar: React.FC = () => {
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link className="dropdown-item" to="/my-rentals">
|
||||
<Link className="dropdown-item" to="/renting">
|
||||
<i className="bi bi-calendar-check me-2"></i>
|
||||
Renting
|
||||
</Link>
|
||||
</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
|
||||
{pendingRequestsCount > 0 && (
|
||||
<span className="badge bg-danger rounded-pill ms-2">
|
||||
|
||||
@@ -36,7 +36,7 @@ const EarningsDashboard: React.FC = () => {
|
||||
const fetchEarningsData = async () => {
|
||||
try {
|
||||
// Get completed rentals where user is the owner
|
||||
const response = await rentalAPI.getMyListings();
|
||||
const response = await rentalAPI.getListings();
|
||||
const rentals = response.data || [];
|
||||
|
||||
// Filter for completed rentals with earnings data
|
||||
|
||||
@@ -173,7 +173,7 @@ const EditItem: React.FC = () => {
|
||||
|
||||
const fetchAcceptedRentals = async () => {
|
||||
try {
|
||||
const response = await rentalAPI.getMyListings();
|
||||
const response = await rentalAPI.getListings();
|
||||
const rentals: Rental[] = response.data;
|
||||
// Filter for accepted rentals for this specific item
|
||||
const itemRentals = rentals.filter(
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { itemAPI } from '../services/api';
|
||||
import { Item } from '../types';
|
||||
import ItemCard from '../components/ItemCard';
|
||||
import AuthButton from '../components/AuthButton';
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useAuth } from "../contexts/AuthContext";
|
||||
import { itemAPI } from "../services/api";
|
||||
import { Item } from "../types";
|
||||
import ItemCard from "../components/ItemCard";
|
||||
import AuthButton from "../components/AuthButton";
|
||||
|
||||
const Home: React.FC = () => {
|
||||
const { user } = useAuth();
|
||||
@@ -17,7 +17,7 @@ const Home: React.FC = () => {
|
||||
const response = await itemAPI.getItems({ limit: 8 });
|
||||
setFeaturedItems(response.data.items);
|
||||
} catch (error) {
|
||||
console.error('Error fetching items:', error);
|
||||
console.error("Error fetching items:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -28,70 +28,56 @@ const Home: React.FC = () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* Hero Section */}
|
||||
<div className="bg-primary text-white py-3">
|
||||
<div className="container-fluid" style={{ maxWidth: '1800px' }}>
|
||||
<div className="row align-items-center">
|
||||
<div className="col-lg-6">
|
||||
<h1 className="fs-2 fw-bold mb-2">
|
||||
Rent Anything, From Anyone, Anywhere
|
||||
</h1>
|
||||
<p className="mb-3">
|
||||
Join the sharing economy. Rent items you need for a fraction of the cost,
|
||||
or earn money from things you already own.
|
||||
</p>
|
||||
<div className="d-flex gap-3 flex-wrap">
|
||||
<Link to="/items" className="btn btn-light">
|
||||
Start Renting
|
||||
</Link>
|
||||
{user ? (
|
||||
<Link to="/create-item" className="btn btn-outline-light">
|
||||
List Your Items
|
||||
</Link>
|
||||
) : (
|
||||
<AuthButton mode="signup" className="btn btn-outline-light">
|
||||
Start Earning
|
||||
</AuthButton>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-lg-6 text-center d-none d-lg-block">
|
||||
<i className="bi bi-box-seam" style={{ fontSize: '8rem', opacity: 0.3 }}></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Featured Items Section */}
|
||||
<div className="py-4 bg-light">
|
||||
<div className="container-fluid" style={{ maxWidth: '1800px' }}>
|
||||
<div className="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2 className="mb-0">Items for Rent</h2>
|
||||
<Link to="/items" className="btn btn-link">
|
||||
View All <i className="bi bi-arrow-right"></i>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="py-4" style={{ backgroundColor: "#2C3E50" }}>
|
||||
<div className="container-fluid" style={{ maxWidth: "1800px" }}>
|
||||
{loading ? (
|
||||
<div className="text-center py-4">
|
||||
<div className="spinner-border text-primary" role="status">
|
||||
<div
|
||||
className="spinner-border"
|
||||
role="status"
|
||||
style={{ color: "#4A90E2" }}
|
||||
>
|
||||
<span className="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="row g-4">
|
||||
{featuredItems.map((item) => (
|
||||
<div key={item.id} className="col-md-6 col-lg-4 col-xl-3">
|
||||
<ItemCard item={item} variant="compact" />
|
||||
<>
|
||||
<div className="row g-4">
|
||||
{featuredItems.map((item) => (
|
||||
<div key={item.id} className="col-md-6 col-lg-4 col-xl-3">
|
||||
<ItemCard item={item} variant="compact" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{featuredItems.length > 0 && (
|
||||
<div className="text-center mt-4">
|
||||
<Link
|
||||
to="/items"
|
||||
className="btn btn-link"
|
||||
style={{ color: "#4A90E2" }}
|
||||
>
|
||||
View All <i className="bi bi-arrow-right"></i>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{!loading && featuredItems.length === 0 && (
|
||||
<div className="text-center py-5">
|
||||
<p className="text-muted">No items available for rent yet.</p>
|
||||
<Link to="/create-item" className="btn btn-primary">
|
||||
<p style={{ color: "rgba(255, 255, 255, 0.7)" }}>
|
||||
No items available for rent yet.
|
||||
</p>
|
||||
<Link
|
||||
to="/create-item"
|
||||
className="btn"
|
||||
style={{
|
||||
backgroundColor: "#4A90E2",
|
||||
color: "white",
|
||||
borderColor: "#4A90E2",
|
||||
}}
|
||||
>
|
||||
Be the first to list an item!
|
||||
</Link>
|
||||
</div>
|
||||
@@ -99,40 +85,164 @@ const Home: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Benefits Section */}
|
||||
<div className="py-5" style={{ backgroundColor: "#34495e" }}>
|
||||
<div className="container-fluid" style={{ maxWidth: "1800px" }}>
|
||||
<div className="row align-items-center">
|
||||
<div className="col-lg-6">
|
||||
<h2 className="mb-4" style={{ color: "white" }}>
|
||||
Why Choose CommunityRentals.App?
|
||||
</h2>
|
||||
<div className="d-flex mb-3">
|
||||
<i
|
||||
className="bi bi-check-circle-fill me-3"
|
||||
style={{ fontSize: "1.5rem", color: "#7FB069" }}
|
||||
></i>
|
||||
<div>
|
||||
<h5 style={{ color: "white" }}>Save Money</h5>
|
||||
<p style={{ color: "rgba(255, 255, 255, 0.8)" }}>
|
||||
Why buy when you can rent? Access items for a fraction of
|
||||
the purchase price.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex mb-3">
|
||||
<i
|
||||
className="bi bi-check-circle-fill me-3"
|
||||
style={{ fontSize: "1.5rem", color: "#7FB069" }}
|
||||
></i>
|
||||
<div>
|
||||
<h5 style={{ color: "white" }}>Earn Extra Income</h5>
|
||||
<p style={{ color: "rgba(255, 255, 255, 0.8)" }}>
|
||||
Turn your unused items into a revenue stream. Your garage
|
||||
could be a goldmine.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex mb-3">
|
||||
<i
|
||||
className="bi bi-check-circle-fill me-3"
|
||||
style={{ fontSize: "1.5rem", color: "#7FB069" }}
|
||||
></i>
|
||||
<div>
|
||||
<h5 style={{ color: "white" }}>Build Community</h5>
|
||||
<p style={{ color: "rgba(255, 255, 255, 0.8)" }}>
|
||||
Connect with neighbors and help each other. Sharing builds
|
||||
stronger communities.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex">
|
||||
<i
|
||||
className="bi bi-check-circle-fill me-3"
|
||||
style={{ fontSize: "1.5rem", color: "#7FB069" }}
|
||||
></i>
|
||||
<div>
|
||||
<h5 style={{ color: "white" }}>Reduce Waste</h5>
|
||||
<p style={{ color: "rgba(255, 255, 255, 0.8)" }}>
|
||||
Share instead of everyone buying. It's better for your
|
||||
wallet and the planet.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-lg-6 text-center">
|
||||
<h2 className="mb-4" style={{ color: "white" }}>
|
||||
Ready to Get Started?
|
||||
</h2>
|
||||
<p
|
||||
className="lead mb-4"
|
||||
style={{ color: "rgba(255, 255, 255, 0.9)" }}
|
||||
>
|
||||
Join thousands of people sharing and renting in your community
|
||||
</p>
|
||||
<div className="d-flex gap-3 justify-content-center flex-wrap">
|
||||
{user ? (
|
||||
<Link
|
||||
to="/create-item"
|
||||
className="btn btn-lg"
|
||||
style={{
|
||||
backgroundColor: "#7FB069",
|
||||
color: "white",
|
||||
borderColor: "#7FB069",
|
||||
}}
|
||||
>
|
||||
Start Earning
|
||||
</Link>
|
||||
) : (
|
||||
<AuthButton
|
||||
mode="signup"
|
||||
className="btn btn-lg"
|
||||
style={{
|
||||
backgroundColor: "#7FB069",
|
||||
color: "white",
|
||||
borderColor: "#7FB069",
|
||||
}}
|
||||
>
|
||||
Start Earning
|
||||
</AuthButton>
|
||||
)}
|
||||
<Link
|
||||
to="/items"
|
||||
className="btn btn-lg"
|
||||
style={{
|
||||
backgroundColor: "#4A90E2",
|
||||
color: "white",
|
||||
borderColor: "#4A90E2",
|
||||
}}
|
||||
>
|
||||
Browse Rentals
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* How It Works - For Renters */}
|
||||
<div className="py-5">
|
||||
<div className="container-fluid" style={{ maxWidth: '1800px' }}>
|
||||
<h2 className="text-center mb-5">For Renters: Get What You Need, When You Need It</h2>
|
||||
<div className="container-fluid" style={{ maxWidth: "1800px" }}>
|
||||
<h2 className="text-center mb-5">
|
||||
For Renters: Get What You Need, When You Need It
|
||||
</h2>
|
||||
<div className="row g-4">
|
||||
<div className="col-md-4 text-center">
|
||||
<div className="mb-3">
|
||||
<i className="bi bi-search text-primary" style={{ fontSize: '3rem' }}></i>
|
||||
<i
|
||||
className="bi bi-search"
|
||||
style={{ fontSize: "3rem", color: "#4A90E2" }}
|
||||
></i>
|
||||
</div>
|
||||
<h4>1. Find What You Need</h4>
|
||||
<p className="text-muted">
|
||||
Browse our marketplace for tools, equipment, electronics, and more.
|
||||
Filter by location, price, and availability.
|
||||
Browse our marketplace for tools, equipment, electronics, and
|
||||
more. Filter by location, price, and availability.
|
||||
</p>
|
||||
</div>
|
||||
<div className="col-md-4 text-center">
|
||||
<div className="mb-3">
|
||||
<i className="bi bi-calendar-check text-primary" style={{ fontSize: '3rem' }}></i>
|
||||
<i
|
||||
className="bi bi-calendar-check"
|
||||
style={{ fontSize: "3rem", color: "#4A90E2" }}
|
||||
></i>
|
||||
</div>
|
||||
<h4>2. Book Your Rental</h4>
|
||||
<p className="text-muted">
|
||||
Select your rental dates, choose delivery or pickup, and pay securely.
|
||||
Your payment is held until the owner confirms.
|
||||
Select your rental dates, choose delivery or pickup, and pay
|
||||
securely. Your payment is held until the owner confirms.
|
||||
</p>
|
||||
</div>
|
||||
<div className="col-md-4 text-center">
|
||||
<div className="mb-3">
|
||||
<i className="bi bi-box-arrow-right text-primary" style={{ fontSize: '3rem' }}></i>
|
||||
<i
|
||||
className="bi bi-box-arrow-right"
|
||||
style={{ fontSize: "3rem", color: "#4A90E2" }}
|
||||
></i>
|
||||
</div>
|
||||
<h4>3. Enjoy & Return</h4>
|
||||
<p className="text-muted">
|
||||
Use the item for your project or event, then return it as agreed.
|
||||
Rate your experience to help the community.
|
||||
Use the item for your project or event, then return it as
|
||||
agreed. Rate your experience to help the community.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -140,23 +250,31 @@ const Home: React.FC = () => {
|
||||
</div>
|
||||
|
||||
{/* How It Works - For Owners */}
|
||||
<div className="py-5 bg-light">
|
||||
<div className="container-fluid" style={{ maxWidth: '1800px' }}>
|
||||
<h2 className="text-center mb-5">For Owners: Turn Your Idle Items Into Income</h2>
|
||||
<div className="py-5" style={{ backgroundColor: "#F7F9FB" }}>
|
||||
<div className="container-fluid" style={{ maxWidth: "1800px" }}>
|
||||
<h2 className="text-center mb-5">
|
||||
For Owners: Turn Your Idle Items Into Income
|
||||
</h2>
|
||||
<div className="row g-4">
|
||||
<div className="col-md-4 text-center">
|
||||
<div className="mb-3">
|
||||
<i className="bi bi-camera text-success" style={{ fontSize: '3rem' }}></i>
|
||||
<i
|
||||
className="bi bi-camera"
|
||||
style={{ fontSize: "3rem", color: "#7FB069" }}
|
||||
></i>
|
||||
</div>
|
||||
<h4>1. List Your Items</h4>
|
||||
<p className="text-muted">
|
||||
Take photos, set your price, and choose when your items are available.
|
||||
List anything from power tools to party supplies.
|
||||
Take photos, set your price, and choose when your items are
|
||||
available. List anything from power tools to party supplies.
|
||||
</p>
|
||||
</div>
|
||||
<div className="col-md-4 text-center">
|
||||
<div className="mb-3">
|
||||
<i className="bi bi-bell text-success" style={{ fontSize: '3rem' }}></i>
|
||||
<i
|
||||
className="bi bi-bell"
|
||||
style={{ fontSize: "3rem", color: "#7FB069" }}
|
||||
></i>
|
||||
</div>
|
||||
<h4>2. Accept Requests</h4>
|
||||
<p className="text-muted">
|
||||
@@ -166,140 +284,20 @@ const Home: React.FC = () => {
|
||||
</div>
|
||||
<div className="col-md-4 text-center">
|
||||
<div className="mb-3">
|
||||
<i className="bi bi-cash-stack text-success" style={{ fontSize: '3rem' }}></i>
|
||||
<i
|
||||
className="bi bi-cash-stack"
|
||||
style={{ fontSize: "3rem", color: "#7FB069" }}
|
||||
></i>
|
||||
</div>
|
||||
<h4>3. Get Paid</h4>
|
||||
<p className="text-muted">
|
||||
Earn money from items sitting in your garage.
|
||||
Payments are processed securely after each rental.
|
||||
Earn money from items sitting in your garage. Payments are
|
||||
processed securely after each rental.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Popular Categories */}
|
||||
<div className="py-5">
|
||||
<div className="container-fluid" style={{ maxWidth: '1800px' }}>
|
||||
<h2 className="text-center mb-5">Popular Rental Categories</h2>
|
||||
<div className="row g-3">
|
||||
<div className="col-6 col-md-4 col-lg-2">
|
||||
<div className="card h-100 text-center border-0 shadow-sm">
|
||||
<div className="card-body">
|
||||
<i className="bi bi-tools text-primary mb-2" style={{ fontSize: '2rem' }}></i>
|
||||
<h6 className="mb-0">Tools</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-6 col-md-4 col-lg-2">
|
||||
<div className="card h-100 text-center border-0 shadow-sm">
|
||||
<div className="card-body">
|
||||
<i className="bi bi-camera-fill text-primary mb-2" style={{ fontSize: '2rem' }}></i>
|
||||
<h6 className="mb-0">Electronics</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-6 col-md-4 col-lg-2">
|
||||
<div className="card h-100 text-center border-0 shadow-sm">
|
||||
<div className="card-body">
|
||||
<i className="bi bi-bicycle text-primary mb-2" style={{ fontSize: '2rem' }}></i>
|
||||
<h6 className="mb-0">Sports</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-6 col-md-4 col-lg-2">
|
||||
<div className="card h-100 text-center border-0 shadow-sm">
|
||||
<div className="card-body">
|
||||
<i className="bi bi-music-note-beamed text-primary mb-2" style={{ fontSize: '2rem' }}></i>
|
||||
<h6 className="mb-0">Music</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-6 col-md-4 col-lg-2">
|
||||
<div className="card h-100 text-center border-0 shadow-sm">
|
||||
<div className="card-body">
|
||||
<i className="bi bi-balloon text-primary mb-2" style={{ fontSize: '2rem' }}></i>
|
||||
<h6 className="mb-0">Party</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-6 col-md-4 col-lg-2">
|
||||
<div className="card h-100 text-center border-0 shadow-sm">
|
||||
<div className="card-body">
|
||||
<i className="bi bi-tree text-primary mb-2" style={{ fontSize: '2rem' }}></i>
|
||||
<h6 className="mb-0">Outdoor</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Benefits Section */}
|
||||
<div className="py-5 bg-light">
|
||||
<div className="container-fluid" style={{ maxWidth: '1800px' }}>
|
||||
<div className="row align-items-center">
|
||||
<div className="col-lg-6">
|
||||
<h2 className="mb-4">Why Choose CommunityRentals.App?</h2>
|
||||
<div className="d-flex mb-3">
|
||||
<i className="bi bi-check-circle-fill text-success me-3" style={{ fontSize: '1.5rem' }}></i>
|
||||
<div>
|
||||
<h5>Save Money</h5>
|
||||
<p className="text-muted">Why buy when you can rent? Access expensive items for a fraction of the purchase price.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex mb-3">
|
||||
<i className="bi bi-check-circle-fill text-success me-3" style={{ fontSize: '1.5rem' }}></i>
|
||||
<div>
|
||||
<h5>Earn Extra Income</h5>
|
||||
<p className="text-muted">Turn your unused items into a revenue stream. Your garage could be a goldmine.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex mb-3">
|
||||
<i className="bi bi-check-circle-fill text-success me-3" style={{ fontSize: '1.5rem' }}></i>
|
||||
<div>
|
||||
<h5>Build Community</h5>
|
||||
<p className="text-muted">Connect with neighbors and help each other. Sharing builds stronger communities.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex">
|
||||
<i className="bi bi-check-circle-fill text-success me-3" style={{ fontSize: '1.5rem' }}></i>
|
||||
<div>
|
||||
<h5>Reduce Waste</h5>
|
||||
<p className="text-muted">Share instead of everyone buying. It's better for your wallet and the planet.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-lg-6 text-center">
|
||||
<i className="bi bi-shield-check" style={{ fontSize: '15rem', color: '#e0e0e0' }}></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* CTA Section */}
|
||||
<div className="bg-primary text-white py-5">
|
||||
<div className="container text-center">
|
||||
<h2 className="mb-4">Ready to Get Started?</h2>
|
||||
<p className="lead mb-4">
|
||||
Join thousands of people sharing and renting in your community
|
||||
</p>
|
||||
<div className="d-flex gap-3 justify-content-center flex-wrap">
|
||||
<Link to="/items" className="btn btn-light btn-lg">
|
||||
Browse Rentals
|
||||
</Link>
|
||||
{user ? (
|
||||
<Link to="/create-item" className="btn btn-outline-light btn-lg">
|
||||
List an Item
|
||||
</Link>
|
||||
) : (
|
||||
<AuthButton mode="signup" className="btn btn-outline-light btn-lg">
|
||||
Sign Up Free
|
||||
</AuthButton>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -48,7 +48,7 @@ const ItemDetail: React.FC = () => {
|
||||
|
||||
const checkIfAlreadyRenting = async () => {
|
||||
try {
|
||||
const response = await rentalAPI.getMyRentals();
|
||||
const response = await rentalAPI.getRentals();
|
||||
const rentals: Rental[] = response.data;
|
||||
// Check if user has an active rental for this item
|
||||
const hasActiveRental = rentals.some(
|
||||
|
||||
@@ -10,7 +10,7 @@ import DeclineRentalModal from "../components/DeclineRentalModal";
|
||||
import ConditionCheckModal from "../components/ConditionCheckModal";
|
||||
import ReturnStatusModal from "../components/ReturnStatusModal";
|
||||
|
||||
const MyListings: React.FC = () => {
|
||||
const Owning: React.FC = () => {
|
||||
// Helper function to format time
|
||||
const formatTime = (timeString?: string) => {
|
||||
if (!timeString || timeString.trim() === "") return "";
|
||||
@@ -66,12 +66,12 @@ const MyListings: React.FC = () => {
|
||||
const [rentalForReturn, setRentalForReturn] = useState<Rental | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetchMyListings();
|
||||
fetchListings();
|
||||
fetchOwnerRentals();
|
||||
fetchAvailableChecks();
|
||||
}, [user]);
|
||||
|
||||
const fetchMyListings = async () => {
|
||||
const fetchListings = async () => {
|
||||
if (!user) return;
|
||||
|
||||
try {
|
||||
@@ -124,7 +124,7 @@ const MyListings: React.FC = () => {
|
||||
|
||||
const fetchOwnerRentals = async () => {
|
||||
try {
|
||||
const response = await rentalAPI.getMyListings();
|
||||
const response = await rentalAPI.getListings();
|
||||
setOwnerRentals(response.data);
|
||||
} catch (err: any) {
|
||||
console.error("Failed to fetch owner rentals:", err);
|
||||
@@ -698,4 +698,4 @@ const MyListings: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default MyListings;
|
||||
export default Owning;
|
||||
@@ -155,7 +155,7 @@ const Profile: React.FC = () => {
|
||||
);
|
||||
|
||||
// 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 acceptedRentals = ownerRentals.filter((r) =>
|
||||
@@ -194,14 +194,14 @@ const Profile: React.FC = () => {
|
||||
const fetchRentalHistory = async () => {
|
||||
try {
|
||||
// Fetch past rentals as a renter
|
||||
const renterResponse = await rentalAPI.getMyRentals();
|
||||
const renterResponse = await rentalAPI.getRentals();
|
||||
const pastRenterRentals = renterResponse.data.filter((r: Rental) =>
|
||||
["completed", "cancelled"].includes(r.status)
|
||||
);
|
||||
setPastRenterRentals(pastRenterRentals);
|
||||
|
||||
// Fetch past rentals as an owner
|
||||
const ownerResponse = await rentalAPI.getMyListings();
|
||||
const ownerResponse = await rentalAPI.getListings();
|
||||
const pastOwnerRentals = ownerResponse.data.filter((r: Rental) =>
|
||||
["completed", "cancelled"].includes(r.status)
|
||||
);
|
||||
@@ -608,7 +608,7 @@ const Profile: React.FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container mt-4">
|
||||
<div className="container mt-4 mb-5">
|
||||
<h1 className="mb-4">Profile</h1>
|
||||
|
||||
{error && (
|
||||
@@ -664,33 +664,6 @@ const Profile: React.FC = () => {
|
||||
<i className="bi bi-person me-2"></i>
|
||||
Personal Information
|
||||
</button>
|
||||
<button
|
||||
className={`list-group-item list-group-item-action ${
|
||||
activeSection === "notifications" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => setActiveSection("notifications")}
|
||||
>
|
||||
<i className="bi bi-bell me-2"></i>
|
||||
Notification Settings
|
||||
</button>
|
||||
<button
|
||||
className={`list-group-item list-group-item-action ${
|
||||
activeSection === "privacy" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => setActiveSection("privacy")}
|
||||
>
|
||||
<i className="bi bi-shield-lock me-2"></i>
|
||||
Privacy & Security
|
||||
</button>
|
||||
<button
|
||||
className={`list-group-item list-group-item-action ${
|
||||
activeSection === "payment" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => setActiveSection("payment")}
|
||||
>
|
||||
<i className="bi bi-credit-card me-2"></i>
|
||||
Payment Methods
|
||||
</button>
|
||||
<button
|
||||
className="list-group-item list-group-item-action text-danger"
|
||||
onClick={logout}
|
||||
@@ -804,12 +777,6 @@ const Profile: React.FC = () => {
|
||||
{profileData?.firstName} {profileData?.lastName}
|
||||
</h5>
|
||||
<p className="text-muted">@{profileData?.username}</p>
|
||||
{profileData?.isVerified && (
|
||||
<span className="badge bg-success mb-3">
|
||||
<i className="bi bi-check-circle-fill"></i>{" "}
|
||||
Verified
|
||||
</span>
|
||||
)}
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
@@ -1431,33 +1398,6 @@ const Profile: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Placeholder sections for other menu items */}
|
||||
{activeSection === "notifications" && (
|
||||
<div>
|
||||
<h4 className="mb-4">Notification Settings</h4>
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<p className="text-muted">
|
||||
Notification preferences coming soon...
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeSection === "privacy" && (
|
||||
<div>
|
||||
<h4 className="mb-4">Privacy & Security</h4>
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<p className="text-muted">
|
||||
Privacy and security settings coming soon...
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ const PublicProfile: React.FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container mt-4">
|
||||
<div className="container mt-4 mb-5">
|
||||
<div className="row justify-content-center">
|
||||
<div className="col-md-8">
|
||||
<div className="card">
|
||||
@@ -86,11 +86,6 @@ const PublicProfile: React.FC = () => {
|
||||
)}
|
||||
<h3>{user.firstName} {user.lastName}</h3>
|
||||
<p className="text-muted">@{user.username}</p>
|
||||
{user.isVerified && (
|
||||
<span className="badge bg-success">
|
||||
<i className="bi bi-check-circle-fill"></i> Verified User
|
||||
</span>
|
||||
)}
|
||||
{currentUser && currentUser.id !== user.id && (
|
||||
<button
|
||||
className="btn btn-primary mt-3"
|
||||
|
||||
@@ -223,7 +223,7 @@ const RentItem: React.FC = () => {
|
||||
<div className="d-grid gap-2 d-md-block">
|
||||
<button
|
||||
className="btn btn-primary me-2"
|
||||
onClick={() => navigate("/my-rentals")}
|
||||
onClick={() => navigate("/renting")}
|
||||
>
|
||||
View My Rentals
|
||||
</button>
|
||||
|
||||
@@ -7,7 +7,7 @@ import ReviewItemModal from "../components/ReviewModal";
|
||||
import RentalCancellationModal from "../components/RentalCancellationModal";
|
||||
import ConditionCheckModal from "../components/ConditionCheckModal";
|
||||
|
||||
const MyRentals: React.FC = () => {
|
||||
const Renting: React.FC = () => {
|
||||
// Helper function to format time
|
||||
const formatTime = (timeString?: string) => {
|
||||
if (!timeString || timeString.trim() === "") return "";
|
||||
@@ -66,7 +66,7 @@ const MyRentals: React.FC = () => {
|
||||
|
||||
const fetchRentals = async () => {
|
||||
try {
|
||||
const response = await rentalAPI.getMyRentals();
|
||||
const response = await rentalAPI.getRentals();
|
||||
setRentals(response.data);
|
||||
} catch (err: any) {
|
||||
setError(err.response?.data?.message || "Failed to fetch rentals");
|
||||
@@ -470,4 +470,4 @@ const MyRentals: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default MyRentals;
|
||||
export default Renting;
|
||||
@@ -203,8 +203,8 @@ export const itemAPI = {
|
||||
|
||||
export const rentalAPI = {
|
||||
createRental: (data: any) => api.post("/rentals", data),
|
||||
getMyRentals: () => api.get("/rentals/my-rentals"),
|
||||
getMyListings: () => api.get("/rentals/my-listings"),
|
||||
getRentals: () => api.get("/rentals/renting"),
|
||||
getListings: () => api.get("/rentals/owning"),
|
||||
getPendingRequestsCount: () => api.get("/rentals/pending-requests-count"),
|
||||
updateRentalStatus: (id: string, status: string) =>
|
||||
api.put(`/rentals/${id}/status`, { status }),
|
||||
|
||||
Reference in New Issue
Block a user