139 lines
4.9 KiB
TypeScript
139 lines
4.9 KiB
TypeScript
"use client";
|
||
|
||
import { useState } from "react";
|
||
|
||
type Player = { id: string; name: string; position: string };
|
||
type StatRow = {
|
||
playerId: string;
|
||
goals: number;
|
||
assists: number;
|
||
yellowCards: number;
|
||
redCards: number;
|
||
minutesPlayed: number;
|
||
cleanSheet: boolean;
|
||
};
|
||
|
||
export default function StatsForm({ match }: { match: any }) {
|
||
const allPlayers: Player[] = [
|
||
...match.homeTeam.players,
|
||
...match.awayTeam.players,
|
||
];
|
||
|
||
const initStats = (): Record<string, StatRow> => {
|
||
const map: Record<string, StatRow> = {};
|
||
for (const p of allPlayers) {
|
||
const existing = match.playerStats.find((s: any) => s.playerId === p.id);
|
||
map[p.id] = existing ?? {
|
||
playerId: p.id,
|
||
goals: 0,
|
||
assists: 0,
|
||
yellowCards: 0,
|
||
redCards: 0,
|
||
minutesPlayed: 0,
|
||
cleanSheet: false,
|
||
};
|
||
}
|
||
return map;
|
||
};
|
||
|
||
const [stats, setStats] = useState<Record<string, StatRow>>(initStats);
|
||
const [loading, setLoading] = useState(false);
|
||
const [saved, setSaved] = useState(false);
|
||
|
||
function update(playerId: string, field: keyof StatRow, value: any) {
|
||
setStats((prev) => ({ ...prev, [playerId]: { ...prev[playerId], [field]: value } }));
|
||
}
|
||
|
||
async function handleSave() {
|
||
setLoading(true);
|
||
const payload = Object.values(stats).filter((s) => s.minutesPlayed > 0);
|
||
await fetch(`/api/matches/${match.id}/stats`, {
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(payload),
|
||
});
|
||
setSaved(true);
|
||
setLoading(false);
|
||
setTimeout(() => setSaved(false), 3000);
|
||
}
|
||
|
||
const renderTeam = (players: Player[], teamName: string) => (
|
||
<div className="mb-8">
|
||
<h3 className="font-bold text-lg mb-3 text-green-800">{teamName}</h3>
|
||
<div className="bg-white rounded-2xl shadow overflow-hidden">
|
||
<table className="w-full text-sm">
|
||
<thead className="bg-gray-100 text-gray-600">
|
||
<tr>
|
||
<th className="text-right px-4 py-3">بازیکن</th>
|
||
<th className="px-3 py-3">دقیقه</th>
|
||
<th className="px-3 py-3">گل</th>
|
||
<th className="px-3 py-3">پاس گل</th>
|
||
<th className="px-3 py-3">زرد</th>
|
||
<th className="px-3 py-3">قرمز</th>
|
||
<th className="px-3 py-3">کلینشیت</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{players.map((p) => {
|
||
const s = stats[p.id];
|
||
if (!s) return null;
|
||
return (
|
||
<tr key={p.id} className="border-t hover:bg-gray-50">
|
||
<td className="px-4 py-2">
|
||
<div className="font-medium">{p.name}</div>
|
||
<div className="text-xs text-gray-400">{p.position}</div>
|
||
</td>
|
||
{(["minutesPlayed", "goals", "assists", "yellowCards", "redCards"] as const).map((field) => (
|
||
<td key={field} className="px-2 py-2 text-center">
|
||
<input
|
||
type="number"
|
||
min="0"
|
||
max={field === "minutesPlayed" ? 120 : 10}
|
||
value={s[field] as number}
|
||
onChange={(e) => update(p.id, field, parseInt(e.target.value) || 0)}
|
||
className="w-14 border rounded-lg px-2 py-1 text-center focus:outline-none focus:ring-2 focus:ring-green-400"
|
||
/>
|
||
</td>
|
||
))}
|
||
<td className="px-2 py-2 text-center">
|
||
<input
|
||
type="checkbox"
|
||
checked={s.cleanSheet}
|
||
onChange={(e) => update(p.id, "cleanSheet", e.target.checked)}
|
||
className="w-4 h-4 accent-green-600"
|
||
/>
|
||
</td>
|
||
</tr>
|
||
);
|
||
})}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
);
|
||
|
||
return (
|
||
<div>
|
||
<div className="bg-green-50 border border-green-200 rounded-2xl p-4 mb-6 text-center">
|
||
<span className="font-bold text-lg">{match.homeTeam.name}</span>
|
||
<span className="mx-4 text-gray-400">vs</span>
|
||
<span className="font-bold text-lg">{match.awayTeam.name}</span>
|
||
</div>
|
||
|
||
{renderTeam(match.homeTeam.players, match.homeTeam.name)}
|
||
{renderTeam(match.awayTeam.players, match.awayTeam.name)}
|
||
|
||
<div className="flex items-center gap-4">
|
||
<button
|
||
onClick={handleSave}
|
||
disabled={loading}
|
||
className="bg-green-700 text-white px-8 py-3 rounded-xl font-bold hover:bg-green-800 transition disabled:opacity-50"
|
||
>
|
||
{loading ? "در حال ذخیره..." : "ذخیره آمار و محاسبه امتیازات"}
|
||
</button>
|
||
{saved && <span className="text-green-600 font-medium">✓ ذخیره شد</span>}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|