Kacemath's picture
feat: update with latest changes
47bba68
import React from 'react';
import { useGridStore } from '../../store/gridStore';
import { Card, CardContent, CardHeader, CardTitle } from '../ui/card';
import { Button } from '../ui/button';
import {
X,
Truck,
Package,
Route,
Clock,
Activity,
HardDrive,
ArrowRight,
CheckCircle,
Eye,
EyeOff,
} from 'lucide-react';
// Colors matching the store
const PATH_COLORS = [
'#f97316', // orange
'#06b6d4', // cyan
'#ec4899', // pink
'#84cc16', // lime
'#a855f7', // purple
'#14b8a6', // teal
'#f43f5e', // rose
'#eab308', // yellow
'#6366f1', // indigo
'#22c55e', // green
];
interface PlanResultsModalProps {
isOpen: boolean;
onClose: () => void;
}
export const PlanResultsModal: React.FC<PlanResultsModalProps> = ({ isOpen, onClose }) => {
const { planResult, selectedAlgorithm, showPlanPaths, setShowPlanPaths } = useGridStore();
if (!isOpen || !planResult) return null;
return (
<div className="fixed inset-0 z-50 flex items-center justify-center">
{/* Backdrop */}
<div
className="absolute inset-0 bg-black/70 backdrop-blur-sm"
onClick={onClose}
/>
{/* Modal */}
<div className="relative bg-zinc-900 border border-zinc-800 rounded-xl shadow-2xl w-full max-w-3xl max-h-[85vh] overflow-hidden m-4">
{/* Header */}
<div className="flex items-center justify-between px-6 py-4 border-b border-zinc-800 bg-zinc-800/30">
<div className="flex items-center gap-3">
<div className="p-2 bg-zinc-800 rounded-lg">
<Truck className="w-5 h-5 text-zinc-300" />
</div>
<div>
<h2 className="text-sm font-semibold text-zinc-200">Delivery Plan Results</h2>
<p className="text-xs text-zinc-500">Algorithm: {selectedAlgorithm}</p>
</div>
</div>
<Button variant="ghost" size="icon" onClick={onClose}>
<X className="w-4 h-4" />
</Button>
</div>
{/* Content */}
<div className="overflow-y-auto max-h-[calc(85vh-140px)] p-6 space-y-4">
{/* Summary Stats */}
<div className="grid grid-cols-4 gap-3">
<Card>
<CardContent className="p-3">
<div className="flex items-center gap-2 text-zinc-500 text-xs mb-1">
<Route className="w-3.5 h-3.5" />
Total Cost
</div>
<p className="text-lg font-semibold text-zinc-200 font-mono">
{planResult.totalCost}
</p>
</CardContent>
</Card>
<Card>
<CardContent className="p-3">
<div className="flex items-center gap-2 text-zinc-500 text-xs mb-1">
<Activity className="w-3.5 h-3.5" />
Nodes Expanded
</div>
<p className="text-lg font-semibold text-zinc-200 font-mono">
{planResult.totalNodesExpanded.toLocaleString()}
</p>
</CardContent>
</Card>
<Card>
<CardContent className="p-3">
<div className="flex items-center gap-2 text-zinc-500 text-xs mb-1">
<Clock className="w-3.5 h-3.5" />
Runtime
</div>
<p className="text-lg font-semibold text-zinc-200 font-mono">
{planResult.runtimeMs.toFixed(2)}ms
</p>
</CardContent>
</Card>
<Card>
<CardContent className="p-3">
<div className="flex items-center gap-2 text-zinc-500 text-xs mb-1">
<HardDrive className="w-3.5 h-3.5" />
Memory
</div>
<p className="text-lg font-semibold text-zinc-200 font-mono">
{planResult.memoryKb.toFixed(2)}KB
</p>
</CardContent>
</Card>
</div>
{/* Plan Output */}
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-xs text-zinc-400 font-medium">Plan Output</CardTitle>
</CardHeader>
<CardContent>
<div className="bg-zinc-950 rounded-lg p-3 font-mono text-xs text-zinc-300 whitespace-pre-wrap overflow-x-auto">
{planResult.output || 'No output'}
</div>
</CardContent>
</Card>
{/* Assignments */}
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-xs text-zinc-400 font-medium flex items-center gap-2">
<Package className="w-3.5 h-3.5" />
Delivery Assignments ({planResult.assignments.length})
</CardTitle>
</CardHeader>
<CardContent className="space-y-2">
{planResult.assignments.length === 0 ? (
<p className="text-zinc-500 text-sm">No assignments made</p>
) : (
planResult.assignments.map((assignment, index) => {
const pathColor = PATH_COLORS[index % PATH_COLORS.length];
return (
<div
key={index}
className="bg-zinc-800/50 rounded-lg p-3 border border-zinc-800"
style={{ borderLeftWidth: 4, borderLeftColor: pathColor }}
>
<div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-3">
{/* Color indicator */}
<div
className="w-3 h-3 rounded-full"
style={{ backgroundColor: pathColor }}
/>
<div className="flex items-center gap-2">
<div className="w-6 h-6 rounded bg-blue-500/20 border border-blue-500/30 flex items-center justify-center">
<span className="text-xs font-mono text-blue-400">S{assignment.store_id}</span>
</div>
<ArrowRight className="w-4 h-4 text-zinc-600" />
<div className="w-6 h-6 rounded-full bg-emerald-500/20 border border-emerald-500/30 flex items-center justify-center">
<span className="text-xs font-mono text-emerald-400">D{assignment.destination_id}</span>
</div>
</div>
<CheckCircle className="w-4 h-4 text-emerald-500" />
</div>
<div className="flex items-center gap-4 text-xs text-zinc-500">
<span>Cost: <span className="text-zinc-300 font-mono">{assignment.path.cost}</span></span>
<span>Nodes: <span className="text-zinc-300 font-mono">{assignment.path.nodes_expanded}</span></span>
</div>
</div>
<div className="text-xs text-zinc-500">
<span className="text-zinc-600">Path: </span>
<span className="font-mono text-zinc-400">{assignment.path.plan || 'Direct'}</span>
</div>
</div>
);
})
)}
</CardContent>
</Card>
</div>
{/* Footer */}
<div className="px-6 py-3 border-t border-zinc-800 bg-zinc-800/20 flex justify-between">
<Button
variant={showPlanPaths ? 'primary' : 'outline'}
size="sm"
onClick={() => setShowPlanPaths(!showPlanPaths)}
className="gap-2"
>
{showPlanPaths ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
{showPlanPaths ? 'Hide Paths on Grid' : 'Show Paths on Grid'}
</Button>
<Button variant="secondary" size="sm" onClick={onClose}>
Close
</Button>
</div>
</div>
</div>
);
};
export default PlanResultsModal;