diff --git a/client/build/images/logo.png b/client/build/images/logo.png
index e198825..f720038 100644
Binary files a/client/build/images/logo.png and b/client/build/images/logo.png differ
diff --git a/client/package-lock.json b/client/package-lock.json
index 187cdcb..e9e17bc 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -30,6 +30,9 @@
"react-router-dom": "^6.19.0",
"react-scripts": "^5.0.1",
"swiper": "^11.0.5"
+ },
+ "devDependencies": {
+ "cross-env": "^10.1.0"
}
},
"node_modules/@alloc/quick-lru": {
@@ -2526,6 +2529,13 @@
"integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==",
"license": "MIT"
},
+ "node_modules/@epic-web/invariant": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz",
+ "integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@eslint-community/eslint-utils": {
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
@@ -6565,6 +6575,24 @@
"node": ">=10"
}
},
+ "node_modules/cross-env": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz",
+ "integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@epic-web/invariant": "^1.0.0",
+ "cross-spawn": "^7.0.6"
+ },
+ "bin": {
+ "cross-env": "dist/bin/cross-env.js",
+ "cross-env-shell": "dist/bin/cross-env-shell.js"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -16978,20 +17006,6 @@
}
}
},
- "node_modules/tailwindcss/node_modules/yaml": {
- "version": "2.8.1",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
- "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
- "license": "ISC",
- "optional": true,
- "peer": true,
- "bin": {
- "yaml": "bin.mjs"
- },
- "engines": {
- "node": ">= 14.6"
- }
- },
"node_modules/tapable": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
diff --git a/client/package.json b/client/package.json
index b455171..ecb2805 100644
--- a/client/package.json
+++ b/client/package.json
@@ -27,7 +27,7 @@
"swiper": "^11.0.5"
},
"scripts": {
- "start": "PORT=3060 react-scripts start",
+ "start": "cross-env PORT=3060 react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
@@ -50,5 +50,8 @@
"last 1 safari version"
]
},
- "proxy": "http://localhost:5080"
+ "proxy": "http://localhost:5080",
+ "devDependencies": {
+ "cross-env": "^10.1.0"
+ }
}
diff --git a/client/public/images/logo.png b/client/public/images/logo.png
index e198825..f720038 100644
Binary files a/client/public/images/logo.png and b/client/public/images/logo.png differ
diff --git a/client/src/components/layout/Header.js b/client/src/components/layout/Header.js
index 393cee9..eb1ace4 100644
--- a/client/src/components/layout/Header.js
+++ b/client/src/components/layout/Header.js
@@ -2,7 +2,6 @@ import React, { useState, useEffect } from 'react';
import {
AppBar,
Toolbar,
- Typography,
Button,
Box,
IconButton,
@@ -15,8 +14,6 @@ import {
ListItemText,
useMediaQuery,
useTheme,
- Select,
- FormControl,
} from '@mui/material';
import {
Menu as MenuIcon,
@@ -32,11 +29,21 @@ const Header = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('lg'));
const location = useLocation();
-
+
const [mobileOpen, setMobileOpen] = useState(false);
const [languageAnchor, setLanguageAnchor] = useState(null);
const [scrolled, setScrolled] = useState(false);
+ // ✅ لون غامق ثابت للهيدر الفاتح (حتى لو الثيم Dark)
+ const lightHeaderText = '#1a1a1a';
+
+ // ✅ Pending 17: Book Now -> WhatsApp with preset message
+ const WA_NUMBER = '963986105010';
+ const WA_TEXT = encodeURIComponent(
+ 'For all booking inquiries and reservation confirmations, kindly contact us via WhatsApp'
+ );
+ const WA_LINK = `https://wa.me/${WA_NUMBER}?text=${WA_TEXT}`;
+
const navigationItems = [
{ label: t('nav.home'), path: '/' },
{ label: t('nav.about'), path: '/about' },
@@ -53,25 +60,24 @@ const Header = () => {
];
useEffect(() => {
- const handleScroll = () => {
- setScrolled(window.scrollY > 50);
- };
+ const handleScroll = () => setScrolled(window.scrollY > 50);
window.addEventListener('scroll', handleScroll);
+ handleScroll();
return () => window.removeEventListener('scroll', handleScroll);
}, []);
- const handleDrawerToggle = () => {
- setMobileOpen(!mobileOpen);
- };
+ // ✅ صفحات الخلفية عندها فاتحة (زيدي هون أي route تاني)
+ const lightHeaderRoutes = ['/facilities', '/contact'];
+ const forceLightHeader = lightHeaderRoutes.some(
+ (r) => location.pathname === r || location.pathname.startsWith(r + '/')
+ );
- const handleLanguageClick = (event) => {
- setLanguageAnchor(event.currentTarget);
- };
+ const isLightHeader = scrolled || forceLightHeader;
- const handleLanguageClose = () => {
- setLanguageAnchor(null);
- };
+ const handleDrawerToggle = () => setMobileOpen((prev) => !prev);
+ const handleLanguageClick = (event) => setLanguageAnchor(event.currentTarget);
+ const handleLanguageClose = () => setLanguageAnchor(null);
const handleLanguageChange = (languageCode) => {
i18n.changeLanguage(languageCode);
handleLanguageClose();
@@ -100,7 +106,7 @@ const Header = () => {
-
+
{navigationItems.map((item) => (
@@ -110,7 +116,7 @@ const Header = () => {
sx={{
textAlign: 'center',
backgroundColor: isActiveRoute(item.path) ? 'primary.main' : 'transparent',
- color: isActiveRoute(item.path) ? 'white' : 'text.primary',
+ color: isActiveRoute(item.path) ? 'white' : lightHeaderText,
'&:hover': {
backgroundColor: 'primary.light',
color: 'white',
@@ -121,20 +127,21 @@ const Header = () => {
))}
-
+
+ {/* ✅ Pending 17: Drawer Book Now -> WhatsApp */}
@@ -149,15 +156,22 @@ const Header = () => {
-
+
{/* Logo */}
{
display: 'flex',
alignItems: 'center',
textDecoration: 'none',
- '&:hover': {
- opacity: 0.8,
- },
+ '&:hover': { opacity: 0.8 },
}}
>
{
component={Link}
to={item.path}
sx={{
- color: scrolled
- ? (isActiveRoute(item.path) ? 'secondary.main' : 'text.primary')
- : (isActiveRoute(item.path) ? 'white' : 'white'),
+ color: isLightHeader
+ ? (isActiveRoute(item.path) ? 'secondary.main' : lightHeaderText)
+ : 'white',
fontWeight: isActiveRoute(item.path) ? 600 : 400,
borderBottom: isActiveRoute(item.path) ? 2 : 0,
borderColor: 'secondary.main',
borderRadius: 0,
- opacity: isActiveRoute(item.path) ? 1 : 0.8,
+ opacity: isActiveRoute(item.path) ? 1 : 0.85,
'&:hover': {
backgroundColor: 'transparent',
- color: scrolled ? 'secondary.main' : 'white',
+ color: isLightHeader ? 'secondary.main' : 'white',
opacity: 1,
},
}}
@@ -221,27 +233,26 @@ const Header = () => {
))}
-
+
{/* Language Selector */}
-
- {/* Book Now Button */}
+
+ {/* ✅ Pending 17: Book Now -> WhatsApp */}
@@ -249,17 +260,13 @@ const Header = () => {
)}
- {/* Mobile Menu Button */}
+ {/* Mobile */}
{isMobile && (
-
+
@@ -273,9 +280,7 @@ const Header = () => {
anchor="right"
open={mobileOpen}
onClose={handleDrawerToggle}
- ModalProps={{
- keepMounted: true,
- }}
+ ModalProps={{ keepMounted: true }}
sx={{
'& .MuiDrawer-paper': {
boxSizing: 'border-box',
@@ -307,9 +312,8 @@ const Header = () => {
))}
-
>
);
};
-export default Header;
\ No newline at end of file
+export default Header;
diff --git a/client/src/index.css b/client/src/index.css
index d276692..9f4870b 100644
--- a/client/src/index.css
+++ b/client/src/index.css
@@ -9,8 +9,8 @@ html {
}
body {
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
+ font-family: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
+ "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@@ -18,6 +18,7 @@ body {
line-height: 1.6;
}
+
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
diff --git a/client/src/locales/ar.json b/client/src/locales/ar.json
index ca2c0bc..7238bb5 100644
--- a/client/src/locales/ar.json
+++ b/client/src/locales/ar.json
@@ -17,10 +17,12 @@
"exploreRooms": "استكشف الغرف"
},
"home": {
- "welcomeTitle": "مرحباً بكم في فندق العريشة القديمة",
+ "welcomeTitle": "مرحباً بكم في فندق الدالية القديمة",
"welcomeSubtitle": "حيث تلتقي الرفاهية بالتقاليد",
"welcomeDescription": "اكتشف تجربة ضيافة استثنائية في فندق العريشة القديمة، حيث كل تفصيل مصمم ليمنحك لحظات لا تُنسى من الراحة والأناقة.",
"featuresTitle": "لماذا تختارنا",
+ "feature6Title": "قاعة اجتماعات",
+ "feature6Description": "يوفّر بيئة فريدة لرجال الأعمال لعقد اجتماعاتهم ومؤتمراتهم.",
"feature1Title": "إقامة فاخرة",
"feature1Description": "غرف وأجنحة أنيقة مع وسائل راحة متميزة",
"feature2Title": "مطاعم راقية",
@@ -97,6 +99,8 @@
"message": "الرسالة",
"sendMessage": "إرسال رسالة",
"messageSent": "تم إرسال الرسالة بنجاح!",
+ "whatsappOpened": "تم فتح واتساب. اضغط إرسال داخل واتساب لإرسال الرسالة.",
+ "requiredFields": "رجاءً املأ الحقول المطلوبة (الاسم، البريد، الرسالة).",
"directions": "احصل على الاتجاهات",
"whatsapp": "واتساب"
},
diff --git a/client/src/locales/en.json b/client/src/locales/en.json
index 3d66c7c..7542c31 100644
--- a/client/src/locales/en.json
+++ b/client/src/locales/en.json
@@ -32,6 +32,8 @@
"roomsTitle": "Our Rooms & Suites",
"roomsSubtitle": "Comfort and elegance in every detail",
"viewAllRooms": "View All Rooms",
+ "feature6Title": "Meeting Room",
+ "feature6Description": "A unique setting for business meetings and conferences.",
"offersTitle": "Special Offers",
"offersSubtitle": "Exclusive deals for your perfect stay"
},
diff --git a/client/src/locales/fr.json b/client/src/locales/fr.json
index 38d9b0a..a97cec8 100644
--- a/client/src/locales/fr.json
+++ b/client/src/locales/fr.json
@@ -27,6 +27,8 @@
"feature2Description": "Cuisine exquise et expériences culinaires de classe mondiale",
"feature4Title": "Emplacement privilégié",
"feature5Title": "Belles terrasses",
+ "feature6Title": "Salle de réunion",
+ "feature6Description": "Un cadre unique pour les réunions d’affaires et les conférences.",
"feature5Description": "Détendez-vous sur nos magnifiques terrasses avec des vues imprenables sur la vieille Damas",
"feature4Description": "Parfaitement situé pour les affaires et les loisirs",
"roomsTitle": "Nos chambres et suites",
@@ -95,8 +97,11 @@
"hours": "Heures",
"name": "Nom complet",
"message": "Message",
+ "subject": "Sujet",
"sendMessage": "Envoyer le message",
"messageSent": "Message envoyé avec succès !",
+ "whatsappOpened": "WhatsApp est ouvert. Appuyez sur Envoyer dans WhatsApp pour envoyer votre message.",
+ "requiredFields": "Veuillez remplir les champs obligatoires (nom, e-mail, message).",
"directions": "Obtenir l'itinéraire",
"whatsapp": "WhatsApp"
},
diff --git a/client/src/pages/About.js b/client/src/pages/About.js
index 3f00d9a..28c688e 100644
--- a/client/src/pages/About.js
+++ b/client/src/pages/About.js
@@ -332,102 +332,104 @@ const About = () => {
+ {false && (
+
+
+
+ Our Journey
+
- {/* Timeline Section */}
-
-
-
+ {/* Timeline line */}
+
+
+ {milestones.map((milestone, index) => (
+
- Our Journey
-
-
-
- {/* Timeline line */}
-
- {milestones.map((milestone, index) => (
-
-
+
+
-
-
-
- {milestone.year}
-
-
- {milestone.title}
-
-
- {milestone.description}
-
-
-
-
- {/* Timeline dot */}
-
-
-
-
-
- ))}
-
-
-
+
+ {milestone.year}
+
+
+ {milestone.title}
+
+
+ {milestone.description}
+
+
+
+
+ {/* Timeline dot */}
+
+
+
+
+
+ ))}
+
+
+
+)}
>
);
diff --git a/client/src/pages/Contact.js b/client/src/pages/Contact.js
index 7d02c67..eb3c025 100644
--- a/client/src/pages/Contact.js
+++ b/client/src/pages/Contact.js
@@ -5,18 +5,15 @@ import {
Typography,
Grid,
Card,
- CardContent,
TextField,
Button,
IconButton,
Alert,
- useTheme,
} from '@mui/material';
import {
Phone,
Email,
LocationOn,
- AccessTime,
WhatsApp,
Facebook,
Instagram,
@@ -26,132 +23,153 @@ import {
import { useTranslation } from 'react-i18next';
import { motion } from 'framer-motion';
import { Helmet } from 'react-helmet-async';
-import { useQuery, useMutation } from 'react-query';
+import { useQuery } from 'react-query';
import axios from 'axios';
+const HOTEL_WHATSAPP = '963986105010';
+
const Contact = () => {
- const { t } = useTranslation();
- const theme = useTheme();
-
+ const { t, i18n } = useTranslation();
+
+ const lang = (i18n.resolvedLanguage || i18n.language || 'en').toLowerCase();
+ const isAr = lang.startsWith('ar');
+ const isFr = lang.startsWith('fr');
+
+ const tf = (key, en, ar, fr) => t(key, isAr ? ar : isFr ? fr : en);
+
const [formData, setFormData] = useState({
name: '',
email: '',
phone: '',
subject: '',
- message: ''
+ message: '',
});
const [submitStatus, setSubmitStatus] = useState(null);
- // Fetch contact information
const { data: contactInfo } = useQuery(
'contactInfo',
- () => axios.get('/api/contact/info').then(res => res.data.data),
+ () => axios.get('/api/contact/info').then((res) => res.data.data),
{
- staleTime: 5 * 60 * 1000, // 5 minutes
- }
- );
-
- // Submit contact form
- const submitContactForm = useMutation(
- (formData) => axios.post('/api/contact', formData),
- {
- onSuccess: () => {
- setSubmitStatus({ type: 'success', message: t('contact.messageSent') });
- setFormData({ name: '', email: '', phone: '', subject: '', message: '' });
- },
- onError: (error) => {
- setSubmitStatus({
- type: 'error',
- message: error.response?.data?.message || 'Failed to send message'
- });
- }
+ staleTime: 5 * 60 * 1000,
+ retry: 0,
}
);
const handleInputChange = (e) => {
- setFormData({
- ...formData,
- [e.target.name]: e.target.value
- });
+ setFormData((prev) => ({
+ ...prev,
+ [e.target.name]: e.target.value,
+ }));
+ };
+
+ const openWhatsApp = () => {
+ const lines = [
+ tf(
+ 'contact.whatsappNewMessageHeader',
+ 'New message from website:',
+ 'رسالة جديدة من موقع الفندق:',
+ 'Nouveau message du site web :'
+ ),
+ `${tf('contact.whatsappLabelName', 'Name', 'الاسم', 'Nom')}: ${formData.name}`,
+ `${tf('contact.whatsappLabelEmail', 'Email', 'البريد الإلكتروني', 'E-mail')}: ${formData.email}`,
+ `${tf('contact.whatsappLabelPhone', 'Phone', 'الهاتف', 'Téléphone')}: ${formData.phone || '-'}`,
+ `${tf('contact.whatsappLabelSubject', 'Subject', 'الموضوع', 'Sujet')}: ${formData.subject || '-'}`,
+ `${tf('contact.whatsappLabelMessage', 'Message', 'الرسالة', 'Message')}: ${formData.message}`,
+ ];
+
+ const text = encodeURIComponent(lines.join('\n'));
+ const url = `https://wa.me/${HOTEL_WHATSAPP}?text=${text}`;
+ window.open(url, '_blank', 'noopener,noreferrer');
};
const handleSubmit = (e) => {
e.preventDefault();
- if (formData.name && formData.email && formData.message) {
- submitContactForm.mutate(formData);
+
+ if (!formData.name || !formData.email || !formData.message) {
+ setSubmitStatus({
+ type: 'error',
+ message: tf(
+ 'contact.requiredFields',
+ 'Please fill the required fields (name, email, message).',
+ 'يرجى تعبئة الحقول المطلوبة (الاسم، البريد الإلكتروني، الرسالة).',
+ 'Veuillez remplir les champs obligatoires (nom, e-mail, message).'
+ ),
+ });
+ return;
}
+
+ openWhatsApp();
+
+ setSubmitStatus({
+ type: 'success',
+ message: tf(
+ 'contact.whatsappOpened',
+ 'WhatsApp opened. Press Send inside WhatsApp to deliver your message.',
+ 'تم فتح واتساب. اضغط "إرسال" داخل واتساب لإرسال رسالتك.',
+ 'WhatsApp s’est ouvert. Appuyez sur Envoyer داخل WhatsApp pour إرسال رسالتك.'
+ ),
+ });
+
+ setFormData({ name: '', email: '', phone: '', subject: '', message: '' });
};
const contactCards = [
{
- title: 'Phone',
+ title: tf('contact.cardPhoneTitle', 'Phone', 'الهاتف', 'Téléphone'),
icon: ,
primary: '0112241609',
- secondary: '24/7 Available',
- action: 'tel:0112241609'
+ secondary: tf('contact.cardPhoneSecondary', '24/7 Available', 'متاح 24/7', 'Disponible 24/7'),
+ action: 'tel:0112241609',
},
{
- title: 'Email',
+ title: tf('contact.cardEmailTitle', 'Email', 'البريد الإلكتروني', 'E-mail'),
icon: ,
primary: 'reservations@oldvinehotel.com',
- secondary: 'Response within 24 hours',
- action: 'mailto:reservations@oldvinehotel.com'
+ secondary: tf(
+ 'contact.cardEmailSecondary',
+ 'Response within 24 hours',
+ 'الرد خلال 24 ساعة',
+ 'Réponse sous 24 heures'
+ ),
+ action: 'mailto:reservations@oldvinehotel.com',
},
{
- title: 'WhatsApp',
+ title: tf('contact.cardWhatsAppTitle', 'WhatsApp', 'واتساب', 'WhatsApp'),
icon: ,
primary: '+963986105010',
- secondary: 'Quick responses',
- action: 'https://wa.me/963986105010'
+ secondary: tf('contact.cardWhatsAppSecondary', 'Quick responses', 'رد سريع', 'Réponses rapides'),
+ action: `https://wa.me/${HOTEL_WHATSAPP}`,
},
{
- title: 'Address',
+ title: tf('contact.cardAddressTitle', 'Address', 'العنوان', 'Adresse'),
icon: ,
- primary: contactInfo?.hotel?.address?.formatted || 'Old Damascus City',
+ primary: contactInfo?.hotel?.address?.formatted || tf('contact.addressFallback', 'Old Vine Hotel, Damascus', 'فندق أولد فاين - دمشق', 'Old Vine Hotel, Damas'),
secondary: t('contact.directions'),
- action: 'https://maps.google.com/?q=' + encodeURIComponent(contactInfo?.hotel?.address?.formatted || 'Old Damascus City')
- }
- ];
-
- const departments = [
- {
- name: 'Reservations',
- phone: contactInfo?.departments?.reservations?.phone || '+1 (555) 123-4567',
- email: contactInfo?.departments?.reservations?.email || 'reservations@oldvinehotel.com',
- hours: contactInfo?.departments?.reservations?.hours || '24/7'
+ action: 'https://www.google.com/maps/search/?api=1&query=Old%20Vine%20Hotel%20Damascus',
},
- {
- name: 'Concierge',
- phone: contactInfo?.departments?.concierge?.phone || '+1 (555) 123-4568',
- email: contactInfo?.departments?.concierge?.email || 'concierge@oldvinehotel.com',
- hours: contactInfo?.departments?.concierge?.hours || '6:00 AM - 12:00 AM'
- },
- {
- name: 'Restaurant',
- phone: contactInfo?.departments?.restaurant?.phone || '+1 (555) 123-4569',
- email: contactInfo?.departments?.restaurant?.email || 'restaurant@oldvinehotel.com',
- hours: contactInfo?.departments?.restaurant?.hours || '6:30 AM - 11:00 PM'
- },
- {
- name: 'Spa & Wellness',
- phone: contactInfo?.departments?.spa?.phone || '+1 (555) 123-4570',
- email: contactInfo?.departments?.spa?.email || 'spa@oldvinehotel.com',
- hours: contactInfo?.departments?.spa?.hours || '8:00 AM - 9:00 PM'
- }
];
return (
<>
- Contact Us - The Old Vine Hotel
-
+ {tf('contact.pageTitle', 'Contact Us - The Old Vine Hotel', 'تواصل معنا - فندق أولد فاين', 'Contact - The Old Vine Hotel')}
+
{/* Hero Section */}
{
component="h1"
sx={{
mb: 3,
- fontFamily: 'Playfair Display',
fontSize: { xs: '2.5rem', md: '3.5rem' },
}}
>
@@ -223,17 +240,10 @@ const Contact = () => {
},
}}
>
-
+
{card.icon}
-
+
{card.title}
@@ -248,9 +258,8 @@ const Contact = () => {
))}
- {/* Contact Form and Departments */}
+ {/* Contact Form */}
- {/* Contact Form */}
{
viewport={{ once: true }}
>
-
- Send us a Message
+
+ {tf('contact.sendUsMessageTitle', 'Send us a Message', 'أرسل لنا رسالة', 'Envoyez-nous un message')}
-
+
{submitStatus && (
- setSubmitStatus(null)}
>
@@ -315,7 +317,7 @@ const Contact = () => {
{
onChange={handleInputChange}
/>
+
@@ -352,7 +354,7 @@ const Contact = () => {
- {/* Social Media Section */}
+ {/* Social Media */}
{
transition={{ duration: 0.8 }}
viewport={{ once: true }}
>
- {/* Social Media */}
-
- Follow Us
+
+ {tf('contact.followUs', 'Follow Us', 'تابعنا', 'Suivez-nous')}
-
+
@@ -392,11 +382,7 @@ const Contact = () => {
href={contactInfo?.socialMedia?.instagram || '#'}
target="_blank"
rel="noopener noreferrer"
- sx={{
- backgroundColor: '#E4405F',
- color: 'white',
- '&:hover': { backgroundColor: '#D62D4A' },
- }}
+ sx={{ backgroundColor: '#E4405F', color: 'white' }}
>
@@ -405,24 +391,16 @@ const Contact = () => {
href={contactInfo?.socialMedia?.twitter || '#'}
target="_blank"
rel="noopener noreferrer"
- sx={{
- backgroundColor: '#1DA1F2',
- color: 'white',
- '&:hover': { backgroundColor: '#1A91DA' },
- }}
+ sx={{ backgroundColor: '#1DA1F2', color: 'white' }}
>
@@ -436,18 +414,18 @@ const Contact = () => {
{/* Map Section */}
>
);
};
-export default Contact;
\ No newline at end of file
+export default Contact;
diff --git a/client/src/pages/Home.js b/client/src/pages/Home.js
index 34b7988..9cf94e1 100644
--- a/client/src/pages/Home.js
+++ b/client/src/pages/Home.js
@@ -9,20 +9,14 @@ import {
CardContent,
CardMedia,
Chip,
- useTheme,
CircularProgress,
} from '@mui/material';
import {
Hotel,
Restaurant,
- FitnessCenter,
LocationOn,
- Star,
- CheckCircle,
- Spa,
- Pool,
- BusinessCenter,
Deck,
+ BusinessCenter,
} from '@mui/icons-material';
import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
@@ -32,22 +26,19 @@ import staticData from '../utils/staticData';
const Home = () => {
const { t, i18n } = useTranslation();
- const theme = useTheme();
const [content, setContent] = useState(null);
const [roomCategories, setRoomCategories] = useState([]);
const [loading, setLoading] = useState(true);
const currentLanguage = i18n.language;
- // Fetch homepage content and room categories from static data
useEffect(() => {
const fetchContent = async () => {
try {
const [homeContent, categories] = await Promise.all([
staticData.getHomeContent(),
- staticData.getRoomCategories()
+ staticData.getRoomCategories(),
]);
setContent(homeContent);
- // Get first 3 categories
setRoomCategories(categories.slice(0, 3));
} catch (error) {
console.error('Error loading homepage content:', error);
@@ -80,29 +71,41 @@ const Home = () => {
title: t('home.feature5Title'),
description: t('home.feature5Description'),
},
+ {
+ icon: ,
+ title: t('home.feature6Title', 'Meeting Room'),
+ description: t(
+ 'home.feature6Description',
+ 'A unique business-friendly setting for meetings and conferences.'
+ ),
+ },
];
- // Map room categories from API to display format
+ const heroImage = content?.hero?.backgroundImage || '/images/hero.jpg';
+
+ const welcomeSection = content?.sections?.find((s) => s.sectionId === 'welcome') || {};
+ const useTranslations = currentLanguage !== 'en';
+
+ const welcomeTitle = useTranslations
+ ? t('home.welcomeTitle')
+ : (welcomeSection.title || t('home.welcomeTitle'));
+
+ const welcomeSubtitle = useTranslations
+ ? t('home.welcomeSubtitle')
+ : (welcomeSection.subtitle || t('home.welcomeSubtitle'));
+
+ const welcomeContent = useTranslations
+ ? t('home.welcomeDescription')
+ : (welcomeSection.content || t('home.welcomeDescription'));
+
const roomTypes = roomCategories.map((category) => ({
id: category._id || category.slug,
name: category.name,
image: category.primaryImage || '/images/room-default.jpg',
- price: category.priceRange?.min || 0,
- features: category.features?.slice(0, 4) || [], // Show first 4 features
+ features: category.features?.slice(0, 4) || [],
slug: category.slug,
}));
- // Special offers - using translations
- const specialOffers = [
- {
- title: t('home.offersTitle'),
- description: t('home.offersSubtitle'),
- discount: '25% OFF',
- validUntil: '2025-12-31',
- },
- ];
-
- // Show loading state
if (loading) {
return (
@@ -111,98 +114,59 @@ const Home = () => {
);
}
- // Use translations for non-English languages, static data for English
- const useTranslations = currentLanguage !== 'en';
-
- // Fallback content - prioritize translations for non-English
- const heroTitle = useTranslations ? t('hero.hotelName') : (content?.hero?.title || t('hero.hotelName'));
- const heroSubtitle = useTranslations ? t('hero.subtitle') : (content?.hero?.subtitle || t('hero.subtitle'));
- const heroDescription = useTranslations ? '' : (content?.hero?.description || '');
- const heroImage = content?.hero?.backgroundImage || '/images/hero.jpg';
- const heroCTAText = useTranslations ? t('hero.exploreRooms') : (content?.hero?.ctaText || t('hero.exploreRooms'));
- const heroCTALink = content?.hero?.ctaLink || '/rooms';
-
- // Get welcome section from content
- const welcomeSection = content?.sections?.find(s => s.sectionId === 'welcome') || {};
- const welcomeTitle = useTranslations ? t('home.welcomeTitle') : (welcomeSection.title || t('home.welcomeTitle'));
- const welcomeSubtitle = useTranslations ? t('home.welcomeSubtitle') : (welcomeSection.subtitle || t('home.welcomeSubtitle'));
- const welcomeContent = useTranslations ? t('home.welcomeDescription') : (welcomeSection.content || t('home.welcomeDescription'));
+ const LOGO_BOTTOM = { xs: 40, sm: 55, md: 70 };
return (
<>
{content?.seo?.title || 'The Old Vine Hotel - Luxury Accommodation & Premium Hospitality'}
-
-
+
+
{/* Hero Section - Logo and Image Only */}
+
-
+
- {/* Logo Only */}
-
-
+
-
- {/* Scroll Indicator */}
-
-
- Scroll Down
-
-
-
{/* Welcome Section */}
@@ -214,31 +178,14 @@ const Home = () => {
viewport={{ once: true }}
>
-
+
{welcomeTitle}
-
-
+
+
{welcomeSubtitle}
-
+
{
mx: 'auto',
lineHeight: 1.8,
fontSize: '1.1rem',
- whiteSpace: 'pre-line', // Preserve line breaks
+ whiteSpace: 'pre-line',
}}
>
{welcomeContent}
@@ -264,68 +211,74 @@ const Home = () => {
transition={{ duration: 0.8 }}
viewport={{ once: true }}
>
-
+
{t('home.featuresTitle')}
-
-
+
+
{features.map((feature, index) => (
-
-
+
-
+ {feature.icon}
+
+
+
-
- {feature.icon}
-
-
-
- {feature.title}
-
-
-
- {feature.description}
-
-
-
-
+ {feature.title}
+
+
+
+ {feature.description}
+
+
+
))}
-
+
@@ -339,30 +292,15 @@ const Home = () => {
viewport={{ once: true }}
>
-
+
{t('home.roomsTitle')}
-
-
+
+
{t('home.roomsSubtitle')}
-
+
{roomTypes.map((room, index) => (
@@ -380,37 +318,26 @@ const Home = () => {
alt={room.name}
sx={{
transition: 'transform 0.3s ease',
- '&:hover': {
- transform: 'scale(1.05)',
- },
+ '&:hover': { transform: 'scale(1.05)' },
}}
/>
-
+
-
+
{room.name}
-
+
{room.features.map((feature, idx) => (
))}
-
+
))}
-
+
-
>
);
};
-export default Home;
\ No newline at end of file
+export default Home;