Files
SweetHome/app/layout.js
Rahaf 6d81ff56a8 Edit admin page
Edit home image
Added properties page
2026-02-15 01:53:37 +03:00

285 lines
12 KiB
JavaScript

'use client';
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import "./i18n/config";
import Link from "next/link";
import Image from "next/image";
import { NavLink, MobileNavLink } from "./components/NavLinks";
import { useTranslation } from 'react-i18next';
import { Globe } from 'lucide-react';
import { useState, useEffect } from 'react';
import { motion } from 'framer-motion';
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export default function RootLayout({ children }) {
const { t, i18n } = useTranslation();
const [currentLanguage, setCurrentLanguage] = useState('en');
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const currentYear = new Date().getFullYear();
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
setCurrentLanguage(lng);
localStorage.setItem('language', lng);
if (lng === 'ar') {
document.documentElement.dir = 'rtl';
document.documentElement.lang = 'ar';
document.documentElement.classList.add('rtl');
document.documentElement.classList.remove('ltr');
} else {
document.documentElement.dir = 'ltr';
document.documentElement.lang = 'en';
document.documentElement.classList.add('ltr');
document.documentElement.classList.remove('rtl');
}
};
useEffect(() => {
const savedLanguage = localStorage.getItem('language') || 'en';
const lng = savedLanguage;
setCurrentLanguage(lng);
i18n.changeLanguage(lng);
if (lng === 'ar') {
document.documentElement.dir = 'rtl';
document.documentElement.lang = 'ar';
document.documentElement.classList.add('rtl');
} else {
document.documentElement.dir = 'ltr';
document.documentElement.lang = 'en';
document.documentElement.classList.add('ltr');
}
}, [i18n]);
const toggleMobileMenu = () => {
setIsMobileMenuOpen(!isMobileMenuOpen);
};
const closeMobileMenu = () => {
setIsMobileMenuOpen(false);
};
return (
<html lang={currentLanguage}>
<head>
<title>SweetHome</title>
<meta name="description" content={currentLanguage === 'ar' ? 'اكتشف أثاث وديكور منزلي فاخر' : 'Discover premium furniture and home decor'} />
</head>
<body className={`${geistSans.variable} ${geistMono.variable} antialiased ${currentLanguage === 'ar' ? 'font-arabic' : ''}`}>
<nav className="fixed top-0 left-0 right-0 bg-white/95 backdrop-blur-sm border-b border-gray-200 z-50 transition-all duration-300 shadow-sm">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className={`flex justify-between items-center h-20 ${currentLanguage === 'ar' ? 'flex-row-reverse' : ''}`}>
<div className="flex items-center">
<Link href="/" className="flex items-center space-x-3 group">
<div className="relative w-10 h-10">
<Image
src="/logo.png"
alt={t("logoAlt")}
fill
className="object-contain group-hover:scale-105 transition-transform duration-300"
priority
sizes="40px"
/>
</div>
<span className="text-3xl font-bold text-gray-800 hidden md:block">
{t("brandNamePart1")}<span className="text-amber-600">{t("brandNamePart2")}</span>
</span>
</Link>
</div>
<div className="hidden md:flex items-center space-x-4">
<div className={`flex items-center space-x-1 ${currentLanguage === 'ar' ? 'flex-row-reverse space-x-reverse' : ''}`}>
<NavLink href="/">
{t("home")}
</NavLink>
<NavLink href="/properties">
{t("ourProducts")}
</NavLink>
<NavLink href="/admin">
{t("admin")}
</NavLink>
</div>
<motion.button
whileHover={{ scale: 1.1, rotate: 360 }}
whileTap={{ scale: 0.9 }}
onClick={() => changeLanguage(currentLanguage === 'en' ? 'ar' : 'en')}
className="flex items-center justify-center w-10 h-10 bg-gray-100 hover:bg-gray-200 rounded-full transition-all duration-200 ml-4"
aria-label={currentLanguage === 'en' ? t("switchToArabic") : t("switchToEnglish")}
title={currentLanguage === 'en' ? t("switchToArabic") : t("switchToEnglish")}
>
<Globe className="w-5 h-5 text-gray-700" />
</motion.button>
</div>
<div className="md:hidden flex items-center gap-3">
<motion.button
whileHover={{ scale: 1.1, rotate: 360 }}
whileTap={{ scale: 0.9 }}
onClick={() => changeLanguage(currentLanguage === 'en' ? 'ar' : 'en')}
className="flex items-center justify-center w-10 h-10 bg-gray-100 hover:bg-gray-200 rounded-full transition-colors"
aria-label={currentLanguage === 'en' ? t("switchToArabic") : t("switchToEnglish")}
title={currentLanguage === 'en' ? t("switchToArabic") : t("switchToEnglish")}
>
<Globe className="w-5 h-5 text-gray-700" />
</motion.button>
<button
type="button"
onClick={toggleMobileMenu}
className="inline-flex items-center justify-center p-2 rounded-md text-gray-700 hover:text-amber-600 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-amber-500 transition-colors"
aria-expanded={isMobileMenuOpen}
aria-label={t("openMainMenu")}
>
<span className="sr-only">{t("openMainMenu")}</span>
{isMobileMenuOpen ? (
<svg
className="h-6 w-6"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
) : (
<svg
className="h-6 w-6"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
</svg>
)}
</button>
</div>
</div>
</div>
{isMobileMenuOpen && (
<motion.div
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
className="md:hidden bg-white border-t border-gray-200 shadow-lg"
>
<div className="px-2 pt-2 pb-3 space-y-1">
<MobileNavLink href="/" onClick={closeMobileMenu}>
{t("home")}
</MobileNavLink>
<MobileNavLink href="/properties" onClick={closeMobileMenu}>
{t("ourProducts")}
</MobileNavLink>
<MobileNavLink href="/admin" onClick={closeMobileMenu}>
{t("admin")}
</MobileNavLink>
</div>
</motion.div>
)}
</nav>
<main className={`pt-16 min-h-screen bg-gradient-to-b from-gray-50 to-white ${currentLanguage === 'ar' ? 'text-right' : 'text-left'}`}>
{children}
</main>
<footer className="bg-gray-900 text-white py-12">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className={`grid grid-cols-1 md:grid-cols-4 gap-8 ${currentLanguage === 'ar' ? 'text-right' : 'text-left'}`}>
<div className="space-y-4">
<div className={`flex items-center ${currentLanguage === 'ar' ? 'flex-row-reverse' : 'space-x-3'}`}>
<div className="relative w-10 h-10">
<Image
src="/logo.png"
alt={t("logoAlt")}
fill
className="object-contain"
sizes="40px"
/>
</div>
<span className="text-3xl font-bold">
{t("brandNamePart1")}<span className="text-amber-400">{t("brandNamePart2")}</span>
</span>
</div>
<p className="text-gray-400 text-sm">
{t("footerDescription")}
</p>
</div>
<div>
<h3 className="text-lg font-semibold mb-4">{t("quickLinks")}</h3>
<ul className="space-y-2">
<li>
<Link href="/" className="text-gray-400 hover:text-white transition-colors block py-1">
{t("home")}
</Link>
</li>
<li>
<Link href="/properties" className="text-gray-400 hover:text-white transition-colors block py-1">
{t("ourProducts")}
</Link>
</li>
<li>
<Link href="/admin" className="text-gray-400 hover:text-white transition-colors block py-1">
{t("admin")}
</Link>
</li>
</ul>
</div>
<div>
<h3 className="text-lg font-semibold mb-4">{t("contactUs")}</h3>
<ul className="space-y-3 text-gray-400">
<li className={`flex items-center ${currentLanguage === 'ar' ? 'flex-row-reverse' : 'space-x-2'}`}>
<svg className="w-5 h-5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
</svg>
<span>{t("phone")}</span>
</li>
<li className={`flex items-center ${currentLanguage === 'ar' ? 'flex-row-reverse' : 'space-x-2'}`}>
<svg className="w-5 h-5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
<span>{t("footerEmail")}</span>
</li>
</ul>
</div>
<div>
<h3 className="text-lg font-semibold mb-4">{t("stayUpdated")}</h3>
<div className="space-y-3">
<input
type="email"
placeholder={t("yourEmail")}
className="w-full px-4 py-2 bg-gray-800 border border-gray-700 rounded-lg focus:outline-none focus:ring-2 focus:ring-amber-500 focus:border-transparent"
/>
<button className="w-full bg-amber-600 hover:bg-amber-700 text-white px-4 py-2 rounded-lg transition-colors font-medium">
{t("subscribe")}
</button>
</div>
</div>
</div>
<div className="mt-8 pt-8 border-t border-gray-800 text-center text-gray-400 text-sm">
<p>&copy; {currentYear} {t("copyright")}. {t("allRightsReserved")}</p>
</div>
</div>
</footer>
</body>
</html>
);
}