Browse Source

fix (UI) : UI of hero , DownloadApp , customTour , sections and header changed changed

main
sina_sajjadi 1 week ago
parent
commit
fb55c70431
  1. 4
      public/locales/en/common.json
  2. 13
      src/app/[locale]/(client-components)/(Header)/LangDropdown.tsx
  3. 11
      src/app/[locale]/(client-components)/(Header)/MainNav1.tsx
  4. 25
      src/app/[locale]/(client-components)/(Header)/MyTripButton.tsx
  5. 6
      src/app/[locale]/(client-components)/(Header)/SearchDropdown.tsx
  6. 32
      src/app/[locale]/(home)/SectionDowloadApp.tsx
  7. 58
      src/app/[locale]/(server-components)/SectionHero.tsx
  8. 159
      src/app/[locale]/custom-trip/page.tsx
  9. 2
      src/app/[locale]/page.tsx
  10. 128
      src/components/SectionCustomTour.tsx
  11. 2
      src/components/SectionGridFeaturePlaces.tsx
  12. 4
      src/components/UserMenu.tsx
  13. BIN
      src/images/Frame 412.png
  14. BIN
      src/images/Free Mockup - iPhone 16 Pro Max copy 1.png
  15. BIN
      src/images/Vector.png
  16. BIN
      src/images/map.png
  17. BIN
      src/images/material-symbols-light_language.png
  18. 3
      src/images/material-symbols-light_language.svg
  19. 3
      src/images/mynaui_search.svg
  20. 19
      src/shared/Navigation/NavigationItem.tsx

4
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",

