Изменены текстовые метки и комментарии в коде для замены термина "Оптовик" на "Поставщик" во всех компонентах и файлах, включая интерфейсы, мутации и резолверы. Обновлены соответствующие комментарии для улучшения понимания кода и его структуры.
This commit is contained in:
@ -806,10 +806,10 @@ export function BusinessDemo() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Карточки оптовиков */}
|
||||
{/* Карточки поставщиков */}
|
||||
<Card className="glass-card border-white/10">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-white">Карточки оптовиков</CardTitle>
|
||||
<CardTitle className="text-white">Карточки поставщиков</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
|
@ -370,7 +370,7 @@ export function BusinessProcessesDemo() {
|
||||
},
|
||||
{
|
||||
id: "wholesale",
|
||||
name: "Оптовик",
|
||||
name: "Поставщик",
|
||||
description: "Оптовые продажи",
|
||||
icon: Building2,
|
||||
color: "bg-cyan-500/20 text-cyan-400 border-cyan-500/30",
|
||||
@ -454,7 +454,7 @@ export function BusinessProcessesDemo() {
|
||||
|
||||
E["🚛 Логистика<br/>Логистические решения<br/>• Перевозки<br/>• Заявки"]
|
||||
|
||||
F["🏭 Оптовик<br/>Оптовые продажи<br/>• Отгрузки<br/>• Склад"]
|
||||
F["🏭 Поставщик<br/>Оптовые продажи<br/>• Отгрузки<br/>• Склад"]
|
||||
|
||||
%% Общие модули
|
||||
G["💬 Мессенджер<br/>Общение между участниками<br/>• Чаты<br/>• Файлы<br/>• Голосовые"]
|
||||
@ -628,7 +628,7 @@ export function BusinessProcessesDemo() {
|
||||
Процесс заказа
|
||||
</h4>
|
||||
<p className="text-white/70 text-sm">
|
||||
Селлер → Маркет → Оптовик → Фулфилмент → Логистика
|
||||
Селлер → Маркет → Поставщик → Фулфилмент → Логистика
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -704,7 +704,7 @@ export function BusinessProcessesDemo() {
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-white text-sm font-medium">
|
||||
Оптовик одобряет
|
||||
Поставщик одобряет
|
||||
</p>
|
||||
<p className="text-white/60 text-xs">
|
||||
Подтверждает наличие товара
|
||||
@ -782,7 +782,7 @@ export function BusinessProcessesDemo() {
|
||||
<span className="text-green-400">Мессенджер</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between text-xs">
|
||||
<span className="text-cyan-400">Оптовик</span>
|
||||
<span className="text-cyan-400">Поставщик</span>
|
||||
<ArrowRight className="h-3 w-3 text-white/30" />
|
||||
<span className="text-green-400">Мессенджер</span>
|
||||
</div>
|
||||
|
@ -201,7 +201,7 @@ export function FormsDemo() {
|
||||
<SelectItem value="fulfillment">Фулфилмент</SelectItem>
|
||||
<SelectItem value="seller">Селлер</SelectItem>
|
||||
<SelectItem value="logist">Логистика</SelectItem>
|
||||
<SelectItem value="wholesale">Оптовик</SelectItem>
|
||||
<SelectItem value="wholesale">Поставщик</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
@ -500,7 +500,7 @@ export function FormsDemo() {
|
||||
<SelectItem value="fulfillment">Фулфилмент</SelectItem>
|
||||
<SelectItem value="seller">Селлер</SelectItem>
|
||||
<SelectItem value="logist">Логистика</SelectItem>
|
||||
<SelectItem value="wholesale">Оптовик</SelectItem>
|
||||
<SelectItem value="wholesale">Поставщик</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
@ -447,7 +447,7 @@ export function IconsDemo() {
|
||||
Логистика
|
||||
</Badge>
|
||||
<Badge className="bg-orange-500/20 text-orange-400 border-orange-500/50">
|
||||
Оптовик
|
||||
Поставщик
|
||||
</Badge>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -504,7 +504,7 @@ export function InteractiveDemo() {
|
||||
<div className="text-white/80">
|
||||
<p className="mb-4">
|
||||
SferaV - современная система управления бизнесом для фулфилмент-центров,
|
||||
селлеров, логистических компаний и оптовиков.
|
||||
селлеров, логистических компаний и поставщиков.
|
||||
</p>
|
||||
|
||||
<div className="space-y-2 text-sm">
|
||||
|
@ -113,7 +113,7 @@ export function SpecializedDemo() {
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center space-x-2">
|
||||
<span className="text-white font-medium text-sm">ОптТорг</span>
|
||||
<Badge className="bg-purple-500/20 text-purple-300 text-xs">Оптовик</Badge>
|
||||
<Badge className="bg-purple-500/20 text-purple-300 text-xs">Поставщик</Badge>
|
||||
</div>
|
||||
<p className="text-white/60 text-xs">Новый прайс готов</p>
|
||||
</div>
|
||||
@ -333,7 +333,7 @@ export function SpecializedDemo() {
|
||||
</Avatar>
|
||||
<div className="flex-1">
|
||||
<div className="text-white text-xs font-medium">ОптТорг</div>
|
||||
<Badge className="bg-purple-500/20 text-purple-300 text-xs">Оптовик</Badge>
|
||||
<Badge className="bg-purple-500/20 text-purple-300 text-xs">Поставщик</Badge>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -75,7 +75,7 @@ export function SuppliesDemo() {
|
||||
<Tabs defaultValue="product-cards" className="w-full">
|
||||
<TabsList className="grid grid-cols-4 bg-white/5 backdrop-blur border-white/10 mb-6">
|
||||
<TabsTrigger value="product-cards">Карточки товаров</TabsTrigger>
|
||||
<TabsTrigger value="wholesaler-cards">Карточки оптовиков</TabsTrigger>
|
||||
<TabsTrigger value="wholesaler-cards">Карточки поставщиков</TabsTrigger>
|
||||
<TabsTrigger value="floating-cart">Плавающая корзина</TabsTrigger>
|
||||
<TabsTrigger value="supply-types">Типы поставок</TabsTrigger>
|
||||
</TabsList>
|
||||
@ -274,13 +274,13 @@ export function SuppliesDemo() {
|
||||
|
||||
<TabsContent value="wholesaler-cards" className="space-y-6">
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-white mb-4">Карточки оптовиков</h3>
|
||||
<h3 className="text-xl font-semibold text-white mb-4">Карточки поставщиков</h3>
|
||||
<p className="text-white/60 mb-6">
|
||||
Информационные карточки поставщиков и оптовиков
|
||||
Информационные карточки поставщиков и поставщиков
|
||||
</p>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{/* Главная карточка оптовика */}
|
||||
{/* Главная карточка поставщика */}
|
||||
<Card className="bg-white/10 backdrop-blur border-white/20 p-6 hover:bg-white/15 hover:border-white/30 transition-all duration-300 hover:scale-105">
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-start justify-between">
|
||||
@ -540,7 +540,7 @@ export function SuppliesDemo() {
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Вариант 2: Оптовик */}
|
||||
{/* Вариант 2: Поставщик */}
|
||||
<Card
|
||||
className="bg-white/10 backdrop-blur border-white/20 p-6 cursor-pointer transition-all hover:bg-white/15 hover:border-white/30"
|
||||
>
|
||||
@ -549,9 +549,9 @@ export function SuppliesDemo() {
|
||||
<Users className="h-8 w-8 text-green-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-white mb-2">Оптовик</h3>
|
||||
<h3 className="text-xl font-semibold text-white mb-2">Поставщик</h3>
|
||||
<p className="text-white/60 text-sm">
|
||||
Создание поставки через выбор товаров у оптовиков
|
||||
Создание поставки через выбор товаров у поставщиков
|
||||
</p>
|
||||
</div>
|
||||
<Badge className="bg-green-500/20 text-green-300 border-green-500/30">
|
||||
|
@ -90,7 +90,7 @@ export function UsersSection() {
|
||||
FULFILLMENT: { label: 'Фулфилмент', variant: 'default' as const },
|
||||
SELLER: { label: 'Селлер', variant: 'secondary' as const },
|
||||
LOGIST: { label: 'Логистика', variant: 'outline' as const },
|
||||
WHOLESALE: { label: 'Оптовик', variant: 'destructive' as const }
|
||||
WHOLESALE: { label: 'Поставщик', variant: 'destructive' as const }
|
||||
}
|
||||
return typeMap[type as keyof typeof typeMap] || { label: type, variant: 'outline' as const }
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ export function AuthFlow({ partnerCode }: AuthFlowProps = {}) {
|
||||
{
|
||||
authData.cabinetType === 'fulfillment' ? 'Фулфилмент' :
|
||||
authData.cabinetType === 'logist' ? 'Логистика' :
|
||||
authData.cabinetType === 'wholesale' ? 'Оптовик' :
|
||||
authData.cabinetType === 'wholesale' ? 'Поставщик' :
|
||||
'Селлер'
|
||||
}
|
||||
</p>
|
||||
|
@ -39,8 +39,8 @@ export function CabinetSelectStep({ onNext, onBack }: CabinetSelectStepProps) {
|
||||
},
|
||||
{
|
||||
id: 'wholesale' as const,
|
||||
title: 'Оптовик',
|
||||
description: 'Оптовые продажи',
|
||||
title: 'Поставщик',
|
||||
description: 'Поставки товаров',
|
||||
icon: Building2,
|
||||
features: ['Опт', 'Поставки', 'ИНН'],
|
||||
color: 'orange'
|
||||
|
@ -139,7 +139,7 @@ export function ConfirmationStep({ data, onConfirm, onBack }: ConfirmationStepPr
|
||||
<span className="text-white/70 text-sm">
|
||||
{data.cabinetType === 'fulfillment' ? 'Фулфилмент' :
|
||||
data.cabinetType === 'logist' ? 'Логистика' :
|
||||
data.cabinetType === 'wholesale' ? 'Оптовик' :
|
||||
data.cabinetType === 'wholesale' ? 'Поставщик' :
|
||||
'Селлер'}
|
||||
</span>
|
||||
<Badge
|
||||
|
@ -31,7 +31,7 @@ import {
|
||||
function NewOrdersNotification() {
|
||||
const { user } = useAuth();
|
||||
|
||||
// Загружаем заказы поставок для оптовика
|
||||
// Загружаем заказы поставок для поставщика
|
||||
const { data: ordersData } = useQuery(GET_SUPPLY_ORDERS, {
|
||||
pollInterval: 30000, // Обновляем каждые 30 секунд для заявок
|
||||
fetchPolicy: "cache-first",
|
||||
@ -42,7 +42,7 @@ function NewOrdersNotification() {
|
||||
if (user?.organization?.type !== "WHOLESALE") return null;
|
||||
|
||||
const orders = ordersData?.supplyOrders || [];
|
||||
// Считаем заявки в статусе PENDING (ожидают одобрения оптовика)
|
||||
// Считаем заявки в статусе PENDING (ожидают одобрения поставщика)
|
||||
const pendingOrders = orders.filter(
|
||||
(order) =>
|
||||
order.status === "PENDING" && order.partnerId === user?.organization?.id
|
||||
@ -114,7 +114,7 @@ export function Sidebar() {
|
||||
case "LOGIST":
|
||||
return "Логистика";
|
||||
case "WHOLESALE":
|
||||
return "Оптовик";
|
||||
return "Поставщик";
|
||||
default:
|
||||
return "Кабинет";
|
||||
}
|
||||
@ -553,7 +553,7 @@ export function Sidebar() {
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* Заявки - для оптовиков */}
|
||||
{/* Заявки - для поставщиков */}
|
||||
{user?.organization?.type === "WHOLESALE" && (
|
||||
<Button
|
||||
variant={isSuppliesActive ? "secondary" : "ghost"}
|
||||
@ -595,7 +595,7 @@ export function Sidebar() {
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* Склад - только для оптовиков */}
|
||||
{/* Склад - только для поставщиков */}
|
||||
{user?.organization?.type === "WHOLESALE" && (
|
||||
<Button
|
||||
variant={isWarehouseActive ? "secondary" : "ghost"}
|
||||
|
@ -172,7 +172,7 @@ export function UserSettings() {
|
||||
case 'LOGIST':
|
||||
return 'Логистика'
|
||||
case 'WHOLESALE':
|
||||
return 'Оптовик'
|
||||
return 'Поставщик'
|
||||
default:
|
||||
return 'Не указан'
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ export function CreateFulfillmentConsumablesSupplyPage() {
|
||||
// Мутация для создания заказа поставки расходников
|
||||
const [createSupplyOrder] = useMutation(CREATE_SUPPLY_ORDER);
|
||||
|
||||
// Фильтруем только поставщиков расходников (оптовиков)
|
||||
// Фильтруем только поставщиков расходников (поставщиков)
|
||||
const consumableSuppliers = (
|
||||
counterpartiesData?.myCounterparties || []
|
||||
).filter((org: FulfillmentConsumableSupplier) => org.type === "WHOLESALE");
|
||||
|
@ -50,7 +50,7 @@ interface Organization {
|
||||
type: string;
|
||||
}
|
||||
|
||||
// Новый интерфейс для поставщика/оптовика
|
||||
// Новый интерфейс для поставщика/поставщика
|
||||
interface Supplier {
|
||||
id: string;
|
||||
name: string;
|
||||
@ -1213,7 +1213,7 @@ export function FulfillmentGoodsTab() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Третий уровень - Поставщики/Оптовики */}
|
||||
{/* Третий уровень - Поставщики/Поставщики */}
|
||||
{isRouteExpanded &&
|
||||
route?.suppliers &&
|
||||
Array.isArray(route.suppliers) &&
|
||||
@ -1222,7 +1222,7 @@ export function FulfillmentGoodsTab() {
|
||||
<div className="mb-3">
|
||||
<h5 className="text-white font-medium text-sm flex items-center gap-2">
|
||||
<Building2 className="h-4 w-4 text-purple-400" />
|
||||
Поставщики/Оптовики (
|
||||
Поставщики/Поставщики (
|
||||
{route?.suppliers?.length || 0})
|
||||
</h5>
|
||||
</div>
|
||||
@ -1294,7 +1294,7 @@ export function FulfillmentGoodsTab() {
|
||||
>
|
||||
{supplier?.type ===
|
||||
"WHOLESALE"
|
||||
? "Оптовик"
|
||||
? "Поставщик"
|
||||
: "Поставщик"}
|
||||
</Badge>
|
||||
</div>
|
||||
|
@ -81,7 +81,7 @@ export function MaterialsOrderForm() {
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [deliveryDate, setDeliveryDate] = useState("");
|
||||
|
||||
// Загружаем контрагентов-оптовиков
|
||||
// Загружаем контрагентов-поставщиков
|
||||
const { data: counterpartiesData, loading: counterpartiesLoading } = useQuery(
|
||||
GET_MY_COUNTERPARTIES
|
||||
);
|
||||
@ -98,7 +98,7 @@ export function MaterialsOrderForm() {
|
||||
// Мутация для создания заказа поставки
|
||||
const [createSupplyOrder, { loading: isCreatingOrder }] = useMutation(CREATE_SUPPLY_ORDER);
|
||||
|
||||
// Фильтруем только оптовиков из партнеров
|
||||
// Фильтруем только поставщиков из партнеров
|
||||
const wholesalePartners = (counterpartiesData?.myCounterparties || []).filter(
|
||||
(org: Partner) => org.type === "WHOLESALE"
|
||||
);
|
||||
@ -490,7 +490,7 @@ export function MaterialsOrderForm() {
|
||||
Заказ расходников
|
||||
</h1>
|
||||
<p className="text-white/60">
|
||||
Выберите партнера-оптовика для заказа расходников
|
||||
Выберите партнера-поставщика для заказа расходников
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -522,7 +522,7 @@ export function MaterialsOrderForm() {
|
||||
<Building2 className="h-12 w-12 text-white/20 mx-auto mb-4" />
|
||||
<p className="text-white/60">
|
||||
{wholesalePartners.length === 0
|
||||
? "У вас пока нет партнеров-оптовиков"
|
||||
? "У вас пока нет партнеров-поставщиков"
|
||||
: "Партнеры не найдены"}
|
||||
</p>
|
||||
<p className="text-white/40 text-sm mt-2">
|
||||
|
@ -63,7 +63,7 @@ export function MarketCategories({ onSelectCategory, onShowCart, onShowFavorites
|
||||
Каталог товаров
|
||||
</h1>
|
||||
<p className="text-white/60">
|
||||
Выберите категорию для просмотра товаров от оптовиков
|
||||
Выберите категорию для просмотра товаров от поставщиков
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -234,7 +234,7 @@ export function MarketCounterparties() {
|
||||
case 'FULFILLMENT': return 'Фулфилмент'
|
||||
case 'SELLER': return 'Селлер'
|
||||
case 'LOGIST': return 'Логистика'
|
||||
case 'WHOLESALE': return 'Оптовик'
|
||||
case 'WHOLESALE': return 'Поставщик'
|
||||
default: return type
|
||||
}
|
||||
}
|
||||
@ -300,7 +300,7 @@ export function MarketCounterparties() {
|
||||
<SelectItem value="FULFILLMENT">Фулфилмент</SelectItem>
|
||||
<SelectItem value="SELLER">Селлер</SelectItem>
|
||||
<SelectItem value="LOGIST">Логистика</SelectItem>
|
||||
<SelectItem value="WHOLESALE">Оптовик</SelectItem>
|
||||
<SelectItem value="WHOLESALE">Поставщик</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
|
@ -166,7 +166,7 @@ export function MarketProducts({ selectedCategoryId, selectedCategoryName, onBac
|
||||
<div className="flex items-center space-x-3">
|
||||
<ShoppingBag className="h-6 w-6 text-purple-400" />
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold text-white">Товары оптовиков</h3>
|
||||
<h3 className="text-lg font-semibold text-white">Товары поставщиков</h3>
|
||||
<p className="text-white/60 text-sm">
|
||||
Найдено {totalProducts} товаров, доступно {availableCount}
|
||||
</p>
|
||||
@ -221,7 +221,7 @@ export function MarketProducts({ selectedCategoryId, selectedCategoryName, onBac
|
||||
<p className="text-white/40 text-sm mt-2">
|
||||
{searchTerm || selectedCategory
|
||||
? 'Попробуйте изменить условия поиска или фильтры'
|
||||
: 'Оптовики еще не добавили свои товары'
|
||||
: 'Поставщики еще не добавили свои товары'
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
|
@ -89,7 +89,7 @@ export function MarketRequests({ onBackToCategories }: MarketRequestsProps) {
|
||||
<Package className="h-24 w-24 text-white/20 mb-6" />
|
||||
<h2 className="text-xl font-semibold text-white mb-2">Нет заявок</h2>
|
||||
<p className="text-white/60 mb-6 max-w-md">
|
||||
Добавьте товары в заявки из раздела "Товары", чтобы создать заявку для оптовика
|
||||
Добавьте товары в заявки из раздела "Товары", чтобы создать заявку для поставщика
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
@ -91,7 +91,7 @@ export function MarketWholesale() {
|
||||
<div className="flex items-center space-x-3 flex-shrink-0 mb-4">
|
||||
<Boxes className="h-6 w-6 text-purple-400" />
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold text-white">Оптовики</h3>
|
||||
<h3 className="text-lg font-semibold text-white">Поставщики</h3>
|
||||
<p className="text-white/60 text-sm">Найдите и добавьте оптовые компании в контрагенты</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -107,7 +107,7 @@ export function MarketWholesale() {
|
||||
<div className="text-center">
|
||||
<Boxes className="h-12 w-12 text-white/20 mx-auto mb-4" />
|
||||
<p className="text-white/60">
|
||||
{searchTerm ? 'Оптовые компании не найдены' : 'Введите запрос для поиска оптовиков'}
|
||||
{searchTerm ? 'Поставщики не найдены' : 'Введите запрос для поиска поставщиков'}
|
||||
</p>
|
||||
<p className="text-white/40 text-sm mt-2">
|
||||
Попробуйте изменить условия поиска
|
||||
|
@ -90,7 +90,7 @@ export function OrganizationCard({
|
||||
case 'FULFILLMENT': return 'Фулфилмент'
|
||||
case 'SELLER': return 'Селлер'
|
||||
case 'LOGIST': return 'Логистика'
|
||||
case 'WHOLESALE': return 'Оптовик'
|
||||
case 'WHOLESALE': return 'Поставщик'
|
||||
default: return type
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ function getTypeLabel(type: string): string {
|
||||
case 'LOGIST':
|
||||
return 'Логистика'
|
||||
case 'WHOLESALE':
|
||||
return 'Оптовик'
|
||||
return 'Поставщик'
|
||||
default:
|
||||
return type
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ export function MessengerChat({ counterparty, onMessagesRead }: MessengerChatPro
|
||||
case 'LOGIST':
|
||||
return 'Логистика'
|
||||
case 'WHOLESALE':
|
||||
return 'Оптовик'
|
||||
return 'Поставщик'
|
||||
default:
|
||||
return type
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ export function MessengerConversations({
|
||||
case 'LOGIST':
|
||||
return 'Логистика'
|
||||
case 'WHOLESALE':
|
||||
return 'Оптовик'
|
||||
return 'Поставщик'
|
||||
default:
|
||||
return type
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ export function PartnersDashboard() {
|
||||
value="wholesale"
|
||||
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70"
|
||||
>
|
||||
Оптовик
|
||||
Поставщик
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
|
@ -36,7 +36,7 @@ export function CartSummary({
|
||||
return null
|
||||
}
|
||||
|
||||
// Группируем товары по оптовикам
|
||||
// Группируем товары по поставщикам
|
||||
const groupedProducts = selectedProducts.reduce((acc, product) => {
|
||||
if (!acc[product.wholesalerId]) {
|
||||
acc[product.wholesalerId] = {
|
||||
@ -86,7 +86,7 @@ export function CartSummary({
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Группировка по оптовикам */}
|
||||
{/* Группировка по поставщикам */}
|
||||
{Object.entries(groupedProducts).map(([wholesalerId, group]) => (
|
||||
<div key={wholesalerId} className="mb-4 last:mb-0">
|
||||
<div className="flex items-center mb-2 pb-1 border-b border-white/10">
|
||||
|
@ -106,7 +106,7 @@ export function CreateConsumablesSupplyPage() {
|
||||
// Мутация для создания заказа поставки расходников
|
||||
const [createSupplyOrder] = useMutation(CREATE_SUPPLY_ORDER);
|
||||
|
||||
// Фильтруем только поставщиков расходников (оптовиков)
|
||||
// Фильтруем только поставщиков расходников (поставщиков)
|
||||
const consumableSuppliers = (
|
||||
counterpartiesData?.myCounterparties || []
|
||||
).filter((org: ConsumableSupplier) => org.type === "WHOLESALE");
|
||||
|
@ -40,7 +40,7 @@ interface CreateSupplyFormProps {
|
||||
onSupplyCreated: () => void
|
||||
}
|
||||
|
||||
// Моковые данные оптовиков
|
||||
// Моковые данные поставщиков
|
||||
const mockWholesalers: Wholesaler[] = [
|
||||
{
|
||||
id: '1',
|
||||
@ -126,7 +126,7 @@ export function CreateSupplyForm({ onClose, onSupplyCreated }: CreateSupplyFormP
|
||||
Назад
|
||||
</Button>
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-white mb-1">Товары оптовика</h2>
|
||||
<h2 className="text-2xl font-bold text-white mb-1">Товары поставщика</h2>
|
||||
<p className="text-white/60">{selectedWholesaler.name}</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -140,7 +140,7 @@ export function CreateSupplyForm({ onClose, onSupplyCreated }: CreateSupplyFormP
|
||||
</Button>
|
||||
</div>
|
||||
<div className="text-center py-12">
|
||||
<p className="text-white/60">Компонент товаров оптовика в разработке...</p>
|
||||
<p className="text-white/60">Компонент товаров поставщика в разработке...</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@ -160,8 +160,8 @@ export function CreateSupplyForm({ onClose, onSupplyCreated }: CreateSupplyFormP
|
||||
Назад
|
||||
</Button>
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-white mb-1">Выбор оптовика</h2>
|
||||
<p className="text-white/60">Выберите оптовика для создания поставки</p>
|
||||
<h2 className="text-2xl font-bold text-white mb-1">Выбор поставщика</h2>
|
||||
<p className="text-white/60">Выберите поставщика для создания поставки</p>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
@ -294,7 +294,7 @@ export function CreateSupplyForm({ onClose, onSupplyCreated }: CreateSupplyFormP
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Вариант 2: Оптовик */}
|
||||
{/* Вариант 2: Поставщик */}
|
||||
<Card
|
||||
className="bg-white/10 backdrop-blur border-white/20 p-6 cursor-pointer transition-all hover:bg-white/15 hover:border-white/30"
|
||||
onClick={() => setSelectedVariant('wholesaler')}
|
||||
@ -304,9 +304,9 @@ export function CreateSupplyForm({ onClose, onSupplyCreated }: CreateSupplyFormP
|
||||
<Users className="h-8 w-8 text-green-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-white mb-2">Оптовик</h3>
|
||||
<h3 className="text-xl font-semibold text-white mb-2">Поставщик</h3>
|
||||
<p className="text-white/60 text-sm">
|
||||
Создание поставки через выбор товаров у оптовиков
|
||||
Создание поставки через выбор товаров у поставщиков
|
||||
</p>
|
||||
</div>
|
||||
<Badge className="bg-green-500/20 text-green-300 border-green-500/30">
|
||||
|
@ -604,7 +604,7 @@ export function FulfillmentGoodsTab() {
|
||||
<div className="w-1 h-1 rounded-full bg-green-400 mr-1"></div>
|
||||
<Building2 className="h-3 w-3 text-green-400" />
|
||||
<span className="text-white font-medium text-sm">
|
||||
Оптовик
|
||||
Поставщик
|
||||
</span>
|
||||
</div>
|
||||
<div className="absolute left-0 top-0 w-0.5 h-full bg-green-400/30"></div>
|
||||
|
@ -106,13 +106,13 @@ export function RealSupplyOrdersTab() {
|
||||
}
|
||||
);
|
||||
|
||||
// Получаем ID текущей организации (оптовика)
|
||||
// Получаем ID текущей организации (поставщика)
|
||||
const currentOrganizationId = user?.organization?.id;
|
||||
|
||||
// Фильтруем заказы где текущая организация является поставщиком (заказы К оптовику)
|
||||
// Фильтруем заказы где текущая организация является поставщиком (заказы К поставщику)
|
||||
const incomingSupplyOrders: SupplyOrder[] = (data?.supplyOrders || []).filter(
|
||||
(order: SupplyOrder) => {
|
||||
// Показываем заказы где текущий оптовик указан как поставщик (partnerId)
|
||||
// Показываем заказы где текущий поставщик указан как поставщик (partnerId)
|
||||
return order.partner.id === currentOrganizationId;
|
||||
}
|
||||
);
|
||||
@ -208,7 +208,7 @@ export function RealSupplyOrdersTab() {
|
||||
});
|
||||
};
|
||||
|
||||
// Статистика для оптовика
|
||||
// Статистика для поставщика
|
||||
const totalOrders = incomingSupplyOrders.length;
|
||||
const totalAmount = incomingSupplyOrders.reduce(
|
||||
(sum, order) => sum + order.totalAmount,
|
||||
|
@ -630,7 +630,7 @@ export function SuppliesGoodsTab() {
|
||||
</Button>
|
||||
<Building2 className="h-4 w-4 text-green-400" />
|
||||
<span className="text-white font-medium">
|
||||
Оптовик
|
||||
Поставщик
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
|
@ -36,8 +36,8 @@ export function ProductGrid({
|
||||
<div className="flex items-center justify-center p-8">
|
||||
<div className="text-center">
|
||||
<Package className="h-12 w-12 text-white/20 mx-auto mb-4" />
|
||||
<p className="text-white/60">У этого оптовика нет товаров</p>
|
||||
<p className="text-white/40 text-sm mt-2">Выберите другого оптовика</p>
|
||||
<p className="text-white/60">У этого поставщика нет товаров</p>
|
||||
<p className="text-white/40 text-sm mt-2">Выберите другого поставщика</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -95,7 +95,7 @@ export function TabsHeader({
|
||||
}`}
|
||||
>
|
||||
<Users className="h-4 w-4 mr-1 inline" />
|
||||
Оптовики
|
||||
Поставщики
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -21,7 +21,7 @@ export function WholesalerGrid({
|
||||
onSearchChange,
|
||||
loading = false
|
||||
}: WholesalerGridProps) {
|
||||
// Фильтруем оптовиков по поисковому запросу
|
||||
// Фильтруем поставщиков по поисковому запросу
|
||||
const filteredWholesalers = wholesalers.filter((wholesaler) =>
|
||||
wholesaler.name?.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
wholesaler.fullName?.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
@ -50,7 +50,7 @@ export function WholesalerGrid({
|
||||
<div className="flex items-center justify-center p-8">
|
||||
<div className="text-center">
|
||||
<div className="animate-spin rounded-full h-12 w-12 border-4 border-white border-t-transparent mx-auto mb-4"></div>
|
||||
<p className="text-white/60">Загружаем оптовиков...</p>
|
||||
<p className="text-white/60">Загружаем поставщиков...</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@ -63,7 +63,7 @@ export function WholesalerGrid({
|
||||
<div className="relative max-w-md">
|
||||
<Search className="absolute left-3 top-3 h-4 w-4 text-white/40" />
|
||||
<Input
|
||||
placeholder="Поиск оптовиков..."
|
||||
placeholder="Поиск поставщиков..."
|
||||
value={searchQuery}
|
||||
onChange={(e) => onSearchChange(e.target.value)}
|
||||
className="pl-10 glass-input text-white placeholder:text-white/40 h-10"
|
||||
@ -75,10 +75,10 @@ export function WholesalerGrid({
|
||||
<div className="text-center p-8">
|
||||
<Users className="h-12 w-12 text-white/20 mx-auto mb-4" />
|
||||
<p className="text-white/60">
|
||||
{searchQuery ? 'Оптовики не найдены' : 'У вас нет контрагентов-оптовиков'}
|
||||
{searchQuery ? 'Поставщики не найдены' : 'У вас нет контрагентов-поставщиков'}
|
||||
</p>
|
||||
<p className="text-white/40 text-sm mt-2">
|
||||
{searchQuery ? 'Попробуйте изменить условия поиска' : 'Добавьте оптовиков в разделе "Партнеры"'}
|
||||
{searchQuery ? 'Попробуйте изменить условия поиска' : 'Добавьте поставщиков в разделе "Партнеры"'}
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
|
@ -85,7 +85,7 @@ export function WholesalerProductsPage({
|
||||
Назад
|
||||
</Button>
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-white mb-2">Товары оптовика</h1>
|
||||
<h1 className="text-3xl font-bold text-white mb-2">Товары поставщика</h1>
|
||||
<p className="text-white/60">{selectedWholesaler.name} • {products.length} товаров</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -233,7 +233,7 @@ export function WholesalerProducts({ wholesaler, onBack, onClose, onSupplyCreate
|
||||
Назад
|
||||
</Button>
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-white mb-1">Товары оптовика</h2>
|
||||
<h2 className="text-2xl font-bold text-white mb-1">Товары поставщика</h2>
|
||||
<p className="text-white/60">{wholesaler.name} • {mockProducts.length} товаров</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -35,7 +35,7 @@ interface WholesalerSelectionProps {
|
||||
onSupplyCreated: () => void
|
||||
}
|
||||
|
||||
// Моковые данные оптовиков
|
||||
// Моковые данные поставщиков
|
||||
const mockWholesalers: Wholesaler[] = [
|
||||
{
|
||||
id: '1',
|
||||
@ -129,7 +129,7 @@ export function WholesalerSelection({ onBack, onClose, onSupplyCreated }: Wholes
|
||||
Назад
|
||||
</Button>
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-white mb-1">Товары оптовика</h2>
|
||||
<h2 className="text-2xl font-bold text-white mb-1">Товары поставщика</h2>
|
||||
<p className="text-white/60">{selectedWholesaler.name}</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -164,8 +164,8 @@ export function WholesalerSelection({ onBack, onClose, onSupplyCreated }: Wholes
|
||||
Назад
|
||||
</Button>
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-white mb-1">Выбор оптовика</h2>
|
||||
<p className="text-white/60">Выберите оптовика для создания поставки</p>
|
||||
<h2 className="text-2xl font-bold text-white mb-1">Выбор поставщика</h2>
|
||||
<p className="text-white/60">Выберите поставщика для создания поставки</p>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
|
@ -791,7 +791,7 @@ export const DELETE_LOGISTICS = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
// Мутации для товаров оптовика
|
||||
// Мутации для товаров поставщика
|
||||
export const CREATE_PRODUCT = gql`
|
||||
mutation CreateProduct($input: ProductInput!) {
|
||||
createProduct(input: $input) {
|
||||
|
@ -823,7 +823,7 @@ export const resolvers = {
|
||||
});
|
||||
},
|
||||
|
||||
// Мои товары (для оптовиков)
|
||||
// Мои товары (для поставщиков)
|
||||
myProducts: async (_: unknown, __: unknown, context: Context) => {
|
||||
if (!context.user) {
|
||||
throw new GraphQLError("Требуется авторизация", {
|
||||
@ -840,9 +840,9 @@ export const resolvers = {
|
||||
throw new GraphQLError("У пользователя нет организации");
|
||||
}
|
||||
|
||||
// Проверяем, что это оптовик
|
||||
// Проверяем, что это поставщик
|
||||
if (currentUser.organization.type !== "WHOLESALE") {
|
||||
throw new GraphQLError("Товары доступны только для оптовиков");
|
||||
throw new GraphQLError("Товары доступны только для поставщиков");
|
||||
}
|
||||
|
||||
return await prisma.product.findMany({
|
||||
@ -855,7 +855,7 @@ export const resolvers = {
|
||||
});
|
||||
},
|
||||
|
||||
// Все товары всех оптовиков для маркета
|
||||
// Все товары всех поставщиков для маркета
|
||||
allProducts: async (
|
||||
_: unknown,
|
||||
args: { search?: string; category?: string },
|
||||
@ -870,7 +870,7 @@ export const resolvers = {
|
||||
const where: Record<string, unknown> = {
|
||||
isActive: true, // Показываем только активные товары
|
||||
organization: {
|
||||
type: "WHOLESALE", // Только товары оптовиков
|
||||
type: "WHOLESALE", // Только товары поставщиков
|
||||
},
|
||||
};
|
||||
|
||||
@ -964,7 +964,7 @@ export const resolvers = {
|
||||
});
|
||||
},
|
||||
|
||||
// Публичные расходники контрагента (для оптовиков)
|
||||
// Публичные расходники контрагента (для поставщиков)
|
||||
counterpartySupplies: async (
|
||||
_: unknown,
|
||||
args: { organizationId: string },
|
||||
@ -3189,7 +3189,7 @@ export const resolvers = {
|
||||
}
|
||||
}
|
||||
|
||||
// Проверяем, что партнер существует и является оптовиком
|
||||
// Проверяем, что партнер существует и является поставщиком
|
||||
const partner = await prisma.organization.findFirst({
|
||||
where: {
|
||||
id: args.input.partnerId,
|
||||
@ -3200,7 +3200,7 @@ export const resolvers = {
|
||||
if (!partner) {
|
||||
return {
|
||||
success: false,
|
||||
message: "Партнер не найден или не является оптовиком",
|
||||
message: "Партнер не найден или не является поставщиком",
|
||||
};
|
||||
}
|
||||
|
||||
@ -3425,9 +3425,9 @@ export const resolvers = {
|
||||
throw new GraphQLError("У пользователя нет организации");
|
||||
}
|
||||
|
||||
// Проверяем, что это оптовик
|
||||
// Проверяем, что это поставщик
|
||||
if (currentUser.organization.type !== "WHOLESALE") {
|
||||
throw new GraphQLError("Товары доступны только для оптовиков");
|
||||
throw new GraphQLError("Товары доступны только для поставщиков");
|
||||
}
|
||||
|
||||
// Проверяем уникальность артикула в рамках организации
|
||||
|
@ -49,10 +49,10 @@ export const typeDefs = gql`
|
||||
# Поставки Wildberries
|
||||
myWildberriesSupplies: [WildberriesSupply!]!
|
||||
|
||||
# Товары оптовика
|
||||
# Товары поставщика
|
||||
myProducts: [Product!]!
|
||||
|
||||
# Все товары всех оптовиков для маркета
|
||||
# Все товары всех поставщиков для маркета
|
||||
allProducts(search: String, category: String): [Product!]!
|
||||
|
||||
# Все категории
|
||||
@ -78,7 +78,7 @@ export const typeDefs = gql`
|
||||
# Публичные услуги контрагента (для фулфилмента)
|
||||
counterpartyServices(organizationId: ID!): [Service!]!
|
||||
|
||||
# Публичные расходники контрагента (для оптовиков)
|
||||
# Публичные расходники контрагента (для поставщиков)
|
||||
counterpartySupplies(organizationId: ID!): [Supply!]!
|
||||
|
||||
# Админ запросы
|
||||
@ -188,7 +188,7 @@ export const typeDefs = gql`
|
||||
updateLogistics(id: ID!, input: LogisticsInput!): LogisticsResponse!
|
||||
deleteLogistics(id: ID!): Boolean!
|
||||
|
||||
# Работа с товарами (для оптовиков)
|
||||
# Работа с товарами (для поставщиков)
|
||||
createProduct(input: ProductInput!): ProductResponse!
|
||||
updateProduct(id: ID!, input: ProductInput!): ProductResponse!
|
||||
deleteProduct(id: ID!): Boolean!
|
||||
@ -621,7 +621,7 @@ export const typeDefs = gql`
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
|
||||
# Типы для товаров оптовика
|
||||
# Типы для товаров поставщика
|
||||
type Product {
|
||||
id: ID!
|
||||
name: String!
|
||||
|
Reference in New Issue
Block a user