Files
football-next/app/(admin)/admin/players/PlayerForm.tsx
2026-05-03 17:01:46 +03:30

181 lines
6.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import Image from "next/image";
type Country = { id: string; name: string };
type CardTier = "GOLD" | "SILVER" | "BRONZE";
export default function PlayerForm({
countries,
initial,
playerId,
}: {
countries: Country[];
initial?: { name: string; position: string; countryId: string; price: number; image?: string | null; cardTier: CardTier };
playerId?: string;
}) {
const router = useRouter();
const [form, setForm] = useState({
name: initial?.name ?? "",
position: initial?.position ?? "FWD",
countryId: initial?.countryId ?? "",
price: initial?.price ?? 5.0,
image: initial?.image ?? "",
cardTier: initial?.cardTier ?? "BRONZE",
});
const [loading, setLoading] = useState(false);
const [uploading, setUploading] = useState(false);
const [error, setError] = useState("");
async function handleImageUpload(e: React.ChangeEvent<HTMLInputElement>) {
const file = e.target.files?.[0];
if (!file) return;
setUploading(true);
setError("");
const formData = new FormData();
formData.append("file", file);
try {
const res = await fetch("/api/upload/player-image", {
method: "POST",
body: formData,
});
if (res.ok) {
const data = await res.json();
setForm({ ...form, image: data.fileName });
} else {
const data = await res.json();
setError(data.error ?? "خطا در آپلود تصویر");
}
} catch (err) {
setError("خطا در آپلود تصویر");
} finally {
setUploading(false);
}
}
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
setLoading(true);
const res = await fetch(playerId ? `/api/players/${playerId}` : "/api/players", {
method: playerId ? "PUT" : "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(form),
});
if (res.ok) {
router.push("/admin/players");
router.refresh();
} else {
const d = await res.json();
setError(d.error ?? "خطا");
}
setLoading(false);
}
return (
<form onSubmit={handleSubmit} className="bg-white rounded-2xl shadow p-6 flex flex-col gap-4">
{error && <p className="text-red-500 text-sm">{error}</p>}
<div>
<label className="block text-sm font-medium mb-1">تصویر بازیکن</label>
<div className="flex items-center gap-4">
{form.image && (
<div className="relative w-24 h-24 rounded-xl overflow-hidden border">
<Image
src={`/uploads/players/${form.image}`}
alt={form.name}
fill
className="object-cover"
/>
</div>
)}
<div className="flex-1">
<input
type="file"
accept="image/*"
onChange={handleImageUpload}
disabled={uploading}
className="w-full border rounded-xl px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-green-500"
/>
{uploading && <p className="text-sm text-gray-500 mt-1">در حال آپلود...</p>}
</div>
</div>
</div>
<div>
<label className="block text-sm font-medium mb-1">نام بازیکن</label>
<input
type="text"
value={form.name}
onChange={(e) => setForm({ ...form, name: e.target.value })}
className="w-full border rounded-xl px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-green-500"
required
/>
</div>
<div>
<label className="block text-sm font-medium mb-1">پست</label>
<select
value={form.position}
onChange={(e) => setForm({ ...form, position: e.target.value })}
className="w-full border rounded-xl px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-green-500"
>
<option value="GK">دروازهبان</option>
<option value="DEF">مدافع</option>
<option value="MID">هافبک</option>
<option value="FWD">مهاجم</option>
</select>
</div>
<div>
<label className="block text-sm font-medium mb-1">تیم ملی</label>
<select
value={form.countryId}
onChange={(e) => setForm({ ...form, countryId: e.target.value })}
className="w-full border rounded-xl px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-green-500"
required
>
<option value="">انتخاب کنید</option>
{countries.map((c) => (
<option key={c.id} value={c.id}>{c.name}</option>
))}
</select>
</div>
<div>
<label className="block text-sm font-medium mb-1">قیمت (میلیون)</label>
<input
type="number"
step="0.5"
min="4"
max="15"
value={form.price}
onChange={(e) => setForm({ ...form, price: parseFloat(e.target.value) })}
className="w-full border rounded-xl px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-green-500"
/>
</div>
<div>
<label className="block text-sm font-medium mb-1">نوع کارت</label>
<select
value={form.cardTier}
onChange={(e) => setForm({ ...form, cardTier: e.target.value as CardTier })}
className="w-full border rounded-xl px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-green-500"
>
<option value="GOLD">طلایی</option>
<option value="SILVER">نقره ای</option>
<option value="BRONZE">برنزی</option>
</select>
</div>
<button
type="submit"
disabled={loading}
className="bg-green-700 text-white py-3 rounded-xl font-bold hover:bg-green-800 transition disabled:opacity-50"
>
{loading ? "در حال ذخیره..." : playerId ? "ذخیره تغییرات" : "افزودن بازیکن"}
</button>
</form>
);
}