show case slider connected to backend
This commit is contained in:
@@ -33,15 +33,6 @@ export function Navbar() {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log({ navbarItems });
|
|
||||||
|
|
||||||
const tabs = [
|
|
||||||
{ name: t("navbar.about"), value: "" },
|
|
||||||
{ name: t("about.subPages.baza"), value: "baza" },
|
|
||||||
{ name: t("about.subPages.certificate"), value: "sertificate" },
|
|
||||||
{ name: t("about.subPages.notePP"), value: "notePP" },
|
|
||||||
];
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleScroll = () => {
|
const handleScroll = () => {
|
||||||
setScrolled(window.scrollY > 50);
|
setScrolled(window.scrollY > 50);
|
||||||
@@ -110,13 +101,14 @@ export function Navbar() {
|
|||||||
{item.children.length > 0 && (
|
{item.children.length > 0 && (
|
||||||
<DropdownMenuContent className="space-y-2">
|
<DropdownMenuContent className="space-y-2">
|
||||||
{item.children.map((child: NavbarItem) => (
|
{item.children.map((child: NavbarItem) => (
|
||||||
<Link
|
<DropdownMenuItem asChild key={child.id}>
|
||||||
key={child.id}
|
<Link
|
||||||
href={`/${locale}/${child.url}`}
|
href={`/${locale}/${child.url}`}
|
||||||
className="font-unbounded uppercase text-white text-sm h-full flex items-center font-semibold hover:cursor-pointer hover:text-red-500 transition"
|
className="font-unbounded uppercase text-white text-sm h-full flex items-center font-semibold hover:cursor-pointer hover:text-red-500 transition"
|
||||||
>
|
>
|
||||||
{child.name}
|
{child.name}
|
||||||
</Link>
|
</Link>
|
||||||
|
</DropdownMenuItem>
|
||||||
))}
|
))}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
)}
|
)}
|
||||||
|
|||||||
68
components/pages/home/banner/loading.tsx
Normal file
68
components/pages/home/banner/loading.tsx
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
export function BannerSliderSkeleton() {
|
||||||
|
return (
|
||||||
|
<div className="max-w-7xl mx-auto relative z-30 h-full mt-20 flex items-center justify-center">
|
||||||
|
{/* Fake nav buttons */}
|
||||||
|
<div className="w-10 h-10 absolute z-10 left-[5%] top-[40vh] rounded-full bg-gray-700/50 lg:flex hidden animate-pulse" />
|
||||||
|
<div className="w-10 h-10 absolute z-10 right-[5%] top-[40vh] rounded-full bg-gray-700/50 lg:flex hidden animate-pulse" />
|
||||||
|
|
||||||
|
{/* Slide content */}
|
||||||
|
<div className="relative z-20 h-full flex items-center lg:mt-0 sm:mt-[10vh] mt-[5vh] w-full">
|
||||||
|
<div className="max-w-400 mx-auto px-4 sm:px-6 lg:px-8 w-full">
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-12 items-center h-full">
|
||||||
|
|
||||||
|
{/* Mobile text skeleton (hidden on lg) */}
|
||||||
|
<div className="lg:hidden space-y-6">
|
||||||
|
{/* Badge */}
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="w-3 h-3 rounded-full bg-gray-600 animate-pulse" />
|
||||||
|
<div className="h-4 w-32 rounded-full bg-gray-600 animate-pulse" />
|
||||||
|
</div>
|
||||||
|
{/* Heading */}
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div className="h-8 w-4/5 rounded-lg bg-gray-600 animate-pulse" />
|
||||||
|
<div className="h-8 w-3/5 rounded-lg bg-gray-600 animate-pulse" />
|
||||||
|
</div>
|
||||||
|
{/* Description */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<div className="h-4 w-full rounded bg-gray-700 animate-pulse" />
|
||||||
|
<div className="h-4 w-11/12 rounded bg-gray-700 animate-pulse" />
|
||||||
|
<div className="h-4 w-3/4 rounded bg-gray-700 animate-pulse" />
|
||||||
|
</div>
|
||||||
|
{/* CTA */}
|
||||||
|
<div className="h-12 w-40 rounded-full bg-red-900/40 animate-pulse" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Image skeleton */}
|
||||||
|
<div className="flex items-end justify-center">
|
||||||
|
<div className="lg:w-[375px] w-[250px] lg:h-[375px] h-[250px] max-[300px]:w-[80vw] rounded-xl bg-gray-700/50 animate-pulse shimmer" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Desktop text skeleton (hidden on mobile) */}
|
||||||
|
<div className="lg:inline-block hidden space-y-6 mb-20">
|
||||||
|
{/* Badge */}
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="w-3 h-3 rounded-full bg-gray-600 animate-pulse" />
|
||||||
|
<div className="h-4 w-36 rounded-full bg-gray-600 animate-pulse" />
|
||||||
|
</div>
|
||||||
|
{/* Heading */}
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div className="h-10 w-4/5 rounded-lg bg-gray-600 animate-pulse" />
|
||||||
|
<div className="h-10 w-3/5 rounded-lg bg-gray-600 animate-pulse" />
|
||||||
|
<div className="h-10 w-2/5 rounded-lg bg-gray-600 animate-pulse" />
|
||||||
|
</div>
|
||||||
|
{/* Description */}
|
||||||
|
<div className="space-y-2 max-w-md">
|
||||||
|
<div className="h-4 w-full rounded bg-gray-700 animate-pulse" />
|
||||||
|
<div className="h-4 w-11/12 rounded bg-gray-700 animate-pulse" />
|
||||||
|
<div className="h-4 w-3/4 rounded bg-gray-700 animate-pulse" />
|
||||||
|
</div>
|
||||||
|
{/* CTA */}
|
||||||
|
<div className="h-12 w-40 rounded-full bg-red-900/40 animate-pulse" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -9,6 +9,11 @@ import Image from "next/image";
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useLocale, useTranslations } from "next-intl";
|
import { useLocale, useTranslations } from "next-intl";
|
||||||
import DotAnimatsiya from "@/components/dot/DotAnimatsiya";
|
import DotAnimatsiya from "@/components/dot/DotAnimatsiya";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import httpClient from "@/request/api";
|
||||||
|
import { endPoints } from "@/request/links";
|
||||||
|
import { BannerType } from "@/lib/types";
|
||||||
|
import { BannerSliderSkeleton } from "./loading";
|
||||||
// The custom CSS selectors for navigation
|
// The custom CSS selectors for navigation
|
||||||
const navigationPrevEl = ".hero-swiper-prev";
|
const navigationPrevEl = ".hero-swiper-prev";
|
||||||
const navigationNextEl = ".hero-swiper-next";
|
const navigationNextEl = ".hero-swiper-next";
|
||||||
@@ -16,6 +21,11 @@ const navigationNextEl = ".hero-swiper-next";
|
|||||||
export function BannerSlider() {
|
export function BannerSlider() {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const locale = useLocale();
|
const locale = useLocale();
|
||||||
|
const { data, isLoading } = useQuery({
|
||||||
|
queryKey: ["banner"],
|
||||||
|
queryFn: () => httpClient(endPoints.banner),
|
||||||
|
select: (data: any): BannerType[] => data?.data?.results,
|
||||||
|
});
|
||||||
const BANNER_DATA = [
|
const BANNER_DATA = [
|
||||||
{
|
{
|
||||||
image: "/images/homeBanner3.png",
|
image: "/images/homeBanner3.png",
|
||||||
@@ -28,6 +38,11 @@ export function BannerSlider() {
|
|||||||
description: t("home.banner.description"),
|
description: t("home.banner.description"),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const bannerData = data ?? BANNER_DATA;
|
||||||
|
|
||||||
|
if (isLoading) return <BannerSliderSkeleton />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-7xl mx-auto relative z-30 h-full mt-20 flex items-center justify-center ">
|
<div className="max-w-7xl mx-auto relative z-30 h-full mt-20 flex items-center justify-center ">
|
||||||
{/* Custom buttons */}
|
{/* Custom buttons */}
|
||||||
@@ -35,7 +50,7 @@ export function BannerSlider() {
|
|||||||
className={`${navigationPrevEl.replace(
|
className={`${navigationPrevEl.replace(
|
||||||
".",
|
".",
|
||||||
"",
|
"",
|
||||||
)} w-10 h-10 absolute z-10 left-[5%] top-[40vh] rounded-full p-0 bg-primary text-center text-white lg:flex hidden items-center justify-center hover:bg-red-600 hover:cursor-pointer transition`}
|
)} w-10 h-10 absolute z-10 left-0 top-[40vh] rounded-full p-0 bg-primary text-center text-white lg:flex hidden items-center justify-center hover:bg-red-600 hover:cursor-pointer transition`}
|
||||||
>
|
>
|
||||||
<ChevronLeft size={30} />
|
<ChevronLeft size={30} />
|
||||||
</button>
|
</button>
|
||||||
@@ -43,7 +58,7 @@ export function BannerSlider() {
|
|||||||
className={`${navigationNextEl.replace(
|
className={`${navigationNextEl.replace(
|
||||||
".",
|
".",
|
||||||
"",
|
"",
|
||||||
)} w-10 h-10 absolute z-10 right-[5%] top-[40vh] rounded-full bg-primary text-center text-white lg:flex hidden items-center justify-center hover:bg-red-600 hover:cursor-pointer transition `}
|
)} w-10 h-10 absolute z-10 right-0 top-[40vh] rounded-full bg-primary text-center text-white lg:flex hidden items-center justify-center hover:bg-red-600 hover:cursor-pointer transition `}
|
||||||
>
|
>
|
||||||
<ChevronRight size={30} />
|
<ChevronRight size={30} />
|
||||||
</button>
|
</button>
|
||||||
@@ -62,7 +77,7 @@ export function BannerSlider() {
|
|||||||
disableOnInteraction: false,
|
disableOnInteraction: false,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{BANNER_DATA.map((item, index) => (
|
{bannerData.map((item, index) => (
|
||||||
<SwiperSlide key={index}>
|
<SwiperSlide key={index}>
|
||||||
<div className="relative z-20 h-full flex items-center lg:mt-0 sm:mt-[10vh] mt-[5vh]">
|
<div className="relative z-20 h-full flex items-center lg:mt-0 sm:mt-[10vh] mt-[5vh]">
|
||||||
<div className="max-w-400 mx-auto px-4 sm:px-6 lg:px-8 w-full">
|
<div className="max-w-400 mx-auto px-4 sm:px-6 lg:px-8 w-full">
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ export function ServicePageServices() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("service page services: ", data);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-[#1e1d1c] py-10 md:py-16 lg:py-20 mb-15">
|
<div className="bg-[#1e1d1c] py-10 md:py-16 lg:py-20 mb-15">
|
||||||
<div className="max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8">
|
<div className="max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
|||||||
@@ -47,3 +47,10 @@ export interface NavbarItem {
|
|||||||
open_in_new_tab: boolean;
|
open_in_new_tab: boolean;
|
||||||
children: NavbarItem[];
|
children: NavbarItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface BannerType {
|
||||||
|
id: number;
|
||||||
|
image: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export const endPoints = {
|
|||||||
gallery: "gallery/?page_size=500",
|
gallery: "gallery/?page_size=500",
|
||||||
contact: "contact/",
|
contact: "contact/",
|
||||||
statistics: "statistics/",
|
statistics: "statistics/",
|
||||||
banner: "banner/",
|
banner: "banner/?page_size=500",
|
||||||
navbar:"navigationitem/?page_size=500",
|
navbar:"navigationitem/?page_size=500",
|
||||||
filter: {
|
filter: {
|
||||||
size: "size/",
|
size: "size/",
|
||||||
|
|||||||
Reference in New Issue
Block a user