fixed some bugs

This commit is contained in:
Jelaletdin12
2025-12-23 13:32:57 +05:00
parent cdc9fa686f
commit 2b46d525f2
30 changed files with 857 additions and 260 deletions

View File

@@ -3,7 +3,9 @@ import { useState, useEffect, useMemo } from "react";
import { Card } from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";
import CartItemCard from "../../../features/cart/components/CartItemCard";
import CartItemSkeleton from "../../../features/cart/components/CartItemSkeleton";
import OrderSummary from "../../../features/cart/components/OrderSummary";
import OrderSummarySkeleton from "../../../features/cart/components/OrderSummarySkeleton";
import {
useCart,
useCreateOrder,
@@ -14,6 +16,7 @@ import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation";
import type { DeliveryType, PaymentType } from "@/lib/types/api";
import EmptyCart from "@/features/cart/components/EmptyCart";
import ErrorPage from "@/components/ErrorPage";
export default function CartPage() {
const [isClient, setIsClient] = useState(false);
@@ -29,12 +32,14 @@ export default function CartPage() {
const router = useRouter();
const t = useTranslations();
const { data: cartResponse, isLoading, isError } = useCart();
const { data: provinces = [] } = useRegions();
const { data: paymentTypes = [] } = usePaymentTypes();
const { data: cartResponse, isLoading: cartLoading, isError } = useCart();
const { data: provinces = [], isLoading: provincesLoading } = useRegions();
const { data: paymentTypes = [], isLoading: paymentTypesLoading } =
usePaymentTypes();
const { mutate: createOrder, isPending: isCreatingOrder } = useCreateOrder();
const cartItems = cartResponse?.data || [];
const isLoading = cartLoading || provincesLoading || paymentTypesLoading;
useEffect(() => {
setIsClient(true);
@@ -120,12 +125,38 @@ export default function CartPage() {
if (!isClient) return null;
if (isError || cartItems.length === 0) {
if (isLoading) {
return (
<div className="mx-auto px-2 md:px-4 lg:px-6 mb-18">
<h1 className="text-xl md:text-2xl lg:text-3xl font-bold mb-4 md:mb-6 pt-3">
{t("cart")}
</h1>
<div className="flex flex-col md:flex-row gap-6">
<div className="flex-1">
<Card className="p-4 md:p-6 rounded-xl">
<div className="space-y-4">
{Array.from({ length: 3 }).map((_, i) => (
<CartItemSkeleton key={i} />
))}
</div>
</Card>
</div>
<OrderSummarySkeleton />
</div>
</div>
);
}
if (isError ) {
return <ErrorPage />;
}
if (cartItems.length === 0) {
return <EmptyCart />;
}
return (
<div className=" mx-auto px-2 md:px-4 lg:px-6 mb-18">
<div className="mx-auto px-2 md:px-4 lg:px-6 mb-18">
<h1 className="text-xl md:text-2xl lg:text-3xl font-bold mb-4 md:mb-6 pt-3">
{t("cart")}
</h1>

View File

@@ -1,35 +1,52 @@
import type { Metadata } from "next"
import type { Metadata } from "next";
type Props = {
params: Promise<{ locale: string; slug: string }>
}
params: Promise<{ locale: string; slug: string }>;
};
export const revalidate = 600 // ISR: Revalidate every 10 minutes
export const revalidate = 600; // ISR: Revalidate every 10 minutes
const CATEGORY_META = {
tm: {
suffix: " | Post shop",
description: "Kategoriýa boýunça harytlary gözläň",
ogLocale: "tk_TM",
},
ru: {
suffix: " | Post shop",
description: "Просмотр товаров в данной категории",
ogLocale: "ru_RU",
},
} as const;
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { locale, slug } = await params
const { locale, slug } = await params;
const meta =
CATEGORY_META[locale as keyof typeof CATEGORY_META] ?? CATEGORY_META.ru;
return {
title: `${slug.charAt(0).toUpperCase() + slug.slice(1)} | E-Commerce`,
description: `Browse ${slug} products in our store`,
title: `${slug}${meta.suffix}`,
description: meta.description,
openGraph: {
locale,
type: "website",
title: `${slug.charAt(0).toUpperCase() + slug.slice(1)} | E-Commerce`,
description: `Browse ${slug} products in our store`,
locale: meta.ogLocale,
title: `${slug}${meta.suffix}`,
description: meta.description,
},
}
};
}
export async function generateStaticParams() {
const categories = ["electronics", "clothing", "home-garden"]
return categories.map((slug) => ({ slug }))
const categories = ["electronics", "clothing", "home-garden"];
return categories.map((slug) => ({ slug }));
}
export default async function CategoryPage(props: Props) {
const params = await props.params
const { slug } = params
const params = await props.params;
const { slug } = params;
const CategoryPageClient = (await import("../../../../features/category/components/CategoryPageClient")).default
return <CategoryPageClient params={params} />
const CategoryPageClient = (
await import("../../../../features/category/components/CategoryPageClient")
).default;
return <CategoryPageClient params={params} />;
}

View File

@@ -1,37 +1,64 @@
import type { Metadata } from "next"
import type { Metadata } from "next";
type Props = {
params: Promise<{ locale: string; slug: string }>
params: Promise<{ locale: string; slug: string }>;
};
export const revalidate = 600; // ISR: 10 minutes
const META = {
tm: {
titleSuffix: " | Post shop",
description: (name: string) => `${name} kolleksiýasyndaky harytlary gözläň`,
ogLocale: "tk_TM",
},
ru: {
titleSuffix: " | Post shop",
description: (name: string) => `Просмотр товаров из коллекции «${name}»`,
ogLocale: "ru_RU",
},
} as const;
function formatSlug(slug: string) {
return slug
.split("-")
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
.join(" ");
}
export const revalidate = 600 // ISR: Revalidate every 10 minutes
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { locale, slug } = await params
const { locale, slug } = await params;
const meta = META[locale as keyof typeof META] ?? META.ru;
const collectionName = formatSlug(slug);
const title = `${collectionName}${meta.titleSuffix}`;
const description = meta.description(collectionName);
return {
title: `${slug.charAt(0).toUpperCase() + slug.slice(1)} | E-Commerce`,
description: `Browse ${slug} collection products in our store`,
title,
description,
openGraph: {
locale,
type: "website",
title: `${slug.charAt(0).toUpperCase() + slug.slice(1)} | E-Commerce`,
description: `Browse ${slug} collection products in our store`,
locale: meta.ogLocale,
title,
description,
},
}
};
}
export async function generateStaticParams() {
const collections = ["new-arrivals", "best-sellers", "featured"]
return collections.map((slug) => ({ slug }))
const collections = ["new-arrivals", "best-sellers", "featured"];
return collections.map((slug) => ({ slug }));
}
export default async function CollectionPage(props: Props) {
const params = await props.params
const params = await props.params;
const CollectionPageClient = (
await import("../../../../features/collections/components/CollectionPageClient")
).default
return <CollectionPageClient params={params} />
}
await import(
"../../../../features/collections/components/CollectionPageClient"
)
).default;
return <CollectionPageClient params={params} />;
}

View File

@@ -6,33 +6,46 @@ import { useTranslations } from "next-intl";
import ProductCard from "@/features/home/components/ProductCard";
import type { Favorite } from "@/lib/types/api";
import EmptyFavorites from "@/features/favorites/components/EmptyFavorites";
import ErrorPage from "@/components/ErrorPage";
export default function FavoritesPage() {
const t = useTranslations();
const { data: favorites, isLoading, isError } = useFavorites();
if (isLoading) {
return (
<div className=" mx-auto px-4 py-8 min-h-screen">
<h1 className="text-3xl font-bold mb-6">{t("favorite_products")}</h1>
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4">
<div className="mx-auto px-2 md:px-4 lg:px-6 pb-12 space-y-8 max-w-[1504px]">
<h1 className="bg-white text-3xl p-4 font-bold mb-0 pb-6">
{t("favorite_products")}
</h1>
<div className="bg-white grid grid-cols-2 sm:grid-cols-3 rounded-b-lg md:grid-cols-4 lg:grid-cols-5 gap-3 p-4">
{Array.from({ length: 10 }).map((_, i) => (
<Skeleton key={i} className="w-full h-64 rounded-lg" />
<div key={i} className="space-y-2">
<Skeleton className="w-full h-[260px] rounded-xl" />
<Skeleton className="h-4 w-3/4 mx-2" />
<Skeleton className="h-6 w-1/2 mx-2" />
</div>
))}
</div>
</div>
);
}
if (isError || !favorites || favorites.length === 0) {
return (
<EmptyFavorites/>
);
if (isError) {
return <ErrorPage />;
}
if (!favorites || favorites.length === 0) {
return <EmptyFavorites />;
}
return (
<div className=" mx-auto px-2 md:px-4 lg:px-6 pb-12 space-y-8 max-w-[1504px]
">
<h1 className="bg-white text-3xl p-4 font-bold mb-0 pb-6">{t("favorite_products")}</h1>
<div
className=" mx-auto px-2 md:px-4 lg:px-6 pb-12 space-y-8 max-w-[1504px]
"
>
<h1 className="bg-white text-3xl p-4 font-bold mb-0 pb-6">
{t("favorite_products")}
</h1>
<div className="bg-white grid grid-cols-2 sm:grid-cols-3 rounded-b-lg md:grid-cols-4 lg:grid-cols-5 gap-3 p-4">
{favorites.map((favorite: Favorite) => {
const product = favorite.product;