"use client"; import { IconRefresh } from "@tabler/icons-react"; import { Button } from "@kandev/ui/button"; import { SettingsPageTemplate } from "@/components/settings/settings-page-template"; import { usePlugins } from "@/hooks/domains/plugins/use-plugins"; import { InstallPluginDialog } from "./install-plugin-dialog"; import { PluginRow } from "./plugin-row"; import { UninstallPluginDialog } from "./uninstall-plugin-dialog"; import { usePluginActions } from "./use-plugin-actions"; /** * Operator UI to install/list/enable/disable/uninstall plugins * (docs/plans/plugins/task-20-mgmt-page.md, reworked for the install-based * flow in docs/plans/plugins/GRPC-CONTRACT.md ยง7). Gated on the `plugins` * feature flag by the page-level default export. */ export function PluginsSettings() { const { items, loaded, loading, error } = usePlugins(); const actions = usePluginActions(); return ( undefined} showSaveButton={false} > Installed plugins Sync Install plugin {actions.syncErrors.length > 0 && ( {actions.syncErrors.map((err) => ( {err.path}: {err.reason} ))} )} ); } type PluginListProps = { items: ReturnType["items"]; loaded: boolean; loading: boolean; error: string | null; actions: ReturnType; }; function PluginList({ items, loaded, loading, error, actions }: PluginListProps) { if (error) { return ( {error} ); } if (!loaded && loading) { return ( Loading plugins... ); } if (loaded && items.length === 0) { return ( No plugins yet. Install a plugin package to get started. ); } return ( {items.map((plugin) => ( ))} ); }