Добавлены модели товаров и корзины для оптовиков, реализованы соответствующие мутации и запросы в GraphQL. Обновлен API для загрузки файлов с учетом новых типов данных. Улучшена обработка ошибок и добавлены новые функции для работы с категориями товаров.

This commit is contained in:
Bivekich
2025-07-17 16:36:07 +03:00
parent 6a94d51032
commit f377fbab5f
21 changed files with 3958 additions and 34 deletions

View File

@ -0,0 +1,205 @@
"use client"
import { useQuery } from '@apollo/client'
import { Card } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { GET_CATEGORIES, GET_MY_CART } from '@/graphql/queries'
import { Package2, ArrowRight, Sparkles, ShoppingCart } from 'lucide-react'
interface Category {
id: string
name: string
createdAt: string
updatedAt: string
}
interface MarketCategoriesProps {
onSelectCategory: (categoryId: string, categoryName: string) => void
onShowCart?: () => void
}
export function MarketCategories({ onSelectCategory, onShowCart }: MarketCategoriesProps) {
const { data, loading, error } = useQuery(GET_CATEGORIES)
const { data: cartData } = useQuery(GET_MY_CART)
const categories: Category[] = data?.categories || []
const cart = cartData?.myCart
const uniqueItemsCount = cart?.items?.length || 0
if (loading) {
return (
<div className="h-full flex items-center justify-center">
<div className="text-center">
<div className="animate-spin rounded-full h-16 w-16 border-4 border-white border-t-transparent mx-auto mb-4"></div>
<p className="text-white/70">Загружаем категории...</p>
</div>
</div>
)
}
if (error) {
return (
<div className="h-full flex items-center justify-center">
<div className="text-center">
<Package2 className="h-16 w-16 text-red-400/40 mx-auto mb-4" />
<p className="text-red-400">Ошибка загрузки категорий</p>
<p className="text-white/40 text-sm mt-2">{error.message}</p>
</div>
</div>
)
}
return (
<div className="h-full flex flex-col p-6">
{/* Заголовок */}
<div className="flex items-center justify-between mb-8">
<div className="flex items-center space-x-3">
<div className="p-3 rounded-xl bg-gradient-to-r from-purple-500/20 to-pink-500/20 border border-purple-500/30">
<Package2 className="h-8 w-8 text-purple-400" />
</div>
<div>
<h1 className="text-2xl font-bold text-white mb-1">
Каталог товаров
</h1>
<p className="text-white/60">
Выберите категорию для просмотра товаров от оптовиков
</p>
</div>
</div>
{/* Кнопка корзины */}
{onShowCart && (
<Button
onClick={onShowCart}
className="bg-gradient-to-r from-purple-500/20 to-pink-500/20 hover:from-purple-500/30 hover:to-pink-500/30 text-white border-purple-500/30 hover:border-purple-400/50 transition-all duration-200 shadow-lg px-6 py-3"
>
<ShoppingCart className="h-5 w-5 mr-2" />
Корзина {uniqueItemsCount > 0 && `(${uniqueItemsCount})`}
</Button>
)}
</div>
{/* Категории */}
<div className="flex-1 overflow-auto">
{categories.length === 0 ? (
<div className="glass-card p-8">
<div className="text-center">
<Package2 className="h-16 w-16 text-white/20 mx-auto mb-4" />
<h3 className="text-lg font-semibold text-white mb-2">
Категории отсутствуют
</h3>
<p className="text-white/60">
Пока нет доступных категорий товаров
</p>
</div>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
{/* Карточка "Все товары" */}
<Card
onClick={() => onSelectCategory('', 'Все товары')}
className="group relative overflow-hidden bg-gradient-to-br from-indigo-500/10 via-purple-500/10 to-pink-500/10 backdrop-blur border-white/10 hover:border-white/20 transition-all duration-300 cursor-pointer hover:scale-105"
>
<div className="p-6 h-32 flex flex-col justify-between">
<div className="flex items-center justify-between">
<div className="p-3 rounded-lg bg-gradient-to-r from-indigo-500/20 to-purple-500/20 border border-indigo-500/30">
<Sparkles className="h-6 w-6 text-indigo-400" />
</div>
<ArrowRight className="h-5 w-5 text-white/40 group-hover:text-white/80 transition-colors" />
</div>
<div>
<h3 className="text-lg font-semibold text-white group-hover:text-white transition-colors">
Все товары
</h3>
<p className="text-white/60 text-sm">
Просмотреть весь каталог
</p>
</div>
</div>
{/* Эффект при наведении */}
<div className="absolute inset-0 bg-gradient-to-r from-indigo-500/5 to-purple-500/5 opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
</Card>
{/* Карточки категорий */}
{categories.map((category, index) => {
// Разные градиенты для разных категорий
const gradients = [
'from-purple-500/10 via-pink-500/10 to-red-500/10',
'from-blue-500/10 via-cyan-500/10 to-teal-500/10',
'from-green-500/10 via-emerald-500/10 to-lime-500/10',
'from-yellow-500/10 via-orange-500/10 to-red-500/10',
'from-pink-500/10 via-rose-500/10 to-purple-500/10',
'from-indigo-500/10 via-blue-500/10 to-cyan-500/10',
'from-teal-500/10 via-green-500/10 to-emerald-500/10'
]
const borderColors = [
'border-purple-500/30',
'border-blue-500/30',
'border-green-500/30',
'border-orange-500/30',
'border-pink-500/30',
'border-indigo-500/30',
'border-teal-500/30'
]
const iconColors = [
'text-purple-400',
'text-blue-400',
'text-green-400',
'text-orange-400',
'text-pink-400',
'text-indigo-400',
'text-teal-400'
]
const bgColors = [
'from-purple-500/20 to-pink-500/20',
'from-blue-500/20 to-cyan-500/20',
'from-green-500/20 to-emerald-500/20',
'from-yellow-500/20 to-orange-500/20',
'from-pink-500/20 to-rose-500/20',
'from-indigo-500/20 to-blue-500/20',
'from-teal-500/20 to-green-500/20'
]
const gradient = gradients[index % gradients.length]
const borderColor = borderColors[index % borderColors.length]
const iconColor = iconColors[index % iconColors.length]
const bgColor = bgColors[index % bgColors.length]
return (
<Card
key={category.id}
onClick={() => onSelectCategory(category.id, category.name)}
className={`group relative overflow-hidden bg-gradient-to-br ${gradient} backdrop-blur border-white/10 hover:${borderColor} transition-all duration-300 cursor-pointer hover:scale-105`}
>
<div className="p-6 h-32 flex flex-col justify-between">
<div className="flex items-center justify-between">
<div className={`p-3 rounded-lg bg-gradient-to-r ${bgColor} border ${borderColor}`}>
<Package2 className={`h-6 w-6 ${iconColor}`} />
</div>
<ArrowRight className="h-5 w-5 text-white/40 group-hover:text-white/80 transition-colors" />
</div>
<div>
<h3 className="text-lg font-semibold text-white group-hover:text-white transition-colors">
{category.name}
</h3>
<p className="text-white/60 text-sm">
Товары категории
</p>
</div>
</div>
{/* Эффект при наведении */}
<div className={`absolute inset-0 bg-gradient-to-r ${gradient} opacity-0 group-hover:opacity-50 transition-opacity duration-300`} />
</Card>
)
})}
</div>
)}
</div>
</div>
)
}