Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 26 additions & 24 deletions admin/src/app/(dashboard)/admin/seo/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { Button } from "@/components/ui/button";
import { RefreshCcw, CheckCircle2, AlertCircle, Clock } from "lucide-react";
import { MpPageHeader, MpStatusPill, MpTableCard, MpCard, MpSectionTitle } from "@/components/mp/kit";

interface SyncLog {
id: string;
Expand Down Expand Up @@ -96,16 +97,19 @@ export default function AdminSeoPage() {

return (
<div className="space-y-6 p-6">
<header>
<h1 className="text-2xl font-bold">SEO Slug Sync</h1>
<p className="mt-1 text-sm text-stone-600">
Quản lý cron đồng bộ slug cho các trang SEO{" "}
<code className="rounded bg-stone-100 px-1 py-0.5 text-xs">/giai-chay/*</code>
. Cron tự chạy mỗi Chủ Nhật 02:00 — có thể trigger thủ công.
</p>
</header>
<MpPageHeader
eyebrow="Hệ thống"
title="SEO Slug Sync"
subtitle={
<>
Quản lý cron đồng bộ slug cho các trang SEO{" "}
<code className="rounded bg-stone-100 px-1 py-0.5 text-xs">/giai-chay/*</code>
. Cron tự chạy mỗi Chủ Nhật 02:00 — có thể trigger thủ công.
</>
}
/>

<section className="rounded-xl border border-stone-200 bg-white p-5">
<MpCard>
<div className="flex items-start justify-between gap-4">
<div>
<h2 className="text-base font-semibold">Trạng thái mới nhất</h2>
Expand All @@ -124,13 +128,11 @@ export default function AdminSeoPage() {
<dt className="text-stone-500">Trạng thái:</dt>
<dd className="font-medium">
{stats.lockSkipped ? (
<span className="text-amber-700">⚠️ Lock skip</span>
<MpStatusPill tone="warning">⚠️ Lock skip</MpStatusPill>
) : stats.errors.length > 0 ? (
<span className="text-red-700">
❌ {stats.errors.length} lỗi
</span>
<MpStatusPill tone="danger">❌ {stats.errors.length} lỗi</MpStatusPill>
) : (
<span className="text-green-700">✅ Thành công</span>
<MpStatusPill tone="success">✅ Thành công</MpStatusPill>
)}
</dd>
</dl>
Expand Down Expand Up @@ -163,10 +165,10 @@ export default function AdminSeoPage() {
<AlertCircle className="inline h-4 w-4" /> {errorMsg}
</div>
)}
</section>
</MpCard>

<section>
<h2 className="mb-3 text-base font-semibold">Lịch sử 10 lần gần nhất</h2>
<MpSectionTitle>Lịch sử 10 lần gần nhất</MpSectionTitle>
{isLoading ? (
<div className="rounded-xl border border-stone-200 bg-white p-8 text-center text-sm text-stone-500">
<Clock className="mx-auto h-5 w-5 animate-spin" />
Expand All @@ -177,7 +179,7 @@ export default function AdminSeoPage() {
Chưa có lịch sử sync nào.
</div>
) : (
<div className="overflow-x-auto rounded-xl border border-stone-200 bg-white">
<MpTableCard>
<table className="w-full text-sm">
<thead className="bg-stone-50 text-left text-xs font-semibold uppercase text-stone-600">
<tr>
Expand All @@ -198,25 +200,25 @@ export default function AdminSeoPage() {
<td className="px-3 py-2.5">
{log.triggeredBy === "cron" ? "🕒 cron" : "👤 manual"}
</td>
<td className="px-3 py-2.5">{log.racesScanned}</td>
<td className="px-3 py-2.5 font-semibold">
<td className="px-3 py-2.5 font-mono tabular-nums">{log.racesScanned}</td>
<td className="px-3 py-2.5 font-semibold font-mono tabular-nums">
{log.slugsGenerated}
</td>
<td className="px-3 py-2.5">{log.durationMs}ms</td>
<td className="px-3 py-2.5 font-mono tabular-nums">{log.durationMs}ms</td>
<td className="px-3 py-2.5">
{log.lockSkipped ? (
<span className="text-amber-700">⚠️ skip</span>
<MpStatusPill tone="warning">⚠️ skip</MpStatusPill>
) : log.errors.length > 0 ? (
<span className="text-red-700">❌ {log.errors.length} lỗi</span>
<MpStatusPill tone="danger">❌ {log.errors.length} lỗi</MpStatusPill>
) : (
<span className="text-green-700">✅ OK</span>
<MpStatusPill tone="success">✅ OK</MpStatusPill>
)}
</td>
</tr>
))}
</tbody>
</table>
</div>
</MpTableCard>
)}
</section>
</div>
Expand Down
Loading