diff --git a/src/food-market.web/src/components/Breadcrumbs.tsx b/src/food-market.web/src/components/Breadcrumbs.tsx new file mode 100644 index 0000000..a365809 --- /dev/null +++ b/src/food-market.web/src/components/Breadcrumbs.tsx @@ -0,0 +1,43 @@ +import { Fragment, type ReactNode } from 'react' +import { Link } from 'react-router-dom' +import { ChevronRight } from 'lucide-react' + +/** + * Хлебные крошки для edit-страниц: «Каталог / Товары / Молоко 3.2%». + * + * Каждый item с `to` — кликабельная ссылка (sm grey). Последний item — + * текущий, не кликабельный, semibold темнее. Разделитель — ChevronRight. + * + * Используется через PageHeader/инлайн в шапке формы. + */ +export interface BreadcrumbItem { + label: ReactNode + to?: string +} + +interface Props { + items: BreadcrumbItem[] + className?: string +} + +export function Breadcrumbs({ items, className }: Props) { + if (items.length === 0) return null + return ( + + ) +} diff --git a/src/food-market.web/src/pages/DemandEditPage.tsx b/src/food-market.web/src/pages/DemandEditPage.tsx index 5aac9ae..d282fb8 100644 --- a/src/food-market.web/src/pages/DemandEditPage.tsx +++ b/src/food-market.web/src/pages/DemandEditPage.tsx @@ -9,6 +9,7 @@ import { DateField } from '@/components/DateField' import { ProductPicker } from '@/components/ProductPicker' import { ConfirmDialog } from '@/components/ConfirmDialog' import { FormSkeleton } from '@/components/Skeleton' +import { Breadcrumbs } from '@/components/Breadcrumbs' import { useConfirm } from '@/lib/useConfirm' import { useStores, useCurrencies } from '@/lib/useLookups' import { useOrgSettings } from '@/lib/useOrgSettings' @@ -221,14 +222,19 @@ export function DemandEditPage() {
+

{isNew ? 'Новая отгрузка' : existing.data?.number ?? 'Отгрузка'}

-

- {isPosted - ? Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} - : 'Черновик — товар не списан, пока не проведёшь'} -

+ {isPosted && ( +

+ Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} +

+ )}
diff --git a/src/food-market.web/src/pages/EnterEditPage.tsx b/src/food-market.web/src/pages/EnterEditPage.tsx index 97c79ac..be866fc 100644 --- a/src/food-market.web/src/pages/EnterEditPage.tsx +++ b/src/food-market.web/src/pages/EnterEditPage.tsx @@ -9,6 +9,7 @@ import { DateField } from '@/components/DateField' import { ProductPicker } from '@/components/ProductPicker' import { ConfirmDialog } from '@/components/ConfirmDialog' import { FormSkeleton } from '@/components/Skeleton' +import { Breadcrumbs } from '@/components/Breadcrumbs' import { useConfirm } from '@/lib/useConfirm' import { useStores, useCurrencies } from '@/lib/useLookups' import { useOrgSettings } from '@/lib/useOrgSettings' @@ -201,14 +202,19 @@ export function EnterEditPage() {
+

{isNew ? 'Новое оприходование' : existing.data?.number ?? 'Оприходование'}

-

- {isPosted - ? Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} - : 'Черновик — товар не попадает на склад, пока не проведёшь'} -

+ {isPosted && ( +

+ Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} +

+ )}
diff --git a/src/food-market.web/src/pages/InventoryEditPage.tsx b/src/food-market.web/src/pages/InventoryEditPage.tsx index a92cfd3..3ac4a19 100644 --- a/src/food-market.web/src/pages/InventoryEditPage.tsx +++ b/src/food-market.web/src/pages/InventoryEditPage.tsx @@ -8,6 +8,7 @@ import { Field, TextArea, Select, NumberInput, Checkbox } from '@/components/Fie import { DateField } from '@/components/DateField' import { ConfirmDialog } from '@/components/ConfirmDialog' import { FormSkeleton } from '@/components/Skeleton' +import { Breadcrumbs } from '@/components/Breadcrumbs' import { useConfirm } from '@/lib/useConfirm' import { useStores } from '@/lib/useLookups' import { InventoryStatus, type InventoryDto } from '@/lib/types' @@ -217,14 +218,19 @@ export function InventoryEditPage() {
+

