seo uodate
This commit is contained in:
@@ -1,6 +1,57 @@
|
||||
import { AboutContent } from '@/features/about/ui/AboutContent';
|
||||
import { AboutHero } from '@/features/about/ui/AboutHero';
|
||||
import { PartnershipForm } from '@/features/about/ui/AboutPage';
|
||||
import { Metadata } from 'next';
|
||||
|
||||
interface Props {
|
||||
params: { locale: 'uz' | 'ru' };
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
|
||||
const titles = {
|
||||
uz: 'Biz haqimizda | GASTRO',
|
||||
ru: 'О нас | Магазин товаров',
|
||||
};
|
||||
|
||||
const descriptions = {
|
||||
uz: 'Bizning onlayn do‘konimizda sifatli mahsulotlarni toping. Tez yetkazib berish va qulay to‘lov imkoniyatlari mavjud.',
|
||||
ru: 'В нашем онлайн-магазине вы найдете качественные товары. Быстрая доставка и удобная оплата.',
|
||||
};
|
||||
|
||||
const keywords = {
|
||||
uz: 'mahsulot, onlayn do‘kon, xarid, yetkazib berish',
|
||||
ru: 'товары, онлайн-магазин, покупка, доставка',
|
||||
};
|
||||
|
||||
return {
|
||||
title: titles[locale],
|
||||
description: descriptions[locale],
|
||||
keywords: keywords[locale],
|
||||
openGraph: {
|
||||
title: titles[locale],
|
||||
description: descriptions[locale],
|
||||
siteName: 'GASTRO',
|
||||
images: [
|
||||
{
|
||||
url: '/logos/logo.png',
|
||||
width: 1200,
|
||||
height: 1200,
|
||||
alt: titles[locale],
|
||||
},
|
||||
],
|
||||
locale: locale === 'uz' ? 'uz_UZ' : 'ru_RU',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: titles[locale],
|
||||
description: descriptions[locale],
|
||||
images: ['/logos/logo.png'],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const page = () => {
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,57 @@
|
||||
import Login from '@/features/auth/ui/Login';
|
||||
import { Metadata } from 'next';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
interface Props {
|
||||
params: { locale: 'uz' | 'ru' };
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
|
||||
const titles = {
|
||||
uz: 'Tizimga kirish | GASTRO',
|
||||
ru: 'Вход в систему | GASTRO',
|
||||
};
|
||||
|
||||
const descriptions = {
|
||||
uz: 'Onlayn do‘konimizga tizimga kirish uchun login va parolingizni kiriting. Tez va xavfsiz kirish imkoniyati.',
|
||||
ru: 'Введите ваш логин и пароль для входа в наш онлайн-магазин. Быстрый и безопасный вход.',
|
||||
};
|
||||
|
||||
const keywords = {
|
||||
uz: 'login, tizimga kirish, mahsulotlar do‘koni, parol',
|
||||
ru: 'логин, вход, магазин товаров, пароль',
|
||||
};
|
||||
|
||||
return {
|
||||
title: titles[locale],
|
||||
description: descriptions[locale],
|
||||
keywords: keywords[locale],
|
||||
openGraph: {
|
||||
title: titles[locale],
|
||||
description: descriptions[locale],
|
||||
siteName: 'GASTRO',
|
||||
images: [
|
||||
{
|
||||
url: '/logos/logo.png', // public papkadan
|
||||
width: 1200,
|
||||
height: 1200,
|
||||
alt: titles[locale],
|
||||
},
|
||||
],
|
||||
locale: locale === 'uz' ? 'uz_UZ' : 'ru_RU',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: titles[locale],
|
||||
description: descriptions[locale],
|
||||
images: ['/logos/logo.png'],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const page = () => {
|
||||
return (
|
||||
<Suspense>
|
||||
|
||||
@@ -1,7 +1,58 @@
|
||||
import OrderPage from '@/features/cart/ui/OrderPage';
|
||||
import { Metadata } from 'next';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
const page = () => {
|
||||
interface Props {
|
||||
params: { locale: 'uz' | 'ru' };
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
|
||||
const titles = {
|
||||
uz: 'Buyurtma | GASTRO',
|
||||
ru: 'Оформление заказа | Магазин товаров',
|
||||
};
|
||||
|
||||
const descriptions = {
|
||||
uz: 'Buyurtma sahifasi orqali xaridingizni tasdiqlang, yetkazib berish manzilini belgilang va to‘lov usulini tanlang. Tez va qulay xarid tajribasi.',
|
||||
ru: 'Страница оформления заказа. Подтверждайте покупки, указывайте адрес доставки и выбирайте способ оплаты. Быстрый и удобный процесс покупки.',
|
||||
};
|
||||
|
||||
const keywords = {
|
||||
uz: 'buyurtma, xarid, yetkazib berish, mahsulotlar, online do‘kon, to‘lov',
|
||||
ru: 'заказ, покупки, доставка, товары, онлайн-магазин, оплата',
|
||||
};
|
||||
|
||||
return {
|
||||
title: titles[locale],
|
||||
description: descriptions[locale],
|
||||
keywords: keywords[locale],
|
||||
openGraph: {
|
||||
title: titles[locale],
|
||||
description: descriptions[locale],
|
||||
siteName: 'GASTRO',
|
||||
images: [
|
||||
{
|
||||
url: '/logos/logo.png', // public papkadan rasm
|
||||
width: 1200,
|
||||
height: 1200,
|
||||
alt: titles[locale],
|
||||
},
|
||||
],
|
||||
locale: locale === 'uz' ? 'uz_UZ' : 'ru_RU',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: titles[locale],
|
||||
description: descriptions[locale],
|
||||
images: ['/logos/logo.png'],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<Suspense>
|
||||
<OrderPage />
|
||||
@@ -9,4 +60,4 @@ const page = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default page;
|
||||
export default Page;
|
||||
|
||||
@@ -1,7 +1,58 @@
|
||||
import CartPage from '@/features/cart/ui/CartPage';
|
||||
import { Metadata } from 'next';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
const page = () => {
|
||||
interface Props {
|
||||
params: { locale: 'uz' | 'ru' };
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
|
||||
const titles = {
|
||||
uz: 'Savat | GASTRO',
|
||||
ru: 'Корзина | Магазин товаров',
|
||||
};
|
||||
|
||||
const descriptions = {
|
||||
uz: 'Sizning xaridingizni boshqarish uchun savat sahifasi. Mahsulotlar qo‘shing, o‘chiring yoki miqdorini o‘zgartiring. Tez va qulay xarid tajribasi.',
|
||||
ru: 'Страница корзины для управления вашими покупками. Добавляйте товары, удаляйте или изменяйте количество. Быстрый и удобный опыт покупки.',
|
||||
};
|
||||
|
||||
const keywords = {
|
||||
uz: 'savat, xarid, mahsulotlar, onlayn do‘kon, xaridni boshqarish',
|
||||
ru: 'корзина, покупки, товары, онлайн-магазин, управление покупками',
|
||||
};
|
||||
|
||||
return {
|
||||
title: titles[locale],
|
||||
description: descriptions[locale],
|
||||
keywords: keywords[locale],
|
||||
openGraph: {
|
||||
title: titles[locale],
|
||||
description: descriptions[locale],
|
||||
siteName: 'GASTRO',
|
||||
images: [
|
||||
{
|
||||
url: '/logos/logo.png', // public papkadan rasm
|
||||
width: 1200,
|
||||
height: 1200,
|
||||
alt: titles[locale],
|
||||
},
|
||||
],
|
||||
locale: locale === 'uz' ? 'uz_UZ' : 'ru_RU',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: titles[locale],
|
||||
description: descriptions[locale],
|
||||
images: ['/logos/logo.png'],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<Suspense>
|
||||
<CartPage />
|
||||
@@ -9,4 +60,4 @@ const page = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default page;
|
||||
export default Page;
|
||||
|
||||
@@ -1,7 +1,63 @@
|
||||
import Product from '@/features/category/ui/Product';
|
||||
import { category_api } from '@/shared/config/api/category/api';
|
||||
import { BASE_URL } from '@/shared/config/api/URLs';
|
||||
import { Metadata } from 'next';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
const page = () => {
|
||||
interface Params {
|
||||
params: {
|
||||
categoryId: string;
|
||||
};
|
||||
}
|
||||
|
||||
const fetchCategory = async (categoryId: string) => {
|
||||
try {
|
||||
const res = await category_api.getCategory({ page: 1, page_size: 99 });
|
||||
return res.data.results.find((c) => c.id.toString() === categoryId);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export async function generateMetadata({ params }: Params): Promise<Metadata> {
|
||||
const { categoryId } = await params;
|
||||
const category = await fetchCategory(categoryId);
|
||||
|
||||
if (!category) {
|
||||
return {
|
||||
title: 'Kategoriya topilmadi',
|
||||
description: 'Kategoriya mavjud emas',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
title: `${category.name} | GASTRO`,
|
||||
description: `Bizning do‘konimizdagi ${category.name} kategoriyasidagi mahsulotlar`,
|
||||
keywords: `mahsulotlar, kategoriya, ${category.name}`,
|
||||
openGraph: {
|
||||
title: `${category.name} | GASTRO`,
|
||||
description: `Bizning do‘konimizdagi ${category.name} kategoriyasidagi mahsulotlar`,
|
||||
siteName: 'GASTRO',
|
||||
images: [
|
||||
{
|
||||
url: category.image ? BASE_URL + category.image : '/logos/logo.png',
|
||||
width: 1200,
|
||||
height: 1200,
|
||||
alt: category.name,
|
||||
},
|
||||
],
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: `${category.name} | GASTRO`,
|
||||
description: `Bizning do‘konimizdagi ${category.name} kategoriyasidagi mahsulotlar`,
|
||||
images: [category.image ? BASE_URL + category.image : '/logos/logo.png'],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<Suspense>
|
||||
<Product />
|
||||
@@ -9,4 +65,4 @@ const page = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default page;
|
||||
export default Page;
|
||||
|
||||
@@ -1,7 +1,88 @@
|
||||
// app/category/page.tsx
|
||||
import Category from '@/features/category/ui/Category';
|
||||
import { category_api } from '@/shared/config/api/category/api';
|
||||
import { Metadata } from 'next';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
const page = () => {
|
||||
const fetchCategoryData = async () => {
|
||||
try {
|
||||
const res = await category_api.getCategory({ page: 1, page_size: 99 });
|
||||
return res.data.results;
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
interface PageProps {
|
||||
params: {
|
||||
locale: 'uz' | 'ru';
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: PageProps): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
const categories = await fetchCategoryData();
|
||||
const categoryNames = categories.map((c) => c.name).join(', ');
|
||||
|
||||
if (locale === 'ru') {
|
||||
return {
|
||||
title: 'Категории | GASTRO',
|
||||
description: `Категории в нашем магазине: ${categoryNames}`,
|
||||
keywords: `категории, продукты, магазин, ${categoryNames}`,
|
||||
openGraph: {
|
||||
title: 'Категории | GASTRO',
|
||||
description: `Категории в нашем магазине: ${categoryNames}`,
|
||||
siteName: 'GASTRO',
|
||||
images: [
|
||||
{
|
||||
url: '/logos/logo.png',
|
||||
width: 1200,
|
||||
height: 1200,
|
||||
alt: 'Категории',
|
||||
},
|
||||
],
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Категории | GASTRO',
|
||||
description: `Категории в нашем магазине: ${categoryNames}`,
|
||||
images: ['/logos/logo.png'],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// default: Uzbek
|
||||
return {
|
||||
title: 'Kategoriyalar | GASTRO',
|
||||
description: `Bizning do‘konimizdagi kategoriyalar: ${categoryNames}`,
|
||||
keywords: `kategoriyalar, mahsulotlar, do‘kon, ${categoryNames}`,
|
||||
openGraph: {
|
||||
title: 'Kategoriyalar | GASTRO',
|
||||
description: `Bizning do‘konimizdagi kategoriyalar: ${categoryNames}`,
|
||||
siteName: 'GASTRO',
|
||||
images: [
|
||||
{
|
||||
url: '/logos/logo.png',
|
||||
width: 1200,
|
||||
height: 1200,
|
||||
alt: 'Kategoriyalar',
|
||||
},
|
||||
],
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Kategoriyalar | GASTRO',
|
||||
description: `Bizning do‘konimizdagi kategoriyalar: ${categoryNames}`,
|
||||
images: ['/logos/logo.png'],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<Suspense>
|
||||
<Category />
|
||||
@@ -9,4 +90,4 @@ const page = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default page;
|
||||
export default Page;
|
||||
|
||||
@@ -1,11 +1,77 @@
|
||||
// app/faq/page.tsx
|
||||
import { faq_api } from '@/features/faq/lib/api';
|
||||
import Faq from '@/features/faq/ui/Faq';
|
||||
import { Metadata } from 'next';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
const page = () => {
|
||||
// FAQ ma'lumotini API dan olish
|
||||
const fetchFaqData = async () => {
|
||||
try {
|
||||
const res = await faq_api.list();
|
||||
return res.data;
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
interface PageProps {
|
||||
params: {
|
||||
locale: 'uz' | 'ru';
|
||||
};
|
||||
}
|
||||
|
||||
// Dynamic metadata generatsiyasi
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: PageProps): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
const data = await fetchFaqData();
|
||||
const faqCount = data.length;
|
||||
|
||||
if (locale === 'ru') {
|
||||
return {
|
||||
title: `FAQ | Часто задаваемые вопросы`,
|
||||
description: `В нашем разделе FAQ ${faqCount} часто задаваемых вопросов с ответами.`,
|
||||
keywords: `faq, часто задаваемые вопросы, ответы, gastro market`,
|
||||
openGraph: {
|
||||
title: `FAQ | Часто задаваемые вопросы`,
|
||||
description: `В нашем разделе FAQ ${faqCount} часто задаваемых вопросов с ответами.`,
|
||||
siteName: 'Gastro Market',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: `FAQ | Часто задаваемые вопросы`,
|
||||
description: `В нашем разделе FAQ ${faqCount} часто задаваемых вопросов с ответами.`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// default: Uzbek
|
||||
return {
|
||||
title: `FAQ | Tez-tez So'raladigan Savollar`,
|
||||
description: `Bizning FAQ bo'limimizda ${faqCount} ta tez-tez so'raladigan savollarga javoblar.`,
|
||||
keywords: `faq, tez-tez so'raladigan savollar, javoblar, gastro market`,
|
||||
openGraph: {
|
||||
title: `FAQ | Tez-tez So'raladigan Savollar`,
|
||||
description: `Bizning FAQ bo'limimizda ${faqCount} ta tez-tez so'raladigan savollarga javoblar.`,
|
||||
siteName: 'Gastro Market',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: `FAQ | Tez-tez So'raladigan Savollar`,
|
||||
description: `Bizning FAQ bo'limimizda ${faqCount} ta tez-tez so'raladigan savollarga javoblar.`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<div>
|
||||
<Suspense>
|
||||
<Faq />
|
||||
</div>
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
|
||||
export default page;
|
||||
export default Page;
|
||||
|
||||
@@ -1,7 +1,84 @@
|
||||
// app/favourite/page.tsx
|
||||
import Favourite from '@/features/favourite/ui/Favourite';
|
||||
import { product_api } from '@/shared/config/api/product/api';
|
||||
import { Metadata } from 'next';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
const page = () => {
|
||||
export const dynamic = 'force-dynamic'; // Dynamic rendering uchun
|
||||
|
||||
interface PageProps {
|
||||
params: {
|
||||
locale: 'uz' | 'ru';
|
||||
};
|
||||
}
|
||||
|
||||
// SEO metadata
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: PageProps): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
try {
|
||||
const res = await product_api.favouuriteProduct();
|
||||
const total = res.data.total;
|
||||
|
||||
if (locale === 'ru') {
|
||||
return {
|
||||
title: total
|
||||
? `Избранные товары (${total}) - Gastro Market`
|
||||
: 'Избранные товары - Gastro Market',
|
||||
description: total
|
||||
? `Количество ваших избранных товаров: ${total}. Управляйте избранным и покупайте через Gastro Market.`
|
||||
: 'Вы еще не добавили товары в избранное. Добавляйте любимые товары и совершайте покупки через Gastro Market.',
|
||||
openGraph: {
|
||||
title: total
|
||||
? `Избранные товары (${total}) - Gastro Market`
|
||||
: 'Избранные товары - Gastro Market',
|
||||
description: total
|
||||
? `Количество ваших избранных товаров: ${total}.`
|
||||
: 'Вы еще не добавили товары в избранное.',
|
||||
url: '/favourite',
|
||||
type: 'website',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Default: Uzbek
|
||||
return {
|
||||
title: total
|
||||
? `Sevimli mahsulotlar (${total}) - Gastro Market`
|
||||
: 'Sevimli mahsulotlar - Gastro Market',
|
||||
description: total
|
||||
? `Sizning sevimli mahsulotlaringiz soni: ${total}. Gastro Market orqali sevimlilarni boshqarish va xarid qilish.`
|
||||
: 'Hali hech qanday mahsulot sevimlilarga qo‘shilmadi. Gastro Market bilan sevimli mahsulotlaringizni qo‘shing va xarid qiling.',
|
||||
openGraph: {
|
||||
title: total
|
||||
? `Sevimli mahsulotlar (${total}) - Gastro Market`
|
||||
: 'Sevimli mahsulotlar - Gastro Market',
|
||||
description: total
|
||||
? `Sizning sevimli mahsulotlaringiz soni: ${total}.`
|
||||
: 'Hali hech qanday mahsulot sevimlilarga qo‘shilmadi.',
|
||||
url: '/favourite',
|
||||
type: 'website',
|
||||
},
|
||||
};
|
||||
} catch {
|
||||
if (locale === 'ru') {
|
||||
return {
|
||||
title: 'Избранные товары - Gastro Market',
|
||||
description:
|
||||
'Управляйте вашими избранными товарами и совершайте покупки через Gastro Market.',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
title: 'Sevimli mahsulotlar - Gastro Market',
|
||||
description:
|
||||
'Sizning sevimli mahsulotlaringizni boshqarish va xarid qilish. Gastro Market bilan.',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<Suspense>
|
||||
<Favourite />
|
||||
@@ -9,4 +86,4 @@ const page = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default page;
|
||||
export default Page;
|
||||
|
||||
@@ -9,7 +9,7 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
|
||||
const titles = {
|
||||
uz: 'Bosh sahifa | Mahsulotlar do‘koni',
|
||||
uz: 'Bosh sahifa | GASTRO',
|
||||
ru: 'Главная | Магазин товаров',
|
||||
};
|
||||
|
||||
@@ -30,7 +30,7 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
openGraph: {
|
||||
title: titles[locale],
|
||||
description: descriptions[locale],
|
||||
siteName: 'Mahsulotlar do‘koni',
|
||||
siteName: 'GASTRO',
|
||||
images: [
|
||||
{
|
||||
url: '/logos/logo.png',
|
||||
|
||||
@@ -1,11 +1,63 @@
|
||||
// app/privacy-policy/page.tsx
|
||||
import PrivacyPolicy from '@/features/privacy-policy/ui/PrivacyPlicy';
|
||||
import { Metadata } from 'next';
|
||||
|
||||
const page = () => {
|
||||
return (
|
||||
<div>
|
||||
<PrivacyPolicy />
|
||||
</div>
|
||||
);
|
||||
interface PageProps {
|
||||
params: {
|
||||
locale: 'uz' | 'ru';
|
||||
};
|
||||
}
|
||||
|
||||
// Dynamic metadata (bilingval)
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: PageProps): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
|
||||
if (locale === 'ru') {
|
||||
return {
|
||||
title: 'Политика конфиденциальности - Gastro Market',
|
||||
description:
|
||||
'Gastro Market объясняет, как собирает, использует и защищает ваши персональные данные. Ознакомьтесь с политикой конфиденциальности.',
|
||||
openGraph: {
|
||||
title: 'Политика конфиденциальности - Gastro Market',
|
||||
description:
|
||||
'Gastro Market объясняет, как собирает, использует и защищает ваши персональные данные.',
|
||||
url: '/privacy-policy',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Политика конфиденциальности - Gastro Market',
|
||||
description:
|
||||
'Gastro Market объясняет, как собирает, использует и защищает ваши персональные данные.',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Default: Uzbek
|
||||
return {
|
||||
title: 'Maxfiylik Siyosati - Gastro Market',
|
||||
description:
|
||||
"Gastro Market sizning shaxsiy ma'lumotlaringizni qanday to'playdi, ishlatadi va himoya qiladi. Maxfiylik Siyosatini o‘qing.",
|
||||
openGraph: {
|
||||
title: 'Maxfiylik Siyosati - Gastro Market',
|
||||
description:
|
||||
"Gastro Market sizning shaxsiy ma'lumotlaringizni qanday to'playdi, ishlatadi va himoya qiladi.",
|
||||
url: '/privacy-policy',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Maxfiylik Siyosati - Gastro Market',
|
||||
description:
|
||||
"Gastro Market sizning shaxsiy ma'lumotlaringizni qanday to'playdi, ishlatadi va himoya qiladi.",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const Page = () => {
|
||||
return <PrivacyPolicy />;
|
||||
};
|
||||
|
||||
export default page;
|
||||
export default Page;
|
||||
|
||||
@@ -1,7 +1,70 @@
|
||||
// app/product/[product]/page.tsx
|
||||
import ProductDetail from '@/features/product/ui/Product';
|
||||
import { product_api } from '@/shared/config/api/product/api';
|
||||
import { BASE_URL } from '@/shared/config/api/URLs';
|
||||
import type { Metadata } from 'next';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
const page = () => {
|
||||
interface PageProps {
|
||||
params: {
|
||||
product: string;
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: PageProps): Promise<Metadata> {
|
||||
try {
|
||||
const { product } = await params;
|
||||
|
||||
const res = await product_api.detail(product);
|
||||
|
||||
return {
|
||||
title: `${res.data.name} - Gastro Market`,
|
||||
description:
|
||||
res.data.description || `Gastro Market mahsuloti: ${res.data.name}`,
|
||||
openGraph: {
|
||||
title: `${res.data.name} - Gastro Market`,
|
||||
description:
|
||||
res.data.description || `Gastro Market mahsuloti: ${res.data.name}`,
|
||||
type: 'website',
|
||||
images: [
|
||||
{
|
||||
url:
|
||||
res.data.images && res.data.images.length > 0
|
||||
? res.data.images[0].image.includes(BASE_URL)
|
||||
? res.data.images[0].image
|
||||
: BASE_URL + res.data.images[0].image
|
||||
: '/placeholder.svg',
|
||||
width: 800,
|
||||
height: 600,
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: `${res.data.name} - Gastro Market`,
|
||||
description:
|
||||
res.data.description || `Gastro Market mahsuloti: ${res.data.name}`,
|
||||
images:
|
||||
res.data.images && res.data.images.length > 0
|
||||
? [
|
||||
res.data.images[0].image.includes(BASE_URL)
|
||||
? res.data.images[0].image
|
||||
: BASE_URL + res.data.images[0].image,
|
||||
]
|
||||
: ['/placeholder.svg'],
|
||||
},
|
||||
};
|
||||
} catch {
|
||||
return {
|
||||
title: 'Mahsulot - Gastro Market',
|
||||
description: 'Gastro Market mahsulotlarini kashf eting',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<Suspense>
|
||||
<ProductDetail />
|
||||
@@ -9,4 +72,4 @@ const page = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default page;
|
||||
export default Page;
|
||||
|
||||
@@ -1,7 +1,67 @@
|
||||
// app/profile/page.tsx
|
||||
import Profile from '@/features/profile/ui/Profile';
|
||||
import { Metadata } from 'next';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
const page = () => {
|
||||
interface PageProps {
|
||||
params: {
|
||||
locale: 'uz' | 'ru';
|
||||
};
|
||||
}
|
||||
|
||||
// Dynamic bilingval metadata
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: PageProps): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
|
||||
if (locale === 'ru') {
|
||||
return {
|
||||
title: 'Мой профиль - Gastro Market',
|
||||
description: 'Gastro Market: управление вашим пользовательским профилем',
|
||||
robots: {
|
||||
index: false, // profil sahifasi indekslanmasligi uchun
|
||||
follow: true,
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Мой профиль - Gastro Market',
|
||||
description:
|
||||
'Gastro Market: управление вашим пользовательским профилем',
|
||||
url: '/profile',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary',
|
||||
title: 'Мой профиль - Gastro Market',
|
||||
description:
|
||||
'Gastro Market: управление вашим пользовательским профилем',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Default: Uzbek
|
||||
return {
|
||||
title: 'Mening Profilim - Gastro Market',
|
||||
description: 'Gastro Market foydalanuvchi profilingizni boshqarish',
|
||||
robots: {
|
||||
index: false, // profil sahifasi indekslanmasligi uchun
|
||||
follow: true,
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Mening Profilim - Gastro Market',
|
||||
description: 'Gastro Market foydalanuvchi profilingizni boshqarish',
|
||||
url: '/profile',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary',
|
||||
title: 'Mening Profilim - Gastro Market',
|
||||
description: 'Gastro Market foydalanuvchi profilingizni boshqarish',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<Suspense>
|
||||
<Profile />
|
||||
@@ -9,4 +69,4 @@ const page = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default page;
|
||||
export default Page;
|
||||
|
||||
@@ -1,4 +1,63 @@
|
||||
// app/profile/refresh-order/page.tsx
|
||||
import RefreshOrder from '@/features/profile/ui/RefreshOrder';
|
||||
import type { Metadata } from 'next';
|
||||
|
||||
interface PageProps {
|
||||
params: {
|
||||
locale: 'uz' | 'ru';
|
||||
};
|
||||
}
|
||||
|
||||
// Dynamic bilingval metadata
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: PageProps): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
|
||||
if (locale === 'ru') {
|
||||
return {
|
||||
title: 'Оформление заказа - Gastro Market',
|
||||
description:
|
||||
'Оформите ваш заказ на Gastro Market, заполните все необходимые данные для доставки и оплаты.',
|
||||
keywords: 'заказ, оформление заказа, gastro market, доставка, оплата',
|
||||
openGraph: {
|
||||
title: 'Оформление заказа - Gastro Market',
|
||||
description:
|
||||
'Оформите ваш заказ на Gastro Market, заполните все необходимые данные для доставки и оплаты.',
|
||||
url: '/profile/refresh-order',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Оформление заказа - Gastro Market',
|
||||
description:
|
||||
'Оформите ваш заказ на Gastro Market, заполните все необходимые данные для доставки и оплаты.',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Default: Uzbek
|
||||
return {
|
||||
title: 'Buyurtmani rasmiylashtirish - Gastro Market',
|
||||
description:
|
||||
"Gastro Market orqali buyurtmangizni rasmiylashtiring, yetkazib berish va to‘lov ma'lumotlarini to‘ldiring.",
|
||||
keywords:
|
||||
"buyurtma, rasmiylashtirish, gastro market, yetkazib berish, to'lov",
|
||||
openGraph: {
|
||||
title: 'Buyurtmani rasmiylashtirish - Gastro Market',
|
||||
description:
|
||||
"Gastro Market orqali buyurtmangizni rasmiylashtiring, yetkazib berish va to‘lov ma'lumotlarini to‘ldiring.",
|
||||
url: '/profile/refresh-order',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Buyurtmani rasmiylashtirish - Gastro Market',
|
||||
description:
|
||||
"Gastro Market orqali buyurtmangizni rasmiylashtiring, yetkazib berish va to‘lov ma'lumotlarini to‘ldiring.",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const Page = () => {
|
||||
return <RefreshOrder />;
|
||||
|
||||
@@ -1,7 +1,81 @@
|
||||
// app/search/page.tsx
|
||||
import SearchResult from '@/features/search/ui/Search';
|
||||
import type { Metadata } from 'next';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
const page = () => {
|
||||
interface PageProps {
|
||||
searchParams: {
|
||||
q: string;
|
||||
};
|
||||
params: {
|
||||
locale: 'uz' | 'ru';
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateMetadata({
|
||||
searchParams,
|
||||
params,
|
||||
}: PageProps): Promise<Metadata> {
|
||||
const query = (await searchParams?.q?.trim()) || '';
|
||||
const { locale } = await params;
|
||||
|
||||
if (locale === 'ru') {
|
||||
const title = query
|
||||
? `Результаты поиска по запросу “${query}” - Gastro Market`
|
||||
: 'Поиск товаров - Gastro Market';
|
||||
const description = query
|
||||
? `Найдите все товары на Gastro Market по запросу “${query}”.`
|
||||
: 'Поиск всех товаров на Gastro Market.';
|
||||
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
keywords: query
|
||||
? `поиск, ${query}, товары, gastro market`
|
||||
: 'поиск, товары, gastro market',
|
||||
openGraph: {
|
||||
title,
|
||||
description,
|
||||
url: `/search${query ? `?q=${encodeURIComponent(query)}` : ''}`,
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title,
|
||||
description,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Default: Uzbek
|
||||
const title = query
|
||||
? `“${query}” bo‘yicha qidiruv natijalari - Gastro Market`
|
||||
: 'Mahsulot qidirish - Gastro Market';
|
||||
const description = query
|
||||
? `Gastro Marketda “${query}” bo‘yicha barcha mahsulotlarni toping.`
|
||||
: 'Gastro Marketdagi barcha mahsulotlarni qidirish.';
|
||||
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
keywords: query
|
||||
? `qidiruv, ${query}, mahsulotlar, gastro market`
|
||||
: 'qidiruv, mahsulotlar, gastro market',
|
||||
openGraph: {
|
||||
title,
|
||||
description,
|
||||
url: `/search${query ? `?q=${encodeURIComponent(query)}` : ''}`,
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title,
|
||||
description,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<Suspense>
|
||||
<SearchResult />
|
||||
@@ -9,4 +83,4 @@ const page = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default page;
|
||||
export default Page;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useRouter } from '@/shared/config/i18n/navigation';
|
||||
import { useCartId } from '@/shared/hooks/cartId';
|
||||
import { getMe, removeToken } from '@/shared/lib/token';
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@/shared/ui/avatar';
|
||||
import { Button } from '@/shared/ui/button';
|
||||
@@ -16,6 +17,7 @@ const Profile = () => {
|
||||
const t = useTranslations();
|
||||
const queryClient = useQueryClient();
|
||||
const user = getMe();
|
||||
const { setCartId } = useCartId();
|
||||
|
||||
const menuItems = [
|
||||
{ id: 'overview', label: 'Umumiy', icon: Home },
|
||||
@@ -98,7 +100,9 @@ const Profile = () => {
|
||||
onClick={() => {
|
||||
queryClient.refetchQueries({ queryKey: ['product_list'] });
|
||||
queryClient.refetchQueries({ queryKey: ['favourite_product'] });
|
||||
queryClient.refetchQueries({ queryKey: ['cart_items'] });
|
||||
queryClient.refetchQueries({ queryKey: ['search'] });
|
||||
setCartId(null);
|
||||
removeToken();
|
||||
router.push('/');
|
||||
}}
|
||||
@@ -130,11 +134,13 @@ const Profile = () => {
|
||||
size="icon"
|
||||
onClick={() => {
|
||||
queryClient.refetchQueries({ queryKey: ['product_list'] });
|
||||
queryClient.refetchQueries({ queryKey: ['cart_items'] });
|
||||
queryClient.refetchQueries({
|
||||
queryKey: ['favourite_product'],
|
||||
});
|
||||
queryClient.refetchQueries({ queryKey: ['search'] });
|
||||
removeToken();
|
||||
setCartId(null);
|
||||
router.push('/');
|
||||
}}
|
||||
className="w-9 h-9 md:w-10 md:h-10"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
'use client';
|
||||
|
||||
import { usePathname } from '@/shared/config/i18n/navigation';
|
||||
import { LanguageRoutes } from '@/shared/config/i18n/types';
|
||||
import { Button } from '@/shared/ui/button';
|
||||
import {
|
||||
@@ -10,7 +9,7 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
} from '@/shared/ui/dropdown-menu';
|
||||
import Image from 'next/image';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useParams, usePathname, useRouter } from 'next/navigation';
|
||||
import { languages } from '../lib/data';
|
||||
|
||||
export const MobileLanguageSelector = () => {
|
||||
|
||||
@@ -82,8 +82,10 @@ const Navbar = () => {
|
||||
if (cartItems) {
|
||||
const total = cartItems.reduce((sum, item) => sum + item.quantity, 0);
|
||||
setCartQuenty(total > 9 ? 9 : total);
|
||||
} else if (cart_id === null) {
|
||||
setCartQuenty(0);
|
||||
}
|
||||
}, [cartItems]);
|
||||
}, [cartItems, cart_id]);
|
||||
|
||||
useEffect(() => {
|
||||
setQuery(queryFromUrl);
|
||||
|
||||
Reference in New Issue
Block a user