diff --git a/public/locales/en/common.json b/public/locales/en/common.json index bd09220..aa9507b 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -7,7 +7,9 @@ "customTour": "Custom Tour", "searchPlaceholder": "Where to?", "searchDescription": "Anywhere • Any week • Add guests", - "beginAdventure": "Begin your spiritual adventure", + "beginAdventure": "Begin your", + "beginAdventure1": "spiritual", + "beginAdventure2": "adventure", "planPilgrimage": "Plan your pilgrimage with ease. Find the best accommodations, transportation, and guided experiences to Shia shrines around the world", "startJourney": "Start your journey", "listOfTours": "List of Tours", diff --git a/src/app/[locale]/(client-components)/(Header)/LangDropdown.tsx b/src/app/[locale]/(client-components)/(Header)/LangDropdown.tsx index c721ca4..7dabb46 100644 --- a/src/app/[locale]/(client-components)/(Header)/LangDropdown.tsx +++ b/src/app/[locale]/(client-components)/(Header)/LangDropdown.tsx @@ -2,8 +2,9 @@ import React, { Fragment, useState, useEffect } from "react"; import { Popover, Tab, Transition } from "@headlessui/react"; import { useRouter, usePathname } from "next/navigation"; import { ChevronDownIcon } from "@heroicons/react/24/outline"; -import { MdOutlineLanguage } from "react-icons/md"; +import MdOutlineLanguage from "@/images/material-symbols-light_language.svg"; import Cookies from "js-cookie"; // Import js-cookie +import Image from "next/image"; // Language options const languageOptions = [ @@ -11,25 +12,25 @@ const languageOptions = [ id: "en", name: "English", description: "United States", - icon: , + icon: MdOutlineLanguage, }, { id: "vi", name: "Vietnamese", description: "Vietnam", - icon: , + icon: MdOutlineLanguage, }, { id: "fr", name: "French", description: "France", - icon: , + icon: MdOutlineLanguage, }, { id: "ar", name: "Arabic", description: "Arabic", - icon: , + icon: MdOutlineLanguage, }, ]; @@ -90,7 +91,7 @@ const LangDropdown: React.FC = ({ group self-center h-10 sm:h-12 px-3 py-1.5 inline-flex items-center text-sm text-gray-800 dark:text-neutral-200 font-medium hover:text-opacity-100 focus:outline-none `} > - + language button = ({ className = "" }) => {
- - - - - + +
diff --git a/src/app/[locale]/(client-components)/(Header)/MyTripButton.tsx b/src/app/[locale]/(client-components)/(Header)/MyTripButton.tsx new file mode 100644 index 0000000..80a1912 --- /dev/null +++ b/src/app/[locale]/(client-components)/(Header)/MyTripButton.tsx @@ -0,0 +1,25 @@ +import { useUserContext } from "@/components/contexts/userContext"; +import Link from "next/link"; +import { MdOutlineCardTravel } from "react-icons/md"; + +function MyTripButton() { + + const {user} = useUserContext() + + + if (!Object.keys(user).length) { + return null + } + return ( +
+ + + +
+ ); +} + +export default MyTripButton; diff --git a/src/app/[locale]/(client-components)/(Header)/SearchDropdown.tsx b/src/app/[locale]/(client-components)/(Header)/SearchDropdown.tsx index 8341989..e8b05e8 100644 --- a/src/app/[locale]/(client-components)/(Header)/SearchDropdown.tsx +++ b/src/app/[locale]/(client-components)/(Header)/SearchDropdown.tsx @@ -4,6 +4,8 @@ import React, { FC, Fragment, useEffect, useState } from "react"; import { useToursContext } from "@/components/contexts/tourDetails"; import SearchCard from "@/components/SearchCard"; import axiosInstance from "@/components/api/axios"; +import SearchImage from "@/images/mynaui_search.svg" +import Image from "next/image"; interface Props { className?: string; @@ -76,8 +78,8 @@ const SearchDropdown: FC = ({ className = "" }) => { return ( <> - - + + {SearchImage} { return ( -
- +
+ dowloadAppPng -
+
-
+ {/*
-
+
*/} -
-

+
+

Mobile Apps

- + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed dapibus porttitor nisl, sit amet finibus libero. @@ -47,14 +47,14 @@ const SectionDowloadApp = () => {
- + /> */}
- + {/* */}

diff --git a/src/app/[locale]/(server-components)/SectionHero.tsx b/src/app/[locale]/(server-components)/SectionHero.tsx index e9724dc..a57e3bb 100644 --- a/src/app/[locale]/(server-components)/SectionHero.tsx +++ b/src/app/[locale]/(server-components)/SectionHero.tsx @@ -1,7 +1,8 @@ -"use client" +"use client"; import React, { FC } from "react"; import imagePng from "@/images/hero-right.png"; +import vectorPng from "@/images/Vector.png"; import HeroSearchForm from "../(client-components)/(HeroSearchForm)/HeroSearchForm"; import Image from "next/image"; import ButtonPrimary from "@/shared/ButtonPrimary"; @@ -15,28 +16,43 @@ const SectionHero: FC = ({ className = "" }) => { const { t } = useTranslation("common"); // Initialize useTranslation return ( -
-
-
-

- {t("beginAdventure")} {/* Translate the heading */} -

- - {t("planPilgrimage")} {/* Translate the description */} - - - {t("startJourney")} {/* Translate the button text */} - -
-
- hero +
+ hero + +
+
+
+

+ {t("beginAdventure")} +

+

+ {t("beginAdventure1")} +

+

+ {t("beginAdventure2")} +

+ + {t("planPilgrimage")} + + + {t("startJourney")} + +
+
+ hero +
-
-
- +
+ +
); diff --git a/src/app/[locale]/custom-trip/page.tsx b/src/app/[locale]/custom-trip/page.tsx index b868afb..3cda235 100644 --- a/src/app/[locale]/custom-trip/page.tsx +++ b/src/app/[locale]/custom-trip/page.tsx @@ -22,6 +22,12 @@ interface Country { city: City[]; } +interface Passengers { + adults: number; + children: number; + infants: number; +} + interface CommonLayoutProps {} const CommonLayout: FC = () => { @@ -32,10 +38,11 @@ const CommonLayout: FC = () => { const [countries, setCountries] = useState([]); const [startCity, setStartCity] = useState(""); const [startDate, setStartDate] = useState(""); - const [guestAdultsInputValue, setGuestAdultsInputValue] = useState(1); - const [guestChildrenInputValue, setGuestChildrenInputValue] = useState(0); - const [guestInfantsInputValue, setGuestInfantsInputValue] = useState(0); - const [passengers, setPassengers] = useState(1); + const [passengers, setPassengers] = useState({ + adults: 1, + children: 0, + infants: 0, + }); const [transport, setTransport] = useState([]); const [hotel, setHotel] = useState([]); const [estimatedCost, setEstimatedCost] = useState(0); @@ -77,7 +84,7 @@ const CommonLayout: FC = () => { .catch((error) => console.error("Error fetching countries:", error)); }, []); console.log(destinations); - + useEffect(() => { const lastDestination = destinations[destinations.length - 1]; if (lastDestination?.endCity) { @@ -87,7 +94,9 @@ const CommonLayout: FC = () => { .split("/")[2] .trim()}&to_city=${lastDestination.endCity.split("/")[2].trim()}` ) - .then((response) => {setTransport(response.data) ;console.log(response); + .then((response) => { + setTransport(response.data); + console.log(response); }) .catch((error) => console.error("Error fetching transport options:", error) @@ -97,7 +106,9 @@ const CommonLayout: FC = () => { .get( `/api/trip/hotels/${lastDestination.endCity.split("/")[2].trim()}/` ) - .then((response) => {setHotel(response.data.results) ; console.log(response); + .then((response) => { + setHotel(response.data.results); + console.log(response); }) .catch((error) => console.error("Error fetching hotels:", error)); } @@ -113,20 +124,8 @@ const CommonLayout: FC = () => { const calculateTransportCost = ( transport: any, - adults: number, - children: number, - infants: number + { adults, children, infants }: Passengers ) => { - console.log( - transport, - adults, - children, - infants, - transport.price * adults + - transport.price_child * children + - transport.price_infant * infants - ); - return ( transport.price * adults + transport.price_child * children + @@ -137,21 +136,8 @@ const CommonLayout: FC = () => { const calculateHotelCost = ( hotel: any, days: number, - adults: number, - children: number, - infants: number + { adults, children, infants }: Passengers ) => { - console.log( - hotel, - adults, - children, - infants, - (hotel.price_per_day * adults + - hotel.price_per_day_child * children + - hotel.price_per_day_infant * infants) * days - - ); - return ( (hotel.price_per_day * adults + hotel.price_per_day_child * children + @@ -161,9 +147,8 @@ const CommonLayout: FC = () => { const updateEstimatedCost = () => { const totalCost = destinations.reduce((acc, destination) => { - const transportCost = destination.transportCost * passengers; - const hotelCost = - destination.hotelCost * destination.duration * passengers; + const transportCost = destination.transportCost; + const hotelCost = destination.hotelCost * destination.duration; return acc + transportCost + hotelCost; }, 0); setEstimatedCost(totalCost); @@ -173,7 +158,7 @@ const CommonLayout: FC = () => { const isValid = startCity !== "" && startDate !== "" && - passengers > 0 && + passengers.adults > 0 && destinations.every( (destination) => destination.endCity !== "" && @@ -191,7 +176,7 @@ const CommonLayout: FC = () => { isFormValid && startCity !== "" && startDate !== "" && - passengers > 0; + passengers.adults > 0; setIsContinueValid(isValid); }, [destinations, startCity, startDate, passengers, isFormValid]); @@ -228,9 +213,7 @@ const CommonLayout: FC = () => { ); updatedDestinations[index].transportCost = calculateTransportCost( selected, - guestAdultsInputValue, - guestChildrenInputValue, - guestInfantsInputValue + passengers ); } @@ -239,9 +222,7 @@ const CommonLayout: FC = () => { updatedDestinations[index].hotelCost = calculateHotelCost( selected, updatedDestinations[index].duration, - guestAdultsInputValue, - guestChildrenInputValue, - guestInfantsInputValue + passengers ); } @@ -263,22 +244,13 @@ const CommonLayout: FC = () => { validateForm(); }; - const handleChangeData = (value: number, type: string) => { - if (type === "guestAdults") { - setGuestAdultsInputValue(value); - } else if (type === "guestChildren") { - setGuestChildrenInputValue(value); - } else if (type === "guestInfants") { - setGuestInfantsInputValue(value); - } + const handleChangeData = (value: number, type: keyof Passengers) => { + setPassengers((prev) => ({ + ...prev, + [type]: value, + })); }; - useEffect(() => { - setPassengers( - guestAdultsInputValue + guestChildrenInputValue + guestInfantsInputValue - ); - }, [guestAdultsInputValue, guestChildrenInputValue, guestInfantsInputValue]); - const submitTour = async () => { const formData = { destinations: destinations.map((destination) => ({ @@ -293,7 +265,7 @@ const CommonLayout: FC = () => { city: `${startCity.split("/")[0].trim()}-${startCity .split("/")[1] .trim()} `, - number_passenger: `${passengers}`, + number_passenger: passengers , start_date: startDate.replace(/-/g, "/"), }, ...destinations.reduce<{ [key: number]: any }>( @@ -330,7 +302,10 @@ const CommonLayout: FC = () => { Authorization: `token ${user.token}`, "Content-Type": "application/json", }, - }); + }).then((response) => { + console.log(response); + + }) toast.success(t("successMessage")); router.push("/custom-history"); } catch (error) { @@ -343,21 +318,21 @@ const CommonLayout: FC = () => {
-

{t("customTrip")}

{/* Translate custom trip title */} +

{t("customTrip")}

-

{t("guide")}

{/* Translate guide */} -

{t("guideDescription")}

{/* Translate guide description */} +

{t("guide")}

+

{t("guideDescription")}

-

{t("beginYourTrip")}

{/* Translate begin your trip */} +

{t("beginYourTrip")}

- {/* Translate start date label */} + setStartDate(e.target.value)} /> - {/* Translate number of passengers */} +
handleChangeData(value, "guestAdults")} + defaultValue={passengers.adults} + onChange={(value) => handleChangeData(value, "adults")} max={20} - label={t("adults")} // Translate adults label - desc={t("adultsDesc")} // Translate age description + label={t("adults")} + desc={t("adultsDesc")} /> - handleChangeData(value, "guestChildren") - } + defaultValue={passengers.children} + onChange={(value) => handleChangeData(value, "children")} max={20} - label={t("children")} // Translate children label - desc={t("childrenDesc")} // Translate age description + label={t("children")} + desc={t("childrenDesc")} /> - handleChangeData(value, "guestInfants") - } + defaultValue={passengers.infants} + onChange={(value) => handleChangeData(value, "infants")} max={20} - label={t("infants")} // Translate infants label - desc={t("infantsDesc")} // Translate age description + label={t("infants")} + desc={t("infantsDesc")} />
@@ -415,7 +386,7 @@ const CommonLayout: FC = () => { {destinations.map((destination, index) => (

- {stringifyNumber(index + 1)} {t("destination")} {/* Translate destination */} + {stringifyNumber(index + 1)} {t("destination")}

- {/* Translate transportation */} + - {/* Translate hotel */} +
- {/* Translate duration */} + = () => { min="1" /> - {/* Translate finish date */} + = () => { type="button" disabled={!isFormValid} > - {t("addDestination")} {/* Translate add destination */} + {t("addDestination")} - {t("continue")} {/* Translate continue */} + {t("continue")}
diff --git a/src/app/[locale]/page.tsx b/src/app/[locale]/page.tsx index 73ff1cf..cfb9b4a 100644 --- a/src/app/[locale]/page.tsx +++ b/src/app/[locale]/page.tsx @@ -40,7 +40,7 @@ function PageHome() { - {/* */} + {/* */} diff --git a/src/components/SectionCustomTour.tsx b/src/components/SectionCustomTour.tsx index 18ec6d4..abd1318 100644 --- a/src/components/SectionCustomTour.tsx +++ b/src/components/SectionCustomTour.tsx @@ -1,68 +1,76 @@ -import React, { FC } from "react"; -import rightImgPng from "@/images/our-features.png"; -import Image, { StaticImageData } from "next/image"; -import Badge from "@/shared/Badge"; +import BackgroundSection from "@/components/BackgroundSection"; +import React from "react"; +import BackgroundImage from "@/images/Frame 412.png"; +import Image from "next/image"; import ButtonPrimary from "@/shared/ButtonPrimary"; -export interface SectionCustomTourProps { - className?: string; - rightImg?: StaticImageData; - type?: "type1" | "type2"; -} - -const SectionCustomTour: FC = ({ - className = "lg:py-14", - rightImg = rightImgPng, - type = "type1", -}) => { +const SectionDownloadApp = () => { return ( -
-
- -
-
- -

Custoum Tour

- -
    -
  • - - Cost-effective advertising - - - With a free listing, you can advertise your rental with no upfront - costs - -
  • -
  • + + {/* Background Image */} + Custom Tour Background - - Millions of people are searching for unique places to stay around - the world - -
  • -
  • - - A Holiday Lettings listing gives you a secure and easy way to take - bookings and payments online - -
  • -
  • - Custoum Tour -
  • -
+ {/* Content Wrapper */} +
+

+ Create +

+

+ Custom Tour +

+

+ Create your personalized tour and design the +

+

+ perfect travel experience tailored to your preferences. +

+ Custom Tour
-
+ ); }; -export default SectionCustomTour; +export default SectionDownloadApp; +// import BackgroundSection from "@/components/BackgroundSection"; +// import React from "react"; +// import BackgroundImage from "@/images/Frame 412.png"; +// import Image from "next/image"; +// import ButtonPrimary from "@/shared/ButtonPrimary"; + +// const SectionDownloadApp = () => { +// return ( +// +// {/* Background Image */} +// Custom Tour Background + +// {/* Content Wrapper */} +//
+//

+// Create +//

+//

+// Custom Tour +//

+//

+// Create your personalized tour and design the +//

+//

+// perfect travel experience tailored to your preferences. +//

+// Custom Tour +//
+//
+// ); +// }; + +// export default SectionDownloadApp; diff --git a/src/components/SectionGridFeaturePlaces.tsx b/src/components/SectionGridFeaturePlaces.tsx index 4f41183..960ed13 100644 --- a/src/components/SectionGridFeaturePlaces.tsx +++ b/src/components/SectionGridFeaturePlaces.tsx @@ -156,7 +156,7 @@ const SectionGridFeaturePlaces: FC = ({
-
+
router.push("/tours")}> Show me more diff --git a/src/components/UserMenu.tsx b/src/components/UserMenu.tsx index 277f0c7..de7b969 100644 --- a/src/components/UserMenu.tsx +++ b/src/components/UserMenu.tsx @@ -22,11 +22,11 @@ const UserMenu: FC = ({ className = "" }) => { return (
{Object.keys(user).length ? ( - + ) : ( -
+
{translation.logIn} diff --git a/src/images/Frame 412.png b/src/images/Frame 412.png new file mode 100644 index 0000000..874a7e8 Binary files /dev/null and b/src/images/Frame 412.png differ diff --git a/src/images/Free Mockup - iPhone 16 Pro Max copy 1.png b/src/images/Free Mockup - iPhone 16 Pro Max copy 1.png new file mode 100644 index 0000000..5d88517 Binary files /dev/null and b/src/images/Free Mockup - iPhone 16 Pro Max copy 1.png differ diff --git a/src/images/Vector.png b/src/images/Vector.png new file mode 100644 index 0000000..119c5bb Binary files /dev/null and b/src/images/Vector.png differ diff --git a/src/images/map.png b/src/images/map.png new file mode 100644 index 0000000..01f6c7a Binary files /dev/null and b/src/images/map.png differ diff --git a/src/images/material-symbols-light_language.png b/src/images/material-symbols-light_language.png new file mode 100644 index 0000000..af9231b Binary files /dev/null and b/src/images/material-symbols-light_language.png differ diff --git a/src/images/material-symbols-light_language.svg b/src/images/material-symbols-light_language.svg new file mode 100644 index 0000000..9d5e05d --- /dev/null +++ b/src/images/material-symbols-light_language.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/mynaui_search.svg b/src/images/mynaui_search.svg new file mode 100644 index 0000000..a1c0331 --- /dev/null +++ b/src/images/mynaui_search.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/shared/Navigation/NavigationItem.tsx b/src/shared/Navigation/NavigationItem.tsx index 56949e5..b90966d 100644 --- a/src/shared/Navigation/NavigationItem.tsx +++ b/src/shared/Navigation/NavigationItem.tsx @@ -36,7 +36,7 @@ type NavigationItemWithRouterProps = NavigationItemProps; const NavigationItem: FC = ({ menuItem }) => { const [menuCurrentHovers, setMenuCurrentHovers] = useState([]); - const {countries} = useToursContext() + const { countries } = useToursContext(); // CLOSE ALL MENU OPENING WHEN CHANGE HISTORY const locationPathName = usePathname(); @@ -56,6 +56,11 @@ const NavigationItem: FC = ({ menuItem }) => { }); }; + // Utility function to remove any language prefix (e.g., /en, /fr, /de) from the path + const removeLangPrefix = (path: string) => { + return path.replace(/^\/[a-z]{2}(\/|$)/, ""); // Matches any two-letter language code at the start + }; + // ===================== MENU MEGAMENU ===================== const renderMegaMenu = (menu: NavItemType) => { const isHover = menuCurrentHovers.includes(menu.id); @@ -163,7 +168,7 @@ const NavigationItem: FC = ({ menuItem }) => { className="sub-menu will-change-transform absolute transform z-10 w-56 top-full left-0" >
    - { countries?.map((i) => { + {countries?.map((i) => { if (i.type) { return renderDropdownMenuNavlinkHasChild(i); } else { @@ -255,10 +260,16 @@ const NavigationItem: FC = ({ menuItem }) => { // ===================== MENU MAIN MENU ===================== const renderMainItem = (item: NavItemType) => { + const currentPath = removeLangPrefix(locationPathName); // Strip language prefix from current path + const isActive = `/${currentPath}` === item.href; // Check if the cleaned path matches item.href + console.log(currentPath , item.href); + return ( {item.name} @@ -271,7 +282,6 @@ const NavigationItem: FC = ({ menuItem }) => { ); }; -console.log(menuItem.type); switch (menuItem.type) { case "megaMenu": @@ -286,6 +296,5 @@ console.log(menuItem.type); ); } }; -// Your component own properties export default NavigationItem;