feat: delivery/pickup switching in admin card + address field
- Added delivery address input field in manual agreement form (visible when delivery type) - Pickup switching clears delivery_address in DB, delivery switching preserves/updates it - useOrderGroups passes deliveryType, deliveryAddress, pickupDate, pickupTimeSlot to API - orderGroupRepository: updateOrderGroupDeliveryChoice now handles delivery_type and address - Pickup orders: address cleared, pickup_date/pickup_time_slot saved - Delivery orders: address saved, pickup fields cleared - Updated tests to match new payload structure
This commit is contained in:
parent
9aef4d49c0
commit
498faca24d
|
|
@ -637,8 +637,8 @@ export const OrderDetailPanel = ({
|
|||
deliveryDate: deliveryType === "pickup" ? pickupDate : deliveryDate,
|
||||
deliveryTime: deliveryType === "pickup" ? pickupTimeSlot : deliveryTime,
|
||||
deliveryType,
|
||||
...(deliveryType === "pickup" ? { pickupDate, pickupTimeSlot } : {}),
|
||||
...(deliveryType === "delivery" && deliveryAddress.trim() ? { deliveryAddress: deliveryAddress.trim() } : {}),
|
||||
...(deliveryType === "pickup" ? { pickupDate, pickupTimeSlot, deliveryAddress: "" } : {}),
|
||||
...(deliveryType === "delivery" ? { deliveryAddress: deliveryAddress.trim() } : {}),
|
||||
});
|
||||
|
||||
if (result?.success) {
|
||||
|
|
@ -866,6 +866,20 @@ export const OrderDetailPanel = ({
|
|||
<p>Начиная с 3-го рабочего дня — <strong>300 ₽/день</strong> платного хранения.</p>
|
||||
</div>
|
||||
)}
|
||||
{deliveryType === "delivery" && (
|
||||
<div className="space-y-2">
|
||||
<label className="text-xs font-semibold uppercase tracking-[0.14em] text-[var(--color-text-muted)]">
|
||||
Адрес доставки
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={deliveryAddress}
|
||||
onChange={(e) => setDeliveryAddress(e.target.value)}
|
||||
placeholder="Введите адрес доставки"
|
||||
className="w-full rounded-2xl border border-[var(--color-border)] bg-[var(--color-surface)] px-4 py-3 text-sm !text-[var(--color-text)] placeholder:text-[var(--color-text-muted)] focus:border-[var(--color-accent)] focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{isDeliveryAgreed && !isEditingDate ? (
|
||||
<div className="space-y-3">
|
||||
<div className="rounded-[24px] border border-[rgba(18,128,92,0.35)] bg-[var(--color-accent-soft)] p-4 !text-[var(--color-text)]">
|
||||
|
|
|
|||
|
|
@ -115,6 +115,10 @@ export const useOrderGroups = () => {
|
|||
orderGroupId,
|
||||
deliveryDate,
|
||||
deliveryTime,
|
||||
deliveryType,
|
||||
deliveryAddress,
|
||||
pickupDate,
|
||||
pickupTimeSlot,
|
||||
}) => {
|
||||
setIsSavingDeliveryChoice(true);
|
||||
|
||||
|
|
@ -125,6 +129,10 @@ export const useOrderGroups = () => {
|
|||
orderGroupId,
|
||||
deliveryDate,
|
||||
deliveryTime,
|
||||
deliveryType,
|
||||
deliveryAddress,
|
||||
pickupDate,
|
||||
pickupTimeSlot,
|
||||
});
|
||||
|
||||
if (result.error) {
|
||||
|
|
|
|||
|
|
@ -258,25 +258,36 @@ export const updateOrderGroupDeliveryChoice = async ({
|
|||
deliveryDate,
|
||||
deliveryTime,
|
||||
deliveryType,
|
||||
deliveryAddress,
|
||||
pickupDate,
|
||||
pickupTimeSlot,
|
||||
}) => {
|
||||
return safeSupabaseCall(async () => {
|
||||
const client = requireSupabase();
|
||||
const effectiveDeliveryStatus = deliveryType === "pickup" ? "pickup" : "agreed";
|
||||
const updateResult = await client
|
||||
.from("order_groups")
|
||||
.update({
|
||||
const updatePayload = {
|
||||
delivery_status: effectiveDeliveryStatus,
|
||||
delivery_date: deliveryDate,
|
||||
delivery_time: deliveryTime,
|
||||
delivery_type: deliveryType || "delivery",
|
||||
pickup_date: deliveryType === "pickup" ? pickupDate : null,
|
||||
pickup_time_slot: deliveryType === "pickup" ? pickupTimeSlot : null,
|
||||
delivery_date_source: "manual",
|
||||
notification_status: "confirmed",
|
||||
updated_at: new Date().toISOString(),
|
||||
})
|
||||
};
|
||||
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;
|
||||
if (deliveryAddress !== undefined) {
|
||||
updatePayload.delivery_address = deliveryAddress;
|
||||
}
|
||||
}
|
||||
const updateResult = await client
|
||||
.from("order_groups")
|
||||
.update(updatePayload)
|
||||
.eq("id", orderGroupId);
|
||||
|
||||
if (updateResult.error) {
|
||||
|
|
|
|||
|
|
@ -158,15 +158,16 @@ describe("updateOrderGroupDeliveryChoice", () => {
|
|||
});
|
||||
|
||||
expect(fromMock).toHaveBeenCalledWith("order_groups");
|
||||
expect(updateMock).toHaveBeenCalledWith({
|
||||
expect(updateMock).toHaveBeenCalledWith(expect.objectContaining({
|
||||
delivery_status: "agreed",
|
||||
delivery_date: "2026-05-13",
|
||||
delivery_time: "Первая половина дня",
|
||||
delivery_type: "delivery",
|
||||
notification_status: "confirmed",
|
||||
updated_at: expect.any(String),
|
||||
});
|
||||
}));
|
||||
expect(eqMock).toHaveBeenCalledWith("id", "group-id");
|
||||
expect(selectMock).toHaveBeenCalledWith("id, group_key, order_numbers, status, delivery_status, sms_sent_at, created_at, updated_at, created_from_exchange_at, source_key, customer_name, customer_phone, customer_phone_normalized, customer_date, orders_total, orders_ready, orders_not_ready, source_orders, order_list, order_list_structured, delivery_invitation_id, delivery_link, notification_status, sms_attempts, first_sms_sent_at, second_sms_sent_at, last_sms_error, next_notification_check_at, delivery_date, delivery_time, delivery_address, manual_confirmation_at, paid_storage_at, assigned_driver_id, assigned_driver:users!order_groups_assigned_driver_id_fkey(id, name)");
|
||||
expect(selectMock).toHaveBeenCalledWith(expect.stringContaining("delivery_type, pickup_date, pickup_time_slot"));
|
||||
expect(singleMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue