diff --git a/public/service-worker.js b/public/service-worker.js index 9252f3e..8b8308b 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -1,7 +1,7 @@ const isLocalhost = self.location.hostname === "localhost" || self.location.hostname === "127.0.0.1"; if (!isLocalhost) { - const STATIC_CACHE = "construction-delivery-static-v132"; + const STATIC_CACHE = "construction-delivery-static-v133"; const RUNTIME_CACHE = "construction-delivery-runtime-v119"; const APP_SHELL_URLS = ["/", "/client", "/index.html", "/manifest.webmanifest", "/icons/icon-192.png", "/icons/icon-512.png"]; diff --git a/src/components/admin/analytics/CommsFunnelBlock.jsx b/src/components/admin/analytics/CommsFunnelBlock.jsx index 69b2a9e..7caca68 100644 --- a/src/components/admin/analytics/CommsFunnelBlock.jsx +++ b/src/components/admin/analytics/CommsFunnelBlock.jsx @@ -26,6 +26,11 @@ const CHANNEL_LABELS = { manual: 'Менеджер', link: 'Ссылка из SMS', automation: 'Автоматически', + // Клиентские каналы из ссылки (/delivery/{hash}?src=...) — до 29.09.2026 не писались. + sms: 'SMS-ссылка', + client: 'Ссылка (прямой заход)', + push: 'Push', + messenger: 'Мессенджер', }; const STATUS_LABELS = { diff --git a/src/components/admin/analytics/CommsFunnelBlock.test.jsx b/src/components/admin/analytics/CommsFunnelBlock.test.jsx index 3812e7b..813411b 100644 --- a/src/components/admin/analytics/CommsFunnelBlock.test.jsx +++ b/src/components/admin/analytics/CommsFunnelBlock.test.jsx @@ -80,6 +80,31 @@ describe("CommsFunnelBlock", () => { expect(html).toContain("Ссылка из SMS"); }); + it("подписывает клиентские каналы ссылки, а не показывает ключи БД", () => { + const clientChannels = renderToStaticMarkup( + , + ); + expect(clientChannels).toContain("SMS-ссылка"); + expect(clientChannels).toContain("Ссылка (прямой заход)"); + expect(clientChannels).toContain("Push"); + expect(clientChannels).toContain("Мессенджер"); + // сырые ключи источника наружу не уходят + expect(clientChannels).not.toContain(">client<"); + expect(clientChannels).not.toContain(">messenger<"); + }); + it("перечисляет тех, кто не берёт трубку, и тех, кто открыл ссылку без подтверждения", () => { expect(html).toContain("Не поднимают трубку"); expect(html).toContain("9787617568"); diff --git a/src/components/admin/analytics/OrderPathFunnelBlock.jsx b/src/components/admin/analytics/OrderPathFunnelBlock.jsx index 2dbfc88..b4d1c41 100644 --- a/src/components/admin/analytics/OrderPathFunnelBlock.jsx +++ b/src/components/admin/analytics/OrderPathFunnelBlock.jsx @@ -34,6 +34,12 @@ const SOURCE_LABELS = { link: 'Ссылка из SMS', automation: 'Автоматически', none: 'В обход (без даты)', + // Клиентские каналы из ссылки (/delivery/{hash}?src=...) — до 29.09.2026 не писались, + // поэтому в старых строках стоит пустой источник («В обход (без даты)»). + sms: 'SMS-ссылка', + client: 'Ссылка (прямой заход)', + push: 'Push', + messenger: 'Мессенджер', }; const FunnelTooltip = ({ active, payload }) => { diff --git a/src/components/admin/analytics/OrderPathFunnelBlock.test.jsx b/src/components/admin/analytics/OrderPathFunnelBlock.test.jsx index 5d73e7b..f1b572f 100644 --- a/src/components/admin/analytics/OrderPathFunnelBlock.test.jsx +++ b/src/components/admin/analytics/OrderPathFunnelBlock.test.jsx @@ -65,6 +65,33 @@ describe("OrderPathFunnelBlock", () => { expect(html).toContain("Доставка"); }); + it("подписывает клиентские источники даты, а не показывает ключи БД", () => { + const withClientSources = renderToStaticMarkup( + , + ); + expect(withClientSources).toContain("SMS-ссылка"); + expect(withClientSources).toContain("Ссылка (прямой заход)"); + expect(withClientSources).toContain("Push"); + expect(withClientSources).toContain("Мессенджер"); + expect(withClientSources).not.toContain(">client<"); + expect(withClientSources).not.toContain(">messenger<"); + }); + it("на пустом периоде пишет заглушку", () => { const e = renderToStaticMarkup(); expect(e).toContain("За период заказов нет");