+ WebP srcset. Браузер сам выбирает лучший вариант по
+ // type-фильтру (WebP) + srcset (DPR). Старые браузеры без WebP-support
+ // получат оригинал из
.
+ if (size === 'thumb') {
+ return (
+
+
+
+
+ )
+ }
+ return (
+
+
+
+
+ )
+}
diff --git a/src/food-market.web/src/pages/DashboardPage.tsx b/src/food-market.web/src/pages/DashboardPage.tsx
index 1d3bb52..c0cb6ea 100644
--- a/src/food-market.web/src/pages/DashboardPage.tsx
+++ b/src/food-market.web/src/pages/DashboardPage.tsx
@@ -3,13 +3,16 @@ import { lazy, Suspense, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Package, Users, Warehouse, Store, TrendingUp, TrendingDown, Receipt, Banknote, Calendar, Wifi, WifiOff, CalendarDays } from 'lucide-react'
import { PageHeader } from '@/components/PageHeader'
-import { SalesChart } from '@/components/SalesChart'
import { Skeleton } from '@/components/Skeleton'
import { api } from '@/lib/api'
import { toast } from '@/lib/toast'
import { useNotificationsHub } from '@/lib/useNotificationsHub'
import type { PagedResult, SalesStatsResponse } from '@/lib/types'
+// Sprint 14: SalesChart тянет recharts (~150КБ raw / ~50КБ gzip). Лениво —
+// сам Dashboard рендерится сразу с KPI'ами, чарт догружается за ~50мс.
+const SalesChart = lazy(() => import('@/components/SalesChart').then(m => ({ default: m.SalesChart })))
+
// Виджеты lazy: они тянут heavy-ish DOM (списки), но критично только KPI/график
// для first-paint. Чанки уйдут отдельным запросом, skeleton — мгновенно.
const TopProductsWidget = lazy(() => import('@/components/DashboardWidgets').then(m => ({ default: m.TopProductsWidget })))
@@ -199,7 +202,9 @@ export function DashboardPage() {
{t('dashboard.noSalesHint')}
) : (
-
+ }>
+
+
)}