Spaces:
Running
Running
File size: 6,655 Bytes
f7cecf3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | import React from "react";
import { Trash2 } from "lucide-react";
export const DraftsComparisonTable = ({
drafts, horizonGWs, activeDraftId, globalPlayers,
setActiveDraftId, getValidLayout, availableGWs,
baselineFt, ftAtStartOfGw, setDrafts
}) => {
if (!drafts || drafts.length === 0) return null;
const handleDeleteDraft = (e, id) => {
e.stopPropagation(); // Prevents the row click from triggering
if (drafts.length <= 1) return;
const nextDrafts = drafts.filter(d => d.id !== id);
setDrafts(nextDrafts);
if (activeDraftId === id) setActiveDraftId(nextDrafts[0].id);
};
const getDraftGwState = (draft, gw) => {
if (draft.cachedEvs && draft.cachedEvs[gw]) {
return draft.cachedEvs[gw];
}
const chip = draft.chipsByGw?.[gw];
const capMult = chip === "tc" ? 3 : 2;
let squad = [];
let capId = null;
if (gw === draft.activeGW) {
squad = draft.teamData;
capId = draft.captainId;
} else {
const lock = draft.manualOverrides?.[gw];
if (lock && lock.ids && lock.ids.length === 15) {
squad = lock.ids.map(id => draft.teamData?.find(p => String(p.ID) === String(id)) || globalPlayers.find(p => String(p.ID) === String(id))).filter(Boolean);
capId = lock.cap;
if (squad.length !== 15) {
const opt = getValidLayout(draft.teamData, gw);
if (opt) { squad = opt.optimalArray; capId = opt.cap; }
}
} else {
const opt = getValidLayout(draft.teamData, gw);
if (opt) { squad = opt.optimalArray; capId = opt.cap; }
}
}
let gwPts = 0;
if (squad && squad.length === 15) {
squad.slice(0, 11).forEach(p => {
if (!p.isBlank) gwPts += (Number(p[`${gw}_Pts`]) || 0) * (String(p.ID) === String(capId) ? capMult : 1);
});
let ofIdx = 0;
squad.slice(11, 15).forEach(p => {
if (!p.isBlank) {
if (chip === "bb") gwPts += (Number(p[`${gw}_Pts`]) || 0);
else if (p.Pos === "G") gwPts += (Number(p[`${gw}_Pts`]) || 0) * 0.04;
else { gwPts += (Number(p[`${gw}_Pts`]) || 0) * ([0.17, 0.05, 0.02][ofIdx] || 0.02); ofIdx++; }
}
});
}
const ftStart = ftAtStartOfGw(gw, availableGWs, baselineFt, draft.transfersByGw || {}, draft.chipsByGw || {});
const moves = draft.transfersByGw?.[gw]?.count || 0;
const isChipFree = chip === "wc" || chip === "fh";
const hits = isChipFree ? 0 : Math.max(0, moves - ftStart);
return { ev: gwPts - (hits * 4), chip, hits, ftStart, moves, isChipFree };
};
return (
<div className="w-full bg-[#0a0f1c] border border-[#2a2d5c] rounded-xl shadow-[0_0_30px_rgba(42,45,92,0.4)] overflow-hidden mb-6">
<div className="overflow-x-auto custom-scrollbar">
<table className="w-full text-center font-mono whitespace-nowrap">
<thead>
<tr className="text-slate-400 text-[9px] uppercase tracking-widest border-b border-[#2a2d5c] bg-[#050811]">
<th className="py-2 px-4 text-left font-black w-40">Timeline</th>
{horizonGWs.map(gw => (
<th key={gw} className="py-2 px-3 border-l border-[#1a1c3a]">GW{gw}</th>
))}
<th className="py-2 px-4 text-emerald-400 font-black border-l border-[#2a2d5c] w-24 shadow-[inset_10px_0_20px_rgba(0,0,0,0.2)]">Total EV</th>
</tr>
</thead>
<tbody className="divide-y divide-[#1a1c3a]">
{drafts.map((draft) => {
const isActive = draft.id === activeDraftId;
const rowData = horizonGWs.map(gw => getDraftGwState(draft, gw));
const totalEv = rowData.reduce((sum, d) => sum + d.ev, 0);
return (
<tr
key={draft.id}
onClick={() => setActiveDraftId(draft.id)}
className={`transition-all cursor-pointer group ${isActive ? "bg-[#1e2247]/60" : "bg-[#0a0f1c] hover:bg-[#151833]"}`}
>
<td className="py-2.5 px-4 border-r border-[#1a1c3a]">
<div className="flex items-center justify-between w-32">
<div className={`font-bold text-[11px] truncate transition-colors ${isActive ? "text-white" : "text-slate-400 group-hover:text-slate-200"}`}>
{draft.name}
</div>
{/* FIX: Native Flexbox Delete Button (always clickable, visually clean) */}
{drafts.length > 1 && (
<button
onClick={(e) => handleDeleteDraft(e, draft.id)}
className="p-1.5 text-slate-500 hover:text-red-400 hover:bg-red-500/10 rounded-md transition-all flex-shrink-0"
title="Delete Timeline"
>
<Trash2 size={12} />
</button>
)}
</div>
</td>
{rowData.map((d, i) => (
<td key={i} className="py-2 px-3 border-l border-[#1a1c3a] relative">
<div className={`text-[15px] font-black tracking-tight drop-shadow-md ${isActive ? (d.ev > 55 ? 'text-[#818cf8]' : 'text-indigo-200') : 'text-slate-500'}`}>
{d.ev.toFixed(1)}
</div>
<div className="flex justify-center items-center gap-1.5 mt-1">
<span className="text-[8px] font-black uppercase text-[#c084fc] w-3 text-left">{d.chip || ""}</span>
<span className={`text-[8.5px] font-bold flex items-center gap-1.5 ${isActive ? 'text-indigo-300' : 'text-slate-600'}`}>
<span>{d.hits > 0 ? `-${d.hits*4}` : "-"}</span>
<span>{d.isChipFree ? `${d.moves}/∞` : `${d.moves}/${d.ftStart}`}</span>
</span>
</div>
</td>
))}
<td className={`py-2 px-4 border-l border-[#2a2d5c] shadow-[inset_10px_0_20px_rgba(0,0,0,0.2)] ${isActive ? 'bg-[#050811]/40' : 'bg-[#050811]/80'}`}>
<div className={`text-lg font-black drop-shadow-[0_0_10px_rgba(52,211,153,0.3)] ${isActive ? 'text-emerald-400' : 'text-emerald-700'}`}>
{totalEv.toFixed(1)}
</div>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
);
}; |