dc-copy/src/table.tsx
2025-04-01 00:08:06 +09:00

235 lines
No EOL
9.6 KiB
TypeScript

import { cn } from './util/cn';
export type AuthorData = {
// 운영자
type: "operator"
} | {
// 고닉
// 중복 불가능 닉네임
type: "nickname",
nickname: string,
// 파딱, 주딱 구분을 위한 userType
userType?: "manager" | "submanager" // Optional, if applicable
} | {
// 유동닉
type: "IP",
// IP 주소
ip: string,
} | {
// 반유동닉
// 중복 가능 닉네임
type: "semi-nickname",
nickname: string,
}
// --- Data Interface (Remains the same) ---
export interface TableRowData {
id: string | number;
category: string;
titleText: string;
commentCount?: number;
// e.g., "icon_notice", "icon_pic", "icon_txt", "icon_survey"
variant?: "icon_notice" | "icon_recoming" | "icon_recomovie" | "icon_pic" | "icon_txt" | "icon_survey"
| "icon_ad" | "icon_dctrend";
// e.g., "운영자", "고닉", "반유동", "유동닉"
author?: {
type: "operator"
} | {
type: "nickname",
nickname: string,
userType?: "manager" | "submanager" // Optional, if applicable
} | {
type: "IP",
ip: string,
} | {
type: "semi-nickname",
nickname: string,
}
date: string;
views: "" | "-" | number;
recommendations: "" | "-" | number;
// Special flags for row types affecting style/structure
isNotice?: boolean;
isAdOrSurvey?: boolean;
isNews?: boolean; // Handle the last row type specifically if needed
titleLinkUrl?: string; // Optional URL for title
authorLinkUrl?: string; // Optional URL for author
}
// --- Child Component: TableRow ---
interface TableRowProps {
rowData: TableRowData;
}
const NicknameImagePath = {
"주딱": "/fix_managernik.gif",
"파딱": "/fix_sub_managernik.gif",
"반유동": "/nik.gif",
"default": "/fix_nik.gif"
}
export function TableRow({ rowData }: TableRowProps) {
const {
id,
category,
titleText,
commentCount,
variant,
date,
views,
recommendations,
isNotice,
isAdOrSurvey,
isNews,
titleLinkUrl = "#",
authorLinkUrl = "#",
author,
} = rowData;
const iconTable = {
icon_notice: "0px 0px",
icon_recoming: "0px -193px",
icon_recomovie: "0px -193px",
icon_pic: "0px -100px",
icon_txt: "0px -123px",
icon_survey: "0px -170px",
icon_ad: "0px -193px",
icon_dctrend: "-3px -877px", // Example for news
}
const iconPosition = iconTable[variant ?? "icon_txt"]; // Default to undefined if not found
// --- Base Cell Styles ---
// Note: some styles like height/padding might be slightly different due to Tailwind defaults vs specific px
const tdBaseClasses = 'border-t border-custom-gray-light align-middle text-custom-gray-dark h-[25px] relative px-1 py-[2px]'; // Approximates tdBaseStyle
const tdCenterClasses = cn(tdBaseClasses, "text-center font-tahoma text-[11px] pt-[1px] pb-[2px]"); // Approximates tdCenterStyle
// --- Standard Row Rendering ---
return (
<tr className="bg-transparent hover:bg-custom-gray-light">
<td className={tdCenterClasses}>{isNews ? "" : id}</td>
<td className={cn(
tdCenterClasses,
'text-xs', // Base font size for category is 12px
(isAdOrSurvey || isNotice) && 'font-bold', // Conditional bold
)}>{category}</td>
<td className={cn(tdBaseClasses, "text-left text-[13px] h-[29px]")}>
<a href={titleLinkUrl} className={cn(
'text-custom-gray-dark inline-block max-w-[82%] align-middle text-ellipsis whitespace-nowrap overflow-hidden pt-[1px] leading-tight', // Approximates titleLinkStyle
"hover:underline",
isNews && '!text-custom-green', // News specific color override
(isNotice || isAdOrSurvey) && 'font-bold', // Title bold for Notice/Ad/Survey
)}>
{iconPosition && (
<em className="inline-block w-[15px] h-[15px] align-[-3px] mr-[7px] bg-no-repeat" style={{
background: `url("/icon_img.png?1012")`,
backgroundPosition: iconPosition,
}}></em>
)}
{/* Title text - boldness handled by titleLinkClasses */}
{titleText}
</a>
{commentCount !== undefined && commentCount > 0 && (
<span className="text-xs text-custom-gray-medium ml-1 align-middle tracking-[-0.05em]">
[{commentCount}]
</span>
)}
</td>
<td className={cn(
tdCenterClasses, // Base style for author cell
'text-[13px]', // Author cell often uses 13px base font size
authorLinkUrl !== '#' ? 'cursor-pointer' : 'cursor-default', // Conditional cursor
)}>
{author?.type === "operator" ? (
<b className="font-bold"></b>
) : (
<>
{/* Author Name Span */}
<span className="inline-block max-w-[81%] align-top text-ellipsis overflow-hidden whitespace-nowrap">
{/* Inner em/span for potential finer control if needed */}
<em className="not-italic leading-[13px]">
{author?.type === "nickname" ? author?.nickname : "ㅇㅇ"}
</em>
</span>
{/* Author IP */}
{author?.type === "IP" && (
<span className="font-tahoma text-[11px] text-custom-gray-medium tracking-[-0.05em] ml-[3px]">
({author.ip})
</span>
)}
{/* Author Icon Placeholder */}
{author?.type !== "IP" && (
<a href={authorLinkUrl} className="text-custom-gray-dark ml-0.5 inline-block">
{/* Replace with actual icon component or img tag */}
<img
alt="icon"
src={
author?.type === "nickname" ? (
author?.userType === "manager" ? NicknameImagePath["주딱"] :
author?.userType === "submanager" ? NicknameImagePath["파딱"] :
NicknameImagePath["default"]
) : NicknameImagePath["반유동"]
}
className="align-middle cursor-pointer w-3 h-3" // Example size
/>
</a>
)}
</>
)}
</td>
<td className={tdCenterClasses}>{date}</td>
<td className={tdCenterClasses}>{views}</td>
<td className={tdCenterClasses}>{recommendations}</td>
</tr>
);
}
// --- Main Component: Table ---
export function GalleryTable(props: {
data: TableRowData[];
}) {
const { data } = props; // Destructure props to get data
// --- Base TH Styles ---
const thBaseClasses = 'bg-transparent h-[37px] border-t-2 border-b border-custom-blue-dark align-middle text-center text-custom-gray-dark font-appleDotum'; // Uses config colors
return (
<table className="bg-transparent border-collapse table-fixed text-xs font-apple w-full border-b border-custom-blue-dark">
{/* Screen Reader Only Caption */}
<caption className="relative w-0 text-[0px] leading-[0] -z-10">
</caption>
{/* Column Widths */}
<colgroup>
<col style={{ width: "7%" }} />
<col style={{ width: 51 }} />
<col />
<col style={{ width: "18%" }} />
<col style={{ width: "6%" }} />
<col style={{ width: "6%" }} />
<col style={{ width: "6%" }} />
</colgroup>
{/* Table Header */}
<thead className="bg-transparent">
<tr className="bg-transparent">
<th className={thBaseClasses}> </th>
<th className={thBaseClasses}> </th>
<th className={thBaseClasses}> </th>
<th className={thBaseClasses}> </th>
<th className={thBaseClasses}> </th>
<th className={thBaseClasses}> </th>
<th className={thBaseClasses}> </th>
{/* Note: Original CSS applied right border to all TH. Tailwind border utilities apply to all sides unless specified (e.g., border-l), so the above covers it. If you only wanted specific borders, you'd adjust.*/}
</tr>
</thead>
{/* Table Body */}
<tbody className="bg-transparent">
{data.map((row, index) => (
// Using id-index key for potential non-unique IDs between notices/regular posts
<TableRow key={`${row.id}-${index}`} rowData={row} />
))}
</tbody>
</table>
);
}