admin
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user