diff --git a/src/app/logistics/page.tsx b/src/app/logistics/page.tsx new file mode 100644 index 0000000..023949e --- /dev/null +++ b/src/app/logistics/page.tsx @@ -0,0 +1,10 @@ +import { AuthGuard } from "@/components/auth-guard"; +import { LogisticsDashboard } from "@/components/logistics/logistics-dashboard"; + +export default function LogisticsPage() { + return ( + + + + ); +} diff --git a/src/components/dashboard/sidebar.tsx b/src/components/dashboard/sidebar.tsx index 9b46382..6992dd0 100644 --- a/src/components/dashboard/sidebar.tsx +++ b/src/components/dashboard/sidebar.tsx @@ -83,11 +83,22 @@ export function Sidebar() { } const handleSuppliesClick = () => { - // Для фулфилмент кабинетов используем новый роут - if (user?.organization?.type === 'FULFILLMENT') { - router.push('/fulfillment-supplies') - } else { - router.push('/supplies') + // Для каждого типа кабинета свой роут + switch (user?.organization?.type) { + case 'FULFILLMENT': + router.push('/fulfillment-supplies') + break + case 'SELLER': + router.push('/supplies') + break + case 'WHOLESALE': + router.push('/supplies') + break + case 'LOGIST': + router.push('/logistics') + break + default: + router.push('/supplies') } } @@ -103,7 +114,7 @@ export function Sidebar() { const isServicesActive = pathname.startsWith('/services') const isWarehouseActive = pathname.startsWith('/warehouse') const isEmployeesActive = pathname.startsWith('/employees') - const isSuppliesActive = pathname.startsWith('/supplies') || pathname.startsWith('/fulfillment-supplies') + const isSuppliesActive = pathname.startsWith('/supplies') || pathname.startsWith('/fulfillment-supplies') || pathname.startsWith('/logistics') const isPartnersActive = pathname.startsWith('/partners') return ( @@ -270,8 +281,8 @@ export function Sidebar() { )} - {/* Поставки - для селлеров и фулфилмент */} - {(user?.organization?.type === 'SELLER' || user?.organization?.type === 'FULFILLMENT') && ( + {/* Мои поставки - для селлеров */} + {user?.organization?.type === 'SELLER' && ( + )} + + {/* Входящие поставки - для фулфилмент */} + {user?.organization?.type === 'FULFILLMENT' && ( + + )} + + {/* Отгрузки - для оптовиков */} + {user?.organization?.type === 'WHOLESALE' && ( + + )} + + {/* Перевозки - для логистов */} + {user?.organization?.type === 'LOGIST' && ( + )} diff --git a/src/components/logistics/logistics-dashboard.tsx b/src/components/logistics/logistics-dashboard.tsx new file mode 100644 index 0000000..fa1a76b --- /dev/null +++ b/src/components/logistics/logistics-dashboard.tsx @@ -0,0 +1,285 @@ +"use client"; + +import { useState } from "react"; +import { Card } from "@/components/ui/card"; +import { Button } from "@/components/ui/button"; +import { Badge } from "@/components/ui/badge"; +import { Sidebar } from "@/components/dashboard/sidebar"; +import { useSidebar } from "@/hooks/useSidebar"; +import { + Truck, + Plus, + MapPin, + Clock, + Package, + TrendingUp, + AlertTriangle, + Navigation, +} from "lucide-react"; + +// Мок данные для перевозок +const mockLogistics = [ + { + id: "1", + routeNumber: "LOG-001", + from: "Садовод", + fromAddress: "Москва, 14-й км МКАД", + to: "SFERAV Logistics", + toAddress: "Москва, ул. Складская, 15", + status: "in_transit", + distance: "45 км", + estimatedTime: "1 ч 30 мин", + cargo: "Смартфоны (50 шт.)", + price: 15000, + createdDate: "2024-01-10", + }, + { + id: "2", + routeNumber: "LOG-002", + from: "SFERAV Logistics", + fromAddress: "Москва, ул. Складская, 15", + to: "Коледино WB", + toAddress: "МО, г. Подольск, Коледино", + status: "delivered", + distance: "62 км", + estimatedTime: "2 ч 15 мин", + cargo: "Одежда (120 шт.)", + price: 22000, + createdDate: "2024-01-09", + }, + { + id: "3", + routeNumber: "LOG-003", + from: "Тверь Ozon", + fromAddress: "г. Тверь, ул. Складская, 88", + to: "SFERAV Logistics", + toAddress: "Москва, ул. Складская, 15", + status: "planned", + distance: "178 км", + estimatedTime: "3 ч 45 мин", + cargo: "Электроника (75 шт.)", + price: 35000, + createdDate: "2024-01-11", + }, +]; + +export function LogisticsDashboard() { + const { getSidebarMargin } = useSidebar(); + + const formatCurrency = (amount: number) => { + return new Intl.NumberFormat("ru-RU", { + style: "currency", + currency: "RUB", + minimumFractionDigits: 0, + }).format(amount); + }; + + const formatDate = (dateString: string) => { + return new Date(dateString).toLocaleDateString("ru-RU", { + day: "2-digit", + month: "2-digit", + year: "numeric", + }); + }; + + const getStatusBadge = (status: string) => { + const statusConfig = { + planned: { + color: "text-blue-300 border-blue-400/30", + label: "Запланировано", + }, + in_transit: { + color: "text-yellow-300 border-yellow-400/30", + label: "В пути", + }, + delivered: { + color: "text-green-300 border-green-400/30", + label: "Доставлено", + }, + cancelled: { color: "text-red-300 border-red-400/30", label: "Отменено" }, + }; + + const config = + statusConfig[status as keyof typeof statusConfig] || statusConfig.planned; + + return ( + + {config.label} + + ); + }; + + const getTotalRevenue = () => { + return mockLogistics.reduce((sum, route) => sum + route.price, 0); + }; + + const getInTransitCount = () => { + return mockLogistics.filter((route) => route.status === "in_transit") + .length; + }; + + const getDeliveredCount = () => { + return mockLogistics.filter((route) => route.status === "delivered").length; + }; + + return ( +
+ +
+
+ {/* Заголовок */} +
+
+

Перевозки

+

+ Управление логистическими маршрутами +

+
+ +
+ + {/* Статистика */} +
+ +
+
+ +
+
+

Всего маршрутов

+

+ {mockLogistics.length} +

+
+
+
+ + +
+
+ +
+
+

В пути

+

+ {getInTransitCount()} +

+
+
+
+ + +
+
+ +
+
+

Доставлено

+

+ {getDeliveredCount()} +

+
+
+
+ + +
+
+ +
+
+

Выручка

+

+ {formatCurrency(getTotalRevenue())} +

+
+
+
+
+ + {/* Список маршрутов */} + +
+

+ Активные маршруты +

+
+ {mockLogistics.map((route) => ( + +
+
+
+

+ {route.routeNumber} +

+ {getStatusBadge(route.status)} +
+ +
+
+
+ +
+

+ {route.from} +

+

+ {route.fromAddress} +

+
+
+
+ +
+

+ {route.to} +

+

+ {route.toAddress} +

+
+
+
+ +
+
+ + {route.cargo} +
+
+ + + {route.distance} • {route.estimatedTime} + +
+
+
+ +
+ + Создано: {formatDate(route.createdDate)} + + + {formatCurrency(route.price)} + +
+
+
+
+ ))} +
+
+
+
+
+
+ ); +}