Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
"@testing-library/user-event": "^13.5.0",
"autoprefixer": "^10.4.21",
"axios": "^1.8.4",
"i18next": "^25.7.3",
"leaflet": "1.9.4",
"lucide-react": "^0.544.0",
"node-fetch": "^3.3.2",
"postcss": "^8.5.3",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-i18next": "^16.5.1",
"react-icons": "^5.5.0",
"react-leaflet": "4.2.1",
"react-router-dom": "^7.4.0",
Expand Down
51 changes: 26 additions & 25 deletions frontend/src/components/Footer.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";

const Footer = () => {

const [email, setEmail] = useState("");
const [isSubscribing, setIsSubscribing] = useState(false);
const [subscribeStatus, setSubscribeStatus] = useState(null); // null | 'success' | 'error'
const { t } = useTranslation('footer');

const handleSubscribe = async (e) => {
e.preventDefault();
Expand Down Expand Up @@ -48,9 +51,7 @@ const Footer = () => {
<span className="font-light">RentSystem</span>
</h3>
<p className="text-neutral-400 mb-6 leading-relaxed max-w-sm">
Find your perfect home away from home. SmartRent provides a secure
platform for property rental with verified hosts and quality
listings.
{t("companyDescription")}
</p>
<div className="flex space-x-4">
<a
Expand Down Expand Up @@ -97,7 +98,7 @@ const Footer = () => {
{/* Quick Links */}
<div className="mt-4 sm:mt-0">
<h3 className="text-lg font-semibold mb-4 sm:mb-6 text-white inline-block border-b-2 border-primary-500 pb-1">
Quick Links
{t("quickLinks")}
</h3>
<ul className="space-y-2.5 sm:space-y-3">
<li>
Expand All @@ -107,7 +108,7 @@ const Footer = () => {
onClick={() => window.scrollTo(0, 0)}
>
<i className="fas fa-chevron-right text-xs mr-2 text-primary-500"></i>
Home
{t("home")}
</Link>
</li>
<li>
Expand All @@ -117,7 +118,7 @@ const Footer = () => {
onClick={() => window.scrollTo(0, 0)}
>
<i className="fas fa-chevron-right text-xs mr-2 text-primary-500"></i>
About Us
{t("aboutUs")}
</Link>
</li>
<li>
Expand All @@ -127,7 +128,7 @@ const Footer = () => {
onClick={() => window.scrollTo(0, 0)}
>
<i className="fas fa-chevron-right text-xs mr-2 text-primary-500"></i>
Contact
{t("contact")}
</Link>
</li>
<li>
Expand All @@ -137,15 +138,15 @@ const Footer = () => {
onClick={() => window.scrollTo(0, 0)}
>
<i className="fas fa-chevron-right text-xs mr-2 text-primary-500"></i>
Blog
{t("blog")}
</Link>
</li>
</ul>
</div>

{/* Support */}
<div>
<h3 className="text-lg font-semibold mb-6 text-white">Support</h3>
<h3 className="text-lg font-semibold mb-6 text-white">{t("support")}</h3>
<ul className="space-y-3">
<li>
<Link
Expand All @@ -154,7 +155,7 @@ const Footer = () => {
onClick={() => window.scrollTo(0, 0)}
>
<i className="fas fa-chevron-right text-xs mr-2 text-primary-500"></i>
Help
{t("help")}
</Link>
</li>
<li>
Expand All @@ -164,7 +165,7 @@ const Footer = () => {
onClick={() => window.scrollTo(0, 0)}
>
<i className="fas fa-chevron-right text-xs mr-2 text-primary-500"></i>
Safety Information
{t("safetyInformation")}
</Link>
</li>
<li>
Expand All @@ -174,7 +175,7 @@ const Footer = () => {
onClick={() => window.scrollTo(0, 0)}
>
<i className="fas fa-chevron-right text-xs mr-2 text-primary-500"></i>
Cancellation Options
{t("cancellationOptions")}
</Link>
</li>
<li>
Expand All @@ -184,7 +185,7 @@ const Footer = () => {
onClick={() => window.scrollTo(0, 0)}
>
<i className="fas fa-chevron-right text-xs mr-2 text-primary-500"></i>
Report Concern
{t("reportConcern")}
</Link>
</li>
<li>
Expand All @@ -194,7 +195,7 @@ const Footer = () => {
onClick={() => window.scrollTo(0, 0)}
>
<i className="fas fa-chevron-right text-xs mr-2 text-primary-500"></i>
FAQ
{t("faq")}
</Link>
</li>
</ul>
Expand All @@ -203,13 +204,13 @@ const Footer = () => {
{/* Contact */}
<div className="mt-4 sm:mt-0">
<h3 className="text-lg font-semibold mb-4 sm:mb-6 text-white inline-block border-b-2 border-primary-500 pb-1">
Contact Us
{t("contactUs")}
</h3>
<ul className="space-y-4 text-neutral-400">
<li className="flex items-start justify-center sm:justify-start group">
<i className="fas fa-map-marker-alt mt-1 mr-3 text-primary-500 group-hover:scale-110 transition-transform duration-300"></i>
<span className="group-hover:text-neutral-300 transition-colors duration-300">
123 Rent Street, City, Country
{t("address")}
</span>
</li>
<li className="flex items-center justify-center sm:justify-start group">
Expand All @@ -233,13 +234,13 @@ const Footer = () => {
</ul>
<div className="mt-8">
<h4 className="text-sm font-semibold mb-4 text-white">
Subscribe to Newsletter
{t("subscribeNewsletter")}
</h4>
<form onSubmit={handleSubscribe} className="space-y-2">
<div className="flex max-w-sm mx-auto sm:mx-0 group focus-within:scale-[1.02] transition-transform duration-300">
<input
type="email"
placeholder="Your email"
placeholder={t("yourEmail")}
value={email}
onChange={(e) => setEmail(e.target.value)}
className={`w-full text-sm text-neutral-800 bg-neutral-100 rounded-l-lg px-4 py-2.5
Expand All @@ -264,8 +265,8 @@ const Footer = () => {
disabled={isSubscribing}
aria-label={
isSubscribing
? "Subscribing..."
: "Subscribe to newsletter"
? t("subscribing")
: t("subscribeNewsletter")
}
>
{isSubscribing ? (
Expand All @@ -285,8 +286,8 @@ const Footer = () => {
} transition-all duration-300 animate-fadeIn text-center sm:text-left`}
>
{subscribeStatus === "success"
? "Thank you for subscribing!"
: "Please enter a valid email address."}
? t("subscribeSuccess")
: t("subscribeError")}
</p>
)}
</form>
Expand All @@ -308,23 +309,23 @@ const Footer = () => {
className="text-neutral-400 hover:text-primary-400 text-sm transition-all duration-300 hover:translate-y-[-1px]"
onClick={() => window.scrollTo(0, 0)}
>
Privacy Policy
{t("privacyPolicy")}
</Link>
<span className="hidden sm:block text-neutral-600">β€’</span>
<Link
to="/terms"
className="text-neutral-400 hover:text-primary-400 text-sm transition-all duration-300 hover:translate-y-[-1px]"
onClick={() => window.scrollTo(0, 0)}
>
Terms of Service
{t("termsOfService")}
</Link>
<span className="hidden sm:block text-neutral-600">β€’</span>
<Link
to="/cookies"
className="text-neutral-400 hover:text-primary-400 text-sm transition-all duration-300 hover:translate-y-[-1px]"
onClick={() => window.scrollTo(0, 0)}
>
Cookie Policy
{t("cookiePolicy")}
</Link>
</div>
</div>
Expand Down
36 changes: 20 additions & 16 deletions frontend/src/components/Navbar.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useEffect, useState, useRef } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { useAppSettings } from "../contexts/AppSettingsContext";
import { useTranslation } from "react-i18next";
import { useAuth } from "../contexts/AuthContext";
import NavLogo from "./navbar/NavLogo";
import NavSearch from "./navbar/NavSearch";
Expand Down Expand Up @@ -29,6 +30,7 @@ const Navbar = () => {
// Use auth context
const { currentUser, logout, isAuthenticated } = useAuth();


// Use the app settings context
const {
language,
Expand All @@ -37,11 +39,13 @@ const Navbar = () => {
changeLanguage,
changeCurrency,
supportedLanguages,
getText,
isTranslating,
isLoadingRates,
} = useAppSettings();

// Use i18next translation hook
const { t } = useTranslation('navbar');

// Popular suggestions
const suggestions = [
"New York",
Expand All @@ -62,7 +66,7 @@ const Navbar = () => {
{ code: "INR", symbol: "β‚Ή", name: "Indian Rupee" },
];

// Close profile and settings menus on route change
// Close profile and settings menus on route change
useEffect(() => {
setIsProfileMenuOpen(false);
setIsSettingsMenuOpen(false);
Expand Down Expand Up @@ -230,7 +234,7 @@ const Navbar = () => {
aria-label="Explore Properties"
>
<i className="fas fa-compass text-lg"></i>
<span className="font-medium">Explore</span>
<span className="font-medium">{t('explore')}</span>
</Link>
</div>
)}
Expand All @@ -244,7 +248,7 @@ const Navbar = () => {
<form onSubmit={handleSearchSubmit} className="relative w-full flex items-center">
<input
type="text"
placeholder={getText("common", "search")}
placeholder={t("search")}
value={searchQuery}
onChange={handleSearchChange}
onFocus={() => setIsSearchFocused(true)}
Expand Down Expand Up @@ -328,7 +332,7 @@ const Navbar = () => {
to="/host/become-a-host"
className="text-neutral-700 hover:text-neutral-900 px-4 py-2 rounded-full text-sm font-medium hidden sm:block"
>
{getText("common", "becomeHost")}
{t("becomeHost")}
</Link>

{/* Language and Currency Selector */}
Expand Down Expand Up @@ -628,28 +632,28 @@ const Navbar = () => {
className="block px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-50"
onClick={() => setIsProfileMenuOpen(false)}
>
{getText("common", "login")}
{t("login")}
</Link>
<Link
to="/register"
className="block px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-50"
onClick={() => setIsProfileMenuOpen(false)}
>
{getText("common", "signup")}
{t("signup")}
</Link>
<Link
to="/host/become-a-host"
className="block px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-50"
onClick={() => setIsProfileMenuOpen(false)}
>
{getText("common", "becomeHost")}
{t("becomeHost")}
</Link>
<Link
to="/help"
className="block px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-50"
onClick={() => setIsProfileMenuOpen(false)}
>
{getText("common", "help")}
{t("help")}
</Link>
</div>
) : (
Expand Down Expand Up @@ -694,21 +698,21 @@ const Navbar = () => {
className="block px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-50"
onClick={() => setIsProfileMenuOpen(false)}
>
{getText("common", "messages")}
{t("messages")}
</Link>
<Link
to="/trips"
className="block px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-50"
onClick={() => setIsProfileMenuOpen(false)}
>
{getText("common", "trips")}
{t("trips")}
</Link>
<Link
to="/wishlist"
className="block px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-50"
onClick={() => setIsProfileMenuOpen(false)}
>
{getText("common", "wishlist")}
{t("wishlist")}
</Link>
</div>
{/* Account management links */}
Expand All @@ -725,20 +729,20 @@ const Navbar = () => {
className="block px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-50"
onClick={() => setIsProfileMenuOpen(false)}
>
{getText("common", "account")}
{t("account")}
</Link>
<button
className="w-full text-left block px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-50"
onClick={handleLogout}
>
{getText("common", "logout")}
{t("logout")}
</button>
<Link
to="/help"
className="block px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-50"
onClick={() => setIsProfileMenuOpen(false)}
>
{getText("common", "help")}
{t("help")}
</Link>
</div>
</>
Expand Down Expand Up @@ -766,7 +770,7 @@ const Navbar = () => {
<form onSubmit={handleSearchSubmit} className="w-full">
<input
type="text"
placeholder={getText("common", "search")}
placeholder={t("search")}
value={searchQuery}
onChange={handleSearchChange}
className="w-full px-4 py-2 border border-neutral-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500"
Expand Down
Loading