13
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: <MdOutlineLanguage />,
icon: MdOutlineLanguage,
},
{
id: "vi",
name: "Vietnamese",
description: "Vietnam",
icon: <MdOutlineLanguage />,
icon: MdOutlineLanguage,
},
{
id: "fr",
name: "French",
description: "France",
icon: <MdOutlineLanguage />,
icon: MdOutlineLanguage,
},
{
id: "ar",
name: "Arabic",
description: "Arabic",
icon: <MdOutlineLanguage />,
icon: MdOutlineLanguage,
},
];
@ -90,7 +91,7 @@ const LangDropdown: React.FC<LangDropdownProps> = ({
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
`}
>
<MdOutlineLanguage size={25} />
<Image alt="language button" src={MdOutlineLanguage} width={24} height={24}/>
<ChevronDownIcon
className={`${open ? "-rotate-180" : "text-opacity-70"}
ml-1 h-4 w-4 group-hover:text-opacity-80 transition ease-in-out duration-150`}

11
src/app/[locale]/(client-components)/(Header)/MainNav1.tsx

@ -9,6 +9,7 @@ import { MdOutlineCardTravel } from "react-icons/md";
import Link from "next/link";
import LangDropdown from "./LangDropdown";
import UserMenu from "@/components/UserMenu";
import MyTripButton from "./MyTripButton";
export interface MainNav1Props {
className?: string;
@ -31,14 +32,8 @@ const MainNav1: FC<MainNav1Props> = ({ className = "" }) => {
<div className="hidden md:flex flex-shrink-0 justify-end flex-1 lg:flex-none text-neutral-700 dark:text-neutral-100">
<div className="hidden xl:flex space-x-0.5 items-center">
<LangDropdown />
<Link
href="/my-trips"
className="self-center text-2xl md:text-[28px] w-12 h-12 rounded-full text-neutral-700 dark:text-neutral-300 hover:bg-neutral-100 dark:hover:bg-neutral-800 focus:outline-none flex items-center justify-center"
>
<MdOutlineCardTravel size={25} />
</Link>
<LangDropdown className="font-thin" />
<MyTripButton />
<SwitchDarkMode />
<SearchDropdown className="flex items-center" />
<div className="px-1" />

25
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 (
<div>
<Link
href="/my-trips"
className="self-center text-2xl md:text-[28px] w-12 h-12 rounded-full text-neutral-700 dark:text-neutral-300 hover:bg-neutral-100 dark:hover:bg-neutral-800 focus:outline-none flex items-center justify-center"
>
<MdOutlineCardTravel size={25} />
</Link>
</div>
);
}
export default MyTripButton;

6
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<Props> = ({ className = "" }) => {
return (
<>
<Popover.Button className="text-2xl md:text-[28px] w-12 h-12 rounded-full text-neutral-700 dark:text-neutral-300 hover:bg-neutral-100 dark:hover:bg-neutral-800 focus:outline-none flex items-center justify-center">
<i className="las la-search"></i>
<Popover.Button className="text-2xl md:text-[28px] w-10 h-10 rounded-full p-1 bg-bronze-secondary text-neutral-700 dark:text-neutral-300 hover:bg-neutral-100 dark:hover:bg-neutral-800 focus:outline-none flex items-center justify-center">
<Image alt={SearchImage} src = {SearchImage} width={24} height={24} />
</Popover.Button>
<Transition

32
src/app/[locale]/(home)/SectionDowloadApp.tsx

@ -1,40 +1,40 @@
import BackgroundSection from "@/components/BackgroundSection";
import React from "react";
import appSvg1 from "@/images/appSvg1.png";
import Map from "@/images/map.png";
import appSvg2 from "@/images/appSvg2.png";
import appRightImgTree from "@/images/appRightImgTree.png";
import dowloadAppBGPng from "@/images/dowloadAppBG.png";
import appRightImg from "@/images/appRightImg.png";
import appRightImg from "@/images/Free Mockup - iPhone 16 Pro Max copy 1.png";
import btnIosPng from "@/images/btn-ios.png";
import btnAndroidPng from "@/images/btn-android.png";
import Image from "next/image";
const SectionDowloadApp = () => {
return (
<div className="relative pb-0 pt-24 lg:py-32 xl:py-40 2xl:py-48">
<BackgroundSection className="bg-neutral-100 bg-opacity-80 dark:bg-opacity-100 ">
<div className="relative h-[455px] pb-0 pt-24 lg:py-32 xl:py-40 2xl:py-48 flex items-center">
<BackgroundSection className="bg-[#FFF8F1] dark:bg-opacity-100 ">
<Image
className="absolute inset-0 w-full h-full object-cover rounded-3xl object-right"
src={dowloadAppBGPng}
alt="dowloadAppPng"
className="object-cover object-left xl:rounded-[40px]"
src={Map}
alt="Map background"
/>
<div className="hidden lg:block absolute right-0 bottom-0 max-w-xl xl:max-w-2xl rounded-3xl overflow-hidden">
<div className="hidden lg:block absolute right-0 bottom-0 max-w-xl xl:max-w-2xl rounded-3xl">
<Image src={appRightImg} alt="" />
</div>
<div className="absolute right-0 top-0 max-w-2xl">
{/* <div className="absolute right-0 top-0 max-w-2xl">
<Image src={appRightImgTree} alt="" />
</div>
<div className="absolute left-0 bottom-10 max-w-2xl">
<Image src={appSvg1} alt="" />
</div>
</div> */}
</BackgroundSection>
<div className="relative inline-block ">
<h2 className="text-5xl md:text-6xl xl:text-7xl font-bold text-neutral-800">
<div className="relative flex flex-col ">
<h2 className="text-5xl md:text-6xl xl:text-7xl font-medium text-bronze">
Mobile Apps
</h2>
<span className="block mt-7 max-w-md text-neutral-6000">
<span className="block mt-7 max-w-2xl text-neutral-6000">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed dapibus
porttitor nisl, sit amet finibus libero.
</span>
@ -47,14 +47,14 @@ const SectionDowloadApp = () => {
</a>
</div>
<Image
{/* <Image
className="hidden lg:block absolute lg:left-full lg:top-0 xl:top-1/2 z-10 lg:max-w-sm 2xl:max-w-none"
src={appSvg2}
alt=""
/>
/> */}
<div className="block lg:hidden mt-10 max-w-2xl rounded-3xl overflow-hidden">
<Image src={appRightImg} alt="" />
{/* <Image src={appRightImg} alt="" /> */}
</div>
</div>
</div>

58
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<SectionHeroProps> = ({ className = "" }) => {
const { t } = useTranslation("common"); // Initialize useTranslation
return (
<div
className={`nc-SectionHero flex flex-col-reverse lg:flex-col relative ${className}`}
>
<div className="flex flex-col lg:flex-row lg:items-center">
<div className="flex-shrink-0 lg:w-1/2 flex flex-col items-start space-y-8 sm:space-y-10 pb-14 lg:pb-64 xl:pr-14 lg:mr-10 xl:mr-0">
<h2 className="font-medium text-4xl md:text-5xl xl:text-7xl !leading-[114%] ">
{t("beginAdventure")} {/* Translate the heading */}
</h2>
<span className="text-base md:text-lg text-neutral-500 dark:text-neutral-400">
{t("planPilgrimage")} {/* Translate the description */}
</span>
<ButtonPrimary href="/tours" sizeClass="px-5 py-4 sm:px-7">
{t("startJourney")} {/* Translate the button text */}
</ButtonPrimary>
</div>
<div className="flex-grow">
<Image className="w-full" src={imagePng} alt="hero" priority />
<div className="">
<Image
className="absolute top-10 left-[-100px]" // Move the image further left and scale it up
src={vectorPng}
alt="hero"
priority
/>
<div
className={`nc-SectionHero flex flex-col-reverse lg:flex-col relative z-10 ${className}`}
>
<div className="flex flex-col lg:flex-row">
<div className="flex-shrink-0 lg:w-1/2 flex flex-col items-start space-y-8 sm:space-y-10 pb-14 lg:pb-64 xl:pr-14 lg:mr-10 xl:mr-0">
<h2 className="font-medium text-4xl md:text-5xl xl:text-7xl !leading-[114%] ">
{t("beginAdventure")}
</h2>
<h2 className="font-bold text-bronze text-4xl md:text-5xl xl:text-7xl !leading-[114%] ">
{t("beginAdventure1")}
</h2>
<h2 className="font-medium text-4xl md:text-5xl xl:text-7xl !leading-[114%] ">
{t("beginAdventure2")}
</h2>
<span className="text-base md:text-lg text-neutral-500 dark:text-neutral-400">
{t("planPilgrimage")}
</span>
<ButtonPrimary href="/tours" sizeClass="px-5 py-4 sm:px-7">
{t("startJourney")}
</ButtonPrimary>
</div>
<div className="flex-grow">
<Image className="w-full rounded-l-[40px]" src={imagePng} alt="hero" priority />
</div>
</div>
</div>
<div className="hidden lg:block z-10 mb-12 lg:mb-0 lg:-mt-40 w-full">
<HeroSearchForm />
<div className="hidden lg:block z-10 mb-12 lg:mb-0 lg:-mt-40 w-full">
<HeroSearchForm />
</div>
</div>
</div>
);

159
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<CommonLayoutProps> = () => {
@ -32,10 +38,11 @@ const CommonLayout: FC<CommonLayoutProps> = () => {
const [countries, setCountries] = useState<Country[]>([]);
const [startCity, setStartCity] = useState<string>("");
const [startDate, setStartDate] = useState<string>("");
const [guestAdultsInputValue, setGuestAdultsInputValue] = useState(1);
const [guestChildrenInputValue, setGuestChildrenInputValue] = useState(0);
const [guestInfantsInputValue, setGuestInfantsInputValue] = useState(0);
const [passengers, setPassengers] = useState<number>(1);
const [passengers, setPassengers] = useState<Passengers>({
adults: 1,
children: 0,
infants: 0,
});
const [transport, setTransport] = useState<any[]>([]);
const [hotel, setHotel] = useState<any[]>([]);
const [estimatedCost, setEstimatedCost] = useState<number>(0);
@ -77,7 +84,7 @@ const CommonLayout: FC<CommonLayoutProps> = () => {
.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<CommonLayoutProps> = () => {
.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<CommonLayoutProps> = () => {
.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<CommonLayoutProps> = () => {
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<CommonLayoutProps> = () => {
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<CommonLayoutProps> = () => {
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<CommonLayoutProps> = () => {
const isValid =
startCity !== "" &&
startDate !== "" &&
passengers > 0 &&
passengers.adults > 0 &&
destinations.every(
(destination) =>
destination.endCity !== "" &&
@ -191,7 +176,7 @@ const CommonLayout: FC<CommonLayoutProps> = () => {
isFormValid &&
startCity !== "" &&
startDate !== "" &&
passengers > 0;
passengers.adults > 0;
setIsContinueValid(isValid);
}, [destinations, startCity, startDate, passengers, isFormValid]);
@ -228,9 +213,7 @@ const CommonLayout: FC<CommonLayoutProps> = () => {
);
updatedDestinations[index].transportCost = calculateTransportCost(
selected,
guestAdultsInputValue,
guestChildrenInputValue,
guestInfantsInputValue
passengers
);
}
@ -239,9 +222,7 @@ const CommonLayout: FC<CommonLayoutProps> = () => {
updatedDestinations[index].hotelCost = calculateHotelCost(
selected,
updatedDestinations[index].duration,
guestAdultsInputValue,
guestChildrenInputValue,
guestInfantsInputValue
passengers
);
}
@ -263,22 +244,13 @@ const CommonLayout: FC<CommonLayoutProps> = () => {
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<CommonLayoutProps> = () => {
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<CommonLayoutProps> = () => {
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<CommonLayoutProps> = () => {
<div className="space-y-11">
<form>
<div className="listingSection__wrap">
<h2 className="text-2xl font-semibold">{t("customTrip")}</h2> {/* Translate custom trip title */}
<h2 className="text-2xl font-semibold">{t("customTrip")}</h2>
<div className="w-14 border-b border-neutral-200 dark:border-neutral-700"></div>
<h3 className="text-[#BD3F3F] font-medium">{t("guide")}</h3> {/* Translate guide */}
<p>{t("guideDescription")}</p> {/* Translate guide description */}
<h3 className="text-[#BD3F3F] font-medium">{t("guide")}</h3>
<p>{t("guideDescription")}</p>
<div className="w-14 border-b border-neutral-200 dark:border-neutral-700"></div>
<div className="space-y-8">
<p className="text-bronze text-xs">{t("beginYourTrip")}</p> {/* Translate begin your trip */}
<p className="text-bronze text-xs">{t("beginYourTrip")}</p>
<FormItem label="" desc="">
<Select
value={startCity}
onChange={(e) => setStartCity(e.target.value)}
>
<option value="">{t("selectCity")}</option> {/* Translate select city */}
<option value="">{t("selectCity")}</option>
{countries.flatMap((country) =>
country.city.map((city) => (
<option
@ -370,42 +345,38 @@ const CommonLayout: FC<CommonLayoutProps> = () => {
)}
</Select>
</FormItem>
<FormItem label={t("startDate")}> {/* Translate start date label */}
<FormItem label={t("startDate")}>
<Input
type="date"
value={startDate}
onChange={(e) => setStartDate(e.target.value)}
/>
</FormItem>
<FormItem className="ml-4" label={t("numberOfPassengers")}> {/* Translate number of passengers */}
<FormItem className="ml-4" label={t("numberOfPassengers")}>
<div className={`flex flex-col relative p-5`}>
<NcInputNumber
className="w-full"
defaultValue={guestAdultsInputValue}
onChange={(value) => 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")}
/>
<NcInputNumber
className="w-full mt-6"
defaultValue={guestChildrenInputValue}
onChange={(value) =>
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")}
/>
<NcInputNumber
className="w-full mt-6"
defaultValue={guestInfantsInputValue}
onChange={(value) =>
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")}
/>
</div>
</FormItem>
@ -415,7 +386,7 @@ const CommonLayout: FC<CommonLayoutProps> = () => {
{destinations.map((destination, index) => (
<div key={index} className="space-y-8">
<p className="text-bronze text-xs">
{stringifyNumber(index + 1)} {t("destination")} {/* Translate destination */}
{stringifyNumber(index + 1)} {t("destination")}
</p>
<FormItem label="" desc="">
<Select
@ -424,7 +395,7 @@ const CommonLayout: FC<CommonLayoutProps> = () => {
handleDestinationChange(index, "endCity", e.target.value)
}
>
<option value="">{t("selectCity")}</option> {/* Translate select city */}
<option value="">{t("selectCity")}</option>
{countries.flatMap((country) =>
country.city.map((city) => (
<option
@ -437,7 +408,7 @@ const CommonLayout: FC<CommonLayoutProps> = () => {
)}
</Select>
</FormItem>
<FormItem label={t("transportation")} desc=""> {/* Translate transportation */}
<FormItem label={t("transportation")} desc="">
<Select
value={destination.transport}
onChange={(e) =>
@ -448,7 +419,7 @@ const CommonLayout: FC<CommonLayoutProps> = () => {
)
}
>
<option value="">{t("selectTransport")}</option> {/* Translate select transport */}
<option value="">{t("selectTransport")}</option>
{transport.map((item) => (
<option
key={item.transportaion.id}
@ -459,14 +430,14 @@ const CommonLayout: FC<CommonLayoutProps> = () => {
))}
</Select>
</FormItem>
<FormItem label={t("hotel")} desc=""> {/* Translate hotel */}
<FormItem label={t("hotel")} desc="">
<Select
value={destination.hotel}
onChange={(e) =>
handleDestinationChange(index, "hotel", e.target.value)
}
>
<option value="">{t("selectHotel")}</option> {/* Translate select hotel */}
<option value="">{t("selectHotel")}</option>
{hotel.map((hotelItem) => (
<option key={hotelItem.name} value={hotelItem.name}>
{hotelItem.name}
@ -475,7 +446,7 @@ const CommonLayout: FC<CommonLayoutProps> = () => {
</Select>
</FormItem>
<div className="flex w-[100%]">
<FormItem className="w-[50%]" label={t("duration")}> {/* Translate duration */}
<FormItem className="w-[50%]" label={t("duration")}>
<Input
type="number"
value={destination.duration}
@ -489,7 +460,7 @@ const CommonLayout: FC<CommonLayoutProps> = () => {
min="1"
/>
</FormItem>
<FormItem className="w-[50%] ml-4" label={t("finishDate")}> {/* Translate finish date */}
<FormItem className="w-[50%] ml-4" label={t("finishDate")}>
<Input
readOnly
type="date"
@ -507,14 +478,14 @@ const CommonLayout: FC<CommonLayoutProps> = () => {
type="button"
disabled={!isFormValid}
>
{t("addDestination")} {/* Translate add destination */}
{t("addDestination")}
</ButtonPrimary>
<ButtonPrimary
onClick={submitTour}
type="button"
disabled={!isContinueValid}
>
{t("continue")} {/* Translate continue */}
{t("continue")}
</ButtonPrimary>
</div>
</form>

2
src/app/[locale]/page.tsx

@ -40,7 +40,7 @@ function PageHome() {
<SectionOurFeatures />
{/* <SectionCustomTour /> */}
<SectionCustomTour />
{/* <SectionSliderNewCategories categories={DEMO_CATS} /> */}
<SectionDowloadApp/>

128
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<SectionCustomTourProps> = ({
className = "lg:py-14",
rightImg = rightImgPng,
type = "type1",
}) => {
const SectionDownloadApp = () => {
return (
<div
className={`nc-SectionCustomTour relative flex flex-col items-center ${
type === "type1" ? "lg:flex-row" : "lg:flex-row-reverse"
} ${className}`}
data-nc-id="SectionCustomTour"
>
<div className="flex-grow">
<Image src={rightImg} alt="" />
</div>
<div
className={`max-w-2xl flex-shrink-0 mt-10 lg:mt-0 lg:w-2/5 ${
type === "type1" ? "lg:pl-16" : "lg:pr-16"
}`}
>
<h2 className="font-semibold text-4xl mt-5">Custoum Tour </h2>
<ul className="space-y-10 mt-16">
<li className="space-y-4">
<span className="block text-xl font-semibold">
Cost-effective advertising
</span>
<span className="block mt-5 text-neutral-500 dark:text-neutral-400">
With a free listing, you can advertise your rental with no upfront
costs
</span>
</li>
<li className="space-y-4">
<BackgroundSection className="relative h-[455px] lg:py-32 xl:py-40 rounded-lg flex items-center sm:text-left sm:pl-12 lg:pl-56 xl:overflow-hidden bg-gray-900 text-center">
{/* Background Image */}
<Image
className="absolute inset-0 object-cover object-right z-0" // Dim the background image for contrast
alt="Custom Tour Background"
src={BackgroundImage}
fill
/>
<span className="block mt-5 text-neutral-500 dark:text-neutral-400">
Millions of people are searching for unique places to stay around
the world
</span>
</li>
<li className="space-y-4">
<span className="block mt-5 text-neutral-500 dark:text-neutral-400">
A Holiday Lettings listing gives you a secure and easy way to take
bookings and payments online
</span>
</li>
<li className="space-y-4">
<ButtonPrimary>Custoum Tour</ButtonPrimary>
</li>
</ul>
{/* Content Wrapper */}
<div className="relative z-10 ">
<h1 className="text-white text-4xl md:text-5xl lg:text-6xl font-bold leading-tight">
Create
</h1>
<h1 className="text-white text-4xl md:text-5xl lg:text-6xl font-bold leading-tight">
Custom Tour
</h1>
<p className="text-white text-lg mt-4 opacity-80">
Create your personalized tour and design the
</p>
<p className="text-white text-lg mt-4 opacity-80">
perfect travel experience tailored to your preferences.
</p>
<ButtonPrimary className="mt-8 px-8 py-3 text-lg">Custom Tour</ButtonPrimary>
</div>
</div>
</BackgroundSection>
);
};
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 (
// <BackgroundSection className="relative h-[455px] pl-56 pb-0 pt-24 lg:py-32 xl:py-40 rounded-lg overflow-hidden flex items-center bg-gray-900 bg-opacity-50">
// {/* Background Image */}
// <Image
// className="absolute inset-0 object-cover z-0" // Dim the background image for contrast
// alt="Custom Tour Background"
// src={BackgroundImage}
// fill
// />
// {/* Content Wrapper */}
// <div className="relative z-10 ">
// <h1 className="text-white text-4xl md:text-5xl lg:text-6xl font-bold leading-tight">
// Create
// </h1>
// <h1 className="text-white text-4xl md:text-5xl lg:text-6xl font-bold leading-tight">
// Custom Tour
// </h1>
// <p className="text-white text-lg mt-4 opacity-80">
// Create your personalized tour and design the
// </p>
// <p className="text-white text-lg mt-4 opacity-80">
// perfect travel experience tailored to your preferences.
// </p>
// <ButtonPrimary className="mt-8 px-8 py-3 text-lg">Custom Tour</ButtonPrimary>
// </div>
// </BackgroundSection>
// );
// };
// export default SectionDownloadApp;

2
src/components/SectionGridFeaturePlaces.tsx

@ -156,7 +156,7 @@ const SectionGridFeaturePlaces: FC<SectionGridFeaturePlacesProps> = ({
</div>
</MotionConfig>
<div className="flex mt-16 justify-center items-center">
<div className="flex mt-16">
<ButtonPrimary onClick={() => router.push("/tours")}>
Show me more
</ButtonPrimary>

4
src/components/UserMenu.tsx

@ -22,11 +22,11 @@ const UserMenu: FC<UserMenuProps> = ({ className = "" }) => {
return (
<div className={`nc-UserMenu ${className}`}>
{Object.keys(user).length ? (
<Link className="self-center" href="/account">
<Link className="self-center self-center text-2xl md:text-3xl w-12 h-12 rounded-full text-neutral-700 dark:text-neutral-300 hover:bg-neutral-100 dark:hover:bg-neutral-800 focus:outline-none flex items-center justify-center" href="/account">
<Avatar imgUrl={user?.avatar} sizeClass="w-10 h-10" />
</Link>
) : (
<div className="flex items-center space-x-4">
<div className="flex items-center space-x-4 ">
<Link className="text-md" href="/login">
{translation.logIn}
</Link>

BIN
src/images/Frame 412.png

After

Width: 1520  |  Height: 553  |  Size: 443 KiB

BIN
src/images/Free Mockup - iPhone 16 Pro Max copy 1.png

After

Width: 298  |  Height: 536  |  Size: 152 KiB

BIN
src/images/Vector.png

After

Width: 136  |  Height: 358  |  Size: 24 KiB

BIN
src/images/map.png

After

Width: 920  |  Height: 455  |  Size: 55 KiB

BIN
src/images/material-symbols-light_language.png

After

Width: 24  |  Height: 24  |  Size: 759 B

3
src/images/material-symbols-light_language.svg

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 21C10.7613 21 9.59467 20.7633 8.5 20.29C7.40533 19.816 6.452 19.1727 5.64 18.36C4.828 17.5473 4.18467 16.594 3.71 15.5C3.23533 14.406 2.99867 13.2393 3 12C3 10.7573 3.23667 9.58967 3.71 8.497C4.184 7.40367 4.82733 6.45133 5.64 5.64C6.45267 4.82867 7.406 4.18533 8.5 3.71C9.59467 3.23667 10.7613 3 12 3C13.2427 3 14.4103 3.23667 15.503 3.71C16.5963 4.184 17.549 4.82733 18.361 5.64C19.173 6.45267 19.816 7.405 20.29 8.497C20.7633 9.59033 21 10.758 21 12C21 13.2387 20.7633 14.4053 20.29 15.5C19.816 16.5947 19.1727 17.548 18.36 18.36C17.5473 19.172 16.595 19.8153 15.503 20.29C14.411 20.7647 13.2433 21.0013 12 21ZM12 20.008C12.5867 19.254 13.0707 18.5137 13.452 17.787C13.8327 17.0603 14.1423 16.247 14.381 15.347H9.619C9.88367 16.2977 10.1997 17.1363 10.567 17.863C10.935 18.5897 11.4127 19.3047 12 20.008ZM10.727 19.858C10.2603 19.308 9.83433 18.628 9.449 17.818C9.06367 17.0087 8.777 16.1847 8.589 15.346H4.754C5.32733 16.5893 6.13967 17.6093 7.191 18.406C8.243 19.202 9.42167 19.686 10.727 19.858ZM13.273 19.858C14.5783 19.686 15.757 19.202 16.809 18.406C17.8603 17.6093 18.6727 16.5893 19.246 15.346H15.412C15.1587 16.1973 14.8397 17.0277 14.455 17.837C14.0697 18.647 13.6757 19.3213 13.273 19.858ZM4.346 14.347H8.381C8.305 13.9363 8.25167 13.5363 8.221 13.147C8.189 12.7583 8.173 12.376 8.173 12C8.173 11.624 8.18867 11.2417 8.22 10.853C8.25133 10.4643 8.30467 10.0643 8.38 9.653H4.347C4.23833 9.99967 4.15333 10.3773 4.092 10.786C4.03067 11.194 4 11.5987 4 12C4 12.4013 4.03033 12.8063 4.091 13.215C4.15167 13.6237 4.23667 14.0007 4.346 14.346M9.381 14.346H14.619C14.695 13.936 14.7483 13.5427 14.779 13.166C14.811 12.79 14.827 12.4013 14.827 12C14.827 11.5987 14.8113 11.21 14.78 10.834C14.7487 10.458 14.6953 10.0647 14.62 9.654H9.38C9.30467 10.064 9.25133 10.4573 9.22 10.834C9.18867 11.21 9.173 11.5987 9.173 12C9.173 12.4013 9.18867 12.79 9.22 13.166C9.25133 13.542 9.30567 13.9353 9.381 14.346ZM15.62 14.346H19.654C19.7627 14 19.8477 13.623 19.909 13.215C19.9697 12.8063 20 12.4013 20 12C20 11.5987 19.9697 11.1937 19.909 10.785C19.8483 10.3763 19.7633 9.99933 19.654 9.654H15.619C15.695 10.064 15.7483 10.4637 15.779 10.853C15.811 11.2423 15.827 11.6247 15.827 12C15.827 12.3753 15.8113 12.7577 15.78 13.147C15.7487 13.5363 15.6953 13.9363 15.62 14.347M15.412 8.654H19.246C18.66 7.38467 17.8573 6.36467 16.838 5.594C15.8187 4.82333 14.6303 4.333 13.273 4.123C13.7397 4.737 14.1593 5.43933 14.532 6.23C14.9047 7.02 15.198 7.828 15.412 8.654ZM9.619 8.654H14.381C14.117 7.71533 13.7913 6.86667 13.404 6.108C13.0167 5.34933 12.5487 4.644 12 3.992C11.4513 4.64333 10.9833 5.34867 10.596 6.108C10.2087 6.86733 9.88233 7.716 9.619 8.654ZM4.755 8.654H8.589C8.803 7.82867 9.09633 7.02067 9.469 6.23C9.84167 5.43933 10.2613 4.737 10.728 4.123C9.35867 4.33367 8.16733 4.827 7.154 5.603C6.14067 6.38033 5.34067 7.397 4.754 8.653" fill="#838E92"/>
</svg>

3
src/images/mynaui_search.svg

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.893 16.92L19.973 20M19 11.5C19 13.4891 18.2098 15.3968 16.8033 16.8033C15.3968 18.2098 13.4891 19 11.5 19C9.51088 19 7.60322 18.2098 6.1967 16.8033C4.79018 15.3968 4 13.4891 4 11.5C4 9.51088 4.79018 7.60322 6.1967 6.1967C7.60322 4.79018 9.51088 4 11.5 4C13.4891 4 15.3968 4.79018 16.8033 6.1967C18.2098 7.60322 19 9.51088 19 11.5Z" stroke="#D09460" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

19
src/shared/Navigation/NavigationItem.tsx

@ -36,7 +36,7 @@ type NavigationItemWithRouterProps = NavigationItemProps;
const NavigationItem: FC<NavigationItemWithRouterProps> = ({ menuItem }) => {
const [menuCurrentHovers, setMenuCurrentHovers] = useState<string[]>([]);
const {countries} = useToursContext()
const { countries } = useToursContext();
// CLOSE ALL MENU OPENING WHEN CHANGE HISTORY
const locationPathName = usePathname();
@ -56,6 +56,11 @@ const NavigationItem: FC<NavigationItemWithRouterProps> = ({ 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<NavigationItemWithRouterProps> = ({ menuItem }) => {
className="sub-menu will-change-transform absolute transform z-10 w-56 top-full left-0"
>
<ul className="rounded-lg shadow-lg ring-1 ring-black ring-opacity-5 dark:ring-white dark:ring-opacity-10 text-sm relative bg-white dark:bg-neutral-900 py-4 grid space-y-1">
{ countries?.map((i) => {
{countries?.map((i) => {
if (i.type) {
return renderDropdownMenuNavlinkHasChild(i);
} else {
@ -255,10 +260,16 @@ const NavigationItem: FC<NavigationItemWithRouterProps> = ({ 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 (
<Link
rel="noopener noreferrer"
className="inline-flex items-center text-sm xl:text-base font-normal text-neutral-700 dark:text-neutral-300 py-2 px-4 xl:px-5 rounded-full hover:text-neutral-900 hover:bg-neutral-100 dark:hover:bg-neutral-800 dark:hover:text-neutral-200"
className={`inline-flex items-center text-sm xl:text-base ${
isActive ? "text-neutral-700 font-medium" : "text-neutral-500 font-normal"
} dark:text-neutral-300 py-2 px-4 xl:px-5 rounded-full hover:text-neutral-900 hover:bg-neutral-100 dark:hover:bg-neutral-800 dark:hover:text-neutral-200`}
href={item.href || "/"}
>
{item.name}
@ -271,7 +282,6 @@ const NavigationItem: FC<NavigationItemWithRouterProps> = ({ menuItem }) => {
</Link>
);
};
console.log(menuItem.type);
switch (menuItem.type) {
case "megaMenu":
@ -286,6 +296,5 @@ console.log(menuItem.type);
);
}
};
// Your component own properties
export default NavigationItem;
Loading…
Cancel
Save