fix: order numbers clickable+copy, expandable sub-accounts, preserve delivery address on pickup switch, opaque calendar, tab-aware date label

This commit is contained in:
root 2026-06-12 13:19:57 +00:00
parent 005d4467bc
commit fb5728ba43
2 changed files with 50 additions and 9 deletions

View File

@ -76,6 +76,34 @@ const DELIVERY_TIME_ALIASES = {
"После обеда": "Вторая половина дня",
};
const CollapsibleChips = ({ label, items }) => {
const [open, setOpen] = React.useState(false);
if (!Array.isArray(items) || items.length === 0) return null;
return (
<span className="inline">
<button
type="button"
className="ml-1 cursor-pointer rounded-full bg-[var(--color-surface)] px-2 py-0.5 text-xs font-medium text-[var(--color-text-muted)] transition hover:bg-[var(--color-accent-soft)] hover:text-[var(--color-accent)]"
onClick={() => setOpen(!open)}
>
{label} {open ? "▲" : "▼"}
</button>
{open && (
<span className="ml-1 inline-flex flex-wrap gap-1">
{items.map((item, idx) => (
<span
key={idx}
className="cursor-pointer rounded-full bg-[var(--color-surface)] px-2 py-0.5 text-xs text-[var(--color-text-muted)] transition hover:bg-[var(--color-accent-soft)] hover:text-[var(--color-accent)]"
title="Нажмите, чтобы скопировать"
onClick={() => { navigator.clipboard?.writeText(item); }}
>{item}</span>
))}
</span>
)}
</span>
);
};
const renderList = (values) => {
if (!Array.isArray(values) || !values.length) {
return <p className="text-sm text-[var(--color-text-muted)]">Нет данных</p>;
@ -574,7 +602,7 @@ export const OrderDetailPanel = ({
const [deliveryType, setDeliveryType] = React.useState(order?.deliveryType || "delivery");
const [pickupDate, setPickupDate] = React.useState(order?.pickupDate || "");
const [pickupTimeSlot, setPickupTimeSlot] = React.useState(DELIVERY_TIME_OPTIONS[0]);
const [deliveryAddress, setDeliveryAddress] = React.useState(order?.deliveryAddress || order?.customerAddress || "");
const [deliveryAddress, setDeliveryAddress] = React.useState(order?.originalDeliveryAddress || order?.deliveryAddress || order?.customerAddress || "");
const [confirmAction, setConfirmAction] = React.useState(null);
const minSelectableDateKey = React.useMemo(() => getNextSelectableDateKey(), []);
const [currentMonth, setCurrentMonth] = React.useState(() => {
@ -613,6 +641,7 @@ export const OrderDetailPanel = ({
setDeliveryType(order?.deliveryType || "delivery");
setPickupDate(order?.pickupDate || "");
setPickupTimeSlot(normalizeDeliveryTimeChoice(order?.pickupTimeSlot || order?.deliveryTime || order?.deliveryHalfDay));
setDeliveryAddress(order?.originalDeliveryAddress || order?.deliveryAddress || order?.customerAddress || "");
setFormMessage("");
}, [order?.id, order?.deliveryDate, order?.deliveryHalfDay, order?.deliveryTime, order?.deliveryType, order?.pickupDate, order?.pickupTimeSlot]);
@ -655,7 +684,7 @@ export const OrderDetailPanel = ({
deliveryDate: deliveryType === "pickup" ? pickupDate : deliveryDate,
deliveryTime: deliveryType === "pickup" ? pickupTimeSlot : deliveryTime,
deliveryType,
...(deliveryType === "pickup" ? { pickupDate, pickupTimeSlot, deliveryAddress: "" } : {}),
...(deliveryType === "pickup" ? { pickupDate, pickupTimeSlot } : {}),
...(deliveryType === "delivery" ? { deliveryAddress: deliveryAddress.trim() } : {}),
});
@ -800,9 +829,19 @@ export const OrderDetailPanel = ({
if (mainNumbers.length > 0) {
return (
<span>
<span className="font-bold">{mainNumbers.join(", ")}</span>
{mainNumbers.map((num, idx) => (
<span
key={idx}
className="mr-1 cursor-pointer rounded-full bg-[var(--color-accent-soft)] px-2.5 py-0.5 text-sm font-bold text-[var(--color-accent)] transition hover:opacity-80 active:opacity-60"
title="Нажмите, чтобы скопировать"
onClick={() => { navigator.clipboard?.writeText(num); }}
>{num}</span>
))}
{extraNumbers.length > 0 && (
<span className="text-[var(--color-text-muted)]"> +{extraNumbers.length} сч.</span>
<CollapsibleChips
label={`+${extraNumbers.length} сч.`}
items={extraNumbers}
/>
)}
</span>
);
@ -921,7 +960,7 @@ export const OrderDetailPanel = ({
disabled={isSavingDeliveryChoice}
className="text-sm"
>
Изменить {(order.deliveryType === "pickup" || order.deliveryStatus === "pickup" || order.delivery_status === "pickup") ? "дату самовывоза" : "дату доставки"}
Изменить дату {deliveryType === "pickup" ? "самовывоза" : "доставки"}
</Button>
) : null}
</div>
@ -939,7 +978,7 @@ export const OrderDetailPanel = ({
<span aria-hidden="true" className="text-[var(--color-text-muted)]"></span>
</button>
{isCalendarOpen ? (
<div className="rounded-[20px] border border-[var(--color-border)] bg-[var(--color-surface)] p-3 shadow-soft absolute left-0 top-full z-50 mt-2 w-[300px]">
<div className="rounded-[20px] border border-[var(--color-border)] bg-[var(--color-surface-strong)] p-3 shadow-lg absolute left-0 top-full z-50 mt-2 w-[300px]">
<div className="flex items-center justify-between gap-3">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.14em] text-[var(--color-text-muted)]">
@ -1070,7 +1109,7 @@ export const OrderDetailPanel = ({
<span aria-hidden="true" className="text-[var(--color-text-muted)]"></span>
</button>
{isCalendarOpen ? (
<div className="rounded-[20px] border border-[var(--color-border)] bg-[var(--color-surface)] p-3 shadow-soft absolute left-0 top-full z-50 mt-2 w-[300px]">
<div className="rounded-[20px] border border-[var(--color-border)] bg-[var(--color-surface-strong)] p-3 shadow-lg absolute left-0 top-full z-50 mt-2 w-[300px]">
<div className="flex items-center justify-between gap-3">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.14em] text-[var(--color-text-muted)]">Календарь самовывоза</p>

View File

@ -123,7 +123,9 @@ export const mapOrderGroupRowToDeliveryGroup = (row) => {
? "pickup"
: (row.delivery_type || "delivery");
// Clear placeholder pickup address
// Preserve original address for pre-filling delivery form (don't clear for pickup)
const originalDeliveryAddress = deliveryAddress;
// For display: show nothing for pickup placeholder addresses
const resolvedDeliveryAddress = (effectiveDeliveryType === "pickup" && (deliveryAddress.toUpperCase() === "САМОВЫВОЗ" || !deliveryAddress))
? ""
: deliveryAddress;
@ -170,6 +172,7 @@ export const mapOrderGroupRowToDeliveryGroup = (row) => {
customerPhoneNormalized: parsedKey.phone || normalizePhone(customerPhone),
customerDate,
deliveryAddress: resolvedDeliveryAddress,
originalDeliveryAddress,
customerAddress,
city,
assignedDriverId: row.assigned_driver_id || null,
@ -277,7 +280,6 @@ export const updateOrderGroupDeliveryChoice = async ({
if (deliveryType === "pickup") {
updatePayload.pickup_date = pickupDate || null;
updatePayload.pickup_time_slot = pickupTimeSlot || null;
updatePayload.delivery_address = "";
} else {
updatePayload.pickup_date = null;
updatePayload.pickup_time_slot = null;