130 lines
5.2 KiB
TypeScript
130 lines
5.2 KiB
TypeScript
import { db } from "@/lib/db";
|
||
import { requireAdmin } from "@/lib/session";
|
||
import Link from "next/link";
|
||
import LotteryButton from "./LotteryButton";
|
||
import QuizDeleteButton from "./QuizDeleteButton";
|
||
import { formatPersianDate, formatPersianTime } from "@/lib/persianDate";
|
||
import { resolveQuizRewardTier } from "@/lib/cardTier";
|
||
|
||
function getTotalWinnersCount(quiz: {
|
||
goldWinnersCount: number;
|
||
silverWinnersCount: number;
|
||
bronzeWinnersCount: number;
|
||
}) {
|
||
return quiz.goldWinnersCount + quiz.silverWinnersCount + quiz.bronzeWinnersCount;
|
||
}
|
||
|
||
export default async function AdminQuizPage() {
|
||
await requireAdmin();
|
||
|
||
const quizzes = await db.dailyQuiz.findMany({
|
||
orderBy: { date: "desc" },
|
||
include: {
|
||
questions: true,
|
||
submissions: {
|
||
select: { score: true, correctAnswers: true },
|
||
},
|
||
_count: { select: { submissions: true } },
|
||
},
|
||
});
|
||
|
||
return (
|
||
<div>
|
||
<div className="flex justify-between items-center mb-6">
|
||
<h1 className="text-2xl font-bold">کوییز روزانه</h1>
|
||
<Link
|
||
href="/admin/quiz/new"
|
||
className="bg-green-700 text-white px-5 py-2 rounded-xl hover:bg-green-800 transition font-medium"
|
||
>
|
||
+ کوییز جدید
|
||
</Link>
|
||
</div>
|
||
|
||
<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="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>
|
||
{quizzes.map((q) => {
|
||
const eligibleParticipants =
|
||
q.goldMinCorrect != null || q.silverMinCorrect != null || q.bronzeMinCorrect != null
|
||
? q.submissions.filter((submission) => resolveQuizRewardTier(q, submission.correctAnswers) !== null).length
|
||
: q.submissions.filter((submission) => submission.score === 100).length;
|
||
|
||
return (
|
||
<tr key={q.id} className="border-t hover:bg-gray-50 transition">
|
||
<td className="px-5 py-3 font-medium">
|
||
{formatPersianDate(new Date(q.date))}
|
||
</td>
|
||
<td className="px-5 py-3 text-gray-600 text-xs">
|
||
{formatPersianTime(new Date(q.windowStart))}
|
||
{" - "}
|
||
{formatPersianTime(new Date(q.windowEnd))}
|
||
</td>
|
||
<td className="px-5 py-3">{q.questions.length}</td>
|
||
<td className="px-5 py-3">{q._count.submissions}</td>
|
||
<td className="px-5 py-3 text-green-700 font-bold">
|
||
{getTotalWinnersCount(q)}
|
||
<div className="text-[11px] font-normal text-gray-500">
|
||
G:{q.goldWinnersCount} | S:{q.silverWinnersCount} | B:{q.bronzeWinnersCount}
|
||
</div>
|
||
</td>
|
||
<td className="px-5 py-3">
|
||
{q.isProcessed ? (
|
||
<span className="bg-green-100 text-green-700 text-xs px-2 py-1 rounded-full">انجام شده</span>
|
||
) : (
|
||
<span className="bg-yellow-100 text-yellow-700 text-xs px-2 py-1 rounded-full">در انتظار</span>
|
||
)}
|
||
</td>
|
||
<td className="px-5 py-3 flex gap-2">
|
||
<Link href={`/admin/quiz/${q.id}/results`} className="text-blue-600 hover:underline text-xs">
|
||
نتایج
|
||
</Link>
|
||
{!q.isProcessed && (
|
||
<Link href={`/admin/quiz/${q.id}/edit`} className="text-emerald-700 hover:underline text-xs">
|
||
ویرایش
|
||
</Link>
|
||
)}
|
||
{!q.isProcessed && (
|
||
<LotteryButton
|
||
quizId={q.id}
|
||
goldWinnersCount={q.goldWinnersCount}
|
||
silverWinnersCount={q.silverWinnersCount}
|
||
bronzeWinnersCount={q.bronzeWinnersCount}
|
||
totalParticipants={q._count.submissions}
|
||
perfectParticipants={eligibleParticipants}
|
||
/>
|
||
)}
|
||
{!q.isProcessed && (
|
||
<QuizDeleteButton
|
||
quizId={q.id}
|
||
submissionsCount={q._count.submissions}
|
||
/>
|
||
)}
|
||
</td>
|
||
</tr>
|
||
);
|
||
})}
|
||
{quizzes.length === 0 && (
|
||
<tr>
|
||
<td colSpan={7} className="text-center py-10 text-gray-400">
|
||
هیچ کوییزی ثبت نشده
|
||
</td>
|
||
</tr>
|
||
)}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|