ui(product-card): «Закупка» и «Цены продажи» в две колонки на десктопе
Some checks are pending
CI / POS (WPF, Windows) (push) Waiting to run
CI / Backend (.NET 8) (push) Successful in 46s
CI / Web (React + Vite) (push) Successful in 34s
Docker Web / Build + push Web (push) Successful in 29s
Docker Web / Deploy Web on stage (push) Successful in 12s

Внутри секции «Цены» теперь двухколоночная сетка (lg:grid-cols-2):
закупка слева, цены продажи справа, с вертикальным разделителем.
На узких экранах (<lg) колонки складываются вертикально, как раньше.

В правой колонке цены продажи переведены на стандартный <Field>
с label сверху, чтобы выравниваться с полями закупки.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
nns 2026-04-26 01:35:29 +05:00
parent 4edf7db8cc
commit 56f36c30b4

View file

@ -423,8 +423,10 @@ export function ProductEditPage() {
</div> </div>
} }
> >
<div className="grid grid-cols-1 lg:grid-cols-2 gap-x-6 gap-y-5">
<div>
<h3 className="text-xs font-semibold uppercase tracking-wide text-slate-500 mb-3">Закупка</h3> <h3 className="text-xs font-semibold uppercase tracking-wide text-slate-500 mb-3">Закупка</h3>
<Grid cols={4}> <div className="space-y-3">
{org.data?.showReferencePriceOnProduct && ( {org.data?.showReferencePriceOnProduct && (
<Field label="Эталонная цена"> <Field label="Эталонная цена">
<MoneyInput <MoneyInput
@ -454,9 +456,10 @@ export function ProductEditPage() {
</Select> </Select>
</Field> </Field>
)} )}
</Grid> </div>
</div>
<div className="mt-5 pt-5 border-t border-slate-100 dark:border-slate-800"> <div className="lg:border-l lg:border-slate-100 lg:dark:border-slate-800 lg:pl-6">
<h3 className="text-xs font-semibold uppercase tracking-wide text-slate-500 mb-3">Цены продажи</h3> <h3 className="text-xs font-semibold uppercase tracking-wide text-slate-500 mb-3">Цены продажи</h3>
{/* Список цен рендерится по справочнику PriceType: одно поле на каждый {/* Список цен рендерится по справочнику PriceType: одно поле на каждый
* тип, без выпадашки выбора. Значение хранится в form.prices, * тип, без выпадашки выбора. Значение хранится в form.prices,
@ -469,11 +472,7 @@ export function ProductEditPage() {
const row = idx >= 0 ? form.prices[idx] : null const row = idx >= 0 ? form.prices[idx] : null
const required = pt.isRequired const required = pt.isRequired
return ( return (
<div key={pt.id} className="grid grid-cols-1 sm:grid-cols-3 gap-2 items-start"> <Field key={pt.id} label={`${pt.name}${required ? ' *' : ''}`}>
<label className="text-sm text-slate-700 dark:text-slate-200 sm:pt-2">
{pt.name}{required && <span className="text-red-500"> *</span>}
</label>
<div className="sm:col-span-2">
<MoneyInput <MoneyInput
value={row?.amount ?? null} value={row?.amount ?? null}
onChange={(n) => { onChange={(n) => {
@ -491,20 +490,20 @@ export function ProductEditPage() {
currencyCode={currencies.data?.find((c) => c.id === row?.currencyId)?.code ?? org.data?.defaultCurrencyCode ?? undefined} currencyCode={currencies.data?.find((c) => c.id === row?.currencyId)?.code ?? org.data?.defaultCurrencyCode ?? undefined}
currencySymbol={currencies.data?.find((c) => c.id === row?.currencyId)?.symbol ?? org.data?.defaultCurrencySymbol ?? undefined} currencySymbol={currencies.data?.find((c) => c.id === row?.currencyId)?.symbol ?? org.data?.defaultCurrencySymbol ?? undefined}
/> />
</div> </Field>
</div>
) )
})} })}
{priceTypes.data?.length === 0 && ( {priceTypes.data?.length === 0 && (
<div className="text-sm text-slate-400 py-2">Нет ни одного типа цен. Создай в «Настройки Типы цен».</div> <div className="text-sm text-slate-400 py-2">Нет ни одного типа цен. Создай в «Настройки Типы цен».</div>
)} )}
</div>
</div>
</div>
{missingRequiredPrices.length > 0 && ( {missingRequiredPrices.length > 0 && (
<div className="text-sm text-red-600 mt-2"> <div className="text-sm text-red-600 mt-3">
Заполни обязательные цены: {missingRequiredPrices.map((pt) => `«${pt.name}»`).join(', ')} (значение должно быть больше 0). Заполни обязательные цены: {missingRequiredPrices.map((pt) => `«${pt.name}»`).join(', ')} (значение должно быть больше 0).
</div> </div>
)} )}
</div>
</div>
</Section> </Section>
{org.data?.showMinMaxStock && ( {org.data?.showMinMaxStock && (