home page rework

This commit is contained in:
jackiettran
2025-07-18 22:07:53 -04:00
parent f289022b5d
commit e65c53e6aa
4 changed files with 336 additions and 114 deletions

View File

@@ -2,6 +2,7 @@ import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import { AuthProvider } from './contexts/AuthContext';
import Navbar from './components/Navbar';
import Footer from './components/Footer';
import Home from './pages/Home';
import Login from './pages/Login';
import Register from './pages/Register';
@@ -23,8 +24,10 @@ function App() {
return (
<AuthProvider>
<Router>
<Navbar />
<Routes>
<div className="d-flex flex-column min-vh-100">
<Navbar />
<main className="flex-grow-1">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
@@ -95,7 +98,10 @@ function App() {
</PrivateRoute>
}
/>
</Routes>
</Routes>
</main>
<Footer />
</div>
</Router>
</AuthProvider>
);

View File

@@ -0,0 +1,142 @@
import React from 'react';
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>
Rentall
</h5>
<p className="small text-white-50">
The marketplace for renting anything, from anyone, anywhere.
</p>
</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 Rentall. 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">
Privacy Policy
</Link>
<Link to="/terms" className="text-decoration-none text-white-50 small">
Terms of Service
</Link>
</div>
</div>
</div>
</footer>
);
};
export default Footer;

View File

