feat : comment feature
CI / Verify (push) Successful in 2m30s
CI / Build immutable images and deploy (push) Successful in 3m9s

This commit is contained in:
2026-10-08 01:40:08 +07:00 Unverified
parent 8c8815cda5
commit 5812d99715
65 changed files with 27013 additions and 10 deletions
+5
View File
@@ -13,6 +13,7 @@ import {
SwordsIcon,
} from "lucide-react";
import { AdminUnreadCount } from "@/components/comments/admin-unread-comments";
import { Button } from "@/components/ui/button";
import { SignOutButton } from "@/components/auth/sign-out-button";
import { CommissionPushEntryPrompt } from "@/components/commission/push-entry-prompt";
@@ -33,6 +34,10 @@ export function AdminHeader() {
<span className="hidden lg:inline">ไกด์เกนชินไม่ใช่เกมมือถือ</span>
</Link>
<nav aria-label="เมนูแอดมิน" className="flex min-w-0 flex-1 items-center gap-1 overflow-x-auto sm:justify-end">
<Button variant={pathname.startsWith("/admin/comments") ? "secondary" : "ghost"} size="sm" nativeButton={false}
render={<Link href="/admin/comments" prefetch={false} />} aria-label="ความคิดเห็น">
<Image src="/icon/nav/Comment.webp" alt="" width={20} height={20} className="size-5 object-contain" /><span className="hidden xl:inline">ความคิดเห็น</span><AdminUnreadCount />
</Button>
<Button variant={pathname.startsWith("/admin/commission") ? "secondary" : "ghost"}
size="sm" nativeButton={false} render={<Link href="/admin/commission" />} aria-label="Commission">
<MessagesSquareIcon data-icon="inline-start" /><span className="hidden xl:inline">Commission</span>
+4
View File
@@ -2,6 +2,7 @@
import { UsersIcon } from "lucide-react";
import { AdminUnreadBadge } from "@/components/comments/admin-unread-comments";
import { Badge } from "@/components/ui/badge";
import { useAdminPresence } from "@/hooks/use-presence";
@@ -9,6 +10,7 @@ export function EditorPresence({ guideId, section }: { guideId: string; section:
const presence = useAdminPresence(guideId, section);
const editors = presence?.editorsByGuide[guideId] ?? [];
return (
<div className="flex flex-col items-end gap-1">
<div className="flex flex-wrap items-center gap-1" aria-live="polite">
<Badge variant="secondary">
<UsersIcon data-icon="inline-start" />
@@ -21,5 +23,7 @@ export function EditorPresence({ guideId, section }: { guideId: string; section:
</Badge>
))}
</div>
<AdminUnreadBadge target={`guide:${guideId}`} />
</div>
);
}
+3 -1
View File
@@ -50,6 +50,7 @@ import {
} from "@/components/ui/input-group";
import { ClearableInputGroupInput as InputGroupInput } from "@/components/admin/ui/clearable-input";
import { Spinner } from "@/components/ui/spinner";
import { AdminUnreadBadge } from "@/components/comments/admin-unread-comments";
import { useAdminPresence } from "@/hooks/use-presence";
import type { CatalogSyncJob } from "@/lib/catalog/sync";
import { cn } from "@/lib/utils";
@@ -236,13 +237,14 @@ export function StructuredDashboard({
{editor.sections.length ? ` - ${editor.sections.join(", ")}` : ""}
</Badge>
))}
<AdminUnreadBadge target={`guide:${guide.id}`} />
</div>
</CardAction>
</CardHeader>
<CardContent>
<p className="text-xs text-muted-foreground">
แก้ไขล่าสุด{" "}
{new Date(guide.updatedAt).toLocaleString("th-TH")}
{new Date(guide.updatedAt).toLocaleString("th-TH", { timeZone: "Asia/Bangkok" })}
</p>
</CardContent>
<CardFooter className="flex-wrap justify-between gap-2 pb-5">