feat : update
CI / Verify (push) Successful in 1m14s
CI / Build immutable images and deploy (push) Successful in 4m51s

This commit is contained in:
2026-09-06 17:41:16 +07:00 Unverified
parent fcf6a2c187
commit 770c60c4a2
10 changed files with 91 additions and 17 deletions
+6 -3
View File
@@ -5,8 +5,8 @@ import { UsersIcon } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { useAdminPresence } from "@/hooks/use-presence";
export function EditorPresence({ guideId }: { guideId: string }) {
const presence = useAdminPresence(guideId);
export function EditorPresence({ guideId, section }: { guideId: string; section: string }) {
const presence = useAdminPresence(guideId, section);
const editors = presence?.editorsByGuide[guideId] ?? [];
return (
<div className="flex flex-wrap items-center gap-1" aria-live="polite">
@@ -15,7 +15,10 @@ export function EditorPresence({ guideId }: { guideId: string }) {
Editing {editors.length || (presence ? 0 : "")}
</Badge>
{editors.map((editor) => (
<Badge key={editor.userId} variant="outline">{editor.name}</Badge>
<Badge key={editor.userId} variant="outline">
{editor.name}
{editor.sections.length ? ` · ${editor.sections.join(", ")}` : ""}
</Badge>
))}
</div>
);
+4 -1
View File
@@ -217,7 +217,10 @@ export function StructuredDashboard({
<div className="flex flex-col items-end gap-1">
<Badge variant="secondary">v{guide.version}</Badge>
{(presence?.editorsByGuide[guide.id] ?? []).map((editor) => (
<Badge key={editor.userId} variant="outline">{editor.name}</Badge>
<Badge key={editor.userId} variant="outline">
{editor.name}
{editor.sections.length ? ` · ${editor.sections.join(", ")}` : ""}
</Badge>
))}
</div>
</CardAction>
+13 -1
View File
@@ -2,15 +2,17 @@
import Image from "next/image";
import Link from "next/link";
import { SearchIcon } from "lucide-react";
import { SearchIcon, UsersIcon } from "lucide-react";
import { useState } from "react";
import {
Card,
CardAction,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import {
Empty,
EmptyDescription,
@@ -22,6 +24,7 @@ import {
InputGroupAddon,
InputGroupInput,
} from "@/components/ui/input-group";
import { useVisitorPresence } from "@/hooks/use-presence";
type GuideCard = {
id: string;
@@ -35,6 +38,7 @@ type GuideCard = {
export function StructuredDirectory({ guides }: { guides: GuideCard[] }) {
const [query, setQuery] = useState("");
const presence = useVisitorPresence(null);
const normalized = query.trim().toLowerCase();
const filtered = guides.filter((guide) =>
`${guide.name} ${guide.overview} ${guide.aliases.join(" ")}`.toLowerCase().includes(normalized),
@@ -71,6 +75,14 @@ export function StructuredDirectory({ guides }: { guides: GuideCard[] }) {
</div>
<CardHeader className="pt-5">
<CardTitle>{guide.name}</CardTitle>
{(presence?.byGuide[guide.id] ?? 0) > 0 ? (
<CardAction>
<Badge variant="secondary">
<UsersIcon data-icon="inline-start" />
{presence?.byGuide[guide.id]} คน
</Badge>
</CardAction>
) : null}
<CardDescription className="line-clamp-3">
{guide.overview}
</CardDescription>