{isNew ? 'Новая инвентаризация' : existing.data?.number ?? 'Инвентаризация'}

-

- {isPosted - ? Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} - : 'Черновик — расхождения не отражаются на остатках, пока не проведёшь'} -

+ {isPosted && ( +

+ Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} +

+ )}
diff --git a/src/food-market.web/src/pages/LossEditPage.tsx b/src/food-market.web/src/pages/LossEditPage.tsx index c99af54..55cdb9b 100644 --- a/src/food-market.web/src/pages/LossEditPage.tsx +++ b/src/food-market.web/src/pages/LossEditPage.tsx @@ -9,6 +9,7 @@ import { DateField } from '@/components/DateField' import { ProductPicker } from '@/components/ProductPicker' import { ConfirmDialog } from '@/components/ConfirmDialog' import { FormSkeleton } from '@/components/Skeleton' +import { Breadcrumbs } from '@/components/Breadcrumbs' import { useConfirm } from '@/lib/useConfirm' import { useStores, useCurrencies } from '@/lib/useLookups' import { useOrgSettings } from '@/lib/useOrgSettings' @@ -204,14 +205,19 @@ export function LossEditPage() {
+

{isNew ? 'Новое списание' : existing.data?.number ?? 'Списание'}

-

- {isPosted - ? Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} - : 'Черновик — товар не списан, пока не проведёшь'} -

