classify web
This commit is contained in:
172
components/PagesComponent/LandingPage/AnythingYouWant.jsx
Normal file
172
components/PagesComponent/LandingPage/AnythingYouWant.jsx
Normal file
@@ -0,0 +1,172 @@
|
||||
"use client";
|
||||
import { t } from "@/utils";
|
||||
import { useEffect, useState } from "react";
|
||||
import { IoSearchOutline } from "react-icons/io5";
|
||||
import Img1 from "../../../public/assets/Image1.png";
|
||||
import Img2 from "../../../public/assets/Image2.png";
|
||||
import Img3 from "../../../public/assets/Image3.png";
|
||||
import Img4 from "../../../public/assets/Image4.png";
|
||||
import Img5 from "../../../public/assets/Image5.png";
|
||||
import Img6 from "../../../public/assets/Image6.png";
|
||||
import {
|
||||
getCityData,
|
||||
getIsBrowserSupported,
|
||||
getKilometerRange,
|
||||
saveCity,
|
||||
} from "@/redux/reducer/locationSlice";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { CurrentLanguageData } from "@/redux/reducer/languageSlice";
|
||||
import LocationModal from "../../Location/LocationModal";
|
||||
import { toast } from "sonner";
|
||||
import { FaLocationCrosshairs } from "react-icons/fa6";
|
||||
import { getCompanyName } from "@/redux/reducer/settingSlice";
|
||||
import CustomLink from "@/components/Common/CustomLink";
|
||||
import { ArrowRight } from "lucide-react";
|
||||
import { setIsVisitedLandingPage } from "@/redux/reducer/globalStateSlice";
|
||||
import CustomImage from "@/components/Common/CustomImage";
|
||||
import { useNavigate } from "@/components/Common/useNavigate";
|
||||
import LandingAdEditSearchAutocomplete from "@/components/Location/LandingAdEditSearchAutocomplete";
|
||||
|
||||
const AnythingYouWant = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { navigate } = useNavigate();
|
||||
const CurrentLanguage = useSelector(CurrentLanguageData);
|
||||
const LocationData = useSelector(getCityData);
|
||||
const companyName = useSelector(getCompanyName);
|
||||
const [selectedCity, setSelectedCity] = useState(LocationData);
|
||||
const IsBrowserSupported = useSelector(getIsBrowserSupported);
|
||||
const [IsLocationModalOpen, setIsLocationModalOpen] = useState(false);
|
||||
const KmRange = useSelector(getKilometerRange);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(setIsVisitedLandingPage(true));
|
||||
}, []);
|
||||
|
||||
const handleSearchLocation = () => {
|
||||
const isInvalidLocation =
|
||||
KmRange > 0
|
||||
? !selectedCity?.lat || !selectedCity?.long
|
||||
: !selectedCity?.areaId &&
|
||||
!selectedCity?.city &&
|
||||
!selectedCity?.state &&
|
||||
!selectedCity?.country;
|
||||
|
||||
if (isInvalidLocation) {
|
||||
toast.error(t("pleaseSelectLocation"));
|
||||
return;
|
||||
}
|
||||
|
||||
saveCity(selectedCity);
|
||||
navigate("/");
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<section
|
||||
id="anythingYouWant"
|
||||
className="py-28 bg-muted flex items-center justify-center"
|
||||
>
|
||||
<div className="container relative">
|
||||
<div className="flex flex-col items-center gap-6 text-center">
|
||||
<div className="flex flex-col items-center font-bold text-4xl lg:text-5xl gap-3 relative">
|
||||
<h1 className="flex flex-column items-center relative z-10 after:content-[''] after:absolute after:bg-[#00b2ca] after:h-[40%] after:w-full after:z-[-1] after:bottom-0">
|
||||
{t("buySell")}
|
||||
</h1>
|
||||
<h1>{t("anythingYouWant")}</h1>
|
||||
</div>
|
||||
<p className="text-sm font-light md:w-1/2">
|
||||
{t("discoverEndlessPossibilitiesAt")} {companyName}{" "}
|
||||
{t("goToMarketplace")}
|
||||
</p>
|
||||
<div className="space-between gap-3 rounded border w-full lg:w-[60%] bg-white py-2 ltr:pr-2 rtl:pl-2 relative">
|
||||
<LandingAdEditSearchAutocomplete
|
||||
saveOnSuggestionClick={false}
|
||||
setSelectedLocation={setSelectedCity}
|
||||
/>
|
||||
<div className="flex items-center gap-3">
|
||||
{IsBrowserSupported && (
|
||||
<button
|
||||
className="flex items-center gap-2"
|
||||
onClick={() => setIsLocationModalOpen(true)}
|
||||
>
|
||||
<FaLocationCrosshairs size={22} />
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
className="flex items-center gap-2 bg-primary px-3 py-[6px] rounded text-white"
|
||||
onClick={handleSearchLocation}
|
||||
>
|
||||
<IoSearchOutline size={22} />
|
||||
<span className="hidden md:block">{t("search")}</span>
|
||||
</button>
|
||||
</div>
|
||||
<CustomLink
|
||||
href="/"
|
||||
className="hidden sm:flex items-center gap-2 text-destructive"
|
||||
>
|
||||
<span className="whitespace-nowrap">{t("skip")}</span>
|
||||
<ArrowRight size={16} className="rtl:scale-x-[-1]" />
|
||||
</CustomLink>
|
||||
</div>
|
||||
<CustomLink
|
||||
href="/"
|
||||
className="sm:hidden flex items-center gap-2 text-destructive"
|
||||
>
|
||||
<span className="whitespace-nowrap">{t("skip")}</span>
|
||||
<ArrowRight size={16} className="rtl:scale-x-[-1]" />
|
||||
</CustomLink>
|
||||
</div>
|
||||
<CustomImage
|
||||
src={Img1}
|
||||
className="hidden xl:block absolute xl:-top-[38%] ltr:xl:left-[3%] rtl:xl:right-[3%] xl:w-[110px] rounded-full"
|
||||
height={135}
|
||||
width={90}
|
||||
alt="landing page image 1"
|
||||
/>
|
||||
<CustomImage
|
||||
src={Img2}
|
||||
className="hidden xl:block absolute xl:top-[38%] ltr:xl:left-[9%] rtl:xl:right-[9%] xl:w-[110px] rounded-full"
|
||||
height={135}
|
||||
width={90}
|
||||
alt="landing page image 2"
|
||||
/>
|
||||
<CustomImage
|
||||
src={Img3}
|
||||
className="hidden xl:block absolute xl:top-[120%] ltr:xl:left-[3%] rtl:xl:right-[3%] xl:w-[110px] rounded-full"
|
||||
height={90}
|
||||
width={90}
|
||||
alt="landing page image 3"
|
||||
/>
|
||||
<CustomImage
|
||||
src={Img4}
|
||||
className="hidden xl:block absolute xl:-top-[38%] ltr:xl:right-[3%] rtl:xl:left-[3%] xl:w-[110px] rounded-full"
|
||||
height={135}
|
||||
width={90}
|
||||
alt="landing page image 4"
|
||||
/>
|
||||
<CustomImage
|
||||
src={Img5}
|
||||
className="hidden xl:block absolute xl:top-[38%] ltr:xl:right-[9%] rtl:xl:left-[9%] xl:w-[110px] rounded-full"
|
||||
height={90}
|
||||
width={90}
|
||||
alt="landing page image 5"
|
||||
/>
|
||||
<CustomImage
|
||||
src={Img6}
|
||||
className="hidden xl:block absolute xl:top-[109%] ltr:xl:right-[3%] rtl:xl:left-[3%] xl:w-[110px] rounded-full"
|
||||
height={0}
|
||||
width={0}
|
||||
alt="landing page image 6"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
<LocationModal
|
||||
key={`${IsLocationModalOpen}-location-modal`}
|
||||
IsLocationModalOpen={IsLocationModalOpen}
|
||||
setIsLocationModalOpen={setIsLocationModalOpen}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AnythingYouWant;
|
||||
37
components/PagesComponent/LandingPage/BlogCard.jsx
Normal file
37
components/PagesComponent/LandingPage/BlogCard.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
"use client";
|
||||
import { FaArrowRight } from "react-icons/fa";
|
||||
import CustomLink from "@/components/Common/CustomLink";
|
||||
import { t } from "@/utils";
|
||||
import CustomImage from "@/components/Common/CustomImage";
|
||||
|
||||
const BlogCard = ({ blog }) => {
|
||||
return (
|
||||
<div className="p-4 rounded-3xl flex flex-col gap-4 border h-100 bg-white h-full">
|
||||
<CustomImage
|
||||
src={blog?.image}
|
||||
alt="Blog image"
|
||||
className="w-full object-cover rounded-[8px] aspect-[388/200]"
|
||||
width={378}
|
||||
height={195}
|
||||
/>
|
||||
<h5 className="text-lg font-semibold truncate">
|
||||
{blog?.translated_title || blog?.title}
|
||||
</h5>
|
||||
<p
|
||||
className="opacity-65 line-clamp-2"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: blog?.translated_description || blog?.description,
|
||||
}}
|
||||
></p>
|
||||
<CustomLink
|
||||
href={`/blogs/${blog?.slug}`}
|
||||
className="flex items-center gap-3 text-primary text-lg mt-auto"
|
||||
>
|
||||
<span>{t("readArticle")}</span>
|
||||
<FaArrowRight className="rtl:scale-x-[-1]" size={20} />
|
||||
</CustomLink>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogCard;
|
||||
141
components/PagesComponent/LandingPage/LandingHeader.jsx
Normal file
141
components/PagesComponent/LandingPage/LandingHeader.jsx
Normal file
@@ -0,0 +1,141 @@
|
||||
"use client";
|
||||
import { t } from "@/utils";
|
||||
import { useSelector } from "react-redux";
|
||||
import { CurrentLanguageData } from "@/redux/reducer/languageSlice";
|
||||
import { settingsData } from "@/redux/reducer/settingSlice";
|
||||
import LanguageDropdown from "../../Common/LanguageDropdown";
|
||||
import LandingMobileMenu from "@/components/PagesComponent/LandingPage/LandingMobileMenu";
|
||||
import { useState, useEffect } from "react";
|
||||
import CustomImage from "@/components/Common/CustomImage";
|
||||
import CustomLink from "@/components/Common/CustomLink";
|
||||
|
||||
const LandingHeader = () => {
|
||||
const CurrentLanguage = useSelector(CurrentLanguageData);
|
||||
const settings = useSelector(settingsData);
|
||||
const [isShowMobileMenu, setIsShowMobileMenu] = useState(false);
|
||||
const [activeSection, setActiveSection] = useState("anythingYouWant");
|
||||
|
||||
const handleMobileMenuClose = () => {
|
||||
if (isShowMobileMenu) {
|
||||
setIsShowMobileMenu(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Intersection Observer to track which section is currently visible
|
||||
useEffect(() => {
|
||||
const sections = ["anythingYouWant", "work_process", "faq", "ourBlogs"];
|
||||
const observerOptions = {
|
||||
root: null,
|
||||
rootMargin: "0px", // Trigger when section is 20% from top
|
||||
threshold: 0.7,
|
||||
};
|
||||
const observerCallback = (entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
setActiveSection(entry.target.id);
|
||||
}
|
||||
});
|
||||
};
|
||||
const observer = new IntersectionObserver(
|
||||
observerCallback,
|
||||
observerOptions
|
||||
);
|
||||
// Observe all sections
|
||||
sections.forEach((sectionId) => {
|
||||
const element = document.getElementById(sectionId);
|
||||
if (element) {
|
||||
observer.observe(element);
|
||||
}
|
||||
});
|
||||
// Cleanup observer on component unmount
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<header className="sticky top-0 z-50 bg-white shadow-xs">
|
||||
<nav className="shadow-md">
|
||||
<div className="container py-5 lg:flex lg:items-center lg:justify-between">
|
||||
<div className="flex w-100 items-center justify-between">
|
||||
<CustomImage
|
||||
src={settings?.header_logo}
|
||||
className="w-full h-[52px] object-contain ltr:object-left rtl:object-right max-w-[195px]"
|
||||
alt="logo"
|
||||
width={195}
|
||||
height={52}
|
||||
/>
|
||||
|
||||
<LandingMobileMenu
|
||||
isOpen={isShowMobileMenu}
|
||||
setIsOpen={setIsShowMobileMenu}
|
||||
activeSection={activeSection}
|
||||
/>
|
||||
</div>
|
||||
<div className="hidden lg:flex gap-6">
|
||||
<ul className="flex items-center gap-6">
|
||||
<li>
|
||||
<CustomLink
|
||||
href="#anythingYouWant"
|
||||
className={`cursor-pointer transition-all duration-200 ${
|
||||
activeSection === "anythingYouWant"
|
||||
? "text-primary"
|
||||
: "hover:text-primary"
|
||||
}`}
|
||||
>
|
||||
{t("home")}
|
||||
</CustomLink>
|
||||
</li>
|
||||
<li>
|
||||
<CustomLink
|
||||
href="#work_process"
|
||||
className={`cursor-pointer transition-all duration-200 ${
|
||||
activeSection === "work_process"
|
||||
? "text-primary"
|
||||
: "hover:text-primary"
|
||||
}`}
|
||||
onClick={handleMobileMenuClose}
|
||||
>
|
||||
{t("whyChooseUs")}
|
||||
</CustomLink>
|
||||
</li>
|
||||
<li>
|
||||
<CustomLink
|
||||
href="#faq"
|
||||
className={`cursor-pointer transition-all duration-200 ${
|
||||
activeSection === "faq"
|
||||
? "text-primary"
|
||||
: "hover:text-primary"
|
||||
}`}
|
||||
onClick={handleMobileMenuClose}
|
||||
>
|
||||
{t("faqs")}
|
||||
</CustomLink>
|
||||
</li>
|
||||
<li>
|
||||
<CustomLink
|
||||
href="#ourBlogs"
|
||||
className={`cursor-pointer transition-all duration-200 ${
|
||||
activeSection === "ourBlogs"
|
||||
? "text-primary"
|
||||
: "hover:text-primary"
|
||||
}`}
|
||||
onClick={handleMobileMenuClose}
|
||||
>
|
||||
{t("blog")}
|
||||
</CustomLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="hidden lg:flex">
|
||||
<LanguageDropdown />
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LandingHeader;
|
||||
103
components/PagesComponent/LandingPage/LandingMobileMenu.jsx
Normal file
103
components/PagesComponent/LandingPage/LandingMobileMenu.jsx
Normal file
@@ -0,0 +1,103 @@
|
||||
"use client";
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
SheetTrigger,
|
||||
} from "@/components/ui/sheet";
|
||||
import { settingsData } from "@/redux/reducer/settingSlice";
|
||||
import { t } from "@/utils";
|
||||
import { GiHamburgerMenu } from "react-icons/gi";
|
||||
import { useSelector } from "react-redux";
|
||||
import LanguageDropdown from "../../Common/LanguageDropdown";
|
||||
import { CurrentLanguageData } from "@/redux/reducer/languageSlice";
|
||||
import CustomImage from "@/components/Common/CustomImage";
|
||||
|
||||
const LandingMobileMenu = ({ isOpen, setIsOpen, activeSection }) => {
|
||||
const CurrentLanguage = useSelector(CurrentLanguageData);
|
||||
const settings = useSelector(settingsData);
|
||||
|
||||
const scrollToSection = (id) => {
|
||||
const section = document.getElementById(id);
|
||||
if (section) {
|
||||
setIsOpen(false);
|
||||
section.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Sheet open={isOpen} onOpenChange={setIsOpen} className="lg:hidden">
|
||||
<SheetTrigger asChild className="lg:hidden">
|
||||
<button
|
||||
id="hamburg"
|
||||
className="text-2xl cursor-pointer border rounded-lg p-1"
|
||||
>
|
||||
<GiHamburgerMenu size={25} className="text-primary" />
|
||||
</button>
|
||||
</SheetTrigger>
|
||||
<SheetContent className="[&>button:first-child]:hidden] p-0">
|
||||
<SheetHeader className="py-4 px-6 border-b border">
|
||||
<SheetTitle>
|
||||
<CustomImage
|
||||
src={settings?.header_logo}
|
||||
width={195}
|
||||
height={52}
|
||||
alt="Logo"
|
||||
className="w-full h-[52px] object-contain ltr:object-left rtl:object-right max-w-[195px]"
|
||||
/>
|
||||
</SheetTitle>
|
||||
</SheetHeader>
|
||||
<div className="p-6">
|
||||
<div className="flex flex-col list-none">
|
||||
<li
|
||||
className={`cursor-pointer py-3 border-b border-dashed transition-all duration-200 ${
|
||||
activeSection === "anythingYouWant"
|
||||
? "text-primary"
|
||||
: "hover:text-primary"
|
||||
}`}
|
||||
onClick={() => scrollToSection("anythingYouWant")}
|
||||
>
|
||||
{t("home")}
|
||||
</li>
|
||||
<li
|
||||
className={`cursor-pointer py-3 border-b border-dashed transition-all duration-200 ${
|
||||
activeSection === "work_process"
|
||||
? "text-primary"
|
||||
: "hover:text-primary"
|
||||
}`}
|
||||
onClick={() => scrollToSection("work_process")}
|
||||
>
|
||||
{t("whyChooseUs")}
|
||||
</li>
|
||||
<li
|
||||
className={`cursor-pointer py-3 border-b border-dashed transition-all duration-200 ${
|
||||
activeSection === "faq"
|
||||
? "text-primary font-semibold bg-primary/5"
|
||||
: "hover:text-primary"
|
||||
}`}
|
||||
onClick={() => scrollToSection("faq")}
|
||||
>
|
||||
{t("faqs")}
|
||||
</li>
|
||||
<li
|
||||
className={`cursor-pointer py-3 border-b border-dashed transition-all duration-200 ${
|
||||
activeSection === "ourBlogs"
|
||||
? "text-primary font-semibold bg-primary/5"
|
||||
: "hover:text-primary"
|
||||
}`}
|
||||
onClick={() => scrollToSection("ourBlogs")}
|
||||
>
|
||||
{t("blog")}
|
||||
</li>
|
||||
<li className="py-3">
|
||||
<LanguageDropdown />
|
||||
</li>
|
||||
</div>
|
||||
</div>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
);
|
||||
};
|
||||
|
||||
export default LandingMobileMenu;
|
||||
122
components/PagesComponent/LandingPage/OurBlogs.jsx
Normal file
122
components/PagesComponent/LandingPage/OurBlogs.jsx
Normal file
@@ -0,0 +1,122 @@
|
||||
"use client";
|
||||
import { t } from "@/utils";
|
||||
import {
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
CarouselItem,
|
||||
} from "@/components/ui/carousel";
|
||||
import { useEffect, useState } from "react";
|
||||
import { RiArrowLeftLine, RiArrowRightLine } from "react-icons/ri";
|
||||
import { getBlogsApi } from "@/utils/api";
|
||||
import BlogCardSkeleton from "../../Skeletons/BlogCardSkeleton.jsx";
|
||||
import BlogCard from "./BlogCard.jsx";
|
||||
import { CurrentLanguageData } from "@/redux/reducer/languageSlice.js";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
const OurBlogs = () => {
|
||||
const CurrentLanguage = useSelector(CurrentLanguageData);
|
||||
const isRTL = CurrentLanguage?.rtl;
|
||||
const [api, setApi] = useState();
|
||||
const [current, setCurrent] = useState(0);
|
||||
const [Blogs, setBlogs] = useState([]);
|
||||
const [IsLoading, setIsLoading] = useState(true);
|
||||
|
||||
const getBlogsData = async () => {
|
||||
try {
|
||||
const res = await getBlogsApi.getBlogs();
|
||||
setBlogs(res?.data?.data?.data);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getBlogsData();
|
||||
}, [CurrentLanguage.id]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
setCurrent(api.selectedScrollSnap());
|
||||
api.on("select", () => {
|
||||
setCurrent(api.selectedScrollSnap());
|
||||
});
|
||||
}, [api]);
|
||||
|
||||
return (
|
||||
<section className="py-28 bg-muted" id="ourBlogs">
|
||||
<div className="container">
|
||||
<div className="flex items-center flex-col gap-6">
|
||||
<p className="outlinedSecHead">{t("ourBlog")}</p>
|
||||
<h1 className="landingSecHeader">
|
||||
{t("masteringMarketplace")}
|
||||
<br />
|
||||
{t("withOurBlog")}
|
||||
</h1>
|
||||
</div>
|
||||
<Carousel
|
||||
key={isRTL ? "rtl" : "ltr"}
|
||||
className="w-full mt-20"
|
||||
setApi={setApi}
|
||||
opts={{ align: "start", direction: isRTL ? "rtl" : "ltr" }}
|
||||
>
|
||||
<CarouselContent className="-ml-3 md:-ml-[30px]">
|
||||
{IsLoading
|
||||
? Array.from({ length: 6 }).map((_, i) => (
|
||||
<CarouselItem
|
||||
key={i}
|
||||
className="sm:basis-1/2 xl:basis-1/3 pl-3 md:pl-[30px]"
|
||||
>
|
||||
<BlogCardSkeleton />
|
||||
</CarouselItem>
|
||||
))
|
||||
: Blogs &&
|
||||
Blogs.length > 0 &&
|
||||
Blogs.map((blog) => (
|
||||
<CarouselItem
|
||||
key={blog?.id}
|
||||
className="sm:basis-1/2 xl:basis-1/3 pl-3 md:pl-[30px]"
|
||||
>
|
||||
<BlogCard blog={blog} />
|
||||
</CarouselItem>
|
||||
))}
|
||||
</CarouselContent>
|
||||
</Carousel>
|
||||
|
||||
<div className="flex items-center justify-center mt-[30px] gap-4">
|
||||
<button
|
||||
onClick={() => api?.scrollTo(current - 1)}
|
||||
className={`bg-primary p-2 rounded ${
|
||||
!api?.canScrollPrev() ? "opacity-65 cursor-default" : ""
|
||||
}`}
|
||||
disabled={!api?.canScrollPrev()}
|
||||
>
|
||||
<RiArrowLeftLine
|
||||
size={24}
|
||||
color="white"
|
||||
className={isRTL ? "rotate-180" : ""}
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => api?.scrollTo(current + 1)}
|
||||
className={`bg-primary p-2 rounded ${
|
||||
!api?.canScrollNext() ? "opacity-65 cursor-default" : ""
|
||||
}`}
|
||||
disabled={!api?.canScrollNext()}
|
||||
>
|
||||
<RiArrowRightLine
|
||||
size={24}
|
||||
color="white"
|
||||
className={isRTL ? "rotate-180" : ""}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default OurBlogs;
|
||||
70
components/PagesComponent/LandingPage/QuickAnswers.jsx
Normal file
70
components/PagesComponent/LandingPage/QuickAnswers.jsx
Normal file
@@ -0,0 +1,70 @@
|
||||
"use client";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/components/ui/accordion";
|
||||
import { CurrentLanguageData } from "@/redux/reducer/languageSlice";
|
||||
import { t } from "@/utils";
|
||||
import { getFaqApi } from "@/utils/api";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
const QuickAnswers = () => {
|
||||
const CurrentLanguage = useSelector(CurrentLanguageData);
|
||||
const [Faqs, setFaqs] = useState([]);
|
||||
|
||||
const getFaqData = async () => {
|
||||
try {
|
||||
const res = await getFaqApi.getFaq();
|
||||
setFaqs(res?.data?.data);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getFaqData();
|
||||
}, [CurrentLanguage.id]);
|
||||
|
||||
return (
|
||||
<section className="py-28" id="faq">
|
||||
<div className="container">
|
||||
<div className="flex items-center flex-col gap-6">
|
||||
<p className="outlinedSecHead">{t("navigating")}</p>
|
||||
<h1 className="landingSecHeader">{t("quickAnswers")}</h1>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4 md:gap-8 mt-20">
|
||||
{Faqs &&
|
||||
Faqs.length > 0 &&
|
||||
Faqs.map((faq) => (
|
||||
<Accordion
|
||||
type="single"
|
||||
collapsible
|
||||
className="border rounded-md overflow-hidden"
|
||||
key={faq?.id}
|
||||
>
|
||||
<AccordionItem value={faq?.id} className="border-none group">
|
||||
<AccordionTrigger
|
||||
className="text-start font-bold text-base px-4 hover:no-underline bg-transparent
|
||||
group-data-[state=open]:bg-muted group-data-[state=open]:text-primary
|
||||
group-data-[state=open]:border-b"
|
||||
>
|
||||
{faq?.translated_question || faq?.question}
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="bg-muted p-4">
|
||||
<p className="text-base">
|
||||
{faq?.translated_answer || faq?.answer}
|
||||
</p>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default QuickAnswers;
|
||||
56
components/PagesComponent/LandingPage/WorkProcess.jsx
Normal file
56
components/PagesComponent/LandingPage/WorkProcess.jsx
Normal file
@@ -0,0 +1,56 @@
|
||||
"use client";
|
||||
import { t } from "@/utils";
|
||||
import Arrow from "../../../public/assets/Arrow.svg";
|
||||
import { workProcessSteps } from "@/utils/constants";
|
||||
import { useSelector } from "react-redux";
|
||||
import { settingsData } from "@/redux/reducer/settingSlice";
|
||||
import { CurrentLanguageData } from "@/redux/reducer/languageSlice";
|
||||
import CustomImage from "@/components/Common/CustomImage";
|
||||
|
||||
const WorkProcess = () => {
|
||||
const CurrentLanguage = useSelector(CurrentLanguageData);
|
||||
const settings = useSelector(settingsData);
|
||||
|
||||
return (
|
||||
<section className="py-28" id="work_process">
|
||||
<div className="container">
|
||||
<div className="flex items-center flex-col gap-6">
|
||||
<p className="outlinedSecHead">
|
||||
{t("how")} {settings?.company_name} {t("getsYouResults")}
|
||||
</p>
|
||||
<h1 className="landingSecHeader">
|
||||
{t("unravelingThe")} {settings?.company_name} <br />{" "}
|
||||
{t("workProcess")}
|
||||
</h1>
|
||||
</div>
|
||||
<div className="mt-20">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 text-center">
|
||||
{workProcessSteps.map((step, index) => (
|
||||
<div
|
||||
key={step.id}
|
||||
className="flex flex-col items-center gap-4 relative"
|
||||
>
|
||||
{index !== workProcessSteps.length - 1 && (
|
||||
<CustomImage
|
||||
src={Arrow}
|
||||
alt="arrow"
|
||||
width={128}
|
||||
height={22}
|
||||
className="absolute hidden w-32 top-[5%] lg:block lg:-right-[34%] xl:-right-[30%] 2xl:-right-[25%] rtl:right-auto rtl:lg:-left-[34%] rtl:xl:-left-[30%] rtl:2xl:-left-[25%] rtl:scale-x-[-1]"
|
||||
/>
|
||||
)}
|
||||
<span className="flex items-center justify-center text-white font-bold w-[40px] h-[40px] bg-primary rounded-full">
|
||||
{step.id}
|
||||
</span>
|
||||
<h5 className="font-bold">{t(step.title)}</h5>
|
||||
<p>{t(step.description)}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default WorkProcess;
|
||||
Reference in New Issue
Block a user