bug fixed

This commit is contained in:
Samandar Turgunboyev
2026-03-05 14:57:34 +05:00
parent 95d17b274f
commit 35374094eb
3 changed files with 72 additions and 28 deletions

View File

@@ -81,16 +81,18 @@ const ProductDetail = () => {
? 0 ? 0
: Number(String(quantity).replace(',', '.')); : Number(String(quantity).replace(',', '.'));
/* ---------------- HELPERS ---------------- */
const clampQuantity = (value: number) => { const clampQuantity = (value: number) => {
if (isNaN(value)) return MIN_QTY; if (isNaN(value)) return MIN_QTY;
let safe = Math.max(value, MIN_QTY); let safe = value;
safe = Math.min(safe);
if (isGram) {
safe = Math.max(value, MIN_QTY);
safe = Math.ceil(safe / STEP) * STEP;
}
return safe; return safe;
}; };
const getQuantityMessage = (qty: number, measurement: string | null) => { const getQuantityMessage = (qty: number, measurement: string | null) => {
if (!measurement) return `${qty} dona`; if (!measurement) return `${qty} dona`;
return `${qty} ${measurement}`; return `${qty} ${measurement}`;

View File

@@ -3,12 +3,14 @@
import { useRouter } from '@/shared/config/i18n/navigation'; import { useRouter } from '@/shared/config/i18n/navigation';
import { cn } from '@/shared/lib/utils'; import { cn } from '@/shared/lib/utils';
import { Button } from '@/shared/ui/button'; import { Button } from '@/shared/ui/button';
import { Card } from '@/shared/ui/card';
import { import {
Carousel, Carousel,
CarouselContent, CarouselContent,
CarouselItem, CarouselItem,
type CarouselApi, type CarouselApi,
} from '@/shared/ui/carousel'; } from '@/shared/ui/carousel';
import { Skeleton } from '@/shared/ui/skeleton';
import { ProductCard } from '@/widgets/categories/ui/product-card'; import { ProductCard } from '@/widgets/categories/ui/product-card';
import { ProductRes } from '@/widgets/welcome/lib/api'; import { ProductRes } from '@/widgets/welcome/lib/api';
import { ChevronLeft, ChevronRight } from 'lucide-react'; import { ChevronLeft, ChevronRight } from 'lucide-react';
@@ -20,11 +22,13 @@ import { memo, useEffect, useRef, useState } from 'react';
interface CategoryCarouselProps { interface CategoryCarouselProps {
category: ProductRes; category: ProductRes;
isLoading: boolean; isLoading: boolean;
isError: boolean;
} }
const CategoryCarousel = memo(function CategoryCarousel({ const CategoryCarousel = memo(function CategoryCarousel({
category, category,
isLoading, isLoading,
isError,
}: CategoryCarouselProps) { }: CategoryCarouselProps) {
const router = useRouter(); const router = useRouter();
const [api, setApi] = useState<CarouselApi>(); const [api, setApi] = useState<CarouselApi>();
@@ -36,7 +40,6 @@ const CategoryCarousel = memo(function CategoryCarousel({
// Intersection Observer // Intersection Observer
useEffect(() => { useEffect(() => {
if (!sectionRef.current) return; if (!sectionRef.current) return;
const observer = new IntersectionObserver( const observer = new IntersectionObserver(
(entries) => { (entries) => {
entries.forEach((entry) => { entries.forEach((entry) => {
@@ -48,7 +51,6 @@ const CategoryCarousel = memo(function CategoryCarousel({
}, },
{ rootMargin: '100px', threshold: 0.1 }, { rootMargin: '100px', threshold: 0.1 },
); );
observer.observe(sectionRef.current); observer.observe(sectionRef.current);
return () => observer.disconnect(); return () => observer.disconnect();
}, []); }, []);
@@ -72,7 +74,6 @@ const CategoryCarousel = memo(function CategoryCarousel({
const scrollPrev = () => api?.scrollPrev(); const scrollPrev = () => api?.scrollPrev();
const scrollNext = () => api?.scrollNext(); const scrollNext = () => api?.scrollNext();
// Shartli renderlar
if (!isVisible) { if (!isVisible) {
return ( return (
<section <section
@@ -82,11 +83,8 @@ const CategoryCarousel = memo(function CategoryCarousel({
); );
} }
if (!isLoading && !category) return null;
const activeProducts = const activeProducts =
category?.products.filter((p) => p.state === 'A') ?? []; category?.products?.filter((p) => p.state === 'A') ?? [];
if (!isLoading && activeProducts.length === 0) return null;
return ( return (
<section <section
@@ -99,7 +97,7 @@ const CategoryCarousel = memo(function CategoryCarousel({
onClick={() => router.push(`/category/${category.id}/`)} onClick={() => router.push(`/category/${category.id}/`)}
> >
<h2 className="text-2xl font-bold text-slate-800 group-hover:text-blue-600 transition-colors"> <h2 className="text-2xl font-bold text-slate-800 group-hover:text-blue-600 transition-colors">
{category.name} {category.name || '---'}
</h2> </h2>
<div className="p-1.5 bg-slate-100 rounded-full group-hover:bg-blue-100 transition-all"> <div className="p-1.5 bg-slate-100 rounded-full group-hover:bg-blue-100 transition-all">
<ChevronRight className="text-slate-600 group-hover:text-blue-600 group-hover:translate-x-0.5 transition-all" /> <ChevronRight className="text-slate-600 group-hover:text-blue-600 group-hover:translate-x-0.5 transition-all" />
@@ -108,15 +106,26 @@ const CategoryCarousel = memo(function CategoryCarousel({
</div> </div>
<Carousel <Carousel
opts={{ opts={{ align: 'start', dragFree: true }}
align: 'start',
dragFree: true, // 🔥 free scroll
}}
className="w-full mt-2" className="w-full mt-2"
setApi={setApi} setApi={setApi}
> >
<CarouselContent className="pr-[12%] sm:pr-0"> <CarouselContent className="pr-[12%] sm:pr-0">
{activeProducts.map((product) => ( {isLoading || isError || activeProducts.length === 0
? Array.from({ length: 6 }).map((__, index) => (
<CarouselItem
key={index}
className="basis-1/2 sm:basis-1/3 md:basis-1/4 lg:basis-1/5 xl:basis-1/6 pb-2"
>
<Card className="p-3 space-y-3 rounded-xl">
<Skeleton className="h-40 sm:h-48 md:h-56 w-full rounded-lg" />
<Skeleton className="h-4 w-3/4" />
<Skeleton className="h-4 w-1/2" />
<Skeleton className="h-10 w-full rounded-lg" />
</Card>
</CarouselItem>
))
: activeProducts.map((product) => (
<CarouselItem <CarouselItem
key={product.id} key={product.id}
className="basis-1/2 sm:basis-1/3 md:basis-1/4 lg:basis-1/5 xl:basis-1/6 pb-2" className="basis-1/2 sm:basis-1/3 md:basis-1/4 lg:basis-1/5 xl:basis-1/6 pb-2"

View File

@@ -80,7 +80,11 @@ const Welcome = () => {
}, },
}); });
const { data: allProducts, isLoading: allProductsLoading } = useQuery({ const {
data: allProducts,
isLoading: allProductsLoading,
isError: allProductsError,
} = useQuery({
queryKey: ['all_products'], queryKey: ['all_products'],
queryFn: () => banner_api.getAllProducts(), queryFn: () => banner_api.getAllProducts(),
select(data) { select(data) {
@@ -300,14 +304,43 @@ const Welcome = () => {
</Button> </Button>
</section> </section>
{allProducts && {productLoading || allProductsLoading ? (
allProducts.map((e) => ( <section className="relative custom-container mt-5 justify-center items-center border-b border-slate-200">
<Carousel
opts={{
align: 'start',
dragFree: true,
}}
className="w-full"
setApi={setApiPro}
>
<CarouselContent className="pr-[12%] sm:pr-0">
{Array.from({ length: 6 }).map((__, index) => (
<CarouselItem
key={index}
className="basis-1/2 sm:basis-1/3 md:basis-1/4 lg:basis-1/5 xl:basis-1/6 pb-2"
>
<Card className="p-3 space-y-3 rounded-xl">
<Skeleton className="h-40 sm:h-48 md:h-56 w-full rounded-lg" />
<Skeleton className="h-4 w-3/4" />
<Skeleton className="h-4 w-1/2" />
<Skeleton className="h-10 w-full rounded-lg" />
</Card>
</CarouselItem>
))}
</CarouselContent>
</Carousel>
</section>
) : (
allProducts?.map((e) => (
<CategoryCarousel <CategoryCarousel
category={e} category={e}
key={e.id} key={e.id}
isLoading={allProductsLoading} isLoading={allProductsLoading}
isError={allProductsError}
/> />
))} ))
)}
</> </>
); );
}; };