diff --git a/packages/client/src/components/gallery/DescItem.tsx b/packages/client/src/components/gallery/DescItem.tsx
index f9d72c3..42a4c2a 100644
--- a/packages/client/src/components/gallery/DescItem.tsx
+++ b/packages/client/src/components/gallery/DescItem.tsx
@@ -2,30 +2,48 @@ import StyledLink from "@/components/gallery/StyledLink";
import { cn } from "@/lib/utils";
import { Fragment } from "react/jsx-runtime";
-export function DescItem({ name, children, className }: {
+
+export function DescItem({
+ name,
+ children,
+ className,
+ icon
+}: {
name: string;
className?: string;
children?: React.ReactNode;
+ icon?: React.ReactNode;
}) {
return
-
{name}
-
{children}
+
+ {icon && {icon}}
+ {name}
+
+
{children}
;
}
+
export function DescTagItem({
- items, name, className,
+ items, name, className, icon
}: {
name: string;
items: string[];
className?: string;
+ icon?: React.ReactNode;
}) {
- return
- {items.length === 0 ? "N/A" : items.map(
+ return
+ {items.length === 0 ? (
+ 정보 없음
+ ) : items.map(
(x, i) =>
- {x}
- {i + 1 < items.length && , }
+
+ {x}
+
+ {i + 1 < items.length && , }
)}
;
-}
+}
\ No newline at end of file
diff --git a/packages/client/src/page/contentInfoPage.tsx b/packages/client/src/page/contentInfoPage.tsx
index b70465b..48e36fb 100644
--- a/packages/client/src/page/contentInfoPage.tsx
+++ b/packages/client/src/page/contentInfoPage.tsx
@@ -10,7 +10,12 @@ import { GalleryCard } from "@/components/gallery/GalleryCard.tsx";
import { useEffect, useRef } from "react";
import { useLogin } from "@/state/user.ts";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu.tsx";
-import { DotsVerticalIcon } from "@radix-ui/react-icons";
+import { EllipsisVerticalIcon } from "lucide-react";
+import {
+ RefreshCw, ScanSearch, Trash2,
+ Paintbrush
+ , Users, BookOpen, User, Clock, FileCheck, FileText, Layers, Tag, Loader2, AlertCircle, FileQuestion
+} from "lucide-react";
export interface ContentInfoPageProps {
params: {
@@ -45,19 +50,30 @@ export function ContentInfoPage({ params }: ContentInfoPageProps) {
const isAdmin = username === "admin";
if (isLoading) {
- return
-
- Loading...
+ return
+
+
+ 콘텐츠 정보 로드 중...
}
if (error) {
- return Error: {String(error)}
+ return
+
+
오류가 발생했습니다
+
{String(error)}
+
}
if (!data) {
- return Not found
+ return
+
+
콘텐츠를 찾을 수 없습니다
+
+
}
const tags = data?.tags ?? [];
@@ -68,77 +84,117 @@ export function ContentInfoPage({ params }: ContentInfoPageProps) {
return (
-
+
- {isAdmin &&
-
-
-
-
-
-
- {
- await rehashDoc(params.id);
- }}
+
+
+
+
+ {data.title}
+
+
+
+
+
+ {classifiedTags.type[0] ?? "N/A"}
+
+
+
+ {isAdmin &&
+
+
+
+
+
+
+ {
+ await rehashDoc(params.id);
+ }}
+ className="flex items-center gap-2 cursor-pointer"
>
- Rehash
-
- {
- if (!window.confirm("Are you sure?")) {
- return;
- }
- // Rescan
- await rescanDoc(params.id);
- }}
+
+ Rehash
+
+ {
+ if (!window.confirm("Are you sure?")) {
+ return;
+ }
+ await rescanDoc(params.id);
+ }}
+ className="flex items-center gap-2 cursor-pointer"
>
- Rescan
-
- {
- if (!window.confirm("Are you sure?")) {
- return;
- }
- // Delete
- await deleteDoc(params.id);
- }}
+
+ Rescan
+
+ {
+ if (!window.confirm("Are you sure?")) {
+ return;
+ }
+ await deleteDoc(params.id);
+ }}
+ className="flex items-center gap-2 cursor-pointer text-destructive hover:text-destructive"
>
- Delete
-
-
-
-
- }
-
-
-
- {data.title}
-
-
-
-
- {classifiedTags.type[0] ?? "N/A"}
-
-
-
+
+ Delete
+
+
+
+
+ }
+
-
-
-
-
-
-
{new Date(data.created_at).toLocaleString()} / {new Date(data.modified_at).toLocaleString()}
-
{data.content_hash}
-
{`${data.basepath}/${data.filename}`}
-
{data.pagenum}
+
+
} />
+
+
} />
+
+
} />
+
+
} />
+
+
}
+ className="md:col-span-2">
+
+ {new Date(data.created_at).toLocaleString()} /
+ {new Date(data.modified_at).toLocaleString()}
+
+
+
+
}>
+
{data.content_hash}
+
+
+
}>
+
{data.pagenum} 페이지
+
+
+
}>
+
{`${data.basepath}/${data.filename}`}
+
+
Tags
@@ -161,20 +217,37 @@ function SimilarContentCard({
const { data, error, isLoading } = useGalleryDocSimilar(id);
if (isLoading) {
- return
Loading...
+ return
+
+ 유사 콘텐츠 불러오는 중...
+
}
if (error) {
- return
Error: {String(error)}
+ return
+
+
+ 오류: {String(error)}
+
+
}
- if (!data) {
- return
Not found
+ if (!data || data.length === 0) {
+ return
+
+ 유사한 콘텐츠가 없습니다.
+
}
return (
-
Contents with Similar Tags
+
+
유사한 콘텐츠
+
+
+ {data.length}개 항목
+
+
{data.map((doc) => (