+ {isPosted && ( +

+ Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} +

+ )}
diff --git a/src/food-market.web/src/pages/ProductEditPage.tsx b/src/food-market.web/src/pages/ProductEditPage.tsx index 774d6bf..11fbc68 100644 --- a/src/food-market.web/src/pages/ProductEditPage.tsx +++ b/src/food-market.web/src/pages/ProductEditPage.tsx @@ -13,6 +13,7 @@ import { BarcodeType, Packaging, type Product } from '@/lib/types' import { ProductImageGallery } from '@/components/ProductImageGallery' import { ConfirmDialog } from '@/components/ConfirmDialog' import { FormSkeleton } from '@/components/Skeleton' +import { Breadcrumbs } from '@/components/Breadcrumbs' import { useConfirm } from '@/lib/useConfirm' import { generateEan13InternalPrefix2, generateBarcode, generateArticle } from '@/lib/barcode' @@ -238,12 +239,14 @@ export function ProductEditPage() {
+

{isNew ? 'Новый товар' : form.name || 'Товар'}

-

- {isNew ? 'Создание новой позиции каталога' : 'Редактирование'} -

diff --git a/src/food-market.web/src/pages/RetailSaleEditPage.tsx b/src/food-market.web/src/pages/RetailSaleEditPage.tsx index d9ed513..7a0d7cb 100644 --- a/src/food-market.web/src/pages/RetailSaleEditPage.tsx +++ b/src/food-market.web/src/pages/RetailSaleEditPage.tsx @@ -8,6 +8,7 @@ import { Field, TextInput, TextArea, Select, AsyncSelect, MoneyInput, NumberInpu import { ProductPicker } from '@/components/ProductPicker' import { ConfirmDialog } from '@/components/ConfirmDialog' import { FormSkeleton } from '@/components/Skeleton' +import { Breadcrumbs } from '@/components/Breadcrumbs' import { useConfirm } from '@/lib/useConfirm' import { useStores, useCurrencies } from '@/lib/useLookups' import { useOrgSettings } from '@/lib/useOrgSettings' @@ -220,14 +221,19 @@ export function RetailSaleEditPage() {
+

{isNew ? 'Новый чек' : existing.data?.number ?? 'Чек'}

-

- {isPosted - ? Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} - : 'Черновик — товар не списывается со склада до проведения'} -

+ {isPosted && ( +

+ Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} +

+ )}
diff --git a/src/food-market.web/src/pages/SupplierReturnEditPage.tsx b/src/food-market.web/src/pages/SupplierReturnEditPage.tsx index 4172750..ddb051c 100644 --- a/src/food-market.web/src/pages/SupplierReturnEditPage.tsx +++ b/src/food-market.web/src/pages/SupplierReturnEditPage.tsx @@ -9,6 +9,7 @@ import { DateField } from '@/components/DateField' import { ProductPicker } from '@/components/ProductPicker' import { ConfirmDialog } from '@/components/ConfirmDialog' import { FormSkeleton } from '@/components/Skeleton' +import { Breadcrumbs } from '@/components/Breadcrumbs' import { useConfirm } from '@/lib/useConfirm' import { useStores, useCurrencies } from '@/lib/useLookups' import { useOrgSettings } from '@/lib/useOrgSettings' @@ -207,14 +208,19 @@ export function SupplierReturnEditPage() {
+

{isNew ? 'Новый возврат поставщику' : existing.data?.number ?? 'Возврат поставщику'}

-

- {isPosted - ? Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} - : 'Черновик — товар не списан, пока не проведёшь'} -

+ {isPosted && ( +

+ Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} +

+ )}
diff --git a/src/food-market.web/src/pages/SupplyEditPage.tsx b/src/food-market.web/src/pages/SupplyEditPage.tsx index 653f425..1dbfbac 100644 --- a/src/food-market.web/src/pages/SupplyEditPage.tsx +++ b/src/food-market.web/src/pages/SupplyEditPage.tsx @@ -10,6 +10,7 @@ import { ProductPicker } from '@/components/ProductPicker' import { SupplyLineQuickAdd, type AddedProduct } from '@/components/SupplyLineQuickAdd' import { ConfirmDialog } from '@/components/ConfirmDialog' import { FormSkeleton } from '@/components/Skeleton' +import { Breadcrumbs } from '@/components/Breadcrumbs' import { useConfirm } from '@/lib/useConfirm' import { useStores, useCurrencies, usePriceTypes } from '@/lib/useLookups' import { useOrgSettings } from '@/lib/useOrgSettings' @@ -281,14 +282,19 @@ export function SupplyEditPage() {
+

{isNew ? 'Новая приёмка' : existing.data?.number ?? 'Приёмка'}

-

- {isPosted - ? Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} - : 'Черновик — товар не попадает на склад, пока не проведёшь'} -

+ {isPosted && ( +

+ Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} +

+ )}
diff --git a/src/food-market.web/src/pages/TransferEditPage.tsx b/src/food-market.web/src/pages/TransferEditPage.tsx index e572189..09ca7c2 100644 --- a/src/food-market.web/src/pages/TransferEditPage.tsx +++ b/src/food-market.web/src/pages/TransferEditPage.tsx @@ -9,6 +9,7 @@ import { DateField } from '@/components/DateField' import { ProductPicker } from '@/components/ProductPicker' import { ConfirmDialog } from '@/components/ConfirmDialog' import { FormSkeleton } from '@/components/Skeleton' +import { Breadcrumbs } from '@/components/Breadcrumbs' import { useConfirm } from '@/lib/useConfirm' import { useStores } from '@/lib/useLookups' import { useOrgSettings } from '@/lib/useOrgSettings' @@ -189,14 +190,19 @@ export function TransferEditPage() {
+

{isNew ? 'Новое перемещение' : existing.data?.number ?? 'Перемещение'}

-

- {isPosted - ? Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} - : 'Черновик — товар не перемещён, пока не проведёшь'} -

+ {isPosted && ( +

+ Проведён {existing.data?.postedAt ? new Date(existing.data.postedAt).toLocaleString('ru') : ''} +

+ )}