diff --git a/src/app/[locale]/about/page.tsx b/src/app/[locale]/about/page.tsx index 1164e29..3a8e13f 100644 --- a/src/app/[locale]/about/page.tsx +++ b/src/app/[locale]/about/page.tsx @@ -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 { + 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 ( diff --git a/src/app/[locale]/auth/page.tsx b/src/app/[locale]/auth/page.tsx index d97fc7f..766362f 100644 --- a/src/app/[locale]/auth/page.tsx +++ b/src/app/[locale]/auth/page.tsx @@ -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 { + 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 ( diff --git a/src/app/[locale]/cart/order/page.tsx b/src/app/[locale]/cart/order/page.tsx index 72a3f84..00d743c 100644 --- a/src/app/[locale]/cart/order/page.tsx +++ b/src/app/[locale]/cart/order/page.tsx @@ -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 { + 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 ( @@ -9,4 +60,4 @@ const page = () => { ); }; -export default page; +export default Page; diff --git a/src/app/[locale]/cart/page.tsx b/src/app/[locale]/cart/page.tsx index 169842c..908d780 100644 --- a/src/app/[locale]/cart/page.tsx +++ b/src/app/[locale]/cart/page.tsx @@ -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 { + 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 ( @@ -9,4 +60,4 @@ const page = () => { ); }; -export default page; +export default Page; diff --git a/src/app/[locale]/category/[categoryId]/page.tsx b/src/app/[locale]/category/[categoryId]/page.tsx index 5f9a5f5..77c27a2 100644 --- a/src/app/[locale]/category/[categoryId]/page.tsx +++ b/src/app/[locale]/category/[categoryId]/page.tsx @@ -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 { + 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 ( @@ -9,4 +65,4 @@ const page = () => { ); }; -export default page; +export default Page; diff --git a/src/app/[locale]/category/page.tsx b/src/app/[locale]/category/page.tsx index 096200a..0b459f2 100644 --- a/src/app/[locale]/category/page.tsx +++ b/src/app/[locale]/category/page.tsx @@ -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 { + 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 ( @@ -9,4 +90,4 @@ const page = () => { ); }; -export default page; +export default Page; diff --git a/src/app/[locale]/faq/page.tsx b/src/app/[locale]/faq/page.tsx index 8aee4b4..2521ae1 100644 --- a/src/app/[locale]/faq/page.tsx +++ b/src/app/[locale]/faq/page.tsx @@ -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 { + 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 ( -
+ -
+
); }; -export default page; +export default Page; diff --git a/src/app/[locale]/favourite/page.tsx b/src/app/[locale]/favourite/page.tsx index b480835..c1f246f 100644 --- a/src/app/[locale]/favourite/page.tsx +++ b/src/app/[locale]/favourite/page.tsx @@ -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 { + 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 ( @@ -9,4 +86,4 @@ const page = () => { ); }; -export default page; +export default Page; diff --git a/src/app/[locale]/page.tsx b/src/app/[locale]/page.tsx index e232b13..bb94221 100644 --- a/src/app/[locale]/page.tsx +++ b/src/app/[locale]/page.tsx @@ -9,7 +9,7 @@ export async function generateMetadata({ params }: Props): Promise { 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 { openGraph: { title: titles[locale], description: descriptions[locale], - siteName: 'Mahsulotlar do‘koni', + siteName: 'GASTRO', images: [ { url: '/logos/logo.png', diff --git a/src/app/[locale]/privacy-policy/page.tsx b/src/app/[locale]/privacy-policy/page.tsx index e966baf..0a1bfb7 100644 --- a/src/app/[locale]/privacy-policy/page.tsx +++ b/src/app/[locale]/privacy-policy/page.tsx @@ -1,11 +1,63 @@ +// app/privacy-policy/page.tsx import PrivacyPolicy from '@/features/privacy-policy/ui/PrivacyPlicy'; +import { Metadata } from 'next'; -const page = () => { - return ( -
- -
- ); +interface PageProps { + params: { + locale: 'uz' | 'ru'; + }; +} + +// Dynamic metadata (bilingval) +export async function generateMetadata({ + params, +}: PageProps): Promise { + 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 ; }; -export default page; +export default Page; diff --git a/src/app/[locale]/product/[product]/page.tsx b/src/app/[locale]/product/[product]/page.tsx index a5460f8..475d8b3 100644 --- a/src/app/[locale]/product/[product]/page.tsx +++ b/src/app/[locale]/product/[product]/page.tsx @@ -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 { + 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 ( @@ -9,4 +72,4 @@ const page = () => { ); }; -export default page; +export default Page; diff --git a/src/app/[locale]/profile/page.tsx b/src/app/[locale]/profile/page.tsx index 78e736e..d4c2d72 100644 --- a/src/app/[locale]/profile/page.tsx +++ b/src/app/[locale]/profile/page.tsx @@ -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 { + 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 ( @@ -9,4 +69,4 @@ const page = () => { ); }; -export default page; +export default Page; diff --git a/src/app/[locale]/profile/refresh-order/page.tsx b/src/app/[locale]/profile/refresh-order/page.tsx index 18a5fa2..a8d2426 100644 --- a/src/app/[locale]/profile/refresh-order/page.tsx +++ b/src/app/[locale]/profile/refresh-order/page.tsx @@ -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 { + 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 ; diff --git a/src/app/[locale]/search/page.tsx b/src/app/[locale]/search/page.tsx index 0fe8343..3e7b120 100644 --- a/src/app/[locale]/search/page.tsx +++ b/src/app/[locale]/search/page.tsx @@ -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 { + 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 ( @@ -9,4 +83,4 @@ const page = () => { ); }; -export default page; +export default Page; diff --git a/src/features/profile/ui/Profile.tsx b/src/features/profile/ui/Profile.tsx index d798134..afede84 100644 --- a/src/features/profile/ui/Profile.tsx +++ b/src/features/profile/ui/Profile.tsx @@ -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" diff --git a/src/widgets/navbar/ui/MobileLanguageSelector.tsx b/src/widgets/navbar/ui/MobileLanguageSelector.tsx index 297c486..35a5945 100644 --- a/src/widgets/navbar/ui/MobileLanguageSelector.tsx +++ b/src/widgets/navbar/ui/MobileLanguageSelector.tsx @@ -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 = () => { diff --git a/src/widgets/navbar/ui/index.tsx b/src/widgets/navbar/ui/index.tsx index ec02e35..544d057 100644 --- a/src/widgets/navbar/ui/index.tsx +++ b/src/widgets/navbar/ui/index.tsx @@ -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);