"use client"; import { IconTrash, IconRefresh, IconPlayerPlay, IconPlayerPause, IconRestore, } from "@tabler/icons-react"; import { Button } from "@kandev/ui/button"; import { Badge } from "@kandev/ui/badge"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@kandev/ui/table"; import { Tooltip, TooltipContent, TooltipTrigger } from "@kandev/ui/tooltip"; import { useToast } from "@/components/toast-provider"; import { useAppStore } from "@/components/state-provider"; import type { IssueWatch } from "@/lib/types/github"; import { useTranslation } from "react-i18next"; import type { TFunction } from "i18next"; import { formatRelative } from "@/lib/i18n/formats"; type IssueWatchTableProps = { watches: IssueWatch[]; // showWorkspace renders a Workspace column when the table aggregates rows // from every workspace (install-wide settings page). showWorkspace?: boolean; onEdit: (watch: IssueWatch) => void; onDelete: (id: string) => void; onTrigger: (id: string) => void; onReset: (id: string) => void; onToggleEnabled: (watch: IssueWatch) => void; }; // `formatRelative` already implements these exact buckets (just now / Nm / Nh / // Nd ago) against the catalog, so the local copy is dropped rather than // translated — it was English-only and duplicated the shared helper. function formatLastPolled(t: TFunction, dateStr: string | null): string { if (!dateStr) return t("github:never"); return formatRelative(dateStr); } function formatRepoNames(t: TFunction, watch: IssueWatch): string { if (watch.repos.length === 0) return t("github:allRepositories"); return watch.repos .map((r) => (r.name === "" ? `${r.owner}/*` : `${r.owner}/${r.name}`)) .join(", "); } function formatLabels(watch: IssueWatch): string { if (!watch.labels || watch.labels.length === 0) return ""; return watch.labels.join(", "); } type WatchActionsProps = { watch: IssueWatch; onToggleEnabled: (watch: IssueWatch) => void; onTrigger: (id: string) => void; onReset: (id: string) => void; onDelete: (id: string) => void; }; function WatchActions({ watch, onToggleEnabled, onTrigger, onReset, onDelete }: WatchActionsProps) { const { t } = useTranslation(); const { toast } = useToast(); return (
{watch.enabled ? t("github:pause") : t("github:enable")} {t("github:checkNow")} {t("common:reset")} {t("github:delete")}
); } export function IssueWatchTable({ watches, showWorkspace, onEdit, onDelete, onTrigger, onReset, onToggleEnabled, }: IssueWatchTableProps) { const { t } = useTranslation(); const workspaces = useAppStore((s) => s.workspaces.items); const workspaceName = (id: string) => workspaces.find((w) => w.id === id)?.name ?? id; if (watches.length === 0) { return (

{t("github:noIssueWatchesConfiguredCreateOne")}

); } return ( {showWorkspace && {t("common:workspace")}} {t("github:repository")} {t("github:labels")} {t("github:interval")} {t("github:lastPolled")} {t("common:status")} {t("github:actions")} {watches.map((watch) => ( onEdit(watch)}> {showWorkspace && ( {workspaceName(watch.workspace_id)} )} {formatRepoNames(t, watch)} {formatLabels(watch) || "-"} {Math.round(watch.poll_interval_seconds / 60)}m {formatLastPolled(t, watch.last_polled_at)} {watch.enabled ? t("github:active") : t("github:paused")} ))}
); }