/** @jsxRuntime classic */ import React, { useEffect, useState } from "react"; import { Notice, SearchControl } from "@wordpress/components"; import { __, _n, sprintf } from "@wordpress/i18n"; import ExcludedContentTable from "./components/ExcludedContentTable"; import { fetchExcludedContent, removeExcludedContent, } from "./data/api"; import type { ExcludedContentItem } from "./data/types"; import styles from "./App.module.css"; function getItemCountLabel(count: number): string { return sprintf( _n("Showing %d item", "Showing %d items", count, "flexible-chat"), count, ); } function getItemKey(item: ExcludedContentItem): string { return `${item.kind}:${item.id}`; } export default function App() { const [items, setItems] = useState([]); const [total, setTotal] = useState(0); const [search, setSearch] = useState(""); const [selectedType, setSelectedType] = useState(""); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [removingKeys, setRemovingKeys] = useState([]); useEffect(() => { const controller = new AbortController(); const timeoutId = window.setTimeout(() => { setLoading(true); setError(null); fetchExcludedContent(search, controller.signal) .then((response) => { setItems(response.items); setTotal(response.total); }) .catch((err: Error) => { if (err.name === "AbortError") { return; } setError(err.message); }) .finally(() => { if (!controller.signal.aborted) { setLoading(false); } }); }, 180); return () => { controller.abort(); window.clearTimeout(timeoutId); }; }, [search]); const handleRemove = async (item: ExcludedContentItem) => { const itemKey = getItemKey(item); const previousItems = items; const previousTotal = total; setRemovingKeys((current) => current.includes(itemKey) ? current : [...current, itemKey], ); setItems((current) => current.filter((currentItem) => getItemKey(currentItem) !== itemKey), ); setTotal((current) => Math.max(0, current - 1)); setError(null); try { await removeExcludedContent(item); } catch (err) { const message = err instanceof Error ? err.message : __("Failed to remove exclusion.", "flexible-chat"); setItems(previousItems); setTotal(previousTotal); setError(message); } finally { setRemovingKeys((current) => current.filter((currentKey) => currentKey !== itemKey), ); } }; const typeOptions = Array.from( new Map( items.map((item) => [item.entityType, item.typeLabel] as const), ).entries(), ).sort((left, right) => left[1].localeCompare(right[1])); const filteredItems = selectedType === "" ? items : items.filter((item) => item.entityType === selectedType); return (

{__("Knowledge exclusion", "flexible-chat")}

{__( "These items are excluded from the chat knowledge base. To exclude more content, edit a post, page, product, category, or tag.", "flexible-chat", )}

{getItemCountLabel(filteredItems.length)}

{error && (

{error}

)}
); }