loading and catalog card
This commit is contained in:
@@ -135,4 +135,6 @@ body {
|
||||
background: #1e1d1c;
|
||||
}
|
||||
|
||||
|
||||
.loio{
|
||||
color:#8b1515, #c91d1d
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import { NextIntlClientProvider } from "next-intl";
|
||||
import { getMessages } from "next-intl/server";
|
||||
import BackAnimatsiya from "@/components/backAnimatsiya/backAnimatsiya";
|
||||
import { PriceModal } from "@/components/priceContact";
|
||||
import PageTransition from "@/components/pageTransition/pageTransition";
|
||||
import { InitialLoading } from "@/components/initialLoading/initialLoading";
|
||||
|
||||
const geistSans = Geist({
|
||||
variable: "--font-geist-sans",
|
||||
@@ -57,12 +59,13 @@ export default async function RootLayout({
|
||||
<body
|
||||
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
||||
>
|
||||
<InitialLoading />
|
||||
<NextIntlClientProvider messages={messages} locale={locale}>
|
||||
<BackAnimatsiya />
|
||||
<Navbar />
|
||||
{children}
|
||||
<Footer />
|
||||
<PriceModal />
|
||||
<PriceModal />
|
||||
<Analytics />
|
||||
</NextIntlClientProvider>
|
||||
</body>
|
||||
|
||||
117
components/initialLoading/initialLoading.css
Normal file
117
components/initialLoading/initialLoading.css
Normal file
@@ -0,0 +1,117 @@
|
||||
.initial-loading {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: linear-gradient(135deg, #0c0c0c 0%, #151313 100%);
|
||||
z-index: 99999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 1;
|
||||
transition: opacity 0.6s ease-out;
|
||||
}
|
||||
|
||||
.initial-loading.fade-out {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.initial-loading-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.initial-svg {
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
animation: initialFloat 2s ease-in-out infinite, initialScale 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.initial-path {
|
||||
fill: url(#initial-gradient);
|
||||
filter: url(#initial-glow);
|
||||
stroke: #ffffff;
|
||||
stroke-width: 2;
|
||||
animation: pathPulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Loading dots animation */
|
||||
.initial-loading-text {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.loading-dots {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.loading-dots span {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background: #ff0000;
|
||||
border-radius: 50%;
|
||||
animation: dotBounce 1.4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.loading-dots span:nth-child(1) {
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.loading-dots span:nth-child(2) {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.loading-dots span:nth-child(3) {
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes initialFloat {
|
||||
0%, 100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-30px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes initialScale {
|
||||
0%, 100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pathPulse {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
stroke-width: 2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.7;
|
||||
stroke-width: 3;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dotBounce {
|
||||
0%, 80%, 100% {
|
||||
transform: scale(0);
|
||||
opacity: 0.5;
|
||||
}
|
||||
40% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Smooth scroll prevention */
|
||||
body:has(.initial-loading:not(.fade-out)) {
|
||||
overflow: hidden;
|
||||
}
|
||||
106
components/initialLoading/initialLoading.tsx
Normal file
106
components/initialLoading/initialLoading.tsx
Normal file
@@ -0,0 +1,106 @@
|
||||
"use client";
|
||||
import { useState, useEffect } from "react";
|
||||
import "./initialLoading.css";
|
||||
|
||||
export function InitialLoading() {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isVisible, setIsVisible] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
// Faqat birinchi yuklanishda ishga tushadi
|
||||
const hasVisited = sessionStorage.getItem("hasVisited");
|
||||
|
||||
if (hasVisited) {
|
||||
// Agar oldin tashrif buyurilgan bo'lsa, darhol yashirish
|
||||
setIsLoading(false);
|
||||
setIsVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Birinchi tashrif
|
||||
const loadingTimer = setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
|
||||
// Fade out animatsiyasi
|
||||
const hideTimer = setTimeout(() => {
|
||||
setIsVisible(false);
|
||||
sessionStorage.setItem("hasVisited", "true");
|
||||
}, 1000); // Fade out duration
|
||||
|
||||
return () => clearTimeout(hideTimer);
|
||||
}, 1500); // Loading duration
|
||||
|
||||
return () => clearTimeout(loadingTimer);
|
||||
}, []);
|
||||
|
||||
// Agar ko'rinmas bo'lsa, hech narsa render qilmaymiz
|
||||
if (!isVisible) return null;
|
||||
|
||||
return (
|
||||
<div className={`initial-loading ${!isLoading ? "fade-out" : ""}`}>
|
||||
<div className="initial-loading-content">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 423.22 424.82"
|
||||
className="w-full h-full"
|
||||
>
|
||||
<defs>
|
||||
{/* Qizil neon gradient for github*/}
|
||||
<linearGradient id="neon-gradient" x1="0%" y1="100%" x2="100%" y2="0%">
|
||||
<stop offset="0%" stopColor="#979797" />
|
||||
<stop offset="50%" stopColor="#e4e4e4" />
|
||||
<stop offset="100%" stopColor="#9a9a9a" />
|
||||
</linearGradient>
|
||||
|
||||
{/* Neon glow filter */}
|
||||
<filter id="neon-glow">
|
||||
<feGaussianBlur stdDeviation="3" result="coloredBlur"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="coloredBlur"/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<g>
|
||||
<polygon
|
||||
className="logo-path"
|
||||
points="352.86 365.08 347.11 365.08 347.11 381 289.38 381 289.38 365.08 283.63 365.08 283.63 381 204.78 381 204.78 365.08 199.03 365.08 199.03 381 141.32 381 141.32 365.08 135.57 365.08 135.57 381 77.87 381 77.87 365.08 71.86 365.08 71.85 381 17.21 381 17.21 386.74 72.11 386.74 72.11 424.82 74.04 424.82 74.04 386.74 350.94 386.74 350.94 424.82 352.86 424.82 352.86 386.74 406.02 386.74 406.02 381 352.86 381 352.86 365.08"
|
||||
/>
|
||||
<path
|
||||
className="logo-path"
|
||||
d="m72.11,157.74v73.55l-41.42,23.89h3.83l37.58-21.68-.04,21.68h5.79v-24.99l57.7-33.27v58.26h5.75v-57.15l57.71-33.29v90.44h5.75v-90.43l39.43,22.77,39.43,22.77v44.89h5.74v-41.58l57.73,33.32v8.25h5.75v-95.41h-1.92v82.75l-61.56-35.55v-98.77l59.59-34.35-.97-1.66-58.62,33.81V0h-1.92v42.86h-88.43v115.23l-5.2,3-14.21,8.16-27.25,15.74-11.05,6.37v-73.53l36.14-20.85-.96-1.66-35.19,20.29v-35.03h-1.92v36.13l-65.36,37.7v-37.25h-1.92v38.35l-53.08,30.6.96,1.67,52.12-30.07ZM204.78,48.58h78.85v60.71l-78.85,45.48V48.58Zm0,108.41l78.85-45.49v92.14l-78.85-45.54v-1.11Zm-126.91,1.92l57.7-33.32v69.11l-57.7,33.26v-69.05Z"
|
||||
/>
|
||||
<g>
|
||||
<rect className="logo-path" y="277.99" width="12.06" height="64.23" />
|
||||
<path
|
||||
className="logo-path"
|
||||
d="m88.82,342.36c3.93-.65,7.51-1.73,10.75-3.23,3.24-1.5,6.01-3.46,8.32-5.89l1.31,8.97h7.76v-35.25h-39.45v9.72h27.58v1.03c0,3.12-.94,5.84-2.8,8.18-1.87,2.34-4.81,4.13-8.83,5.38-4.02,1.25-9.3,1.87-15.85,1.87-5.49,0-10.28-.73-14.4-2.2-4.11-1.46-7.32-3.8-9.63-7.01-2.31-3.21-3.46-7.46-3.46-12.76v-2.24c0-3.93.75-7.28,2.24-10.05,1.5-2.77,3.58-5.03,6.26-6.78,2.68-1.74,5.8-3.02,9.35-3.83,3.55-.81,7.39-1.21,11.5-1.21,3.37,0,6.56.2,9.58.61,3.02.41,5.75,1.11,8.18,2.1,2.43,1,4.35,2.38,5.75,4.16,1.4,1.78,2.1,3.97,2.1,6.59h11.78c0-4.05-.89-7.56-2.66-10.52-1.78-2.96-4.33-5.41-7.67-7.34-3.33-1.93-7.32-3.38-11.97-4.35-4.64-.97-9.83-1.45-15.57-1.45-8.6,0-15.99,1.25-22.16,3.74-6.17,2.49-10.89,6.22-14.16,11.17-3.27,4.95-4.91,11.08-4.91,18.37,0,11.16,3.23,19.48,9.68,24.96,6.45,5.49,16.16,8.23,29.12,8.23,4.24,0,8.32-.33,12.25-.98Z"
|
||||
/>
|
||||
<path
|
||||
className="logo-path"
|
||||
d="m160.8,299.31c1.68,1.81,3.3,3.49,4.86,5.05l37.96,37.86h11.12v-64.23h-11.59v37.02c0,1.31.03,2.9.09,4.77.06,1.87.12,3.43.19,4.68h-.75c-.75-.87-1.67-1.87-2.76-2.99-1.09-1.12-2.15-2.23-3.18-3.32-1.03-1.09-1.92-1.98-2.66-2.66l-37.86-37.49h-11.5v64.23h11.59v-36.37c0-2.31-.02-4.46-.05-6.45-.03-1.99-.08-3.46-.14-4.39h.65c1,1.06,2.34,2.49,4.02,4.3Z"
|
||||
/>
|
||||
<path
|
||||
className="logo-path"
|
||||
d="m242.6,277.99v35.34c0,6.11,1.26,11.42,3.79,15.94,2.52,4.52,6.36,7.99,11.5,10.42,5.14,2.43,11.64,3.65,19.49,3.65s14.33-1.21,19.45-3.65c5.11-2.43,8.93-5.9,11.45-10.42,2.52-4.52,3.79-9.83,3.79-15.94v-35.34h-12.06v34.97c0,6.48-1.96,11.47-5.89,14.96-3.93,3.49-9.5,5.23-16.73,5.23s-12.89-1.74-16.78-5.23c-3.9-3.49-5.84-8.48-5.84-14.96v-34.97h-12.15Z"
|
||||
/>
|
||||
<path
|
||||
className="logo-path"
|
||||
d="m404.99,277.99l-17.2,37.02c-.5,1.12-1.11,2.51-1.82,4.16-.72,1.65-1.42,3.32-2.1,5-.69,1.68-1.31,3.18-1.87,4.49h-.56c-.62-1.5-1.3-3.12-2.01-4.86-.72-1.74-1.42-3.44-2.1-5.1-.69-1.65-1.25-2.94-1.68-3.88l-17.2-36.83h-18.51v64.23h11.59v-40.29c0-1.31-.02-2.67-.05-4.07-.03-1.4-.06-2.76-.09-4.07-.03-1.31-.08-2.4-.14-3.27h.75c.31.81.67,1.79,1.07,2.94.4,1.15.89,2.37,1.45,3.65.56,1.28,1.12,2.51,1.68,3.69l19.26,41.42h11.87l19.17-41.42c.43-.94.92-2.02,1.45-3.27.53-1.25,1.04-2.49,1.54-3.74.5-1.25.9-2.34,1.22-3.27h.75c-.06,1-.13,2.18-.19,3.55-.06,1.37-.11,2.74-.14,4.11-.03,1.37-.05,2.62-.05,3.74v40.29h12.15v-64.23h-18.23Z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
{/* Loading dots */}
|
||||
<div className="initial-loading-text">
|
||||
<div className="loading-dots">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import "./logo.css";
|
||||
|
||||
export default function NavbarLogo() {
|
||||
return (
|
||||
<div className="relative w-24 h-12">
|
||||
<div className="relative w-24 h-20">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 423.22 424.82"
|
||||
|
||||
@@ -3,19 +3,35 @@ import { usePathname } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import "./page-transition.css";
|
||||
|
||||
export default function PageTransition({ children }: { children: React.ReactNode }) {
|
||||
export default function PageTransition({
|
||||
children
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
const pathname = usePathname();
|
||||
const [displayPath, setDisplayPath] = useState(pathname);
|
||||
const [isTransitioning, setIsTransitioning] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setIsTransitioning(true);
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
setIsTransitioning(false);
|
||||
}, 1500); // Animatsiya davomiyligi
|
||||
if (pathname !== displayPath) {
|
||||
// Start exit animation
|
||||
setIsTransitioning(true);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, [pathname]);
|
||||
const exitTimer = setTimeout(() => {
|
||||
// Update path (triggers content change)
|
||||
setDisplayPath(pathname);
|
||||
|
||||
// Start enter animation
|
||||
const enterTimer = setTimeout(() => {
|
||||
setIsTransitioning(false);
|
||||
}, 800); // Enter animation duration
|
||||
|
||||
return () => clearTimeout(enterTimer);
|
||||
}, 800); // Exit animation duration
|
||||
|
||||
return () => clearTimeout(exitTimer);
|
||||
}
|
||||
}, [pathname, displayPath]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -32,7 +48,6 @@ export default function PageTransition({ children }: { children: React.ReactNode
|
||||
<stop offset="50%" stopColor="#ff4444" />
|
||||
<stop offset="100%" stopColor="#ff0000" />
|
||||
</linearGradient>
|
||||
|
||||
<filter id="transition-glow">
|
||||
<feGaussianBlur stdDeviation="5" result="coloredBlur"/>
|
||||
<feMerge>
|
||||
@@ -53,7 +68,7 @@ export default function PageTransition({ children }: { children: React.ReactNode
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
|
||||
{/* Page content */}
|
||||
<div className={`page-content ${isTransitioning ? "transitioning" : ""}`}>
|
||||
{children}
|
||||
|
||||
@@ -69,20 +69,20 @@ export default function CatalogCard({
|
||||
return (
|
||||
<Link
|
||||
href={`/${locale}/products?category=${id}`}
|
||||
className="group relative h-[450px] w-full overflow-hidden rounded-2xl bg-linear-to-br from-[#444242] to-black border border-white/10 transition-all duration-500 hover:border-red-500/50 hover:-translate-y-1"
|
||||
className="group relative h-112.5 w-full overflow-hidden rounded-2xl bg-[#17161679] from-[#444242] to-black border hover:border-red-700 border-white/10 transition-all duration-500 hover:-translate-y-1"
|
||||
>
|
||||
{/* Background glow effect */}
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-red-600/20 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||
<div className="absolute inset-0 bg-linear-to-t from-red-600/20 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||
|
||||
{/* Decorative corner accent */}
|
||||
<div className="absolute top-0 right-0 w-24 h-24 bg-gradient-to-br from-red-500/20 to-transparent rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||
<div className="absolute top-0 right-0 w-24 h-24 bg-linear-to-br from-red-500/20 to-transparent rounded-bl-full opacity-0 group-hover:opacity-00 transition-opacity duration-500" />
|
||||
|
||||
{/* Content container */}
|
||||
<div className="relative h-full flex flex-col p-6">
|
||||
{/* Title section */}
|
||||
<div className="mb-4">
|
||||
<div className="flex items-start justify-between mb-2">
|
||||
<h3 className="text-2xl font-unbounded font-bold text-white leading-tight group-hover:text-red-400 transition-colors duration-300">
|
||||
<h3 className="text-2xl font-unbounded font-bold text-white leading-tight transition-colors duration-300">
|
||||
{title}
|
||||
</h3>
|
||||
<div className="shrink-0 w-8 h-8 rounded-full bg-white/10 flex items-center justify-center group-hover:bg-red-500 transition-all duration-300 group-hover:scale-110">
|
||||
@@ -97,9 +97,9 @@ export default function CatalogCard({
|
||||
</div>
|
||||
|
||||
{/* Image container with elegant frame */}
|
||||
<div className="relative flex-1 rounded-xl overflow-hidden bg-gradient-to-br from-[#444242] to-gray-900/50 border border-white/5 group-hover:border-white/20 transition-all duration-500">
|
||||
<div className="relative flex-1 rounded-xl overflow-hidden bg-linear-to-br from-[#444242] to-gray-900/50 border border-white/5 group-hover:border-white/20 transition-all duration-500">
|
||||
{/* Animated gradient overlay */}
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent z-10" />
|
||||
<div className="absolute inset-0 bg-linear-to-t from-black/60 via-transparent to-transparent z-10" />
|
||||
|
||||
{/* Image */}
|
||||
<div className="relative w-full h-full">
|
||||
@@ -118,7 +118,7 @@ export default function CatalogCard({
|
||||
</div>
|
||||
|
||||
{/* Bottom accent bar */}
|
||||
<div className="mt-4 h-1 w-0 bg-gradient-to-r from-red-500 to-red-600 group-hover:w-full transition-all duration-500 rounded-full" />
|
||||
<div className="mt-4 h-1 w-0 bg-linear-to-r from-red-500 to-red-600 group-hover:w-full transition-all duration-500 rounded-full" />
|
||||
</div>
|
||||
|
||||
{/* Subtle noise texture overlay */}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
},
|
||||
"about": {
|
||||
"title": "About us",
|
||||
"subtitle": "Fire Protection Systems Ready",
|
||||
"subtitle": "Fire Protection Systems",
|
||||
"prevention": {
|
||||
"title": "Fire Prevention Systems",
|
||||
"description": "We offer the most advanced fire prevention technologies. Every detail is designed to ensure safety and reliability."
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"banner": {
|
||||
"title1": "Ignum-ga xush kelibsiz",
|
||||
"title2": "YONG'INGA QARSHI HIMOYA",
|
||||
"description": "Biz umid nuri, tartibsizlik davrida tinchlik va eng qiyin vaziyatlarda ishonchli himoya manbai sifatida ko'rilamiz.",
|
||||
"description": "Biz yong‘in xavfsizligi tizimlarini o‘rnatish va sertifikatlangan himoya vositalari savdosi bo‘yicha professional xizmatlar ko‘rsatamiz.",
|
||||
"cta": "Boshlash"
|
||||
},
|
||||
"statistics": {
|
||||
@@ -14,7 +14,7 @@
|
||||
},
|
||||
"about": {
|
||||
"title": "Biz haqimizda",
|
||||
"subtitle": "YONG'INGA QARSHI TIZIMLAR TAYYOR",
|
||||
"subtitle": "YONG'INGA QARSHI TIZIMLAR",
|
||||
"prevention": {
|
||||
"title": "YONG'INDI OLDINI OLISH TIZIMLARI",
|
||||
"description": "Biz eng ilg'or yong'in oldini olish texnologiyalarini taklif etamiz. Har bir detal xavfsizlik va ishonchlilikni ta'minlash uchun ishlab chiqilgan."
|
||||
@@ -177,7 +177,7 @@
|
||||
"answer": "Biz muntazam texnik xizmat ko'rsatish va 24/7 favqulodda xizmatni taklif etamiz. Har olti oyda bir marta profilaktik tekshiruvlar o'tkaziladi."
|
||||
},
|
||||
"question4": {
|
||||
"question": "Kafolatiy muddati qancha?",
|
||||
"question": "Kafolat muddati qancha?",
|
||||
"answer": "Barcha uskunalarimiz uchun 2 yillik kafolat va 10 yillik texnik xizmat ko'rsatish kafolati beriladi."
|
||||
},
|
||||
"question5": {
|
||||
|
||||
Reference in New Issue
Block a user