diff --git a/apps/internal-ui/src/App.tsx b/apps/internal-ui/src/App.tsx index 8d501ea..2bcef08 100644 --- a/apps/internal-ui/src/App.tsx +++ b/apps/internal-ui/src/App.tsx @@ -26,8 +26,8 @@ export function App() { const [selectedAgentId, setSelectedAgentId] = useState(initialRoute.agentId); const [selectedReleaseId, setSelectedReleaseId] = useState(initialRoute.releaseId); const [selectedConversationId, setSelectedConversationId] = useState(null); - const [selectedClientId, setSelectedClientId] = useState(null); - const [selectedOrderId, setSelectedOrderId] = useState(null); + const [selectedClientId, setSelectedClientId] = useState(initialRoute.clientId); + const [selectedOrderId, setSelectedOrderId] = useState(initialRoute.orderId); const [data, setData] = useState({ employees: [], departments: [], products: [], agents: [], releases: [] }); const [dataError, setDataError] = useState(false); @@ -103,6 +103,8 @@ export function App() { setSelectedProductCode(nextRoute.productCode); setSelectedAgentId(nextRoute.agentId); setSelectedReleaseId(nextRoute.releaseId); + setSelectedClientId(nextRoute.clientId); + setSelectedOrderId(nextRoute.orderId); }; window.addEventListener("popstate", onPopState); return () => window.removeEventListener("popstate", onPopState); diff --git a/apps/internal-ui/src/router.test.ts b/apps/internal-ui/src/router.test.ts index aa7e0d1..1fef945 100644 --- a/apps/internal-ui/src/router.test.ts +++ b/apps/internal-ui/src/router.test.ts @@ -4,7 +4,7 @@ import { pathFromRoute, routeFromPath } from "./router"; describe("product routes", () => { it("parses a product detail URL", () => { - expect(routeFromPath("/products/42")).toEqual({ route: "productDetail", employeeId: null, productId: 42, productCode: null, agentId: null, releaseId: null }); + expect(routeFromPath("/products/42")).toEqual({ route: "productDetail", employeeId: null, productId: 42, productCode: null, agentId: null, releaseId: null, clientId: null, orderId: null }); }); it("creates a product detail URL", () => { @@ -12,9 +12,24 @@ describe("product routes", () => { }); }); +describe("sales detail routes", () => { + it("parses a client detail URL", () => { + expect(routeFromPath("/departments/sales/clients/15")).toEqual({ route: "salesClientDetail", employeeId: null, productId: null, productCode: null, agentId: null, releaseId: null, clientId: 15, orderId: null }); + }); + + it("parses an order detail URL", () => { + expect(routeFromPath("/departments/sales/orders/8")).toEqual({ route: "salesOrderDetail", employeeId: null, productId: null, productCode: null, agentId: null, releaseId: null, clientId: null, orderId: 8 }); + }); + + it("creates client and order detail URLs", () => { + expect(pathFromRoute("salesClientDetail", 15)).toBe("/departments/sales/clients/15"); + expect(pathFromRoute("salesOrderDetail", 8)).toBe("/departments/sales/orders/8"); + }); +}); + describe("ai agent routes", () => { it("parses an AI agent detail URL", () => { - expect(routeFromPath("/ai/agents/7")).toEqual({ route: "aiAgentDetail", employeeId: null, productId: null, productCode: null, agentId: 7, releaseId: null }); + expect(routeFromPath("/ai/agents/7")).toEqual({ route: "aiAgentDetail", employeeId: null, productId: null, productCode: null, agentId: 7, releaseId: null, clientId: null, orderId: null }); }); it("creates an AI agent detail URL", () => { @@ -22,7 +37,7 @@ describe("ai agent routes", () => { }); it("parses an AI agent creation URL", () => { - expect(routeFromPath("/ai/agents/new", "?product=academy")).toEqual({ route: "aiAgentCreate", employeeId: null, productId: null, productCode: "academy", agentId: null, releaseId: null }); + expect(routeFromPath("/ai/agents/new", "?product=academy")).toEqual({ route: "aiAgentCreate", employeeId: null, productId: null, productCode: "academy", agentId: null, releaseId: null, clientId: null, orderId: null }); }); it("creates an AI agent creation URL", () => { @@ -32,7 +47,7 @@ describe("ai agent routes", () => { describe("ai release routes", () => { it("parses a release URL", () => { - expect(routeFromPath("/ai/releases/12")).toEqual({ route: "aiRelease", employeeId: null, productId: null, productCode: null, agentId: null, releaseId: 12 }); + expect(routeFromPath("/ai/releases/12")).toEqual({ route: "aiRelease", employeeId: null, productId: null, productCode: null, agentId: null, releaseId: 12, clientId: null, orderId: null }); }); it("creates a release URL", () => { diff --git a/apps/internal-ui/src/router.ts b/apps/internal-ui/src/router.ts index c6af900..71e7aa0 100644 --- a/apps/internal-ui/src/router.ts +++ b/apps/internal-ui/src/router.ts @@ -7,19 +7,27 @@ export type RouteState = { productCode: string | null; agentId: number | null; releaseId: number | null; + clientId: number | null; + orderId: number | null; }; export function routeFromPath(pathname: string, search = ""): RouteState { const path = pathname.replace(/\/+$/, "") || "/"; - const base = { employeeId: null, productId: null, productCode: null, agentId: null, releaseId: null }; + const base = { employeeId: null, productId: null, productCode: null, agentId: null, releaseId: null, clientId: null, orderId: null }; if (path === "/" || path === "/command") return { route: "command", ...base }; if (path === "/departments") return { route: "departments", ...base }; if (path === "/departments/sales") return { route: "salesOverview", ...base }; if (path === "/departments/sales/clients") return { route: "salesClients", ...base }; - if (path === "/departments/sales/clients/CUS-4702") return { route: "salesClientDetail", ...base }; + if (path.startsWith("/departments/sales/clients/")) { + const id = Number(path.split("/")[4]); + return Number.isInteger(id) && id > 0 ? { ...base, route: "salesClientDetail", clientId: id } : { route: "salesClients", ...base }; + } if (path === "/departments/sales/dialogs") return { route: "salesDialogs", ...base }; if (path === "/departments/sales/orders") return { route: "salesOrders", ...base }; - if (path === "/departments/sales/orders/ORD-10519") return { route: "salesOrderDetail", ...base }; + if (path.startsWith("/departments/sales/orders/")) { + const id = Number(path.split("/")[4]); + return Number.isInteger(id) && id > 0 ? { ...base, route: "salesOrderDetail", orderId: id } : { route: "salesOrders", ...base }; + } if (path === "/employees") return { route: "employees", ...base }; if (path.startsWith("/employees/")) { const id = Number(path.split("/")[2]); @@ -55,10 +63,10 @@ export function pathFromRoute(route: RouteKey, entityId: number | null = null, p if (route === "departments") return "/departments"; if (route === "salesOverview") return "/departments/sales"; if (route === "salesClients") return "/departments/sales/clients"; - if (route === "salesClientDetail") return "/departments/sales/clients/CUS-4702"; + if (route === "salesClientDetail") return entityId ? `/departments/sales/clients/${entityId}` : "/departments/sales/clients"; if (route === "salesDialogs") return "/departments/sales/dialogs"; if (route === "salesOrders") return "/departments/sales/orders"; - if (route === "salesOrderDetail") return "/departments/sales/orders/ORD-10519"; + if (route === "salesOrderDetail") return entityId ? `/departments/sales/orders/${entityId}` : "/departments/sales/orders"; if (route === "employees") return "/employees"; if (route === "employeeDetail") return entityId ? `/employees/${entityId}` : "/employees"; if (route === "products") return "/products"; diff --git a/apps/internal-ui/src/routes.ts b/apps/internal-ui/src/routes.ts index 77d6f4a..d078d8a 100644 --- a/apps/internal-ui/src/routes.ts +++ b/apps/internal-ui/src/routes.ts @@ -8,10 +8,10 @@ export const routes: Record = { productDetail: "Продукты", products: "Продукты", profile: "Профиль", - salesClientDetail: "Елена Кузнецова", + salesClientDetail: "Клиент", salesClients: "Клиенты", salesDialogs: "Диалоги", - salesOrderDetail: "ORD-10519", + salesOrderDetail: "Заказ", salesOrders: "Продажи", salesOverview: "Обзор", aiAgents: "AI-агенты",