173 lines
5.4 KiB
JavaScript
173 lines
5.4 KiB
JavaScript
import React from "react";
|
||
import { Navigate } from "react-router-dom";
|
||
import { DriverDeliveryPlanner } from "../components/driver/DriverDeliveryPlanner";
|
||
import { LogisticsReadinessBoard } from "../components/logistics/LogisticsReadinessBoard";
|
||
import { OrderDetailPanel } from "../components/orders/OrderDetailPanel";
|
||
import { OrdersTable } from "../components/orders/OrdersTable";
|
||
import { Button } from "../components/UI/Button";
|
||
import { Modal } from "../components/UI/Modal";
|
||
import { Panel } from "../components/UI/Panel";
|
||
import { ProductGuidePanel } from "../components/dashboard/ProductGuidePanel";
|
||
import { useAuth } from "../context/AuthContext";
|
||
import { useOrderGroups } from "../hooks/useOrderGroups";
|
||
import { AppShell } from "../layouts/AppShell";
|
||
|
||
const ROLE_SECTION = {
|
||
manager: {
|
||
key: "orders",
|
||
label: "Группы",
|
||
description: "Реестр групп доставки, поиск и просмотр карточки.",
|
||
},
|
||
logistician: {
|
||
key: "logistics",
|
||
label: "Логистика",
|
||
description: "Группы доставки по готовности к уведомлению.",
|
||
},
|
||
driver: {
|
||
key: "deliveries",
|
||
label: "Мои доставки",
|
||
description: "Группы доставки по датам и статусам.",
|
||
},
|
||
};
|
||
|
||
export const DashboardPage = () => {
|
||
const { user, signOut } = useAuth();
|
||
const userRole = user?.role;
|
||
const section = ROLE_SECTION[userRole] || ROLE_SECTION.manager;
|
||
const [activeSection, setActiveSection] = React.useState(section.key);
|
||
const [isGroupModalOpen, setIsGroupModalOpen] = React.useState(false);
|
||
|
||
const {
|
||
orderGroups,
|
||
allOrderGroups,
|
||
filteredOrderGroups,
|
||
selectedOrderGroup,
|
||
selectedOrderGroupId,
|
||
setSelectedOrderGroupId,
|
||
filters,
|
||
setFilters,
|
||
statusOptions,
|
||
isLoading,
|
||
loadError,
|
||
} = useOrderGroups();
|
||
|
||
React.useEffect(() => {
|
||
setActiveSection(section.key);
|
||
}, [section.key]);
|
||
|
||
const openGroupModal = React.useCallback((groupId) => {
|
||
setSelectedOrderGroupId(groupId);
|
||
setIsGroupModalOpen(true);
|
||
}, []);
|
||
|
||
const navItems = [
|
||
{
|
||
key: section.key,
|
||
label: section.label,
|
||
description: section.description,
|
||
badge: String(allOrderGroups.length || orderGroups.length || 0),
|
||
},
|
||
];
|
||
const guideSectionMeta = {
|
||
key: "guide",
|
||
label: "Справка",
|
||
description: "Карта продукта, роли, сценарии и частые вопросы.",
|
||
};
|
||
const activeSectionMeta = activeSection === "guide" ? guideSectionMeta : navItems[0];
|
||
const isGuideOpen = activeSection === "guide";
|
||
|
||
if (!user) {
|
||
return <Navigate to="/login" replace />;
|
||
}
|
||
|
||
const renderManagerWorkspace = () => (
|
||
<div className="space-y-6 xl:space-y-8">
|
||
<OrdersTable
|
||
orderGroups={filteredOrderGroups}
|
||
selectedOrderGroupId={selectedOrderGroupId}
|
||
onOpenOrder={openGroupModal}
|
||
filters={filters}
|
||
setFilters={setFilters}
|
||
statusOptions={statusOptions}
|
||
/>
|
||
</div>
|
||
);
|
||
|
||
const renderLogisticsWorkspace = () => (
|
||
<div className="space-y-6 xl:space-y-8">
|
||
<LogisticsReadinessBoard orderGroups={allOrderGroups} onSelectSet={openGroupModal} />
|
||
</div>
|
||
);
|
||
|
||
const renderDriverWorkspace = () => (
|
||
<div className="space-y-6 xl:space-y-8">
|
||
<DriverDeliveryPlanner
|
||
orderGroups={allOrderGroups}
|
||
onOpenOrder={openGroupModal}
|
||
/>
|
||
</div>
|
||
);
|
||
|
||
const renderActiveSection = () => {
|
||
if (activeSection === "guide") {
|
||
return <ProductGuidePanel />;
|
||
}
|
||
|
||
if (userRole === "driver") {
|
||
return renderDriverWorkspace();
|
||
}
|
||
|
||
if (userRole === "logistician") {
|
||
return renderLogisticsWorkspace();
|
||
}
|
||
|
||
return renderManagerWorkspace();
|
||
};
|
||
|
||
return (
|
||
<AppShell
|
||
user={user}
|
||
onSignOut={signOut}
|
||
onOpenGuide={() => setActiveSection((current) => (current === "guide" ? section.key : "guide"))}
|
||
isGuideOpen={isGuideOpen}
|
||
navItems={navItems}
|
||
activeSection={activeSection}
|
||
onSectionChange={setActiveSection}
|
||
sectionMeta={activeSectionMeta}
|
||
>
|
||
{isLoading ? (
|
||
<Panel className="border border-dashed border-[var(--color-border)] bg-[var(--color-surface-strong)] p-4 text-sm text-[var(--color-text-muted)]">
|
||
Загружаем данные...
|
||
</Panel>
|
||
) : null}
|
||
{loadError ? (
|
||
<Panel className="border border-dashed border-[var(--color-danger)] bg-[var(--color-surface-strong)] p-4 text-sm text-[var(--color-danger)]">
|
||
Не удалось загрузить данные. Обратитесь к администратору.
|
||
</Panel>
|
||
) : null}
|
||
|
||
{renderActiveSection()}
|
||
|
||
<Modal isOpen={isGroupModalOpen} onClose={() => setIsGroupModalOpen(false)}>
|
||
<div className="space-y-5">
|
||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||
<div>
|
||
<h3 className="text-xl font-semibold">Карточка группы доставки</h3>
|
||
<p className="text-sm text-[var(--color-text-muted)]">Все данные из таблицы `order_groups`.</p>
|
||
</div>
|
||
<Button
|
||
variant="ghost"
|
||
onClick={() => {
|
||
setIsGroupModalOpen(false);
|
||
}}
|
||
>
|
||
Закрыть
|
||
</Button>
|
||
</div>
|
||
<OrderDetailPanel order={selectedOrderGroup} />
|
||
</div>
|
||
</Modal>
|
||
</AppShell>
|
||
);
|
||
};
|