krona-front/src/features/operations/DeliveryView.tsx

201 lines
8.5 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, DeliveryItem } from '../../mock/store';
import { Badge } from '../../shared/components/Badge';
import { Button } from '../../shared/components/Button';
import { formatCurrency } from '../../shared/utils/formatters';
import {
Truck,
MapPin,
Phone,
CheckCircle2,
Smartphone,
} from 'lucide-react';
export interface DeliveryViewProps {
initialMobile?: boolean;
}
export const DeliveryView: React.FC<DeliveryViewProps> = ({ initialMobile = false }) => {
const { deliveries, updateDeliveryStatus } = useDemoStore();
const [courierMobileMode, setCourierMobileMode] = useState(initialMobile);
const getStatusBadge = (status: DeliveryItem['status']) => {
switch (status) {
case 'in_transit':
return <Badge variant="info" size="sm">Курьер в пути</Badge>;
case 'delivered':
return <Badge variant="green" size="sm">Доставлен</Badge>;
case 'pending':
default:
return <Badge variant="warning" size="sm">Ожидает курьера</Badge>;
}
};
return (
<div className="space-y-4 animate-fade-in">
<div className="flex items-center justify-between bg-krona-surface p-3.5 rounded-xl border border-krona-border shadow-krona-soft">
<div>
<h2 className="text-sm font-bold text-krona-primary">
Управление доставкой & Мониторинг курьеров
</h2>
<p className="text-xs text-krona-secondary">
Логистический контур: распределение заказов, расчет времени прибытия (ETA) и контроль налички
</p>
</div>
<Button
variant={courierMobileMode ? 'gold' : 'secondary'}
size="sm"
onClick={() => setCourierMobileMode(!courierMobileMode)}
>
<Smartphone className="w-3.5 h-3.5 mr-1.5" />
{courierMobileMode ? 'Обычный диспетчерский вид' : 'Экран курьера (Mobile View)'}
</Button>
</div>
{courierMobileMode ? (
/* Courier Mobile-First Screen */
<div className="max-w-md mx-auto bg-krona-surface border-2 border-krona-gold/60 rounded-2xl p-4 shadow-xl space-y-4">
<div className="flex items-center justify-between pb-3 border-b border-krona-border">
<div className="flex items-center gap-2">
<div className="w-8 h-8 rounded-full bg-krona-gold/20 flex items-center justify-center text-krona-gold">
<Truck className="w-4 h-4" />
</div>
<div>
<h4 className="text-xs font-bold text-krona-primary">Алексей Смирнов (Авто)</h4>
<span className="text-[10px] text-krona-secondary">Смена активна • Наличные: 24 500 ₽</span>
</div>
</div>
<Badge variant="green" size="sm">Онлайн</Badge>
</div>
<div className="space-y-3">
<span className="text-xs font-semibold uppercase tracking-wider text-krona-secondary block">
Мои текущие доставки ({deliveries.filter((d) => d.status !== 'delivered').length})
</span>
{deliveries.map((del) => (
<div
key={del.id}
className="p-3.5 rounded-xl border border-krona-border bg-krona-workspace space-y-2.5"
>
<div className="flex items-center justify-between">
<span className="font-bold text-xs text-krona-primary">{del.orderId}</span>
{getStatusBadge(del.status)}
</div>
<div className="space-y-1 text-xs">
<div className="flex items-start gap-1.5 text-krona-primary font-medium">
<MapPin className="w-3.5 h-3.5 text-krona-danger shrink-0 mt-0.5" />
<span>{del.address}</span>
</div>
<div className="flex items-center justify-between pt-1 text-[11px] text-krona-secondary">
<span>{del.recipientName}</span>
<a href={`tel:${del.phone}`} className="text-krona-green font-semibold flex items-center gap-1">
<Phone className="w-3 h-3" />
{del.phone}
</a>
</div>
<div className="flex items-center justify-between pt-1 border-t border-krona-border/60">
<span className="text-krona-secondary">К оплате:</span>
<span className="font-bold text-krona-primary">{formatCurrency(del.amount)} ({del.paymentMethod})</span>
</div>
</div>
<div className="pt-2 flex gap-2">
{del.status === 'pending' && (
<Button
variant="primary"
size="sm"
className="w-full text-xs"
onClick={() => updateDeliveryStatus(del.id, 'in_transit')}
>
Заказ забрал, еду к клиенту
</Button>
)}
{del.status === 'in_transit' && (
<Button
variant="gold"
size="sm"
className="w-full text-xs"
onClick={() => updateDeliveryStatus(del.id, 'delivered')}
>
<CheckCircle2 className="w-3.5 h-3.5 mr-1" />
Заказ вручен и оплачен
</Button>
)}
</div>
</div>
))}
</div>
</div>
) : (
/* Dispatcher Desktop Grid */
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{deliveries.map((del) => (
<div
key={del.id}
className="p-4 rounded-xl border border-krona-border bg-krona-surface shadow-krona-soft space-y-3"
>
<div className="flex items-center justify-between pb-2 border-b border-krona-border/60">
<span className="font-bold text-sm text-krona-primary">{del.orderId}</span>
{getStatusBadge(del.status)}
</div>
<div className="space-y-1.5 text-xs">
<div className="flex items-start gap-1.5">
<MapPin className="w-3.5 h-3.5 text-krona-danger shrink-0 mt-0.5" />
<span className="text-krona-primary font-medium leading-tight">{del.address}</span>
</div>
<div className="pt-1 text-krona-secondary">
<div>Получатель: <strong className="text-krona-primary">{del.recipientName}</strong></div>
<div>Телефон: <span className="font-mono">{del.phone}</span></div>
<div>Курьер: <strong className="text-krona-primary">{del.courierName}</strong></div>
</div>
<div className="flex justify-between pt-1 border-t border-krona-border/40 font-bold">
<span>Сумма:</span>
<span className="text-krona-green">{formatCurrency(del.amount)}</span>
</div>
</div>
<div className="pt-2 border-t border-krona-border/60 flex justify-end gap-2">
{del.status === 'pending' && (
<Button
variant="primary"
size="sm"
className="w-full text-xs"
onClick={() => updateDeliveryStatus(del.id, 'in_transit')}
>
Передать курьеру
</Button>
)}
{del.status === 'in_transit' && (
<Button
variant="secondary"
size="sm"
className="w-full text-xs"
onClick={() => updateDeliveryStatus(del.id, 'delivered')}
>
Отметить вручение
</Button>
)}
{del.status === 'delivered' && (
<div className="w-full text-center text-xs text-krona-green font-semibold py-1">
✓ Успешно доставлен
</div>
)}
</div>
</div>
))}
</div>
)}
</div>
);
};