docs: обновление архитектурной документации и модульного рефакторинга
- Обновлен CLAUDE.md с новыми правилами системы - Дополнен workflow-catalog.md с процессами - Обновлены interaction-integrity-rules.md - Завершен модульный рефакторинг create-suppliers компонента - Добавлен модульный user-settings с блочной архитектурой - Система готова к следующему этапу архитектурных улучшений 🚀 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -31,7 +31,8 @@ export const CartBlock = React.memo(function CartBlock({
|
||||
}: CartBlockProps) {
|
||||
return (
|
||||
<div className="w-72 flex-shrink-0">
|
||||
<div className="bg-white/10 backdrop-blur border-white/20 p-3 sticky top-0 rounded-2xl">
|
||||
{/* ОТКАТ: было w-96, вернули w-72 */}
|
||||
<div className="bg-white/10 backdrop-blur border-white/20 p-3 rounded-2xl h-full flex flex-col">
|
||||
<h3 className="text-white font-semibold mb-3 flex items-center text-sm">
|
||||
<ShoppingCart className="h-4 w-4 mr-2" />
|
||||
Корзина ({selectedGoods.length} шт)
|
||||
@ -47,31 +48,33 @@ export const CartBlock = React.memo(function CartBlock({
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{/* Список товаров в корзине */}
|
||||
<div className="space-y-2 mb-4">
|
||||
{selectedGoods.map((item) => {
|
||||
const priceWithRecipe = item.price // Здесь будет расчет с рецептурой
|
||||
{/* Список товаров в корзине - скроллируемая область */}
|
||||
<div className="flex-1 overflow-y-auto mb-4">
|
||||
<div className="space-y-2">
|
||||
{selectedGoods.map((item) => {
|
||||
const priceWithRecipe = item.price // Здесь будет расчет с рецептурой
|
||||
|
||||
return (
|
||||
<div key={item.id} className="flex items-center justify-between bg-white/5 rounded-lg p-2">
|
||||
<div className="flex-1 min-w-0">
|
||||
<h4 className="text-white text-sm font-medium truncate">{item.name}</h4>
|
||||
<p className="text-white/60 text-xs">
|
||||
{priceWithRecipe.toLocaleString('ru-RU')} ₽ × {item.selectedQuantity}
|
||||
</p>
|
||||
return (
|
||||
<div key={item.id} className="flex items-center justify-between bg-white/5 rounded-lg p-2">
|
||||
<div className="flex-1 min-w-0">
|
||||
<h4 className="text-white text-sm font-medium truncate">{item.name}</h4>
|
||||
<p className="text-white/60 text-xs">
|
||||
{priceWithRecipe.toLocaleString('ru-RU')} ₽ × {item.selectedQuantity}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => onItemRemove(item.id)}
|
||||
className="text-white/40 hover:text-red-400 ml-2 transition-colors"
|
||||
>
|
||||
<X className="h-3 w-3" />
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => onItemRemove(item.id)}
|
||||
className="text-white/40 hover:text-red-400 ml-2 transition-colors"
|
||||
>
|
||||
<X className="h-3 w-3" />
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Настройки поставки */}
|
||||
{/* Настройки поставки - фиксированная область */}
|
||||
<div className="space-y-3 mb-4">
|
||||
<div>
|
||||
<p className="text-white/60 text-xs mb-1">Дата поставки:</p>
|
||||
|
@ -43,7 +43,7 @@ export const DetailedCatalogBlock = React.memo(function DetailedCatalogBlock({
|
||||
const fulfillmentCenters = allCounterparties?.filter((partner) => partner.type === 'FULFILLMENT') || []
|
||||
|
||||
return (
|
||||
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl">
|
||||
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl h-full flex flex-col">
|
||||
{/* Панель управления */}
|
||||
<div className="p-6 border-b border-white/10">
|
||||
<h3 className="text-white font-semibold text-lg mb-4 flex items-center">
|
||||
@ -89,7 +89,7 @@ export const DetailedCatalogBlock = React.memo(function DetailedCatalogBlock({
|
||||
</div>
|
||||
|
||||
{/* Каталог товаров с рецептурой */}
|
||||
<div className="p-6">
|
||||
<div className="flex-1 overflow-y-auto p-6">
|
||||
<h4 className="text-white font-semibold text-md mb-4">Товары в поставке ({allSelectedProducts.length})</h4>
|
||||
|
||||
{allSelectedProducts.length === 0 ? (
|
||||
|
@ -22,7 +22,8 @@ export const ProductCardsBlock = React.memo(function ProductCardsBlock({
|
||||
}: ProductCardsBlockProps) {
|
||||
if (!selectedSupplier) {
|
||||
return (
|
||||
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-6">
|
||||
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-6 h-full flex flex-col">
|
||||
{/* ОТКАТ: вернули h-full flex flex-col */}
|
||||
<div className="text-center py-8">
|
||||
<div className="bg-gradient-to-br from-blue-500/20 to-purple-500/20 rounded-full p-4 w-fit mx-auto mb-3">
|
||||
<Package className="h-8 w-8 text-blue-300" />
|
||||
@ -36,7 +37,8 @@ export const ProductCardsBlock = React.memo(function ProductCardsBlock({
|
||||
|
||||
if (products.length === 0) {
|
||||
return (
|
||||
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-6">
|
||||
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-6 h-full flex flex-col">
|
||||
{/* ОТКАТ: вернули h-full flex flex-col */}
|
||||
<h3 className="text-white font-semibold text-lg mb-4">2. Товары поставщика (0)</h3>
|
||||
<div className="text-center py-8">
|
||||
<div className="bg-gradient-to-br from-orange-500/20 to-red-500/20 rounded-full p-4 w-fit mx-auto mb-3">
|
||||
@ -50,10 +52,12 @@ export const ProductCardsBlock = React.memo(function ProductCardsBlock({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-6">
|
||||
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-6 h-full flex flex-col">
|
||||
{/* ОТКАТ: вернули h-full flex flex-col */}
|
||||
<h3 className="text-white font-semibold text-lg mb-4">2. Товары поставщика ({products.length})</h3>
|
||||
|
||||
<div className="overflow-x-auto">
|
||||
<div className="flex-1 overflow-x-auto overflow-y-hidden">
|
||||
{/* ОТКАТ: вернули flex-1 overflow-x-auto overflow-y-hidden */}
|
||||
<div className="flex gap-3 pb-2" style={{ width: 'max-content' }}>
|
||||
{products.slice(0, 10).map(
|
||||
(
|
||||
|
@ -25,8 +25,8 @@ export const SuppliersBlock = React.memo(function SuppliersBlock({
|
||||
}: SuppliersBlockProps) {
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-6">
|
||||
<div className="flex items-center justify-center h-44">
|
||||
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-6 h-full flex flex-col">
|
||||
<div className="flex items-center justify-center flex-1">
|
||||
<div className="text-white/60 text-sm">Загрузка поставщиков...</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -34,7 +34,7 @@ export const SuppliersBlock = React.memo(function SuppliersBlock({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-6">
|
||||
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-6 h-full flex flex-col">
|
||||
{/* Заголовок и поиск */}
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-white font-semibold text-lg">1. Выберите поставщика ({suppliers.length})</h3>
|
||||
@ -50,7 +50,7 @@ export const SuppliersBlock = React.memo(function SuppliersBlock({
|
||||
</div>
|
||||
|
||||
{suppliers.length === 0 ? (
|
||||
<div className="flex items-center justify-center h-44">
|
||||
<div className="flex items-center justify-center flex-1">
|
||||
<div className="text-center">
|
||||
<div className="text-white/60 text-sm mb-2">
|
||||
{searchQuery ? 'Поставщики не найдены' : 'Нет доступных поставщиков'}
|
||||
@ -66,7 +66,7 @@ export const SuppliersBlock = React.memo(function SuppliersBlock({
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="h-44 overflow-hidden">
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<div
|
||||
className={`h-full ${
|
||||
suppliers.length <= 4
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
import { useMutation } from '@apollo/client'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useState, useMemo } from 'react'
|
||||
import { useState, useMemo, useCallback } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
import { CREATE_SUPPLY_ORDER } from '@/graphql/mutations'
|
||||
|
@ -191,24 +191,30 @@ export function CreateSuppliersSupplyPage() {
|
||||
<div className="flex-1 flex gap-2 min-h-0">
|
||||
{/* ЛЕВАЯ КОЛОНКА - 3 блока */}
|
||||
<div className="flex-1 flex flex-col gap-2 min-h-0">
|
||||
{/* БЛОК 1: ВЫБОР ПОСТАВЩИКОВ */}
|
||||
<SuppliersBlock
|
||||
suppliers={suppliers}
|
||||
selectedSupplier={selectedSupplier}
|
||||
searchQuery={searchQuery}
|
||||
loading={suppliersLoading}
|
||||
onSupplierSelect={handleSupplierSelect}
|
||||
onSearchChange={setSearchQuery}
|
||||
/>
|
||||
{/* БЛОК 1: ВЫБОР ПОСТАВЩИКОВ - Фиксированная высота */}
|
||||
<div className="h-48">
|
||||
{/* ОТКАТ: было h-44, вернули h-48 */}
|
||||
<SuppliersBlock
|
||||
suppliers={suppliers}
|
||||
selectedSupplier={selectedSupplier}
|
||||
searchQuery={searchQuery}
|
||||
loading={suppliersLoading}
|
||||
onSupplierSelect={handleSupplierSelect}
|
||||
onSearchChange={setSearchQuery}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* БЛОК 2: КАРТОЧКИ ТОВАРОВ (МИНИ-ПРЕВЬЮ) */}
|
||||
<ProductCardsBlock
|
||||
products={products}
|
||||
selectedSupplier={selectedSupplier}
|
||||
onProductAdd={handleProductAdd}
|
||||
/>
|
||||
{/* БЛОК 2: КАРТОЧКИ ТОВАРОВ (МИНИ-ПРЕВЬЮ) - Фиксированная высота */}
|
||||
<div className="h-72">
|
||||
{/* ОТКАТ: было flex-shrink-0, вернули h-72 */}
|
||||
<ProductCardsBlock
|
||||
products={products}
|
||||
selectedSupplier={selectedSupplier}
|
||||
onProductAdd={handleProductAdd}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* БЛОК 3: ДЕТАЛЬНЫЙ КАТАЛОГ С РЕЦЕПТУРОЙ */}
|
||||
{/* БЛОК 3: ДЕТАЛЬНЫЙ КАТАЛОГ С РЕЦЕПТУРОЙ - Оставшееся место */}
|
||||
<div className="flex-1 min-h-0">
|
||||
<DetailedCatalogBlock
|
||||
allSelectedProducts={allSelectedProducts}
|
||||
|
Reference in New Issue
Block a user