@@ -13,7 +13,7 @@ const Navbar: React.FC = () => {
return (
<nav className="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
<div className="container">
<div className="container-fluid" style={{ maxWidth: '1800px' }}>
<Link className="navbar-brand fw-bold" to="/">
<i className="bi bi-box-seam me-2"></i>
Rentall
@@ -30,82 +30,88 @@ const Navbar: React.FC = () => {
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarNav">
<ul className="navbar-nav me-auto">
<li className="nav-item">
<Link className="nav-link" to="/items">
Browse Items
<div className="d-flex align-items-center w-100">
<div className="position-absolute start-50 translate-middle-x">
<div className="input-group" style={{ width: '400px' }}>
<input
type="text"
className="form-control"
placeholder="Search for items to rent..."
aria-label="Search"
/>
<button className="btn btn-outline-secondary" type="button">
<i className="bi bi-search"></i>
</button>
</div>
</div>
<div className="ms-auto d-flex align-items-center">
<Link className="btn btn-outline-primary btn-sm me-3 text-nowrap" to="/create-item">
Start Earning
</Link>
</li>
{user && (
<li className="nav-item">
<Link className="nav-link" to="/create-item">
List an Item
</Link>
</li>
)}
</ul>
<ul className="navbar-nav">
{user ? (
<>
<li className="nav-item dropdown">
<a
className="nav-link dropdown-toggle"
href="#"
id="navbarDropdown"
role="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
<i className="bi bi-person-circle me-1"></i>
{user.firstName}
</a>
<ul className="dropdown-menu" aria-labelledby="navbarDropdown">
<li>
<Link className="dropdown-item" to="/profile">
<i className="bi bi-person me-2"></i>Profile
<ul className="navbar-nav flex-row">
{user ? (
<>
<li className="nav-item dropdown">
<a
className="nav-link dropdown-toggle"
href="#"
id="navbarDropdown"
role="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
<i className="bi bi-person-circle me-1"></i>
{user.firstName}
</a>
<ul className="dropdown-menu" aria-labelledby="navbarDropdown">
<li>
<Link className="dropdown-item" to="/profile">
<i className="bi bi-person me-2"></i>Profile
</Link>
</li>
<li>
<Link className="dropdown-item" to="/my-rentals">
<i className="bi bi-calendar-check me-2"></i>My Rentals
</Link>
</li>
<li>
<Link className="dropdown-item" to="/my-listings">
<i className="bi bi-list-ul me-2"></i>My Listings
</Link>
</li>
<li>
<Link className="dropdown-item" to="/messages">
<i className="bi bi-envelope me-2"></i>Messages
</Link>
</li>
<li>
<hr className="dropdown-divider" />
</li>
<li>
<button className="dropdown-item" onClick={handleLogout}>
<i className="bi bi-box-arrow-right me-2"></i>Logout
</button>
</li>
</ul>
</li>
</>
) : (
<>
<li className="nav-item me-2">
<Link className="btn btn-outline-secondary btn-sm text-nowrap" to="/login">
Login
</Link>
</li>
<li>
<Link className="dropdown-item" to="/my-rentals">
<i className="bi bi-calendar-check me-2"></i>My Rentals
<li className="nav-item">
<Link className="btn btn-primary btn-sm text-nowrap" to="/register">
Sign Up
</Link>
</li>
<li>
<Link className="dropdown-item" to="/my-listings">
<i className="bi bi-list-ul me-2"></i>My Listings
</Link>
</li>
<li>
<Link className="dropdown-item" to="/messages">
<i className="bi bi-envelope me-2"></i>Messages
</Link>
</li>
<li>
<hr className="dropdown-divider" />
</li>
<li>
<button className="dropdown-item" onClick={handleLogout}>
<i className="bi bi-box-arrow-right me-2"></i>Logout
</button>
</li>
</ul>
</li>
</>
) : (
<>
<li className="nav-item">
<Link className="nav-link" to="/login">
Login
</Link>
</li>
<li className="nav-item">
<Link className="btn btn-primary btn-sm ms-2" to="/register">
Sign Up
</Link>
</li>
</>
)}
</ul>
</>
)}
</ul>
</div>
</div>
</div>
</div>
</nav>

View File

@@ -1,49 +1,141 @@
import React from 'react';
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';
const Home: React.FC = () => {
const { user } = useAuth();
const [featuredItems, setFeaturedItems] = useState<Item[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchFeaturedItems = async () => {
try {
const response = await itemAPI.getItems({ limit: 8 });
setFeaturedItems(response.data.items);
} catch (error) {
console.error('Error fetching items:', error);
} finally {
setLoading(false);
}
};
fetchFeaturedItems();
}, []);
return (
<div>
{/* Hero Section */}
<div className="bg-primary text-white py-5">
<div className="container">
<div className="row align-items-center min-vh-50">
<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="display-4 fw-bold mb-4">
<h1 className="fs-2 fw-bold mb-2">
Rent Anything, From Anyone, Anywhere
</h1>
<p className="lead mb-4">
<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 btn-lg">
<Link to="/items" className="btn btn-light">
Start Renting
</Link>
{user ? (
<Link to="/create-item" className="btn btn-outline-light btn-lg">
<Link to="/create-item" className="btn btn-outline-light">
List Your Items
</Link>
) : (
<Link to="/register" className="btn btn-outline-light btn-lg">
<Link to="/register" className="btn btn-outline-light">
Start Earning
</Link>
)}
</div>
</div>
<div className="col-lg-6 text-center">
<i className="bi bi-box-seam" style={{ fontSize: '15rem', opacity: 0.3 }}></i>
<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>
{loading ? (
<div className="text-center py-4">
<div className="spinner-border text-primary" role="status">
<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">
<Link to={`/items/${item.id}`} className="text-decoration-none">
<div className="card h-100 shadow-sm hover-shadow">
{item.images && item.images.length > 0 ? (
<img
src={item.images[0]}
className="card-img-top"
alt={item.name}
style={{ height: '150px', objectFit: 'cover' }}
/>
) : (
<div
className="card-img-top bg-light d-flex align-items-center justify-content-center"
style={{ height: '150px' }}
>
<i className="bi bi-image text-muted" style={{ fontSize: '2rem' }}></i>
</div>
)}
<div className="card-body p-2">
<h6 className="card-title text-truncate mb-1">{item.name}</h6>
<p className="card-text text-muted small text-truncate mb-1">
{item.location}
</p>
<div className="d-flex justify-content-between align-items-center">
<div>
{item.pricePerDay && (
<div className="fw-bold small">
${item.pricePerDay}/day
</div>
)}
</div>
<small className="text-muted" style={{ fontSize: '0.75rem' }}>
{item.owner?.firstName || 'Unknown'}
</small>
</div>
</div>
</div>
</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">
Be the first to list an item!
</Link>
</div>
)}
</div>
</div>
{/* How It Works - For Renters */}
<div className="py-5">
<div className="container">
<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">
@@ -82,7 +174,7 @@ const Home: React.FC = () => {
{/* How It Works - For Owners */}
<div className="py-5 bg-light">
<div className="container">
<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">
@@ -121,7 +213,7 @@ const Home: React.FC = () => {
{/* Popular Categories */}
<div className="py-5">
<div className="container">
<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">
@@ -178,7 +270,7 @@ const Home: React.FC = () => {
{/* Benefits Section */}
<div className="py-5 bg-light">
<div className="container">
<div className="container-fluid" style={{ maxWidth: '1800px' }}>
<div className="row align-items-center">
<div className="col-lg-6">
<h2 className="mb-4">Why Choose Rentall?</h2>
@@ -241,30 +333,6 @@ const Home: React.FC = () => {
</div>
</div>
</div>
{/* Stats Section */}
<div className="py-5">
<div className="container">
<div className="row text-center">
<div className="col-md-3">
<h2 className="text-primary">1000+</h2>
<p className="text-muted">Active Items</p>
</div>
<div className="col-md-3">
<h2 className="text-primary">500+</h2>
<p className="text-muted">Happy Renters</p>
</div>
<div className="col-md-3">
<h2 className="text-primary">$50k+</h2>
<p className="text-muted">Earned by Owners</p>
</div>
<div className="col-md-3">
<h2 className="text-primary">4.8</h2>
<p className="text-muted">Average Rating</p>
</div>
</div>
</div>
</div>
</div>
);
};