fix: визуальная обратная связь после сохранения отгрузки водителем
- После нажатия 'Сохранить отгрузку' показывается заметный summary-блок - Каждая позиция в отдельной карточке: зелёная рамка (отгружено) / оранжевая рамка (не отгружено) - Причина неотгрузки показана внутри карточки - Кнопка 'Изменить' позволяет вернуться к редактированию - При повторном открытии — компактная плашка 'Отгрузка ранее сохранена'
This commit is contained in:
parent
41272bdbbf
commit
55c91d8d32
|
|
@ -92,7 +92,8 @@ const parseOrderItems = (order) => {
|
||||||
export const DriverShipmentPanel = ({ order, onShipmentChange, onSaveShipment, isSavingShipment }) => {
|
export const DriverShipmentPanel = ({ order, onShipmentChange, onSaveShipment, isSavingShipment }) => {
|
||||||
const [stopWords, setStopWords] = React.useState([]);
|
const [stopWords, setStopWords] = React.useState([]);
|
||||||
const [scopeActive, setScopeActive] = React.useState(true);
|
const [scopeActive, setScopeActive] = React.useState(true);
|
||||||
const [savedShipment, setSavedShipment] = React.useState(null); // last saved snapshot
|
const [savedShipment, setSavedShipment] = React.useState([]);
|
||||||
|
const [justSaved, setJustSaved] = React.useState(false);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!supabase) return;
|
if (!supabase) return;
|
||||||
|
|
@ -302,14 +303,19 @@ export const DriverShipmentPanel = ({ order, onShipmentChange, onSaveShipment, i
|
||||||
{onSaveShipment && items.length > 0 && (
|
{onSaveShipment && items.length > 0 && (
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => onSaveShipment(items.map((item) => ({
|
onClick={() => {
|
||||||
id: item.id,
|
const data = items.map((item) => ({
|
||||||
name: item.name,
|
id: item.id,
|
||||||
quantity: item.quantity,
|
name: item.name,
|
||||||
unit: item.unit,
|
quantity: item.quantity,
|
||||||
shipped: shippedItems.has(item.id),
|
unit: item.unit,
|
||||||
comment: shippedItems.has(item.id) ? "" : (comments[item.id] || ""),
|
shipped: shippedItems.has(item.id),
|
||||||
})))}
|
comment: shippedItems.has(item.id) ? "" : (comments[item.id] || ""),
|
||||||
|
}));
|
||||||
|
setSavedShipment(data);
|
||||||
|
setJustSaved(true);
|
||||||
|
onSaveShipment(data);
|
||||||
|
}}
|
||||||
disabled={isSavingShipment || shippedCount === 0}
|
disabled={isSavingShipment || shippedCount === 0}
|
||||||
>
|
>
|
||||||
{isSavingShipment ? "Сохраняем..." : "Сохранить отгрузку"}
|
{isSavingShipment ? "Сохраняем..." : "Сохранить отгрузку"}
|
||||||
|
|
@ -322,33 +328,63 @@ export const DriverShipmentPanel = ({ order, onShipmentChange, onSaveShipment, i
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{savedShipment && savedShipment.length > 0 && (
|
{/* Saved shipment summary — show prominently after save */}
|
||||||
<div className="rounded-xl border border-[var(--color-accent)] bg-[var(--color-accent-soft)] p-4 text-sm">
|
{justSaved && savedShipment.length > 0 && (
|
||||||
<div className="flex items-center gap-2 mb-2">
|
<div className="rounded-xl border-2 border-[var(--color-accent)] bg-[var(--color-accent-soft)] p-4 text-sm">
|
||||||
<span className="text-lg">✅</span>
|
<div className="flex items-center justify-between mb-3">
|
||||||
<strong className="text-[var(--color-accent)]">
|
<div className="flex items-center gap-2">
|
||||||
Отгрузка сохранена: {savedShipment.filter((i) => i.shipped).length} из {savedShipment.length} позиций
|
<span className="text-xl">✅</span>
|
||||||
</strong>
|
<strong className="text-[var(--color-accent)]">
|
||||||
|
Отгрузка сохранена: {savedShipment.filter((i) => i.shipped).length} из {savedShipment.length}
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
<Button variant="ghost" size="sm" onClick={() => setJustSaved(false)}>
|
||||||
|
Изменить
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-1">
|
<div className="space-y-2">
|
||||||
{savedShipment.map((item) => (
|
{savedShipment.map((item) => (
|
||||||
<div key={item.id} className="flex items-start gap-2">
|
<div
|
||||||
<span className={item.shipped ? "text-[var(--color-accent)]" : "text-[var(--color-warning)]"}>
|
key={item.id}
|
||||||
{item.shipped ? "✓" : "✗"}
|
className={[
|
||||||
</span>
|
"rounded-lg px-3 py-2",
|
||||||
<span className={item.shipped ? "text-[var(--color-text-muted)] line-through" : "text-[var(--color-text)]"}>
|
item.shipped
|
||||||
{item.name}{item.quantity ? ` — ${item.quantity}${item.unit ? ` ${item.unit}` : ""}` : ""}
|
? "bg-[var(--color-surface-strong)] border border-[var(--color-accent)]"
|
||||||
</span>
|
: "bg-[var(--color-warning-soft)] border border-[var(--color-warning)]",
|
||||||
{!item.shipped && item.comment && (
|
].join(" ")}
|
||||||
<span className="text-xs text-[var(--color-warning)] ml-1">
|
>
|
||||||
({item.comment})
|
<div className="flex items-center gap-2">
|
||||||
|
<span className={item.shipped ? "text-[var(--color-accent)]" : "text-[var(--color-warning)]"}>
|
||||||
|
{item.shipped ? "✓" : "✗"}
|
||||||
</span>
|
</span>
|
||||||
|
<span className={item.shipped ? "text-[var(--color-text-muted)] line-through" : "text-[var(--color-text)] font-medium"}>
|
||||||
|
{item.name}{item.quantity ? ` — ${item.quantity}${item.unit ? ` ${item.unit}` : ""}` : ""}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{!item.shipped && item.comment && (
|
||||||
|
<div className="mt-1 ml-6 text-xs text-[var(--color-warning)]">
|
||||||
|
Причина: {item.comment}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Restore saved state on load (when not justSaved) */}
|
||||||
|
{!justSaved && savedShipment.length > 0 && (
|
||||||
|
<div className="rounded-xl border border-[var(--color-accent)] bg-[var(--color-accent-soft)] px-3 py-2 text-xs text-[var(--color-accent)]">
|
||||||
|
✅ Отгрузка ранее сохранена: {savedShipment.filter((i) => i.shipped).length}/{savedShipment.length} позиций
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="ml-2 underline text-[var(--color-text-muted)]"
|
||||||
|
onClick={() => setJustSaved(true)}
|
||||||
|
>
|
||||||
|
Показать
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</Panel>
|
</Panel>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue