frontend refactor

This commit is contained in:
Egor Pozharov
2026-04-14 17:10:13 +06:00
parent 0540218332
commit 9b90a8aa7f
14 changed files with 328 additions and 127 deletions

View File

@@ -1,7 +1,8 @@
import { useState, useEffect } from 'react';
import { useState, useEffect, useCallback } from 'react';
import { Button, Input, Select, Modal } from '../ui';
import { pickupOptions } from '../../constants/pickup';
import { formatDateForInput, parseDateFromInput, getTodayFrontend } from '../../utils/date';
import type { Delivery, PickupLocation, DeliveryStatus } from '../../types';
import { pickupLocationLabels } from '../../types';
interface DeliveryFormProps {
isOpen: boolean;
@@ -12,16 +13,12 @@ interface DeliveryFormProps {
isSubmitting?: boolean;
}
const pickupOptions: { value: PickupLocation; label: string }[] = [
{ value: 'warehouse', label: pickupLocationLabels.warehouse },
{ value: 'symbat', label: pickupLocationLabels.symbat },
{ value: 'nursaya', label: pickupLocationLabels.nursaya },
{ value: 'galaktika', label: pickupLocationLabels.galaktika },
];
// Phone validation regex for Kazakhstan numbers
const PHONE_REGEX = /^\+7\s?\(?\d{3}\)?\s?\d{3}[\s-]?\d{2}[\s-]?\d{2}$/;
export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDate, isSubmitting }: DeliveryFormProps) => {
const [formData, setFormData] = useState({
date: defaultDate || new Date().toLocaleDateString('ru-RU').split('.').join('-'),
date: defaultDate || getTodayFrontend(),
pickupLocation: 'warehouse' as PickupLocation,
productName: '',
address: '',
@@ -50,34 +47,39 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
}
}, [initialData, defaultDate, isOpen]);
const handleSubmit = (e: React.FormEvent) => {
const validatePhone = useCallback((phone: string): boolean => {
if (!phone) return false;
return PHONE_REGEX.test(phone);
}, []);
const isPhoneValid = !formData.phone || validatePhone(formData.phone);
const isAdditionalPhoneValid = !formData.additionalPhone || validatePhone(formData.additionalPhone);
const isFormValid = formData.productName && formData.address && formData.phone && isPhoneValid;
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
onSubmit(formData);
if (!initialData) {
setFormData({
date: defaultDate || new Date().toLocaleDateString('ru-RU').split('.').join('-'),
pickupLocation: 'warehouse',
productName: '',
address: '',
phone: '',
additionalPhone: '',
hasElevator: false,
comment: '',
status: 'new',
});
if (!isFormValid) return;
try {
await onSubmit(formData);
if (!initialData) {
setFormData({
date: defaultDate || getTodayFrontend(),
pickupLocation: 'warehouse',
productName: '',
address: '',
phone: '',
additionalPhone: '',
hasElevator: false,
comment: '',
status: 'new',
});
}
onClose();
} catch {
// Error is handled by parent, keep form open
}
onClose();
};
const formatDateForInput = (dateStr: string) => {
const [day, month, year] = dateStr.split('-');
return `${year}-${month}-${day}`;
};
const formatDateFromInput = (dateStr: string) => {
const [year, month, day] = dateStr.split('-');
return `${day}-${month}-${year}`;
};
return (
<Modal
@@ -89,7 +91,7 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
<Button variant="ghost" onClick={onClose} disabled={isSubmitting}>
Отмена
</Button>
<Button type="submit" form="delivery-form" disabled={isSubmitting}>
<Button type="submit" form="delivery-form" disabled={isSubmitting || !isFormValid}>
{isSubmitting ? 'Сохранение...' : initialData ? 'Сохранить' : 'Создать'}
</Button>
</>
@@ -103,7 +105,7 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
<input
type="date"
value={formatDateForInput(formData.date)}
onChange={(e) => setFormData({ ...formData, date: formatDateFromInput(e.target.value) })}
onChange={(e) => setFormData({ ...formData, date: parseDateFromInput(e.target.value) })}
className="w-full px-3 py-2 bg-[#f5f3f5] border border-[#c5c6cd] rounded-md text-[#1b1b1d] focus:outline-none focus:ring-2 focus:ring-[#1B263B] focus:border-transparent transition-colors"
required
/>
@@ -144,7 +146,14 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
}}
placeholder="+7 (776)-567-89-01"
required
aria-invalid={!isPhoneValid}
aria-describedby={!isPhoneValid ? 'phone-error' : undefined}
/>
{!isPhoneValid && formData.phone && (
<p id="phone-error" className="text-sm text-red-500 mt-1">
Введите корректный номер: +7 (XXX) XXX-XX-XX
</p>
)}
<Input
label="Дополнительный номер телефона"
@@ -157,7 +166,14 @@ export const DeliveryForm = ({ isOpen, onClose, onSubmit, initialData, defaultDa
}
}}
placeholder="+7 (776)-567-89-01"
aria-invalid={!isAdditionalPhoneValid}
aria-describedby={!isAdditionalPhoneValid ? 'additional-phone-error' : undefined}
/>
{!isAdditionalPhoneValid && formData.additionalPhone && (
<p id="additional-phone-error" className="text-sm text-red-500 mt-1">
Введите корректный номер: +7 (XXX) XXX-XX-XX
</p>
)}
<div className="flex items-center gap-2">
<input