diff --git a/mechanic-pwa/frontend/src/api/warehouse.ts b/mechanic-pwa/frontend/src/api/warehouse.ts index 74a51a2..0575716 100644 --- a/mechanic-pwa/frontend/src/api/warehouse.ts +++ b/mechanic-pwa/frontend/src/api/warehouse.ts @@ -375,6 +375,8 @@ export interface TyreStockRow { by_grade: Partial>; places: string[]; suggested: boolean; + /** Подтверждённая применимость к выбранной машине. */ + fits: boolean; } export interface TyreSet { @@ -410,6 +412,8 @@ export interface TyreContext { suggested_size: string | null; open_set: TyreSet | null; stock: TyreStockRow[]; + /** Известно ли, что подходит машине. false — фильтровать нечем, показываем всё. */ + fit_known: boolean; } export interface TyreClose { diff --git a/mechanic-pwa/frontend/src/pages/warehouse/TyresPage.tsx b/mechanic-pwa/frontend/src/pages/warehouse/TyresPage.tsx index 194cbca..ee8ce58 100644 --- a/mechanic-pwa/frontend/src/pages/warehouse/TyresPage.tsx +++ b/mechanic-pwa/frontend/src/pages/warehouse/TyresPage.tsx @@ -179,14 +179,19 @@ function IssueForm({ carId, onDone }: { carId: number; onDone: () => void }) { // Подставляем подсказанный размер, как только пришёл контекст. useEffect(() => { if (!ctx || partId !== null) return; - const suggested = ctx.stock.find((s) => s.suggested && s.qty > 0); - if (suggested) setPartId(suggested.part_id); + const best = ctx.stock.find((s) => (s.fits || s.suggested) && s.qty > 0); + if (best) setPartId(best.part_id); }, [ctx, partId]); - const visibleStock = useMemo(() => { - if (!ctx) return []; - return showAll ? ctx.stock : ctx.stock.slice(0, 6); - }, [ctx, showAll]); + // По умолчанию показываем ТОЛЬКО подходящее этой машине — иначе кладовщик + // выбирает размер из девятнадцати позиций глазами. Если применимость по + // машине не заполнена, фильтровать нечем: прятать правильную резину по + // незнанию хуже, чем показать лишнюю (то же правило, что у подбора запчастей). + const fitting = useMemo( + () => (ctx ? ctx.stock.filter((s) => s.fits || s.suggested) : []), + [ctx], + ); + const visibleStock = showAll || !ctx?.fit_known ? (ctx?.stock ?? []) : fitting; if (ctxQuery.isLoading) { return
Загрузка…
; @@ -290,7 +295,20 @@ function IssueForm({ carId, onDone }: { carId: number; onDone: () => void }) { {/* Что выдаём */}
-

Что выдаём

+
+

Что выдаём

+ {ctx.fit_known && ( + + {showAll ? `все размеры (${ctx.stock.length})` : `подходит: ${fitting.length}`} + + )} +
+ {!ctx.fit_known && ( +

+ Для этой модели не отмечено, какая резина подходит, — показаны все размеры. + Отметить можно в карточке позиции на складе. +

+ )}
{visibleStock.length === 0 && (

На складе нет резины.

@@ -304,9 +322,16 @@ function IssueForm({ carId, onDone }: { carId: number; onDone: () => void }) { /> ))}
- {!showAll && ctx.stock.length > 6 && ( - )} {chosen && chosen.qty < qty && ( @@ -400,8 +425,10 @@ function StockRow({ {row.size ?? row.name} - {row.suggested && ( - штатный + {(row.fits || row.suggested) && ( + + {row.fits ? "подходит" : "штатный"} + )} 0 ? "text-muted-foreground" : "text-destructive"}`}> {row.qty} шт