274 lines
8.7 KiB
TypeScript
274 lines
8.7 KiB
TypeScript
"use client";
|
||
|
||
import React, { useState } from "react";
|
||
import { Sidebar } from "@/components/dashboard/sidebar";
|
||
import { useSidebar } from "@/hooks/useSidebar";
|
||
import { useRouter } from "next/navigation";
|
||
import { DirectSupplyCreation } from "./direct-supply-creation";
|
||
import { WholesalerProductsPage } from "./wholesaler-products-page";
|
||
import { TabsHeader } from "./tabs-header";
|
||
import { WholesalerGrid } from "./wholesaler-grid";
|
||
import { CartSummary } from "./cart-summary";
|
||
import { FloatingCart } from "./floating-cart";
|
||
import {
|
||
WholesalerForCreation,
|
||
WholesalerProduct,
|
||
SelectedProduct,
|
||
CounterpartyWholesaler,
|
||
} from "./types";
|
||
import { useQuery } from "@apollo/client";
|
||
import { GET_MY_COUNTERPARTIES, GET_ALL_PRODUCTS } from "@/graphql/queries";
|
||
|
||
export function CreateSupplyPage() {
|
||
const router = useRouter();
|
||
const { getSidebarMargin } = useSidebar();
|
||
const [activeTab, setActiveTab] = useState<"cards" | "wholesaler">("cards");
|
||
const [selectedWholesaler, setSelectedWholesaler] =
|
||
useState<WholesalerForCreation | null>(null);
|
||
const [selectedProducts, setSelectedProducts] = useState<SelectedProduct[]>(
|
||
[]
|
||
);
|
||
const [showSummary, setShowSummary] = useState(false);
|
||
const [searchQuery, setSearchQuery] = useState("");
|
||
const [canCreateSupply, setCanCreateSupply] = useState(false);
|
||
const [isCreatingSupply, setIsCreatingSupply] = useState(false);
|
||
|
||
// Загружаем контрагентов-оптовиков
|
||
const { data: counterpartiesData, loading: counterpartiesLoading } = useQuery(
|
||
GET_MY_COUNTERPARTIES
|
||
);
|
||
|
||
// Загружаем товары для выбранного оптовика
|
||
const { data: productsData, loading: productsLoading } = useQuery(
|
||
GET_ALL_PRODUCTS,
|
||
{
|
||
skip: !selectedWholesaler,
|
||
variables: { search: null, category: null },
|
||
}
|
||
);
|
||
|
||
// Фильтруем только оптовиков
|
||
const wholesalers: CounterpartyWholesaler[] = (
|
||
counterpartiesData?.myCounterparties || []
|
||
).filter((org: { type: string }) => org.type === "WHOLESALE");
|
||
|
||
// Фильтруем товары по выбранному оптовику
|
||
const wholesalerProducts: WholesalerProduct[] = selectedWholesaler
|
||
? (productsData?.allProducts || []).filter(
|
||
(product: { organization: { id: string } }) =>
|
||
product.organization.id === selectedWholesaler.id
|
||
)
|
||
: [];
|
||
|
||
const formatCurrency = (amount: number) => {
|
||
return new Intl.NumberFormat("ru-RU", {
|
||
style: "currency",
|
||
currency: "RUB",
|
||
minimumFractionDigits: 0,
|
||
}).format(amount);
|
||
};
|
||
|
||
const updateProductQuantity = (productId: string, quantity: number) => {
|
||
const product = wholesalerProducts.find((p) => p.id === productId);
|
||
if (!product || !selectedWholesaler) return;
|
||
|
||
setSelectedProducts((prev) => {
|
||
const existing = prev.find(
|
||
(p) => p.id === productId && p.wholesalerId === selectedWholesaler.id
|
||
);
|
||
|
||
if (quantity === 0) {
|
||
return prev.filter(
|
||
(p) =>
|
||
!(p.id === productId && p.wholesalerId === selectedWholesaler.id)
|
||
);
|
||
}
|
||
|
||
if (existing) {
|
||
return prev.map((p) =>
|
||
p.id === productId && p.wholesalerId === selectedWholesaler.id
|
||
? { ...p, selectedQuantity: quantity }
|
||
: p
|
||
);
|
||
} else {
|
||
return [
|
||
...prev,
|
||
{
|
||
...product,
|
||
selectedQuantity: quantity,
|
||
wholesalerId: selectedWholesaler.id,
|
||
wholesalerName: selectedWholesaler.name,
|
||
},
|
||
];
|
||
}
|
||
});
|
||
};
|
||
|
||
const getTotalAmount = () => {
|
||
return selectedProducts.reduce((sum, product) => {
|
||
const discountedPrice = product.discount
|
||
? product.price * (1 - product.discount / 100)
|
||
: product.price;
|
||
return sum + discountedPrice * product.selectedQuantity;
|
||
}, 0);
|
||
};
|
||
|
||
const getTotalItems = () => {
|
||
return selectedProducts.reduce(
|
||
(sum, product) => sum + product.selectedQuantity,
|
||
0
|
||
);
|
||
};
|
||
|
||
const handleCreateSupply = () => {
|
||
if (activeTab === "cards") {
|
||
console.log("Создание поставки с карточками Wildberries");
|
||
} else {
|
||
console.log("Создание поставки с товарами:", selectedProducts);
|
||
}
|
||
router.push("/supplies");
|
||
};
|
||
|
||
const handleGoBack = () => {
|
||
if (selectedWholesaler) {
|
||
setSelectedWholesaler(null);
|
||
setShowSummary(false);
|
||
} else {
|
||
router.push("/supplies");
|
||
}
|
||
};
|
||
|
||
const handleRemoveProduct = (productId: string, wholesalerId: string) => {
|
||
setSelectedProducts((prev) =>
|
||
prev.filter(
|
||
(p) => !(p.id === productId && p.wholesalerId === wholesalerId)
|
||
)
|
||
);
|
||
};
|
||
|
||
const handleCartQuantityChange = (
|
||
productId: string,
|
||
wholesalerId: string,
|
||
quantity: number
|
||
) => {
|
||
setSelectedProducts((prev) =>
|
||
prev.map((p) =>
|
||
p.id === productId && p.wholesalerId === wholesalerId
|
||
? { ...p, selectedQuantity: quantity }
|
||
: p
|
||
)
|
||
);
|
||
};
|
||
|
||
const handleSupplyComplete = () => {
|
||
router.push("/supplies");
|
||
};
|
||
|
||
const handleCreateSupplyClick = () => {
|
||
setIsCreatingSupply(true);
|
||
};
|
||
|
||
const handleCanCreateSupplyChange = (canCreate: boolean) => {
|
||
setCanCreateSupply(canCreate);
|
||
};
|
||
|
||
const handleSupplyCompleted = () => {
|
||
setIsCreatingSupply(false);
|
||
handleSupplyComplete();
|
||
};
|
||
|
||
// Рендер страницы товаров оптовика
|
||
if (selectedWholesaler && activeTab === "wholesaler") {
|
||
return (
|
||
<WholesalerProductsPage
|
||
selectedWholesaler={selectedWholesaler}
|
||
products={wholesalerProducts}
|
||
selectedProducts={selectedProducts}
|
||
onQuantityChange={updateProductQuantity}
|
||
onBack={handleGoBack}
|
||
onCreateSupply={handleCreateSupply}
|
||
formatCurrency={formatCurrency}
|
||
showSummary={showSummary}
|
||
setShowSummary={setShowSummary}
|
||
loading={productsLoading}
|
||
/>
|
||
);
|
||
}
|
||
|
||
// Главная страница с табами
|
||
return (
|
||
<div className="h-screen flex overflow-hidden">
|
||
<Sidebar />
|
||
<main
|
||
className={`flex-1 ${getSidebarMargin()} overflow-hidden transition-all duration-300`}
|
||
style={{ padding: '1rem' }}
|
||
>
|
||
<div className="flex flex-col" style={{ height: 'calc(100vh - 2rem)' }}>
|
||
<TabsHeader
|
||
activeTab={activeTab}
|
||
onTabChange={setActiveTab}
|
||
onBack={() => router.push("/supplies")}
|
||
cartInfo={
|
||
activeTab === "wholesaler" && selectedProducts.length > 0
|
||
? {
|
||
itemCount: selectedProducts.length,
|
||
totalAmount: getTotalAmount(),
|
||
formatCurrency,
|
||
}
|
||
: undefined
|
||
}
|
||
onCartClick={() => setShowSummary(true)}
|
||
onCreateSupply={handleCreateSupplyClick}
|
||
canCreateSupply={canCreateSupply}
|
||
isCreatingSupply={isCreatingSupply}
|
||
/>
|
||
|
||
{/* Контент карточек - новый компонент прямого создания поставки */}
|
||
{activeTab === "cards" && (
|
||
<div className="flex-1 flex flex-col overflow-hidden min-h-0">
|
||
<DirectSupplyCreation
|
||
onComplete={handleSupplyCompleted}
|
||
onCreateSupply={handleCreateSupplyClick}
|
||
canCreateSupply={canCreateSupply}
|
||
isCreatingSupply={isCreatingSupply}
|
||
onCanCreateSupplyChange={handleCanCreateSupplyChange}
|
||
/>
|
||
</div>
|
||
)}
|
||
|
||
{/* Контент оптовиков */}
|
||
{activeTab === "wholesaler" && (
|
||
<div>
|
||
<CartSummary
|
||
selectedProducts={selectedProducts}
|
||
onQuantityChange={handleCartQuantityChange}
|
||
onRemoveProduct={handleRemoveProduct}
|
||
onCreateSupply={handleCreateSupply}
|
||
onToggleVisibility={() => setShowSummary(false)}
|
||
formatCurrency={formatCurrency}
|
||
visible={showSummary && selectedProducts.length > 0}
|
||
/>
|
||
|
||
<WholesalerGrid
|
||
wholesalers={wholesalers}
|
||
onWholesalerSelect={setSelectedWholesaler}
|
||
searchQuery={searchQuery}
|
||
onSearchChange={setSearchQuery}
|
||
loading={counterpartiesLoading}
|
||
/>
|
||
|
||
<FloatingCart
|
||
itemCount={selectedProducts.length}
|
||
totalAmount={getTotalAmount()}
|
||
formatCurrency={formatCurrency}
|
||
onClick={() => setShowSummary(true)}
|
||
visible={selectedProducts.length > 0 && !showSummary}
|
||
/>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</main>
|
||
</div>
|
||
);
|
||
}
|