krona-front/src/app/shell/QuickActionsModal.tsx

217 lines
8.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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>
);
};