Files
Dash/apps/frontend/src/widgets/domain.tsx
T
Tomas DvorakandDevin e0ef60eca6 feat(ui): phase 5 — graphs, widgets, theming, PWA, boards, i18n
P5a: 24h uptime bar strip + latency chart on monitor detail, iframe
embed widget, generic JSON-path widget, accent/wallpaper/custom CSS
settings, PWA manifest + service worker, demo GIF.

P5b: transport picker + per-transport fields + test button in
settings; per-monitor alert-rule fields in dialogs.

P5c: container cpu/mem columns, SMART/ZFS/GPU sections on system
detail, subdomains section on domain detail.

P5d: login/setup page + auth middleware client handling, board
switcher + /b/:slug routes, full string extraction to typed t() keys
with {param} interpolation, complete cs locale, language select.

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-22 12:49:51 +02:00

39 lines
1.5 KiB
TypeScript

import type { WidgetData } from "@/widgets";
import type { Item } from "@/types";
import { cn } from "@/lib/utils";
import { t } from "@/i18n";
// Board tile for a tracked domain: favicon, name, expiry countdown.
export function DomainWidget({ item, data, error }: {
item: Item;
data: WidgetData | undefined;
error: string | undefined;
}) {
const days = typeof data?.daysUntilExpiry === "number" ? data.daysUntilExpiry : undefined;
const sslDays = typeof data?.sslDaysUntilExpiry === "number" ? data.sslDaysUntilExpiry : undefined;
const expiring = data?.expiring === true;
const domainId = typeof item.config?.domainId === "string" ? item.config.domainId : "";
return (
<a
href={domainId ? `/domains/${domainId}` : "/domains"}
className="flex w-full items-center gap-2.5 text-left"
onClick={(e) => e.stopPropagation()}
>
{typeof data?.faviconUrl === "string" && data.faviconUrl ? (
<img src={data.faviconUrl} alt="" className="size-4 shrink-0 rounded-sm" loading="lazy" />
) : null}
<span className="min-w-0 flex-1 truncate text-[12.5px] font-medium">
{typeof data?.name === "string" ? data.name : item.name}
</span>
<span className={cn(
"shrink-0 font-mono text-[10.5px]",
error ? "text-down" : expiring || (days !== undefined && days < 0) ? "text-down" : "text-text-faint",
)}>
{error ? t("widget.err") : days === undefined ? "…" : days < 0 ? t("domains.expired") : `${days}d`}
{sslDays !== undefined && sslDays <= 30 ? ` · ssl ${sslDays}d` : ""}
</span>
</a>
);
}