api ulandi
This commit is contained in:
@@ -1,6 +1,24 @@
|
||||
const BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_URL || 'https://jsonplaceholder.typicode.com';
|
||||
export const BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_URL || 'https://api.gastro.felixits.uz';
|
||||
|
||||
const ENDP_POSTS = '/posts/';
|
||||
export const API_V = '/api/v1/';
|
||||
|
||||
export { BASE_URL, ENDP_POSTS };
|
||||
export const API_URLS = {
|
||||
Banner: `${API_V}shared/banner/list/`,
|
||||
Category: `${API_V}products/category/list/`,
|
||||
Product: `${API_V}products/product/`,
|
||||
Login: `${API_V}accounts/login/`,
|
||||
Search_Product: `${API_V}products/search/`,
|
||||
Favourite: (product_id: string) => `${API_V}accounts/${product_id}/like/`,
|
||||
FavouriteProduct: `${API_V}accounts/liked_products/`,
|
||||
Partners: `${API_V}accounts/questionnaire/send/`,
|
||||
Faq: `${API_V}shared/faq/list/`,
|
||||
CartCrate: `${API_V}orders/cart/create/`,
|
||||
CartItem: `${API_V}orders/cart-item/create/`,
|
||||
CartClear: (id: number | string) => `${API_V}orders/cart/${id}/clear/`,
|
||||
CartItemList: (id: string) => `${API_V}orders/cart/${id}/`,
|
||||
CartItemUpdate: (id: string) => `${API_V}orders/cart-item/${id}/update/`,
|
||||
CartItemDelete: (id: string) => `${API_V}orders/cart-item/${id}/delete/`,
|
||||
CreateOrder: `${API_V}orders/order/create/`,
|
||||
OrderList: `${API_V}orders/order/list/`,
|
||||
};
|
||||
|
||||
14
src/shared/config/api/category/api.ts
Normal file
14
src/shared/config/api/category/api.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { AxiosResponse } from 'axios';
|
||||
import httpClient from '../httpClient';
|
||||
import { API_URLS } from '../URLs';
|
||||
import { Category } from './type';
|
||||
|
||||
export const category_api = {
|
||||
async getCategory(params: {
|
||||
page: number;
|
||||
page_size: number;
|
||||
}): Promise<AxiosResponse<Category>> {
|
||||
const res = await httpClient.get(API_URLS.Category, { params });
|
||||
return res;
|
||||
},
|
||||
};
|
||||
15
src/shared/config/api/category/type.ts
Normal file
15
src/shared/config/api/category/type.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
export interface Category {
|
||||
total: number;
|
||||
page: number;
|
||||
page_size: number;
|
||||
total_pages: number;
|
||||
has_next: boolean;
|
||||
has_previous: boolean;
|
||||
results: CategoryResult[];
|
||||
}
|
||||
|
||||
export interface CategoryResult {
|
||||
id: string;
|
||||
name: string;
|
||||
image: string;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import getLocaleCS from '@/shared/lib/getLocaleCS';
|
||||
import axios from 'axios';
|
||||
import { getToken, removeToken } from '@/shared/lib/token';
|
||||
import axios, { AxiosError } from 'axios';
|
||||
import { getLocale } from 'next-intl/server';
|
||||
import { LanguageRoutes } from '../i18n/types';
|
||||
import { BASE_URL } from './URLs';
|
||||
@@ -20,10 +21,10 @@ httpClient.interceptors.request.use(
|
||||
}
|
||||
|
||||
config.headers['Accept-Language'] = language;
|
||||
// const accessToken = localStorage.getItem('accessToken');
|
||||
// if (accessToken) {
|
||||
// config.headers['Authorization'] = `Bearer ${accessToken}`;
|
||||
// }
|
||||
const accessToken = getToken();
|
||||
if (accessToken) {
|
||||
config.headers['Authorization'] = `Bearer ${accessToken}`;
|
||||
}
|
||||
|
||||
return config;
|
||||
},
|
||||
@@ -34,6 +35,11 @@ httpClient.interceptors.response.use(
|
||||
(response) => response,
|
||||
(error) => {
|
||||
console.error('API error:', error);
|
||||
if ((error as AxiosError)?.status === 403) {
|
||||
removeToken();
|
||||
} else if ((error as AxiosError)?.status === 401) {
|
||||
removeToken();
|
||||
}
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
|
||||
0
src/shared/config/api/order/api.ts
Normal file
0
src/shared/config/api/order/api.ts
Normal file
0
src/shared/config/api/order/type.ts
Normal file
0
src/shared/config/api/order/type.ts
Normal file
60
src/shared/config/api/product/api.ts
Normal file
60
src/shared/config/api/product/api.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import httpClient from '@/shared/config/api/httpClient';
|
||||
import { API_URLS } from '@/shared/config/api/URLs';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import {
|
||||
FavouriteProduct,
|
||||
ProductDetail,
|
||||
ProductList,
|
||||
SearchData,
|
||||
} from './type';
|
||||
|
||||
export const product_api = {
|
||||
async list(params: {
|
||||
page: number;
|
||||
page_size: number;
|
||||
}): Promise<AxiosResponse<ProductList>> {
|
||||
const res = await httpClient.get(`${API_URLS.Product}list/`, { params });
|
||||
return res;
|
||||
},
|
||||
|
||||
async listGetCategoryId({
|
||||
params,
|
||||
category_id,
|
||||
}: {
|
||||
params: {
|
||||
page: number;
|
||||
page_size: number;
|
||||
};
|
||||
category_id: string;
|
||||
}): Promise<AxiosResponse<ProductList>> {
|
||||
const res = await httpClient.get(
|
||||
`${API_URLS.Product}${category_id}/list/`,
|
||||
{ params },
|
||||
);
|
||||
return res;
|
||||
},
|
||||
|
||||
async detail(id: string): Promise<AxiosResponse<ProductDetail>> {
|
||||
const res = await httpClient.get(`${API_URLS.Product}${id}`);
|
||||
return res;
|
||||
},
|
||||
|
||||
async search(params: {
|
||||
search?: string;
|
||||
page?: number;
|
||||
page_szie?: number;
|
||||
}): Promise<AxiosResponse<SearchData>> {
|
||||
const res = await httpClient.get(`${API_URLS.Search_Product}`, { params });
|
||||
return res;
|
||||
},
|
||||
|
||||
async favourite(product_id: string) {
|
||||
const res = await httpClient.get(API_URLS.Favourite(product_id));
|
||||
return res;
|
||||
},
|
||||
|
||||
async favouuriteProduct(): Promise<AxiosResponse<FavouriteProduct>> {
|
||||
const res = await httpClient.get(API_URLS.FavouriteProduct);
|
||||
return res;
|
||||
},
|
||||
};
|
||||
98
src/shared/config/api/product/type.ts
Normal file
98
src/shared/config/api/product/type.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
export interface ProductList {
|
||||
total: number;
|
||||
page: number;
|
||||
page_size: number;
|
||||
total_pages: number;
|
||||
has_next: boolean;
|
||||
has_previous: boolean;
|
||||
results: ProductListResult[];
|
||||
}
|
||||
|
||||
export interface ProductListResult {
|
||||
id: string;
|
||||
name: string;
|
||||
image: string;
|
||||
price: number;
|
||||
description: string;
|
||||
liked: boolean;
|
||||
unity: {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
min_quantity: number;
|
||||
is_active: boolean;
|
||||
}
|
||||
|
||||
export interface ProductDetail {
|
||||
brand: string;
|
||||
description: string;
|
||||
expires_date: null | string;
|
||||
id: string;
|
||||
image: string;
|
||||
images: {
|
||||
id: string;
|
||||
image: string;
|
||||
}[];
|
||||
is_active: boolean;
|
||||
liked: boolean;
|
||||
manufacturer: string;
|
||||
min_quantity: number;
|
||||
name: string;
|
||||
price: number;
|
||||
return_date: null | string;
|
||||
volume: string;
|
||||
unity: {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SearchData {
|
||||
products: SearchDataPro[];
|
||||
}
|
||||
|
||||
export interface SearchDataPro {
|
||||
id: string;
|
||||
name: string;
|
||||
image: string;
|
||||
price: number;
|
||||
description: string;
|
||||
liked: boolean;
|
||||
unity: {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
min_quantity: number;
|
||||
is_active: boolean;
|
||||
}
|
||||
|
||||
export interface FavouriteProduct {
|
||||
total: number;
|
||||
page: number;
|
||||
page_size: number;
|
||||
total_pages: number;
|
||||
has_next: boolean;
|
||||
has_previous: boolean;
|
||||
results: FavouriteProductRes[];
|
||||
}
|
||||
|
||||
export interface FavouriteProductRes {
|
||||
id: string;
|
||||
name: string;
|
||||
image: string;
|
||||
price: number;
|
||||
description: string;
|
||||
unity: {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
min_quantity: number;
|
||||
is_active: boolean;
|
||||
liked: boolean;
|
||||
brand: null | string;
|
||||
return_date: null | string;
|
||||
expires_date: null | string;
|
||||
manufacturer: null | string;
|
||||
volume: null | string;
|
||||
images: { id: string; image: string }[];
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { ENDP_POSTS } from '@/shared/config/api/URLs';
|
||||
import { ReqWithPagination } from './types';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import { TestApiType } from '@/shared/types/testApi';
|
||||
import httpClient from './httpClient';
|
||||
|
||||
const getPosts = async (
|
||||
pagination?: ReqWithPagination,
|
||||
): Promise<AxiosResponse<TestApiType>> => {
|
||||
const response = await httpClient.get(ENDP_POSTS, { params: pagination });
|
||||
return response;
|
||||
};
|
||||
|
||||
export { getPosts };
|
||||
|
||||
@@ -1,6 +1,196 @@
|
||||
{
|
||||
"HomePage": {
|
||||
"title": "Hello world!",
|
||||
"about": "Go to the about page"
|
||||
}
|
||||
"Biz haqimizda": "О нас",
|
||||
"Maxfiylik siyosati": "Политика конфиденциальности",
|
||||
"Savol-javob": "Вопросы и ответы",
|
||||
"Sahifalar": "Страницы",
|
||||
"Biz bilan bog'laning": "Свяжитесь с нами",
|
||||
"Русский": "Русский",
|
||||
"O'zbekcha": "Узбекский",
|
||||
"Mahsulot nomi": "Название продукта",
|
||||
"Tizimga kirilmagan": "Нет входа в систему",
|
||||
"Mahsulotni yuklab bo‘lmadi": "Не удалось загрузить товар. Попробуйте ещё раз.",
|
||||
"Savatga": "В корзину",
|
||||
"Kategoriyalar": "Категории",
|
||||
"Gastronomiya va kulinariya san'ati haqidagi yetakchi onlayn magazin": "Ведущий интернет-магазин по гастрономии и кулинарному искусству",
|
||||
"Bizning maqsadimiz": "Наша цель",
|
||||
"Sifatli Kontent": "Качественный контент",
|
||||
"Jahon oshpazlik san'ati va zamonaviy gastronomiya tendentsiyalari haqida chuqur maqolalar va tahlillar": "Углубленные статьи и анализы о мировом кулинарном искусстве и современных гастрономических тенденциях.",
|
||||
"Professional Jamoa": "Профессиональная команда",
|
||||
"Tajribali kulinariya mutaxassislari va oshpazlar tomonidan tayyorlangan kontent": "Контент подготовлен опытными кулинарами и поварами.",
|
||||
"Yangiliklar": "Новости",
|
||||
"Gastronomiya sohasidagi so'nggi yangiliklar va eng yangi trendlar haqida xabarlar": "Новости о последних новостях и новейших тенденциях в сфере гастрономии",
|
||||
"Innovatsiya, sifat va professionallik": "Инновации, качество и профессионализм",
|
||||
"Gastro Market – bu gastronomiya dunyosidagi eng so'nggi yangiliklarni": "Gastro Market — онлайн-платформа, на которой представлены последние новости, рецепты и тенденции в мире гастрономии. Мы стремимся предоставить нашим читателям качественный и интересный контент.",
|
||||
"Bizning jamoamiz tajribali kulinariya mutaxassislari": "Наша команда состоит из опытных кулинаров, поваров и экспертов в области гастрономии. В каждой статье мы уделяем особое внимание качеству и профессионализму.",
|
||||
"Bizning dunyo": "Наш мир",
|
||||
"Hamkor bo'ling": "Станьте партнером",
|
||||
"Gastro Market bilan hamkorlik qilishni xohlaysizmi?": "Хотите сотрудничать с Gastro Market? Заполните форму ниже, и мы свяжемся с вами в ближайшее время.",
|
||||
"Kompaniya nomi": "Название компании",
|
||||
"Website": "Веб-сайт",
|
||||
"Ism Familiya": "Имя и фамилия",
|
||||
"Email": "Электронная почта",
|
||||
"Telefon raqami": "Телефон",
|
||||
"Kompaniya hujjati": "Документ компании",
|
||||
"Faylni tanlang": "Выберите файл",
|
||||
"Tanlangan fayl": "Выбранный файл",
|
||||
"PDF yoki Word formatida (maksimal 5MB)": "В формате PDF или Word (макс. 5MB)",
|
||||
"So'rov yuborish": "Отправить запрос",
|
||||
"Kompaniya nomi kamida 2 ta belgidan iborat bo'lishi kerak": "Название компании должно содержать не менее 2 символов.",
|
||||
"Ism kamida 2 ta belgidan iborat bo'lishi kerak": "Имя должно содержать не менее 2 символов",
|
||||
"To'g'ri email manzilini kiriting": "Введите правильный адрес электронной почты",
|
||||
"To'g'ri telefon raqamini kiriting": "Введите правильный номер телефона",
|
||||
"File yuklash majburiy": "Загрузка файла обязательна",
|
||||
|
||||
"Maxfiylik Siyosati": "Политика конфиденциальности",
|
||||
"Gastro Market sizning ma'lumotlaringiz xavfsizligini jiddiy qabul qiladi": "Gastro Market серьезно относится к безопасности ваших данных",
|
||||
"Oxirgi yangilanish: 16 Dekabr 2025": "Последнее обновление: 16 декабря 2025",
|
||||
"Ushbu Maxfiylik Siyosati Gastro Market online magazinida siz tomonidan taqdim etilgan shaxsiy ma'lumotlarni qanday to'playmiz": "Эта Политика конфиденциальности объясняет, как Gastro Market собирает, использует и защищает персональные данные, предоставленные вами в онлайн-магазине. Используя наши услуги, вы соглашаетесь с описанными практиками.",
|
||||
|
||||
"Biz To'playdigan Ma'lumotlar": "1. Сбор информации",
|
||||
"Sizning tajribangizni yaxshilash uchun biz quyidagi ma'lumotlarni to'playmiz": "Имя, адрес электронной почты, номер телефона",
|
||||
"Kompaniya nomi, website, hamkorlik so'rovlari": "Название компании, веб-сайт, запросы на сотрудничество",
|
||||
"Hamkorlik uchun yuklangan hujjatlar": "Документы, загруженные для сотрудничества",
|
||||
"IP manzil, brauzer turi, qurilma ma'lumotlari": "IP-адрес, тип браузера, данные устройства",
|
||||
"Shaxsiy Ma'lumotlar": "Персональные данные",
|
||||
"Kompaniya Ma'lumotlari": "Информация о компании",
|
||||
"Fayllar:": "Файлы:",
|
||||
"Texnik Ma'lumotlar": "Технические данные",
|
||||
|
||||
"Ma'lumotlardan Foydalanish": "2. Использование данных",
|
||||
"To'plangan ma'lumotlaringizdan quyidagi maqsadlarda foydalanamiz:": "Мы будем использовать собранные вами данные для следующих целей:",
|
||||
"Hamkorlik so'rovlarini qayta ishlash va javob berish": "Обработка и ответ на запросы на сотрудничество",
|
||||
"Sizga xizmatlarimiz va yangiliklar haqida ma'lumot berish": "Предоставление информации о наших услугах и новостях",
|
||||
"Sayt xavfsizligini ta'minlash va firibgarlikka qarshi kurashish": "Обеспечение безопасности сайта и предотвращение мошенничества",
|
||||
"Foydalanuvchi tajribasini tahlil qilish va yaxshilash": "Анализ и улучшение пользовательского опыта",
|
||||
"Qonuniy talablarni bajarish": "Соблюдение законных требований",
|
||||
|
||||
"Ma'lumotlar Xavfsizligi": "3. Безопасность данных",
|
||||
"Biz sizning shaxsiy ma'lumotlaringizni himoya qilish uchun zamonaviy xavfsizlik choralarini qo'llaymiz:": "Мы применяем современные меры безопасности для защиты ваших персональных данных:",
|
||||
"SSL/TLS shifrlash orqali ma'lumotlar uzatish": "Передача данных с шифрованием SSL/TLS",
|
||||
"Xavfsiz serverlar va ma'lumotlar bazasida saqlash": "Хранение на безопасных серверах и в базе данных",
|
||||
"Cheklangan kirish huquqlari va autentifikatsiya": "Ограниченный доступ и аутентификация",
|
||||
"Doimiy xavfsizlik monitoringi va yangilanishlar": "Постоянный мониторинг безопасности и обновления",
|
||||
|
||||
"Ma'lumotlarni Ulashish": "4. Раскрытие данных",
|
||||
"Biz sizning shaxsiy ma'lumotlaringizni uchinchi shaxslarga sotmaymiz": "Мы не будем продавать ваши персональные данные третьим лицам.",
|
||||
"Sizning roziligingiz bilan": "С вашего согласия",
|
||||
"Qonuniy talablar bo'yicha": "В соответствии с законом",
|
||||
"Xizmat ko'rsatuvchi ishonchli hamkorlar bilan (maxfiylik shartnomalari ostida)": "С надежными партнерами (соглашения о конфиденциальности)",
|
||||
"Kompaniya birlashuvi yoki sotilishi holatida": "В случае слияния или продажи компании",
|
||||
|
||||
"Biz Bilan Bog'lanish": "Связь с нами",
|
||||
"Ushbu Maxfiylik Siyosati yoki shaxsiy ma'lumotlaringiz haqida savollaringiz bo'lsa, biz bilan bog'laning:": "Если у вас есть вопросы по данной Политике конфиденциальности или вашим данным, свяжитесь с нами:",
|
||||
"Telefon": "Телефон",
|
||||
"Toshkent, O'zbekiston": "Ташкент, Узбекистан",
|
||||
"Manzil": "Адрес",
|
||||
|
||||
"Miqdor": "Количество",
|
||||
"Jami": "Итого",
|
||||
"Bepul yetkazib berish": "Бесплатная доставка",
|
||||
"Kafolat": "Гарантия",
|
||||
"Xususiyatlari": "Характеристики",
|
||||
"Qadoq turi": "Тип упаковки",
|
||||
"Brandi": "Бренд",
|
||||
"Ishlab chiqaruvchi": "Производитель",
|
||||
"Hajmi": "Объем",
|
||||
"O'xshash mahsulotlar": "Похожие товары",
|
||||
|
||||
"Hech narsa topilmadi": "Не найдено",
|
||||
"Qidiruv natijalari": "Результаты поиска",
|
||||
"Tavsiya etiladi": "Рекомендуется",
|
||||
"Yuklanmoqda": "Загрузка...",
|
||||
"Natija topilmadi": "Нет результатов",
|
||||
|
||||
"Asosiy": "Основная",
|
||||
"Katalog": "Каталог",
|
||||
"Sevimli": "Избранное",
|
||||
"Savatda": "В корзине",
|
||||
"Profil": "Профиль",
|
||||
|
||||
"Username yoki parol xato kiritildi": "Неверное имя пользователя или пароль",
|
||||
"Tizimga kirish": "Войти в систему",
|
||||
"Username": "Имя пользователя",
|
||||
"Parol": "Пароль",
|
||||
"Kirish": "Вход",
|
||||
|
||||
"Savatingiz bo'sh": "Ваша корзина пуста",
|
||||
"Mahsulotlar qo'shish uchun katalogga o'ting": "Перейти в каталог, чтобы добавить товары",
|
||||
"Xarid qilishni boshlash": "Начать покупку",
|
||||
"Savat": "Корзина",
|
||||
"ta mahsulot": "товар(ов)",
|
||||
"Buyurtma haqida": "О заказе",
|
||||
"Mahsulotlar narxi": "Цена товаров",
|
||||
"Chegirma": "Скидка",
|
||||
"Yetkazib berish": "Доставка",
|
||||
"Bepul": "Бесплатно",
|
||||
"Buyurtmani rasmiylashtirish": "Оформить заказ",
|
||||
"Xaridni davom ettirish": "Продолжить покупки",
|
||||
"Tez yetkazib berish 1-2 kun ichida": "Быстрая доставка в течение 1-2 дней",
|
||||
"Xavfsiz to'lov usullari": "Безопасные способы оплаты",
|
||||
"Buyurtma qabul qilindi!": "Заказ принят!",
|
||||
"Buyurtma raqami": "Номер заказа",
|
||||
"Buyurtmangiz muvaffaqiyatli qabul qilindi": "Ваш заказ успешно принят.",
|
||||
"Bosh sahifaga qaytish": "Вернуться на главную",
|
||||
"Ma'lumotlaringizni to'ldiring": "Заполните ваши данные",
|
||||
"Shaxsiy ma'lumotlar": "Личные данные",
|
||||
"Ism": "Имя",
|
||||
"Ismingiz": "Ваше имя",
|
||||
"Familiya": "Фамилия",
|
||||
"Familiyangiz": "Ваша фамилия",
|
||||
"Telefon raqam": "Номер телефона",
|
||||
"Izoh": "Комментарий",
|
||||
"Yetkazib berish manzili": "Адрес доставки",
|
||||
"Manzilni qidirish": "Поиск адреса",
|
||||
"Toshkent": "Ташкент",
|
||||
"Mening joylashuvim": "Моё местоположение",
|
||||
|
||||
"Yetkazib berish usuli": "Способ доставки",
|
||||
"Standart yetkazib berish": "Стандартная доставка",
|
||||
"2-3 kun ichida": "В течение 2–3 дней",
|
||||
"Tez yetkazib berish": "Экспресс-доставка",
|
||||
"1 kun ichida": "В течение 1 дня",
|
||||
|
||||
"To'lov usuli": "Способ оплаты",
|
||||
"Naqd pul": "Наличные",
|
||||
"Yetkazib berishda to'lash": "Оплата при доставке",
|
||||
"Plastik karta": "Банковская карта",
|
||||
"Online to'lov": "Онлайн-оплата",
|
||||
|
||||
"Mahsulotlar": "Товары",
|
||||
"Buyurtmani tasdiqlash": "Подтвердить заказ",
|
||||
|
||||
"Majburiy maydon": "Обязательное поле",
|
||||
"Xato raqam kiritildi": "Введен неверный номер",
|
||||
"Orqaga": "Назад",
|
||||
|
||||
"Sevimlilar bo'sh": "Избранное пусто",
|
||||
"Hali hech qanday mahsulotni sevimlilarga qo'shmadingiz": "Вы пока не добавили ни одного товара в избранное. Перейдите в каталог и сохраните понравившиеся товары.",
|
||||
"Sevimli mahsulotlar": "Избранные товары",
|
||||
"Ism email manzil telefon raqami": "Имя, адрес электронной почты, номер телефона",
|
||||
|
||||
"Faol buyurtmalar": "Активные заказы",
|
||||
"Barchasi": "Все",
|
||||
"Buyurtmalar tarixi": "История заказов",
|
||||
"Qayta": "Повторить",
|
||||
"Chiqish": "Выйти",
|
||||
"Umumiy": "Общее",
|
||||
"Buyurtmalar": "Заказы",
|
||||
"Tarix": "История",
|
||||
|
||||
"Faol": "Активно",
|
||||
"Tugadi": "Заканчивается",
|
||||
"Yetkazish": "Доставка",
|
||||
"Yo'lda": "В пути",
|
||||
"Punktda": "В пункте",
|
||||
"Yetkazildi": "Доставлено",
|
||||
"Bekor qilindi": "Отменено",
|
||||
"Bu hafta": "На этой неделе",
|
||||
"Bu oy": "В этом месяце",
|
||||
"Qo'llab-quvatlash": "Поддержка",
|
||||
"Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling": "Если у вас нет логина и пароля для входа, пожалуйста, свяжитесь с нами",
|
||||
"Murojat qilish": "Заявление",
|
||||
"So'rov yuborildi!": "Запрос успешно отправлен!",
|
||||
|
||||
"Tez-tez So'raladigan Savollar": "Часто задаваемые вопросы",
|
||||
"Gastro Market haqida eng ko'p so'raladigan savollarga javoblar":"Ответы на самые часто задаваемые вопросы о Gastro Market"
|
||||
}
|
||||
|
||||
@@ -2,9 +2,196 @@
|
||||
// See: https://next-intl.dev/docs/workflows/typescript#messages-arguments
|
||||
|
||||
declare const messages: {
|
||||
HomePage: {
|
||||
title: 'Salom dunyo!';
|
||||
about: 'Go to the about page';
|
||||
};
|
||||
'Biz haqimizda': 'Biz haqimizda';
|
||||
'Maxfiylik siyosati': 'Maxfiylik siyosati';
|
||||
'Savol-javob': 'Savol-javob';
|
||||
Sahifalar: 'Sahifalar';
|
||||
"Biz bilan bog'laning": "Biz bilan bog'laning";
|
||||
Русский: 'Русский';
|
||||
"O'zbekcha": "O'zbekcha";
|
||||
'Mahsulot nomi': 'Mahsulot nomi';
|
||||
'Tizimga kirilmagan': 'Tizimga kirilmagan';
|
||||
'Mahsulotni yuklab bo‘lmadi': 'Mahsulotni yuklab bo‘lmadi. Qayta urinib ko‘ring.';
|
||||
Savatga: 'Savatga';
|
||||
Kategoriyalar: 'Kategoriyalar';
|
||||
"Gastronomiya va kulinariya san'ati haqidagi yetakchi onlayn magazin": "Gastronomiya va kulinariya san'ati haqidagi yetakchi onlayn magazin";
|
||||
'Bizning maqsadimiz': 'Bizning maqsadimiz';
|
||||
'Sifatli Kontent': 'Sifatli Kontent';
|
||||
"Jahon oshpazlik san'ati va zamonaviy gastronomiya tendentsiyalari haqida chuqur maqolalar va tahlillar": "Jahon oshpazlik san'ati va zamonaviy gastronomiya tendentsiyalari haqida chuqur maqolalar va tahlillar";
|
||||
'Professional Jamoa': 'Professional Jamoa';
|
||||
'Tajribali kulinariya mutaxassislari va oshpazlar tomonidan tayyorlangan kontent': 'Tajribali kulinariya mutaxassislari va oshpazlar tomonidan tayyorlangan kontent';
|
||||
Yangiliklar: 'Yangiliklar';
|
||||
"Gastronomiya sohasidagi so'nggi yangiliklar va eng yangi trendlar haqida xabarlar": "Gastronomiya sohasidagi so'nggi yangiliklar va eng yangi trendlar haqida xabarlar";
|
||||
'Innovatsiya, sifat va professionallik': 'Innovatsiya, sifat va professionallik';
|
||||
"Gastro Market – bu gastronomiya dunyosidagi eng so'nggi yangiliklarni": "Gastro Market – bu gastronomiya dunyosidagi eng so'nggi yangiliklarni, retseptlarni va tendentsiyalarni taqdim etuvchi onlayn platforma. Biz o'quvchilarimizga sifatli va qiziqarli kontent taqdim etishga intilamiz.";
|
||||
'Bizning jamoamiz tajribali kulinariya mutaxassislari': "Bizning jamoamiz tajribali kulinariya mutaxassislari, oshpazlar va gastronomiya sohasidagi ekspertlardan iborat. Biz har bir maqolada sifat va professionallikka e'tibor qaratamiz.";
|
||||
'Bizning dunyo': 'Bizning dunyo';
|
||||
"Hamkor bo'ling": "Hamkor bo'ling";
|
||||
'Gastro Market bilan hamkorlik qilishni xohlaysizmi?': "Gastro Market bilan hamkorlik qilishni xohlaysizmi? Quyidagi formani to'ldiring va biz siz bilan tez orada bog'lanamiz.";
|
||||
'Kompaniya nomi': 'Kompaniya nomi';
|
||||
Website: 'Website';
|
||||
'Ism Familiya': 'Ism Familiya';
|
||||
Email: 'Email';
|
||||
'Telefon raqami': 'Telefon raqami';
|
||||
'Kompaniya hujjati': 'Kompaniya hujjati';
|
||||
'Faylni tanlang': 'Faylni tanlang';
|
||||
'Tanlangan fayl': 'Tanlangan fayl';
|
||||
'PDF yoki Word formatida (maksimal 5MB)': 'PDF yoki Word formatida (maksimal 5MB)';
|
||||
"So'rov yuborish": "So'rov yuborish";
|
||||
"Kompaniya nomi kamida 2 ta belgidan iborat bo'lishi kerak": "Kompaniya nomi kamida 2 ta belgidan iborat bo'lishi kerak";
|
||||
"Ism kamida 2 ta belgidan iborat bo'lishi kerak": "Ism kamida 2 ta belgidan iborat bo'lishi kerak";
|
||||
"To'g'ri email manzilini kiriting": "To'g'ri email manzilini kiriting";
|
||||
"To'g'ri telefon raqamini kiriting": "To'g'ri telefon raqamini kiriting";
|
||||
'File yuklash majburiy': 'File yuklash majburiy';
|
||||
|
||||
'Maxfiylik Siyosati': 'Maxfiylik Siyosati';
|
||||
"Gastro Market sizning ma'lumotlaringiz xavfsizligini jiddiy qabul qiladi": "Gastro Market sizning ma'lumotlaringiz xavfsizligini jiddiy qabul qiladi";
|
||||
'Oxirgi yangilanish: 16 Dekabr 2025': 'Oxirgi yangilanish: 16 Dekabr 2025';
|
||||
"Ushbu Maxfiylik Siyosati Gastro Market online magazinida siz tomonidan taqdim etilgan shaxsiy ma'lumotlarni qanday to'playmiz": "Ushbu Maxfiylik Siyosati Gastro Market online magazinida siz tomonidan taqdim etilgan shaxsiy ma'lumotlarni qanday to'playmiz, ishlatamiz va himoya qilishimizni tushuntiradi. Xizmatlarimizdan foydalanish orqali siz ushbu siyosatda tasvirlangan amaliyotlarga rozilik bildirasiz.";
|
||||
|
||||
"Biz To'playdigan Ma'lumotlar": "1. Biz To'playdigan Ma'lumotlar";
|
||||
"Sizning tajribangizni yaxshilash uchun biz quyidagi ma'lumotlarni to'playmiz": "Sizning tajribangizni yaxshilash uchun biz quyidagi ma'lumotlarni to'playmiz:";
|
||||
'Ism email manzil telefon raqami': 'Ism, email manzil, telefon raqami';
|
||||
"Kompaniya nomi, website, hamkorlik so'rovlari": "Kompaniya nomi, website, hamkorlik so'rovlari";
|
||||
'Hamkorlik uchun yuklangan hujjatlar': 'Hamkorlik uchun yuklangan hujjatlar';
|
||||
"IP manzil, brauzer turi, qurilma ma'lumotlari": "IP manzil, brauzer turi, qurilma ma'lumotlari";
|
||||
"Shaxsiy Ma'lumotlar": "Shaxsiy Ma'lumotlar";
|
||||
"Kompaniya Ma'lumotlari": "Kompaniya Ma'lumotlari";
|
||||
'Fayllar:': 'Fayllar:';
|
||||
"Texnik Ma'lumotlar": "Texnik Ma'lumotlar";
|
||||
|
||||
"Ma'lumotlardan Foydalanish": "2. Ma'lumotlardan Foydalanish";
|
||||
"To'plangan ma'lumotlaringizdan quyidagi maqsadlarda foydalanamiz:": "To'plangan ma'lumotlaringizdan quyidagi maqsadlarda foydalanamiz:";
|
||||
"Hamkorlik so'rovlarini qayta ishlash va javob berish": "Hamkorlik so'rovlarini qayta ishlash va javob berish";
|
||||
"Sizga xizmatlarimiz va yangiliklar haqida ma'lumot berish": "Sizga xizmatlarimiz va yangiliklar haqida ma'lumot berish";
|
||||
"Sayt xavfsizligini ta'minlash va firibgarlikka qarshi kurashish": "Sayt xavfsizligini ta'minlash va firibgarlikka qarshi kurashish";
|
||||
'Foydalanuvchi tajribasini tahlil qilish va yaxshilash': 'Foydalanuvchi tajribasini tahlil qilish va yaxshilash';
|
||||
'Qonuniy talablarni bajarish': 'Qonuniy talablarni bajarish';
|
||||
|
||||
"Ma'lumotlar Xavfsizligi": "3. Ma'lumotlar Xavfsizligi";
|
||||
"Biz sizning shaxsiy ma'lumotlaringizni himoya qilish uchun zamonaviy xavfsizlik choralarini qo'llaymiz:": "Biz sizning shaxsiy ma'lumotlaringizni himoya qilish uchun zamonaviy xavfsizlik choralarini qo'llaymiz:";
|
||||
"SSL/TLS shifrlash orqali ma'lumotlar uzatish": "SSL/TLS shifrlash orqali ma'lumotlar uzatish";
|
||||
"Xavfsiz serverlar va ma'lumotlar bazasida saqlash": "Xavfsiz serverlar va ma'lumotlar bazasida saqlash";
|
||||
'Cheklangan kirish huquqlari va autentifikatsiya': 'Cheklangan kirish huquqlari va autentifikatsiya';
|
||||
'Doimiy xavfsizlik monitoringi va yangilanishlar': 'Doimiy xavfsizlik monitoringi va yangilanishlar';
|
||||
|
||||
"Ma'lumotlarni Ulashish": "4. Ma'lumotlarni Ulashish";
|
||||
"Biz sizning shaxsiy ma'lumotlaringizni uchinchi shaxslarga sotmaymiz": "Biz sizning shaxsiy ma'lumotlaringizni uchinchi shaxslarga sotmaymiz";
|
||||
'Sizning roziligingiz bilan': 'Sizning roziligingiz bilan';
|
||||
"Qonuniy talablar bo'yicha": "Qonuniy talablar bo'yicha";
|
||||
"Xizmat ko'rsatuvchi ishonchli hamkorlar bilan (maxfiylik shartnomalari ostida)": "Xizmat ko'rsatuvchi ishonchli hamkorlar bilan (maxfiylik shartnomalari ostida)";
|
||||
'Kompaniya birlashuvi yoki sotilishi holatida': 'Kompaniya birlashuvi yoki sotilishi holatida';
|
||||
|
||||
"Biz Bilan Bog'lanish": "Biz Bilan Bog'lanish";
|
||||
"Ushbu Maxfiylik Siyosati yoki shaxsiy ma'lumotlaringiz haqida savollaringiz bo'lsa, biz bilan bog'laning:": "Ushbu Maxfiylik Siyosati yoki shaxsiy ma'lumotlaringiz haqida savollaringiz bo'lsa, biz bilan bog'laning:";
|
||||
Telefon: 'Telefon';
|
||||
"Toshkent, O'zbekiston": "Toshkent, O'zbekiston";
|
||||
Manzil: 'Manzil';
|
||||
|
||||
Miqdor: 'Miqdor';
|
||||
Jami: 'Jami';
|
||||
'Bepul yetkazib berish': 'Bepul yetkazib berish';
|
||||
Kafolat: 'Kafolat';
|
||||
Xususiyatlari: 'Xususiyatlari';
|
||||
'Qadoq turi': 'Qadoq turi';
|
||||
Brandi: 'Brend';
|
||||
'Ishlab chiqaruvchi': 'Ishlab chiqaruvchi';
|
||||
Hajmi: 'Hajmi';
|
||||
"O'xshash mahsulotlar": "O'xshash mahsulotlar";
|
||||
|
||||
'Hech narsa topilmadi': 'Hech narsa topilmadi';
|
||||
'Qidiruv natijalari': 'Qidiruv natijalari';
|
||||
'Tavsiya etiladi': 'Tavsiya etiladi';
|
||||
Yuklanmoqda: 'Yuklanmoqda....';
|
||||
'Natija topilmadi': 'Natija topilmadi';
|
||||
|
||||
Asosiy: 'Asosiy';
|
||||
Katalog: 'Katalog';
|
||||
Sevimli: 'Sevimli';
|
||||
Savatda: 'Savatda';
|
||||
Profil: 'Profil';
|
||||
|
||||
'Username yoki parol xato kiritildi': 'Username yoki parol xato kiritildi';
|
||||
'Tizimga kirish': 'Tizimga kirish';
|
||||
Username: 'Username';
|
||||
Parol: 'Parol';
|
||||
Kirish: 'Kirish';
|
||||
|
||||
"Savatingiz bo'sh": "Savatingiz bo'sh";
|
||||
"Mahsulotlar qo'shish uchun katalogga o'ting": "Mahsulotlar qo'shish uchun katalogga o'ting";
|
||||
'Xarid qilishni boshlash': 'Xarid qilishni boshlash';
|
||||
Savat: 'Savat';
|
||||
'ta mahsulot': 'ta mahsulot';
|
||||
'Buyurtma haqida': 'Buyurtma haqida';
|
||||
'Mahsulotlar narxi': 'Mahsulotlar narxi';
|
||||
Chegirma: 'Chegirma';
|
||||
'Yetkazib berish': 'Yetkazib berish';
|
||||
Bepul: 'Bepul';
|
||||
'Buyurtmani rasmiylashtirish': 'Buyurtmani rasmiylashtirish';
|
||||
'Xaridni davom ettirish': 'Xaridni davom ettirish';
|
||||
'Tez yetkazib berish 1-2 kun ichida': 'Tez yetkazib berish 1-2 kun ichida';
|
||||
"Xavfsiz to'lov usullari": "Xavfsiz to'lov usullari";
|
||||
|
||||
'Buyurtma qabul qilindi!': 'Buyurtma qabul qilindi!';
|
||||
'Buyurtma raqami': 'Buyurtma raqami';
|
||||
'Buyurtmangiz muvaffaqiyatli qabul qilindi': 'Buyurtmangiz muvaffaqiyatli qabul qilindi.';
|
||||
'Bosh sahifaga qaytish': 'Bosh sahifaga qaytish';
|
||||
"Ma'lumotlaringizni to'ldiring": "Ma'lumotlaringizni to'ldiring";
|
||||
"Shaxsiy ma'lumotlar": "Shaxsiy ma'lumotlar";
|
||||
Ism: 'Ism';
|
||||
Ismingiz: 'Ismingiz';
|
||||
Familiya: 'Familiya';
|
||||
Familiyangiz: 'Familiyangiz';
|
||||
'Telefon raqam': 'Telefon raqam';
|
||||
Izoh: 'Izoh';
|
||||
'Yetkazib berish manzili': 'Yetkazib berish manzili';
|
||||
'Manzilni qidirish': 'Manzilni qidirish';
|
||||
Toshkent: 'Toshkent';
|
||||
'Mening joylashuvim': 'Mening joylashuvim';
|
||||
'Yetkazib berish usuli': 'Yetkazib berish usuli';
|
||||
'Standart yetkazib berish': 'Standart yetkazib berish';
|
||||
'2-3 kun ichida': '2-3 kun ichida';
|
||||
'Tez yetkazib berish': 'Tez yetkazib berish';
|
||||
'1 kun ichida': '1 kun ichida';
|
||||
"To'lov usuli": "To'lov usuli";
|
||||
'Naqd pul': 'Naqd pul';
|
||||
"Yetkazib berishda to'lash": "Yetkazib berishda to'lash";
|
||||
'Plastik karta': 'Plastik karta';
|
||||
"Online to'lov": "Online to'lov";
|
||||
Mahsulotlar: 'Mahsulotlar';
|
||||
'Buyurtmani tasdiqlash': 'Buyurtmani tasdiqlash';
|
||||
'Majburiy maydon': 'Majburiy maydon';
|
||||
'Xato raqam kiritildi': 'Xato raqam kiritildi';
|
||||
Orqaga: 'Orqaga';
|
||||
|
||||
"Sevimlilar bo'sh": "Sevimlilar bo'sh";
|
||||
"Hali hech qanday mahsulotni sevimlilarga qo'shmadingiz": "Hali hech qanday mahsulotni sevimlilarga qo'shmadingiz. Mahsulotlar ro'yxatiga o'ting va yoqqan mahsulotlaringizni saqlang.";
|
||||
'Sevimli mahsulotlar': 'Sevimli mahsulotlar';
|
||||
|
||||
'Faol buyurtmalar': 'Faol buyurtmalar';
|
||||
Barchasi: 'Barchasi';
|
||||
'Buyurtmalar tarixi': 'Buyurtmalar tarixi';
|
||||
Qayta: 'Qayta';
|
||||
Chiqish: 'Chiqish';
|
||||
Umumiy: 'Umumiy';
|
||||
Buyurtmalar: 'Buyurtmalar';
|
||||
Tarix: 'Tarix';
|
||||
|
||||
Faol: 'Faol';
|
||||
Tugadi: 'Tugadi';
|
||||
Yetkazish: 'Yetkazish';
|
||||
"Yo'lda": "Yo'lda";
|
||||
Punktda: 'Punktda';
|
||||
Yetkazildi: 'Yetkazildi';
|
||||
'Bekor qilindi': 'Bekor qilindi';
|
||||
'Bu hafta': 'Bu hafta';
|
||||
'Bu oy': 'Bu oy';
|
||||
"Qo'llab-quvatlash": "Qo'llab-quvatlash";
|
||||
"Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling": "Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling";
|
||||
'Murojat qilish': 'Murojat qilish';
|
||||
"So'rov yuborildi!": "So'rov yuborildi!";
|
||||
|
||||
"Tez-tez So'raladigan Savollar": "Tez-tez So'raladigan Savollar";
|
||||
"Gastro Market haqida eng ko'p so'raladigan savollarga javoblar": "Gastro Market haqida eng ko'p so'raladigan savollarga javoblar";
|
||||
};
|
||||
export default messages;
|
||||
|
||||
@@ -1,6 +1,193 @@
|
||||
{
|
||||
"HomePage": {
|
||||
"title": "Salom dunyo!",
|
||||
"about": "Go to the about page"
|
||||
}
|
||||
"Biz haqimizda": "Biz haqimizda",
|
||||
"Maxfiylik siyosati": "Maxfiylik siyosati",
|
||||
"Savol-javob": "Savol-javob",
|
||||
"Sahifalar": "Sahifalar",
|
||||
"Biz bilan bog'laning": "Biz bilan bog'laning",
|
||||
"Русский": "Русский",
|
||||
"O'zbekcha": "O'zbekcha",
|
||||
"Mahsulot nomi": "Mahsulot nomi",
|
||||
"Tizimga kirilmagan": "Tizimga kirilmagan",
|
||||
"Mahsulotni yuklab bo‘lmadi": "Mahsulotni yuklab bo‘lmadi. Qayta urinib ko‘ring.",
|
||||
"Savatga": "Savatga",
|
||||
"Kategoriyalar": "Kategoriyalar",
|
||||
"Gastronomiya va kulinariya san'ati haqidagi yetakchi onlayn magazin": "Gastronomiya va kulinariya san'ati haqidagi yetakchi onlayn magazin",
|
||||
"Bizning maqsadimiz": "Bizning maqsadimiz",
|
||||
"Sifatli Kontent": "Sifatli Kontent",
|
||||
"Jahon oshpazlik san'ati va zamonaviy gastronomiya tendentsiyalari haqida chuqur maqolalar va tahlillar": "Jahon oshpazlik san'ati va zamonaviy gastronomiya tendentsiyalari haqida chuqur maqolalar va tahlillar",
|
||||
"Professional Jamoa": "Professional Jamoa",
|
||||
"Tajribali kulinariya mutaxassislari va oshpazlar tomonidan tayyorlangan kontent": "Tajribali kulinariya mutaxassislari va oshpazlar tomonidan tayyorlangan kontent",
|
||||
"Yangiliklar": "Yangiliklar",
|
||||
"Gastronomiya sohasidagi so'nggi yangiliklar va eng yangi trendlar haqida xabarlar": "Gastronomiya sohasidagi so'nggi yangiliklar va eng yangi trendlar haqida xabarlar",
|
||||
"Innovatsiya, sifat va professionallik": "Innovatsiya, sifat va professionallik",
|
||||
"Gastro Market – bu gastronomiya dunyosidagi eng so'nggi yangiliklarni": "Gastro Market – bu gastronomiya dunyosidagi eng so'nggi yangiliklarni, retseptlarni va tendentsiyalarni taqdim etuvchi onlayn platforma. Biz o'quvchilarimizga sifatli va qiziqarli kontent taqdim etishga intilamiz.",
|
||||
"Bizning jamoamiz tajribali kulinariya mutaxassislari": "Bizning jamoamiz tajribali kulinariya mutaxassislari, oshpazlar va gastronomiya sohasidagi ekspertlardan iborat. Biz har bir maqolada sifat va professionallikka e'tibor qaratamiz.",
|
||||
"Bizning dunyo": "Bizning dunyo",
|
||||
"Hamkor bo'ling": "Hamkor bo'ling",
|
||||
"Gastro Market bilan hamkorlik qilishni xohlaysizmi?": "Gastro Market bilan hamkorlik qilishni xohlaysizmi? Quyidagi formani to'ldiring va biz siz bilan tez orada bog'lanamiz.",
|
||||
"Kompaniya nomi": "Kompaniya nomi",
|
||||
"Website": "Website",
|
||||
"Ism Familiya": "Ism Familiya",
|
||||
"Email": "Email",
|
||||
"Telefon raqami": "Telefon raqami",
|
||||
"Kompaniya hujjati": "Kompaniya hujjati",
|
||||
"Faylni tanlang": "Faylni tanlang",
|
||||
"Tanlangan fayl": "Tanlangan fayl",
|
||||
"PDF yoki Word formatida (maksimal 5MB)": "PDF yoki Word formatida (maksimal 5MB)",
|
||||
"So'rov yuborish": "So'rov yuborish",
|
||||
"Kompaniya nomi kamida 2 ta belgidan iborat bo'lishi kerak": "Kompaniya nomi kamida 2 ta belgidan iborat bo'lishi kerak",
|
||||
"Ism kamida 2 ta belgidan iborat bo'lishi kerak": "Ism kamida 2 ta belgidan iborat bo'lishi kerak",
|
||||
"To'g'ri email manzilini kiriting": "To'g'ri email manzilini kiriting",
|
||||
"To'g'ri telefon raqamini kiriting": "To'g'ri telefon raqamini kiriting",
|
||||
"File yuklash majburiy": "File yuklash majburiy",
|
||||
|
||||
"Maxfiylik Siyosati": "Maxfiylik Siyosati",
|
||||
"Gastro Market sizning ma'lumotlaringiz xavfsizligini jiddiy qabul qiladi": "Gastro Market sizning ma'lumotlaringiz xavfsizligini jiddiy qabul qiladi",
|
||||
"Oxirgi yangilanish: 16 Dekabr 2025": "Oxirgi yangilanish: 16 Dekabr 2025",
|
||||
"Ushbu Maxfiylik Siyosati Gastro Market online magazinida siz tomonidan taqdim etilgan shaxsiy ma'lumotlarni qanday to'playmiz": "Ushbu Maxfiylik Siyosati Gastro Market online magazinida siz tomonidan taqdim etilgan shaxsiy ma'lumotlarni qanday to'playmiz, ishlatamiz va himoya qilishimizni tushuntiradi. Xizmatlarimizdan foydalanish orqali siz ushbu siyosatda tasvirlangan amaliyotlarga rozilik bildirasiz.",
|
||||
|
||||
"Biz To'playdigan Ma'lumotlar": "1. Biz To'playdigan Ma'lumotlar",
|
||||
"Sizning tajribangizni yaxshilash uchun biz quyidagi ma'lumotlarni to'playmiz": "Sizning tajribangizni yaxshilash uchun biz quyidagi ma'lumotlarni to'playmiz:",
|
||||
"Ism email manzil telefon raqami": "Ism, email manzil, telefon raqami",
|
||||
"Kompaniya nomi, website, hamkorlik so'rovlari": "Kompaniya nomi, website, hamkorlik so'rovlari",
|
||||
"Hamkorlik uchun yuklangan hujjatlar": "Hamkorlik uchun yuklangan hujjatlar",
|
||||
"IP manzil, brauzer turi, qurilma ma'lumotlari": "IP manzil, brauzer turi, qurilma ma'lumotlari",
|
||||
"Shaxsiy Ma'lumotlar": "Shaxsiy Ma'lumotlar",
|
||||
"Kompaniya Ma'lumotlari": "Kompaniya Ma'lumotlari",
|
||||
"Fayllar:": "Fayllar:",
|
||||
"Texnik Ma'lumotlar": "Texnik Ma'lumotlar",
|
||||
|
||||
"Ma'lumotlardan Foydalanish": "2. Ma'lumotlardan Foydalanish",
|
||||
"To'plangan ma'lumotlaringizdan quyidagi maqsadlarda foydalanamiz:": "To'plangan ma'lumotlaringizdan quyidagi maqsadlarda foydalanamiz:",
|
||||
"Hamkorlik so'rovlarini qayta ishlash va javob berish": "Hamkorlik so'rovlarini qayta ishlash va javob berish",
|
||||
"Sizga xizmatlarimiz va yangiliklar haqida ma'lumot berish": "Sizga xizmatlarimiz va yangiliklar haqida ma'lumot berish",
|
||||
"Sayt xavfsizligini ta'minlash va firibgarlikka qarshi kurashish": "Sayt xavfsizligini ta'minlash va firibgarlikka qarshi kurashish",
|
||||
"Foydalanuvchi tajribasini tahlil qilish va yaxshilash": "Foydalanuvchi tajribasini tahlil qilish va yaxshilash",
|
||||
"Qonuniy talablarni bajarish": "Qonuniy talablarni bajarish",
|
||||
|
||||
"Ma'lumotlar Xavfsizligi": "3. Ma'lumotlar Xavfsizligi",
|
||||
"Biz sizning shaxsiy ma'lumotlaringizni himoya qilish uchun zamonaviy xavfsizlik choralarini qo'llaymiz:": "Biz sizning shaxsiy ma'lumotlaringizni himoya qilish uchun zamonaviy xavfsizlik choralarini qo'llaymiz:",
|
||||
"SSL/TLS shifrlash orqali ma'lumotlar uzatish": "SSL/TLS shifrlash orqali ma'lumotlar uzatish",
|
||||
"Xavfsiz serverlar va ma'lumotlar bazasida saqlash": "Xavfsiz serverlar va ma'lumotlar bazasida saqlash",
|
||||
"Cheklangan kirish huquqlari va autentifikatsiya": "Cheklangan kirish huquqlari va autentifikatsiya",
|
||||
"Doimiy xavfsizlik monitoringi va yangilanishlar": "Doimiy xavfsizlik monitoringi va yangilanishlar",
|
||||
|
||||
"Ma'lumotlarni Ulashish": "4. Ma'lumotlarni Ulashish",
|
||||
"Biz sizning shaxsiy ma'lumotlaringizni uchinchi shaxslarga sotmaymiz": "Biz sizning shaxsiy ma'lumotlaringizni uchinchi shaxslarga sotmaymiz",
|
||||
"Sizning roziligingiz bilan": "Sizning roziligingiz bilan",
|
||||
"Qonuniy talablar bo'yicha": "Qonuniy talablar bo'yicha",
|
||||
"Xizmat ko'rsatuvchi ishonchli hamkorlar bilan (maxfiylik shartnomalari ostida)": "Xizmat ko'rsatuvchi ishonchli hamkorlar bilan (maxfiylik shartnomalari ostida)",
|
||||
"Kompaniya birlashuvi yoki sotilishi holatida": "Kompaniya birlashuvi yoki sotilishi holatida",
|
||||
|
||||
"Biz Bilan Bog'lanish": "Biz Bilan Bog'lanish",
|
||||
"Ushbu Maxfiylik Siyosati yoki shaxsiy ma'lumotlaringiz haqida savollaringiz bo'lsa, biz bilan bog'laning:": "Ushbu Maxfiylik Siyosati yoki shaxsiy ma'lumotlaringiz haqida savollaringiz bo'lsa, biz bilan bog'laning:",
|
||||
"Telefon": "Telefon",
|
||||
"Toshkent, O'zbekiston": "Toshkent, O'zbekiston",
|
||||
"Manzil": "Manzil",
|
||||
|
||||
"Miqdor": "Miqdor",
|
||||
"Jami": "Jami",
|
||||
"Bepul yetkazib berish": "Bepul yetkazib berish",
|
||||
"Kafolat": "Kafolat",
|
||||
"Xususiyatlari": "Xususiyatlari",
|
||||
"Qadoq turi": "Qadoq turi",
|
||||
"Brandi": "Brend",
|
||||
"Ishlab chiqaruvchi": "Ishlab chiqaruvchi",
|
||||
"Hajmi": "Hajmi",
|
||||
"O'xshash mahsulotlar": "O'xshash mahsulotlar",
|
||||
|
||||
"Hech narsa topilmadi": "Hech narsa topilmadi",
|
||||
"Qidiruv natijalari": "Qidiruv natijalari",
|
||||
"Tavsiya etiladi": "Tavsiya etiladi",
|
||||
"Yuklanmoqda": "Yuklanmoqda....",
|
||||
"Natija topilmadi": "Natija topilmadi",
|
||||
|
||||
"Asosiy": "Asosiy",
|
||||
"Katalog": "Katalog",
|
||||
"Sevimli": "Sevimli",
|
||||
"Savatda": "Savatda",
|
||||
"Profil": "Profil",
|
||||
|
||||
"Username yoki parol xato kiritildi": "Username yoki parol xato kiritildi",
|
||||
"Tizimga kirish": "Tizimga kirish",
|
||||
"Username": "Username",
|
||||
"Parol": "Parol",
|
||||
"Kirish": "Kirish",
|
||||
|
||||
"Savatingiz bo'sh": "Savatingiz bo'sh",
|
||||
"Mahsulotlar qo'shish uchun katalogga o'ting": "Mahsulotlar qo'shish uchun katalogga o'ting",
|
||||
"Xarid qilishni boshlash": "Xarid qilishni boshlash",
|
||||
"Savat": "Savat",
|
||||
"ta mahsulot": "ta mahsulot",
|
||||
"Buyurtma haqida": "Buyurtma haqida",
|
||||
"Mahsulotlar narxi": "Mahsulotlar narxi",
|
||||
"Chegirma": "Chegirma",
|
||||
"Yetkazib berish": "Yetkazib berish",
|
||||
"Bepul": "Bepul",
|
||||
"Buyurtmani rasmiylashtirish": "Buyurtmani rasmiylashtirish",
|
||||
"Xaridni davom ettirish": "Xaridni davom ettirish",
|
||||
"Tez yetkazib berish 1-2 kun ichida": "Tez yetkazib berish 1-2 kun ichida",
|
||||
"Xavfsiz to'lov usullari": "Xavfsiz to'lov usullari",
|
||||
|
||||
"Buyurtma qabul qilindi!": "Buyurtma qabul qilindi!",
|
||||
"Buyurtma raqami": "Buyurtma raqami",
|
||||
"Buyurtmangiz muvaffaqiyatli qabul qilindi": "Buyurtmangiz muvaffaqiyatli qabul qilindi.",
|
||||
"Bosh sahifaga qaytish": "Bosh sahifaga qaytish",
|
||||
"Ma'lumotlaringizni to'ldiring": "Ma'lumotlaringizni to'ldiring",
|
||||
"Shaxsiy ma'lumotlar": "Shaxsiy ma'lumotlar",
|
||||
"Ism": "Ism",
|
||||
"Ismingiz": "Ismingiz",
|
||||
"Familiya": "Familiya",
|
||||
"Familiyangiz": "Familiyangiz",
|
||||
"Telefon raqam": "Telefon raqam",
|
||||
"Izoh": "Izoh",
|
||||
"Yetkazib berish manzili": "Yetkazib berish manzili",
|
||||
"Manzilni qidirish": "Manzilni qidirish",
|
||||
"Toshkent": "Toshkent",
|
||||
"Mening joylashuvim": "Mening joylashuvim",
|
||||
"Yetkazib berish usuli": "Yetkazib berish usuli",
|
||||
"Standart yetkazib berish": "Standart yetkazib berish",
|
||||
"2-3 kun ichida": "2-3 kun ichida",
|
||||
"Tez yetkazib berish": "Tez yetkazib berish",
|
||||
"1 kun ichida": "1 kun ichida",
|
||||
"To'lov usuli": "To'lov usuli",
|
||||
"Naqd pul": "Naqd pul",
|
||||
"Yetkazib berishda to'lash": "Yetkazib berishda to'lash",
|
||||
"Plastik karta": "Plastik karta",
|
||||
"Online to'lov": "Online to'lov",
|
||||
"Mahsulotlar": "Mahsulotlar",
|
||||
"Buyurtmani tasdiqlash": "Buyurtmani tasdiqlash",
|
||||
"Majburiy maydon": "Majburiy maydon",
|
||||
"Xato raqam kiritildi": "Xato raqam kiritildi",
|
||||
"Orqaga": "Orqaga",
|
||||
|
||||
"Sevimlilar bo'sh": "Sevimlilar bo'sh",
|
||||
"Hali hech qanday mahsulotni sevimlilarga qo'shmadingiz": "Hali hech qanday mahsulotni sevimlilarga qo'shmadingiz. Mahsulotlar ro'yxatiga o'ting va yoqqan mahsulotlaringizni saqlang.",
|
||||
"Sevimli mahsulotlar": "Sevimli mahsulotlar",
|
||||
|
||||
"Faol buyurtmalar": "Faol buyurtmalar",
|
||||
"Barchasi": "Barchasi",
|
||||
"Buyurtmalar tarixi": "Buyurtmalar tarixi",
|
||||
"Qayta": "Qayta",
|
||||
"Chiqish": "Chiqish",
|
||||
"Umumiy": "Umumiy",
|
||||
"Buyurtmalar": "Buyurtmalar",
|
||||
"Tarix": "Tarix",
|
||||
|
||||
"Faol": "Faol",
|
||||
"Tugadi": "Tugadi",
|
||||
"Yetkazish": "Yetkazish",
|
||||
"Yo'lda": "Yo'lda",
|
||||
"Punktda": "Punktda",
|
||||
"Yetkazildi": "Yetkazildi",
|
||||
"Bekor qilindi": "Bekor qilindi",
|
||||
"Bu hafta": "Bu hafta",
|
||||
"Bu oy": "Bu oy",
|
||||
"Qo'llab-quvatlash": "Qo'llab-quvatlash",
|
||||
"Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling": "Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling",
|
||||
"Murojat qilish": "Murojat qilish",
|
||||
"So'rov yuborildi!": "So'rov yuborildi!",
|
||||
|
||||
"Tez-tez So'raladigan Savollar": "Tez-tez So'raladigan Savollar",
|
||||
"Gastro Market haqida eng ko'p so'raladigan savollarga javoblar": "Gastro Market haqida eng ko'p so'raladigan savollarga javoblar"
|
||||
}
|
||||
|
||||
14
src/shared/hooks/cartId.ts
Normal file
14
src/shared/hooks/cartId.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
type State = {
|
||||
cart_id: string | null;
|
||||
};
|
||||
|
||||
type Actions = {
|
||||
setCartId: (cartId: string | null) => void;
|
||||
};
|
||||
|
||||
export const useCartId = create<State & Actions>((set) => ({
|
||||
cart_id: null,
|
||||
setCartId: (cartId: string | null) => set(() => ({ cart_id: cartId })),
|
||||
}));
|
||||
6
src/shared/lib/onlyNumber.ts
Normal file
6
src/shared/lib/onlyNumber.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
const onlyNumber = (digits: string | number) => {
|
||||
const phone = digits.toString();
|
||||
return phone.replace(/\D/g, '');
|
||||
};
|
||||
|
||||
export default onlyNumber;
|
||||
28
src/shared/lib/token.ts
Normal file
28
src/shared/lib/token.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import cookie from 'js-cookie';
|
||||
|
||||
const TOKEN = 'gastro-token';
|
||||
const USER = 'gastro-user';
|
||||
|
||||
export const getToken = () => {
|
||||
return cookie.get(TOKEN);
|
||||
};
|
||||
|
||||
export const getMe = () => {
|
||||
return cookie.get(USER);
|
||||
};
|
||||
|
||||
export const removeToken = () => {
|
||||
cookie.remove(TOKEN);
|
||||
};
|
||||
|
||||
export const removeUser = () => {
|
||||
cookie.remove(USER);
|
||||
};
|
||||
|
||||
export const setToken = (value: string) => {
|
||||
cookie.set(TOKEN, value);
|
||||
};
|
||||
|
||||
export const setUser = (value: string) => {
|
||||
cookie.set(USER, value);
|
||||
};
|
||||
66
src/shared/ui/alert.tsx
Normal file
66
src/shared/ui/alert.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
import * as React from 'react';
|
||||
import { cva, type VariantProps } from 'class-variance-authority';
|
||||
|
||||
import { cn } from '@/shared/lib/utils';
|
||||
|
||||
const alertVariants = cva(
|
||||
'relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'bg-card text-card-foreground',
|
||||
destructive:
|
||||
'text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
function Alert({
|
||||
className,
|
||||
variant,
|
||||
...props
|
||||
}: React.ComponentProps<'div'> & VariantProps<typeof alertVariants>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="alert"
|
||||
role="alert"
|
||||
className={cn(alertVariants({ variant }), className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="alert-title"
|
||||
className={cn(
|
||||
'col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function AlertDescription({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="alert-description"
|
||||
className={cn(
|
||||
'text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export { Alert, AlertTitle, AlertDescription };
|
||||
@@ -1,8 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import * as React from 'react';
|
||||
import type * as LabelPrimitive from '@radix-ui/react-label';
|
||||
import { Slot } from '@radix-ui/react-slot';
|
||||
import * as React from 'react';
|
||||
import {
|
||||
Controller,
|
||||
FormProvider,
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
|
||||
import { cn } from '@/shared/lib/utils';
|
||||
import { Label } from '@/shared/ui/label';
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
const Form = FormProvider;
|
||||
|
||||
@@ -137,6 +138,7 @@ function FormDescription({ className, ...props }: React.ComponentProps<'p'>) {
|
||||
}
|
||||
|
||||
function FormMessage({ className, ...props }: React.ComponentProps<'p'>) {
|
||||
const t = useTranslations();
|
||||
const { error, formMessageId } = useFormField();
|
||||
const body = error ? String(error?.message ?? '') : props.children;
|
||||
|
||||
@@ -151,18 +153,18 @@ function FormMessage({ className, ...props }: React.ComponentProps<'p'>) {
|
||||
className={cn('text-destructive text-sm', className)}
|
||||
{...props}
|
||||
>
|
||||
{body}
|
||||
{error && error.message ? t(error.message) : body}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
export {
|
||||
useFormField,
|
||||
Form,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormMessage,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
useFormField,
|
||||
};
|
||||
|
||||
102
src/shared/ui/global-pagination.tsx
Normal file
102
src/shared/ui/global-pagination.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
'use client';
|
||||
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
||||
import { Button } from './button';
|
||||
|
||||
type GlobalPaginationProps = {
|
||||
page: number;
|
||||
total: number;
|
||||
pageSize?: number;
|
||||
onChange: (page: number) => void;
|
||||
};
|
||||
|
||||
const getPages = (current: number, total: number) => {
|
||||
const pages: (number | 'dots')[] = [];
|
||||
|
||||
if (total <= 7) {
|
||||
return Array.from({ length: total }, (_, i) => i + 1);
|
||||
}
|
||||
|
||||
pages.push(1);
|
||||
|
||||
if (current > 4) {
|
||||
pages.push('dots');
|
||||
}
|
||||
|
||||
const start = Math.max(2, current - 1);
|
||||
const end = Math.min(total - 1, current + 1);
|
||||
|
||||
for (let i = start; i <= end; i++) {
|
||||
pages.push(i);
|
||||
}
|
||||
|
||||
if (current < total - 3) {
|
||||
pages.push('dots');
|
||||
}
|
||||
|
||||
pages.push(total);
|
||||
|
||||
return pages;
|
||||
};
|
||||
|
||||
export const GlobalPagination = ({
|
||||
page,
|
||||
total,
|
||||
pageSize = 36,
|
||||
onChange,
|
||||
}: GlobalPaginationProps) => {
|
||||
const totalPages = Math.ceil(total / pageSize);
|
||||
if (totalPages <= 1) return null;
|
||||
|
||||
const pages = getPages(page, totalPages);
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<Button
|
||||
variant={'outline'}
|
||||
onClick={() => page > 1 && onChange(page - 1)}
|
||||
disabled={page === 1}
|
||||
className="flex items-center justify-center w-10 cursor-pointer h-10 rounded-lg transition-all duration-200 hover:bg-gray-100 disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent"
|
||||
>
|
||||
<ChevronLeft className="!w-6 !h-6 text-gray-600" />
|
||||
</Button>
|
||||
|
||||
{/* Page Numbers */}
|
||||
<div className="flex items-center gap-1">
|
||||
{pages.map((p, i) => (
|
||||
<div key={i}>
|
||||
{p === 'dots' ? (
|
||||
<span className="flex items-center justify-center w-9 h-9 text-gray-400 font-medium">
|
||||
···
|
||||
</span>
|
||||
) : (
|
||||
<Button
|
||||
variant={'outline'}
|
||||
onClick={() => onChange(p)}
|
||||
className={`
|
||||
flex items-center justify-center w-10 h-10 px-3 rounded-lg font-medium transition-all duration-200
|
||||
${
|
||||
p === page
|
||||
? 'bg-blue-600 text-white shadow-md shadow-blue-200 scale-105'
|
||||
: 'text-gray-700 hover:bg-gray-100 hover:scale-105'
|
||||
}
|
||||
`}
|
||||
>
|
||||
{p}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
onClick={() => page < totalPages && onChange(page + 1)}
|
||||
disabled={page === totalPages}
|
||||
variant={'outline'}
|
||||
className="flex items-center justify-center w-10 cursor-pointer h-10 rounded-lg transition-all duration-200 hover:bg-gray-100 disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent"
|
||||
>
|
||||
<ChevronRight className="!w-6 !h-6 text-gray-600" />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
126
src/shared/ui/pagination.tsx
Normal file
126
src/shared/ui/pagination.tsx
Normal file
@@ -0,0 +1,126 @@
|
||||
import {
|
||||
ChevronLeftIcon,
|
||||
ChevronRightIcon,
|
||||
MoreHorizontalIcon,
|
||||
} from 'lucide-react';
|
||||
import * as React from 'react';
|
||||
|
||||
import { cn } from '@/shared/lib/utils';
|
||||
import { buttonVariants, type Button } from '@/shared/ui/button';
|
||||
|
||||
function Pagination({ className, ...props }: React.ComponentProps<'nav'>) {
|
||||
return (
|
||||
<nav
|
||||
role="navigation"
|
||||
aria-label="pagination"
|
||||
data-slot="pagination"
|
||||
className={cn('mx-auto flex w-full justify-center', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function PaginationContent({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<'ul'>) {
|
||||
return (
|
||||
<ul
|
||||
data-slot="pagination-content"
|
||||
className={cn('flex flex-row items-center gap-1', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function PaginationItem({ ...props }: React.ComponentProps<'li'>) {
|
||||
return <li data-slot="pagination-item" {...props} />;
|
||||
}
|
||||
|
||||
type PaginationLinkProps = {
|
||||
isActive?: boolean;
|
||||
} & Pick<React.ComponentProps<typeof Button>, 'size'> &
|
||||
React.ComponentProps<'a'>;
|
||||
|
||||
function PaginationLink({
|
||||
className,
|
||||
isActive,
|
||||
size = 'icon',
|
||||
...props
|
||||
}: PaginationLinkProps) {
|
||||
return (
|
||||
<a
|
||||
aria-current={isActive ? 'page' : undefined}
|
||||
data-slot="pagination-link"
|
||||
data-active={isActive}
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
variant: isActive ? 'outline' : 'ghost',
|
||||
size,
|
||||
}),
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function PaginationPrevious({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof PaginationLink>) {
|
||||
return (
|
||||
<PaginationLink
|
||||
aria-label="Go to previous page"
|
||||
size="default"
|
||||
className={cn('gap-1 px-2.5 sm:pl-2.5', className)}
|
||||
{...props}
|
||||
>
|
||||
<ChevronLeftIcon />
|
||||
<span className="hidden sm:block">Previous</span>
|
||||
</PaginationLink>
|
||||
);
|
||||
}
|
||||
|
||||
function PaginationNext({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof PaginationLink>) {
|
||||
return (
|
||||
<PaginationLink
|
||||
aria-label="Go to next page"
|
||||
size="default"
|
||||
className={cn('gap-1 px-2.5 sm:pr-2.5', className)}
|
||||
{...props}
|
||||
>
|
||||
<ChevronRightIcon />
|
||||
</PaginationLink>
|
||||
);
|
||||
}
|
||||
|
||||
function PaginationEllipsis({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<'span'>) {
|
||||
return (
|
||||
<span
|
||||
aria-hidden
|
||||
data-slot="pagination-ellipsis"
|
||||
className={cn('flex size-9 items-center justify-center', className)}
|
||||
{...props}
|
||||
>
|
||||
<MoreHorizontalIcon className="size-4" />
|
||||
<span className="sr-only">More pages</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export {
|
||||
Pagination,
|
||||
PaginationContent,
|
||||
PaginationEllipsis,
|
||||
PaginationItem,
|
||||
PaginationLink,
|
||||
PaginationNext,
|
||||
PaginationPrevious,
|
||||
};
|
||||
13
src/shared/ui/skeleton.tsx
Normal file
13
src/shared/ui/skeleton.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { cn } from '@/shared/lib/utils';
|
||||
|
||||
function Skeleton({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="skeleton"
|
||||
className={cn('bg-accent animate-pulse rounded-md', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export { Skeleton };
|
||||
Reference in New Issue
Block a user