feat: завершить полную миграцию V1→V2 с модульной архитектурой и документацией
АРХИТЕКТУРНЫЕ ИЗМЕНЕНИЯ: - Полная миграция на URL структуру /{role}/{domain}/{section}/{view} - Удаление всех старых директорий (/fulfillment-supplies/, /fulfillment-warehouse/, etc.) - Модульная архитектура seller warehouse с URL-based routing - Система rollback через комментарии для безопасных изменений НОВЫЕ КОМПОНЕНТЫ И СТРАНИЦЫ: - Создание всех недостающих страниц для FULFILLMENT, SELLER ролей - Модульный layout для seller warehouse с 3 табами - Извлечение переиспользуемого хука useWBWarehouseData ИСПРАВЛЕНИЯ БЕЗОПАСНОСТИ: - Добавление 'use client' директив во все WHOLESALE и LOGISTICS страницы - Исправление отсутствующих security guards (useRoleGuard + AuthGuard) - Обновление navigation конфигураций для всех ролей ДОКУМЕНТАЦИЯ: - Создание MIGRATION_GUIDE_V1_TO_V2.md: 8-этапное руководство по миграции - Создание NEXTJS_BEST_PRACTICES.md: паттерны для Next.js 13+ в SFERA - Обновление URL_ROUTING_RULES.md с seller warehouse и rollback системой - Обновление SIDEBAR_ARCHITECTURE_IMPLEMENTATION.md с новыми метриками - Обновление INDEX.md с новыми документами Development раздела ИСПРАВЛЕНИЯ ESLINT: - Удаление неиспользуемых импортов и переменных - Исправление import/order ошибок в модульных компонентах - Исправление react/no-unescaped-entities - Перенос длинных строк для соответствия max-len 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
124
src/app/seller/warehouse/layout.tsx
Normal file
124
src/app/seller/warehouse/layout.tsx
Normal file
@ -0,0 +1,124 @@
|
||||
'use client'
|
||||
|
||||
import { Home, Warehouse, Package } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { usePathname } from 'next/navigation'
|
||||
|
||||
import { AuthGuard } from '@/components/auth-guard'
|
||||
import { Sidebar } from '@/components/dashboard/sidebar'
|
||||
import { useRoleGuard } from '@/hooks/useRoleGuard'
|
||||
import { useSidebar } from '@/hooks/useSidebar'
|
||||
|
||||
// Компонент Breadcrumbs
|
||||
function Breadcrumbs({ pathname }: { pathname: string }) {
|
||||
const segments = pathname.split('/').filter(Boolean)
|
||||
|
||||
const breadcrumbs = [{ name: 'Главная', href: '/dashboard', icon: Home }]
|
||||
|
||||
if (segments[0] === 'seller' && segments[1] === 'warehouse') {
|
||||
breadcrumbs.push({ name: 'Склад', href: '/seller/warehouse', icon: Warehouse })
|
||||
|
||||
if (segments[2]) {
|
||||
const sectionMap: Record<string, string> = {
|
||||
fulfillment: 'Склад фулфилмент',
|
||||
wildberries: 'Склад Wildberries',
|
||||
storage: 'Мой склад',
|
||||
}
|
||||
|
||||
const section = sectionMap[segments[2]]
|
||||
if (section) {
|
||||
breadcrumbs.push({
|
||||
name: section,
|
||||
href: `/seller/warehouse/${segments[2]}`,
|
||||
icon: Package,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<nav className="flex items-center space-x-2 text-sm text-white/60 mb-6">
|
||||
{breadcrumbs.map((crumb, index) => (
|
||||
<div key={crumb.href} className="flex items-center">
|
||||
{index > 0 && <span className="mx-2 text-white/40">/</span>}
|
||||
<Link href={crumb.href} className="flex items-center gap-1 hover:text-white transition-colors">
|
||||
<crumb.icon className="h-4 w-4" />
|
||||
{crumb.name}
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
|
||||
export default function SellerWarehouseLayout({ children }: { children: React.ReactNode }) {
|
||||
useRoleGuard('SELLER')
|
||||
const { getSidebarMargin } = useSidebar()
|
||||
const pathname = usePathname()
|
||||
|
||||
// Определяем активный таб
|
||||
const getActiveTab = () => {
|
||||
if (pathname.includes('/fulfillment')) return 'fulfillment'
|
||||
if (pathname.includes('/wildberries')) return 'wildberries'
|
||||
if (pathname.includes('/storage')) return 'storage'
|
||||
return 'fulfillment' // default
|
||||
}
|
||||
|
||||
const activeTab = getActiveTab()
|
||||
|
||||
return (
|
||||
<AuthGuard>
|
||||
<div className="h-screen flex overflow-hidden">
|
||||
<Sidebar />
|
||||
<main className={`flex-1 ${getSidebarMargin()} px-6 py-4 overflow-hidden transition-all duration-300`}>
|
||||
<div className="h-full w-full flex flex-col space-y-4">
|
||||
{/* Breadcrumbs */}
|
||||
<Breadcrumbs pathname={pathname} />
|
||||
|
||||
{/* Табы навигация - точно как в WBWarehouseDashboard */}
|
||||
<div className="mb-6">
|
||||
<div className="grid grid-cols-3 w-full max-w-md bg-white/5 border border-white/10 rounded-lg p-1">
|
||||
<Link
|
||||
href="/seller/warehouse/fulfillment"
|
||||
className={`flex items-center justify-center gap-2 text-sm font-medium
|
||||
transition-all duration-200 rounded-md px-3 py-2 whitespace-nowrap ${
|
||||
activeTab === 'fulfillment'
|
||||
? 'bg-blue-600 text-white shadow-lg'
|
||||
: 'text-white/60 hover:text-white hover:bg-white/5'
|
||||
}`}
|
||||
>
|
||||
Склад фулфилмент
|
||||
</Link>
|
||||
<Link
|
||||
href="/seller/warehouse/wildberries"
|
||||
className={`flex items-center justify-center gap-2 text-sm font-medium
|
||||
transition-all duration-200 rounded-md px-3 py-2 ${
|
||||
activeTab === 'wildberries'
|
||||
? 'bg-blue-600 text-white shadow-lg'
|
||||
: 'text-white/60 hover:text-white hover:bg-white/5'
|
||||
}`}
|
||||
>
|
||||
Склад Wildberries
|
||||
</Link>
|
||||
<Link
|
||||
href="/seller/warehouse/storage"
|
||||
className={`flex items-center justify-center gap-2 text-sm font-medium
|
||||
transition-all duration-200 rounded-md px-3 py-2 ${
|
||||
activeTab === 'storage'
|
||||
? 'bg-blue-600 text-white shadow-lg'
|
||||
: 'text-white/60 hover:text-white hover:bg-white/5'
|
||||
}`}
|
||||
>
|
||||
Мой склад
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Контент страницы */}
|
||||
<div className="flex-1 overflow-hidden min-h-0">{children}</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</AuthGuard>
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user