This commit is contained in:
2026-04-07 10:38:28 +03:30
parent aa9ed69dd2
commit 8bcd1c2951
99 changed files with 3357 additions and 178 deletions

View File

@@ -2,10 +2,12 @@
import { useState, useRef } from "react";
import PositionBadge from "@/components/PositionBadge";
import Image from "next/image";
type Player = {
id: string;
name: string;
image: string | null;
position: string;
price: number;
totalPoints: number;
@@ -346,42 +348,56 @@ export default function TeamBuilder({
onChange={(e) => setFilter(e.target.value)}
className="w-full border rounded-xl px-4 py-2 text-sm mb-3 focus:outline-none focus:ring-2 focus:ring-green-400" />
<div className="bg-white rounded-2xl shadow overflow-hidden" style={{ maxHeight: 520, overflowY: "auto" }}>
<table className="w-full text-sm">
<thead className="bg-green-800 text-white sticky top-0">
<tr>
<th className="text-right px-3 py-3">بازیکن</th>
<th className="px-2 py-3">قیمت</th>
<th className="px-2 py-3">pts</th>
<th className="px-2 py-3"></th>
</tr>
</thead>
<tbody>
{filtered.map((p) => (
<tr key={p.id} className="border-t hover:bg-green-50 transition">
<td className="px-3 py-2">
<div className="font-medium text-sm">{p.name}</div>
<div className="flex items-center gap-1 mt-0.5">
<span className="text-xs text-gray-400">{p.country.flagUrl} {p.country.name}</span>
<PositionBadge position={p.position} />
<div className="bg-white rounded-2xl shadow p-4" style={{ maxHeight: 520, overflowY: "auto" }}>
<div className="flex gap-3 flex-wrap">
{filtered.map((p) => (
<div
key={p.id}
draggable
onDragStart={() => setDraggedId(p.id)}
className="flex-shrink-0 bg-gray-50 rounded-xl p-2 cursor-move hover:bg-gray-100 transition border-2 border-transparent hover:border-green-500"
style={{ width: "90px" }}
>
<div className="relative w-20 h-20 rounded-lg overflow-hidden bg-gray-200 mb-1 mx-auto">
{p.image ? (
<Image
src={`/uploads/players/${p.image}`}
alt={p.name}
fill
className="object-cover"
/>
) : (
<div className="w-full h-full flex items-center justify-center text-gray-400 text-3xl">
👤
</div>
</td>
<td className="px-2 py-2 text-center text-green-700 font-bold text-xs">{p.price}M</td>
<td className="px-2 py-2 text-center text-blue-700 font-bold text-xs">{p.totalPoints}</td>
<td className="px-2 py-2">
<button onClick={() => addPlayer(p.id)}
disabled={loading || p.price > remaining + 0.01}
className="bg-green-600 text-white w-7 h-7 rounded-lg text-lg font-bold hover:bg-green-700 disabled:opacity-30 transition flex items-center justify-center">
+
</button>
</td>
</tr>
))}
{filtered.length === 0 && (
<tr><td colSpan={4} className="text-center text-gray-400 py-8">بازیکنی پیدا نشد</td></tr>
)}
</tbody>
</table>
)}
</div>
<div className="text-[10px] font-bold text-gray-800 text-center leading-tight mb-1">
{p.name.split(" ").slice(-1)[0]}
</div>
<div className="flex items-center justify-center gap-1 mb-1">
<span className="text-xs">{p.country.flagUrl}</span>
<PositionBadge position={p.position} />
</div>
<div className="text-[9px] text-center text-gray-600 mb-2">
<span className="text-green-700 font-bold">{p.price}M</span>
<span className="mx-1">·</span>
<span className="text-blue-700 font-bold">{p.totalPoints}pts</span>
</div>
<button
onClick={() => addPlayer(p.id)}
onPointerDown={(e) => e.stopPropagation()}
disabled={loading || p.price > remaining + 0.01}
className="w-full bg-green-600 text-white text-xs py-1 rounded-lg hover:bg-green-700 transition disabled:opacity-30 font-bold"
>
+ افزودن
</button>
</div>
))}
{filtered.length === 0 && (
<div className="w-full text-center text-gray-400 py-8">بازیکنی پیدا نشد</div>
)}
</div>
</div>
</div>
</div>
@@ -418,42 +434,79 @@ function PitchCard({ tp, onRemove, onDragStart, onDrop, onCaptain, draggedId, sm
const [showMenu, setShowMenu] = useState(false);
const isDragging = draggedId === tp.playerId;
const isEliminated = (tp.player as any).country?.isEliminated;
const color = isEliminated
? "bg-gray-500 text-gray-300 border-gray-600"
: POS_COLORS[tp.player.position] ?? "bg-gray-400 text-white border-gray-500";
const shortName = tp.player.name.split(" ").slice(-1)[0];
return (
<div className={`relative flex flex-col items-center gap-1 cursor-grab select-none transition-opacity ${isDragging ? "opacity-40" : ""} ${small ? "w-14" : "w-16"} group`}
<div
className={`relative group ${isDragging ? "opacity-50" : ""}`}
draggable
onDragStart={() => onDragStart(tp.playerId)}
onDragOver={(e) => e.preventDefault()}
onDrop={() => onDrop(tp.playerId)}
onClick={() => setShowMenu((v) => !v)}>
<div className={`relative ${small ? "w-11 h-11 text-lg" : "w-14 h-14 text-xl"} rounded-full border-2 flex items-center justify-center font-bold shadow-lg ${color} ${isEliminated ? "grayscale opacity-60" : ""}`}>
{tp.player.position === "GK" ? "🧤" : tp.player.position === "DEF" ? "🛡️" : tp.player.position === "MID" ? "⚙️" : "⚡"}
{isEliminated && <div className="absolute -top-1 -right-1 w-4 h-4 bg-red-500 rounded-full flex items-center justify-center text-white text-[8px] font-bold"></div>}
</div>
<div className={`text-center font-medium leading-tight truncate w-full ${small ? "text-[9px]" : "text-[10px]"} ${isEliminated ? "text-gray-400" : "text-white"}`}>
{shortName}
</div>
<div className="flex items-center gap-1">
{tp.isCaptain && <span className="text-yellow-300 text-xs font-bold">©</span>}
{tp.isViceCaptain && <span className="text-gray-300 text-xs font-bold">VC</span>}
<span className={`text-[9px] ${isEliminated ? "text-gray-500" : "text-white/60"}`}>{tp.player.totalPoints}pts</span>
</div>
{isEliminated && (
<div className="absolute -top-8 left-1/2 -translate-x-1/2 bg-gray-900 text-white text-[9px] px-2 py-1 rounded whitespace-nowrap opacity-0 group-hover:opacity-100 pointer-events-none z-50 transition-opacity">
تیم ملی حذف شده
>
<div className={`bg-white/95 rounded-xl p-2 cursor-move hover:bg-white transition shadow-lg ${small ? "w-16" : "w-20"}`}>
<div className={`relative ${small ? "w-12 h-12" : "w-16 h-16"} rounded-lg overflow-hidden bg-gray-200 mb-1 mx-auto`}>
{tp.player.image ? (
<Image
src={`/uploads/players/${tp.player.image}`}
alt={tp.player.name}
fill
className="object-cover"
/>
) : (
<div className="w-full h-full flex items-center justify-center text-gray-400 text-2xl">
👤
</div>
)}
{isEliminated && (
<div className="absolute inset-0 bg-black/50 flex items-center justify-center">
<span className="text-white text-xs font-bold"></span>
</div>
)}
</div>
)}
{showMenu && (
<div className="absolute top-full mt-1 bg-white rounded-xl shadow-xl z-50 text-xs w-36 overflow-hidden border" onClick={(e) => e.stopPropagation()}>
{isEliminated && <div className="px-3 py-2 bg-red-50 text-red-600 text-[10px] border-b"> تیم ملی حذف شده</div>}
<button onClick={() => { onCaptain(tp.playerId, "captain"); setShowMenu(false); }} className="w-full text-right px-3 py-2 hover:bg-gray-50 border-b">کاپیتان ©</button>
<button onClick={() => { onCaptain(tp.playerId, "vice"); setShowMenu(false); }} className="w-full text-right px-3 py-2 hover:bg-gray-50 border-b">نایب کاپیتان VC</button>
<button onClick={() => { onRemove(tp.playerId); setShowMenu(false); }} className="w-full text-right px-3 py-2 hover:bg-red-50 text-red-600">حذف از تیم</button>
<div className={`text-[10px] font-bold text-gray-800 text-center leading-tight ${isEliminated ? "opacity-50" : ""}`}>
{shortName}
</div>
)}
<div className="flex items-center justify-center gap-1 mt-1">
{tp.isCaptain && (
<div className="bg-yellow-400 text-yellow-900 rounded-full w-4 h-4 flex items-center justify-center text-[8px] font-bold">
C
</div>
)}
{tp.isViceCaptain && (
<div className="bg-gray-400 text-white rounded-full w-4 h-4 flex items-center justify-center text-[8px] font-bold">
V
</div>
)}
</div>
<div className="text-[8px] text-center text-gray-600 mt-1">
{tp.player.totalPoints}pts
</div>
</div>
<div className="absolute -bottom-8 left-1/2 -translate-x-1/2 opacity-0 group-hover:opacity-100 transition flex gap-1 z-20">
<button
onClick={(e) => {
e.stopPropagation();
onCaptain(tp.playerId, tp.isCaptain ? "vice" : "captain");
}}
className="bg-yellow-400 text-yellow-900 text-[8px] px-2 py-0.5 rounded-full font-bold whitespace-nowrap shadow"
>
{tp.isCaptain ? "VC" : "C"}
</button>
<button
onClick={(e) => {
e.stopPropagation();
onRemove(tp.playerId);
}}
className="bg-red-500 text-white text-[8px] px-2 py-0.5 rounded-full font-bold shadow"
>
حذف
</button>
</div>
</div>
);
}