113 lines
3.7 KiB
TypeScript
113 lines
3.7 KiB
TypeScript
import {
|
|
Table,
|
|
TableHeader,
|
|
TableColumn,
|
|
TableBody,
|
|
TableRow,
|
|
TableCell,
|
|
} from "@heroui/react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { type NewsItem, type NewsTranslation } from "./adminNewsTypes";
|
|
|
|
const resolveLocale = (field: NewsTranslation | null | undefined, lang: string) => {
|
|
if (!field) return "";
|
|
if (typeof field === "string") return field;
|
|
return field[lang] ?? field["en"] ?? Object.values(field)[0] ?? "";
|
|
};
|
|
|
|
const formatDate = (value: string | null | undefined, lang: string) => {
|
|
if (!value) return "";
|
|
const date = new Date(value);
|
|
if (Number.isNaN(date.getTime())) return "";
|
|
return new Intl.DateTimeFormat(lang, {
|
|
day: "2-digit",
|
|
month: "2-digit",
|
|
year: "numeric",
|
|
}).format(date);
|
|
};
|
|
|
|
type AdminNewsTableProps = {
|
|
items: NewsItem[];
|
|
locale: string;
|
|
loading: boolean;
|
|
error: string | null;
|
|
onEdit: (item: NewsItem) => void;
|
|
};
|
|
|
|
export default function AdminNewsTable({
|
|
items,
|
|
locale,
|
|
loading,
|
|
error,
|
|
onEdit,
|
|
}: AdminNewsTableProps) {
|
|
const { t } = useTranslation("common");
|
|
const valuePlaceholder = t("value_na") ?? "—";
|
|
|
|
if (loading) {
|
|
return <div>{t("admin_news_loading") ?? "Načítám novinky…"}</div>;
|
|
}
|
|
|
|
if (error) {
|
|
return <div className="text-sm text-red-600">{error}</div>;
|
|
}
|
|
|
|
return (
|
|
<Table
|
|
aria-label={t("admin_news_table_aria") ?? "Admin news table"}
|
|
selectionMode="none"
|
|
>
|
|
<TableHeader>
|
|
<TableColumn>{t("admin_news_title_cs") ?? "Název (cs)"}</TableColumn>
|
|
<TableColumn>{t("admin_news_title_en") ?? "Title (en)"}</TableColumn>
|
|
<TableColumn>{t("admin_news_published_at") ?? "Publikováno"}</TableColumn>
|
|
<TableColumn>{t("admin_news_published_flag") ?? "Zveřejněno"}</TableColumn>
|
|
<TableColumn></TableColumn>
|
|
</TableHeader>
|
|
<TableBody items={items}>
|
|
{(item) => (
|
|
<TableRow key={item.id}>
|
|
<TableCell>{resolveLocale(item.title, "cs")}</TableCell>
|
|
<TableCell>{resolveLocale(item.title, "en")}</TableCell>
|
|
<TableCell>
|
|
{(() => {
|
|
if (!item.published_at) return valuePlaceholder;
|
|
const date = new Date(item.published_at);
|
|
if (Number.isNaN(date.getTime())) return valuePlaceholder;
|
|
const isFuture = date.getTime() > Date.now();
|
|
const className = isFuture ? "italic" : "font-semibold";
|
|
return (
|
|
<span className={className}>
|
|
{formatDate(item.published_at, locale)}
|
|
</span>
|
|
);
|
|
})()}
|
|
</TableCell>
|
|
<TableCell>
|
|
{item.is_published ? t("yes") ?? "Ano" : t("no") ?? "Ne"}
|
|
</TableCell>
|
|
<TableCell>
|
|
<button
|
|
type="button"
|
|
onClick={() => onEdit(item)}
|
|
className="inline-flex items-center p-1 rounded hover:bg-default-100 text-default-500 hover:text-default-700"
|
|
aria-label={t("admin_news_edit_aria") ?? "Upravit novinku"}
|
|
>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
viewBox="0 0 20 20"
|
|
fill="currentColor"
|
|
className="h-4 w-4"
|
|
>
|
|
<path d="M13.586 3.586a2 2 0 0 1 2.828 2.828l-8.25 8.25a2 2 0 0 1-.878.518l-3.122.89a.75.75 0 0 1-.926-.926l.89-3.122a2 2 0 0 1 .518-.878l8.25-8.25Z" />
|
|
<path d="M12.475 4.697 4.75 12.422l-.69 2.422 2.422-.69 7.725-7.725-1.732-1.732Z" />
|
|
</svg>
|
|
</button>
|
|
</TableCell>
|
|
</TableRow>
|
|
)}
|
|
</TableBody>
|
|
</Table>
|
|
);
|
|
}
|