217 lines
8.3 KiB
TypeScript
217 lines
8.3 KiB
TypeScript
import React, { useState } from 'react';
|
||
import { useDemoStore } from '../../mock/store';
|
||
import { Modal } from '../../shared/components/Modal';
|
||
import { Button } from '../../shared/components/Button';
|
||
import { Input } from '../../shared/components/Input';
|
||
import {
|
||
ShoppingBag,
|
||
Calendar,
|
||
UserPlus,
|
||
Car,
|
||
Wrench,
|
||
CheckCircle2,
|
||
} from 'lucide-react';
|
||
|
||
export const QuickActionsModal: React.FC = () => {
|
||
const {
|
||
isQuickActionsOpen,
|
||
setIsQuickActionsOpen,
|
||
getActiveProfile,
|
||
addBooking,
|
||
addWorkOrder,
|
||
activeLocation,
|
||
} = useDemoStore();
|
||
|
||
const profile = getActiveProfile();
|
||
const [activeTab, setActiveTab] = useState<string>('order');
|
||
const [successMessage, setSuccessMessage] = useState<string | null>(null);
|
||
|
||
// Form states
|
||
const [clientName, setClientName] = useState('');
|
||
const [clientPhone, setClientPhone] = useState('');
|
||
const [bookingTime, setBookingTime] = useState('19:00');
|
||
const [resource, setResource] = useState('Стол 3');
|
||
const [vehicle, setVehicle] = useState('Toyota Camry (А123АА 154)');
|
||
const [amount, setAmount] = useState('1500');
|
||
|
||
const handleCreate = (e: React.FormEvent) => {
|
||
e.preventDefault();
|
||
if (activeTab === 'booking') {
|
||
addBooking({
|
||
clientName: clientName || 'Новый клиент',
|
||
clientPhone: clientPhone || '+7 (900) 000-00-00',
|
||
resourceName: resource,
|
||
time: bookingTime,
|
||
status: 'confirmed',
|
||
deposit: Number(amount) || 0,
|
||
});
|
||
setSuccessMessage(`Бронирование ресурса "${resource}" успешно создано!`);
|
||
} else if (activeTab === 'work_order') {
|
||
addWorkOrder({
|
||
vehicle: vehicle || 'Автомобиль клиента',
|
||
ownerName: clientName || 'Владелец',
|
||
phone: clientPhone || '+7 (900) 000-00-00',
|
||
bay: 'Пост 1',
|
||
masterName: 'Иван Кузнецов',
|
||
services: ['Комплексная диагностика', 'Мойка / ТО'],
|
||
partsAmount: 1200,
|
||
laborAmount: Number(amount) || 2500,
|
||
status: 'in_progress',
|
||
});
|
||
setSuccessMessage(`Заказ-наряд на ${vehicle} открыт!`);
|
||
} else {
|
||
setSuccessMessage(`Действие успешно выполнено для точки "${activeLocation}"!`);
|
||
}
|
||
|
||
setTimeout(() => {
|
||
setSuccessMessage(null);
|
||
setIsQuickActionsOpen(false);
|
||
}, 1200);
|
||
};
|
||
|
||
return (
|
||
<Modal
|
||
isOpen={isQuickActionsOpen}
|
||
onClose={() => setIsQuickActionsOpen(false)}
|
||
title="Быстрое создание"
|
||
subtitle={`Профиль: ${profile.name} • ${activeLocation}`}
|
||
maxWidth="lg"
|
||
>
|
||
{successMessage ? (
|
||
<div className="py-10 flex flex-col items-center justify-center text-center">
|
||
<CheckCircle2 className="w-12 h-12 text-krona-green mb-3" />
|
||
<h4 className="text-base font-semibold text-krona-primary">{successMessage}</h4>
|
||
<p className="text-xs text-krona-secondary mt-1">Данные синхронизированы в локальном mock API</p>
|
||
</div>
|
||
) : (
|
||
<div className="space-y-4">
|
||
{/* Action Types selector */}
|
||
<div className="grid grid-cols-3 gap-2 pb-2">
|
||
<button
|
||
type="button"
|
||
onClick={() => setActiveTab('order')}
|
||
className={`p-2.5 rounded-lg border text-left flex items-center gap-2.5 transition-all ${
|
||
activeTab === 'order'
|
||
? 'border-krona-green bg-krona-green/10 text-krona-green-text font-medium'
|
||
: 'border-krona-border bg-krona-surface text-krona-secondary hover:bg-krona-workspace'
|
||
}`}
|
||
>
|
||
<ShoppingBag className="w-4 h-4 shrink-0" />
|
||
<div className="text-xs truncate">Новый заказ / чек</div>
|
||
</button>
|
||
|
||
<button
|
||
type="button"
|
||
onClick={() => setActiveTab('booking')}
|
||
className={`p-2.5 rounded-lg border text-left flex items-center gap-2.5 transition-all ${
|
||
activeTab === 'booking'
|
||
? 'border-krona-green bg-krona-green/10 text-krona-green-text font-medium'
|
||
: 'border-krona-border bg-krona-surface text-krona-secondary hover:bg-krona-workspace'
|
||
}`}
|
||
>
|
||
<Calendar className="w-4 h-4 shrink-0" />
|
||
<div className="text-xs truncate">Запись / Бронь</div>
|
||
</button>
|
||
|
||
<button
|
||
type="button"
|
||
onClick={() => setActiveTab(profile.capabilities.work_orders ? 'work_order' : 'client')}
|
||
className={`p-2.5 rounded-lg border text-left flex items-center gap-2.5 transition-all ${
|
||
activeTab === 'work_order' || activeTab === 'client'
|
||
? 'border-krona-green bg-krona-green/10 text-krona-green-text font-medium'
|
||
: 'border-krona-border bg-krona-surface text-krona-secondary hover:bg-krona-workspace'
|
||
}`}
|
||
>
|
||
{profile.capabilities.work_orders ? (
|
||
<>
|
||
<Wrench className="w-4 h-4 shrink-0" />
|
||
<div className="text-xs truncate">Заказ-наряд</div>
|
||
</>
|
||
) : (
|
||
<>
|
||
<UserPlus className="w-4 h-4 shrink-0" />
|
||
<div className="text-xs truncate">Новый клиент</div>
|
||
</>
|
||
)}
|
||
</button>
|
||
</div>
|
||
|
||
<form onSubmit={handleCreate} className="space-y-3 pt-2">
|
||
<div className="grid grid-cols-2 gap-3">
|
||
<Input
|
||
label="Имя клиента"
|
||
value={clientName}
|
||
onChange={(e) => setClientName(e.target.value)}
|
||
placeholder="Иван Петров"
|
||
required
|
||
/>
|
||
<Input
|
||
label="Номер телефона"
|
||
value={clientPhone}
|
||
onChange={(e) => setClientPhone(e.target.value)}
|
||
placeholder="+7 (913) 000-00-00"
|
||
required
|
||
/>
|
||
</div>
|
||
|
||
{activeTab === 'booking' && (
|
||
<div className="grid grid-cols-2 gap-3">
|
||
<Input
|
||
label={`Ресурс (${profile.terminology.bookingResourceLabel})`}
|
||
value={resource}
|
||
onChange={(e) => setResource(e.target.value)}
|
||
placeholder="Стол 4 / Пост 2 / Мастер"
|
||
/>
|
||
<Input
|
||
label="Время записи"
|
||
type="time"
|
||
value={bookingTime}
|
||
onChange={(e) => setBookingTime(e.target.value)}
|
||
/>
|
||
</div>
|
||
)}
|
||
|
||
{activeTab === 'work_order' && (
|
||
<div className="space-y-3">
|
||
<Input
|
||
label="Автомобиль и госномер"
|
||
value={vehicle}
|
||
onChange={(e) => setVehicle(e.target.value)}
|
||
placeholder="BMW X5 (А001АА 154)"
|
||
icon={<Car className="w-4 h-4" />}
|
||
/>
|
||
</div>
|
||
)}
|
||
|
||
<div className="grid grid-cols-2 gap-3">
|
||
<Input
|
||
label="Сумма / Депозит (₽)"
|
||
type="number"
|
||
value={amount}
|
||
onChange={(e) => setAmount(e.target.value)}
|
||
placeholder="2500"
|
||
/>
|
||
<div className="flex flex-col gap-1.5 text-left">
|
||
<label className="text-xs font-medium text-krona-secondary">Точка бизнеса</label>
|
||
<input
|
||
disabled
|
||
value={activeLocation}
|
||
className="w-full bg-krona-workspace text-krona-secondary border border-krona-border rounded-md px-3 py-2 text-sm"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="pt-3 flex justify-end gap-2">
|
||
<Button type="button" variant="secondary" onClick={() => setIsQuickActionsOpen(false)}>
|
||
Отмена
|
||
</Button>
|
||
<Button type="submit" variant="primary">
|
||
Создать сущность
|
||
</Button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
)}
|
||
</Modal>
|
||
);
|
||
};
|