change blog sectio from home page

This commit is contained in:
nabijonovdavronbek619@gmail.com
2026-01-28 12:25:06 +05:00
parent 29e06be337
commit ce8d14c9b2
10 changed files with 110 additions and 27 deletions

23
components/Counter.tsx Normal file
View File

@@ -0,0 +1,23 @@
"use client";
import { useEffect, useState } from "react";
import { animate, motion, useMotionValue, useTransform } from "framer-motion";
export function Counter({ countNum }: { countNum: number }) {
const count = useMotionValue(0);
const rounded = useTransform(count, (latest:any) => Math.round(latest));
const [displayValue, setDisplayValue] = useState(0);
useEffect(() => {
const controls = animate(count, countNum, {
duration: 2,
ease: "easeOut",
onUpdate: (latest:any) => {
setDisplayValue(Math.round(latest));
},
});
return () => controls.stop();
}, [countNum]); // countNum dependency qo'shildi
return <motion.span>{displayValue}</motion.span>;
}

View File

@@ -2,6 +2,7 @@ import Image from "next/image";
import { ChevronRight } from "lucide-react"; import { ChevronRight } from "lucide-react";
import DotAnimatsiya from "@/components/dot/DotAnimatsiya"; import DotAnimatsiya from "@/components/dot/DotAnimatsiya";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import ProductCard from "../products/productCard";
export function Blog() { export function Blog() {
const t = useTranslations(); const t = useTranslations();
@@ -40,22 +41,22 @@ export function Blog() {
<div className="mb-4 flex items-center justify-center gap-2"> <div className="mb-4 flex items-center justify-center gap-2">
<DotAnimatsiya /> <DotAnimatsiya />
<span className="font-almarai text-sm font-semibold tracking-wider text-white uppercase"> <span className="font-almarai text-sm font-semibold tracking-wider text-white uppercase">
{t("home.blog.title")} {t("products.banner.title")}
</span> </span>
</div> </div>
<h2 <h2
className="font-unbounded bg-linear-to-br from-white via-white to-black className="font-unbounded bg-linear-to-br from-white py-2 via-white to-black
text-transparent bg-clip-text text-4xl font-bold tracking-tight md:text-5xl lg:text-6xl" text-transparent bg-clip-text text-4xl font-bold tracking-tight md:text-5xl lg:text-6xl"
> >
{t("home.blog.subtitle")} {t("products.ourproducts")}
</h2> </h2>
</div> </div>
{/* Blog Cards Grid */} {/* Blog Cards Grid */}
<div className="grid gap-8 md:grid-cols-2 lg:grid-cols-3 max-sm:place-items-center"> <div className="grid gap-8 md:grid-cols-2 lg:grid-cols-3 max-sm:place-items-center">
{blogPosts.map((post) => ( {/* {blogPosts.map((post) => (
<article key={post.id} className="group"> <article key={post.id} className="group">
{/* Image Container */}
<div className="relative mb-6 aspect-4/2 md:aspect-4/3 overflow-hidden rounded-lg"> <div className="relative mb-6 aspect-4/2 md:aspect-4/3 overflow-hidden rounded-lg">
<Image <Image
src={post.image || "/placeholder.svg"} src={post.image || "/placeholder.svg"}
@@ -63,7 +64,7 @@ export function Blog() {
fill fill
className="object-cover transition-transform duration-300 group-hover:scale-105" className="object-cover transition-transform duration-300 group-hover:scale-105"
/> />
{/* Category Badge */}
<div className="absolute bottom-4 left-4"> <div className="absolute bottom-4 left-4">
<span className="font-almarai rounded bg-red-600 px-4 py-2 text-sm font-medium text-white"> <span className="font-almarai rounded bg-red-600 px-4 py-2 text-sm font-medium text-white">
{post.category} {post.category}
@@ -71,7 +72,6 @@ export function Blog() {
</div> </div>
</div> </div>
{/* Content */}
<div> <div>
<h3 className="font-unbounded uppercase mb-3 text-lg font-bold leading-tight tracking-wide text-white md:text-xl"> <h3 className="font-unbounded uppercase mb-3 text-lg font-bold leading-tight tracking-wide text-white md:text-xl">
{post.title} {post.title}
@@ -91,7 +91,19 @@ export function Blog() {
</a> </a>
</div> </div>
</article> </article>
))} ))} */}
{Array(3)
.fill(null)
.map((_, index) => (
<ProductCard
key={index}
title="Elektr yong'in detektori-Ypres ver.2"
name="P-0834404"
image="/images/products/products.webp"
slug="P_0834404"
status="full"
/>
))}
</div> </div>
</div> </div>
</section> </section>

View File

@@ -1,26 +1,27 @@
import { Counter } from "@/components/Counter";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
export function Statistics() { export function Statistics() {
const t = useTranslations(); const t = useTranslations();
const stats = [ const stats = [
{ {
number: '25', number: "25",
symbol: '+', symbol: "+",
label: t("home.statistics.experience"), label: t("home.statistics.experience"),
}, },
{ {
number: '450', number: "450",
symbol: '+', symbol: "+",
label: t("home.statistics.projectsCompleted"), label: t("home.statistics.projectsCompleted"),
}, },
{ {
number: '99', number: "99",
symbol: '+', symbol: "+",
label: t("home.statistics.trainedSpecialists"), label: t("home.statistics.trainedSpecialists"),
}, },
{ {
number: '93', number: "93",
symbol: '%', symbol: "%",
label: t("home.statistics.trustedClients"), label: t("home.statistics.trustedClients"),
}, },
]; ];
@@ -30,13 +31,18 @@ export function Statistics() {
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-2 md:grid-cols-4 gap-8 lg:gap-12"> <div className="grid grid-cols-2 md:grid-cols-4 gap-8 lg:gap-12">
{stats.map((stat, index) => ( {stats.map((stat, index) => (
<div key={index} className="flex flex-col items-center justify-center py-10 sm:py-20 lg:py-15 border-b-red-600 border-b"> <div
key={index}
className="flex flex-col items-center justify-center py-10 sm:py-20 lg:py-15 border-b-red-600 border-b"
>
{/* Number and Symbol */} {/* Number and Symbol */}
<div className="flex items-baseline gap-2 font-almarai"> <div className="flex items-baseline gap-2 font-almarai">
<span className="text-4xl sm:text-5xl lg:text-6xl font-bold text-white"> <span className="text-4xl sm:text-5xl lg:text-6xl font-bold text-white">
{stat.number} <Counter countNum={Number(stat.number)} />
</span>
<span className="text-4xl sm:text-5xl lg:text-6xl font-bold text-red-600">
{stat.symbol}
</span> </span>
<span className="text-4xl sm:text-5xl lg:text-6xl font-bold text-red-600">{stat.symbol}</span>
</div> </div>
{/* Label */} {/* Label */}

View File

@@ -28,18 +28,18 @@ export function ProductBanner() {
<div className="spacw-y-4 "> <div className="spacw-y-4 ">
<div className="flex items-center gap-2 w-fit"> <div className="flex items-center gap-2 w-fit">
<DotAnimatsiya /> <DotAnimatsiya />
<span className="text-sm font-semibold tracking-wide"> <span className="font-almarai text-white text-sm font-semibold tracking-wide">
{t("products.banner.title")} {t("products.banner.title")}
</span> </span>
</div> </div>
<p <p
className=" bg-linear-to-br from-white via-white to-black className="font-unbounded uppercase bg-linear-to-br from-white via-white to-black
text-transparent bg-clip-text text-4xl sm:text-5xl lg:text-6xl font-bold leading-tight text-pretty" text-transparent bg-clip-text text-3xl sm:text-4xl lg:text-5xl font-bold leading-tight text-pretty"
> >
{t("products.banner.subtitle")} {t("products.banner.subtitle")}
</p> </p>
</div> </div>
<div className="lg:w-[40%] text-gray-300 lg:mt-20 md:mt-10 sm:mt-5 "> <div className="font-almarai lg:w-[40%] text-gray-300 lg:mt-20 md:mt-10 sm:mt-5 ">
{t("products.banner.description")} {t("products.banner.description")}
</div> </div>
</div> </div>

View File

@@ -36,7 +36,7 @@ export default function ProductCard({
<Link href={`/products/${slug}`}> <Link href={`/products/${slug}`}>
<article className="group transition-all duration-300 hover:cursor-pointer max-sm:max-w-100 max-sm:mx-auto max-sm:w-full "> <article className="group transition-all duration-300 hover:cursor-pointer max-sm:max-w-100 max-sm:mx-auto max-sm:w-full ">
{/* Image Container */} {/* Image Container */}
<div className="relative rounded-2xl h-45 sm:h-55 md:h-65 lg:w-70 w-[90%] mx-auto overflow-hidden bg-white"> <div className="relative rounded-2xl h-45 sm:h-55 md:h-65 lg:w-[95%] w-[90%] mx-auto overflow-hidden bg-white">
<Image <Image
src={image || "/placeholder.svg"} src={image || "/placeholder.svg"}
alt={title} alt={title}

View File

@@ -150,7 +150,8 @@
"title": "Products", "title": "Products",
"subtitle": "Ignum Technology Ready", "subtitle": "Ignum Technology Ready",
"description": "We not only supply equipment but become a successful partner for every client." "description": "We not only supply equipment but become a successful partner for every client."
} },
"ourproducts": "Our Products"
}, },
"faq": { "faq": {
"banner": { "banner": {

View File

@@ -150,7 +150,8 @@
"title": "Продукты", "title": "Продукты",
"subtitle": "Технология Ignum Готова", "subtitle": "Технология Ignum Готова",
"description": "Мы не просто поставляем оборудование, мы становимся успешным партнером для каждого клиента." "description": "Мы не просто поставляем оборудование, мы становимся успешным партнером для каждого клиента."
} },
"ourproducts": "Наши продукты"
}, },
"faq": { "faq": {
"banner": { "banner": {

View File

@@ -150,7 +150,8 @@
"title": "Mahsulotlar", "title": "Mahsulotlar",
"subtitle": "Ignum Texnologiyasi Tayyor", "subtitle": "Ignum Texnologiyasi Tayyor",
"description": "Biz nafaqat uskunalar yetkazib beramiz, balki har bir mijozning muvaffaqiyatli hamkoriga aylanamiz." "description": "Biz nafaqat uskunalar yetkazib beramiz, balki har bir mijozning muvaffaqiyatli hamkoriga aylanamiz."
} },
"ourproducts":"Bizning mahsulotlarimiz"
}, },
"faq": { "faq": {
"banner": { "banner": {

View File

@@ -45,6 +45,7 @@
"cmdk": "1.0.4", "cmdk": "1.0.4",
"date-fns": "4.1.0", "date-fns": "4.1.0",
"embla-carousel-react": "8.5.1", "embla-carousel-react": "8.5.1",
"framer-motion": "^12.29.2",
"input-otp": "1.4.1", "input-otp": "1.4.1",
"lucide-react": "^0.454.0", "lucide-react": "^0.454.0",
"negotiator": "^1.0.0", "negotiator": "^1.0.0",

38
pnpm-lock.yaml generated
View File

@@ -116,6 +116,9 @@ importers:
embla-carousel-react: embla-carousel-react:
specifier: 8.5.1 specifier: 8.5.1
version: 8.5.1(react@19.2.0) version: 8.5.1(react@19.2.0)
framer-motion:
specifier: ^12.29.2
version: 12.29.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
input-otp: input-otp:
specifier: 1.4.1 specifier: 1.4.1
version: 1.4.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) version: 1.4.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
@@ -1567,6 +1570,20 @@ packages:
fraction.js@5.3.4: fraction.js@5.3.4:
resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
framer-motion@12.29.2:
resolution: {integrity: sha512-lSNRzBJk4wuIy0emYQ/nfZ7eWhqud2umPKw2QAQki6uKhZPKm2hRQHeQoHTG9MIvfobb+A/LbEWPJU794ZUKrg==}
peerDependencies:
'@emotion/is-prop-valid': '*'
react: ^18.0.0 || ^19.0.0
react-dom: ^18.0.0 || ^19.0.0
peerDependenciesMeta:
'@emotion/is-prop-valid':
optional: true
react:
optional: true
react-dom:
optional: true
get-nonce@1.0.1: get-nonce@1.0.1:
resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -1687,6 +1704,12 @@ packages:
magic-string@0.30.21: magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
motion-dom@12.29.2:
resolution: {integrity: sha512-/k+NuycVV8pykxyiTCoFzIVLA95Nb1BFIVvfSu9L50/6K6qNeAYtkxXILy/LRutt7AzaYDc2myj0wkCVVYAPPA==}
motion-utils@12.29.2:
resolution: {integrity: sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==}
nanoid@3.3.11: nanoid@3.3.11:
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@@ -3251,6 +3274,15 @@ snapshots:
fraction.js@5.3.4: {} fraction.js@5.3.4: {}
framer-motion@12.29.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0):
dependencies:
motion-dom: 12.29.2
motion-utils: 12.29.2
tslib: 2.8.1
optionalDependencies:
react: 19.2.0
react-dom: 19.2.0(react@19.2.0)
get-nonce@1.0.1: {} get-nonce@1.0.1: {}
graceful-fs@4.2.11: {} graceful-fs@4.2.11: {}
@@ -3342,6 +3374,12 @@ snapshots:
dependencies: dependencies:
'@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/sourcemap-codec': 1.5.5
motion-dom@12.29.2:
dependencies:
motion-utils: 12.29.2
motion-utils@12.29.2: {}
nanoid@3.3.11: {} nanoid@3.3.11: {}
negotiator@1.0.0: {} negotiator@1.0.0: {}