fix(pwa/repairs): drop duplicate mileage input under «Замена масла»

При создании/редактировании ремонта в форме был отдельный «Пробег на
момент замены» внутри блока замены масла — auto-sync от шапочного с
soft-dirty флагом по У24. На практике это всё равно заставляло механика
вводить значение дважды, если шапочный пробег вводился вручную (StarLine
недоступен): момент включения галочки случался после ручного ввода,
soft-sync не успевал отработать или механик не понимал что поле
автозаполнилось.

Упростили: единственный пробег — «Пробег (км)» в шапке формы. На submit
он же подставляется в oil_change.mileage_at_change. Поле «Следующая через»
оставили — это интервал, а не значение пробега.

Бэкенд не трогаем — схема та же (mileage_at_change всё ещё в payload).
This commit is contained in:
2026-05-25 21:29:26 +10:00
parent 8eac0b74fc
commit 205078c5ce
2 changed files with 18 additions and 54 deletions
@@ -67,8 +67,6 @@ interface PartRow {
interface OilChangeState {
enabled: boolean;
mileage_at_change: number | null;
mileage_is_dirty: boolean; // У24: мягкая подписка с шапочным
next_in_km: number;
sticker: PhotoState | null;
}
@@ -107,8 +105,6 @@ export default function CreateRepairPage() {
const [parts, setParts] = useState<PartRow[]>([]);
const [oilChange, setOilChange] = useState<OilChangeState>({
enabled: false,
mileage_at_change: null,
mileage_is_dirty: false,
next_in_km: 10000,
sticker: null,
});
@@ -130,13 +126,9 @@ export default function CreateRepairPage() {
.catch((e) => setCtxError((e as Error).message || "Не удалось загрузить машину"));
}, [carId]);
// У24: мягкая подписка пробега блока масла на шапочный.
useEffect(() => {
if (oilChange.enabled && !oilChange.mileage_is_dirty) {
setOilChange((oc) => ({ ...oc, mileage_at_change: mileage }));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [mileage, oilChange.enabled]);
// У24 упрощено: пробег ввода в форме теперь один — главный «Пробег (км)»
// в шапке. На submit подставляется и в oil_change.mileage_at_change, чтобы
// не заставлять механика вводить одно и то же дважды.
// ── Photo upload ─────────────────────────────────────────────────────────
@@ -325,7 +317,8 @@ export default function CreateRepairPage() {
oil_change: oilChange.enabled
? {
enabled: true,
mileage_at_change: oilChange.mileage_at_change,
// Один источник истины — главный пробег ремонта (см. У24).
mileage_at_change: mileage,
next_in_km: oilChange.next_in_km,
sticker_photo_uuid:
oilChange.sticker?.status === "uploaded"
@@ -625,21 +618,6 @@ export default function CreateRepairPage() {
</label>
{oilChange.enabled && (
<div className="mt-3 space-y-3">
<div>
<Label className="text-sm">Пробег на момент замены</Label>
<Input
type="number"
min={0}
value={oilChange.mileage_at_change ?? ""}
onChange={(e) =>
setOilChange((oc) => ({
...oc,
mileage_at_change: e.target.value === "" ? null : Number(e.target.value),
mileage_is_dirty: true,
}))
}
/>
</div>
<div>
<Label className="text-sm">Следующая замена через (км)</Label>
<Input
@@ -36,7 +36,6 @@ interface PartRow {
interface OilState {
enabled: boolean;
mileage_at_change: number | null;
next_in_km: number | null;
}
@@ -60,7 +59,7 @@ export default function EditRepairPage() {
const [mileage, setMileage] = useState<number | null>(null);
const [works, setWorks] = useState<WorkRow[]>([]);
const [parts, setParts] = useState<PartRow[]>([]);
const [oil, setOil] = useState<OilState>({ enabled: false, mileage_at_change: null, next_in_km: null });
const [oil, setOil] = useState<OilState>({ enabled: false, next_in_km: null });
const [worksPicker, setWorksPicker] = useState<{ open: boolean; q: string; results: MechWork[] }>(
{ open: false, q: "", results: [] }
@@ -89,7 +88,6 @@ export default function EditRepairPage() {
if (d.oil_change) {
setOil({
enabled: true,
mileage_at_change: d.oil_change.mileage_at_change,
next_in_km: d.oil_change.next_in_km,
});
}
@@ -174,7 +172,8 @@ export default function EditRepairPage() {
qty: p.qty,
})),
oil_change: oil.enabled
? { enabled: true, mileage_at_change: oil.mileage_at_change, next_in_km: oil.next_in_km }
// Один источник истины — главный пробег ремонта.
? { enabled: true, mileage_at_change: mileage, next_in_km: oil.next_in_km }
: { enabled: false, mileage_at_change: null, next_in_km: null },
});
navigate(`/repairs/${detail.id}`, { replace: true });
@@ -343,19 +342,7 @@ export default function EditRepairPage() {
Замена масла
</label>
{oil.enabled && (
<div className="mt-3 grid grid-cols-2 gap-2">
<div>
<Label className="text-xs">Пробег</Label>
<Input
type="number"
inputMode="numeric"
value={oil.mileage_at_change ?? ""}
onChange={(e) => setOil((o) => ({
...o, mileage_at_change: e.target.value === "" ? null : Number(e.target.value),
}))}
/>
</div>
<div>
<div className="mt-3">
<Label className="text-xs">Через, км</Label>
<Input
type="number"
@@ -366,7 +353,6 @@ export default function EditRepairPage() {
}))}
/>
</div>
</div>
)}
</section>