diff --git a/src/app/[locale]/about/page.tsx b/src/app/[locale]/about/page.tsx index 3a8e13f..d384577 100644 --- a/src/app/[locale]/about/page.tsx +++ b/src/app/[locale]/about/page.tsx @@ -1,3 +1,6 @@ +// app/[locale]/about/page.tsx +import { partner_api } from '@/features/about/lib/api'; +import { AboutData } from '@/features/about/lib/type'; import { AboutContent } from '@/features/about/ui/AboutContent'; import { AboutHero } from '@/features/about/ui/AboutHero'; import { PartnershipForm } from '@/features/about/ui/AboutPage'; @@ -7,55 +10,72 @@ interface Props { params: { locale: 'uz' | 'ru' }; } +// Dynamic SEO uchun server-side API chaqiruvi export async function generateMetadata({ params }: Props): Promise { - const { locale } = await params; + const { locale } = params; - const titles = { - uz: 'Biz haqimizda | GASTRO', - ru: 'О нас | Магазин товаров', - }; + try { + const res = await partner_api.getAbout(); + const data: AboutData = res.data; - const descriptions = { - uz: 'Bizning onlayn do‘konimizda sifatli mahsulotlarni toping. Tez yetkazib berish va qulay to‘lov imkoniyatlari mavjud.', - ru: 'В нашем онлайн-магазине вы найдете качественные товары. Быстрая доставка и удобная оплата.', - }; + const banner = data.banner; - const keywords = { - uz: 'mahsulot, onlayn do‘kon, xarid, yetkazib berish', - ru: 'товары, онлайн-магазин, покупка, доставка', - }; + const title = + locale === 'uz' + ? banner.title_uz + : locale === 'ru' + ? banner.title_ru + : banner.title_en; - 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 description = + locale === 'uz' + ? banner.description_uz + : locale === 'ru' + ? banner.description_ru + : banner.description_en; + + return { + title: title || 'Gastro Market', + description: + description || 'Gastro Market – gastronomiya va kulinariya olami', + openGraph: { + title: title || 'Gastro Market', + description: + description || 'Gastro Market – gastronomiya va kulinariya olami', + siteName: 'GASTRO', + images: [ + { + url: banner.image ? '/' + banner.image : '/logos/logo.png', + width: 1200, + height: 1200, + alt: title || 'Gastro Market', + }, + ], + locale: locale === 'uz' ? 'uz_UZ' : 'ru_RU', + type: 'website', + }, + twitter: { + card: 'summary_large_image', + title: title || 'Gastro Market', + description: + description || 'Gastro Market – gastronomiya va kulinariya olami', + images: [banner.image ? '/' + banner.image : '/logos/logo.png'], + }, + }; + } catch (err) { + console.error('About metadata error:', err); + return { + title: 'Gastro Market', + description: 'Gastro Market – gastronomiya va kulinariya olami', + }; + } } -const page = () => { +// Page component +const page = async () => { return (
+ {/* Hero va Content ichida React Query ishlatilgan loading + dynamic data */} diff --git a/src/features/about/lib/api.ts b/src/features/about/lib/api.ts index 0bead3e..3f4799c 100644 --- a/src/features/about/lib/api.ts +++ b/src/features/about/lib/api.ts @@ -1,9 +1,16 @@ import httpClient from '@/shared/config/api/httpClient'; import { API_URLS } from '@/shared/config/api/URLs'; +import { AxiosResponse } from 'axios'; +import { AboutData } from './type'; export const partner_api = { async send(body: FormData) { const res = httpClient.post(API_URLS.Partners, body); return res; }, + + async getAbout(): Promise> { + const res = httpClient.get(API_URLS.About); + return res; + }, }; diff --git a/src/features/about/lib/type.ts b/src/features/about/lib/type.ts index 921b702..46f6c50 100644 --- a/src/features/about/lib/type.ts +++ b/src/features/about/lib/type.ts @@ -4,3 +4,35 @@ export interface PartnerSendBody { phone_number: string; file: File; } + +export interface AboutData { + banner: { + id: number; + created_at: string; + updated_at: string; + title_uz: string; + title_ru: string; + title_en: string; + description_uz: string; + description_ru: string; + description_en: string; + image: string; + }; + images: { + id: number; + created_at: string; + updated_at: string; + image: string; + }[]; + text: { + id: number; + created_at: string; + updated_at: string; + title_uz: string; + title_ru: string; + title_en: string; + description_uz: string; + description_ru: string; + description_en: string; + }[]; +} diff --git a/src/features/about/ui/AboutContent.tsx b/src/features/about/ui/AboutContent.tsx index 782e134..c780e02 100644 --- a/src/features/about/ui/AboutContent.tsx +++ b/src/features/about/ui/AboutContent.tsx @@ -1,85 +1,80 @@ -import { Card } from '@/shared/ui/card'; +'use client'; + +import { BASE_URL } from '@/shared/config/api/URLs'; +import { Skeleton } from '@/shared/ui/skeleton'; +import { useQuery } from '@tanstack/react-query'; import { useTranslations } from 'next-intl'; import Image from 'next/image'; +import { useParams } from 'next/navigation'; +import { partner_api } from '../lib/api'; export function AboutContent() { const t = useTranslations(); - const features = [ - { - number: '1', - title: 'Sifatli Kontent', - description: - "Jahon oshpazlik san'ati va zamonaviy gastronomiya tendentsiyalari haqida chuqur maqolalar va tahlillar", - }, - { - number: '2', - title: 'Professional Jamoa', - description: - 'Tajribali kulinariya mutaxassislari va oshpazlar tomonidan tayyorlangan kontent', - }, - { - number: '3', - title: 'Yangiliklar', - description: - "Gastronomiya sohasidagi so'nggi yangiliklar va eng yangi trendlar haqida xabarlar", - }, - ]; + const { locale } = useParams(); - const images = [ - { - url: '/professional-chef-cooking-gourmet-food.jpg', - alt: 'Professional Oshpaz', + const { data: about, isLoading: loadingText } = useQuery({ + queryKey: ['aboutText'], + queryFn: async () => { + return partner_api.getAbout(); }, - { - url: '/fine-dining-restaurant-plating.jpg', - alt: 'Fine Dining', + select(data) { + return data.data; }, - { - url: '/fresh-ingredients-culinary-market.jpg', - alt: 'Fresh Ingredients', - }, - ]; + }); + + const aboutText = about?.text; + const images = about?.images; + + // Loading holati + if (loadingText) { + return ( +
+
+ {/* Text Skeleton */} +
+ + + +
+ + {/* Image Gallery Skeleton */} +
+ +
+ {[...Array(3)].map((_, idx) => ( + + ))} +
+
+
+
+ ); + } return (
- {/* Mission Section */} -
-

- {t('Bizning maqsadimiz')} -

-
- {features.map((feature) => ( - -
- {feature.number} -
-

- {t(feature.title)} -

-

- {t(feature.description)} -

-
- ))} -
-
- {/* About Text */} -
+

- {t('Innovatsiya, sifat va professionallik')} + {locale === 'uz' + ? aboutText?.[0]?.title_uz || 'Gastro Market' + : locale === 'ru' + ? aboutText?.[0]?.title_ru || 'Gastro Market' + : aboutText?.[0]?.title_en || 'Gastro Market'}

- {t( - `Gastro Market – bu gastronomiya dunyosidagi eng so'nggi yangiliklarni`, - )} -

-

- {t(`Bizning jamoamiz tajribali kulinariya mutaxassislari`)} + {locale === 'uz' + ? aboutText?.[0]?.description_uz || + "Gastronomiya va kulinariya san'ati haqidagi yetakchi onlayn magazin" + : locale === 'ru' + ? aboutText?.[0]?.description_ru || + 'Ведущий интернет-магазин по гастрономии и кулинарному искусству' + : aboutText?.[0]?.description_en || + "Gastronomiya va kulinariya san'ati haqidagi yetakchi onlayn magazin"}

@@ -89,7 +84,7 @@ export function AboutContent() { {t('Bizning dunyo')}
- {images.map((image, idx) => ( + {images?.map((image, idx) => (
diff --git a/src/features/about/ui/AboutHero.tsx b/src/features/about/ui/AboutHero.tsx index 6e08536..356969d 100644 --- a/src/features/about/ui/AboutHero.tsx +++ b/src/features/about/ui/AboutHero.tsx @@ -1,8 +1,40 @@ -import { useTranslations } from 'next-intl'; +'use client'; + +import { BASE_URL } from '@/shared/config/api/URLs'; +import { Skeleton } from '@/shared/ui/skeleton'; +import { useQuery } from '@tanstack/react-query'; import Image from 'next/image'; +import { useParams } from 'next/navigation'; +import { partner_api } from '../lib/api'; export function AboutHero() { - const t = useTranslations(); + const { locale } = useParams(); + + const { data: banner, isLoading } = useQuery({ + queryKey: ['about'], + queryFn: async () => { + return partner_api.getAbout(); + }, + select(data) { + return data.data.banner; + }, + }); + + if (isLoading) { + return ( +
+ {/* Background skeleton */} + + {/* Content skeleton */} +
+ + + +
+
+ ); + } + return (
@@ -10,19 +42,31 @@ export function AboutHero() { width={500} height={500} unoptimized - src="/gourmet-food-culinary-magazine-hero-image.jpg" + src={ + BASE_URL + banner?.image || + '/gourmet-food-culinary-magazine-hero-image.jpg' + } alt="Gastro Market" className="w-full h-full object-cover brightness-50" />

- Gastro Market + {locale === 'uz' + ? banner?.title_uz || 'Gastro Market' + : locale === 'ru' + ? banner?.title_ru || 'Gastro Market' + : banner?.title_en || 'Gastro Market'}

- {t( - "Gastronomiya va kulinariya san'ati haqidagi yetakchi onlayn magazin", - )} + {locale === 'uz' + ? banner?.description_uz || + "Gastronomiya va kulinariya san'ati haqidagi yetakchi onlayn magazin" + : locale === 'ru' + ? banner?.description_ru || + 'Ведущий интернет-магазин по гастрономии и кулинарному искусству' + : banner?.description_en || + "Gastronomiya va kulinariya san'ati haqidagi yetakchi onlayn magazin"}

diff --git a/src/features/category/ui/SubCategory.tsx b/src/features/category/ui/SubCategory.tsx index 142d50f..f177212 100644 --- a/src/features/category/ui/SubCategory.tsx +++ b/src/features/category/ui/SubCategory.tsx @@ -27,8 +27,6 @@ const SubCategory = () => { router.push(`/category/${categoryId}/${subCategory.id}`); }; - console.log(categorys); - return (
<> diff --git a/src/shared/config/api/URLs.ts b/src/shared/config/api/URLs.ts index 6d91013..6ba5d7e 100644 --- a/src/shared/config/api/URLs.ts +++ b/src/shared/config/api/URLs.ts @@ -24,4 +24,5 @@ export const API_URLS = { OrderList: `${API_V}orders/order/list/`, Refresh_Token: `${API_V}accounts/refresh/token/`, Get_Me: `${API_V}accounts/me/`, + About: `${API_V}shared/aboutus/`, };