Files
football-next/app/(admin)/admin/news/page.tsx
2026-05-11 14:53:55 +03:30

172 lines
5.6 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.
import { revalidatePath } from "next/cache";
import { db } from "@/lib/db";
import { requireAdmin } from "@/lib/session";
function toDateTimeLocalValue(date: Date) {
const offsetMs = date.getTimezoneOffset() * 60 * 1000;
return new Date(date.getTime() - offsetMs).toISOString().slice(0, 16);
}
async function createNews(formData: FormData) {
"use server";
await requireAdmin();
const icon = String(formData.get("icon") ?? "").trim();
const title = String(formData.get("title") ?? "").trim();
const description = String(formData.get("description") ?? "").trim();
const newsTimeValue = String(formData.get("newsTime") ?? "").trim();
const newsTime = new Date(newsTimeValue);
if (!icon || !title || !description || Number.isNaN(newsTime.getTime())) {
return;
}
await db.fantasyNews.create({
data: {
icon,
title,
description,
newsTime,
},
});
revalidatePath("/admin/news");
revalidatePath("/");
}
async function deleteNews(formData: FormData) {
"use server";
await requireAdmin();
const id = String(formData.get("id") ?? "");
if (!id) return;
await db.fantasyNews.delete({ where: { id } });
revalidatePath("/admin/news");
revalidatePath("/");
}
export default async function AdminNewsPage() {
await requireAdmin();
const news = await db.fantasyNews.findMany({
orderBy: [{ newsTime: "desc" }, { createdAt: "desc" }],
});
return (
<div className="space-y-6">
<div className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold">مدیریت اخبار</h1>
<p className="text-sm text-gray-500 mt-1">اخبار فانتزی که در API اخبار نمایش داده میشوند.</p>
</div>
</div>
<form action={createNews} className="bg-white rounded-2xl shadow p-6 grid grid-cols-1 gap-4">
<div className="grid grid-cols-3 gap-4">
<label className="flex flex-col gap-2 text-sm font-medium text-gray-700">
آیکن
<input
name="icon"
required
defaultValue="info"
className="rounded-xl border border-gray-300 px-4 py-2.5 outline-none focus:border-green-700"
placeholder="info"
/>
</label>
<label className="flex flex-col gap-2 text-sm font-medium text-gray-700 col-span-2">
عنوان
<input
name="title"
required
className="rounded-xl border border-gray-300 px-4 py-2.5 outline-none focus:border-green-700"
placeholder="مثلاً خبر ترکیب تیم‌ها"
/>
</label>
</div>
<label className="flex flex-col gap-2 text-sm font-medium text-gray-700">
متن خبر
<textarea
name="description"
required
rows={5}
className="rounded-xl border border-gray-300 px-4 py-3 outline-none focus:border-green-700 resize-y"
placeholder="متن کامل خبر را وارد کنید"
/>
</label>
<div className="flex items-end justify-between gap-4">
<label className="flex flex-col gap-2 text-sm font-medium text-gray-700 w-72">
زمان خبر
<input
name="newsTime"
type="datetime-local"
required
defaultValue={toDateTimeLocalValue(new Date())}
className="rounded-xl border border-gray-300 px-4 py-2.5 outline-none focus:border-green-700"
/>
</label>
<button
type="submit"
className="bg-green-700 text-white px-6 py-2.5 rounded-xl hover:bg-green-800 transition font-medium"
>
ثبت خبر
</button>
</div>
</form>
<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-5 py-4">زمان</th>
<th className="text-right px-5 py-4">عنوان</th>
<th className="text-right px-5 py-4">متن</th>
<th className="px-5 py-4"></th>
</tr>
</thead>
<tbody>
{news.map((item) => (
<tr key={item.id} className="border-t align-top hover:bg-gray-50 transition">
<td className="px-5 py-4 text-gray-500 whitespace-nowrap">
{item.newsTime.toLocaleString("fa-IR")}
</td>
<td className="px-5 py-4 font-medium">
<div className="flex items-center gap-2">
<span className="text-gray-400">{item.icon}</span>
<span>{item.title}</span>
</div>
</td>
<td className="px-5 py-4 text-gray-600 leading-7 max-w-xl">
{item.description}
</td>
<td className="px-5 py-4">
<form action={deleteNews}>
<input type="hidden" name="id" value={item.id} />
<button type="submit" className="text-red-600 hover:underline text-xs">
حذف
</button>
</form>
</td>
</tr>
))}
{news.length === 0 && (
<tr>
<td colSpan={4} className="text-center py-10 text-gray-400">
هنوز خبری ثبت نشده است
</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
);
}