add warehouse_request_source and warehouse_request_source_2 fields to deliveries table with validation and normalization logic
Build and Push Docker Images / build-backend (push) Has been cancelled
Build and Push Docker Images / build-frontend (push) Has been cancelled

This commit is contained in:
Egor Pozharov
2026-05-04 17:32:03 +06:00
parent f9c54b5172
commit c39bde0b10
13 changed files with 305 additions and 165 deletions
@@ -1,8 +1,8 @@
import { useState, useEffect, useCallback } from 'react';
import { Button, Input, Select, Modal } from '../ui';
import { pickupOptions } from '../../constants/pickup';
import { deliveryRequestSourceOptions, pickupOptions } from '../../constants/pickup';
import { formatDateForInput, parseDateFromInput, getTodayFrontend } from '../../utils/date';
import type { Delivery, PickupLocation, DeliveryStatus } from '../../types';
import type { Delivery, DeliveryRequestSource, PickupLocation, DeliveryStatus } from '../../types';
interface DeliveryFormProps {
isOpen: boolean;
@@ -18,6 +18,10 @@ const PHONE_REGEX = /^\+7\s?\(?\d{3}\)?\s?\d{3}[\s-]?\d{2}[\s-]?\d{2}$/;
// City is not shown in UI but is included in the saved address (used for 2GIS search).
const CITY_LABEL = 'Кокшетау';
const requestSourceOptions = [
{ value: '', label: 'Выберите источник заявки' },
...deliveryRequestSourceOptions,
];
const buildAddressString = (
street: string,
@@ -38,6 +42,8 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
date: defaultDate || getTodayFrontend(),
pickupLocation: 'warehouse' as PickupLocation,
pickupLocation2: null as PickupLocation | null,
warehouseRequestSource: null as DeliveryRequestSource | null,
warehouseRequestSource2: null as DeliveryRequestSource | null,
productName: '',
productName2: '',
customerName: '',
@@ -62,6 +68,8 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
date: initialData.date,
pickupLocation: initialData.pickupLocation,
pickupLocation2: initialData.pickupLocation2 || null,
warehouseRequestSource: initialData.warehouseRequestSource || null,
warehouseRequestSource2: initialData.warehouseRequestSource2 || null,
productName: initialData.productName,
productName2: initialData.productName2 || '',
customerName: initialData.customerName,
@@ -91,7 +99,25 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
const isPhoneValid = !formData.phone || validatePhone(formData.phone);
const isAdditionalPhoneValid = !formData.additionalPhone || validatePhone(formData.additionalPhone);
const isFormValid = formData.productName && formData.phone && isPhoneValid && formData.customerName && formData.street && formData.house;
const isWarehouseRequestSourceValid = formData.pickupLocation !== 'warehouse' || !!formData.warehouseRequestSource;
const isWarehouseRequestSource2Valid = !showSecondPickup || formData.pickupLocation2 !== 'warehouse' || !!formData.warehouseRequestSource2;
const isFormValid = formData.productName && formData.phone && isPhoneValid && formData.customerName && formData.street && formData.house && isWarehouseRequestSourceValid && isWarehouseRequestSource2Valid;
const handlePickupLocationChange = (pickupLocation: PickupLocation) => {
setFormData({
...formData,
pickupLocation,
warehouseRequestSource: pickupLocation === 'warehouse' ? formData.warehouseRequestSource : null,
});
};
const handlePickupLocation2Change = (pickupLocation2: PickupLocation) => {
setFormData({
...formData,
pickupLocation2,
warehouseRequestSource2: pickupLocation2 === 'warehouse' ? formData.warehouseRequestSource2 : null,
});
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
@@ -107,6 +133,8 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
date: defaultDate || getTodayFrontend(),
pickupLocation: 'warehouse',
pickupLocation2: null,
warehouseRequestSource: null,
warehouseRequestSource2: null,
productName: '',
productName2: '',
customerName: '',
@@ -165,10 +193,21 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
<Select
label="Место загрузки"
value={formData.pickupLocation}
onChange={(e) => setFormData({ ...formData, pickupLocation: e.target.value as PickupLocation })}
onChange={(e) => handlePickupLocationChange(e.target.value as PickupLocation)}
options={pickupOptions}
/>
{formData.pickupLocation === 'warehouse' && (
<Select
label="От кого заявка *"
value={formData.warehouseRequestSource || ''}
onChange={(e) => setFormData({ ...formData, warehouseRequestSource: e.target.value ? e.target.value as DeliveryRequestSource : null })}
options={requestSourceOptions}
required
error={!isWarehouseRequestSourceValid ? 'Выберите, от кого исходит заявка' : undefined}
/>
)}
<Input
label="Название товара"
value={formData.productName}
@@ -287,10 +326,14 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
id="hasSecondPickup"
checked={showSecondPickup}
onChange={(e) => {
setShowSecondPickup(e.target.checked);
if (!e.target.checked) {
setFormData({ ...formData, pickupLocation2: null, productName2: '' });
}
const checked = e.target.checked;
setShowSecondPickup(checked);
setFormData({
...formData,
pickupLocation2: checked ? formData.pickupLocation2 || 'warehouse' : null,
warehouseRequestSource2: checked ? formData.warehouseRequestSource2 : null,
productName2: checked ? formData.productName2 : '',
});
}}
className="w-4 h-4 text-[#1B263B] border-[#c5c6cd] rounded focus:ring-[#1B263B]"
/>
@@ -305,9 +348,19 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
<Select
label="Место загрузки 2"
value={formData.pickupLocation2 || ''}
onChange={(e) => setFormData({ ...formData, pickupLocation2: e.target.value as PickupLocation })}
onChange={(e) => handlePickupLocation2Change(e.target.value as PickupLocation)}
options={pickupOptions}
/>
{formData.pickupLocation2 === 'warehouse' && (
<Select
label="От кого заявка 2 *"
value={formData.warehouseRequestSource2 || ''}
onChange={(e) => setFormData({ ...formData, warehouseRequestSource2: e.target.value ? e.target.value as DeliveryRequestSource : null })}
options={requestSourceOptions}
required
error={!isWarehouseRequestSource2Valid ? 'Выберите, от кого исходит заявка' : undefined}
/>
)}
<Input
label="Название товара 2"
value={formData.productName2}